Release 960611
[wine/multimedia.git] / misc / ver.c
blob7541a8286c021d8cc87445665260db6455e1c0f0
1 /*
2 * Implementation of VER.DLL
3 *
4 * Copyright 1996 Marcus Meissner
5 */
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <ctype.h>
11 #include "windows.h"
12 #include "win.h"
13 #include "winerror.h"
14 #include "ver.h"
15 #include "lzexpand.h"
16 #include "module.h"
17 #include "neexe.h"
18 #include "stddebug.h"
19 #include "debug.h"
20 #include "xmalloc.h"
21 #include "winreg.h"
22 #include "string32.h"
24 #define LZREAD(what) if (sizeof(*what)!=LZRead32(lzfd,what,sizeof(*what))) return 0;
26 #define strdupW2A(x) STRING32_DupUniToAnsi(x)
27 #define strdupA2W(x) STRING32_DupAnsiToUni(x)
29 int
30 read_ne_header(HFILE lzfd,struct ne_header_s *nehd) {
31 struct mz_header_s mzh;
33 LZSeek(lzfd,0,SEEK_SET);
34 if (sizeof(mzh)!=LZRead32(lzfd,&mzh,sizeof(mzh)))
35 return 0;
36 if (mzh.mz_magic!=MZ_SIGNATURE)
37 return 0;
38 LZSeek(lzfd,mzh.ne_offset,SEEK_SET);
39 LZREAD(nehd);
40 if (nehd->ne_magic == NE_SIGNATURE) {
41 LZSeek(lzfd,mzh.ne_offset,SEEK_SET);
42 return 1;
44 /* must handle PE files too. Later. */
45 return 0;
49 int
50 find_ne_resource(
51 HFILE lzfd,struct ne_header_s *nehd,SEGPTR typeid,SEGPTR resid,
52 BYTE **resdata,int *reslen,DWORD *off
53 ) {
54 NE_TYPEINFO ti;
55 NE_NAMEINFO ni;
56 int i;
57 WORD shiftcount;
58 DWORD nehdoffset;
60 nehdoffset=LZSeek(lzfd,nehd->resource_tab_offset,SEEK_CUR);
61 LZREAD(&shiftcount);
62 dprintf_resource(stderr,"shiftcount is %d\n",shiftcount);
63 dprintf_resource(stderr,"reading resource typeinfo dir.\n");
65 if (!HIWORD(typeid)) typeid = (SEGPTR)(LOWORD(typeid) | 0x8000);
66 if (!HIWORD(resid)) resid = (SEGPTR)(LOWORD(resid) | 0x8000);
67 while (1) {
68 int skipflag;
70 LZREAD(&ti);
71 if (!ti.type_id)
72 return 0;
73 dprintf_resource(stderr," ti.typeid =%04x,count=%d\n",ti.type_id,ti.count);
74 skipflag=0;
75 if (!HIWORD(typeid)) {
76 if ((ti.type_id&0x8000)&&(typeid!=ti.type_id))
77 skipflag=1;
78 } else {
79 if (ti.type_id & 0x8000) {
80 skipflag=1;
81 } else {
82 BYTE len;
83 char *str;
84 DWORD whereleft;
86 whereleft=LZSeek(
87 lzfd,
88 nehdoffset+nehd->resource_tab_offset+ti.type_id,
89 SEEK_SET
91 LZREAD(&len);
92 str=xmalloc(len);
93 if (len!=LZRead32(lzfd,str,len))
94 return 0;
95 dprintf_resource(stderr,"read %s to compare it with %s\n",
96 str,(char*)PTR_SEG_TO_LIN(typeid)
98 if (lstrcmpi32A(str,(char*)PTR_SEG_TO_LIN(typeid)))
99 skipflag=1;
100 free(str);
101 LZSeek(lzfd,whereleft,SEEK_SET);
104 if (skipflag) {
105 LZSeek(lzfd,ti.count*sizeof(ni),SEEK_CUR);
106 continue;
108 for (i=0;i<ti.count;i++) {
109 WORD *rdata;
110 int len;
112 LZREAD(&ni);
113 dprintf_resource(stderr," ni.id=%4x,offset=%d,length=%d\n",
114 ni.id,ni.offset,ni.length
116 skipflag=1;
117 if (!HIWORD(resid)) {
118 if (ni.id == resid)
119 skipflag=0;
120 } else {
121 if (!(ni.id & 0x8000)) {
122 BYTE len;
123 char *str;
124 DWORD whereleft;
126 whereleft=LZSeek(
127 lzfd,
128 nehdoffset+nehd->resource_tab_offset+ni.id,
129 SEEK_SET
131 LZREAD(&len);
132 str=xmalloc(len);
133 if (len!=LZRead32(lzfd,str,len))
134 return 0;
135 dprintf_resource(stderr,"read %s to compare it with %s\n",
136 str,(char*)PTR_SEG_TO_LIN(typeid)
138 if (!lstrcmpi32A(str,(char*)PTR_SEG_TO_LIN(typeid)))
139 skipflag=0;
140 free(str);
141 LZSeek(lzfd,whereleft,SEEK_SET);
144 if (skipflag)
145 continue;
146 LZSeek(lzfd,((int)ni.offset<<shiftcount),SEEK_SET);
147 *off = (int)ni.offset<<shiftcount;
148 len = ni.length<<shiftcount;
149 rdata=(WORD*)xmalloc(len);
150 if (len!=LZRead32(lzfd,rdata,len)) {
151 free(rdata);
152 return 0;
154 dprintf_resource(stderr,"resource found.\n");
155 *resdata= (BYTE*)rdata;
156 *reslen = len;
157 return 1;
162 /* GetFileResourceSize [VER.2] */
163 DWORD
164 GetFileResourceSize(LPCSTR filename,SEGPTR restype,SEGPTR resid,LPDWORD off) {
165 HFILE lzfd;
166 OFSTRUCT ofs;
167 BYTE *resdata;
168 int reslen;
169 struct ne_header_s nehd;
171 fprintf(stderr,"GetFileResourceSize(%s,%lx,%lx,%p)\n",
172 filename,(LONG)restype,(LONG)resid,off
174 lzfd=LZOpenFile16(filename,&ofs,OF_READ);
175 if (lzfd==0)
176 return 0;
177 if (!read_ne_header(lzfd,&nehd)) {
178 LZClose(lzfd);
179 return 0;
181 if (!find_ne_resource(lzfd,&nehd,restype,resid,&resdata,&reslen,off)) {
182 LZClose(lzfd);
183 return 0;
185 free(resdata);
186 LZClose(lzfd);
187 return reslen;
190 /* GetFileResourceSize [VER.3] */
191 DWORD
192 GetFileResource(LPCSTR filename,SEGPTR restype,SEGPTR resid,
193 DWORD off,DWORD datalen,LPVOID data
195 HFILE lzfd;
196 OFSTRUCT ofs;
197 BYTE *resdata;
198 int reslen;
199 struct ne_header_s nehd;
200 fprintf(stderr,"GetFileResource(%s,%lx,%lx,%ld,%ld,%p)\n",
201 filename,(LONG)restype,(LONG)resid,off,datalen,data
204 lzfd=LZOpenFile16(filename,&ofs,OF_READ);
205 if (lzfd==0)
206 return 0;
207 if (!off) {
208 if (!read_ne_header(lzfd,&nehd)) {
209 LZClose(lzfd);
210 return 0;
212 if (!find_ne_resource(lzfd,&nehd,restype,resid,&resdata,&reslen,&off)) {
213 LZClose(lzfd);
214 return 0;
216 free(resdata);
218 LZSeek(lzfd,off,SEEK_SET);
219 if (reslen>datalen)
220 reslen=datalen;
221 LZRead32(lzfd,data,reslen);
222 LZClose(lzfd);
223 return reslen;
226 /* GetFileVersionInfoSize [VER.6] */
227 DWORD
228 GetFileVersionInfoSize16(LPCSTR filename,LPDWORD handle) {
229 DWORD len,ret;
230 BYTE buf[72];
231 VS_FIXEDFILEINFO *vffi;
233 dprintf_resource(stderr,"GetFileVersionInfoSize16(%s,%p)\n",filename,handle);
234 len=GetFileResourceSize(filename,VS_FILE_INFO,VS_VERSION_INFO,handle);
235 if (!len)
236 return 0;
237 ret=GetFileResource(
238 filename,VS_FILE_INFO,VS_VERSION_INFO,*handle,sizeof(buf),buf
240 if (!ret)
241 return 0;
243 vffi=(VS_FIXEDFILEINFO*)(buf+0x14);
244 if (vffi->dwSignature != VS_FFI_SIGNATURE)
245 return 0;
246 if (*(WORD*)buf < len)
247 len = *(WORD*)buf;
248 fprintf(stderr,"->strucver=%ld.%ld,filever=%ld.%ld,productver=%ld.%ld,flagmask=%lx,flags=%lx,OS=",
249 (vffi->dwStrucVersion>>16),vffi->dwStrucVersion&0xFFFF,
250 vffi->dwFileVersionMS,vffi->dwFileVersionLS,
251 vffi->dwProductVersionMS,vffi->dwProductVersionLS,
252 vffi->dwFileFlagsMask,vffi->dwFileFlags
254 switch (vffi->dwFileOS&0xFFFF0000) {
255 case VOS_DOS:fprintf(stderr,"DOS,");break;
256 case VOS_OS216:fprintf(stderr,"OS/2-16,");break;
257 case VOS_OS232:fprintf(stderr,"OS/2-32,");break;
258 case VOS_NT:fprintf(stderr,"NT,");break;
259 case VOS_UNKNOWN:
260 default:
261 fprintf(stderr,"UNKNOWN(%ld),",vffi->dwFileOS&0xFFFF0000);break;
263 switch (vffi->dwFileOS & 0xFFFF) {
264 case VOS__BASE:fprintf(stderr,"BASE");break;
265 case VOS__WINDOWS16:fprintf(stderr,"WIN16");break;
266 case VOS__WINDOWS32:fprintf(stderr,"WIN32");break;
267 case VOS__PM16:fprintf(stderr,"PM16");break;
268 case VOS__PM32:fprintf(stderr,"PM32");break;
269 default:fprintf(stderr,"UNKNOWN(%ld)",vffi->dwFileOS&0xFFFF);break;
271 switch (vffi->dwFileType) {
272 default:
273 case VFT_UNKNOWN:
274 fprintf(stderr,"filetype=Unknown(%ld)",vffi->dwFileType);
275 break;
276 case VFT_APP:fprintf(stderr,"filetype=APP");break;
277 case VFT_DLL:fprintf(stderr,"filetype=DLL");break;
278 case VFT_DRV:
279 fprintf(stderr,"filetype=DRV,");
280 switch(vffi->dwFileSubtype) {
281 default:
282 case VFT2_UNKNOWN:
283 fprintf(stderr,"UNKNOWN(%ld)",vffi->dwFileSubtype);
284 break;
285 case VFT2_DRV_PRINTER:
286 fprintf(stderr,"PRINTER");
287 break;
288 case VFT2_DRV_KEYBOARD:
289 fprintf(stderr,"KEYBOARD");
290 break;
291 case VFT2_DRV_LANGUAGE:
292 fprintf(stderr,"LANGUAGE");
293 break;
294 case VFT2_DRV_DISPLAY:
295 fprintf(stderr,"DISPLAY");
296 break;
297 case VFT2_DRV_MOUSE:
298 fprintf(stderr,"MOUSE");
299 break;
300 case VFT2_DRV_NETWORK:
301 fprintf(stderr,"NETWORK");
302 break;
303 case VFT2_DRV_SYSTEM:
304 fprintf(stderr,"SYSTEM");
305 break;
306 case VFT2_DRV_INSTALLABLE:
307 fprintf(stderr,"INSTALLABLE");
308 break;
309 case VFT2_DRV_SOUND:
310 fprintf(stderr,"SOUND");
311 break;
312 case VFT2_DRV_COMM:
313 fprintf(stderr,"COMM");
314 break;
315 case VFT2_DRV_INPUTMETHOD:
316 fprintf(stderr,"INPUTMETHOD");
317 break;
319 break;
320 case VFT_FONT:
321 fprintf(stderr,"filetype=FONT.");
322 switch (vffi->dwFileSubtype) {
323 default:
324 fprintf(stderr,"UNKNOWN(%ld)",vffi->dwFileSubtype);
325 break;
326 case VFT2_FONT_RASTER:fprintf(stderr,"RASTER");break;
327 case VFT2_FONT_VECTOR:fprintf(stderr,"VECTOR");break;
328 case VFT2_FONT_TRUETYPE:fprintf(stderr,"TRUETYPE");break;
330 break;
331 case VFT_VXD:fprintf(stderr,"filetype=VXD");break;
332 case VFT_STATIC_LIB:fprintf(stderr,"filetype=STATIC_LIB");break;
334 fprintf(stderr,"filedata=%lx.%lx\n",vffi->dwFileDateMS,vffi->dwFileDateLS);
335 return len;
338 /* GetFileVersionInfoSize32A [VERSION.1] */
339 DWORD
340 GetFileVersionInfoSize32A(LPCSTR filename,LPDWORD handle) {
341 dprintf_resource(stderr,"GetFileVersionInfoSize32A(%s,%p)\n",filename,handle);
342 return GetFileVersionInfoSize16(filename,handle);
345 /* GetFileVersionInfoSize32W [VERSION.2] */
346 DWORD
347 GetFileVersionInfoSize32W(LPCWSTR filename,LPDWORD handle) {
348 LPSTR xfn;
349 DWORD ret;
351 xfn = strdupW2A(filename);
352 ret=GetFileVersionInfoSize16(xfn,handle);
353 free(xfn);
354 return ret;
357 /* GetFileVersionInfo [VER.7] */
358 DWORD
359 GetFileVersionInfo16(LPCSTR filename,DWORD handle,DWORD datasize,LPVOID data) {
360 dprintf_resource(stderr,"GetFileVersionInfo16(%s,%ld,%ld,%p)\n->",
361 filename,handle,datasize,data
363 return GetFileResource(
364 filename,VS_FILE_INFO,VS_VERSION_INFO,handle,datasize,data
368 /* GetFileVersionInfoA [VERSION.0] */
369 DWORD
370 GetFileVersionInfo32A(LPCSTR filename,DWORD handle,DWORD datasize,LPVOID data) {
371 return GetFileVersionInfo16(filename,handle,datasize,data);
374 /* GetFileVersionInfoW [VERSION.3] */
375 DWORD
376 GetFileVersionInfo32W(LPCWSTR filename,DWORD handle,DWORD datasize,LPVOID data){
377 DWORD ret;
378 LPSTR fn;
380 fn = strdupW2A(filename);
381 ret = GetFileVersionInfo16(fn,handle,datasize,data);
382 free(fn);
383 return ret;
386 /* VerFindFile [VER.8] */
387 DWORD
388 VerFindFile16(
389 UINT16 flags,LPCSTR filename,LPCSTR windir,LPCSTR appdir,
390 LPSTR curdir,UINT16 *curdirlen,LPSTR destdir,UINT16 *destdirlen
392 fprintf(stderr,"VerFindFile(%x,%s,%s,%s,%p,%d,%p,%d)\n",
393 flags,filename,windir,appdir,curdir,*curdirlen,destdir,*destdirlen
395 strcpy(curdir,"Z:\\ROOT\\.WINE\\");/*FIXME*/
396 *curdirlen=strlen(curdir);
397 strcpy(destdir,"Z:\\ROOT\\.WINE\\");/*FIXME*/
398 *destdirlen=strlen(destdir);
399 return 0;
402 /* VerFindFileA [VERSION.5] */
403 DWORD
404 VerFindFile32A(
405 UINT32 flags,LPCSTR filename,LPCSTR windir,LPCSTR appdir,
406 LPSTR curdir,UINT32 *curdirlen,LPSTR destdir,UINT32 *destdirlen
408 return VerFindFile16(flags,filename,windir,appdir,curdir,curdirlen,destdir,destdirlen);
411 /* VerFindFileW [VERSION.6] */
412 DWORD
413 VerFindFile32W(
414 UINT32 flags,LPCWSTR filename,LPCWSTR windir,LPCWSTR appdir,
415 LPWSTR curdir,UINT32 *curdirlen,LPWSTR destdir,UINT32 *destdirlen
417 LPSTR wfn,wwd,wad,wdd,wcd;
418 DWORD ret;
420 wfn = strdupW2A(filename);
421 wwd = strdupW2A(windir);
422 wad = strdupW2A(appdir);
423 wcd = (LPSTR)malloc(*curdirlen);
424 wdd = (LPSTR)malloc(*destdirlen);
425 ret=VerFindFile16(flags,wfn,wwd,wad,wcd,curdirlen,wdd,destdirlen);
426 STRING32_AnsiToUni(curdir,wcd);
427 STRING32_AnsiToUni(destdir,wdd);
428 *curdirlen = strlen(wcd);
429 *destdirlen = strlen(wdd);
430 return ret;
433 /* VerInstallFile [VER.9] */
434 DWORD
435 VerInstallFile16(
436 UINT16 flags,LPCSTR srcfilename,LPCSTR destfilename,LPCSTR srcdir,
437 LPCSTR destdir,LPSTR tmpfile,UINT16 *tmpfilelen
439 fprintf(stderr,"VerInstallFile(%x,%s,%s,%s,%s,%p,%d)\n",
440 flags,srcfilename,destfilename,srcdir,destdir,tmpfile,*tmpfilelen
443 /* FIXME: Implementation still missing .... */
445 return VIF_SRCOLD;
448 /* VerFindFileA [VERSION.5] */
449 DWORD
450 VerInstallFile32A(
451 UINT32 flags,LPCSTR srcfilename,LPCSTR destfilename,LPCSTR srcdir,
452 LPCSTR destdir,LPSTR tmpfile,UINT32 *tmpfilelen
454 return VerInstallFile16(flags,srcfilename,destfilename,srcdir,destdir,tmpfile,tmpfilelen);
457 /* VerFindFileW [VERSION.6] */
458 DWORD
459 VerInstallFile32W(
460 UINT32 flags,LPCWSTR srcfilename,LPCWSTR destfilename,LPCWSTR srcdir,
461 LPCWSTR destdir,LPWSTR tmpfile,UINT32 *tmpfilelen
463 LPSTR wsrcf,wsrcd,wdestf,wdestd,wtmpf;
464 DWORD ret;
466 wsrcf = strdupW2A(srcfilename);
467 wsrcd = strdupW2A(srcdir);
468 wdestf = strdupW2A(destfilename);
469 wdestd = strdupW2A(destdir);
470 wtmpf = strdupW2A(tmpfile);
471 ret=VerInstallFile32A(flags,wsrcf,wdestf,wsrcd,wdestd,wtmpf,tmpfilelen);
472 free(wsrcf);
473 free(wsrcd);
474 free(wdestf);
475 free(wdestd);
476 free(wtmpf);
477 return ret;
480 /* FIXME: This table should, of course, be language dependend */
481 static const struct map_id2str {
482 UINT langid;
483 const char *langname;
484 } languages[]={
485 {0x0401,"Arabisch"},
486 {0x0402,"Bulgarisch"},
487 {0x0403,"Katalanisch"},
488 {0x0404,"Traditionales Chinesisch"},
489 {0x0405,"Tschecisch"},
490 {0x0406,"Dänisch"},
491 {0x0407,"Deutsch"},
492 {0x0408,"Griechisch"},
493 {0x0409,"Amerikanisches Englisch"},
494 {0x040A,"Kastilisches Spanisch"},
495 {0x040B,"Finnisch"},
496 {0x040C,"Französisch"},
497 {0x040D,"Hebräisch"},
498 {0x040E,"Ungarisch"},
499 {0x040F,"Isländisch"},
500 {0x0410,"Italienisch"},
501 {0x0411,"Japanisch"},
502 {0x0412,"Koreanisch"},
503 {0x0413,"Niederländisch"},
504 {0x0414,"Norwegisch-Bokmal"},
505 {0x0415,"Polnisch"},
506 {0x0416,"Brasilianisches Portugiesisch"},
507 {0x0417,"Rätoromanisch"},
508 {0x0418,"Rumänisch"},
509 {0x0419,"Russisch"},
510 {0x041A,"Kroatoserbisch (lateinisch)"},
511 {0x041B,"Slowenisch"},
512 {0x041C,"Albanisch"},
513 {0x041D,"Schwedisch"},
514 {0x041E,"Thai"},
515 {0x041F,"Türkisch"},
516 {0x0420,"Urdu"},
517 {0x0421,"Bahasa"},
518 {0x0804,"Vereinfachtes Chinesisch"},
519 {0x0807,"Schweizerdeutsch"},
520 {0x0809,"Britisches Englisch"},
521 {0x080A,"Mexikanisches Spanisch"},
522 {0x080C,"Belgisches Französisch"},
523 {0x0810,"Schweizerisches Italienisch"},
524 {0x0813,"Belgisches Niederländisch"},
525 {0x0814,"Norgwegisch-Nynorsk"},
526 {0x0816,"Portugiesisch"},
527 {0x081A,"Serbokratisch (kyrillisch)"},
528 {0x0C1C,"Kanadisches Französisch"},
529 {0x100C,"Schweizerisches Französisch"},
530 {0x0000,"Unbekannt"},
533 /* VerLanguageName [VER.10] */
534 DWORD
535 VerLanguageName16(UINT16 langid,LPSTR langname,UINT16 langnamelen) {
536 int i;
537 char *buf;
539 fprintf(stderr,"VerLanguageName(%d,%p,%d)\n",langid,langname,langnamelen);
540 /* First, check \System\CurrentControlSet\control\Nls\Locale\<langid>
541 * from the registry.
543 buf=(char*)malloc(strlen("\\System\\CurrentControlSet\\control\\Nls\\Locale\\")+9);
544 sprintf(buf,"\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",langid);
545 if (ERROR_SUCCESS==RegQueryValue16(HKEY_LOCAL_MACHINE,buf,langname,(LPDWORD)&langnamelen)) {
546 langname[langnamelen-1]='\0';
547 return langnamelen;
549 /* if that fails, use the interal table */
550 for (i=0;languages[i].langid!=0;i++)
551 if (langid==languages[i].langid)
552 break;
553 strncpy(langname,languages[i].langname,langnamelen);
554 langname[langnamelen-1]='\0';
555 return strlen(languages[i].langname);
558 /* VerLanguageNameA [VERSION.9] */
559 DWORD
560 VerLanguageName32A(UINT32 langid,LPSTR langname,UINT32 langnamelen) {
561 return VerLanguageName16(langid,langname,langnamelen);
564 /* VerLanguageNameW [VERSION.10] */
565 DWORD
566 VerLanguageName32W(UINT32 langid,LPWSTR langname,UINT32 langnamelen) {
567 int i;
568 char *buf;
569 LPWSTR keyname,result;
571 /* First, check \System\CurrentControlSet\control\Nls\Locale\<langid>
572 * from the registry.
574 buf=(char*)malloc(strlen("\\System\\CurrentControlSet\\control\\Nls\\Locale\\")+9);
575 sprintf(buf,"\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",langid);
576 keyname=strdupA2W(buf);free(buf);
577 if (ERROR_SUCCESS==RegQueryValue32W(HKEY_LOCAL_MACHINE,keyname,langname,(LPDWORD)&langnamelen)) {
578 free(keyname);
579 return langnamelen;
581 free(keyname);
582 /* if that fails, use the interal table */
583 for (i=0;languages[i].langid!=0;i++)
584 if (langid==languages[i].langid)
585 break;
586 result=strdupA2W(languages[i].langname);
587 i=lstrlen32W(result)*sizeof(WCHAR);
588 if (i>langnamelen)
589 i=langnamelen;
590 memcpy(langname,result,i);
591 langname[langnamelen-1]='\0';
592 free(result);
593 return strlen(languages[i].langname); /* same as strlenW(result); */
596 /* FIXME: UNICODE? */
597 struct db {
598 WORD nextoff;
599 WORD datalen;
600 /* in memory structure... */
601 char name[1]; /* padded to dword alignment */
602 /* ....
603 char data[datalen]; padded to dword alignemnt
604 BYTE subdirdata[]; until nextoff
608 static BYTE*
609 _find_data(BYTE *block,LPCSTR str) {
610 char *nextslash;
611 int substrlen;
612 struct db *db;
614 while (*str && *str=='\\')
615 str++;
616 if (NULL!=(nextslash=strchr(str,'\\')))
617 substrlen=nextslash-str;
618 else
619 substrlen=strlen(str);
620 if (nextslash!=NULL) {
621 while (*nextslash && *nextslash=='\\')
622 nextslash++;
623 if (!*nextslash)
624 nextslash=NULL;
628 while (1) {
629 db=(struct db*)block;
630 fprintf(stderr,"db=%p,db->nextoff=%d,db->datalen=%d,db->name=%s,db->data=%s\n",
631 db,db->nextoff,db->datalen,db->name,(char*)((char*)db+4+((strlen(db->name)+4)&~3))
633 if (!db->nextoff)
634 return NULL;
636 fprintf(stderr,"comparing with %s\n",db->name);
637 if (!strncmp(db->name,str,substrlen)) {
638 if (nextslash)
639 return _find_data(
640 block+4+((strlen(db->name)+4)&~3)+((db->datalen+3)&~3)
641 ,nextslash
643 else
644 return block;
646 block=block+((db->nextoff+3)&~3);
650 /* VerQueryValue [VER.11] */
651 /* take care, 'buffer' is NOT a SEGPTR, it just points to one */
652 DWORD
653 VerQueryValue16(SEGPTR segblock,LPCSTR subblock,SEGPTR *buffer,UINT16 *buflen)
655 BYTE *block=PTR_SEG_TO_LIN(segblock),*b;
656 struct db *db;
657 char *s;
659 fprintf(stderr,"VerQueryValue16(%p,%s,%p,%d)\n",
660 block,subblock,buffer,*buflen
662 s=(char*)xmalloc(strlen("VS_VERSION_INFO")+strlen(subblock)+1);
663 strcpy(s,"VS_VERSION_INFO");strcat(s,subblock);
664 b=_find_data(block,s);
665 if (b==NULL) {
666 *buflen=0;
667 return 0;
669 db=(struct db*)b;
670 *buflen = db->datalen;
671 /* let b point to data area */
672 b = b+4+((strlen(db->name)+4)&3);
673 /* now look up what the resp. SEGPTR would be ...
674 * we could use MAKE_SEGPTR , but we don't need to
676 *buffer = (b-block)+segblock;
677 fprintf(stderr," -> %s=%s\n",subblock,b);
678 return 1;
681 DWORD
682 VerQueryValue32A(LPVOID vblock,LPCSTR subblock,LPVOID *vbuffer,UINT32 *buflen)
684 BYTE *b,*block=(LPBYTE)vblock,**buffer=(LPBYTE*)vbuffer;
685 struct db *db;
686 char *s;
688 fprintf(stderr,"VerQueryValue32A(%p,%s,%p,%d)\n",
689 block,subblock,buffer,*buflen
691 s=(char*)xmalloc(strlen("VS_VERSION_INFO")+strlen(subblock)+1);
692 strcpy(s,"VS_VERSION_INFO");strcat(s,subblock);
693 b=_find_data(block,s);
694 if (b==NULL) {
695 *buflen=0;
696 return 0;
698 db=(struct db*)b;
699 *buflen = db->datalen;
700 /* let b point to data area */
701 b = b+4+((strlen(db->name)+4)&3);
702 *buffer = b;
703 fprintf(stderr," -> %s=%s\n",subblock,b);
704 return 1;
707 DWORD
708 VerQueryValue32W(LPVOID vblock,LPCWSTR subblock,LPVOID *vbuffer,UINT32 *buflen)
710 /* FIXME: hmm, we not only need to convert subblock, but also
711 * the content...or?
712 * And what about UNICODE version info?
713 * And the NAMES of the values?
715 BYTE *b,**buffer=(LPBYTE*)vbuffer,*block=(LPBYTE)vblock;
716 struct db *db;
717 char *s,*sb;
719 sb=strdupW2A(subblock);
720 s=(char*)xmalloc(strlen("VS_VERSION_INFO")+strlen(sb)+1);
721 strcpy(s,"VS_VERSION_INFO");strcat(s,sb);
722 b=_find_data(block,s);
723 if (b==NULL) {
724 *buflen=0;
725 free(sb);
726 return 0;
728 db=(struct db*)b;
729 *buflen = db->datalen;
730 /* let b point to data area */
731 b = b+4+((strlen(db->name)+4)&3);
732 *buffer = b;
733 fprintf(stderr," -> %s=%s\n",sb,b);
734 free(sb);
735 return 1;
737 /* 20 GETFILEVERSIONINFORAW */