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

Last change on this file since 9676 was 9676, checked in by sandervl, 23 years ago

Don't import wscnicmp from CRTDLL

File size: 16.8 KB
Line 
1/* $Id: info.c,v 1.4 2003-01-15 10:42:34 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#ifdef __WIN32OS2__
411 if ( !lstrncmpiW( child->szKey, szKey, cbKey ) )
412#else
413 if ( !CRTDLL_wcsnicmp( child->szKey, szKey, cbKey ) )
414#endif
415 return child;
416
417 child = VersionInfo32_Next( child );
418 }
419
420 return NULL;
421}
422
423/***********************************************************************
424 * VerQueryValue32W [VERSION.13]
425 */
426DWORD VerQueryValue32W( LPVOID pBlock, LPCWSTR lpSubBlock,
427 LPVOID *lplpBuffer, UINT *puLen, BOOL *bText)
428{
429 VS_VERSION_INFO_STRUCT32 *info = (VS_VERSION_INFO_STRUCT32 *)pBlock;
430 if ( VersionInfoIs16( info ) )
431 {
432 ERR("called on NE resource!\n" );
433 return FALSE;
434 }
435
436#if defined(__WIN32OS2__)
437 dprintf(("VerQueryValueW %x %x %x %x", pBlock, lpSubBlock, lplpBuffer, puLen));
438#else
439 TRACE("(%p,%s,%p,%p)\n",
440 pBlock, debugstr_w(lpSubBlock), lplpBuffer, puLen );
441#endif
442
443 while ( *lpSubBlock )
444 {
445 /* Find next path component */
446 LPCWSTR lpNextSlash;
447 for ( lpNextSlash = lpSubBlock; *lpNextSlash; lpNextSlash++ )
448 if ( *lpNextSlash == '\\' )
449 break;
450
451 /* Skip empty components */
452 if ( lpNextSlash == lpSubBlock )
453 {
454 lpSubBlock++;
455 continue;
456 }
457
458 /* We have a non-empty component: search info for key */
459 info = VersionInfo32_FindChild( info, lpSubBlock, lpNextSlash-lpSubBlock );
460 if ( !info ) return FALSE;
461
462 /* Skip path component */
463 lpSubBlock = lpNextSlash;
464 }
465
466 /* Return value */
467 *lplpBuffer = VersionInfo32_Value( info );
468 *puLen = info->wValueLength;
469 *bText = info->bText;
470
471#if defined(__WIN32OS2__)
472 dprintf(("VerQueryValueW successful"));
473#endif
474 return TRUE;
475}
476
477
478#if defined(__WIN32OS2__)
479DWORD VerQueryValueW( LPVOID pBlock, LPCWSTR lpSubBlock,
480 LPVOID *lplpBuffer, UINT *puLen)
481{
482 BOOL bText;
483
484 return VerQueryValue32W(pBlock, lpSubBlock, lplpBuffer, puLen, &bText);
485}
486#endif
487
488/***********************************************************************
489 * VerQueryValue32A [VERSION.12]
490 */
491DWORD WINAPI VerQueryValueA( LPVOID pBlock, LPCSTR lpSubBlock,
492 LPVOID *lplpBuffer, UINT *puLen )
493{
494 VS_VERSION_INFO_STRUCT16 *info = (VS_VERSION_INFO_STRUCT16 *)pBlock;
495 if ( !VersionInfoIs16( info ) )
496 {
497#ifdef __WIN32OS2__
498 // this is a quick hack, not much tested
499 WCHAR *ustring = (WCHAR *)malloc(strlen((char *)lpSubBlock)*2+2);
500 LPVOID ubuffer;
501 char *abuffer;
502 UINT len = *puLen * 2;
503 BOOL rc, bText;
504
505 dprintf(("VERSION: called on PE unicode resource!\n" ));
506
507 AsciiToUnicode((char *)lpSubBlock, ustring);
508 rc = VerQueryValue32W( pBlock, (LPWSTR)ustring, &ubuffer, &len, &bText);
509 if(rc == 0) {
510 free(ustring);
511 return 0;
512 }
513 if(!bText) {
514 *lplpBuffer = ubuffer;
515 }
516 else
517 {
518 *lplpBuffer = malloc(len+1); // FIXME: no free, memory leak!!
519 UnicodeToAsciiN((WCHAR *)ubuffer, (char *)*lplpBuffer, len);
520 }
521 *puLen = len;
522 free(ustring);
523 return rc;
524#else
525 ERR("called on PE resource!\n" );
526 return FALSE;
527#endif //__WIN32OS2__
528 }
529
530 TRACE("(%p,%s,%p,%p)\n",
531 pBlock, debugstr_a(lpSubBlock), lplpBuffer, puLen );
532
533 while ( *lpSubBlock )
534 {
535 /* Find next path component */
536 LPCSTR lpNextSlash;
537 for ( lpNextSlash = lpSubBlock; *lpNextSlash; lpNextSlash++ )
538 if ( *lpNextSlash == '\\' )
539 break;
540
541 /* Skip empty components */
542 if ( lpNextSlash == lpSubBlock )
543 {
544 lpSubBlock++;
545 continue;
546 }
547
548 /* We have a non-empty component: search info for key */
549 info = VersionInfo16_FindChild( info, lpSubBlock, lpNextSlash-lpSubBlock );
550 if ( !info ) return FALSE;
551
552 /* Skip path component */
553 lpSubBlock = lpNextSlash;
554 }
555
556 /* Return value */
557 *lplpBuffer = VersionInfo16_Value( info );
558 *puLen = info->wValueLength;
559
560 return TRUE;
561}
Note: See TracBrowser for help on using the repository browser.