Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeninfo.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
1.7.6.1
|