[VERSION] Sync with Wine Staging 1.9.4. CORE-10912
[reactos.git] / reactos / dll / win32 / version / version.c
index ffb8ba6..43f5c18 100644 (file)
@@ -84,9 +84,9 @@ static const IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( const IMAGE_RESOURCE_DI
     while (min <= max)
     {
         pos = (min + max) / 2;
-        if (entry[pos].u1.Id == id)
+        if (entry[pos].u.Id == id)
             return (const IMAGE_RESOURCE_DIRECTORY *)((const char *)root + entry[pos].u2.s2.OffsetToDirectory);
-        if (entry[pos].u1.Id > id) max = pos - 1;
+        if (entry[pos].u.Id > id) max = pos - 1;
         else min = pos + 1;
     }
     return NULL;
@@ -109,6 +109,46 @@ static const IMAGE_RESOURCE_DIRECTORY *find_entry_default( const IMAGE_RESOURCE_
 }
 
 
+/**********************************************************************
+ *  push_language
+ *
+ * push a language onto the list of languages to try
+ */
+static inline int push_language( WORD *list, int pos, WORD lang )
+{
+    int i;
+    for (i = 0; i < pos; i++) if (list[i] == lang) return pos;
+    list[pos++] = lang;
+    return pos;
+}
+
+
+/**********************************************************************
+ *  find_entry_language
+ */
+static const IMAGE_RESOURCE_DIRECTORY *find_entry_language( const IMAGE_RESOURCE_DIRECTORY *dir,
+                                                            const void *root )
+{
+    const IMAGE_RESOURCE_DIRECTORY *ret;
+    WORD list[9];
+    int i, pos = 0;
+
+    /* cf. LdrFindResource_U */
+    pos = push_language( list, pos, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
+    pos = push_language( list, pos, LANGIDFROMLCID( NtCurrentTeb()->CurrentLocale ) );
+    pos = push_language( list, pos, GetUserDefaultLangID() );
+    pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(GetUserDefaultLangID()), SUBLANG_NEUTRAL ));
+    pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(GetUserDefaultLangID()), SUBLANG_DEFAULT ));
+    pos = push_language( list, pos, GetSystemDefaultLangID() );
+    pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(GetSystemDefaultLangID()), SUBLANG_NEUTRAL ));
+    pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(GetSystemDefaultLangID()), SUBLANG_DEFAULT ));
+    pos = push_language( list, pos, MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT ) );
+
+    for (i = 0; i < pos; i++) if ((ret = find_entry_by_id( dir, list[i], root ))) return ret;
+    return find_entry_default( dir, root );
+}
+
+
 /***********************************************************************
  *           read_xx_header         [internal]
  */
@@ -160,7 +200,7 @@ static BOOL find_ne_resource( HFILE lzfd, DWORD *resLen, DWORD *resOff )
 
     /* Read in NE header */
     nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
-    if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
+    if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
 
     resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
     if ( !resTabSize )
@@ -235,7 +275,7 @@ static BOOL find_pe_resource( HFILE lzfd, DWORD *resLen, DWORD *resOff )
     /* Read in PE header */
     pehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
     len = LZRead( lzfd, (LPSTR)&pehd, sizeof(pehd) );
-    if (len < sizeof(pehd.nt32.FileHeader)) return 0;
+    if (len < sizeof(pehd.nt32.FileHeader)) return FALSE;
     if (len < sizeof(pehd)) memset( (char *)&pehd + len, 0, sizeof(pehd) - len );
 
     switch (pehd.nt32.OptionalHeader.Magic)
@@ -247,7 +287,7 @@ static BOOL find_pe_resource( HFILE lzfd, DWORD *resLen, DWORD *resOff )
         resDataDir = pehd.nt64.OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_RESOURCE;
         break;
     default:
-        return 0;
+        return FALSE;
     }
 
     if ( !resDataDir->Size )
@@ -316,7 +356,7 @@ static BOOL find_pe_resource( HFILE lzfd, DWORD *resLen, DWORD *resOff )
         TRACE("No resid entry found\n" );
         goto done;
     }
