2 * Implementation of VER.DLL
4 * Copyright 1996 Marcus Meissner
24 #define LZREAD(what) \
25 if (sizeof(*what)!=LZRead32(lzfd,what,sizeof(*what))) return 0;
26 #define LZTELL(lzfd) LZSeek(lzfd, 0, SEEK_CUR);
29 read_ne_header(HFILE lzfd
,struct ne_header_s
*nehd
) {
30 struct mz_header_s mzh
;
32 LZSeek(lzfd
,0,SEEK_SET
);
33 if (sizeof(mzh
)!=LZRead32(lzfd
,&mzh
,sizeof(mzh
)))
35 if (mzh
.mz_magic
!=MZ_SIGNATURE
)
37 LZSeek(lzfd
,mzh
.ne_offset
,SEEK_SET
);
39 if (nehd
->ne_magic
== NE_SIGNATURE
) {
40 LZSeek(lzfd
,mzh
.ne_offset
,SEEK_SET
);
43 /* must handle PE files too. Later. */
50 HFILE lzfd
,struct ne_header_s
*nehd
,SEGPTR
typeid,SEGPTR resid
,
51 BYTE
**resdata
,int *reslen
,DWORD
*off
59 nehdoffset
= LZTELL(lzfd
);
60 LZSeek(lzfd
,nehd
->resource_tab_offset
,SEEK_CUR
);
62 dprintf_ver(stddeb
,"shiftcount is %d\n",shiftcount
);
63 dprintf_ver(stddeb
,"reading resource typeinfo dir.\n");
65 if (!HIWORD(typeid)) typeid = (SEGPTR
)(LOWORD(typeid) | 0x8000);
66 if (!HIWORD(resid
)) resid
= (SEGPTR
)(LOWORD(resid
) | 0x8000);
73 dprintf_ver(stddeb
," ti.typeid =%04x,count=%d\n",ti
.type_id
,ti
.count
);
75 if (!HIWORD(typeid)) {
76 if ((ti
.type_id
&0x8000)&&(typeid!=ti
.type_id
))
79 if (ti
.type_id
& 0x8000) {
86 whereleft
= LZTELL(lzfd
);
89 nehdoffset
+nehd
->resource_tab_offset
+ti
.type_id
,
94 if (len
!=LZRead32(lzfd
,str
,len
))
96 dprintf_ver(stddeb
,"read %s to compare it with %s\n",
97 str
,(char*)PTR_SEG_TO_LIN(typeid)
99 if (lstrcmpi32A(str
,(char*)PTR_SEG_TO_LIN(typeid)))
102 LZSeek(lzfd
,whereleft
,SEEK_SET
);
106 LZSeek(lzfd
,ti
.count
*sizeof(ni
),SEEK_CUR
);
109 for (i
=0;i
<ti
.count
;i
++) {
114 dprintf_ver(stddeb
," ni.id=%4x,offset=%d,length=%d\n",
115 ni
.id
,ni
.offset
,ni
.length
118 if (!HIWORD(resid
)) {
122 if (!(ni
.id
& 0x8000)) {
127 whereleft
= LZTELL(lzfd
);
130 nehdoffset
+nehd
->resource_tab_offset
+ni
.id
,
135 if (len
!=LZRead32(lzfd
,str
,len
))
137 dprintf_ver(stddeb
,"read %s to compare it with %s\n",
138 str
,(char*)PTR_SEG_TO_LIN(typeid)
140 if (!lstrcmpi32A(str
,(char*)PTR_SEG_TO_LIN(typeid)))
143 LZSeek(lzfd
,whereleft
,SEEK_SET
);
148 LZSeek(lzfd
,((int)ni
.offset
<<shiftcount
),SEEK_SET
);
149 *off
= (int)ni
.offset
<<shiftcount
;
150 len
= ni
.length
<<shiftcount
;
151 rdata
=(WORD
*)xmalloc(len
);
152 if (len
!=LZRead32(lzfd
,rdata
,len
)) {
156 dprintf_ver(stddeb
,"resource found.\n");
157 *resdata
= (BYTE
*)rdata
;
164 /* GetFileResourceSize [VER.2] */
166 GetFileResourceSize(LPCSTR filename
,SEGPTR restype
,SEGPTR resid
,LPDWORD off
) {
171 struct ne_header_s nehd
;
173 dprintf_ver(stddeb
,"GetFileResourceSize(%s,%lx,%lx,%p)\n",
174 filename
,(LONG
)restype
,(LONG
)resid
,off
176 lzfd
=LZOpenFile16(filename
,&ofs
,OF_READ
);
179 if (!read_ne_header(lzfd
,&nehd
)) {
183 if (!find_ne_resource(lzfd
,&nehd
,restype
,resid
,&resdata
,&reslen
,off
)) {
192 /* GetFileResource [VER.3] */
194 GetFileResource(LPCSTR filename
,SEGPTR restype
,SEGPTR resid
,
195 DWORD off
,DWORD datalen
,LPVOID data
201 struct ne_header_s nehd
;
202 dprintf_ver(stddeb
,"GetFileResource(%s,%lx,%lx,%ld,%ld,%p)\n",
203 filename
,(LONG
)restype
,(LONG
)resid
,off
,datalen
,data
206 lzfd
=LZOpenFile16(filename
,&ofs
,OF_READ
);
210 if (!read_ne_header(lzfd
,&nehd
)) {
214 if (!find_ne_resource(lzfd
,&nehd
,restype
,resid
,&resdata
,&reslen
,&off
)) {
220 LZSeek(lzfd
,off
,SEEK_SET
);
223 LZRead32(lzfd
,data
,reslen
);
228 /* GetFileVersionInfoSize [VER.6] */
230 GetFileVersionInfoSize16(LPCSTR filename
,LPDWORD handle
) {
233 VS_FIXEDFILEINFO
*vffi
;
235 dprintf_ver(stddeb
,"GetFileVersionInfoSize16(%s,%p)\n",filename
,handle
);
236 len
=GetFileResourceSize(filename
,VS_FILE_INFO
,VS_VERSION_INFO
,handle
);
240 filename
,VS_FILE_INFO
,VS_VERSION_INFO
,*handle
,sizeof(buf
),buf
245 vffi
=(VS_FIXEDFILEINFO
*)(buf
+0x14);
246 if (vffi
->dwSignature
!= VS_FFI_SIGNATURE
)
248 if (*(WORD
*)buf
< len
)
250 dprintf_ver(stddeb
,"->strucver=%ld.%ld,filever=%ld.%ld,productver=%ld.%ld,flagmask=%lx,flags=%lx,OS=",
251 (vffi
->dwStrucVersion
>>16),vffi
->dwStrucVersion
&0xFFFF,
252 vffi
->dwFileVersionMS
,vffi
->dwFileVersionLS
,
253 vffi
->dwProductVersionMS
,vffi
->dwProductVersionLS
,
254 vffi
->dwFileFlagsMask
,vffi
->dwFileFlags
256 switch (vffi
->dwFileOS
&0xFFFF0000) {
257 case VOS_DOS
:dprintf_ver(stddeb
,"DOS,");break;
258 case VOS_OS216
:dprintf_ver(stddeb
,"OS/2-16,");break;
259 case VOS_OS232
:dprintf_ver(stddeb
,"OS/2-32,");break;
260 case VOS_NT
:dprintf_ver(stddeb
,"NT,");break;
263 dprintf_ver(stddeb
,"UNKNOWN(%ld),",vffi
->dwFileOS
&0xFFFF0000);break;
265 switch (vffi
->dwFileOS
& 0xFFFF) {
266 case VOS__BASE
:dprintf_ver(stddeb
,"BASE");break;
267 case VOS__WINDOWS16
:dprintf_ver(stddeb
,"WIN16");break;
268 case VOS__WINDOWS32
:dprintf_ver(stddeb
,"WIN32");break;
269 case VOS__PM16
:dprintf_ver(stddeb
,"PM16");break;
270 case VOS__PM32
:dprintf_ver(stddeb
,"PM32");break;
271 default:dprintf_ver(stddeb
,"UNKNOWN(%ld)",vffi
->dwFileOS
&0xFFFF);break;
273 switch (vffi
->dwFileType
) {
276 dprintf_ver(stddeb
,"filetype=Unknown(%ld)",vffi
->dwFileType
);
278 case VFT_APP
:dprintf_ver(stddeb
,"filetype=APP");break;
279 case VFT_DLL
:dprintf_ver(stddeb
,"filetype=DLL");break;
281 dprintf_ver(stddeb
,"filetype=DRV,");
282 switch(vffi
->dwFileSubtype
) {
285 dprintf_ver(stddeb
,"UNKNOWN(%ld)",vffi
->dwFileSubtype
);
287 case VFT2_DRV_PRINTER
:
288 dprintf_ver(stddeb
,"PRINTER");
290 case VFT2_DRV_KEYBOARD
:
291 dprintf_ver(stddeb
,"KEYBOARD");
293 case VFT2_DRV_LANGUAGE
:
294 dprintf_ver(stddeb
,"LANGUAGE");
296 case VFT2_DRV_DISPLAY
:
297 dprintf_ver(stddeb
,"DISPLAY");
300 dprintf_ver(stddeb
,"MOUSE");
302 case VFT2_DRV_NETWORK
:
303 dprintf_ver(stddeb
,"NETWORK");
305 case VFT2_DRV_SYSTEM
:
306 dprintf_ver(stddeb
,"SYSTEM");
308 case VFT2_DRV_INSTALLABLE
:
309 dprintf_ver(stddeb
,"INSTALLABLE");
312 dprintf_ver(stddeb
,"SOUND");
315 dprintf_ver(stddeb
,"COMM");
317 case VFT2_DRV_INPUTMETHOD
:
318 dprintf_ver(stddeb
,"INPUTMETHOD");
323 dprintf_ver(stddeb
,"filetype=FONT.");
324 switch (vffi
->dwFileSubtype
) {
326 dprintf_ver(stddeb
,"UNKNOWN(%ld)",vffi
->dwFileSubtype
);
328 case VFT2_FONT_RASTER
:dprintf_ver(stddeb
,"RASTER");break;
329 case VFT2_FONT_VECTOR
:dprintf_ver(stddeb
,"VECTOR");break;
330 case VFT2_FONT_TRUETYPE
:dprintf_ver(stddeb
,"TRUETYPE");break;
333 case VFT_VXD
:dprintf_ver(stddeb
,"filetype=VXD");break;
334 case VFT_STATIC_LIB
:dprintf_ver(stddeb
,"filetype=STATIC_LIB");break;
336 dprintf_ver(stddeb
,"filedata=%lx.%lx\n",vffi
->dwFileDateMS
,vffi
->dwFileDateLS
);
340 /* GetFileVersionInfoSize32A [VERSION.1] */
342 GetFileVersionInfoSize32A(LPCSTR filename
,LPDWORD handle
) {
343 dprintf_ver(stddeb
,"GetFileVersionInfoSize32A(%s,%p)\n",filename
,handle
);
344 return GetFileVersionInfoSize16(filename
,handle
);
347 /* GetFileVersionInfoSize32W [VERSION.2] */
348 DWORD
GetFileVersionInfoSize32W( LPCWSTR filename
, LPDWORD handle
)
350 LPSTR xfn
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
351 DWORD ret
= GetFileVersionInfoSize16( xfn
, handle
);
352 HeapFree( GetProcessHeap(), 0, xfn
);
356 /* GetFileVersionInfo [VER.7] */
358 GetFileVersionInfo16(LPCSTR filename
,DWORD handle
,DWORD datasize
,LPVOID data
) {
359 dprintf_ver(stddeb
,"GetFileVersionInfo16(%s,%ld,%ld,%p)\n->",
360 filename
,handle
,datasize
,data
362 return GetFileResource(
363 filename
,VS_FILE_INFO
,VS_VERSION_INFO
,handle
,datasize
,data
367 /* GetFileVersionInfoA [VERSION.0] */
369 GetFileVersionInfo32A(LPCSTR filename
,DWORD handle
,DWORD datasize
,LPVOID data
) {
370 return GetFileVersionInfo16(filename
,handle
,datasize
,data
);
373 /* GetFileVersionInfoW [VERSION.3] */
374 DWORD
GetFileVersionInfo32W( LPCWSTR filename
, DWORD handle
, DWORD datasize
,
377 LPSTR fn
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
378 DWORD ret
= GetFileVersionInfo16( fn
, handle
, datasize
, data
);
379 HeapFree( GetProcessHeap(), 0, fn
);
383 /* VerFindFile [VER.8] */
386 UINT16 flags
,LPCSTR filename
,LPCSTR windir
,LPCSTR appdir
,
387 LPSTR curdir
,UINT16
*curdirlen
,LPSTR destdir
,UINT16
*destdirlen
389 dprintf_ver(stddeb
,"VerFindFile(%x,%s,%s,%s,%p,%d,%p,%d)\n",
390 flags
,filename
,windir
,appdir
,curdir
,*curdirlen
,destdir
,*destdirlen
392 strcpy(curdir
,"Z:\\ROOT\\.WINE\\");/*FIXME*/
393 *curdirlen
=strlen(curdir
);
394 strcpy(destdir
,"Z:\\ROOT\\.WINE\\");/*FIXME*/
395 *destdirlen
=strlen(destdir
);
399 /* VerFindFileA [VERSION.5] */
402 UINT32 flags
,LPCSTR filename
,LPCSTR windir
,LPCSTR appdir
,
403 LPSTR curdir
,UINT32
*pcurdirlen
,LPSTR destdir
,UINT32
*pdestdirlen
)
405 UINT16 curdirlen
, destdirlen
;
406 DWORD ret
= VerFindFile16(flags
,filename
,windir
,appdir
,
407 curdir
,&curdirlen
,destdir
,&destdirlen
);
408 *pcurdirlen
= curdirlen
;
409 *pdestdirlen
= destdirlen
;
413 /* VerFindFileW [VERSION.6] */
416 UINT32 flags
,LPCWSTR filename
,LPCWSTR windir
,LPCWSTR appdir
,
417 LPWSTR curdir
,UINT32
*pcurdirlen
,LPWSTR destdir
,UINT32
*pdestdirlen
)
419 UINT16 curdirlen
, destdirlen
;
420 LPSTR wfn
,wwd
,wad
,wdd
,wcd
;
423 wfn
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
424 wwd
= HEAP_strdupWtoA( GetProcessHeap(), 0, windir
);
425 wad
= HEAP_strdupWtoA( GetProcessHeap(), 0, appdir
);
426 wcd
= HeapAlloc( GetProcessHeap(), 0, *pcurdirlen
);
427 wdd
= HeapAlloc( GetProcessHeap(), 0, *pdestdirlen
);
428 ret
= VerFindFile16(flags
,wfn
,wwd
,wad
,wcd
,&curdirlen
,wdd
,&destdirlen
);
429 lstrcpynAtoW(curdir
,wcd
,*pcurdirlen
);
430 lstrcpynAtoW(destdir
,wdd
,*pdestdirlen
);
431 *pcurdirlen
= strlen(wcd
);
432 *pdestdirlen
= strlen(wdd
);
433 HeapFree( GetProcessHeap(), 0, wfn
);
434 HeapFree( GetProcessHeap(), 0, wwd
);
435 HeapFree( GetProcessHeap(), 0, wad
);
436 HeapFree( GetProcessHeap(), 0, wcd
);
437 HeapFree( GetProcessHeap(), 0, wdd
);
441 /* VerInstallFile [VER.9] */
444 UINT16 flags
,LPCSTR srcfilename
,LPCSTR destfilename
,LPCSTR srcdir
,
445 LPCSTR destdir
,LPSTR tmpfile
,UINT16
*tmpfilelen
447 dprintf_ver(stddeb
,"VerInstallFile(%x,%s,%s,%s,%s,%p,%d)\n",
448 flags
,srcfilename
,destfilename
,srcdir
,destdir
,tmpfile
,*tmpfilelen
451 /* FIXME: Implementation still missing .... */
456 /* VerFindFileA [VERSION.5] */
459 UINT32 flags
,LPCSTR srcfilename
,LPCSTR destfilename
,LPCSTR srcdir
,
460 LPCSTR destdir
,LPSTR tmpfile
,UINT32
*tmpfilelen
)
463 DWORD ret
= VerInstallFile16(flags
,srcfilename
,destfilename
,srcdir
,
464 destdir
,tmpfile
,&filelen
);
465 *tmpfilelen
= filelen
;
469 /* VerFindFileW [VERSION.6] */
472 UINT32 flags
,LPCWSTR srcfilename
,LPCWSTR destfilename
,LPCWSTR srcdir
,
473 LPCWSTR destdir
,LPWSTR tmpfile
,UINT32
*tmpfilelen
)
475 LPSTR wsrcf
,wsrcd
,wdestf
,wdestd
,wtmpf
;
478 wsrcf
= HEAP_strdupWtoA( GetProcessHeap(), 0, srcfilename
);
479 wsrcd
= HEAP_strdupWtoA( GetProcessHeap(), 0, srcdir
);
480 wdestf
= HEAP_strdupWtoA( GetProcessHeap(), 0, destfilename
);
481 wdestd
= HEAP_strdupWtoA( GetProcessHeap(), 0, destdir
);
482 wtmpf
= HEAP_strdupWtoA( GetProcessHeap(), 0, tmpfile
);
483 ret
= VerInstallFile32A(flags
,wsrcf
,wdestf
,wsrcd
,wdestd
,wtmpf
,tmpfilelen
);
484 HeapFree( GetProcessHeap(), 0, wsrcf
);
485 HeapFree( GetProcessHeap(), 0, wsrcd
);
486 HeapFree( GetProcessHeap(), 0, wdestf
);
487 HeapFree( GetProcessHeap(), 0, wdestd
);
488 HeapFree( GetProcessHeap(), 0, wtmpf
);
492 /* FIXME: This table should, of course, be language dependend */
493 static const struct map_id2str
{
495 const char *langname
;
498 {0x0402,"Bulgarisch"},
499 {0x0403,"Katalanisch"},
500 {0x0404,"Traditionales Chinesisch"},
501 {0x0405,"Tschecisch"},
504 {0x0408,"Griechisch"},
505 {0x0409,"Amerikanisches Englisch"},
506 {0x040A,"Kastilisches Spanisch"},
508 {0x040C,"Französisch"},
509 {0x040D,"Hebräisch"},
510 {0x040E,"Ungarisch"},
511 {0x040F,"Isländisch"},
512 {0x0410,"Italienisch"},
513 {0x0411,"Japanisch"},
514 {0x0412,"Koreanisch"},
515 {0x0413,"Niederländisch"},
516 {0x0414,"Norwegisch-Bokmal"},
518 {0x0416,"Brasilianisches Portugiesisch"},
519 {0x0417,"Rätoromanisch"},
520 {0x0418,"Rumänisch"},
522 {0x041A,"Kroatoserbisch (lateinisch)"},
523 {0x041B,"Slowenisch"},
524 {0x041C,"Albanisch"},
525 {0x041D,"Schwedisch"},
530 {0x0804,"Vereinfachtes Chinesisch"},
531 {0x0807,"Schweizerdeutsch"},
532 {0x0809,"Britisches Englisch"},
533 {0x080A,"Mexikanisches Spanisch"},
534 {0x080C,"Belgisches Französisch"},
535 {0x0810,"Schweizerisches Italienisch"},
536 {0x0813,"Belgisches Niederländisch"},
537 {0x0814,"Norgwegisch-Nynorsk"},
538 {0x0816,"Portugiesisch"},
539 {0x081A,"Serbokratisch (kyrillisch)"},
540 {0x0C1C,"Kanadisches Französisch"},
541 {0x100C,"Schweizerisches Französisch"},
542 {0x0000,"Unbekannt"},
545 /* VerLanguageName [VER.10] */
547 VerLanguageName16(UINT16 langid
,LPSTR langname
,UINT16 langnamelen
) {
551 dprintf_ver(stddeb
,"VerLanguageName(%d,%p,%d)\n",langid
,langname
,langnamelen
);
552 /* First, check \System\CurrentControlSet\control\Nls\Locale\<langid>
555 buf
=(char*)malloc(strlen("\\System\\CurrentControlSet\\control\\Nls\\Locale\\")+9);
556 sprintf(buf
,"\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",langid
);
557 if (ERROR_SUCCESS
==RegQueryValue16(HKEY_LOCAL_MACHINE
,buf
,langname
,(LPDWORD
)&langnamelen
)) {
558 langname
[langnamelen
-1]='\0';
561 /* if that fails, use the interal table */
562 for (i
=0;languages
[i
].langid
!=0;i
++)
563 if (langid
==languages
[i
].langid
)
565 strncpy(langname
,languages
[i
].langname
,langnamelen
);
566 langname
[langnamelen
-1]='\0';
567 return strlen(languages
[i
].langname
);
570 /* VerLanguageNameA [VERSION.9] */
572 VerLanguageName32A(UINT32 langid
,LPSTR langname
,UINT32 langnamelen
) {
573 return VerLanguageName16(langid
,langname
,langnamelen
);
576 /* VerLanguageNameW [VERSION.10] */
578 VerLanguageName32W(UINT32 langid
,LPWSTR langname
,UINT32 langnamelen
) {
583 /* First, check \System\CurrentControlSet\control\Nls\Locale\<langid>
586 sprintf(buffer
,"\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",langid
);
587 keyname
= HEAP_strdupAtoW( GetProcessHeap(), 0, buffer
);
588 if (ERROR_SUCCESS
==RegQueryValue32W(HKEY_LOCAL_MACHINE
,keyname
,langname
,(LPDWORD
)&langnamelen
)) {
589 HeapFree( GetProcessHeap(), 0, keyname
);
592 HeapFree( GetProcessHeap(), 0, keyname
);
593 /* if that fails, use the interal table */
594 for (i
=0;languages
[i
].langid
!=0;i
++)
595 if (langid
==languages
[i
].langid
)
597 lstrcpyAtoW( langname
, languages
[i
].langname
);
598 return strlen(languages
[i
].langname
); /* same as strlenW(langname); */
601 /* FIXME: UNICODE? */
605 /* in memory structure... */
606 char name
[1]; /* padded to dword alignment */
608 char data[datalen]; padded to dword alignemnt
609 BYTE subdirdata[]; until nextoff
614 _find_data(BYTE
*block
,LPCSTR str
) {
619 while (*str
&& *str
=='\\')
621 if (NULL
!=(nextslash
=strchr(str
,'\\')))
622 substrlen
=nextslash
-str
;
624 substrlen
=strlen(str
);
625 if (nextslash
!=NULL
) {
626 while (*nextslash
&& *nextslash
=='\\')
634 db
=(struct db
*)block
;
635 dprintf_ver(stddeb
,"db=%p,db->nextoff=%d,db->datalen=%d,db->name=%s,db->data=%s\n",
636 db
,db
->nextoff
,db
->datalen
,db
->name
,(char*)((char*)db
+4+((strlen(db
->name
)+4)&~3))
641 dprintf_ver(stddeb
,"comparing with %s\n",db
->name
);
642 if (!strncmp(db
->name
,str
,substrlen
)) {
645 block
+4+((strlen(db
->name
)+4)&~3)+((db
->datalen
+3)&~3)
651 block
=block
+((db
->nextoff
+3)&~3);
655 /* VerQueryValue [VER.11] */
656 /* take care, 'buffer' is NOT a SEGPTR, it just points to one */
658 VerQueryValue16(SEGPTR segblock
,LPCSTR subblock
,SEGPTR
*buffer
,UINT16
*buflen
)
660 BYTE
*block
=PTR_SEG_TO_LIN(segblock
),*b
;
664 dprintf_ver(stddeb
,"VerQueryValue16(%p,%s,%p,%d)\n",
665 block
,subblock
,buffer
,*buflen
667 s
=(char*)xmalloc(strlen("VS_VERSION_INFO\\")+strlen(subblock
)+1);
668 strcpy(s
,"VS_VERSION_INFO\\");strcat(s
,subblock
);
669 b
=_find_data(block
,s
);
675 *buflen
= db
->datalen
;
676 /* let b point to data area */
677 b
= b
+4+((strlen(db
->name
)+4)&~3);
678 /* now look up what the resp. SEGPTR would be ... */
679 *buffer
= (b
-block
)+segblock
;
680 dprintf_ver(stddeb
," -> %s=%s\n",subblock
,b
);
685 VerQueryValue32A(LPVOID vblock
,LPCSTR subblock
,LPVOID
*vbuffer
,UINT32
*buflen
)
687 BYTE
*b
,*block
=(LPBYTE
)vblock
,**buffer
=(LPBYTE
*)vbuffer
;
691 dprintf_ver(stddeb
,"VerQueryValue32A(%p,%s,%p,%d)\n",
692 block
,subblock
,buffer
,*buflen
694 s
=(char*)xmalloc(strlen("VS_VERSION_INFO\\")+strlen(subblock
)+1);
695 strcpy(s
,"VS_VERSION_INFO\\");strcat(s
,subblock
);
696 b
=_find_data(block
,s
);
702 *buflen
= db
->datalen
;
703 /* let b point to data area */
704 b
= b
+4+((strlen(db
->name
)+4)&~3);
706 dprintf_ver(stddeb
," -> %s=%s\n",subblock
,b
);
711 VerQueryValue32W(LPVOID vblock
,LPCWSTR subblock
,LPVOID
*vbuffer
,UINT32
*buflen
)
713 /* FIXME: hmm, we not only need to convert subblock, but also
715 * And what about UNICODE version info?
716 * And the NAMES of the values?
718 BYTE
*b
,**buffer
=(LPBYTE
*)vbuffer
,*block
=(LPBYTE
)vblock
;
722 sb
= HEAP_strdupWtoA( GetProcessHeap(), 0, subblock
);
723 s
=(char*)xmalloc(strlen("VS_VERSION_INFO\\")+strlen(sb
)+1);
724 strcpy(s
,"VS_VERSION_INFO\\");strcat(s
,sb
);
725 b
=_find_data(block
,s
);
728 HeapFree( GetProcessHeap(), 0, sb
);
732 *buflen
= db
->datalen
;
733 /* let b point to data area */
734 b
= b
+4+((strlen(db
->name
)+4)&~3);
736 dprintf_ver(stddeb
," -> %s=%s\n",sb
,b
);
737 HeapFree( GetProcessHeap(), 0, sb
);
740 /* 20 GETFILEVERSIONINFORAW */