Almost complete UpdateResource implementation
Vincent Béron
vberon at mecano.gme.usherb.ca
Fri Sep 3 17:10:10 CDT 2004
The only missing part is for EndUpdateResourceW, as I haven't yet looked
at the layout of a module on disk.
Changelog:
Implement BeginUpdateResource and UpdateResource.
Stub out a bit more of EndUpdateResource.
Vincent
-------------- next part --------------
? res.diff
? resource.c-orig
Index: resource.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/resource.c,v
retrieving revision 1.8
diff -u -r1.8 resource.c
--- resource.c 10 Aug 2004 23:43:21 -0000 1.8
+++ resource.c 3 Sep 2004 22:07:23 -0000
@@ -36,6 +36,8 @@
#include "wine/debug.h"
#include "excpt.h"
#include "wine/exception.h"
+#include "wine/unicode.h"
+#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(resource);
@@ -623,36 +625,133 @@
}
-/***********************************************************************
- * BeginUpdateResourceA (KERNEL32.@)
- */
-HANDLE WINAPI BeginUpdateResourceA( LPCSTR pFileName, BOOL bDeleteExistingResources )
+typedef struct
{
- FIXME("(%s,%d): stub\n",debugstr_a(pFileName),bDeleteExistingResources);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return 0;
+ struct list entry;
+ LPWSTR lpType;
+ LPWSTR lpName;
+ WORD wLanguage;
+ LPVOID lpData;
+ DWORD cbData;
+} QUEUEDRESOURCE;
+
+static inline void free_queuedresource(QUEUEDRESOURCE* resource)
+{
+ if(HIWORD(resource->lpType)) HeapFree(GetProcessHeap(), 0, resource->lpType);
+ if(HIWORD(resource->lpName)) HeapFree(GetProcessHeap(), 0, resource->lpName);
+ if(resource->lpData) HeapFree(GetProcessHeap(), 0, resource->lpData);
+ HeapFree(GetProcessHeap(), 0, resource);
}
+typedef struct
+{
+ struct list entry;
+ HANDLE handle;
+ LPWSTR pFileName;
+ QUEUEDRESOURCE *resources_list;
+} QUEUEDUPDATES;
+
+static inline void free_queuedupdates(QUEUEDUPDATES *updates)
+{
+ if(updates->pFileName) HeapFree(GetProcessHeap(), 0, updates->pFileName);
+ HeapFree(GetProcessHeap(), 0, updates);
+}
+
+static int next_update_queue_handle = 1;
+static QUEUEDUPDATES *updates_list = NULL;
+
+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)
+{
+ return EnumResourceLanguagesW(hModule, lpType, lpName, enum_resources_languages_delete_all, lParam);
+}
+
+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);
+}
/***********************************************************************
* BeginUpdateResourceW (KERNEL32.@)
*/
HANDLE WINAPI BeginUpdateResourceW( LPCWSTR pFileName, BOOL bDeleteExistingResources )
{
- FIXME("(%s,%d): stub\n",debugstr_w(pFileName),bDeleteExistingResources);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return 0;
+ QUEUEDUPDATES *current_updates = NULL;
+ HANDLE hFile = NULL;
+ WIN32_FIND_DATAW fd;
+ HANDLE hModule = NULL;
+ HANDLE ret = NULL;
+
+ TRACE("%s, %d\n",debugstr_w(pFileName),bDeleteExistingResources);
+
+ hFile = FindFirstFileW(pFileName, &fd);
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ hFile = NULL;
+ goto done;
+ }
+ if(fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+ {
+ SetLastError(ERROR_FILE_READ_ONLY);
+ goto done;
+ }
+
+ hModule = LoadLibraryW(pFileName);
+ if(hModule == NULL)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ goto done;
+ }
+
+ if(!(current_updates = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUEDUPDATES))))
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ goto done;
+ }
+ if(!(current_updates->pFileName = HeapAlloc(GetProcessHeap(), 0, (strlenW(pFileName)+1)*sizeof(WCHAR))))
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ goto done;
+ }
+ ret = current_updates->handle = (HANDLE)next_update_queue_handle++;
+ strcpyW(current_updates->pFileName, pFileName);
+ current_updates->resources_list = NULL;
+
+ if(!updates_list)
+ {
+ updates_list = current_updates;
+ list_init(&updates_list->entry);
+ }
+ else
+ list_add_after(&updates_list->entry, ¤t_updates->entry);
+
+ if(bDeleteExistingResources)
+ EnumResourceTypesW(hModule, enum_resources_types_delete_all, (LONG_PTR)&ret);
+
+done:
+ if(!ret && current_updates)
+ free_queuedupdates(current_updates);
+ if(hModule) FreeLibrary(hModule);
+ if(hFile) FindClose(hFile);
+ return ret;
}
/***********************************************************************
- * EndUpdateResourceA (KERNEL32.@)
+ * BeginUpdateResourceA (KERNEL32.@)
*/
-BOOL WINAPI EndUpdateResourceA( HANDLE hUpdate, BOOL fDiscard )
+HANDLE WINAPI BeginUpdateResourceA( LPCSTR pFileName, BOOL bDeleteExistingResources )
{
- FIXME("(%p,%d): stub\n",hUpdate, fDiscard);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ UNICODE_STRING FileNameW;
+ HANDLE ret;
+ RtlCreateUnicodeStringFromAsciiz(&FileNameW, pFileName);
+ ret = BeginUpdateResourceW(FileNameW.Buffer, bDeleteExistingResources);
+ RtlFreeUnicodeString(&FileNameW);
+ return ret;
}
@@ -661,41 +760,166 @@
*/
BOOL WINAPI EndUpdateResourceW( HANDLE hUpdate, BOOL fDiscard )
{
- FIXME("(%p,%d): stub\n",hUpdate, fDiscard);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ BOOL ret = FALSE;
+ struct list *ptr;
+ QUEUEDUPDATES *current_updates = NULL;
+ BOOL found = FALSE;
+ QUEUEDRESOURCE *current_resource = NULL;
+
+ FIXME("(%p,%d): stub\n",hUpdate,fDiscard);
+
+ LIST_FOR_EACH(ptr, &updates_list->entry)
+ {
+ current_updates = LIST_ENTRY(ptr, QUEUEDUPDATES, entry);
+ if(current_updates->handle == hUpdate)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ if(!found)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ goto done;
+ }
+
+ if(fDiscard)
+ ret = TRUE;
+ else
+ {
+ /* FIXME: This is the only missing part, an actual implementation */
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ ret = FALSE;
+ }
+
+done:
+ if(current_updates)
+ {
+ if(current_updates == updates_list)
+ {
+ if((QUEUEDUPDATES *)current_updates->entry.next != current_updates)
+ updates_list = (QUEUEDUPDATES *)current_updates->entry.next;
+ else
+ updates_list = NULL;
+ }
+ list_remove(¤t_updates->entry);
+ LIST_FOR_EACH(ptr, ¤t_updates->resources_list->entry)
+ {
+ current_resource = LIST_ENTRY(ptr, QUEUEDRESOURCE, entry);
+ free_queuedresource(current_resource);
+ }
+ free_queuedupdates(current_updates);
+ }
+ return ret;
}
/***********************************************************************
- * UpdateResourceA (KERNEL32.@)
+ * EndUpdateResourceA (KERNEL32.@)
*/
-BOOL WINAPI UpdateResourceA(
- HANDLE hUpdate,
- LPCSTR lpType,
- LPCSTR lpName,
- WORD wLanguage,
- LPVOID lpData,
- DWORD cbData)
-{
- FIXME(": stub\n");
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+BOOL WINAPI EndUpdateResourceA( HANDLE hUpdate, BOOL fDiscard )
+{
+ return EndUpdateResourceW(hUpdate, fDiscard);
}
/***********************************************************************
* UpdateResourceW (KERNEL32.@)
*/
-BOOL WINAPI UpdateResourceW(
- HANDLE hUpdate,
- LPCWSTR lpType,
- LPCWSTR lpName,
- WORD wLanguage,
- LPVOID lpData,
- DWORD cbData)
-{
- FIXME(": stub\n");
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+BOOL WINAPI UpdateResourceW( HANDLE hUpdate, LPCWSTR lpType, LPCWSTR lpName,
+ WORD wLanguage, LPVOID lpData, DWORD cbData)
+{
+ BOOL ret = FALSE;
+ struct list *ptr;
+ QUEUEDUPDATES *current_updates = NULL;
+ BOOL found = FALSE;
+ QUEUEDRESOURCE *current_resource = NULL;
+
+ TRACE("%p %s %s %08x %p %ld\n",hUpdate,debugstr_w(lpType),debugstr_w(lpName),wLanguage,lpData,cbData);
+
+ LIST_FOR_EACH(ptr, &updates_list->entry)
+ {
+ current_updates = LIST_ENTRY(ptr, QUEUEDUPDATES, entry);
+ if(current_updates->handle == hUpdate)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ if(!found)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ 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->lpData = lpData;
+ current_resource->cbData = cbData;
+ ret = TRUE;
+
+ if(!current_updates->resources_list)
+ {
+ current_updates->resources_list = current_resource;
+ list_init(¤t_updates->resources_list->entry);
+ }
+ else
+ list_add_after(¤t_updates->resources_list->entry, ¤t_resource->entry);
+
+done:
+ if(!ret && current_resource)
+ free_queuedresource(current_resource);
+ return ret;
+}
+
+
+/***********************************************************************
+ * UpdateResourceA (KERNEL32.@)
+ */
+BOOL WINAPI UpdateResourceA( HANDLE hUpdate, LPCSTR lpType, LPCSTR lpName,
+ WORD wLanguage, LPVOID lpData, DWORD cbData)
+{
+ BOOL ret;
+ UNICODE_STRING TypeW;
+ UNICODE_STRING NameW;
+ if(!HIWORD(lpType))
+ TypeW.Buffer = (LPWSTR)lpType;
+ else
+ RtlCreateUnicodeStringFromAsciiz(&TypeW, lpType);
+ if(!HIWORD(lpName))
+ NameW.Buffer = (LPWSTR)lpName;
+ else
+ RtlCreateUnicodeStringFromAsciiz(&NameW, lpName);
+ ret = UpdateResourceW(hUpdate, TypeW.Buffer, NameW.Buffer, wLanguage, lpData, cbData);
+ if(HIWORD(lpType)) RtlFreeUnicodeString(&TypeW);
+ if(HIWORD(lpName)) RtlFreeUnicodeString(&NameW);
+ return ret;
}
More information about the wine-patches
mailing list