-    resPtr = find_entry_default( resPtr, resDir );
+    resPtr = find_entry_language( resPtr, resDir );
     if ( !resPtr )
     {
         TRACE("No default language entry found\n" );
@@ -527,7 +567,7 @@ typedef struct
 {
     WORD  wLength;
     WORD  wValueLength;
-    WORD  wType;
+    WORD  wType; /* 1:Text, 0:Binary */
     WCHAR szKey[1];
 #if 0   /* variable length structure */
     /* DWORD aligned */
@@ -566,12 +606,35 @@ typedef struct
  *           GetFileVersionInfoSizeW         [VERSION.@]
  */
 DWORD WINAPI GetFileVersionInfoSizeW( LPCWSTR filename, LPDWORD handle )
+{
+    return GetFileVersionInfoSizeExW( 0, filename, handle );
+}
+
+/***********************************************************************
+ *           GetFileVersionInfoSizeA         [VERSION.@]
+ */
+DWORD WINAPI GetFileVersionInfoSizeA( LPCSTR filename, LPDWORD handle )
+{
+    return GetFileVersionInfoSizeExA( 0, filename, handle );
+}
+
+/******************************************************************************
+ *           GetFileVersionInfoSizeExW       [VERSION.@]
+ */
+DWORD WINAPI GetFileVersionInfoSizeExW( DWORD flags, LPCWSTR filename, LPDWORD handle )
 {
     DWORD len, offset, magic = 1;
     HFILE lzfd;
     HMODULE hModule;
     OFSTRUCT ofs;
 
+    if (flags)
+    {
+        FIXME("stub: %x %s %p\n", flags, wine_dbgstr_w(filename), handle);
+        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+        return 0;
+    }
+
     TRACE("(%s,%p)\n", debugstr_w(filename), handle );
 
     if (handle) *handle = 0;
@@ -596,7 +659,7 @@ DWORD WINAPI GetFileVersionInfoSizeW( LPCWSTR filename, LPDWORD handle )
     if ((magic == 1) && (hModule = LoadLibraryExW( filename, 0, LOAD_LIBRARY_AS_DATAFILE )))
     {
         HRSRC hRsrc = FindResourceW( hModule, MAKEINTRESOURCEW(VS_VERSION_INFO),
-                                     MAKEINTRESOURCEW(VS_FILE_INFO) );
+                                     (LPWSTR)VS_FILE_INFO );
         if (hRsrc)
         {
             magic = IMAGE_NT_SIGNATURE;
@@ -636,10 +699,10 @@ DWORD WINAPI GetFileVersionInfoSizeW( LPCWSTR filename, LPDWORD handle )
     }
 }
 
-/***********************************************************************
- *           GetFileVersionInfoSizeA         [VERSION.@]
+/******************************************************************************
+ *           GetFileVersionInfoSizeExA       [VERSION.@]
  */
-DWORD WINAPI GetFileVersionInfoSizeA( LPCSTR filename, LPDWORD handle )
+DWORD WINAPI GetFileVersionInfoSizeExA( DWORD flags, LPCSTR filename, LPDWORD handle )
 {
     UNICODE_STRING filenameW;
     DWORD retval;
@@ -651,7 +714,7 @@ DWORD WINAPI GetFileVersionInfoSizeA( LPCSTR filename, LPDWORD handle )
     else
         filenameW.Buffer = NULL;
 
-    retval = GetFileVersionInfoSizeW(filenameW.Buffer, handle);
+    retval = GetFileVersionInfoSizeExW(0, filenameW.Buffer, handle);
 
     RtlFreeUnicodeString(&filenameW);
 
@@ -659,10 +722,9 @@ DWORD WINAPI GetFileVersionInfoSizeA( LPCSTR filename, LPDWORD handle )
 }
 
 /***********************************************************************
- *           GetFileVersionInfoW             [VERSION.@]
+ *           GetFileVersionInfoExW           [VERSION.@]
  */
-BOOL WINAPI GetFileVersionInfoW( LPCWSTR filename, DWORD handle,
-                                    DWORD datasize, LPVOID data )
+BOOL WINAPI GetFileVersionInfoExW( DWORD flags, LPCWSTR filename, DWORD handle, DWORD datasize, LPVOID data )
 {
     static const char signature[4] = "FE2X";
     DWORD len, offset, magic = 1;
@@ -671,6 +733,13 @@ BOOL WINAPI GetFileVersionInfoW( LPCWSTR filename, DWORD handle,
     HMODULE hModule;
     VS_VERSION_INFO_STRUCT32* vvis = data;
 
+    if (flags)
+    {
+        FIXME("stub: %x %s %u %u %p\n", flags, wine_dbgstr_w(filename), handle, datasize, data);
+        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+        return 0;
+    }
+
     TRACE("(%s,%d,size=%d,data=%p)\n",
                 debugstr_w(filename), handle, datasize, data );
 
@@ -693,7 +762,7 @@ BOOL WINAPI GetFileVersionInfoW( LPCWSTR filename, DWORD handle,
     if ((magic == 1) && (hModule = LoadLibraryExW( filename, 0, LOAD_LIBRARY_AS_DATAFILE )))
     {
         HRSRC hRsrc = FindResourceW( hModule, MAKEINTRESOURCEW(VS_VERSION_INFO),
-                                     MAKEINTRESOURCEW(VS_FILE_INFO) );
+                                     (LPWSTR)VS_FILE_INFO );
         if (hRsrc)
         {
             HGLOBAL hMem = LoadResource( hModule, hRsrc );
@@ -734,10 +803,9 @@ BOOL WINAPI GetFileVersionInfoW( LPCWSTR filename, DWORD handle,
 }
 
 /***********************************************************************
- *           GetFileVersionInfoA             [VERSION.@]
+ *           GetFileVersionInfoExA           [VERSION.@]
  */
-BOOL WINAPI GetFileVersionInfoA( LPCSTR filename, DWORD handle,
-                                    DWORD datasize, LPVOID data )
+BOOL WINAPI GetFileVersionInfoExA( DWORD flags, LPCSTR filename, DWORD handle, DWORD datasize, LPVOID data )
 {
     UNICODE_STRING filenameW;
     BOOL retval;
@@ -750,13 +818,29 @@ BOOL WINAPI GetFileVersionInfoA( LPCSTR filename, DWORD handle,
     else
         filenameW.Buffer = NULL;
 
-    retval = GetFileVersionInfoW(filenameW.Buffer, handle, datasize, data);
+    retval = GetFileVersionInfoExW(flags, filenameW.Buffer, handle, datasize, data);
 
     RtlFreeUnicodeString(&filenameW);
 
     return retval;
 }
 
+/***********************************************************************
+ *           GetFileVersionInfoW             [VERSION.@]
+ */
+BOOL WINAPI GetFileVersionInfoW( LPCWSTR filename, DWORD handle, DWORD datasize, LPVOID data )
+{
+    return GetFileVersionInfoExW(0, filename, handle, datasize, data);
+}
+
+/***********************************************************************
+ *           GetFileVersionInfoA             [VERSION.@]
+ */
+BOOL WINAPI GetFileVersionInfoA( LPCSTR filename, DWORD handle, DWORD datasize, LPVOID data )
+{
+    return GetFileVersionInfoExA(0, filename, handle, datasize, data);
+}
+
 /***********************************************************************
  *           VersionInfo16_FindChild             [internal]
  */
@@ -847,7 +931,7 @@ static BOOL VersionInfo16_QueryValue( const VS_VERSION_INFO_STRUCT16 *info, LPCS
  *    Gets a value from a 32-bit PE resource
  */
 static BOOL VersionInfo32_QueryValue( const VS_VERSION_INFO_STRUCT32 *info, LPCWSTR lpSubBlock,
-                               LPVOID *lplpBuffer, UINT *puLen )
+                                      LPVOID *lplpBuffer, UINT *puLen, BOOL *pbText )
 {
     TRACE("lpSubBlock : (%s)\n", debugstr_w(lpSubBlock));
 
@@ -883,6 +967,8 @@ static BOOL VersionInfo32_QueryValue( const VS_VERSION_INFO_STRUCT32 *info, LPCW
     *lplpBuffer = VersionInfo32_Value( info );
     if (puLen)
         *puLen = info->wValueLength;
+    if (pbText)
+        *pbText = info->wType;
 
     return TRUE;
 }
@@ -894,7 +980,6 @@ BOOL WINAPI VerQueryValueA( LPCVOID pBlock, LPCSTR lpSubBlock,
                                LPVOID *lplpBuffer, PUINT puLen )
 {
     static const char rootA[] = "\\";
-    static const char varfileinfoA[] = "\\VarFileInfo\\Translation";
     const VS_VERSION_INFO_STRUCT16 *info = pBlock;
 
     TRACE("(%p,%s,%p,%p)\n",
@@ -908,7 +993,7 @@ BOOL WINAPI VerQueryValueA( LPCVOID pBlock, LPCSTR lpSubBlock,
 
     if ( !VersionInfoIs16( info ) )
     {
-        BOOL ret;
+        BOOL ret, isText;
         INT len;
         LPWSTR lpSubBlockW;
 
@@ -920,11 +1005,11 @@ BOOL WINAPI VerQueryValueA( LPCVOID pBlock, LPCSTR lpSubBlock,
 
         MultiByteToWideChar(CP_ACP, 0, lpSubBlock, -1, lpSubBlockW, len);
 
-        ret = VersionInfo32_QueryValue(pBlock, lpSubBlockW, lplpBuffer, puLen);
+        ret = VersionInfo32_QueryValue(pBlock, lpSubBlockW, lplpBuffer, puLen, &isText);
 
         HeapFree(GetProcessHeap(), 0, lpSubBlockW);
 
-        if (ret && strcasecmp( lpSubBlock, rootA ) && strcasecmp( lpSubBlock, varfileinfoA ))
+        if (ret && isText)
         {
             /* Set lpBuffer so it points to the 'empty' area where we store
              * the converted strings
@@ -935,7 +1020,7 @@ BOOL WINAPI VerQueryValueA( LPCVOID pBlock, LPCSTR lpSubBlock,
             len = WideCharToMultiByte(CP_ACP, 0, *lplpBuffer, -1,
                                       lpBufferA + pos, info->wLength - pos, NULL, NULL);
             *lplpBuffer = lpBufferA + pos;
-            *puLen = len;
+            if (puLen) *puLen = len;
         }
         return ret;
     }
@@ -995,12 +1080,12 @@ BOOL WINAPI VerQueryValueW( LPCVOID pBlock, LPCWSTR lpSubBlock,
             len = MultiByteToWideChar(CP_ACP, 0, *lplpBuffer, -1,
                                       lpBufferW + pos, max/sizeof(WCHAR) - pos );
             *lplpBuffer = lpBufferW + pos;
-            *puLen = len;
+            if (puLen) *puLen = len;
         }
         return ret;
     }
 
-    return VersionInfo32_QueryValue(info, lpSubBlock, lplpBuffer, puLen);
+    return VersionInfo32_QueryValue(info, lpSubBlock, lplpBuffer, puLen, NULL);
 }
 
 
@@ -1114,7 +1199,6 @@ DWORD WINAPI VerFindFileA(
 
     GetSystemDirectoryA(systemDir, sizeof(systemDir));
     curDir = "";
-    destDir = "";
 
     if(flags & VFFF_ISSHAREDFILE)
     {
@@ -1211,7 +1295,6 @@ DWORD WINAPI VerFindFileW( DWORD flags,LPCWSTR lpszFilename,LPCWSTR lpszWinDir,
 
     GetSystemDirectoryW(systemDir, sizeof(systemDir)/sizeof(WCHAR));
     curDir = &emptyW;
-    destDir = &emptyW;
 
     if(flags & VFFF_ISSHAREDFILE)
     {
@@ -1287,7 +1370,7 @@ _fetch_versioninfo(LPSTR fn,VS_FIXEDFILEINFO **vffi) {
     alloclen = 1000;
     buf=HeapAlloc(GetProcessHeap(), 0, alloclen);
     if(buf == NULL) {
-        WARN("Memory exausted while fetching version info!\n");
+        WARN("Memory exhausted while fetching version info!\n");
         return NULL;
     }
     while (1) {
@@ -1301,7 +1384,7 @@ _fetch_versioninfo(LPSTR fn,VS_FIXEDFILEINFO **vffi) {
            HeapFree(GetProcessHeap(), 0, buf);
            buf = HeapAlloc(GetProcessHeap(), 0, alloclen);
             if(buf == NULL) {
-               WARN("Memory exausted while fetching version info!\n");
+               WARN("Memory exhausted while fetching version info!\n");
                return NULL;
             }
        } else {