source: trunk/src/version/info.c@ 2347

Last change on this file since 2347 was 2347, checked in by sandervl, 26 years ago

VerQueryValue32A and merged with latest Wine sources (991212)

File size: 16.7 KB
Line 
1/* $Id: info.c,v 1.1 2000-01-06 20:10:07 sandervl Exp $ */
2/*
3 * Implementation of VERSION.DLL - Version Info access (Wine 991212)
4 *
5 * Copyright 1996,1997 Marcus Meissner
6 * Copyright 1997 David Cuthbert
7 * Copyright 1999 Ulrich Weigand
8 */
9
10#include <stdlib.h>
11#include <string.h>
12
13#include "winreg.h"
14#include "winver.h"
15#include "wine/winestring.h"
16#include "winerror.h"
17#include "heap.h"
18#include "crtdll.h"
19#include "debugtools.h"
20
21DEFAULT_DEBUG_CHANNEL(ver)
22
23
24/******************************************************************************
25 *
26 * This function will print via dprintf[_]ver to stddeb debug info regarding
27 * the file info structure vffi.
28 * 15-Feb-1998 Dimitrie Paun (dimi@cs.toronto.edu)
29 * Added this function to clean up the code.
30 *
31 *****************************************************************************/
32static void print_vffi_debug(VS_FIXEDFILEINFO *vffi)
33{
34 TRACE(" structversion=%u.%u, fileversion=%u.%u.%u.%u, productversion=%u.%u.%u.%u, flagmask=0x%lx, flags=%s%s%s%s%s%s\n",
35 HIWORD(vffi->dwStrucVersion),LOWORD(vffi->dwStrucVersion),
36 HIWORD(vffi->dwFileVersionMS),LOWORD(vffi->dwFileVersionMS),
37 HIWORD(vffi->dwFileVersionLS),LOWORD(vffi->dwFileVersionLS),
38 HIWORD(vffi->dwProductVersionMS),LOWORD(vffi->dwProductVersionMS),
39 HIWORD(vffi->dwProductVersionLS),LOWORD(vffi->dwProductVersionLS),
40 vffi->dwFileFlagsMask,
41 (vffi->dwFileFlags & VS_FF_DEBUG) ? "DEBUG," : "",
42 (vffi->dwFileFlags & VS_FF_PRERELEASE) ? "PRERELEASE," : "",
43 (vffi->dwFileFlags & VS_FF_PATCHED) ? "PATCHED," : "",
44 (vffi->dwFileFlags & VS_FF_PRIVATEBUILD) ? "PRIVATEBUILD," : "",
45 (vffi->dwFileFlags & VS_FF_INFOINFERRED) ? "INFOINFERRED," : "",
46 (vffi->dwFileFlags & VS_FF_SPECIALBUILD) ? "SPECIALBUILD," : ""
47 );
48
49 TRACE("(");
50 DPRINTF(" OS=0x%x.0x%x ",
51 HIWORD(vffi->dwFileOS),
52 LOWORD(vffi->dwFileOS)
53 );
54 switch (vffi->dwFileOS&0xFFFF0000) {
55 case VOS_DOS:DPRINTF("DOS,");break;
56 case VOS_OS216:DPRINTF("OS/2-16,");break;
57 case VOS_OS232:DPRINTF("OS/2-32,");break;
58 case VOS_NT:DPRINTF("NT,");break;
59 case VOS_UNKNOWN:
60 default:
61 DPRINTF("UNKNOWN(0x%lx),",vffi->dwFileOS&0xFFFF0000);break;
62 }
63 switch (LOWORD(vffi->dwFileOS)) {
64 case VOS__BASE:DPRINTF("BASE");break;
65 case VOS__WINDOWS16:DPRINTF("WIN16");break;
66 case VOS__WINDOWS32:DPRINTF("WIN32");break;
67 case VOS__PM16:DPRINTF("PM16");break;
68 case VOS__PM32:DPRINTF("PM32");break;
69 default:DPRINTF("UNKNOWN(0x%x)",LOWORD(vffi->dwFileOS));break;
70 }
71 DPRINTF(")\n");
72
73 switch (vffi->dwFileType) {
74 default:
75 case VFT_UNKNOWN:
76 TRACE("filetype=Unknown(0x%lx)",vffi->dwFileType);
77 break;
78 case VFT_APP:TRACE("filetype=APP,");break;
79 case VFT_DLL:TRACE("filetype=DLL,");break;
80 case VFT_DRV:
81 TRACE("filetype=DRV,");
82 switch(vffi->dwFileSubtype) {
83 default:
84 case VFT2_UNKNOWN:
85 DPRINTF("UNKNOWN(0x%lx)",vffi->dwFileSubtype);
86 break;
87 case VFT2_DRV_PRINTER:
88 DPRINTF("PRINTER");
89 break;
90 case VFT2_DRV_KEYBOARD:
91 DPRINTF("KEYBOARD");
92 break;
93 case VFT2_DRV_LANGUAGE:
94 DPRINTF("LANGUAGE");
95 break;
96 case VFT2_DRV_DISPLAY:
97 DPRINTF("DISPLAY");
98 break;
99 case VFT2_DRV_MOUSE:
100 DPRINTF("MOUSE");
101 break;
102 case VFT2_DRV_NETWORK:
103 DPRINTF("NETWORK");
104 break;
105 case VFT2_DRV_SYSTEM:
106 DPRINTF("SYSTEM");
107 break;
108 case VFT2_DRV_INSTALLABLE:
109 DPRINTF("INSTALLABLE");
110 break;
111 case VFT2_DRV_SOUND:
112 DPRINTF("SOUND");
113 break;
114 case VFT2_DRV_COMM:
115 DPRINTF("COMM");
116 break;
117 case VFT2_DRV_INPUTMETHOD:
118 DPRINTF("INPUTMETHOD");
119 break;
120 }
121 break;
122 case VFT_FONT:
123 TRACE("filetype=FONT.");
124 switch (vffi->dwFileSubtype) {
125 default:
126 DPRINTF("UNKNOWN(0x%lx)",vffi->dwFileSubtype);
127 break;
128 case VFT2_FONT_RASTER:DPRINTF("RASTER");break;
129 case VFT2_FONT_VECTOR:DPRINTF("VECTOR");break;
130 case VFT2_FONT_TRUETYPE:DPRINTF("TRUETYPE");break;
131 }
132 break;
133 case VFT_VXD:TRACE("filetype=VXD");break;
134 case VFT_STATIC_LIB:TRACE("filetype=STATIC_LIB");break;
135 }
136 DPRINTF("\n");
137 TRACE(" filedata=0x%lx.0x%lx\n",
138 vffi->dwFileDateMS,vffi->dwFileDateLS);
139}
140
141
142/***********************************************************************
143 * Version Info Structure
144 */
145
146typedef struct
147{
148 WORD wLength;
149 WORD wValueLength;
150 CHAR szKey[1];
151#if 0 /* variable length structure */
152 /* DWORD aligned */
153 BYTE Value[];
154 /* DWORD aligned */
155 VS_VERSION_INFO_STRUCT16 Children[];
156#endif
157} VS_VERSION_INFO_STRUCT16;
158
159typedef struct
160{
161 WORD wLength;
162 WORD wValueLength;
163 WORD bText;
164 WCHAR szKey[1];
165#if 0 /* variable length structure */
166 /* DWORD aligned */
167 BYTE Value[];
168 /* DWORD aligned */
169 VS_VERSION_INFO_STRUCT32 Children[];
170#endif
171} VS_VERSION_INFO_STRUCT32;
172
173#define VersionInfoIs16( ver ) \
174 ( ((VS_VERSION_INFO_STRUCT16 *)ver)->szKey[0] >= ' ' )
175
176#define DWORD_ALIGN( ptr ) ((LPBYTE)( (((DWORD)(ptr)) + 3) & ~3 ))
177
178#define VersionInfo16_Value( ver ) \
179 DWORD_ALIGN( (ver)->szKey + lstrlenA((ver)->szKey) + 1 )
180#define VersionInfo32_Value( ver ) \
181 DWORD_ALIGN( (ver)->szKey + lstrlenW((ver)->szKey) + 1 )
182
183#define VersionInfo16_Children( ver ) \
184 (VS_VERSION_INFO_STRUCT16 *)( VersionInfo16_Value( ver ) + \
185 ( ( (ver)->wValueLength + 3 ) & ~3 ) )
186#define VersionInfo32_Children( ver ) \
187 (VS_VERSION_INFO_STRUCT32 *)( VersionInfo32_Value( ver ) + \
188 ( ( (ver)->wValueLength * \
189 ((ver)->bText? 2 : 1) + 3 ) & ~3 ) )
190
191#define VersionInfo16_Next( ver ) \
192 (VS_VERSION_INFO_STRUCT16 *)( (LPBYTE)ver + (((ver)->wLength + 3) & ~3) )
193#define VersionInfo32_Next( ver ) \
194 (VS_VERSION_INFO_STRUCT32 *)( (LPBYTE)ver + (((ver)->wLength + 3) & ~3) )
195
196#ifndef __WIN32OS2__
197/***********************************************************************
198 * ConvertVersionInfo32To16 [internal]
199 */
200void ConvertVersionInfo32To16( VS_VERSION_INFO_STRUCT32 *info32,
201 VS_VERSION_INFO_STRUCT16 *info16 )
202{
203 /* Copy data onto local stack to prevent overwrites */
204 WORD wLength = info32->wLength;
205 WORD wValueLength = info32->wValueLength;
206 WORD bText = info32->bText;
207 LPBYTE lpValue = VersionInfo32_Value( info32 );
208 VS_VERSION_INFO_STRUCT32 *child32 = VersionInfo32_Children( info32 );
209 VS_VERSION_INFO_STRUCT16 *child16;
210
211 TRACE("Converting %p to %p\n", info32, info16 );
212 TRACE("wLength %d, wValueLength %d, bText %d, value %p, child %p\n",
213 wLength, wValueLength, bText, lpValue, child32 );
214
215 /* Convert key */
216 lstrcpyWtoA( info16->szKey, info32->szKey );
217
218 TRACE("Copied key from %p to %p: %s\n", info32->szKey, info16->szKey,
219 debugstr_a(info16->szKey) );
220
221 /* Convert value */
222 if ( wValueLength == 0 )
223 {
224 info16->wValueLength = 0;
225 TRACE("No value present\n" );
226 }
227 else if ( bText )
228 {
229 info16->wValueLength = lstrlenW( (LPCWSTR)lpValue ) + 1;
230 lstrcpyWtoA( VersionInfo16_Value( info16 ), (LPCWSTR)lpValue );
231
232 TRACE("Copied value from %p to %p: %s\n", lpValue,
233 VersionInfo16_Value( info16 ),
234 debugstr_a(VersionInfo16_Value( info16 )) );
235 }
236 else
237 {
238 info16->wValueLength = wValueLength;
239 memmove( VersionInfo16_Value( info16 ), lpValue, wValueLength );
240
241 TRACE("Copied value from %p to %p: %d bytes\n", lpValue,
242 VersionInfo16_Value( info16 ), wValueLength );
243 }
244
245 /* Convert children */
246 child16 = VersionInfo16_Children( info16 );
247 while ( (DWORD)child32 < (DWORD)info32 + wLength )
248 {
249 VS_VERSION_INFO_STRUCT32 *nextChild = VersionInfo32_Next( child32 );
250
251 ConvertVersionInfo32To16( child32, child16 );
252
253 child16 = VersionInfo16_Next( child16 );
254 child32 = nextChild;
255 }
256
257 /* Fixup length */
258 info16->wLength = (DWORD)child16 - (DWORD)info16;
259
260 TRACE("Finished, length is %d (%p - %p)\n",
261 info16->wLength, info16, child16 );
262}
263
264
265/***********************************************************************
266 * GetFileVersionInfoSize32A [VERSION.2]
267 */
268DWORD WINAPI GetFileVersionInfoSizeA( LPCSTR filename, LPDWORD handle )
269{
270 VS_FIXEDFILEINFO *vffi;
271 DWORD len, ret, offset;
272 BYTE buf[144];
273
274 TRACE("(%s,%p)\n", debugstr_a(filename), handle );
275
276 len = GetFileResourceSize( filename,
277 MAKEINTRESOURCEA(VS_FILE_INFO),
278 MAKEINTRESOURCEA(VS_VERSION_INFO),
279 &offset );
280 if (!len) return 0;
281
282 ret = GetFileResource( filename,
283 MAKEINTRESOURCEA(VS_FILE_INFO),
284 MAKEINTRESOURCEA(VS_VERSION_INFO),
285 offset, sizeof( buf ), buf );
286 if (!ret) return 0;
287
288 if ( handle ) *handle = offset;
289
290 if ( VersionInfoIs16( buf ) )
291 vffi = (VS_FIXEDFILEINFO *)VersionInfo16_Value( (VS_VERSION_INFO_STRUCT16 *)buf );
292 else
293 vffi = (VS_FIXEDFILEINFO *)VersionInfo32_Value( (VS_VERSION_INFO_STRUCT32 *)buf );
294
295 if ( vffi->dwSignature != VS_FFI_SIGNATURE )
296 {
297 WARN("vffi->dwSignature is 0x%08lx, but not 0x%08lx!\n",
298 vffi->dwSignature, VS_FFI_SIGNATURE );
299 return 0;
300 }
301
302 if ( ((VS_VERSION_INFO_STRUCT16 *)buf)->wLength < len )
303 len = ((VS_VERSION_INFO_STRUCT16 *)buf)->wLength;
304
305 if ( TRACE_ON(ver) )
306 print_vffi_debug( vffi );
307
308 return len;
309}
310
311/***********************************************************************
312 * GetFileVersionInfoSize32W [VERSION.3]
313 */
314DWORD WINAPI GetFileVersionInfoSizeW( LPCWSTR filename, LPDWORD handle )
315{
316 LPSTR fn = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
317 DWORD ret = GetFileVersionInfoSizeA( fn, handle );
318 HeapFree( GetProcessHeap(), 0, fn );
319 return ret;
320}
321
322/***********************************************************************
323 * GetFileVersionInfo32A [VERSION.1]
324 */
325DWORD WINAPI GetFileVersionInfoA( LPCSTR filename, DWORD handle,
326 DWORD datasize, LPVOID data )
327{
328 TRACE("(%s,%ld,size=%ld,data=%p)\n",
329 debugstr_a(filename), handle, datasize, data );
330
331 if ( !GetFileResource( filename, MAKEINTRESOURCEA(VS_FILE_INFO),
332 MAKEINTRESOURCEA(VS_VERSION_INFO),
333 handle, datasize, data ) )
334 return FALSE;
335
336 if ( datasize >= sizeof(VS_VERSION_INFO_STRUCT16)
337 && datasize >= ((VS_VERSION_INFO_STRUCT16 *)data)->wLength
338 && !VersionInfoIs16( data ) )
339 {
340 /* convert resource from PE format to NE format */
341 ConvertVersionInfo32To16( (VS_VERSION_INFO_STRUCT32 *)data,
342 (VS_VERSION_INFO_STRUCT16 *)data );
343 }
344
345 return TRUE;
346}
347
348/***********************************************************************
349 * GetFileVersionInfo32W [VERSION.4]
350 */
351DWORD WINAPI GetFileVersionInfoW( LPCWSTR filename, DWORD handle,
352 DWORD datasize, LPVOID data )
353{
354 LPSTR fn = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
355 DWORD retv = TRUE;
356
357 TRACE("(%s,%ld,size=%ld,data=%p)\n",
358 debugstr_a(fn), handle, datasize, data );
359
360 if ( !GetFileResource( fn, MAKEINTRESOURCEA(VS_FILE_INFO),
361 MAKEINTRESOURCEA(VS_VERSION_INFO),
362 handle, datasize, data ) )
363 retv = FALSE;
364
365 else if ( datasize >= sizeof(VS_VERSION_INFO_STRUCT16)
366 && datasize >= ((VS_VERSION_INFO_STRUCT16 *)data)->wLength
367 && VersionInfoIs16( data ) )
368 {
369 ERR("Cannot access NE resource in %s\n", debugstr_a(fn) );
370 retv = FALSE;
371 }
372
373 HeapFree( GetProcessHeap(), 0, fn );
374 return retv;
375}
376#endif //!__WIN32OS2__
377
378/***********************************************************************
379 * VersionInfo16_FindChild [internal]
380 */
381VS_VERSION_INFO_STRUCT16 *VersionInfo16_FindChild( VS_VERSION_INFO_STRUCT16 *info,
382 LPCSTR szKey, UINT cbKey )
383{
384 VS_VERSION_INFO_STRUCT16 *child = VersionInfo16_Children( info );
385
386 while ( (DWORD)child < (DWORD)info + info->wLength )
387 {
388 if ( !lstrncmpiA( child->szKey, szKey, cbKey ) )
389 return child;
390
391 if (!(child->wLength)) return NULL;
392 child = VersionInfo16_Next( child );
393 }
394
395 return NULL;
396}
397
398/***********************************************************************
399 * VersionInfo32_FindChild [internal]
400 */
401VS_VERSION_INFO_STRUCT32 *VersionInfo32_FindChild( VS_VERSION_INFO_STRUCT32 *info,
402 LPCWSTR szKey, UINT cbKey )
403{
404 VS_VERSION_INFO_STRUCT32 *child = VersionInfo32_Children( info );
405
406 while ( (DWORD)child < (DWORD)info + info->wLength )
407 {
408 if ( !CRTDLL__wcsnicmp( child->szKey, szKey, cbKey ) )
409 return child;
410
411 child = VersionInfo32_Next( child );
412 }
413
414 return NULL;
415}
416
417/***********************************************************************
418 * VerQueryValue32W [VERSION.13]
419 */
420DWORD VerQueryValue32W( LPVOID pBlock, LPCWSTR lpSubBlock,
421 LPVOID *lplpBuffer, UINT *puLen, BOOL *bText)
422{
423 VS_VERSION_INFO_STRUCT32 *info = (VS_VERSION_INFO_STRUCT32 *)pBlock;
424 if ( VersionInfoIs16( info ) )
425 {
426 ERR("called on NE resource!\n" );
427 return FALSE;
428 }
429
430#if defined(__WIN32OS2__)
431 dprintf(("VerQueryValueW %x %x %x %x", pBlock, lpSubBlock, lplpBuffer, puLen));
432#else
433 TRACE("(%p,%s,%p,%p)\n",
434 pBlock, debugstr_w(lpSubBlock), lplpBuffer, puLen );
435#endif
436
437 while ( *lpSubBlock )
438 {
439 /* Find next path component */
440 LPCWSTR lpNextSlash;
441 for ( lpNextSlash = lpSubBlock; *lpNextSlash; lpNextSlash++ )
442 if ( *lpNextSlash == '\\' )
443 break;
444
445 /* Skip empty components */
446 if ( lpNextSlash == lpSubBlock )
447 {
448 lpSubBlock++;
449 continue;
450 }
451
452 /* We have a non-empty component: search info for key */
453 info = VersionInfo32_FindChild( info, lpSubBlock, lpNextSlash-lpSubBlock );
454 if ( !info ) return FALSE;
455
456 /* Skip path component */
457 lpSubBlock = lpNextSlash;
458 }
459
460 /* Return value */
461 *lplpBuffer = VersionInfo32_Value( info );
462 *puLen = info->wValueLength;
463 *bText = info->bText;
464
465#if defined(__WIN32OS2__)
466 dprintf(("VerQueryValueW successful"));
467#endif
468 return TRUE;
469}
470
471
472#if defined(__WIN32OS2__)
473DWORD VerQueryValueW( LPVOID pBlock, LPCWSTR lpSubBlock,
474 LPVOID *lplpBuffer, UINT *puLen)
475{
476 BOOL bText;
477
478 return VerQueryValue32W(pBlock, lpSubBlock, lplpBuffer, puLen, &bText);
479}
480#endif
481
482/***********************************************************************
483 * VerQueryValue32A [VERSION.12]
484 */
485DWORD WINAPI VerQueryValueA( LPVOID pBlock, LPCSTR lpSubBlock,
486 LPVOID *lplpBuffer, UINT *puLen )
487{
488 VS_VERSION_INFO_STRUCT16 *info = (VS_VERSION_INFO_STRUCT16 *)pBlock;
489 if ( !VersionInfoIs16( info ) )
490 {
491#ifdef __WIN32OS2__
492 // this is a quick hack, not much tested
493 WCHAR *ustring = (WCHAR *)malloc(strlen((char *)lpSubBlock)*2+2);
494 LPVOID ubuffer;
495 char *abuffer;
496 UINT len = *puLen * 2;
497 BOOL rc, bText;
498
499 dprintf(("VERSION: called on PE unicode resource!\n" ));
500
501 AsciiToUnicode((char *)lpSubBlock, ustring);
502 rc = VerQueryValue32W( pBlock, (LPWSTR)ustring, &ubuffer, &len, &bText);
503 if(rc == 0) {
504 free(ustring);
505 return 0;
506 }
507 if(!bText) {
508 *lplpBuffer = ubuffer;
509 }
510 else
511 {
512 *lplpBuffer = malloc(len+1); // FIXME: no free, memory leak!!
513 UnicodeToAsciiN((WCHAR *)ubuffer, (char *)*lplpBuffer, len);
514 }
515 *puLen = len;
516 free(ustring);
517 return rc;
518#else
519 ERR("called on PE resource!\n" );
520 return FALSE;
521#endif //__WIN32OS2__
522 }
523
524 TRACE("(%p,%s,%p,%p)\n",
525 pBlock, debugstr_a(lpSubBlock), lplpBuffer, puLen );
526
527 while ( *lpSubBlock )
528 {
529 /* Find next path component */
530 LPCSTR lpNextSlash;
531 for ( lpNextSlash = lpSubBlock; *lpNextSlash; lpNextSlash++ )
532 if ( *lpNextSlash == '\\' )
533 break;
534
535 /* Skip empty components */
536 if ( lpNextSlash == lpSubBlock )
537 {
538 lpSubBlock++;
539 continue;
540 }
541
542 /* We have a non-empty component: search info for key */
543 info = VersionInfo16_FindChild( info, lpSubBlock, lpNextSlash-lpSubBlock );
544 if ( !info ) return FALSE;
545
546 /* Skip path component */
547 lpSubBlock = lpNextSlash;
548 }
549
550 /* Return value */
551 *lplpBuffer = VersionInfo16_Value( info );
552 *puLen = info->wValueLength;
553
554 return TRUE;
555}
Note: See TracBrowser for help on using the repository browser.