source: trunk/src/version/version.cpp@ 488

Last change on this file since 488 was 488, checked in by phaller, 26 years ago

Add: added ODINWRAP support plus few enhancements to VERSION

File size: 26.4 KB
Line 
1/* $Id: version.cpp,v 1.5 1999-08-12 23:33:37 phaller Exp $ */
2
3/*
4 * Win32 Version resource APIs for OS/2
5 *
6 * Implementation of VERSION.DLL - File Installer routines
7 * Copyright 1996,1997 Marcus Meissner
8 * Copyright 1997 David Cuthbert
9 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
10 *
11 * Project Odin Software License can be found in LICENSE.TXT
12 */
13
14
15#include <os2win.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <odinwrap.h>
20#include <misc.h>
21#include <unicode.h>
22#include <heapstring.h>
23#include <version.h>
24#include <lzexpand.h>
25#include <win\winreg.h>
26
27
28ODINDEBUGCHANNEL(VERSION)
29
30/*****************************************************************************
31 * Name :
32 * Purpose :
33 * Parameters:
34 * Variables :
35 * Result :
36 * Remark :
37 * Status : UNTESTED STUB
38 *
39 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
40 *****************************************************************************/
41
42VS_VERSION_INFO_STRUCT16 *VersionInfo16_FindChild(VS_VERSION_INFO_STRUCT16 *info,
43 LPCSTR szKey,
44 UINT cbKey )
45{
46 VS_VERSION_INFO_STRUCT16 *child = VersionInfo16_Children( info );
47
48 while ( (DWORD)child < (DWORD)info + info->wLength )
49 {
50 if ( !strnicmp( child->szKey, szKey, cbKey ) )
51 return child;
52
53 if (!(child->wLength)) return NULL;
54 child = VersionInfo16_Next( child );
55 }
56
57 return NULL;
58}
59
60
61/*****************************************************************************
62 * Name :
63 * Purpose :
64 * Parameters:
65 * Variables :
66 * Result :
67 * Remark :
68 * Status : UNTESTED STUB
69 *
70 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
71 *****************************************************************************/
72
73VS_VERSION_INFO_STRUCT32 *VersionInfo32_FindChild(VS_VERSION_INFO_STRUCT32 *info,
74 LPCWSTR szKey,
75 UINT cbKey )
76{
77 VS_VERSION_INFO_STRUCT32 *child = VersionInfo32_Children( info );
78
79 while ( (DWORD)child < (DWORD)info + info->wLength )
80 {
81// if ( !lstrcmpniW( child->szKey, szKey, cbKey ) )
82 if ( !lstrcmpiW( child->szKey, szKey) )
83 return child;
84
85 child = VersionInfo32_Next( child );
86 }
87
88 return NULL;
89}
90
91
92/******************************************************************************
93 *
94 * void ver_dstring(
95 * char const * prologue,
96 * char const * teststring,
97 * char const * epilogue )
98 *
99 * This function will print via dprintf[_]ver to stddeb the prologue string,
100 * followed by the address of teststring and the string it contains if
101 * teststring is non-null or "(null)" otherwise, and then the epilogue
102 * string followed by a new line.
103 *
104 * Revision history
105 * 30-May-1997 Dave Cuthbert (dacut@ece.cmu.edu)
106 * Original implementation as dprintf[_]ver_string
107 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
108 * Fixed problem that caused bug with tools/make_debug -- renaming
109 * this function should fix the problem.
110 * 15-Feb-1998 Dimitrie Paun (dimi@cs.toronto.edu)
111 * Modified it to make it print the message using only one
112 * dprintf[_]ver call.
113 *
114 *****************************************************************************/
115
116static void ver_dstring(char const * prologue,
117 char const * teststring,
118 char const * epilogue )
119{
120 dprintf(("VERSION: ver_dstring(%s, %s, %s)\n",
121 prologue,
122 teststring,
123 epilogue));
124}
125
126
127/******************************************************************************
128 *
129 * int testFileExistence(
130 * char const * path,
131 * char const * file )
132 *
133 * Tests whether a given path/file combination exists. If the file does
134 * not exist, the return value is zero. If it does exist, the return
135 * value is non-zero.
136 *
137 * Revision history
138 * 30-May-1997 Dave Cuthbert (dacut@ece.cmu.edu)
139 * Original implementation
140 *
141 *****************************************************************************/
142
143static int testFileExistence(char const * path,
144 char const * file )
145{
146 char filename[1024];
147 int filenamelen;
148 OFSTRUCT fileinfo;
149 int retval;
150
151 fileinfo.cBytes = sizeof(OFSTRUCT);
152
153 strcpy(filename, path);
154 filenamelen = strlen(filename);
155
156 /* Add a trailing \ if necessary */
157 if(filenamelen)
158 {
159 if(filename[filenamelen - 1] != '\\')
160 strcat(filename, "\\");
161 }
162 else /* specify the current directory */
163 strcpy(filename, ".\\");
164
165 /* Create the full pathname */
166 strcat(filename, file);
167
168 if(OpenFile(filename, &fileinfo, OF_EXIST) == HFILE_ERROR)
169 retval = 0;
170 else
171 retval = 1;
172
173 return retval;
174}
175
176
177/******************************************************************************
178 *
179 * int testFileExclusiveExistence(
180 * char const * path,
181 * char const * file )
182 *
183 * Tests whether a given path/file combination exists and ensures that no
184 * other programs have handles to the given file. If the file does not
185 * exist or is open, the return value is zero. If it does exist, the
186 * return value is non-zero.
187 *
188 * Revision history
189 * 30-May-1997 Dave Cuthbert (dacut@ece.cmu.edu)
190 * Original implementation
191 *
192 *****************************************************************************/
193
194static int testFileExclusiveExistence(char const * path,
195 char const * file )
196{
197 char filename[1024];
198 int filenamelen;
199 OFSTRUCT fileinfo;
200 int retval;
201
202 fileinfo.cBytes = sizeof(OFSTRUCT);
203
204 strcpy(filename, path);
205 filenamelen = strlen(filename);
206
207 /* Add a trailing \ if necessary */
208 if(filenamelen)
209 {
210 if(filename[filenamelen - 1] != '\\')
211 strcat(filename, "\\");
212 }
213 else /* specify the current directory */
214 strcpy(filename, ".\\");
215
216 /* Create the full pathname */
217 strcat(filename, file);
218
219 if(OpenFile(filename,
220 &fileinfo,
221 OF_EXIST | OF_SHARE_EXCLUSIVE) == HFILE_ERROR)
222 retval = 0;
223 else
224 retval = 1;
225
226 return retval;
227}
228
229
230static LPBYTE _fetch_versioninfo(LPSTR fn,VS_FIXEDFILEINFO **vffi)
231{
232 DWORD alloclen;
233 LPBYTE buf;
234 DWORD ret;
235
236 alloclen = 1000;
237 buf = (LPBYTE)malloc(alloclen);
238
239 while (1)
240 {
241 ret = GetFileVersionInfoA(fn,
242 0,
243 alloclen,
244 buf);
245 if (!ret)
246 {
247 free(buf);
248 return 0;
249 }
250
251 if (alloclen<*(WORD*)buf)
252 {
253 free(buf);
254 alloclen = *(WORD*)buf;
255 buf = (LPBYTE)malloc(alloclen);
256 }
257 else
258 {
259 *vffi = (VS_FIXEDFILEINFO*)(buf+0x14);
260
261 if ((*vffi)->dwSignature == 0x004f0049) /* hack to detect unicode */
262 *vffi = (VS_FIXEDFILEINFO*)(buf+0x28);
263
264 if ((*vffi)->dwSignature != VS_FFI_SIGNATURE)
265 dprintf(("VERSION: _fetch_versioninfo: Bad VS_FIXEDFILEINFO signature 0x%08lx\n",
266 (*vffi)->dwSignature));
267
268 return buf;
269 }
270 }
271}
272
273static DWORD _error2vif(DWORD error)
274{
275 switch (error)
276 {
277 case ERROR_ACCESS_DENIED:
278 return VIF_ACCESSVIOLATION;
279
280 case ERROR_SHARING_VIOLATION:
281 return VIF_SHARINGVIOLATION;
282
283 default:
284 return 0;
285 }
286}
287
288
289
290/*****************************************************************************
291 * Name :
292 * Purpose :
293 * Parameters:
294 * Variables :
295 * Result :
296 * Remark :
297 * Status : UNTESTED STUB
298 *
299 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
300 *****************************************************************************/
301
302ODINFUNCTION4(BOOL,GetFileVersionInfoA,LPSTR, lpszFile,
303 DWORD, dwHandle,
304 DWORD, cbBuf,
305 LPVOID,lpvData)
306{
307 return GetVersionStruct((char *)lpszFile,
308 (char *)lpvData,
309 cbBuf);
310}
311
312
313/*****************************************************************************
314 * Name :
315 * Purpose :
316 * Parameters:
317 * Variables :
318 * Result :
319 * Remark :
320 * Status : UNTESTED STUB
321 *
322 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
323 *****************************************************************************/
324
325ODINFUNCTION4(BOOL,GetFileVersionInfoW,LPWSTR, lpszFile,
326 DWORD, dwHandle,
327 DWORD, cbBuf,
328 LPVOID, lpvData)
329{
330 BOOL rc;
331 char *astring = UnicodeToAsciiString(lpszFile);
332
333 rc = GetVersionStruct(astring, (char *)lpvData, cbBuf);
334 FreeAsciiString(astring);
335 return(rc);
336}
337
338
339/*****************************************************************************
340 * Name :
341 * Purpose :
342 * Parameters:
343 * Variables :
344 * Result :
345 * Remark :
346 * Status : UNTESTED STUB
347 *
348 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
349 *****************************************************************************/
350
351ODINFUNCTION2(DWORD,GetFileVersionInfoSizeA,LPSTR, lpszFile,
352 LPDWORD, lpdwHandle)
353{
354 if(lpdwHandle)
355 lpdwHandle = 0;
356
357 return GetVersionSize(lpszFile);
358}
359
360
361/*****************************************************************************
362 * Name :
363 * Purpose :
364 * Parameters:
365 * Variables :
366 * Result :
367 * Remark :
368 * Status : UNTESTED STUB
369 *
370 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
371 *****************************************************************************/
372
373ODINFUNCTION2(DWORD,GetFileVersionInfoSizeW,LPWSTR, lpszFile,
374 LPDWORD, lpdwHandle)
375{
376 char *astring = UnicodeToAsciiString((LPWSTR)lpszFile);
377 DWORD rc;
378
379
380 if(lpdwHandle)
381 lpdwHandle = 0;
382
383 rc = GetVersionSize(astring);
384 FreeAsciiString(astring);
385 return(rc);
386}
387
388
389
390/*****************************************************************************
391 * Name :
392 * Purpose :
393 * Parameters:
394 * Variables :
395 * Result :
396 * Remark :
397 * Status : UNTESTED STUB
398 *
399 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
400 *****************************************************************************/
401
402ODINFUNCTION4(BOOL,VerQueryValueW, LPVOID, pBlock,
403 LPWSTR, lpSubBlock,
404 LPVOID*, lplpBuffer,
405 UINT*, puLen)
406{
407 VS_VERSION_INFO_STRUCT32 *info = (VS_VERSION_INFO_STRUCT32 *)pBlock;
408 if ( VersionInfoIs16( info ) )
409 {
410 dprintf(("VERSION: called on NE resource!\n"));
411 return FALSE;
412 }
413
414 while ( *lpSubBlock )
415 {
416 /* Find next path component */
417 LPCWSTR lpNextSlash;
418 for ( lpNextSlash = lpSubBlock; *lpNextSlash; lpNextSlash++ )
419 if ( *lpNextSlash == '\\' )
420 break;
421
422 /* Skip empty components */
423 if ( lpNextSlash == lpSubBlock )
424 {
425 lpSubBlock++;
426 continue;
427 }
428
429 /* We have a non-empty component: search info for key */
430 info = VersionInfo32_FindChild( info, lpSubBlock, lpNextSlash-lpSubBlock );
431 if ( !info )
432 return FALSE;
433
434 /* Skip path component */
435 lpSubBlock = (LPWSTR)lpNextSlash;
436 }
437
438 /* Return value */
439 *lplpBuffer = VersionInfo32_Value( info );
440 *puLen = info->wValueLength;
441
442 return TRUE;
443}
444
445
446/*****************************************************************************
447 * Name :
448 * Purpose :
449 * Parameters:
450 * Variables :
451 * Result :
452 * Remark :
453 * Status : UNTESTED STUB
454 *
455 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
456 *****************************************************************************/
457
458ODINFUNCTION4(BOOL,VerQueryValueA,LPVOID, pBlock,
459 LPSTR, lpSubBlock,
460 LPVOID*, lplpBuffer,
461 UINT*, puLen )
462{
463 VS_VERSION_INFO_STRUCT16 *info = (VS_VERSION_INFO_STRUCT16 *)pBlock;
464 if ( !VersionInfoIs16( info ) )
465 {
466 // this is a quick hack, not much tested
467 WCHAR *ustring = (WCHAR *)malloc(strlen((char *)lpSubBlock)*2+1);
468 LPVOID ubuffer;
469 char *abuffer;
470 UINT len = *puLen * 2;
471 BOOL rc;
472
473 dprintf(("VERSION: called on PE unicode resource!\n" ));
474
475 AsciiToUnicode((char *)lpSubBlock, ustring);
476 rc = VerQueryValueW( pBlock, (LPWSTR)ustring, &ubuffer, &len);
477 if(lpSubBlock[0] == '\\' && lpSubBlock[1] == 0)
478 *lplpBuffer = ubuffer;
479 else
480 {
481 *lplpBuffer = malloc(len+1); // no free, memory leak
482 UnicodeToAsciiN((WCHAR *)ubuffer, (char *)*lplpBuffer, len);
483 }
484 *puLen = len;
485 free(ustring);
486 return rc;
487 }
488
489 while ( *lpSubBlock )
490 {
491 /* Find next path component */
492 LPCSTR lpNextSlash;
493 for ( lpNextSlash = lpSubBlock; *lpNextSlash; lpNextSlash++ )
494 if ( *lpNextSlash == '\\' )
495 break;
496
497 /* Skip empty components */
498 if ( lpNextSlash == lpSubBlock )
499 {
500 lpSubBlock++;
501 continue;
502 }
503
504 /* We have a non-empty component: search info for key */
505 info = VersionInfo16_FindChild( info, lpSubBlock, lpNextSlash-lpSubBlock );
506 if ( !info ) return FALSE;
507
508 /* Skip path component */
509 lpSubBlock = (LPSTR)lpNextSlash;
510 }
511
512 /* Return value */
513 *lplpBuffer = VersionInfo16_Value( info );
514 *puLen = info->wValueLength;
515
516 return TRUE;
517}
518
519
520
521
522/*****************************************************************************
523 *
524 * VerFindFile() [VER.8]
525 * Determines where to install a file based on whether it locates another
526 * version of the file in the system. The values VerFindFile returns are
527 * used in a subsequent call to the VerInstallFile function.
528 *
529 * Revision history:
530 * 30-May-1997 Dave Cuthbert (dacut@ece.cmu.edu)
531 * Reimplementation of VerFindFile from original stub.
532 *
533 ****************************************************************************/
534
535ODINFUNCTION8(DWORD,VerFindFileA,DWORD, flags,
536 LPSTR, lpszFilename,
537 LPSTR, lpszWinDir,
538 LPSTR, lpszAppDir,
539 LPSTR, lpszCurDir,
540 PUINT, lpuCurDirLen,
541 LPSTR, lpszDestDir,
542 PUINT, lpuDestDirLen )
543{
544 DWORD retval;
545 char curDir[256];
546 char destDir[256];
547 unsigned int curDirSizeReq;
548 unsigned int destDirSizeReq;
549
550 retval = 0;
551
552 ver_dstring("\tlpszFilename = ", lpszFilename, "");
553 ver_dstring("\tlpszWinDir = ", lpszWinDir, "");
554 ver_dstring("\tlpszAppDir = ", lpszAppDir, "");
555
556 /* Figure out where the file should go; shared files default to the
557 system directory */
558
559 strcpy(curDir, "");
560 strcpy(destDir, "");
561
562 if(flags & VFFF_ISSHAREDFILE)
563 {
564 GetSystemDirectoryA(destDir, 256);
565
566 /* Were we given a filename? If so, try to find the file. */
567 if(lpszFilename)
568 {
569 if(testFileExistence(destDir, lpszFilename))
570 {
571 strcpy(curDir, destDir);
572
573 if(!testFileExclusiveExistence(destDir, lpszFilename))
574 retval |= VFF_FILEINUSE;
575 }
576 else
577 if(lpszAppDir && testFileExistence(lpszAppDir,
578 lpszFilename))
579 {
580 strcpy(curDir, lpszAppDir);
581 retval |= VFF_CURNEDEST;
582
583 if(!testFileExclusiveExistence(lpszAppDir, lpszFilename))
584 retval |= VFF_FILEINUSE;
585 }
586 }
587 }
588 else
589 if(!(flags & VFFF_ISSHAREDFILE))
590 { /* not a shared file */
591 if(lpszAppDir)
592 {
593 char systemDir[256];
594 GetSystemDirectoryA(systemDir, 256);
595
596 strcpy(destDir, lpszAppDir);
597
598 if(lpszFilename)
599 {
600 if(testFileExistence(lpszAppDir, lpszFilename))
601 {
602 strcpy(curDir, lpszAppDir);
603
604 if(!testFileExclusiveExistence(lpszAppDir, lpszFilename))
605 retval |= VFF_FILEINUSE;
606 }
607 else
608 if(testFileExistence(systemDir, lpszFilename))
609 {
610 strcpy(curDir, systemDir);
611 retval |= VFF_CURNEDEST;
612
613 if(!testFileExclusiveExistence(systemDir, lpszFilename))
614 retval |= VFF_FILEINUSE;
615 }
616 }
617 }
618 }
619
620 curDirSizeReq = strlen(curDir) + 1;
621 destDirSizeReq = strlen(destDir) + 1;
622
623
624
625 /* Make sure that the pointers to the size of the buffers are
626 valid; if not, do NOTHING with that buffer. If that pointer
627 is valid, then make sure that the buffer pointer is valid, too! */
628
629 if(lpuDestDirLen && lpszDestDir)
630 {
631 if(*lpuDestDirLen < destDirSizeReq)
632 {
633 retval |= VFF_BUFFTOOSMALL;
634 if (*lpuDestDirLen)
635 {
636 strncpy(lpszDestDir, destDir, *lpuDestDirLen - 1);
637 lpszDestDir[*lpuDestDirLen - 1] = '\0';
638 }
639 }
640 else
641 strcpy(lpszDestDir, destDir);
642
643 *lpuDestDirLen = destDirSizeReq;
644 }
645
646 if(lpuCurDirLen && lpszCurDir)
647 {
648 if(*lpuCurDirLen < curDirSizeReq)
649 {
650 retval |= VFF_BUFFTOOSMALL;
651 if (*lpuCurDirLen)
652 {
653 strncpy(lpszCurDir, curDir, *lpuCurDirLen - 1);
654 lpszCurDir[*lpuCurDirLen - 1] = '\0';
655 }
656 }
657 else
658 strcpy(lpszCurDir, curDir);
659
660 *lpuCurDirLen = curDirSizeReq;
661 }
662
663 dprintf(("VERSION: VerFindFileA ret = %lu (%s%s%s)\n", retval,
664 (retval & VFF_CURNEDEST) ? "VFF_CURNEDEST " : "",
665 (retval & VFF_FILEINUSE) ? "VFF_FILEINUSE " : "",
666 (retval & VFF_BUFFTOOSMALL) ? "VFF_BUFFTOOSMALL " : ""));
667
668 ver_dstring("\t(Exit) lpszCurDir = ", lpszCurDir, "");
669
670 return retval;
671}
672
673
674/*****************************************************************************
675 * Name :
676 * Purpose :
677 * Parameters:
678 * Variables :
679 * Result :
680 * Remark :
681 * Status : UNTESTED STUB
682 *
683 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
684 *****************************************************************************/
685
686ODINFUNCTION8(DWORD,VerFindFileW,DWORD, flags,
687 LPWSTR, lpszFilename,
688 LPWSTR, lpszWinDir,
689 LPWSTR, lpszAppDir,
690 LPWSTR, lpszCurDir,
691 PUINT, lpuCurDirLen,
692 LPWSTR, lpszDestDir,
693 PUINT, lpuDestDirLen )
694{
695 UINT curdirlen,
696 destdirlen;
697 LPSTR wfn,
698 wwd,
699 wad,
700 wdd,
701 wcd;
702 DWORD ret;
703
704 wfn = UnicodeToAsciiString(lpszFilename );
705 wwd = UnicodeToAsciiString(lpszWinDir );
706 wad = UnicodeToAsciiString(lpszAppDir );
707 wcd = (LPSTR)HeapAlloc( GetProcessHeap(), 0, *lpuCurDirLen );
708 wdd = (LPSTR)HeapAlloc( GetProcessHeap(), 0, *lpuDestDirLen );
709
710 ret = VerFindFileA(flags,
711 wfn,
712 wwd,
713 wad,
714 wcd,
715 &curdirlen,
716 wdd,
717 &destdirlen);
718
719 AsciiToUnicodeN(wcd,lpszCurDir,*lpuCurDirLen);
720 AsciiToUnicodeN(wdd,lpszDestDir,*lpuDestDirLen);
721 *lpuCurDirLen = strlen(wcd);
722 *lpuDestDirLen = strlen(wdd);
723
724 FreeAsciiString(wfn );
725 FreeAsciiString(wwd );
726 FreeAsciiString(wad );
727 FreeAsciiString(wcd );
728 FreeAsciiString(wdd );
729 return ret;
730}
731
732
733/*****************************************************************************
734 * Name :
735 * Purpose :
736 * Parameters:
737 * Variables :
738 * Result :
739 * Remark :
740 * Status : UNTESTED STUB
741 *
742 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
743 *****************************************************************************/
744
745ODINFUNCTION8(DWORD,VerInstallFileA,DWORD, flags,
746 LPSTR, srcfilename,
747 LPSTR, destfilename,
748 LPSTR, srcdir,
749 LPSTR, destdir,
750 LPSTR, curdir,
751 LPSTR, tmpfile,
752 PUINT, tmpfilelen )
753{
754 LPCSTR pdest;
755 char destfn[260],
756 tmpfn[260],
757 srcfn[260];
758 HFILE hfsrc,
759 hfdst;
760 DWORD attr,
761 ret,
762 xret,
763 tmplast;
764 LPBYTE buf1,buf2;
765 OFSTRUCT ofs;
766
767
768 xret = 0;
769
770 sprintf(srcfn,
771 "%s\\%s",
772 srcdir,
773 srcfilename);
774
775 if (!destdir || !*destdir)
776 pdest = srcdir;
777 else
778 pdest = destdir;
779
780 sprintf(destfn,
781 "%s\\%s",
782 pdest,
783 destfilename);
784
785 hfsrc=LZOpenFileA(srcfn,
786 &ofs,
787 OF_READ);
788
789 if (hfsrc==HFILE_ERROR)
790 return VIF_CANNOTREADSRC;
791
792 sprintf(tmpfn,"%s\\%s",pdest,destfilename);
793 tmplast=strlen(pdest)+1;
794 attr = GetFileAttributesA(tmpfn);
795 if (attr!=-1) {
796 if (attr & FILE_ATTRIBUTE_READONLY) {
797 LZClose(hfsrc);
798 return VIF_WRITEPROT;
799 }
800 /* FIXME: check if file currently in use and return VIF_FILEINUSE */
801 }
802 attr = -1;
803 if (flags & VIFF_FORCEINSTALL) {
804 if (tmpfile[0]) {
805 sprintf(tmpfn,"%s\\%s",pdest,tmpfile);
806 tmplast = strlen(pdest)+1;
807 attr = GetFileAttributesA(tmpfn);
808 /* if it exists, it has been copied by the call before.
809 * we jump over the copy part...
810 */
811 }
812 }
813 if (attr == -1) {
814 char *s;
815
816 GetTempFileNameA(pdest,"ver",0,tmpfn); /* should not fail ... */
817 s=strrchr(tmpfn,'\\');
818 if (s)
819 tmplast = s-tmpfn;
820 else
821 tmplast = 0;
822 hfdst = OpenFile(tmpfn,&ofs,OF_CREATE);
823 if (hfdst == HFILE_ERROR) {
824 LZClose(hfsrc);
825 return VIF_CANNOTCREATE; /* | translated dos error */
826 }
827 ret = LZCopy(hfsrc,hfdst);
828 _lclose(hfdst);
829 if (((long) ret) < 0) {
830 /* translate LZ errors into VIF_xxx */
831 switch (ret) {
832 case LZERROR_BADINHANDLE:
833 case LZERROR_READ:
834 case LZERROR_BADVALUE:
835 case LZERROR_UNKNOWNALG:
836 ret = VIF_CANNOTREADSRC;
837 break;
838 case LZERROR_BADOUTHANDLE:
839 case LZERROR_WRITE:
840 ret = VIF_OUTOFMEMORY; /* FIXME: correct? */
841 break;
842 case LZERROR_GLOBALLOC:
843 case LZERROR_GLOBLOCK:
844 ret = VIF_OUTOFSPACE;
845 break;
846 default: /* unknown error, should not happen */
847 ret = 0;
848 break;
849 }
850 if (ret) {
851 LZClose(hfsrc);
852 return ret;
853 }
854 }
855 }
856 xret = 0;
857 if (!(flags & VIFF_FORCEINSTALL)) {
858 VS_FIXEDFILEINFO *destvffi,*tmpvffi;
859 buf1 = _fetch_versioninfo(destfn,&destvffi);
860 if (buf1) {
861 buf2 = _fetch_versioninfo(tmpfn,&tmpvffi);
862 if (buf2) {
863 char *tbuf1,*tbuf2;
864 UINT len1,len2;
865
866 len1=len2=40;
867
868 /* compare file versions */
869 if ((destvffi->dwFileVersionMS > tmpvffi->dwFileVersionMS)||
870 ((destvffi->dwFileVersionMS==tmpvffi->dwFileVersionMS)&&
871 (destvffi->dwFileVersionLS > tmpvffi->dwFileVersionLS)
872 )
873 )
874 xret |= VIF_MISMATCH|VIF_SRCOLD;
875 /* compare filetypes and filesubtypes */
876 if ((destvffi->dwFileType!=tmpvffi->dwFileType) ||
877 (destvffi->dwFileSubtype!=tmpvffi->dwFileSubtype)
878 )
879 xret |= VIF_MISMATCH|VIF_DIFFTYPE;
880 if (VerQueryValueA(buf1,"\\VarFileInfo\\Translation",(LPVOID*)&tbuf1,&len1) &&
881 VerQueryValueA(buf2,"\\VarFileInfo\\Translation",(LPVOID*)&tbuf2,&len2)
882 ) {
883 /* irgendwas mit tbuf1 und tbuf2 machen
884 * generiert DIFFLANG|MISMATCH
885 */
886 }
887 free(buf2);
888 } else
889 xret=VIF_MISMATCH|VIF_SRCOLD;
890 free(buf1);
891 }
892 }
893 if (xret) {
894 if (*tmpfilelen<strlen(tmpfn+tmplast)) {
895 xret|=VIF_BUFFTOOSMALL;
896 DeleteFileA(tmpfn);
897 } else {
898 strcpy(tmpfile,tmpfn+tmplast);
899 *tmpfilelen = strlen(tmpfn+tmplast)+1;
900 xret|=VIF_TEMPFILE;
901 }
902 } else {
903 if (-1!=GetFileAttributesA(destfn))
904 if (!DeleteFileA(destfn)) {
905 xret|=_error2vif(GetLastError())|VIF_CANNOTDELETE;
906 DeleteFileA(tmpfn);
907 LZClose(hfsrc);
908 return xret;
909 }
910 if ((!(flags & VIFF_DONTDELETEOLD)) &&
911 curdir &&
912 *curdir &&
913 lstrcmpiA(curdir,pdest)
914 ) {
915 char curfn[260];
916
917 sprintf(curfn,"%s\\%s",curdir,destfilename);
918 if (-1!=GetFileAttributesA(curfn)) {
919 /* FIXME: check if in use ... if it is, VIF_CANNOTDELETECUR */
920 if (!DeleteFileA(curfn))
921 xret|=_error2vif(GetLastError())|VIF_CANNOTDELETECUR;
922 }
923 }
924 if (!MoveFileA(tmpfn,destfn)) {
925 xret|=_error2vif(GetLastError())|VIF_CANNOTRENAME;
926 DeleteFileA(tmpfn);
927 }
928 }
929 LZClose(hfsrc);
930 return xret;
931}
932
933
934/*****************************************************************************
935 * Name :
936 * Purpose :
937 * Parameters:
938 * Variables :
939 * Result :
940 * Remark :
941 * Status : UNTESTED STUB
942 *
943 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
944 *****************************************************************************/
945
946ODINFUNCTION8(DWORD,VerInstallFileW,DWORD, flags,
947 LPWSTR, srcfilename,
948 LPWSTR, destfilename,
949 LPWSTR, srcdir,
950 LPWSTR, destdir,
951 LPWSTR, curdir,
952 LPWSTR, tmpfile,
953 PUINT, tmpfilelen )
954{
955 LPSTR wsrcf,
956 wsrcd,
957 wdestf,
958 wdestd,
959 wtmpf,
960 wcurd;
961 DWORD ret;
962
963 wsrcf = UnicodeToAsciiString(srcfilename );
964 wsrcd = UnicodeToAsciiString(srcdir );
965 wdestf = UnicodeToAsciiString(destfilename );
966 wdestd = UnicodeToAsciiString(destdir );
967 wtmpf = UnicodeToAsciiString(tmpfile );
968 wcurd = UnicodeToAsciiString(curdir );
969
970 ret = VerInstallFileA(flags,
971 wsrcf,
972 wdestf,
973 wsrcd,
974 wdestd,
975 wcurd,
976 wtmpf,
977 tmpfilelen);
978 if (!ret)
979 AsciiToUnicodeN(wtmpf,
980 tmpfile,
981 *tmpfilelen);
982
983 FreeAsciiString(wsrcf);
984 FreeAsciiString(wsrcd);
985 FreeAsciiString(wdestf);
986 FreeAsciiString(wdestd);
987 FreeAsciiString(wtmpf);
988
989 if (wcurd)
990 FreeAsciiString(wcurd);
991
992 return ret;
993}
994
995
996
Note: See TracBrowser for help on using the repository browser.