Release 960428
[wine/multimedia.git] / misc / ver.c
blobb390fd9b87da9fe54d990a7c91584ab8d056b086
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 "stackframe.h" /* MAKE_SEGPTR */
19 #include "stddebug.h"
20 #include "debug.h"
21 #include "xmalloc.h"
22 #include "winreg.h"
24 #define LZREAD(what) if (sizeof(*what)!=LZRead(lzfd,MAKE_SEGPTR(what),sizeof(*what))) return 0;
26 int
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)))
32 return 0;
33 if (mzh.mz_magic!=MZ_SIGNATURE)
34 return 0;
35 LZSeek(lzfd,mzh.ne_offset,SEEK_SET);
36 LZREAD(nehd);
37 if (nehd->ne_magic == NE_SIGNATURE) {
38 LZSeek(lzfd,mzh.ne_offset,SEEK_SET);
39 return 1;
41 /* must handle PE files too. Later. */
42 return 0;
46 int
47 find_ne_resource(
48 HFILE lzfd,struct ne_header_s *nehd,SEGPTR typeid,SEGPTR resid,
49 BYTE **resdata,int *reslen,DWORD *off
50 ) {
51 NE_TYPEINFO ti;
52 NE_NAMEINFO ni;
53 int i;
54 WORD shiftcount;
55 DWORD nehdoffset;
57 nehdoffset=LZSeek(lzfd,nehd->resource_tab_offset,SEEK_CUR);
58 LZREAD(&shiftcount);
59 dprintf_resource(stderr,"shiftcount is %d\n",shiftcount);
60 dprintf_resource(stderr,"reading resource typeinfo dir.\n");
62 if (!HIWORD(typeid)) typeid = (SEGPTR)((WORD)typeid | 0x8000);
63 if (!HIWORD(resid)) resid = (SEGPTR)((WORD)resid | 0x8000);
64 while (1) {
65 int skipflag;
67 LZREAD(&ti);
68 if (!ti.type_id)
69 return 0;
70 dprintf_resource(stderr," ti.typeid =%04x,count=%d\n",ti.type_id,ti.count);
71 skipflag=0;
72 if (!HIWORD(typeid)) {
73 if ((ti.type_id&0x8000)&&(typeid!=ti.type_id))
74 skipflag=1;
75 } else {
76 if (ti.type_id & 0x8000) {
77 skipflag=1;
78 } else {
79 BYTE len;
80 char *str;
81 DWORD whereleft;
83 whereleft=LZSeek(
84 lzfd,
85 nehdoffset+nehd->resource_tab_offset+ti.type_id,
86 SEEK_SET
88 LZREAD(&len);
89 str=xmalloc(len);
90 if (len!=LZRead(lzfd,MAKE_SEGPTR(str),len))
91 return 0;
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)))
96 skipflag=1;
97 free(str);
98 LZSeek(lzfd,whereleft,SEEK_SET);
101 if (skipflag) {
102 LZSeek(lzfd,ti.count*sizeof(ni),SEEK_CUR);
103 continue;
105 for (i=0;i<ti.count;i++) {
106 WORD *rdata;
107 int len;
109 LZREAD(&ni);
110 dprintf_resource(stderr," ni.id=%4x,offset=%d,length=%d\n",
111 ni.id,ni.offset,ni.length
113 skipflag=1;
114 if (!HIWORD(resid)) {
115 if (ni.id == resid)
116 skipflag=0;
117 } else {
118 if (!(ni.id & 0x8000)) {
119 BYTE len;
120 char *str;
121 DWORD whereleft;
123 whereleft=LZSeek(
124 lzfd,
125 nehdoffset+nehd->resource_tab_offset+ni.id,
126 SEEK_SET
128 LZREAD(&len);
129 str=xmalloc(len);
130 if (len!=LZRead(lzfd,MAKE_SEGPTR(str),len))
131 return 0;
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)))
136 skipflag=0;
137 free(str);
138 LZSeek(lzfd,whereleft,SEEK_SET);
141 if (skipflag)
142 continue;
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)) {
148 free(rdata);
149 return 0;
151 dprintf_resource(stderr,"resource found.\n");
152 *resdata= (BYTE*)rdata;
153 *reslen = len;
154 return 1;
159 DWORD
160 GetFileResourceSize(LPCSTR filename,SEGPTR restype,SEGPTR resid,LPDWORD off) {
161 HFILE lzfd;
162 OFSTRUCT ofs;
163 BYTE *resdata;
164 int reslen;
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);
171 if (lzfd==0)
172 return 0;
173 if (!read_ne_header(lzfd,&nehd)) {
174 LZClose(lzfd);
175 return 0;
177 if (!find_ne_resource(lzfd,&nehd,restype,resid,&resdata,&reslen,off)) {
178 LZClose(lzfd);
179 return 0;
181 free(resdata);
182 LZClose(lzfd);
183 return reslen;
186 DWORD
187 GetFileResource(LPCSTR filename,SEGPTR restype,SEGPTR resid,
188 DWORD off,DWORD datalen,LPVOID data
190 HFILE lzfd;
191 OFSTRUCT ofs;
192 BYTE *resdata;
193 int reslen;
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);
200 if (lzfd==0)
201 return 0;
202 if (!off) {
203 if (!read_ne_header(lzfd,&nehd)) {
204 LZClose(lzfd);
205 return 0;
207 if (!find_ne_resource(lzfd,&nehd,restype,resid,&resdata,&reslen,&off)) {
208 LZClose(lzfd);
209 return 0;
211 free(resdata);
213 LZSeek(lzfd,off,SEEK_SET);
214 if (reslen>datalen)
215 reslen=datalen;
216 LZRead(lzfd,MAKE_SEGPTR(data),reslen);
217 LZClose(lzfd);
218 return reslen;
221 DWORD
222 GetFileVersionInfoSize(LPCSTR filename,LPDWORD handle) {
223 DWORD len,ret;
224 BYTE buf[72];
225 VS_FIXEDFILEINFO *vffi;
227 fprintf(stderr,"GetFileVersionInfoSize(%s,%p)\n",filename,handle);
229 len=GetFileResourceSize(filename,VS_FILE_INFO,VS_VERSION_INFO,handle);
230 if (!len)
231 return 0;
232 ret=GetFileResource(
233 filename,VS_FILE_INFO,VS_VERSION_INFO,*handle,sizeof(buf),buf
235 if (!ret)
236 return 0;
238 vffi=(VS_FIXEDFILEINFO*)(buf+0x14);
239 if (vffi->dwSignature != VS_FFI_SIGNATURE)
240 return 0;
241 if (*(WORD*)buf < len)
242 len = *(WORD*)buf;
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;
254 case VOS_UNKNOWN:
255 default:
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) {
267 default:
268 case VFT_UNKNOWN:
269 fprintf(stderr,"filetype=Unknown(%ld)",vffi->dwFileType);
270 break;
271 case VFT_APP:fprintf(stderr,"filetype=APP");break;
272 case VFT_DLL:fprintf(stderr,"filetype=DLL");break;
273 case VFT_DRV:
274 fprintf(stderr,"filetype=DRV,");
275 switch(vffi->dwFileSubtype) {
276 default:
277 case VFT2_UNKNOWN:
278 fprintf(stderr,"UNKNOWN(%ld)",vffi->dwFileSubtype);
279 break;
280 case VFT2_DRV_PRINTER:
281 fprintf(stderr,"PRINTER");
282 break;
283 case VFT2_DRV_KEYBOARD:
284 fprintf(stderr,"KEYBOARD");
285 break;
286 case VFT2_DRV_LANGUAGE:
287 fprintf(stderr,"LANGUAGE");
288 break;
289 case VFT2_DRV_DISPLAY:
290 fprintf(stderr,"DISPLAY");
291 break;
292 case VFT2_DRV_MOUSE:
293 fprintf(stderr,"MOUSE");
294 break;
295 case VFT2_DRV_NETWORK:
296 fprintf(stderr,"NETWORK");
297 break;
298 case VFT2_DRV_SYSTEM:
299 fprintf(stderr,"SYSTEM");
300 break;
301 case VFT2_DRV_INSTALLABLE:
302 fprintf(stderr,"INSTALLABLE");
303 break;
304 case VFT2_DRV_SOUND:
305 fprintf(stderr,"SOUND");
306 break;
307 case VFT2_DRV_COMM:
308 fprintf(stderr,"COMM");
309 break;
310 case VFT2_DRV_INPUTMETHOD:
311 fprintf(stderr,"INPUTMETHOD");
312 break;
314 break;
315 case VFT_FONT:
316 fprintf(stderr,"filetype=FONT.");
317 switch (vffi->dwFileSubtype) {
318 default:
319 fprintf(stderr,"UNKNOWN(%ld)",vffi->dwFileSubtype);
320 break;
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;
325 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);
330 return len;
333 DWORD
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
343 DWORD
344 VerFindFile(
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);
355 return 0;
358 DWORD
359 VerInstallFile(
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
366 return VIF_SRCOLD;
369 /* FIXME: This table should, of course, be language dependend */
370 static struct map_id2str {
371 UINT langid;
372 char *langname;
373 } languages[]={
374 {0x0401,"Arabisch"},
375 {0x0402,"Bulgarisch"},
376 {0x0403,"Katalanisch"},
377 {0x0404,"Traditionales Chinesisch"},
378 {0x0405,"Tschecisch"},
379 {0x0406,"Dänisch"},
380 {0x0407,"Deutsch"},
381 {0x0408,"Griechisch"},
382 {0x0409,"Amerikanisches Englisch"},
383 {0x040A,"Kastilisches Spanisch"},
384 {0x040B,"Finnisch"},
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"},
394 {0x0415,"Polnisch"},
395 {0x0416,"Brasilianisches Portugiesisch"},
396 {0x0417,"Rätoromanisch"},
397 {0x0418,"Rumänisch"},
398 {0x0419,"Russisch"},
399 {0x041A,"Kroatoserbisch (lateinisch)"},
400 {0x041B,"Slowenisch"},
401 {0x041C,"Albanisch"},
402 {0x041D,"Schwedisch"},
403 {0x041E,"Thai"},
404 {0x041F,"Türkisch"},
405 {0x0420,"Urdu"},
406 {0x0421,"Bahasa"},
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"},
423 DWORD
424 VerLanguageName(UINT langid,LPSTR langname,UINT langnamelen) {
425 int i;
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)
430 break;
431 strncpy(langname,languages[i].langname,langnamelen);
432 langname[langnamelen-1]='\0';
433 return strlen(languages[i].langname);
436 struct db {
437 WORD nextoff;
438 WORD datalen;
439 /* in memory structure... */
440 char name[1]; /* padded to dword alignment */
441 /* ....
442 char data[datalen]; padded to dword alignemnt
443 BYTE subdirdata[]; until nextoff
447 static BYTE*
448 _find_data(BYTE *block,LPCSTR str) {
449 char *nextslash;
450 int substrlen;
451 struct db *db;
453 while (*str && *str=='\\')
454 str++;
455 if (NULL!=(nextslash=strchr(str,'\\')))
456 substrlen=nextslash-str;
457 else
458 substrlen=strlen(str);
459 if (nextslash!=NULL) {
460 while (*nextslash && *nextslash=='\\')
461 nextslash++;
462 if (!*nextslash)
463 nextslash=NULL;
467 while (1) {
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))
472 if (!db->nextoff)
473 return NULL;
475 fprintf(stderr,"comparing with %s\n",db->name);
476 if (!strncmp(db->name,str,substrlen)) {
477 if (nextslash)
478 return _find_data(
479 block+4+((strlen(db->name)+4)&~3)+((db->datalen+3)&~3)
480 ,nextslash
482 else
483 return block;
485 block=block+((db->nextoff+3)&~3);
490 /* take care, 'buffer' is NOT a SEGPTR, it just points to one */
491 DWORD
492 VerQueryValue(SEGPTR segblock,LPCSTR subblock,SEGPTR *buffer,UINT *buflen) {
493 BYTE *block=PTR_SEG_TO_LIN(segblock),*b;
494 struct db *db;
495 char *s;
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);
503 if (b==NULL) {
504 *buflen=0;
505 return 0;
507 db=(struct db*)b;
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);
516 return 1;
520 20 GETFILEVERSIONINFORAW
521 21 VERFTHK_THUNKDATA16
522 22 VERTHKSL_THUNKDATA16