From 18740e862362e9558cfb7cfb25a13500d05538fc Mon Sep 17 00:00:00 2001 From: Dylan Smith Date: Wed, 8 Jun 2011 15:38:58 -0400 Subject: [PATCH] d3dxof: Factor out duplicated code for parsing X file header. --- dlls/d3dxof/d3dxof.c | 238 +++++------------------------------ dlls/d3dxof/d3dxof_private.h | 1 + dlls/d3dxof/parsing.c | 101 +++++++++++++++ 3 files changed, 130 insertions(+), 210 deletions(-) diff --git a/dlls/d3dxof/d3dxof.c b/dlls/d3dxof/d3dxof.c index 8392c3192f4..031f780609c 100644 --- a/dlls/d3dxof/d3dxof.c +++ b/dlls/d3dxof/d3dxof.c @@ -33,18 +33,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3dxof); -#define MAKEFOUR(a,b,c,d) ((DWORD)a + ((DWORD)b << 8) + ((DWORD)c << 16) + ((DWORD)d << 24)) -#define XOFFILE_FORMAT_MAGIC MAKEFOUR('x','o','f',' ') -#define XOFFILE_FORMAT_VERSION_302 MAKEFOUR('0','3','0','2') -#define XOFFILE_FORMAT_VERSION_303 MAKEFOUR('0','3','0','3') -#define XOFFILE_FORMAT_BINARY MAKEFOUR('b','i','n',' ') -#define XOFFILE_FORMAT_TEXT MAKEFOUR('t','x','t',' ') -#define XOFFILE_FORMAT_BINARY_MSZIP MAKEFOUR('b','z','i','p') -#define XOFFILE_FORMAT_TEXT_MSZIP MAKEFOUR('t','z','i','p') -#define XOFFILE_FORMAT_COMPRESSED MAKEFOUR('c','m','p',' ') -#define XOFFILE_FORMAT_FLOAT_BITS_32 MAKEFOUR('0','0','3','2') -#define XOFFILE_FORMAT_FLOAT_BITS_64 MAKEFOUR('0','0','6','4') - static const struct IDirectXFileVtbl IDirectXFile_Vtbl; static const struct IDirectXFileBinaryVtbl IDirectXFileBinary_Vtbl; static const struct IDirectXFileDataVtbl IDirectXFileData_Vtbl; @@ -57,15 +45,6 @@ static HRESULT IDirectXFileDataReferenceImpl_Create(IDirectXFileDataReferenceImp static HRESULT IDirectXFileEnumObjectImpl_Create(IDirectXFileEnumObjectImpl** ppObj); static HRESULT IDirectXFileSaveObjectImpl_Create(IDirectXFileSaveObjectImpl** ppObj); -/* FOURCC to string conversion for debug messages */ -static const char *debugstr_fourcc(DWORD fourcc) -{ - if (!fourcc) return "'null'"; - return wine_dbg_sprintf ("\'%c%c%c%c\'", - (char)(fourcc), (char)(fourcc >> 8), - (char)(fourcc >> 16), (char)(fourcc >> 24)); -} - HRESULT IDirectXFileImpl_Create(IUnknown* pUnkOuter, LPVOID* ppObj) { IDirectXFileImpl* object; @@ -140,10 +119,6 @@ static HRESULT WINAPI IDirectXFileImpl_CreateEnumObject(IDirectXFile* iface, LPV IDirectXFileImpl *This = impl_from_IDirectXFile(iface); IDirectXFileEnumObjectImpl* object; HRESULT hr; - DWORD* header; - LPBYTE mapped_memory = NULL; - LPBYTE decomp_buffer = NULL; - DWORD decomp_size = 0; LPBYTE file_buffer; DWORD file_size; @@ -155,6 +130,10 @@ static HRESULT WINAPI IDirectXFileImpl_CreateEnumObject(IDirectXFile* iface, LPV /* Only lowest 4 bits are relevant in DXFILELOADOPTIONS */ dwLoadOptions &= 0xF; + hr = IDirectXFileEnumObjectImpl_Create(&object); + if (FAILED(hr)) + return hr; + if (dwLoadOptions == DXFILELOAD_FROMFILE) { HANDLE hFile, file_mapping; @@ -171,22 +150,21 @@ static HRESULT WINAPI IDirectXFileImpl_CreateEnumObject(IDirectXFile* iface, LPV file_size = GetFileSize(hFile, NULL); file_mapping = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + CloseHandle(hFile); if (!file_mapping) { - CloseHandle(hFile); hr = DXFILEERR_BADFILETYPE; goto error; } - mapped_memory = MapViewOfFile(file_mapping, FILE_MAP_READ, 0, 0, 0); + object->mapped_memory = MapViewOfFile(file_mapping, FILE_MAP_READ, 0, 0, 0); CloseHandle(file_mapping); - CloseHandle(hFile); - if (!mapped_memory) + if (!object->mapped_memory) { hr = DXFILEERR_BADFILETYPE; goto error; } - file_buffer = mapped_memory; + file_buffer = object->mapped_memory; } else if (dwLoadOptions == DXFILELOAD_FROMRESOURCE) { @@ -235,107 +213,17 @@ static HRESULT WINAPI IDirectXFileImpl_CreateEnumObject(IDirectXFile* iface, LPV goto error; } - header = (DWORD*)file_buffer; - - if (TRACE_ON(d3dxof)) - { - char string[17]; - memcpy(string, header, 16); - string[16] = 0; - TRACE("header = '%s'\n", string); - } - - if (file_size < 16) - { - hr = DXFILEERR_BADFILETYPE; - goto error; - } - - if (header[0] != XOFFILE_FORMAT_MAGIC) - { - hr = DXFILEERR_BADFILETYPE; - goto error; - } - - if ((header[1] != XOFFILE_FORMAT_VERSION_302) && (header[1] != XOFFILE_FORMAT_VERSION_303)) - { - hr = DXFILEERR_BADFILEVERSION; - goto error; - } - - if ((header[2] != XOFFILE_FORMAT_BINARY) && (header[2] != XOFFILE_FORMAT_TEXT) && - (header[2] != XOFFILE_FORMAT_BINARY_MSZIP) && (header[2] != XOFFILE_FORMAT_TEXT_MSZIP)) - { - WARN("File type %s unknown\n", debugstr_fourcc(header[2])); - hr = DXFILEERR_BADFILETYPE; - goto error; - } - - if ((header[2] == XOFFILE_FORMAT_BINARY_MSZIP) || (header[2] == XOFFILE_FORMAT_TEXT_MSZIP)) - { - int err; - DWORD comp_size; - - /* 0-15 -> xfile header, 16-17 -> decompressed size w/ header, 18-19 -> null, - 20-21 -> decompressed size w/o header, 22-23 -> size of MSZIP compressed data, - 24-xx -> compressed MSZIP data */ - decomp_size = ((WORD*)file_buffer)[10]; - comp_size = ((WORD*)file_buffer)[11]; - - TRACE("Compressed format %s detected: compressed_size = %x, decompressed_size = %x\n", - debugstr_fourcc(header[2]), comp_size, decomp_size); - - decomp_buffer = HeapAlloc(GetProcessHeap(), 0, decomp_size); - if (!decomp_buffer) - { - ERR("Out of memory\n"); - hr = DXFILEERR_BADALLOC; - goto error; - } - err = mszip_decompress(comp_size, decomp_size, (char*)file_buffer + 24, (char*)decomp_buffer); - if (err) - { - WARN("Error while decomrpessing mszip archive %d\n", err); - hr = DXFILEERR_BADALLOC; - goto error; - } - } - - if ((header[3] != XOFFILE_FORMAT_FLOAT_BITS_32) && (header[3] != XOFFILE_FORMAT_FLOAT_BITS_64)) - { - hr = DXFILEERR_BADFILEFLOATSIZE; - goto error; - } - - TRACE("Header is correct\n"); - - hr = IDirectXFileEnumObjectImpl_Create(&object); - if (FAILED(hr)) - goto error; - - object->mapped_memory = mapped_memory; - object->decomp_buffer = decomp_buffer; - object->pDirectXFile = This; - object->buf.pdxf = This; - object->buf.txt = (header[2] == XOFFILE_FORMAT_TEXT) || (header[2] == XOFFILE_FORMAT_TEXT_MSZIP); - object->buf.token_present = FALSE; - TRACE("File size is %d bytes\n", file_size); - if (decomp_size) - { - /* Use decompressed data */ - object->buf.buffer = decomp_buffer; - object->buf.rem_bytes = decomp_size; - } - else - { - /* Go to data after header */ - object->buf.buffer = file_buffer + 16; - object->buf.rem_bytes = file_size - 16; - } + object->pDirectXFile = This; - *ppEnumObj = &object->IDirectXFileEnumObject_iface; + object->buf.pdxf = This; + object->buf.token_present = FALSE; + object->buf.buffer = file_buffer; + object->buf.rem_bytes = file_size; + hr = parse_header(&object->buf, &object->decomp_buffer); + if (FAILED(hr)) + goto error; while (object->buf.rem_bytes && is_template_available(&object->buf)) { @@ -361,12 +249,12 @@ static HRESULT WINAPI IDirectXFileImpl_CreateEnumObject(IDirectXFile* iface, LPV DPRINTF("%s - %s\n", This->xtemplates[i].name, debugstr_guid(&This->xtemplates[i].class_id)); } + *ppEnumObj = &object->IDirectXFileEnumObject_iface; + return DXFILE_OK; error: - if (mapped_memory) - UnmapViewOfFile(mapped_memory); - HeapFree(GetProcessHeap(), 0, decomp_buffer); + IDirectXFileEnumObject_Release(&object->IDirectXFileEnumObject_iface); *ppEnumObj = NULL; return hr; @@ -392,10 +280,9 @@ static HRESULT WINAPI IDirectXFileImpl_CreateSaveObject(IDirectXFile* iface, LPC static HRESULT WINAPI IDirectXFileImpl_RegisterTemplates(IDirectXFile* iface, LPVOID pvData, DWORD cbSize) { IDirectXFileImpl *This = impl_from_IDirectXFile(iface); - DWORD token_header; parse_buffer buf; + HRESULT hr; LPBYTE decomp_buffer = NULL; - DWORD decomp_size = 0; buf.buffer = pvData; buf.rem_bytes = cbSize; @@ -408,87 +295,17 @@ static HRESULT WINAPI IDirectXFileImpl_RegisterTemplates(IDirectXFile* iface, LP if (!pvData) return DXFILEERR_BADVALUE; - if (cbSize < 16) - return DXFILEERR_BADFILETYPE; - - if (TRACE_ON(d3dxof)) - { - char string[17]; - memcpy(string, pvData, 16); - string[16] = 0; - TRACE("header = '%s'\n", string); - } - - read_bytes(&buf, &token_header, 4); - - if (token_header != XOFFILE_FORMAT_MAGIC) - return DXFILEERR_BADFILETYPE; - - read_bytes(&buf, &token_header, 4); - - if ((token_header != XOFFILE_FORMAT_VERSION_302) && (token_header != XOFFILE_FORMAT_VERSION_303)) - return DXFILEERR_BADFILEVERSION; - - read_bytes(&buf, &token_header, 4); - - if ((token_header != XOFFILE_FORMAT_BINARY) && (token_header != XOFFILE_FORMAT_TEXT) && - (token_header != XOFFILE_FORMAT_BINARY_MSZIP) && (token_header != XOFFILE_FORMAT_TEXT_MSZIP)) - { - WARN("File type %s unknown\n", debugstr_fourcc(token_header)); - return DXFILEERR_BADFILETYPE; - } - - if ((token_header == XOFFILE_FORMAT_BINARY_MSZIP) || (token_header == XOFFILE_FORMAT_TEXT_MSZIP)) - { - int err; - DWORD comp_size; - - /* 0-15 -> xfile header, 16-17 -> decompressed size w/ header, 18-19 -> null, - 20-21 -> decompressed size w/o header, 22-23 -> size of MSZIP compressed data, - 24-xx -> compressed MSZIP data */ - decomp_size = ((WORD*)pvData)[10]; - comp_size = ((WORD*)pvData)[11]; - - TRACE("Compressed format %s detected: compressed_size = %x, decompressed_size = %x\n", - debugstr_fourcc(token_header), comp_size, decomp_size); - - decomp_buffer = HeapAlloc(GetProcessHeap(), 0, decomp_size); - if (!decomp_buffer) - { - ERR("Out of memory\n"); - return DXFILEERR_BADALLOC; - } - err = mszip_decompress(comp_size, decomp_size, (char*)pvData + 24, (char*)decomp_buffer); - if (err) - { - WARN("Error while decomrpessing mszip archive %d\n", err); - HeapFree(GetProcessHeap(), 0, decomp_buffer); - return DXFILEERR_BADALLOC; - } - } - - if ((token_header == XOFFILE_FORMAT_TEXT) || (token_header == XOFFILE_FORMAT_TEXT_MSZIP)) - buf.txt = TRUE; - - read_bytes(&buf, &token_header, 4); - - if ((token_header != XOFFILE_FORMAT_FLOAT_BITS_32) && (token_header != XOFFILE_FORMAT_FLOAT_BITS_64)) - return DXFILEERR_BADFILEFLOATSIZE; - - TRACE("Header is correct\n"); - - if (decomp_size) - { - buf.buffer = decomp_buffer; - buf.rem_bytes = decomp_size; - } + hr = parse_header(&buf, &decomp_buffer); + if (FAILED(hr)) + goto cleanup; while (buf.rem_bytes && is_template_available(&buf)) { if (!parse_template(&buf)) { WARN("Template is not correct\n"); - return DXFILEERR_BADVALUE; + hr = DXFILEERR_BADVALUE; + goto cleanup; } else { @@ -506,9 +323,10 @@ static HRESULT WINAPI IDirectXFileImpl_RegisterTemplates(IDirectXFile* iface, LP DPRINTF("%s - %s\n", This->xtemplates[i].name, debugstr_guid(&This->xtemplates[i].class_id)); } + hr = DXFILE_OK; +cleanup: HeapFree(GetProcessHeap(), 0, decomp_buffer); - - return DXFILE_OK; + return hr; } static const IDirectXFileVtbl IDirectXFile_Vtbl = diff --git a/dlls/d3dxof/d3dxof_private.h b/dlls/d3dxof/d3dxof_private.h index 5e61d657b5d..15dca521ce4 100644 --- a/dlls/d3dxof/d3dxof_private.h +++ b/dlls/d3dxof/d3dxof_private.h @@ -163,6 +163,7 @@ typedef struct { HRESULT IDirectXFileImpl_Create(IUnknown *pUnkOuter, LPVOID *ppObj) DECLSPEC_HIDDEN; BOOL read_bytes(parse_buffer * buf, LPVOID data, DWORD size) DECLSPEC_HIDDEN; +HRESULT parse_header(parse_buffer *buf, BYTE **decomp_buffer_ptr) DECLSPEC_HIDDEN; BOOL parse_template(parse_buffer * buf) DECLSPEC_HIDDEN; void dump_template(xtemplate* templates_array, xtemplate* ptemplate) DECLSPEC_HIDDEN; BOOL is_template_available(parse_buffer * buf) DECLSPEC_HIDDEN; diff --git a/dlls/d3dxof/parsing.c b/dlls/d3dxof/parsing.c index 417194be2db..7682dfee76e 100644 --- a/dlls/d3dxof/parsing.c +++ b/dlls/d3dxof/parsing.c @@ -36,6 +36,18 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3dxof_parsing); +#define MAKEFOUR(a,b,c,d) ((DWORD)a + ((DWORD)b << 8) + ((DWORD)c << 16) + ((DWORD)d << 24)) +#define XOFFILE_FORMAT_MAGIC MAKEFOUR('x','o','f',' ') +#define XOFFILE_FORMAT_VERSION_302 MAKEFOUR('0','3','0','2') +#define XOFFILE_FORMAT_VERSION_303 MAKEFOUR('0','3','0','3') +#define XOFFILE_FORMAT_BINARY MAKEFOUR('b','i','n',' ') +#define XOFFILE_FORMAT_TEXT MAKEFOUR('t','x','t',' ') +#define XOFFILE_FORMAT_BINARY_MSZIP MAKEFOUR('b','z','i','p') +#define XOFFILE_FORMAT_TEXT_MSZIP MAKEFOUR('t','z','i','p') +#define XOFFILE_FORMAT_COMPRESSED MAKEFOUR('c','m','p',' ') +#define XOFFILE_FORMAT_FLOAT_BITS_32 MAKEFOUR('0','0','3','2') +#define XOFFILE_FORMAT_FLOAT_BITS_64 MAKEFOUR('0','0','6','4') + #define TOKEN_NAME 1 #define TOKEN_STRING 2 #define TOKEN_INTEGER 3 @@ -70,6 +82,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3dxof_parsing); #define CLSIDFMT "<%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X>" +/* FOURCC to string conversion for debug messages */ +static const char *debugstr_fourcc(DWORD fourcc) +{ + if (!fourcc) return "'null'"; + return wine_dbg_sprintf ("\'%c%c%c%c\'", + (char)(fourcc), (char)(fourcc >> 8), + (char)(fourcc >> 16), (char)(fourcc >> 24)); +} + static const char* get_primitive_string(WORD token) { switch(token) @@ -161,6 +182,86 @@ static void rewind_bytes(parse_buffer * buf, DWORD size) buf->rem_bytes += size; } +HRESULT parse_header(parse_buffer * buf, BYTE ** decomp_buffer_ptr) +{ + /* X File common header: + * 0-3 -> Magic Number (format identifier) + * 4-7 -> Format Version + * 8-11 -> Format Type (text or binary, decompressed or compressed) + * 12-15 -> Float Size (32 or 64 bits) */ + DWORD header[4]; + + if (!read_bytes(buf, header, sizeof(header))) + return DXFILEERR_BADFILETYPE; + + if (TRACE_ON(d3dxof_parsing)) + { + char string[17]; + memcpy(string, header, 16); + string[16] = 0; + TRACE("header = '%s'\n", string); + } + + if (header[0] != XOFFILE_FORMAT_MAGIC) + return DXFILEERR_BADFILETYPE; + + if (header[1] != XOFFILE_FORMAT_VERSION_302 && header[1] != XOFFILE_FORMAT_VERSION_303) + return DXFILEERR_BADFILEVERSION; + + if (header[2] != XOFFILE_FORMAT_BINARY && header[2] != XOFFILE_FORMAT_TEXT && + header[2] != XOFFILE_FORMAT_BINARY_MSZIP && header[2] != XOFFILE_FORMAT_TEXT_MSZIP) + { + WARN("File type %s unknown\n", debugstr_fourcc(header[2])); + return DXFILEERR_BADFILETYPE; + } + + if (header[3] != XOFFILE_FORMAT_FLOAT_BITS_32 && header[3] != XOFFILE_FORMAT_FLOAT_BITS_64) + return DXFILEERR_BADFILEFLOATSIZE; + + buf->txt = header[2] == XOFFILE_FORMAT_TEXT || header[2] == XOFFILE_FORMAT_TEXT_MSZIP; + + if (header[2] == XOFFILE_FORMAT_BINARY_MSZIP || header[2] == XOFFILE_FORMAT_TEXT_MSZIP) + { + /* Extended header for compressed data: + * 16-17 -> decompressed size w/ header, 18-19 -> null, + * 20-21 -> decompressed size w/o header, 22-23 -> size of MSZIP compressed data, + * 24-xx -> compressed MSZIP data */ + int err; + WORD decomp_size; + WORD comp_size; + LPBYTE decomp_buffer; + + buf->rem_bytes -= sizeof(WORD) * 2; + buf->buffer += sizeof(WORD) * 2; + read_bytes(buf, &decomp_size, sizeof(decomp_size)); + read_bytes(buf, &comp_size, sizeof(comp_size)); + + TRACE("Compressed format %s detected: compressed_size = %x, decompressed_size = %x\n", + debugstr_fourcc(header[2]), comp_size, decomp_size); + + decomp_buffer = HeapAlloc(GetProcessHeap(), 0, decomp_size); + if (!decomp_buffer) + { + ERR("Out of memory\n"); + return DXFILEERR_BADALLOC; + } + err = mszip_decompress(comp_size, decomp_size, (char*)buf->buffer, (char*)decomp_buffer); + if (err) + { + WARN("Error while decompressing mszip archive %d\n", err); + HeapFree(GetProcessHeap(), 0, decomp_buffer); + return DXFILEERR_BADALLOC; + } + /* Use decompressed data */ + buf->buffer = *decomp_buffer_ptr = decomp_buffer; + buf->rem_bytes = decomp_size; + } + + TRACE("Header is correct\n"); + + return S_OK; +} + static void dump_TOKEN(WORD token) { #define DUMP_TOKEN(t) case t: TRACE(#t "\n"); break