ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

info.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of VERSION.DLL - Version Info access
00003  *
00004  * Copyright 1996,1997 Marcus Meissner
00005  * Copyright 1997 David Cuthbert
00006  * Copyright 1999 Ulrich Weigand
00007  * Copyright 2005 Paul Vriens
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00022  *
00023  */
00024 
00025 #include <stdarg.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 
00029 #include "windef.h"
00030 #include "winbase.h"
00031 #include "winver.h"
00032 #include "winuser.h"
00033 #include "winternl.h"
00034 #include "lzexpand.h"
00035 #include "wine/unicode.h"
00036 #include "winerror.h"
00037 #include "wine/debug.h"
00038 
00039 WINE_DEFAULT_DEBUG_CHANNEL(ver);
00040 
00041 extern DWORD find_version_resource( HFILE lzfd, DWORD *reslen, DWORD *offset );
00042 
00043 /******************************************************************************
00044  *
00045  *   This function will print via standard TRACE, debug info regarding
00046  *   the file info structure vffi.
00047  *      15-Feb-1998 Dimitrie Paun (dimi@cs.toronto.edu)
00048  *      Added this function to clean up the code.
00049  *
00050  *****************************************************************************/
00051 static void print_vffi_debug(const VS_FIXEDFILEINFO *vffi)
00052 {
00053     BOOL    versioned_printer = FALSE;
00054 
00055     if((vffi->dwFileType == VFT_DLL) || (vffi->dwFileType == VFT_DRV))
00056     {
00057         if(vffi->dwFileSubtype == VFT2_DRV_VERSIONED_PRINTER)
00058             /* this is documented for newer w2k Drivers and up */
00059             versioned_printer = TRUE;
00060         else if( (vffi->dwFileSubtype == VFT2_DRV_PRINTER) &&
00061                  (vffi->dwFileVersionMS != vffi->dwProductVersionMS) &&
00062                  (vffi->dwFileVersionMS > 0) &&
00063                  (vffi->dwFileVersionMS <= 3) )
00064             /* found this on NT 3.51, NT4.0 and old w2k Drivers */
00065             versioned_printer = TRUE;
00066     }
00067 
00068     TRACE("structversion=%u.%u, ",
00069             HIWORD(vffi->dwStrucVersion),LOWORD(vffi->dwStrucVersion));
00070     if(versioned_printer)
00071     {
00072         WORD mode = LOWORD(vffi->dwFileVersionMS);
00073         WORD ver_rev = HIWORD(vffi->dwFileVersionLS);
00074         TRACE("fileversion=%u.%u.%u.%u (%s.major.minor.release), ",
00075             (vffi->dwFileVersionMS),
00076             HIBYTE(ver_rev), LOBYTE(ver_rev), LOWORD(vffi->dwFileVersionLS),
00077             (mode == 3) ? "Usermode" : ((mode <= 2) ? "Kernelmode" : "?") );
00078     }
00079     else
00080     {
00081         TRACE("fileversion=%u.%u.%u.%u, ",
00082             HIWORD(vffi->dwFileVersionMS),LOWORD(vffi->dwFileVersionMS),
00083             HIWORD(vffi->dwFileVersionLS),LOWORD(vffi->dwFileVersionLS));
00084     }
00085     TRACE("productversion=%u.%u.%u.%u\n",
00086           HIWORD(vffi->dwProductVersionMS),LOWORD(vffi->dwProductVersionMS),
00087           HIWORD(vffi->dwProductVersionLS),LOWORD(vffi->dwProductVersionLS));
00088 
00089     TRACE("flagmask=0x%x, flags=0x%x %s%s%s%s%s%s\n",
00090           vffi->dwFileFlagsMask, vffi->dwFileFlags,
00091           (vffi->dwFileFlags & VS_FF_DEBUG) ? "DEBUG," : "",
00092           (vffi->dwFileFlags & VS_FF_PRERELEASE) ? "PRERELEASE," : "",
00093           (vffi->dwFileFlags & VS_FF_PATCHED) ? "PATCHED," : "",
00094           (vffi->dwFileFlags & VS_FF_PRIVATEBUILD) ? "PRIVATEBUILD," : "",
00095           (vffi->dwFileFlags & VS_FF_INFOINFERRED) ? "INFOINFERRED," : "",
00096           (vffi->dwFileFlags & VS_FF_SPECIALBUILD) ? "SPECIALBUILD," : "");
00097 
00098     TRACE("(");
00099 
00100     TRACE("OS=0x%x.0x%x ", HIWORD(vffi->dwFileOS), LOWORD(vffi->dwFileOS));
00101 
00102     switch (vffi->dwFileOS&0xFFFF0000)
00103     {
00104     case VOS_DOS:TRACE("DOS,");break;
00105     case VOS_OS216:TRACE("OS/2-16,");break;
00106     case VOS_OS232:TRACE("OS/2-32,");break;
00107     case VOS_NT:TRACE("NT,");break;
00108     case VOS_UNKNOWN:
00109     default:
00110         TRACE("UNKNOWN(0x%x),",vffi->dwFileOS&0xFFFF0000);break;
00111     }
00112 
00113     switch (LOWORD(vffi->dwFileOS))
00114     {
00115     case VOS__BASE:TRACE("BASE");break;
00116     case VOS__WINDOWS16:TRACE("WIN16");break;
00117     case VOS__WINDOWS32:TRACE("WIN32");break;
00118     case VOS__PM16:TRACE("PM16");break;
00119     case VOS__PM32:TRACE("PM32");break;
00120     default:
00121         TRACE("UNKNOWN(0x%x)",LOWORD(vffi->dwFileOS));break;
00122     }
00123 
00124     TRACE(")\n");
00125 
00126     switch (vffi->dwFileType)
00127     {
00128     case VFT_APP:TRACE("filetype=APP");break;
00129     case VFT_DLL:
00130         TRACE("filetype=DLL");
00131         if(vffi->dwFileSubtype != 0)
00132         {
00133             if(versioned_printer) /* NT3.x/NT4.0 or old w2k Driver  */
00134                 TRACE(",PRINTER");
00135             TRACE(" (subtype=0x%x)", vffi->dwFileSubtype);
00136         }
00137         break;
00138     case VFT_DRV:
00139         TRACE("filetype=DRV,");
00140         switch(vffi->dwFileSubtype)
00141         {
00142         case VFT2_DRV_PRINTER:TRACE("PRINTER");break;
00143         case VFT2_DRV_KEYBOARD:TRACE("KEYBOARD");break;
00144         case VFT2_DRV_LANGUAGE:TRACE("LANGUAGE");break;
00145         case VFT2_DRV_DISPLAY:TRACE("DISPLAY");break;
00146         case VFT2_DRV_MOUSE:TRACE("MOUSE");break;
00147         case VFT2_DRV_NETWORK:TRACE("NETWORK");break;
00148         case VFT2_DRV_SYSTEM:TRACE("SYSTEM");break;
00149         case VFT2_DRV_INSTALLABLE:TRACE("INSTALLABLE");break;
00150         case VFT2_DRV_SOUND:TRACE("SOUND");break;
00151         case VFT2_DRV_COMM:TRACE("COMM");break;
00152         case VFT2_DRV_INPUTMETHOD:TRACE("INPUTMETHOD");break;
00153         case VFT2_DRV_VERSIONED_PRINTER:TRACE("VERSIONED_PRINTER");break;
00154         case VFT2_UNKNOWN:
00155         default:
00156             TRACE("UNKNOWN(0x%x)",vffi->dwFileSubtype);break;
00157         }
00158         break;
00159     case VFT_FONT:
00160         TRACE("filetype=FONT,");
00161         switch (vffi->dwFileSubtype)
00162         {
00163         case VFT2_FONT_RASTER:TRACE("RASTER");break;
00164         case VFT2_FONT_VECTOR:TRACE("VECTOR");break;
00165         case VFT2_FONT_TRUETYPE:TRACE("TRUETYPE");break;
00166         default:TRACE("UNKNOWN(0x%x)",vffi->dwFileSubtype);break;
00167         }
00168         break;
00169     case VFT_VXD:TRACE("filetype=VXD");break;
00170     case VFT_STATIC_LIB:TRACE("filetype=STATIC_LIB");break;
00171     case VFT_UNKNOWN:
00172     default:
00173         TRACE("filetype=Unknown(0x%x)",vffi->dwFileType);break;
00174     }
00175 
00176     TRACE("\n");
00177     TRACE("filedate=0x%x.0x%x\n",vffi->dwFileDateMS,vffi->dwFileDateLS);
00178 }
00179 
00180 /***********************************************************************
00181  * Version Info Structure
00182  */
00183 
00184 typedef struct
00185 {
00186     WORD  wLength;
00187     WORD  wValueLength;
00188     CHAR  szKey[1];
00189 #if 0   /* variable length structure */
00190     /* DWORD aligned */
00191     BYTE  Value[];
00192     /* DWORD aligned */
00193     VS_VERSION_INFO_STRUCT16 Children[];
00194 #endif
00195 } VS_VERSION_INFO_STRUCT16;
00196 
00197 typedef struct
00198 {
00199     WORD  wLength;
00200     WORD  wValueLength;
00201     WORD  wType;
00202     WCHAR szKey[1];
00203 #if 0   /* variable length structure */
00204     /* DWORD aligned */
00205     BYTE  Value[];
00206     /* DWORD aligned */
00207     VS_VERSION_INFO_STRUCT32 Children[];
00208 #endif
00209 } VS_VERSION_INFO_STRUCT32;
00210 
00211 #define VersionInfoIs16( ver ) \
00212     ( ((const VS_VERSION_INFO_STRUCT16 *)ver)->szKey[0] >= ' ' )
00213 
00214 #define DWORD_ALIGN( base, ptr ) \
00215     ( (LPBYTE)(base) + ((((LPBYTE)(ptr) - (LPBYTE)(base)) + 3) & ~3) )
00216 
00217 #define VersionInfo16_Value( ver )  \
00218     DWORD_ALIGN( (ver), (ver)->szKey + strlen((ver)->szKey) + 1 )
00219 #define VersionInfo32_Value( ver )  \
00220     DWORD_ALIGN( (ver), (ver)->szKey + strlenW((ver)->szKey) + 1 )
00221 
00222 #define VersionInfo16_Children( ver )  \
00223     (const VS_VERSION_INFO_STRUCT16 *)( VersionInfo16_Value( ver ) + \
00224                            ( ( (ver)->wValueLength + 3 ) & ~3 ) )
00225 #define VersionInfo32_Children( ver )  \
00226     (const VS_VERSION_INFO_STRUCT32 *)( VersionInfo32_Value( ver ) + \
00227                            ( ( (ver)->wValueLength * \
00228                                ((ver)->wType? 2 : 1) + 3 ) & ~3 ) )
00229 
00230 #define VersionInfo16_Next( ver ) \
00231     (VS_VERSION_INFO_STRUCT16 *)( (LPBYTE)ver + (((ver)->wLength + 3) & ~3) )
00232 #define VersionInfo32_Next( ver ) \
00233     (VS_VERSION_INFO_STRUCT32 *)( (LPBYTE)ver + (((ver)->wLength + 3) & ~3) )
00234 
00235 
00236 /***********************************************************************
00237  *           GetFileVersionInfoSizeW         [VERSION.@]
00238  */
00239 DWORD WINAPI GetFileVersionInfoSizeW( LPCWSTR filename, LPDWORD handle )
00240 {
00241     DWORD len, offset, magic = 1;
00242     HFILE lzfd;
00243     HMODULE hModule;
00244     OFSTRUCT ofs;
00245 
00246     TRACE("(%s,%p)\n", debugstr_w(filename), handle );
00247 
00248     if (handle) *handle = 0;
00249 
00250     if (!filename)
00251     {
00252         SetLastError(ERROR_INVALID_PARAMETER);
00253         return 0;
00254     }
00255     if (!*filename)
00256     {
00257         SetLastError(ERROR_BAD_PATHNAME);
00258         return 0;
00259     }
00260 
00261     if ((lzfd = LZOpenFileW( (LPWSTR)filename, &ofs, OF_READ )) != HFILE_ERROR)
00262     {
00263         magic = find_version_resource( lzfd, &len, &offset );
00264         LZClose( lzfd );
00265     }
00266 
00267     if ((magic == 1) && (hModule = LoadLibraryExW( filename, 0, LOAD_LIBRARY_AS_DATAFILE )))
00268     {
00269         HRSRC hRsrc = FindResourceW( hModule, MAKEINTRESOURCEW(VS_VERSION_INFO),
00270                                      MAKEINTRESOURCEW(VS_FILE_INFO) );
00271         if (hRsrc)
00272         {
00273             magic = IMAGE_NT_SIGNATURE;
00274             len = SizeofResource( hModule, hRsrc );
00275         }
00276         FreeLibrary( hModule );
00277     }
00278 
00279     switch (magic)
00280     {
00281     case IMAGE_OS2_SIGNATURE:
00282         /* We have a 16bit resource.
00283          *
00284          * XP/W2K/W2K3 uses a buffer which is more than the actual needed space:
00285          *
00286          * (info->wLength - sizeof(VS_FIXEDFILEINFO)) * 4
00287          *
00288          * This extra buffer is used for ANSI to Unicode conversions in W-Calls.
00289          * info->wLength should be the same as len. Currently it isn't but that
00290          * doesn't seem to be a problem (len is bigger than info->wLength).
00291          */
00292         SetLastError(0);
00293         return (len - sizeof(VS_FIXEDFILEINFO)) * 4;
00294 
00295     case IMAGE_NT_SIGNATURE:
00296         /* We have a 32bit resource.
00297          *
00298          * XP/W2K/W2K3 uses a buffer which is 2 times the actual needed space + 4 bytes "FE2X"
00299          * This extra buffer is used for Unicode to ANSI conversions in A-Calls
00300          */
00301         SetLastError(0);
00302         return (len * 2) + 4;
00303 
00304     default:
00305         SetLastError( lzfd == HFILE_ERROR ? ofs.nErrCode : ERROR_RESOURCE_DATA_NOT_FOUND );
00306         return 0;
00307     }
00308 }
00309 
00310 /***********************************************************************
00311  *           GetFileVersionInfoSizeA         [VERSION.@]
00312  */
00313 DWORD WINAPI GetFileVersionInfoSizeA( LPCSTR filename, LPDWORD handle )
00314 {
00315     UNICODE_STRING filenameW;
00316     DWORD retval;
00317 
00318     TRACE("(%s,%p)\n", debugstr_a(filename), handle );
00319 
00320     if(filename)
00321         RtlCreateUnicodeStringFromAsciiz(&filenameW, filename);
00322     else
00323         filenameW.Buffer = NULL;
00324 
00325     retval = GetFileVersionInfoSizeW(filenameW.Buffer, handle);
00326 
00327     RtlFreeUnicodeString(&filenameW);
00328 
00329     return retval;
00330 }
00331 
00332 /***********************************************************************
00333  *           GetFileVersionInfoW             [VERSION.@]
00334  */
00335 BOOL WINAPI GetFileVersionInfoW( LPCWSTR filename, DWORD handle,
00336                                     DWORD datasize, LPVOID data )
00337 {
00338     static const char signature[4] = "FE2X";
00339     DWORD len, offset, magic = 1;
00340     HFILE lzfd;
00341     OFSTRUCT ofs;
00342     HMODULE hModule;
00343     VS_VERSION_INFO_STRUCT32* vvis = data;
00344 
00345     TRACE("(%s,%d,size=%d,data=%p)\n",
00346                 debugstr_w(filename), handle, datasize, data );
00347 
00348     if (!data)
00349     {
00350         SetLastError(ERROR_INVALID_DATA);
00351         return FALSE;
00352     }
00353 
00354     if ((lzfd = LZOpenFileW( (LPWSTR)filename, &ofs, OF_READ )) != HFILE_ERROR)
00355     {
00356         if ((magic = find_version_resource( lzfd, &len, &offset )) > 1)
00357         {
00358             LZSeek( lzfd, offset, 0 /* SEEK_SET */ );
00359             len = LZRead( lzfd, data, min( len, datasize ) );
00360         }
00361         LZClose( lzfd );
00362     }
00363 
00364     if ((magic == 1) && (hModule = LoadLibraryExW( filename, 0, LOAD_LIBRARY_AS_DATAFILE )))
00365     {
00366         HRSRC hRsrc = FindResourceW( hModule, MAKEINTRESOURCEW(VS_VERSION_INFO),
00367                                      MAKEINTRESOURCEW(VS_FILE_INFO) );
00368         if (hRsrc)
00369         {
00370             HGLOBAL hMem = LoadResource( hModule, hRsrc );
00371             magic = IMAGE_NT_SIGNATURE;
00372             len = min( SizeofResource(hModule, hRsrc), datasize );
00373             memcpy( data, LockResource( hMem ), len );
00374             FreeResource( hMem );
00375         }
00376         FreeLibrary( hModule );
00377     }
00378 
00379     switch (magic)
00380     {
00381     case IMAGE_OS2_SIGNATURE:
00382         /* We have a 16bit resource. */
00383         if (TRACE_ON(ver))
00384             print_vffi_debug( (VS_FIXEDFILEINFO *)VersionInfo16_Value( (VS_VERSION_INFO_STRUCT16 *)data ));
00385         SetLastError(0);
00386         return TRUE;
00387 
00388     case IMAGE_NT_SIGNATURE:
00389         /* We have a 32bit resource.
00390          *
00391          * XP/W2K/W2K3 uses a buffer which is 2 times the actual needed space + 4 bytes "FE2X"
00392          * This extra buffer is used for Unicode to ANSI conversions in A-Calls
00393          */
00394         len = vvis->wLength + sizeof(signature);
00395         if (datasize >= len) memcpy( (char*)data + vvis->wLength, signature, sizeof(signature) );
00396         if (TRACE_ON(ver))
00397             print_vffi_debug( (VS_FIXEDFILEINFO *)VersionInfo32_Value( vvis ));
00398         SetLastError(0);
00399         return TRUE;
00400 
00401     default:
00402         SetLastError( lzfd == HFILE_ERROR ? ofs.nErrCode : ERROR_RESOURCE_DATA_NOT_FOUND );
00403         return FALSE;
00404     }
00405 }
00406 
00407 /***********************************************************************
00408  *           GetFileVersionInfoA             [VERSION.@]
00409  */
00410 BOOL WINAPI GetFileVersionInfoA( LPCSTR filename, DWORD handle,
00411                                     DWORD datasize, LPVOID data )
00412 {
00413     UNICODE_STRING filenameW;
00414     BOOL retval;
00415 
00416     TRACE("(%s,%d,size=%d,data=%p)\n",
00417                 debugstr_a(filename), handle, datasize, data );
00418 
00419     if(filename)
00420         RtlCreateUnicodeStringFromAsciiz(&filenameW, filename);
00421     else
00422         filenameW.Buffer = NULL;
00423 
00424     retval = GetFileVersionInfoW(filenameW.Buffer, handle, datasize, data);
00425 
00426     RtlFreeUnicodeString(&filenameW);
00427 
00428     return retval;
00429 }
00430 
00431 /***********************************************************************
00432  *           VersionInfo16_FindChild             [internal]
00433  */
00434 static const VS_VERSION_INFO_STRUCT16 *VersionInfo16_FindChild( const VS_VERSION_INFO_STRUCT16 *info,
00435                                             LPCSTR szKey, UINT cbKey )
00436 {
00437     const VS_VERSION_INFO_STRUCT16 *child = VersionInfo16_Children( info );
00438 
00439     while ((char *)child < (char *)info + info->wLength )
00440     {
00441         if (!strncasecmp( child->szKey, szKey, cbKey ) && !child->szKey[cbKey])
00442             return child;
00443 
00444     if (!(child->wLength)) return NULL;
00445         child = VersionInfo16_Next( child );
00446     }
00447 
00448     return NULL;
00449 }
00450 
00451 /***********************************************************************
00452  *           VersionInfo32_FindChild             [internal]
00453  */
00454 static const VS_VERSION_INFO_STRUCT32 *VersionInfo32_FindChild( const VS_VERSION_INFO_STRUCT32 *info,
00455                                             LPCWSTR szKey, UINT cbKey )
00456 {
00457     const VS_VERSION_INFO_STRUCT32 *child = VersionInfo32_Children( info );
00458 
00459     while ((char *)child < (char *)info + info->wLength )
00460     {
00461         if (!strncmpiW( child->szKey, szKey, cbKey ) && !child->szKey[cbKey])
00462             return child;
00463 
00464         if (!(child->wLength)) return NULL;
00465         child = VersionInfo32_Next( child );
00466     }
00467 
00468     return NULL;
00469 }
00470 
00471 /***********************************************************************
00472  *           VersionInfo16_QueryValue              [internal]
00473  *
00474  *    Gets a value from a 16-bit NE resource
00475  */
00476 static BOOL VersionInfo16_QueryValue( const VS_VERSION_INFO_STRUCT16 *info, LPCSTR lpSubBlock,
00477                                LPVOID *lplpBuffer, UINT *puLen )
00478 {
00479     while ( *lpSubBlock )
00480     {
00481         /* Find next path component */
00482         LPCSTR lpNextSlash;
00483         for ( lpNextSlash = lpSubBlock; *lpNextSlash; lpNextSlash++ )
00484             if ( *lpNextSlash == '\\' )
00485                 break;
00486 
00487         /* Skip empty components */
00488         if ( lpNextSlash == lpSubBlock )
00489         {
00490             lpSubBlock++;
00491             continue;
00492         }
00493 
00494         /* We have a non-empty component: search info for key */
00495         info = VersionInfo16_FindChild( info, lpSubBlock, lpNextSlash-lpSubBlock );
00496         if ( !info )
00497         {
00498             if (puLen) *puLen = 0 ;
00499             SetLastError( ERROR_RESOURCE_TYPE_NOT_FOUND );
00500             return FALSE;
00501         }
00502 
00503         /* Skip path component */
00504         lpSubBlock = lpNextSlash;
00505     }
00506 
00507     /* Return value */
00508     *lplpBuffer = VersionInfo16_Value( info );
00509     if (puLen)
00510         *puLen = info->wValueLength;
00511 
00512     return TRUE;
00513 }
00514 
00515 /***********************************************************************
00516  *           VersionInfo32_QueryValue              [internal]
00517  *
00518  *    Gets a value from a 32-bit PE resource
00519  */
00520 static BOOL VersionInfo32_QueryValue( const VS_VERSION_INFO_STRUCT32 *info, LPCWSTR lpSubBlock,
00521                                LPVOID *lplpBuffer, UINT *puLen )
00522 {
00523     TRACE("lpSubBlock : (%s)\n", debugstr_w(lpSubBlock));
00524 
00525     while ( *lpSubBlock )
00526     {
00527         /* Find next path component */
00528         LPCWSTR lpNextSlash;
00529         for ( lpNextSlash = lpSubBlock; *lpNextSlash; lpNextSlash++ )
00530             if ( *lpNextSlash == '\\' )
00531                 break;
00532 
00533         /* Skip empty components */
00534         if ( lpNextSlash == lpSubBlock )
00535         {
00536             lpSubBlock++;
00537             continue;
00538         }
00539 
00540         /* We have a non-empty component: search info for key */
00541         info = VersionInfo32_FindChild( info, lpSubBlock, lpNextSlash-lpSubBlock );
00542         if ( !info )
00543         {
00544             if (puLen) *puLen = 0 ;
00545             SetLastError( ERROR_RESOURCE_TYPE_NOT_FOUND );
00546             return FALSE;
00547         }
00548 
00549         /* Skip path component */
00550         lpSubBlock = lpNextSlash;
00551     }
00552 
00553     /* Return value */
00554     *lplpBuffer = VersionInfo32_Value( info );
00555     if (puLen)
00556         *puLen = info->wValueLength;
00557 
00558     return TRUE;
00559 }
00560 
00561 /***********************************************************************
00562  *           VerQueryValueA              [VERSION.@]
00563  */
00564 BOOL WINAPI VerQueryValueA( LPCVOID pBlock, LPCSTR lpSubBlock,
00565                                LPVOID *lplpBuffer, PUINT puLen )
00566 {
00567     static const char rootA[] = "\\";
00568     static const char varfileinfoA[] = "\\VarFileInfo\\Translation";
00569     const VS_VERSION_INFO_STRUCT16 *info = pBlock;
00570 
00571     TRACE("(%p,%s,%p,%p)\n",
00572                 pBlock, debugstr_a(lpSubBlock), lplpBuffer, puLen );
00573 
00574      if (!pBlock)
00575         return FALSE;
00576 
00577     if (lpSubBlock == NULL || lpSubBlock[0] == '\0')
00578         lpSubBlock = rootA;
00579 
00580     if ( !VersionInfoIs16( info ) )
00581     {
00582         BOOL ret;
00583         INT len;
00584         LPWSTR lpSubBlockW;
00585 
00586         len  = MultiByteToWideChar(CP_ACP, 0, lpSubBlock, -1, NULL, 0);
00587         lpSubBlockW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
00588 
00589         if (!lpSubBlockW)
00590             return FALSE;
00591 
00592         MultiByteToWideChar(CP_ACP, 0, lpSubBlock, -1, lpSubBlockW, len);
00593 
00594         ret = VersionInfo32_QueryValue(pBlock, lpSubBlockW, lplpBuffer, puLen);
00595 
00596         HeapFree(GetProcessHeap(), 0, lpSubBlockW);
00597 
00598         if (ret && strcasecmp( lpSubBlock, rootA ) && strcasecmp( lpSubBlock, varfileinfoA ))
00599         {
00600             /* Set lpBuffer so it points to the 'empty' area where we store
00601              * the converted strings
00602              */
00603             LPSTR lpBufferA = (LPSTR)pBlock + info->wLength + 4;
00604             DWORD pos = (LPCSTR)*lplpBuffer - (LPCSTR)pBlock;
00605 
00606             len = WideCharToMultiByte(CP_ACP, 0, *lplpBuffer, -1,
00607                                       lpBufferA + pos, info->wLength - pos, NULL, NULL);
00608             *lplpBuffer = lpBufferA + pos;
00609             *puLen = len;
00610         }
00611         return ret;
00612     }
00613 
00614     return VersionInfo16_QueryValue(info, lpSubBlock, lplpBuffer, puLen);
00615 }
00616 
00617 /***********************************************************************
00618  *           VerQueryValueW              [VERSION.@]
00619  */
00620 BOOL WINAPI VerQueryValueW( LPCVOID pBlock, LPCWSTR lpSubBlock,
00621                                LPVOID *lplpBuffer, PUINT puLen )
00622 {
00623     static const WCHAR nullW[] = { 0 };
00624     static const WCHAR rootW[] = { '\\', 0 };
00625     static const WCHAR varfileinfoW[] = { '\\','V','a','r','F','i','l','e','I','n','f','o',
00626                                           '\\','T','r','a','n','s','l','a','t','i','o','n', 0 };
00627 
00628     const VS_VERSION_INFO_STRUCT32 *info = pBlock;
00629 
00630     TRACE("(%p,%s,%p,%p)\n",
00631                 pBlock, debugstr_w(lpSubBlock), lplpBuffer, puLen );
00632 
00633     if (!pBlock)
00634         return FALSE;
00635 
00636     if (lpSubBlock == NULL || lpSubBlock[0] == nullW[0])
00637         lpSubBlock = rootW;
00638 
00639     if ( VersionInfoIs16( info ) )
00640     {
00641         BOOL ret;
00642         int len;
00643         LPSTR lpSubBlockA;
00644 
00645         len = WideCharToMultiByte(CP_ACP, 0, lpSubBlock, -1, NULL, 0, NULL, NULL);
00646         lpSubBlockA = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char));
00647 
00648         if (!lpSubBlockA)
00649             return FALSE;
00650 
00651         WideCharToMultiByte(CP_ACP, 0, lpSubBlock, -1, lpSubBlockA, len, NULL, NULL);
00652 
00653         ret = VersionInfo16_QueryValue(pBlock, lpSubBlockA, lplpBuffer, puLen);
00654 
00655         HeapFree(GetProcessHeap(), 0, lpSubBlockA);
00656 
00657         if (ret && strcmpiW( lpSubBlock, rootW ) && strcmpiW( lpSubBlock, varfileinfoW ))
00658         {
00659             /* Set lpBuffer so it points to the 'empty' area where we store
00660              * the converted strings
00661              */
00662             LPWSTR lpBufferW = (LPWSTR)((LPSTR)pBlock + info->wLength);
00663             DWORD pos = (LPCSTR)*lplpBuffer - (LPCSTR)pBlock;
00664             DWORD max = (info->wLength - sizeof(VS_FIXEDFILEINFO)) * 4 - info->wLength;
00665 
00666             len = MultiByteToWideChar(CP_ACP, 0, *lplpBuffer, -1,
00667                                       lpBufferW + pos, max/sizeof(WCHAR) - pos );
00668             *lplpBuffer = lpBufferW + pos;
00669             *puLen = len;
00670         }
00671         return ret;
00672     }
00673 
00674     return VersionInfo32_QueryValue(info, lpSubBlock, lplpBuffer, puLen);
00675 }

Generated on Sat May 26 2012 04:23:12 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.