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

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

EB's VerQueryValueA/W implementation

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