From 794dbe4f93be9008c3d7231d24b4e98663a6c0c4 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Thu, 28 Dec 2006 19:58:35 +0900 Subject: [PATCH] kernel32: Remove incorrect and incomplete implementation of BeginResourceUpdate. --- dlls/kernel32/resource.c | 315 ++++++++++++++------------------- dlls/kernel32/tests/resource.c | 8 +- 2 files changed, 135 insertions(+), 188 deletions(-) diff --git a/dlls/kernel32/resource.c b/dlls/kernel32/resource.c index 12a55e7b5a4..c817fcbfe4f 100644 --- a/dlls/kernel32/resource.c +++ b/dlls/kernel32/resource.c @@ -616,60 +616,111 @@ DWORD WINAPI SizeofResource( HINSTANCE hModule, HRSRC hRsrc ) return ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->Size; } - typedef struct { LPWSTR pFileName; - struct list resources_list; } QUEUEDUPDATES; -typedef struct +BOOL update_add_resource( QUEUEDUPDATES *updates, LPCWSTR Type, LPCWSTR Name, + WORD Language, DWORD codepage, LPCVOID lpData, DWORD cbData ) { - struct list entry; - LPWSTR lpType; - LPWSTR lpName; - WORD wLanguage; - LPVOID lpData; - DWORD cbData; -} QUEUEDRESOURCE; - -static BOOL CALLBACK enum_resources_languages_delete_all(HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, WORD wLang, LONG_PTR lParam) -{ - return UpdateResourceW((HANDLE)lParam, lpType, lpName, wLang, NULL, 0); + FIXME("%p %s %s %04x %p %d bytes\n", updates, debugstr_w(Type), debugstr_w(Name), Language, lpData, cbData); + return FALSE; } -static BOOL CALLBACK enum_resources_names_delete_all(HMODULE hModule, LPCWSTR lpType, LPWSTR lpName, LONG_PTR lParam) +IMAGE_NT_HEADERS *get_nt_header( void *base, DWORD mapping_size ) { - return EnumResourceLanguagesW(hModule, lpType, lpName, enum_resources_languages_delete_all, lParam); + IMAGE_NT_HEADERS *nt; + IMAGE_DOS_HEADER *dos; + + if (mapping_sizee_magic != IMAGE_DOS_SIGNATURE) + return NULL; + + if ((dos->e_lfanew + sizeof (*nt)) > mapping_size) + return NULL; + + nt = (void*) ((BYTE*)base + dos->e_lfanew); + + if (nt->Signature != IMAGE_NT_SIGNATURE) + return NULL; + + return nt; } -static BOOL CALLBACK enum_resources_types_delete_all(HMODULE hModule, LPWSTR lpType, LONG_PTR lParam) +IMAGE_SECTION_HEADER *get_section_header( void *base, DWORD mapping_size, DWORD *num_sections ) { - return EnumResourceNamesW(hModule, lpType, enum_resources_names_delete_all, lParam); + IMAGE_NT_HEADERS *nt; + IMAGE_SECTION_HEADER *sec; + DWORD section_ofs; + + nt = get_nt_header( base, mapping_size ); + if (!nt) + return NULL; + + /* check that we don't go over the end of the file accessing the sections */ + section_ofs = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + nt->FileHeader.SizeOfOptionalHeader; + if ((nt->FileHeader.NumberOfSections * sizeof (*sec) + section_ofs) > mapping_size) + return NULL; + + if (num_sections) + *num_sections = nt->FileHeader.NumberOfSections; + + /* from here we have a valid PE exe to update */ + return (void*) ((BYTE*)nt + section_ofs); } -static BOOL CALLBACK enum_resources_languages_add_all(HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, WORD wLang, LONG_PTR lParam) +static BOOL load_raw_resources( HANDLE file, QUEUEDUPDATES *updates ) { - DWORD size; - HRSRC hResource = FindResourceExW(hModule, lpType, lpName, wLang); - HGLOBAL hGlobal; - LPVOID lpData; + const IMAGE_NT_HEADERS *nt; + const IMAGE_SECTION_HEADER *sec; + BOOL ret = FALSE; + HANDLE mapping; + DWORD mapping_size, num_sections = 0; + void *base = NULL; - if(hResource == NULL) return FALSE; - if(!(hGlobal = LoadResource(hModule, hResource))) return FALSE; - if(!(lpData = LockResource(hGlobal))) return FALSE; - if(!(size = SizeofResource(hModule, hResource))) return FALSE; - return UpdateResourceW((HANDLE)lParam, lpType, lpName, wLang, lpData, size); + mapping_size = GetFileSize( file, NULL ); + + mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL ); + if (!mapping) + goto done; + + base = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, mapping_size ); + if (!base) + goto done; + + nt = get_nt_header( base, mapping_size ); + if (!nt) + goto done; + + TRACE("resources: %08x %08x\n", + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress, + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size); + + sec = get_section_header( base, mapping_size, &num_sections ); + if (!sec) + goto done; + + ret = TRUE; + + FIXME("not implemented\n"); + +done: + if (base) + UnmapViewOfFile( base ); + if (mapping) + CloseHandle( mapping ); + + return ret; } -static BOOL CALLBACK enum_resources_names_add_all(HMODULE hModule, LPCWSTR lpType, LPWSTR lpName, LONG_PTR lParam) +BOOL write_raw_resources( QUEUEDUPDATES *updates ) { - return EnumResourceLanguagesW(hModule, lpType, lpName, enum_resources_languages_add_all, lParam); -} - -static BOOL CALLBACK enum_resources_types_add_all(HMODULE hModule, LPWSTR lpType, LONG_PTR lParam) -{ - return EnumResourceNamesW(hModule, lpType, enum_resources_names_add_all, lParam); + FIXME("not implemented\n"); + return FALSE; } /*********************************************************************** @@ -677,76 +728,41 @@ static BOOL CALLBACK enum_resources_types_add_all(HMODULE hModule, LPWSTR lpType */ HANDLE WINAPI BeginUpdateResourceW( LPCWSTR pFileName, BOOL bDeleteExistingResources ) { - HANDLE hFile = NULL; - WIN32_FIND_DATAW fd; - HANDLE hModule = NULL; - HANDLE hUpdate = NULL; - QUEUEDUPDATES *current_updates = NULL; - HANDLE ret = NULL; + QUEUEDUPDATES *updates = NULL; + HANDLE hUpdate, file, ret = NULL; - TRACE("%s, %d\n",debugstr_w(pFileName),bDeleteExistingResources); + TRACE("%s, %d\n", debugstr_w(pFileName), bDeleteExistingResources); - hFile = FindFirstFileW(pFileName, &fd); - if(hFile == INVALID_HANDLE_VALUE) - { - hFile = NULL; - SetLastError(ERROR_FILE_NOT_FOUND); - goto done; - } - if(fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) - { - SetLastError(ERROR_FILE_READ_ONLY); - goto done; - } + hUpdate = GlobalAlloc(GHND, sizeof(QUEUEDUPDATES)); + if (!hUpdate) + return ret; - hModule = LoadLibraryW(pFileName); - if(hModule == NULL) + updates = GlobalLock(hUpdate); + if (updates) { - SetLastError(ERROR_INVALID_PARAMETER); - goto done; - } + updates->pFileName = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(pFileName)+1)*sizeof(WCHAR)); + if (updates->pFileName) + { + lstrcpyW(updates->pFileName, pFileName); - if(!(hUpdate = GlobalAlloc(GHND, sizeof(QUEUEDUPDATES)))) - { - SetLastError(ERROR_OUTOFMEMORY); - goto done; - } - if(!(current_updates = GlobalLock(hUpdate))) - { - SetLastError(ERROR_INVALID_HANDLE); - goto done; - } - if(!(current_updates->pFileName = HeapAlloc(GetProcessHeap(), 0, (strlenW(pFileName)+1)*sizeof(WCHAR)))) - { - SetLastError(ERROR_OUTOFMEMORY); - goto done; - } - strcpyW(current_updates->pFileName, pFileName); - list_init(¤t_updates->resources_list); + file = CreateFileW( pFileName, GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, 0, 0 ); - if(bDeleteExistingResources) - { - if(!EnumResourceTypesW(hModule, enum_resources_types_delete_all, (LONG_PTR)hUpdate)) - goto done; - } - else - { - if(!EnumResourceTypesW(hModule, enum_resources_types_add_all, (LONG_PTR)hUpdate)) - goto done; - } - ret = hUpdate; + /* if resources are deleted, only the file's presence is checked */ + if (file != INVALID_HANDLE_VALUE && + (bDeleteExistingResources || load_raw_resources( file, updates ))) + ret = hUpdate; + else + HeapFree( GetProcessHeap(), 0, updates->pFileName ); -done: - if(!ret && current_updates) - { - HeapFree(GetProcessHeap(), 0, current_updates->pFileName); + CloseHandle( file ); + } GlobalUnlock(hUpdate); - GlobalFree(hUpdate); - hUpdate = NULL; } - if(hUpdate) GlobalUnlock(hUpdate); - if(hModule) FreeLibrary(hModule); - if(hFile) FindClose(hFile); + + if (!ret) + GlobalFree(hUpdate); + return ret; } @@ -770,46 +786,21 @@ HANDLE WINAPI BeginUpdateResourceA( LPCSTR pFileName, BOOL bDeleteExistingResour */ BOOL WINAPI EndUpdateResourceW( HANDLE hUpdate, BOOL fDiscard ) { - QUEUEDUPDATES *current_updates = NULL; - BOOL found = TRUE; - BOOL ret = FALSE; - struct list *ptr = NULL; - QUEUEDRESOURCE *current_resource = NULL; + QUEUEDUPDATES *updates; + BOOL ret; - FIXME("(%p,%d): stub\n",hUpdate,fDiscard); + TRACE("%p %d\n", hUpdate, fDiscard); - if(!(current_updates = GlobalLock(hUpdate))) - { - SetLastError(ERROR_INVALID_HANDLE); - found = FALSE; - goto done; - } + updates = GlobalLock(hUpdate); + if (!updates) + return FALSE; - if(fDiscard) - ret = TRUE; - else - { - /* FIXME: This is the only missing part, an actual implementation */ - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - ret = FALSE; - } + ret = fDiscard || write_raw_resources( updates ); + + HeapFree( GetProcessHeap(), 0, updates->pFileName ); + GlobalUnlock( hUpdate ); + GlobalFree( hUpdate ); -done: - if(found) - { - while ((ptr = list_head(¤t_updates->resources_list)) != NULL) - { - current_resource = LIST_ENTRY(ptr, QUEUEDRESOURCE, entry); - list_remove(¤t_resource->entry); - if(HIWORD(current_resource->lpType)) HeapFree(GetProcessHeap(), 0, current_resource->lpType); - if(HIWORD(current_resource->lpName)) HeapFree(GetProcessHeap(), 0, current_resource->lpName); - HeapFree(GetProcessHeap(), 0, current_resource->lpData); - HeapFree(GetProcessHeap(), 0, current_resource); - } - HeapFree(GetProcessHeap(), 0, current_updates->pFileName); - GlobalUnlock(hUpdate); - GlobalFree(hUpdate); - } return ret; } @@ -829,63 +820,19 @@ BOOL WINAPI EndUpdateResourceA( HANDLE hUpdate, BOOL fDiscard ) BOOL WINAPI UpdateResourceW( HANDLE hUpdate, LPCWSTR lpType, LPCWSTR lpName, WORD wLanguage, LPVOID lpData, DWORD cbData) { - QUEUEDUPDATES *current_updates = NULL; - BOOL found = TRUE; - QUEUEDRESOURCE *current_resource = NULL; + QUEUEDUPDATES *updates; BOOL ret = FALSE; - TRACE("%p %s %s %08x %p %d\n",hUpdate,debugstr_w(lpType),debugstr_w(lpName),wLanguage,lpData,cbData); + TRACE("%p %s %s %08x %p %d\n", hUpdate, + debugstr_w(lpType), debugstr_w(lpName), wLanguage, lpData, cbData); - if(!(current_updates = GlobalLock(hUpdate))) + updates = GlobalLock(hUpdate); + if (updates) { - SetLastError(ERROR_INVALID_HANDLE); - found = FALSE; - goto done; + ret = update_add_resource( updates, lpType, lpName, + wLanguage, GetACP(), lpData, cbData ); + GlobalUnlock(hUpdate); } - - if(!(current_resource = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUEDRESOURCE)))) - { - SetLastError(ERROR_OUTOFMEMORY); - goto done; - } - if(!HIWORD(lpType)) - current_resource->lpType = (LPWSTR)lpType; - else if((current_resource->lpType = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpType)+1)*sizeof(WCHAR)))) - strcpyW(current_resource->lpType, lpType); - else - { - SetLastError(ERROR_OUTOFMEMORY); - goto done; - } - if(!HIWORD(lpName)) - current_resource->lpName = (LPWSTR)lpName; - else if((current_resource->lpName = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpName)+1)*sizeof(WCHAR)))) - strcpyW(current_resource->lpName, lpName); - else - { - SetLastError(ERROR_OUTOFMEMORY); - goto done; - } - if(!(current_resource->lpData = HeapAlloc(GetProcessHeap(), 0, cbData))) - { - SetLastError(ERROR_OUTOFMEMORY); - goto done; - } - current_resource->wLanguage = wLanguage; - memcpy(current_resource->lpData, lpData, cbData); - current_resource->cbData = cbData; - list_add_tail(¤t_updates->resources_list, ¤t_resource->entry); - ret = TRUE; - -done: - if(!ret && current_resource) - { - if(HIWORD(current_resource->lpType)) HeapFree(GetProcessHeap(), 0, current_resource->lpType); - if(HIWORD(current_resource->lpName)) HeapFree(GetProcessHeap(), 0, current_resource->lpName); - HeapFree(GetProcessHeap(), 0, current_resource->lpData); - HeapFree(GetProcessHeap(), 0, current_resource); - } - if(found) GlobalUnlock(hUpdate); return ret; } diff --git a/dlls/kernel32/tests/resource.c b/dlls/kernel32/tests/resource.c index d5f3707dd78..0c84757d6ed 100644 --- a/dlls/kernel32/tests/resource.c +++ b/dlls/kernel32/tests/resource.c @@ -122,7 +122,7 @@ static void update_empty_exe( void ) CloseHandle( file ); res = BeginUpdateResource( filename, TRUE ); - todo_wine ok( res != NULL, "BeginUpdateResource failed\n"); + ok( res != NULL, "BeginUpdateResource failed\n"); /* check if it's possible to open the file now */ test = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0); @@ -143,7 +143,7 @@ static void update_resources_none( void ) BOOL r; res = BeginUpdateResource( filename, FALSE ); - todo_wine ok( res != NULL, "BeginUpdateResource failed\n"); + ok( res != NULL, "BeginUpdateResource failed\n"); r = EndUpdateResource( res, FALSE ); todo_wine ok( r, "EndUpdateResouce failed\n"); @@ -155,7 +155,7 @@ static void update_resources_delete( void ) BOOL r; res = BeginUpdateResource( filename, TRUE ); - todo_wine ok( res != NULL, "BeginUpdateResource failed\n"); + ok( res != NULL, "BeginUpdateResource failed\n"); r = EndUpdateResource( res, FALSE ); todo_wine ok( r, "EndUpdateResouce failed\n"); @@ -175,10 +175,10 @@ void update_resources_version(void) struct verhdr hdr; char foo[] = "red and white"; - todo_wine { res = BeginUpdateResource( filename, TRUE ); ok( res != NULL, "BeginUpdateResource failed\n"); + todo_wine { memset( &hdr, 0, sizeof hdr ); r = UpdateResource( res, RT_VERSION,