mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-01 11:08:45 +00:00
kernel32: Remove incorrect and incomplete implementation of BeginResourceUpdate.
This commit is contained in:
parent
1cd16ed7f3
commit
794dbe4f93
2 changed files with 135 additions and 188 deletions
|
@ -616,60 +616,111 @@ DWORD WINAPI SizeofResource( HINSTANCE hModule, HRSRC hRsrc )
|
||||||
return ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->Size;
|
return ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
LPWSTR pFileName;
|
LPWSTR pFileName;
|
||||||
struct list resources_list;
|
|
||||||
} QUEUEDUPDATES;
|
} QUEUEDUPDATES;
|
||||||
|
|
||||||
typedef struct
|
BOOL update_add_resource( QUEUEDUPDATES *updates, LPCWSTR Type, LPCWSTR Name,
|
||||||
|
WORD Language, DWORD codepage, LPCVOID lpData, DWORD cbData )
|
||||||
{
|
{
|
||||||
struct list entry;
|
FIXME("%p %s %s %04x %p %d bytes\n", updates, debugstr_w(Type), debugstr_w(Name), Language, lpData, cbData);
|
||||||
LPWSTR lpType;
|
return FALSE;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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_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_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;
|
const IMAGE_NT_HEADERS *nt;
|
||||||
HRSRC hResource = FindResourceExW(hModule, lpType, lpName, wLang);
|
const IMAGE_SECTION_HEADER *sec;
|
||||||
HGLOBAL hGlobal;
|
BOOL ret = FALSE;
|
||||||
LPVOID lpData;
|
HANDLE mapping;
|
||||||
|
DWORD mapping_size, num_sections = 0;
|
||||||
|
void *base = NULL;
|
||||||
|
|
||||||
if(hResource == NULL) return FALSE;
|
mapping_size = GetFileSize( file, NULL );
|
||||||
if(!(hGlobal = LoadResource(hModule, hResource))) return FALSE;
|
|
||||||
if(!(lpData = LockResource(hGlobal))) return FALSE;
|
mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL );
|
||||||
if(!(size = SizeofResource(hModule, hResource))) return FALSE;
|
if (!mapping)
|
||||||
return UpdateResourceW((HANDLE)lParam, lpType, lpName, wLang, lpData, size);
|
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);
|
FIXME("not implemented\n");
|
||||||
}
|
return FALSE;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -677,76 +728,41 @@ static BOOL CALLBACK enum_resources_types_add_all(HMODULE hModule, LPWSTR lpType
|
||||||
*/
|
*/
|
||||||
HANDLE WINAPI BeginUpdateResourceW( LPCWSTR pFileName, BOOL bDeleteExistingResources )
|
HANDLE WINAPI BeginUpdateResourceW( LPCWSTR pFileName, BOOL bDeleteExistingResources )
|
||||||
{
|
{
|
||||||
HANDLE hFile = NULL;
|
QUEUEDUPDATES *updates = NULL;
|
||||||
WIN32_FIND_DATAW fd;
|
HANDLE hUpdate, file, ret = NULL;
|
||||||
HANDLE hModule = NULL;
|
|
||||||
HANDLE hUpdate = NULL;
|
|
||||||
QUEUEDUPDATES *current_updates = NULL;
|
|
||||||
HANDLE ret = NULL;
|
|
||||||
|
|
||||||
TRACE("%s, %d\n",debugstr_w(pFileName),bDeleteExistingResources);
|
TRACE("%s, %d\n", debugstr_w(pFileName), bDeleteExistingResources);
|
||||||
|
|
||||||
hFile = FindFirstFileW(pFileName, &fd);
|
hUpdate = GlobalAlloc(GHND, sizeof(QUEUEDUPDATES));
|
||||||
if(hFile == INVALID_HANDLE_VALUE)
|
if (!hUpdate)
|
||||||
{
|
return ret;
|
||||||
hFile = NULL;
|
|
||||||
SetLastError(ERROR_FILE_NOT_FOUND);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if(fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_FILE_READ_ONLY);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
hModule = LoadLibraryW(pFileName);
|
updates = GlobalLock(hUpdate);
|
||||||
if(hModule == NULL)
|
if (updates)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
updates->pFileName = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(pFileName)+1)*sizeof(WCHAR));
|
||||||
goto done;
|
if (updates->pFileName)
|
||||||
}
|
{
|
||||||
|
lstrcpyW(updates->pFileName, pFileName);
|
||||||
|
|
||||||
if(!(hUpdate = GlobalAlloc(GHND, sizeof(QUEUEDUPDATES))))
|
file = CreateFileW( pFileName, GENERIC_READ | GENERIC_WRITE,
|
||||||
{
|
0, NULL, OPEN_EXISTING, 0, 0 );
|
||||||
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);
|
|
||||||
|
|
||||||
if(bDeleteExistingResources)
|
/* if resources are deleted, only the file's presence is checked */
|
||||||
{
|
if (file != INVALID_HANDLE_VALUE &&
|
||||||
if(!EnumResourceTypesW(hModule, enum_resources_types_delete_all, (LONG_PTR)hUpdate))
|
(bDeleteExistingResources || load_raw_resources( file, updates )))
|
||||||
goto done;
|
ret = hUpdate;
|
||||||
}
|
else
|
||||||
else
|
HeapFree( GetProcessHeap(), 0, updates->pFileName );
|
||||||
{
|
|
||||||
if(!EnumResourceTypesW(hModule, enum_resources_types_add_all, (LONG_PTR)hUpdate))
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
ret = hUpdate;
|
|
||||||
|
|
||||||
done:
|
CloseHandle( file );
|
||||||
if(!ret && current_updates)
|
}
|
||||||
{
|
|
||||||
HeapFree(GetProcessHeap(), 0, current_updates->pFileName);
|
|
||||||
GlobalUnlock(hUpdate);
|
GlobalUnlock(hUpdate);
|
||||||
GlobalFree(hUpdate);
|
|
||||||
hUpdate = NULL;
|
|
||||||
}
|
}
|
||||||
if(hUpdate) GlobalUnlock(hUpdate);
|
|
||||||
if(hModule) FreeLibrary(hModule);
|
if (!ret)
|
||||||
if(hFile) FindClose(hFile);
|
GlobalFree(hUpdate);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,46 +786,21 @@ HANDLE WINAPI BeginUpdateResourceA( LPCSTR pFileName, BOOL bDeleteExistingResour
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI EndUpdateResourceW( HANDLE hUpdate, BOOL fDiscard )
|
BOOL WINAPI EndUpdateResourceW( HANDLE hUpdate, BOOL fDiscard )
|
||||||
{
|
{
|
||||||
QUEUEDUPDATES *current_updates = NULL;
|
QUEUEDUPDATES *updates;
|
||||||
BOOL found = TRUE;
|
BOOL ret;
|
||||||
BOOL ret = FALSE;
|
|
||||||
struct list *ptr = NULL;
|
|
||||||
QUEUEDRESOURCE *current_resource = NULL;
|
|
||||||
|
|
||||||
FIXME("(%p,%d): stub\n",hUpdate,fDiscard);
|
TRACE("%p %d\n", hUpdate, fDiscard);
|
||||||
|
|
||||||
if(!(current_updates = GlobalLock(hUpdate)))
|
updates = GlobalLock(hUpdate);
|
||||||
{
|
if (!updates)
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
return FALSE;
|
||||||
found = FALSE;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fDiscard)
|
ret = fDiscard || write_raw_resources( updates );
|
||||||
ret = TRUE;
|
|
||||||
else
|
HeapFree( GetProcessHeap(), 0, updates->pFileName );
|
||||||
{
|
GlobalUnlock( hUpdate );
|
||||||
/* FIXME: This is the only missing part, an actual implementation */
|
GlobalFree( hUpdate );
|
||||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
||||||
ret = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -829,63 +820,19 @@ BOOL WINAPI EndUpdateResourceA( HANDLE hUpdate, BOOL fDiscard )
|
||||||
BOOL WINAPI UpdateResourceW( HANDLE hUpdate, LPCWSTR lpType, LPCWSTR lpName,
|
BOOL WINAPI UpdateResourceW( HANDLE hUpdate, LPCWSTR lpType, LPCWSTR lpName,
|
||||||
WORD wLanguage, LPVOID lpData, DWORD cbData)
|
WORD wLanguage, LPVOID lpData, DWORD cbData)
|
||||||
{
|
{
|
||||||
QUEUEDUPDATES *current_updates = NULL;
|
QUEUEDUPDATES *updates;
|
||||||
BOOL found = TRUE;
|
|
||||||
QUEUEDRESOURCE *current_resource = NULL;
|
|
||||||
BOOL ret = FALSE;
|
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);
|
ret = update_add_resource( updates, lpType, lpName,
|
||||||
found = FALSE;
|
wLanguage, GetACP(), lpData, cbData );
|
||||||
goto done;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ static void update_empty_exe( void )
|
||||||
CloseHandle( file );
|
CloseHandle( file );
|
||||||
|
|
||||||
res = BeginUpdateResource( filename, TRUE );
|
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 */
|
/* check if it's possible to open the file now */
|
||||||
test = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
|
test = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
|
||||||
|
@ -143,7 +143,7 @@ static void update_resources_none( void )
|
||||||
BOOL r;
|
BOOL r;
|
||||||
|
|
||||||
res = BeginUpdateResource( filename, FALSE );
|
res = BeginUpdateResource( filename, FALSE );
|
||||||
todo_wine ok( res != NULL, "BeginUpdateResource failed\n");
|
ok( res != NULL, "BeginUpdateResource failed\n");
|
||||||
|
|
||||||
r = EndUpdateResource( res, FALSE );
|
r = EndUpdateResource( res, FALSE );
|
||||||
todo_wine ok( r, "EndUpdateResouce failed\n");
|
todo_wine ok( r, "EndUpdateResouce failed\n");
|
||||||
|
@ -155,7 +155,7 @@ static void update_resources_delete( void )
|
||||||
BOOL r;
|
BOOL r;
|
||||||
|
|
||||||
res = BeginUpdateResource( filename, TRUE );
|
res = BeginUpdateResource( filename, TRUE );
|
||||||
todo_wine ok( res != NULL, "BeginUpdateResource failed\n");
|
ok( res != NULL, "BeginUpdateResource failed\n");
|
||||||
|
|
||||||
r = EndUpdateResource( res, FALSE );
|
r = EndUpdateResource( res, FALSE );
|
||||||
todo_wine ok( r, "EndUpdateResouce failed\n");
|
todo_wine ok( r, "EndUpdateResouce failed\n");
|
||||||
|
@ -175,10 +175,10 @@ void update_resources_version(void)
|
||||||
struct verhdr hdr;
|
struct verhdr hdr;
|
||||||
char foo[] = "red and white";
|
char foo[] = "red and white";
|
||||||
|
|
||||||
todo_wine {
|
|
||||||
res = BeginUpdateResource( filename, TRUE );
|
res = BeginUpdateResource( filename, TRUE );
|
||||||
ok( res != NULL, "BeginUpdateResource failed\n");
|
ok( res != NULL, "BeginUpdateResource failed\n");
|
||||||
|
|
||||||
|
todo_wine {
|
||||||
memset( &hdr, 0, sizeof hdr );
|
memset( &hdr, 0, sizeof hdr );
|
||||||
r = UpdateResource( res,
|
r = UpdateResource( res,
|
||||||
RT_VERSION,
|
RT_VERSION,
|
||||||
|
|
Loading…
Reference in a new issue