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, &current_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(&current_updates->entry);
+        LIST_FOR_EACH(ptr, &current_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(&current_updates->resources_list->entry);
+    }
+    else
+        list_add_after(&current_updates->resources_list->entry, &current_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