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) LZSeek32(lzfd, 0, SEEK_CUR);
28 /******************************************************************************
31 * char const * prologue,
32 * char const * teststring,
33 * char const * epilogue )
35 * This function will print via dprintf_ver to stddeb the prologue string,
36 * followed by the address of teststring and the string it contains if
37 * teststring is non-null or "(null)" otherwise, and then the epilogue
41 * 30-May-1997 Dave Cuthbert (dacut@ece.cmu.edu)
42 * Original implementation as dprintf[_]ver_string
43 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
44 * Fixed problem that caused bug with tools/make_debug -- renaming
45 * this function should fix the problem.
47 *****************************************************************************/
49 static void ver_dstring(
50 char const * prologue
,
51 char const * teststring
,
52 char const * epilogue
)
54 dprintf_ver(stddeb
, "%s", prologue
);
57 dprintf_ver(stddeb
, "%p (\"%s\")", (void const *) teststring
,
60 dprintf_ver(stddeb
, "(null)");
62 dprintf_ver(stddeb
, "%s", epilogue
);
67 /******************************************************************************
69 * int testFileExistence(
73 * Tests whether a given path/file combination exists. If the file does
74 * not exist, the return value is zero. If it does exist, the return
78 * 30-May-1997 Dave Cuthbert (dacut@ece.cmu.edu)
79 * Original implementation
81 *****************************************************************************/
83 static int testFileExistence(
92 fileinfo
.cBytes
= sizeof(OFSTRUCT
);
94 strcpy(filename
, path
);
95 filenamelen
= strlen(filename
);
97 /* Add a trailing \ if necessary */
99 if(filename
[filenamelen
- 1] != '\\')
100 strcat(filename
, "\\");
102 else /* specify the current directory */
103 strcpy(filename
, ".\\");
105 /* Create the full pathname */
106 strcat(filename
, file
);
108 if(OpenFile32(filename
, &fileinfo
, OF_EXIST
) == HFILE_ERROR32
)
116 /******************************************************************************
118 * int testFileExclusiveExistence(
120 * char const * file )
122 * Tests whether a given path/file combination exists and ensures that no
123 * other programs have handles to the given file. If the file does not
124 * exist or is open, the return value is zero. If it does exist, the
125 * return value is non-zero.
128 * 30-May-1997 Dave Cuthbert (dacut@ece.cmu.edu)
129 * Original implementation
131 *****************************************************************************/
133 static int testFileExclusiveExistence(
142 fileinfo
.cBytes
= sizeof(OFSTRUCT
);
144 strcpy(filename
, path
);
145 filenamelen
= strlen(filename
);
147 /* Add a trailing \ if necessary */
149 if(filename
[filenamelen
- 1] != '\\')
150 strcat(filename
, "\\");
152 else /* specify the current directory */
153 strcpy(filename
, ".\\");
155 /* Create the full pathname */
156 strcat(filename
, file
);
158 if(OpenFile32(filename
, &fileinfo
, OF_EXIST
| OF_SHARE_EXCLUSIVE
) ==
169 read_ne_header(HFILE32 lzfd
,LPIMAGE_OS2_HEADER nehd
) {
170 IMAGE_DOS_HEADER mzh
;
172 LZSeek32(lzfd
,0,SEEK_SET
);
173 if (sizeof(mzh
)!=LZRead32(lzfd
,&mzh
,sizeof(mzh
)))
175 if (mzh
.e_magic
!=IMAGE_DOS_SIGNATURE
)
177 LZSeek32(lzfd
,mzh
.e_lfanew
,SEEK_SET
);
179 if (nehd
->ne_magic
== IMAGE_OS2_SIGNATURE
) {
180 LZSeek32(lzfd
,mzh
.e_lfanew
,SEEK_SET
);
183 fprintf(stderr
,"misc/ver.c:read_ne_header:can't handle PE files yet.\n");
184 /* must handle PE files too. Later. */
191 HFILE32 lzfd
,LPIMAGE_OS2_HEADER nehd
,SEGPTR
typeid,SEGPTR resid
,
192 BYTE
**resdata
,int *reslen
,DWORD
*off
200 nehdoffset
= LZTELL(lzfd
);
201 LZSeek32(lzfd
,nehd
->resource_tab_offset
,SEEK_CUR
);
203 dprintf_ver(stddeb
,"shiftcount is %d\n",shiftcount
);
204 dprintf_ver(stddeb
,"reading resource typeinfo dir.\n");
206 if (!HIWORD(typeid)) typeid = (SEGPTR
)(LOWORD(typeid) | 0x8000);
207 if (!HIWORD(resid
)) resid
= (SEGPTR
)(LOWORD(resid
) | 0x8000);
214 dprintf_ver(stddeb
," ti.typeid =%04x,count=%d\n",ti
.type_id
,ti
.count
);
216 if (!HIWORD(typeid)) {
217 if ((ti
.type_id
&0x8000)&&(typeid!=ti
.type_id
))
220 if (ti
.type_id
& 0x8000) {
227 whereleft
= LZTELL(lzfd
);
230 nehdoffset
+nehd
->resource_tab_offset
+ti
.type_id
,
235 if (len
!=LZRead32(lzfd
,str
,len
))
237 dprintf_ver(stddeb
,"read %s to compare it with %s\n",
238 str
,(char*)PTR_SEG_TO_LIN(typeid)
240 if (lstrcmpi32A(str
,(char*)PTR_SEG_TO_LIN(typeid)))
243 LZSeek32(lzfd
,whereleft
,SEEK_SET
);
247 LZSeek32(lzfd
,ti
.count
*sizeof(ni
),SEEK_CUR
);
250 for (i
=0;i
<ti
.count
;i
++) {
255 dprintf_ver(stddeb
," ni.id=%4x,offset=%d,length=%d\n",
256 ni
.id
,ni
.offset
,ni
.length
259 if (!HIWORD(resid
)) {
263 if (!(ni
.id
& 0x8000)) {
268 whereleft
= LZTELL(lzfd
);
271 nehdoffset
+nehd
->resource_tab_offset
+ni
.id
,
276 if (len
!=LZRead32(lzfd
,str
,len
))
278 dprintf_ver(stddeb
,"read %s to compare it with %s\n",
279 str
,(char*)PTR_SEG_TO_LIN(typeid)
281 if (!lstrcmpi32A(str
,(char*)PTR_SEG_TO_LIN(typeid)))
284 LZSeek32(lzfd
,whereleft
,SEEK_SET
);
289 LZSeek32(lzfd
,((int)ni
.offset
<<shiftcount
),SEEK_SET
);
290 *off
= (int)ni
.offset
<<shiftcount
;
291 len
= ni
.length
<<shiftcount
;
292 rdata
=(WORD
*)xmalloc(len
);
293 if (len
!=LZRead32(lzfd
,rdata
,len
)) {
297 dprintf_ver(stddeb
,"resource found.\n");
298 *resdata
= (BYTE
*)rdata
;
305 /* GetFileResourceSize [VER.2] */
307 GetFileResourceSize(LPCSTR filename
,SEGPTR restype
,SEGPTR resid
,LPDWORD off
) {
312 IMAGE_OS2_HEADER nehd
;
314 dprintf_ver(stddeb
,"GetFileResourceSize(%s,%lx,%lx,%p)\n",
315 filename
,(LONG
)restype
,(LONG
)resid
,off
317 lzfd
=LZOpenFile32A(filename
,&ofs
,OF_READ
);
320 if (!read_ne_header(lzfd
,&nehd
)) {
324 if (!find_ne_resource(lzfd
,&nehd
,restype
,resid
,&resdata
,&reslen
,off
)) {
333 /* GetFileResource [VER.3] */
335 GetFileResource(LPCSTR filename
,SEGPTR restype
,SEGPTR resid
,
336 DWORD off
,DWORD datalen
,LPVOID data
342 IMAGE_OS2_HEADER nehd
;
343 dprintf_ver(stddeb
,"GetFileResource(%s,%lx,%lx,%ld,%ld,%p)\n",
344 filename
,(LONG
)restype
,(LONG
)resid
,off
,datalen
,data
347 lzfd
=LZOpenFile32A(filename
,&ofs
,OF_READ
);
351 if (!read_ne_header(lzfd
,&nehd
)) {
355 if (!find_ne_resource(lzfd
,&nehd
,restype
,resid
,&resdata
,&reslen
,&off
)) {
361 LZSeek32(lzfd
,off
,SEEK_SET
);
364 LZRead32(lzfd
,data
,reslen
);
369 /* GetFileVersionInfoSize [VER.6] */
371 GetFileVersionInfoSize16(LPCSTR filename
,LPDWORD handle
) {
374 VS_FIXEDFILEINFO
*vffi
;
376 dprintf_ver(stddeb
,"GetFileVersionInfoSize16(%s,%p)\n",filename
,handle
);
377 len
=GetFileResourceSize(filename
,VS_FILE_INFO
,VS_VERSION_INFO
,handle
);
381 filename
,VS_FILE_INFO
,VS_VERSION_INFO
,*handle
,sizeof(buf
),buf
386 vffi
=(VS_FIXEDFILEINFO
*)(buf
+0x14);
387 if (vffi
->dwSignature
!= VS_FFI_SIGNATURE
)
389 if (*(WORD
*)buf
< len
)
391 dprintf_ver(stddeb
,"->strucver=%ld.%ld,filever=%ld.%ld,productver=%ld.%ld,flagmask=%lx,flags=%lx,OS=",
392 (vffi
->dwStrucVersion
>>16),vffi
->dwStrucVersion
&0xFFFF,
393 vffi
->dwFileVersionMS
,vffi
->dwFileVersionLS
,
394 vffi
->dwProductVersionMS
,vffi
->dwProductVersionLS
,
395 vffi
->dwFileFlagsMask
,vffi
->dwFileFlags
397 switch (vffi
->dwFileOS
&0xFFFF0000) {
398 case VOS_DOS
:dprintf_ver(stddeb
,"DOS,");break;
399 case VOS_OS216
:dprintf_ver(stddeb
,"OS/2-16,");break;
400 case VOS_OS232
:dprintf_ver(stddeb
,"OS/2-32,");break;
401 case VOS_NT
:dprintf_ver(stddeb
,"NT,");break;
404 dprintf_ver(stddeb
,"UNKNOWN(%ld),",vffi
->dwFileOS
&0xFFFF0000);break;
406 switch (vffi
->dwFileOS
& 0xFFFF) {
407 case VOS__BASE
:dprintf_ver(stddeb
,"BASE");break;
408 case VOS__WINDOWS16
:dprintf_ver(stddeb
,"WIN16");break;
409 case VOS__WINDOWS32
:dprintf_ver(stddeb
,"WIN32");break;
410 case VOS__PM16
:dprintf_ver(stddeb
,"PM16");break;
411 case VOS__PM32
:dprintf_ver(stddeb
,"PM32");break;
412 default:dprintf_ver(stddeb
,"UNKNOWN(%ld)",vffi
->dwFileOS
&0xFFFF);break;
414 switch (vffi
->dwFileType
) {
417 dprintf_ver(stddeb
,"filetype=Unknown(%ld)",vffi
->dwFileType
);
419 case VFT_APP
:dprintf_ver(stddeb
,"filetype=APP");break;
420 case VFT_DLL
:dprintf_ver(stddeb
,"filetype=DLL");break;
422 dprintf_ver(stddeb
,"filetype=DRV,");
423 switch(vffi
->dwFileSubtype
) {
426 dprintf_ver(stddeb
,"UNKNOWN(%ld)",vffi
->dwFileSubtype
);
428 case VFT2_DRV_PRINTER
:
429 dprintf_ver(stddeb
,"PRINTER");
431 case VFT2_DRV_KEYBOARD
:
432 dprintf_ver(stddeb
,"KEYBOARD");
434 case VFT2_DRV_LANGUAGE
:
435 dprintf_ver(stddeb
,"LANGUAGE");
437 case VFT2_DRV_DISPLAY
:
438 dprintf_ver(stddeb
,"DISPLAY");
441 dprintf_ver(stddeb
,"MOUSE");
443 case VFT2_DRV_NETWORK
:
444 dprintf_ver(stddeb
,"NETWORK");
446 case VFT2_DRV_SYSTEM
:
447 dprintf_ver(stddeb
,"SYSTEM");
449 case VFT2_DRV_INSTALLABLE
:
450 dprintf_ver(stddeb
,"INSTALLABLE");
453 dprintf_ver(stddeb
,"SOUND");
456 dprintf_ver(stddeb
,"COMM");
458 case VFT2_DRV_INPUTMETHOD
:
459 dprintf_ver(stddeb
,"INPUTMETHOD");
464 dprintf_ver(stddeb
,"filetype=FONT.");
465 switch (vffi
->dwFileSubtype
) {
467 dprintf_ver(stddeb
,"UNKNOWN(%ld)",vffi
->dwFileSubtype
);
469 case VFT2_FONT_RASTER
:dprintf_ver(stddeb
,"RASTER");break;
470 case VFT2_FONT_VECTOR
:dprintf_ver(stddeb
,"VECTOR");break;
471 case VFT2_FONT_TRUETYPE
:dprintf_ver(stddeb
,"TRUETYPE");break;
474 case VFT_VXD
:dprintf_ver(stddeb
,"filetype=VXD");break;
475 case VFT_STATIC_LIB
:dprintf_ver(stddeb
,"filetype=STATIC_LIB");break;
477 dprintf_ver(stddeb
,"filedata=%lx.%lx\n",vffi
->dwFileDateMS
,vffi
->dwFileDateLS
);
481 /* GetFileVersionInfoSize32A [VERSION.1] */
483 GetFileVersionInfoSize32A(LPCSTR filename
,LPDWORD handle
) {
484 dprintf_ver(stddeb
,"GetFileVersionInfoSize32A(%s,%p)\n",filename
,handle
);
485 return GetFileVersionInfoSize16(filename
,handle
);
488 /* GetFileVersionInfoSize32W [VERSION.2] */
489 DWORD
GetFileVersionInfoSize32W( LPCWSTR filename
, LPDWORD handle
)
491 LPSTR xfn
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
492 DWORD ret
= GetFileVersionInfoSize16( xfn
, handle
);
493 HeapFree( GetProcessHeap(), 0, xfn
);
497 /* GetFileVersionInfo [VER.7] */
499 GetFileVersionInfo16(LPCSTR filename
,DWORD handle
,DWORD datasize
,LPVOID data
) {
500 dprintf_ver(stddeb
,"GetFileVersionInfo16(%s,%ld,%ld,%p)\n->",
501 filename
,handle
,datasize
,data
503 return GetFileResource(
504 filename
,VS_FILE_INFO
,VS_VERSION_INFO
,handle
,datasize
,data
508 /* GetFileVersionInfoA [VERSION.0] */
510 GetFileVersionInfo32A(LPCSTR filename
,DWORD handle
,DWORD datasize
,LPVOID data
) {
511 return GetFileVersionInfo16(filename
,handle
,datasize
,data
);
514 /* GetFileVersionInfoW [VERSION.3] */
515 DWORD
GetFileVersionInfo32W( LPCWSTR filename
, DWORD handle
, DWORD datasize
,
518 LPSTR fn
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
519 DWORD ret
= GetFileVersionInfo16( fn
, handle
, datasize
, data
);
520 HeapFree( GetProcessHeap(), 0, fn
);
524 /*****************************************************************************
526 * VerFindFile() [VER.8]
527 * Determines where to install a file based on whether it locates another
528 * version of the file in the system. The values VerFindFile returns are
529 * used in a subsequent call to the VerInstallFile function.
532 * 30-May-1997 Dave Cuthbert (dacut@ece.cmu.edu)
533 * Reimplementation of VerFindFile from original stub.
535 ****************************************************************************/
543 UINT16
*lpuCurDirLen
,
545 UINT16
*lpuDestDirLen
)
550 unsigned int curDirSizeReq
;
551 unsigned int destDirSizeReq
;
555 /* Print out debugging information */
556 dprintf_ver(stddeb
, "VerFindFile() called with parameters:\n"
557 "\tflags = %x", flags
);
558 if(flags
& VFFF_ISSHAREDFILE
)
559 dprintf_ver(stddeb
, " (VFFF_ISSHAREDFILE)\n");
561 dprintf_ver(stddeb
, "\n");
563 ver_dstring("\tlpszFilename = ", lpszFilename
, "\n");
564 ver_dstring("\tlpszWinDir = ", lpszWinDir
, "\n");
565 ver_dstring("\tlpszAppDir = ", lpszAppDir
, "\n");
567 dprintf_ver(stddeb
, "\tlpszCurDir = %p\n", lpszCurDir
);
569 dprintf_ver(stddeb
, "\tlpuCurDirLen = %p (%u)\n",
570 lpuCurDirLen
, *lpuCurDirLen
);
572 dprintf_ver(stddeb
, "\tlpuCurDirLen = (null)\n");
574 dprintf_ver(stddeb
, "\tlpszDestDir = %p\n", lpszDestDir
);
576 dprintf_ver(stddeb
, "\tlpuDestDirLen = %p (%u)\n",
577 lpuDestDirLen
, *lpuDestDirLen
);
579 /* Figure out where the file should go; shared files default to the
585 if(flags
& VFFF_ISSHAREDFILE
&& !getuid()) {
586 GetSystemDirectory32A(destDir
, 256);
588 /* Were we given a filename? If so, try to find the file. */
590 if(testFileExistence(destDir
, lpszFilename
)) {
591 strcpy(curDir
, destDir
);
593 if(!testFileExclusiveExistence(destDir
, lpszFilename
))
594 retval
|= VFF_FILEINUSE
;
596 else if(lpszAppDir
&& testFileExistence(lpszAppDir
,
598 strcpy(curDir
, lpszAppDir
);
599 retval
|= VFF_CURNEDEST
;
601 if(!testFileExclusiveExistence(lpszAppDir
, lpszFilename
))
602 retval
|= VFF_FILEINUSE
;
606 else if(!(flags
& VFFF_ISSHAREDFILE
)) { /* not a shared file */
609 GetSystemDirectory32A(systemDir
, 256);
611 strcpy(destDir
, lpszAppDir
);
614 if(testFileExistence(lpszAppDir
, lpszFilename
)) {
615 strcpy(curDir
, lpszAppDir
);
617 if(!testFileExclusiveExistence(lpszAppDir
, lpszFilename
))
618 retval
|= VFF_FILEINUSE
;
620 else if(testFileExistence(systemDir
, lpszFilename
)) {
621 strcpy(curDir
, systemDir
);
622 retval
|= VFF_CURNEDEST
;
624 if(!testFileExclusiveExistence(systemDir
, lpszFilename
))
625 retval
|= VFF_FILEINUSE
;
631 curDirSizeReq
= strlen(curDir
) + 1;
632 destDirSizeReq
= strlen(destDir
) + 1;
636 /* Make sure that the pointers to the size of the buffers are
637 valid; if not, do NOTHING with that buffer. If that pointer
638 is valid, then make sure that the buffer pointer is valid, too! */
640 if(lpuDestDirLen
&& lpszDestDir
) {
641 if(*lpuDestDirLen
< destDirSizeReq
) {
642 retval
|= VFF_BUFFTOOSMALL
;
643 strncpy(lpszDestDir
, destDir
, *lpuDestDirLen
- 1);
644 lpszDestDir
[*lpuDestDirLen
- 1] = '\0';
647 strcpy(lpszDestDir
, destDir
);
649 *lpuDestDirLen
= destDirSizeReq
;
652 if(lpuCurDirLen
&& lpszCurDir
) {
653 if(*lpuCurDirLen
< curDirSizeReq
) {
654 retval
|= VFF_BUFFTOOSMALL
;
655 strncpy(lpszCurDir
, curDir
, *lpuCurDirLen
- 1);
656 lpszCurDir
[*lpuCurDirLen
- 1] = '\0';
659 strcpy(lpszCurDir
, curDir
);
661 *lpuCurDirLen
= curDirSizeReq
;
664 dprintf_ver(stddeb
, "VerFindFile() ret = %lu ",
668 dprintf_ver(stddeb
, "( ");
670 if(retval
& VFF_CURNEDEST
)
671 dprintf_ver(stddeb
, "VFF_CURNEDEST ");
672 if(retval
& VFF_FILEINUSE
)
673 dprintf_ver(stddeb
, "VFF_FILEINUSE ");
674 if(retval
& VFF_BUFFTOOSMALL
)
675 dprintf_ver(stddeb
, "VFF_BUFFTOOSMALL ");
677 dprintf_ver(stddeb
, ")");
680 ver_dstring("\n\t(Exit) lpszCurDir = ", lpszCurDir
, "\n");
682 dprintf_ver(stddeb
, "\t(Exit) lpuCurDirLen = %p (%u)\n",
683 lpuCurDirLen
, *lpuCurDirLen
);
685 dprintf_ver(stddeb
, "\t(Exit) lpuCurDirLen = (null)\n");
687 ver_dstring("\t(Exit) lpszDestDir = ", lpszDestDir
, "\n");
689 dprintf_ver(stddeb
, "\t(Exit) lpuDestDirLen = %p (%u)\n",
690 lpuDestDirLen
, *lpuDestDirLen
);
695 /* VerFindFileA [VERSION.5] */
698 UINT32 flags
,LPCSTR filename
,LPCSTR windir
,LPCSTR appdir
,
699 LPSTR curdir
,UINT32
*pcurdirlen
,LPSTR destdir
,UINT32
*pdestdirlen
)
701 UINT16 curdirlen
, destdirlen
;
702 DWORD ret
= VerFindFile16(flags
,filename
,windir
,appdir
,
703 curdir
,&curdirlen
,destdir
,&destdirlen
);
704 *pcurdirlen
= curdirlen
;
705 *pdestdirlen
= destdirlen
;
709 /* VerFindFileW [VERSION.6] */
712 UINT32 flags
,LPCWSTR filename
,LPCWSTR windir
,LPCWSTR appdir
,
713 LPWSTR curdir
,UINT32
*pcurdirlen
,LPWSTR destdir
,UINT32
*pdestdirlen
)
715 UINT16 curdirlen
, destdirlen
;
716 LPSTR wfn
,wwd
,wad
,wdd
,wcd
;
719 wfn
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
720 wwd
= HEAP_strdupWtoA( GetProcessHeap(), 0, windir
);
721 wad
= HEAP_strdupWtoA( GetProcessHeap(), 0, appdir
);
722 wcd
= HeapAlloc( GetProcessHeap(), 0, *pcurdirlen
);
723 wdd
= HeapAlloc( GetProcessHeap(), 0, *pdestdirlen
);
724 ret
= VerFindFile16(flags
,wfn
,wwd
,wad
,wcd
,&curdirlen
,wdd
,&destdirlen
);
725 lstrcpynAtoW(curdir
,wcd
,*pcurdirlen
);
726 lstrcpynAtoW(destdir
,wdd
,*pdestdirlen
);
727 *pcurdirlen
= strlen(wcd
);
728 *pdestdirlen
= strlen(wdd
);
729 HeapFree( GetProcessHeap(), 0, wfn
);
730 HeapFree( GetProcessHeap(), 0, wwd
);
731 HeapFree( GetProcessHeap(), 0, wad
);
732 HeapFree( GetProcessHeap(), 0, wcd
);
733 HeapFree( GetProcessHeap(), 0, wdd
);
737 /* VerInstallFile [VER.9] */
740 UINT16 flags
,LPCSTR srcfilename
,LPCSTR destfilename
,LPCSTR srcdir
,
741 LPCSTR destdir
,LPCSTR curdir
,LPSTR tmpfile
,UINT16
*tmpfilelen
)
744 DWORD ret
= VerInstallFile32A(flags
,srcfilename
,destfilename
,srcdir
,
745 destdir
,curdir
,tmpfile
,&filelen
);
747 *tmpfilelen
= filelen
;
751 /* VerInstallFileA [VERSION.7] */
753 _fetch_versioninfo(LPSTR fn
) {
759 buf
= xmalloc(alloclen
);
761 ret
= GetFileVersionInfo32A(fn
,0,alloclen
,buf
);
766 if (alloclen
<*(WORD
*)buf
) {
768 alloclen
= *(WORD
*)buf
;
769 buf
= xmalloc(alloclen
);
776 _error2vif(DWORD error
) {
778 case ERROR_ACCESS_DENIED
:
779 return VIF_ACCESSVIOLATION
;
780 case ERROR_SHARING_VIOLATION
:
781 return VIF_SHARINGVIOLATION
;
789 UINT32 flags
,LPCSTR srcfilename
,LPCSTR destfilename
,LPCSTR srcdir
,
790 LPCSTR destdir
,LPCSTR curdir
,LPSTR tmpfile
,UINT32
*tmpfilelen
)
792 char destfn
[260],tmpfn
[260],srcfn
[260];
794 DWORD attr
,ret
,xret
,tmplast
;
798 fprintf(stddeb
,"VerInstallFile(%x,%s,%s,%s,%s,%s,%p,%d)\n",
799 flags
,srcfilename
,destfilename
,srcdir
,destdir
,curdir
,tmpfile
,*tmpfilelen
802 sprintf(srcfn
,"%s\\%s",srcdir
,srcfilename
);
803 sprintf(destfn
,"%s\\%s",destdir
,destfilename
);
804 hfsrc
=LZOpenFile32A(srcfn
,&ofs
,OF_READ
);
805 if (hfsrc
==HFILE_ERROR32
)
806 return VIF_CANNOTREADSRC
;
807 sprintf(tmpfn
,"%s\\%s",destdir
,destfilename
);
808 tmplast
=strlen(destdir
)+1;
809 attr
= GetFileAttributes32A(tmpfn
);
811 if (attr
& FILE_ATTRIBUTE_READONLY
) {
813 return VIF_WRITEPROT
;
815 /* FIXME: check if file currently in use and return VIF_FILEINUSE */
818 if (flags
& VIFF_FORCEINSTALL
) {
820 sprintf(tmpfn
,"%s\\%s",destdir
,tmpfile
);
821 tmplast
= strlen(destdir
)+1;
822 attr
= GetFileAttributes32A(tmpfn
);
823 /* if it exists, it has been copied by the call before.
824 * we jump over the copy part...
831 GetTempFileName32A(destdir
,"ver",0,tmpfn
); /* should not fail ... */
832 s
=strrchr(tmpfn
,'\\');
837 hfdst
= OpenFile32(tmpfn
,&ofs
,OF_CREATE
);
838 if (hfdst
== HFILE_ERROR32
) {
840 return VIF_CANNOTCREATE
; /* | translated dos error */
842 ret
= LZCopy32(hfsrc
,hfdst
);
844 if (((long) ret
) < 0) {
845 /* translate LZ errors into VIF_xxx */
847 case LZERROR_BADINHANDLE
:
849 case LZERROR_BADVALUE
:
850 case LZERROR_UNKNOWNALG
:
851 ret
= VIF_CANNOTREADSRC
;
853 case LZERROR_BADOUTHANDLE
:
855 ret
= VIF_OUTOFMEMORY
; /* FIXME: correct? */
857 case LZERROR_GLOBALLOC
:
858 case LZERROR_GLOBLOCK
:
859 ret
= VIF_OUTOFSPACE
;
861 default: /* unknown error, should not happen */
872 if (!(flags
& VIFF_FORCEINSTALL
)) {
873 buf1
= _fetch_versioninfo(destfn
);
875 buf2
= _fetch_versioninfo(tmpfn
);
878 VS_FIXEDFILEINFO
*destvffi
,*tmpvffi
;
881 destvffi
= (VS_FIXEDFILEINFO
*)(buf1
+0x14);
882 tmpvffi
= (VS_FIXEDFILEINFO
*)(buf2
+0x14);
885 /* compare file versions */
886 if ((destvffi
->dwFileVersionMS
> tmpvffi
->dwFileVersionMS
)||
887 ((destvffi
->dwFileVersionMS
==tmpvffi
->dwFileVersionMS
)&&
888 (destvffi
->dwFileVersionLS
> tmpvffi
->dwFileVersionLS
)
891 xret
|= VIF_MISMATCH
|VIF_SRCOLD
;
892 /* compare filetypes and filesubtypes */
893 if ((destvffi
->dwFileType
!=tmpvffi
->dwFileType
) ||
894 (destvffi
->dwFileSubtype
!=tmpvffi
->dwFileSubtype
)
896 xret
|= VIF_MISMATCH
|VIF_DIFFTYPE
;
897 if (VerQueryValue32A(buf1
,"\\VarFileInfo\\Translation",(LPVOID
*)&tbuf1
,&len1
) &&
898 VerQueryValue32A(buf2
,"\\VarFileInfo\\Translation",(LPVOID
*)&tbuf2
,&len2
)
900 /* irgendwas mit tbuf1 und tbuf2 machen
901 * generiert DIFFLANG|MISMATCH
906 xret
=VIF_MISMATCH
|VIF_SRCOLD
;
911 if (*tmpfilelen
<strlen(tmpfn
+tmplast
)) {
912 xret
|=VIF_BUFTOSMALL
;
913 DeleteFile32A(tmpfn
);
915 strcpy(tmpfile
,tmpfn
+tmplast
);
916 *tmpfilelen
= strlen(tmpfn
+tmplast
)+1;
920 if (-1!=GetFileAttributes32A(destfn
))
921 if (!DeleteFile32A(destfn
)) {
922 xret
|=_error2vif(GetLastError())|VIF_CANNOTDELETE
;
923 DeleteFile32A(tmpfn
);
927 if ((!(flags
& VIFF_DONTDELETEOLD
)) &&
930 lstrcmpi32A(curdir
,destdir
)
934 sprintf(curfn
,"%s\\%s",curdir
,destfilename
);
935 if (-1!=GetFileAttributes32A(curfn
)) {
936 /* FIXME: check if in use ... if it is, VIF_CANNOTDELETECUR */
937 if (!DeleteFile32A(curfn
))
938 xret
|=_error2vif(GetLastError())|VIF_CANNOTDELETECUR
;
941 if (!MoveFile32A(tmpfn
,destfn
)) {
942 xret
|=_error2vif(GetLastError())|VIF_CANNOTRENAME
;
943 DeleteFile32A(tmpfn
);
950 /* VerInstallFileW [VERSION.8] */
953 UINT32 flags
,LPCWSTR srcfilename
,LPCWSTR destfilename
,LPCWSTR srcdir
,
954 LPCWSTR destdir
,LPCWSTR curdir
,LPWSTR tmpfile
,UINT32
*tmpfilelen
)
956 LPSTR wsrcf
,wsrcd
,wdestf
,wdestd
,wtmpf
,wcurd
;
959 wsrcf
= HEAP_strdupWtoA( GetProcessHeap(), 0, srcfilename
);
960 wsrcd
= HEAP_strdupWtoA( GetProcessHeap(), 0, srcdir
);
961 wdestf
= HEAP_strdupWtoA( GetProcessHeap(), 0, destfilename
);
962 wdestd
= HEAP_strdupWtoA( GetProcessHeap(), 0, destdir
);
963 wtmpf
= HEAP_strdupWtoA( GetProcessHeap(), 0, tmpfile
);
964 wcurd
= HEAP_strdupWtoA( GetProcessHeap(), 0, curdir
);
965 ret
= VerInstallFile32A(flags
,wsrcf
,wdestf
,wsrcd
,wdestd
,wcurd
,wtmpf
,tmpfilelen
);
967 lstrcpynAtoW(tmpfile
,wtmpf
,*tmpfilelen
);
968 HeapFree( GetProcessHeap(), 0, wsrcf
);
969 HeapFree( GetProcessHeap(), 0, wsrcd
);
970 HeapFree( GetProcessHeap(), 0, wdestf
);
971 HeapFree( GetProcessHeap(), 0, wdestd
);
972 HeapFree( GetProcessHeap(), 0, wtmpf
);
974 HeapFree( GetProcessHeap(), 0, wcurd
);
979 /* FIXME: UNICODE? */
983 /* in memory structure... */
984 char name
[1]; /* padded to dword alignment */
986 char data[datalen]; padded to dword alignment
987 BYTE subdirdata[]; until nextoff
992 _find_data(BYTE
*block
,LPCSTR str
, WORD buff_remain
) {
994 int substrlen
, inc_size
;
997 while (*str
&& *str
=='\\')
999 if (NULL
!=(nextslash
=strchr(str
,'\\')))
1000 substrlen
=nextslash
-str
;
1002 substrlen
=strlen(str
);
1003 if (nextslash
!=NULL
) {
1004 while (*nextslash
&& *nextslash
=='\\')
1012 db
=(struct db
*)block
;
1013 dprintf_ver(stddeb
,"db=%p,db->nextoff=%d,db->datalen=%d,db->name=%s,db->data=%s\n",
1014 db
,db
->nextoff
,db
->datalen
,db
->name
,(char*)((char*)db
+4+((strlen(db
->name
)+4)&~3))
1016 if ((!db
->nextoff
) || (!buff_remain
)) /* no more entries ? */
1019 dprintf_ver(stddeb
,"comparing with %s\n",db
->name
);
1020 if (!strncmp(db
->name
,str
,substrlen
)) {
1022 inc_size
= 4+((strlen(db
->name
)+4)&~3)+((db
->datalen
+3)&~3);
1024 return _find_data( block
+inc_size
,nextslash
,
1025 buff_remain
- inc_size
);
1030 inc_size
=((db
->nextoff
+3)&~3);
1031 block
=block
+inc_size
;
1032 buff_remain
=buff_remain
-inc_size
;
1036 /* VerQueryValue [VER.11] */
1037 /* take care, 'buffer' is NOT a SEGPTR, it just points to one */
1039 VerQueryValue16(SEGPTR segblock
,LPCSTR subblock
,SEGPTR
*buffer
,UINT16
*buflen
)
1041 BYTE
*block
=PTR_SEG_TO_LIN(segblock
),*b
;
1045 dprintf_ver(stddeb
,"VerQueryValue16(%p,%s,%p,%d)\n",
1046 block
,subblock
,buffer
,*buflen
1048 s
=(char*)xmalloc(strlen("VS_VERSION_INFO\\")+strlen(subblock
)+1);
1049 strcpy(s
,"VS_VERSION_INFO\\");strcat(s
,subblock
);
1050 b
=_find_data(block
, s
, *(WORD
*)block
);
1056 *buflen
= db
->datalen
;
1057 /* let b point to data area */
1058 b
= b
+4+((strlen(db
->name
)+4)&~3);
1059 /* now look up what the resp. SEGPTR would be ... */
1060 *buffer
= (b
-block
)+segblock
;
1061 dprintf_ver(stddeb
," -> %s=%s\n",subblock
,b
);
1066 VerQueryValue32A(LPVOID vblock
,LPCSTR subblock
,LPVOID
*vbuffer
,UINT32
*buflen
)
1068 BYTE
*b
,*block
=(LPBYTE
)vblock
,**buffer
=(LPBYTE
*)vbuffer
;
1072 dprintf_ver(stddeb
,"VerQueryValue32A(%p,%s,%p,%d)\n",
1073 block
,subblock
,buffer
,*buflen
1075 s
=(char*)xmalloc(strlen("VS_VERSION_INFO\\")+strlen(subblock
)+1);
1076 strcpy(s
,"VS_VERSION_INFO\\");strcat(s
,subblock
);
1077 b
=_find_data(block
, s
, *(WORD
*)block
);
1083 *buflen
= db
->datalen
;
1084 /* let b point to data area */
1085 b
= b
+4+((strlen(db
->name
)+4)&~3);
1087 dprintf_ver(stddeb
," -> %s=%s\n",subblock
,b
);
1092 VerQueryValue32W(LPVOID vblock
,LPCWSTR subblock
,LPVOID
*vbuffer
,UINT32
*buflen
)
1094 /* FIXME: hmm, we not only need to convert subblock, but also
1096 * And what about UNICODE version info?
1097 * And the NAMES of the values?
1099 BYTE
*b
,**buffer
=(LPBYTE
*)vbuffer
,*block
=(LPBYTE
)vblock
;
1103 sb
= HEAP_strdupWtoA( GetProcessHeap(), 0, subblock
);
1104 s
=(char*)xmalloc(strlen("VS_VERSION_INFO\\")+strlen(sb
)+1);
1105 strcpy(s
,"VS_VERSION_INFO\\");strcat(s
,sb
);
1106 b
=_find_data(block
, s
, *(WORD
*)block
);
1109 HeapFree( GetProcessHeap(), 0, sb
);
1113 *buflen
= db
->datalen
;
1114 /* let b point to data area */
1115 b
= b
+4+((strlen(db
->name
)+4)&~3);
1117 dprintf_ver(stddeb
," -> %s=%s\n",sb
,b
);
1118 HeapFree( GetProcessHeap(), 0, sb
);
1121 /* 20 GETFILEVERSIONINFORAW */