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

Last change on this file since 1132 was 1132, checked in by sandervl, 26 years ago

VerQueryValueW fix

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