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

Last change on this file since 6502 was 5472, checked in by sandervl, 24 years ago

compile fix

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