[PATCH 2/3] kernel32: Remove incorrect and incomplete implementation
of BeginResourceUpdate.
Mike McCormack
mike at codeweavers.com
Tue Dec 26 23:14:04 CST 2006
---
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 12a55e7..c817fcb 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;
-static BOOL CALLBACK enum_resources_types_delete_all(HMODULE hModule,
LPWSTR lpType, LONG_PTR lParam)
-{
- return EnumResourceNamesW(hModule, lpType,
enum_resources_names_delete_all, lParam);
+ if (mapping_size<sizeof (*dos))
+ return NULL;
+
+ dos = base;
+ if (dos->e_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_languages_add_all(HMODULE hModule,
LPCWSTR lpType, LPCWSTR lpName, WORD wLang, LONG_PTR lParam)
+IMAGE_SECTION_HEADER *get_section_header( void *base, DWORD
mapping_size, DWORD *num_sections )
{
- DWORD size;
- HRSRC hResource = FindResourceExW(hModule, lpType, lpName, wLang);
- HGLOBAL hGlobal;
- LPVOID lpData;
-
- 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);
+ 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_names_add_all(HMODULE hModule,
LPCWSTR lpType, LPWSTR lpName, LONG_PTR lParam)
+static BOOL load_raw_resources( HANDLE file, QUEUEDUPDATES *updates )
{
- return EnumResourceLanguagesW(hModule, lpType, lpName,
enum_resources_languages_add_all, lParam);
+ const IMAGE_NT_HEADERS *nt;
+ const IMAGE_SECTION_HEADER *sec;
+ BOOL ret = FALSE;
+ HANDLE mapping;
+ DWORD mapping_size, num_sections = 0;
+ void *base = NULL;
+
+ 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_types_add_all(HMODULE hModule,
LPWSTR lpType, LONG_PTR lParam)
+BOOL write_raw_resources( QUEUEDUPDATES *updates )
{
- 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;
- }
-
- 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);
+ ret = update_add_resource( updates, lpType, lpName,
+ wLanguage, GetACP(), lpData, cbData );
+ GlobalUnlock(hUpdate);
}
- if(found) GlobalUnlock(hUpdate);
return ret;
}
diff --git a/dlls/kernel32/tests/resource.c b/dlls/kernel32/tests/resource.c
index d5f3707..0c84757 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,
--
1.4.4.1.g431f
More information about the wine-patches
mailing list