2 * Implementation of VER.DLL
4 * Copyright 1996 Marcus Meissner
18 #include "stackframe.h" /* MAKE_SEGPTR */
24 #define LZREAD(what) if (sizeof(*what)!=LZRead(lzfd,MAKE_SEGPTR(what),sizeof(*what))) return 0;
27 read_ne_header(HFILE lzfd
,struct ne_header_s
*nehd
) {
28 struct mz_header_s mzh
;
30 LZSeek(lzfd
,0,SEEK_SET
);
31 if (sizeof(mzh
)!=LZRead(lzfd
,MAKE_SEGPTR(&mzh
),sizeof(mzh
)))
33 if (mzh
.mz_magic
!=MZ_SIGNATURE
)
35 LZSeek(lzfd
,mzh
.ne_offset
,SEEK_SET
);
37 if (nehd
->ne_magic
== NE_SIGNATURE
) {
38 LZSeek(lzfd
,mzh
.ne_offset
,SEEK_SET
);
41 /* must handle PE files too. Later. */
48 HFILE lzfd
,struct ne_header_s
*nehd
,SEGPTR
typeid,SEGPTR resid
,
49 BYTE
**resdata
,int *reslen
,DWORD
*off
57 nehdoffset
=LZSeek(lzfd
,nehd
->resource_tab_offset
,SEEK_CUR
);
59 dprintf_resource(stderr
,"shiftcount is %d\n",shiftcount
);
60 dprintf_resource(stderr
,"reading resource typeinfo dir.\n");
62 if (!HIWORD(typeid)) typeid = (SEGPTR
)(LOWORD(typeid) | 0x8000);
63 if (!HIWORD(resid
)) resid
= (SEGPTR
)(LOWORD(resid
) | 0x8000);
70 dprintf_resource(stderr
," ti.typeid =%04x,count=%d\n",ti
.type_id
,ti
.count
);
72 if (!HIWORD(typeid)) {
73 if ((ti
.type_id
&0x8000)&&(typeid!=ti
.type_id
))
76 if (ti
.type_id
& 0x8000) {
85 nehdoffset
+nehd
->resource_tab_offset
+ti
.type_id
,
90 if (len
!=LZRead(lzfd
,MAKE_SEGPTR(str
),len
))
92 dprintf_resource(stderr
,"read %s to compare it with %s\n",
93 str
,(char*)PTR_SEG_TO_LIN(typeid)
95 if (lstrcmpi(str
,(char*)PTR_SEG_TO_LIN(typeid)))
98 LZSeek(lzfd
,whereleft
,SEEK_SET
);
102 LZSeek(lzfd
,ti
.count
*sizeof(ni
),SEEK_CUR
);
105 for (i
=0;i
<ti
.count
;i
++) {
110 dprintf_resource(stderr
," ni.id=%4x,offset=%d,length=%d\n",
111 ni
.id
,ni
.offset
,ni
.length
114 if (!HIWORD(resid
)) {
118 if (!(ni
.id
& 0x8000)) {
125 nehdoffset
+nehd
->resource_tab_offset
+ni
.id
,
130 if (len
!=LZRead(lzfd
,MAKE_SEGPTR(str
),len
))
132 dprintf_resource(stderr
,"read %s to compare it with %s\n",
133 str
,(char*)PTR_SEG_TO_LIN(typeid)
135 if (!lstrcmpi(str
,(char*)PTR_SEG_TO_LIN(typeid)))
138 LZSeek(lzfd
,whereleft
,SEEK_SET
);
143 LZSeek(lzfd
,((int)ni
.offset
<<shiftcount
),SEEK_SET
);
144 *off
= (int)ni
.offset
<<shiftcount
;
145 len
= ni
.length
<<shiftcount
;
146 rdata
=(WORD
*)xmalloc(len
);
147 if (len
!=LZRead(lzfd
,MAKE_SEGPTR(rdata
),len
)) {
151 dprintf_resource(stderr
,"resource found.\n");
152 *resdata
= (BYTE
*)rdata
;
160 GetFileResourceSize(LPCSTR filename
,SEGPTR restype
,SEGPTR resid
,LPDWORD off
) {
165 struct ne_header_s nehd
;
167 fprintf(stderr
,"GetFileResourceSize(%s,%lx,%lx,%p)\n",
168 filename
,(LONG
)restype
,(LONG
)resid
,off
170 lzfd
=LZOpenFile(filename
,&ofs
,OF_READ
);
173 if (!read_ne_header(lzfd
,&nehd
)) {
177 if (!find_ne_resource(lzfd
,&nehd
,restype
,resid
,&resdata
,&reslen
,off
)) {
187 GetFileResource(LPCSTR filename
,SEGPTR restype
,SEGPTR resid
,
188 DWORD off
,DWORD datalen
,LPVOID data
194 struct ne_header_s nehd
;
195 fprintf(stderr
,"GetFileResource(%s,%lx,%lx,%ld,%ld,%p)\n",
196 filename
,(LONG
)restype
,(LONG
)resid
,off
,datalen
,data
199 lzfd
=LZOpenFile(filename
,&ofs
,OF_READ
);
203 if (!read_ne_header(lzfd
,&nehd
)) {
207 if (!find_ne_resource(lzfd
,&nehd
,restype
,resid
,&resdata
,&reslen
,&off
)) {
213 LZSeek(lzfd
,off
,SEEK_SET
);
216 LZRead(lzfd
,MAKE_SEGPTR(data
),reslen
);
222 GetFileVersionInfoSize(LPCSTR filename
,LPDWORD handle
) {
225 VS_FIXEDFILEINFO
*vffi
;
227 fprintf(stderr
,"GetFileVersionInfoSize(%s,%p)\n",filename
,handle
);
229 len
=GetFileResourceSize(filename
,VS_FILE_INFO
,VS_VERSION_INFO
,handle
);
233 filename
,VS_FILE_INFO
,VS_VERSION_INFO
,*handle
,sizeof(buf
),buf
238 vffi
=(VS_FIXEDFILEINFO
*)(buf
+0x14);
239 if (vffi
->dwSignature
!= VS_FFI_SIGNATURE
)
241 if (*(WORD
*)buf
< len
)
243 fprintf(stderr
,"->strucver=%ld.%ld,filever=%ld.%ld,productver=%ld.%ld,flagmask=%lx,flags=%lx,OS=",
244 (vffi
->dwStrucVersion
>>16),vffi
->dwStrucVersion
&0xFFFF,
245 vffi
->dwFileVersionMS
,vffi
->dwFileVersionLS
,
246 vffi
->dwProductVersionMS
,vffi
->dwProductVersionLS
,
247 vffi
->dwFileFlagsMask
,vffi
->dwFileFlags
249 switch (vffi
->dwFileOS
&0xFFFF0000) {
250 case VOS_DOS
:fprintf(stderr
,"DOS,");break;
251 case VOS_OS216
:fprintf(stderr
,"OS/2-16,");break;
252 case VOS_OS232
:fprintf(stderr
,"OS/2-32,");break;
253 case VOS_NT
:fprintf(stderr
,"NT,");break;
256 fprintf(stderr
,"UNKNOWN(%ld),",vffi
->dwFileOS
&0xFFFF0000);break;
258 switch (vffi
->dwFileOS
& 0xFFFF) {
259 case VOS__BASE
:fprintf(stderr
,"BASE");break;
260 case VOS__WINDOWS16
:fprintf(stderr
,"WIN16");break;
261 case VOS__WINDOWS32
:fprintf(stderr
,"WIN32");break;
262 case VOS__PM16
:fprintf(stderr
,"PM16");break;
263 case VOS__PM32
:fprintf(stderr
,"PM32");break;
264 default:fprintf(stderr
,"UNKNOWN(%ld)",vffi
->dwFileOS
&0xFFFF);break;
266 switch (vffi
->dwFileType
) {
269 fprintf(stderr
,"filetype=Unknown(%ld)",vffi
->dwFileType
);
271 case VFT_APP
:fprintf(stderr
,"filetype=APP");break;
272 case VFT_DLL
:fprintf(stderr
,"filetype=DLL");break;
274 fprintf(stderr
,"filetype=DRV,");
275 switch(vffi
->dwFileSubtype
) {
278 fprintf(stderr
,"UNKNOWN(%ld)",vffi
->dwFileSubtype
);
280 case VFT2_DRV_PRINTER
:
281 fprintf(stderr
,"PRINTER");
283 case VFT2_DRV_KEYBOARD
:
284 fprintf(stderr
,"KEYBOARD");
286 case VFT2_DRV_LANGUAGE
:
287 fprintf(stderr
,"LANGUAGE");
289 case VFT2_DRV_DISPLAY
:
290 fprintf(stderr
,"DISPLAY");
293 fprintf(stderr
,"MOUSE");
295 case VFT2_DRV_NETWORK
:
296 fprintf(stderr
,"NETWORK");
298 case VFT2_DRV_SYSTEM
:
299 fprintf(stderr
,"SYSTEM");
301 case VFT2_DRV_INSTALLABLE
:
302 fprintf(stderr
,"INSTALLABLE");
305 fprintf(stderr
,"SOUND");
308 fprintf(stderr
,"COMM");
310 case VFT2_DRV_INPUTMETHOD
:
311 fprintf(stderr
,"INPUTMETHOD");
316 fprintf(stderr
,"filetype=FONT.");
317 switch (vffi
->dwFileSubtype
) {
319 fprintf(stderr
,"UNKNOWN(%ld)",vffi
->dwFileSubtype
);
321 case VFT2_FONT_RASTER
:fprintf(stderr
,"RASTER");break;
322 case VFT2_FONT_VECTOR
:fprintf(stderr
,"VECTOR");break;
323 case VFT2_FONT_TRUETYPE
:fprintf(stderr
,"TRUETYPE");break;
326 case VFT_VXD
:fprintf(stderr
,"filetype=VXD");break;
327 case VFT_STATIC_LIB
:fprintf(stderr
,"filetype=STATIC_LIB");break;
329 fprintf(stderr
,"filedata=%lx.%lx\n",vffi
->dwFileDateMS
,vffi
->dwFileDateLS
);
334 GetFileVersionInfo(LPCSTR filename
,DWORD handle
,DWORD datasize
,LPVOID data
) {
335 fprintf(stderr
,"GetFileVersionInfo(%s,%ld,%ld,%p)\n->",
336 filename
,handle
,datasize
,data
338 return GetFileResource(
339 filename
,VS_FILE_INFO
,VS_VERSION_INFO
,handle
,datasize
,data
345 UINT flags
,LPCSTR filename
,LPCSTR windir
,LPCSTR appdir
,
346 LPSTR curdir
,UINT
*curdirlen
,LPSTR destdir
,UINT
*destdirlen
348 fprintf(stderr
,"VerFindFile(%x,%s,%s,%s,%p,%d,%p,%d)\n",
349 flags
,filename
,windir
,appdir
,curdir
,*curdirlen
,destdir
,*destdirlen
351 strcpy(curdir
,"Z:\\ROOT\\.WINE\\");/*FIXME*/
352 *curdirlen
=strlen(curdir
);
353 strcpy(destdir
,"Z:\\ROOT\\.WINE\\");/*FIXME*/
354 *destdirlen
=strlen(destdir
);
360 UINT flags
,LPCSTR srcfilename
,LPCSTR destfilename
,LPCSTR srcdir
,
361 LPCSTR destdir
,LPSTR tmpfile
,UINT
*tmpfilelen
363 fprintf(stderr
,"VerInstallFile(%x,%s,%s,%s,%s,%p,%d)\n",
364 flags
,srcfilename
,destfilename
,srcdir
,destdir
,tmpfile
,*tmpfilelen
369 /* FIXME: This table should, of course, be language dependend */
370 static struct map_id2str
{
375 {0x0402,"Bulgarisch"},
376 {0x0403,"Katalanisch"},
377 {0x0404,"Traditionales Chinesisch"},
378 {0x0405,"Tschecisch"},
381 {0x0408,"Griechisch"},
382 {0x0409,"Amerikanisches Englisch"},
383 {0x040A,"Kastilisches Spanisch"},
385 {0x040C,"Französisch"},
386 {0x040D,"Hebräisch"},
387 {0x040E,"Ungarisch"},
388 {0x040F,"Isländisch"},
389 {0x0410,"Italienisch"},
390 {0x0411,"Japanisch"},
391 {0x0412,"Koreanisch"},
392 {0x0413,"Niederländisch"},
393 {0x0414,"Norwegisch-Bokmal"},
395 {0x0416,"Brasilianisches Portugiesisch"},
396 {0x0417,"Rätoromanisch"},
397 {0x0418,"Rumänisch"},
399 {0x041A,"Kroatoserbisch (lateinisch)"},
400 {0x041B,"Slowenisch"},
401 {0x041C,"Albanisch"},
402 {0x041D,"Schwedisch"},
407 {0x0804,"Vereinfachtes Chinesisch"},
408 {0x0807,"Schweizerdeutsch"},
409 {0x0809,"Britisches Englisch"},
410 {0x080A,"Mexikanisches Spanisch"},
411 {0x080C,"Belgisches Französisch"},
412 {0x0810,"Schweizerisches Italienisch"},
413 {0x0813,"Belgisches Niederländisch"},
414 {0x0814,"Norgwegisch-Nynorsk"},
415 {0x0816,"Portugiesisch"},
416 {0x081A,"Serbokratisch (kyrillisch)"},
417 {0x0C1C,"Kanadisches Französisch"},
418 {0x100C,"Schweizerisches Französisch"},
419 {0x0000,"Unbekannt"},
424 VerLanguageName(UINT langid
,LPSTR langname
,UINT langnamelen
) {
427 fprintf(stderr
,"VerLanguageName(%d,%p,%d)\n",langid
,langname
,langnamelen
);
428 for (i
=0;languages
[i
].langid
!=0;i
++)
429 if (langid
==languages
[i
].langid
)
431 strncpy(langname
,languages
[i
].langname
,langnamelen
);
432 langname
[langnamelen
-1]='\0';
433 return strlen(languages
[i
].langname
);
439 /* in memory structure... */
440 char name
[1]; /* padded to dword alignment */
442 char data[datalen]; padded to dword alignemnt
443 BYTE subdirdata[]; until nextoff
448 _find_data(BYTE
*block
,LPCSTR str
) {
453 while (*str
&& *str
=='\\')
455 if (NULL
!=(nextslash
=strchr(str
,'\\')))
456 substrlen
=nextslash
-str
;
458 substrlen
=strlen(str
);
459 if (nextslash
!=NULL
) {
460 while (*nextslash
&& *nextslash
=='\\')
468 db
=(struct db
*)block
;
469 fprintf(stderr
,"db=%p,db->nextoff=%d,db->datalen=%d,db->name=%s,db->data=%s\n",
470 db
,db
->nextoff
,db
->datalen
,db
->name
,(char*)((char*)db
+4+((strlen(db
->name
)+4)&~3))
475 fprintf(stderr
,"comparing with %s\n",db
->name
);
476 if (!strncmp(db
->name
,str
,substrlen
)) {
479 block
+4+((strlen(db
->name
)+4)&~3)+((db
->datalen
+3)&~3)
485 block
=block
+((db
->nextoff
+3)&~3);
490 /* take care, 'buffer' is NOT a SEGPTR, it just points to one */
492 VerQueryValue(SEGPTR segblock
,LPCSTR subblock
,SEGPTR
*buffer
,UINT
*buflen
) {
493 BYTE
*block
=PTR_SEG_TO_LIN(segblock
),*b
;
497 fprintf(stderr
,"VerQueryValue(%p,%s,%p,%d)\n",
498 block
,subblock
,buffer
,*buflen
500 s
=(char*)xmalloc(strlen("VS_VERSION_INFO")+strlen(subblock
)+1);
501 strcpy(s
,"VS_VERSION_INFO");strcat(s
,subblock
);
502 b
=_find_data(block
,s
);
508 *buflen
= db
->datalen
;
509 /* let b point to data area */
510 b
= b
+4+((strlen(db
->name
)+4)&3);
511 /* now look up what the resp. SEGPTR would be ...
512 * we could use MAKE_SEGPTR , but we don't need to
514 *buffer
= (b
-block
)+segblock
;
515 fprintf(stderr
," -> %s=%s\n",subblock
,b
);
520 20 GETFILEVERSIONINFORAW
521 21 VERFTHK_THUNKDATA16
522 22 VERTHKSL_THUNKDATA16