[10296] | 1 | /*
|
---|
| 2 | * Implementation of VERSION.DLL - File Installer routines
|
---|
| 3 | *
|
---|
[2347] | 4 | * Copyright 1996,1997 Marcus Meissner
|
---|
| 5 | * Copyright 1997 David Cuthbert
|
---|
[10296] | 6 | *
|
---|
| 7 | * This library is free software; you can redistribute it and/or
|
---|
| 8 | * modify it under the terms of the GNU Lesser General Public
|
---|
| 9 | * License as published by the Free Software Foundation; either
|
---|
| 10 | * version 2.1 of the License, or (at your option) any later version.
|
---|
| 11 | *
|
---|
| 12 | * This library is distributed in the hope that it will be useful,
|
---|
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
| 15 | * Lesser General Public License for more details.
|
---|
| 16 | *
|
---|
| 17 | * You should have received a copy of the GNU Lesser General Public
|
---|
| 18 | * License along with this library; if not, write to the Free Software
|
---|
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
---|
| 20 | *
|
---|
| 21 | * TODO
|
---|
| 22 | * o Check the installation functions.
|
---|
[2347] | 23 | */
|
---|
| 24 |
|
---|
| 25 | #include <stdlib.h>
|
---|
[10296] | 26 | #include <stdarg.h>
|
---|
| 27 | #include <stdio.h>
|
---|
[2347] | 28 | #include <string.h>
|
---|
| 29 |
|
---|
| 30 | #include "windef.h"
|
---|
[10296] | 31 | #include "winbase.h"
|
---|
[2347] | 32 | #include "winver.h"
|
---|
[10296] | 33 | #include "winnls.h"
|
---|
| 34 | #include "wine/unicode.h"
|
---|
[2347] | 35 | #include "winerror.h"
|
---|
| 36 | #include "lzexpand.h"
|
---|
[10296] | 37 | #include "wine/debug.h"
|
---|
[2347] | 38 |
|
---|
[10300] | 39 | #define DBG_LOCALLOG DBG_install
|
---|
| 40 | #include "dbglocal.h"
|
---|
| 41 |
|
---|
[10296] | 42 | WINE_DEFAULT_DEBUG_CHANNEL(ver);
|
---|
[2347] | 43 |
|
---|
| 44 |
|
---|
| 45 | /******************************************************************************
|
---|
[10296] | 46 | * testFileExistenceA
|
---|
[2347] | 47 | *
|
---|
| 48 | * Tests whether a given path/file combination exists. If the file does
|
---|
| 49 | * not exist, the return value is zero. If it does exist, the return
|
---|
| 50 | * value is non-zero.
|
---|
| 51 | *
|
---|
| 52 | * Revision history
|
---|
| 53 | * 30-May-1997 Dave Cuthbert (dacut@ece.cmu.edu)
|
---|
| 54 | * Original implementation
|
---|
| 55 | *
|
---|
[10296] | 56 | */
|
---|
| 57 | static int testFileExistenceA( char const * path, char const * file, BOOL excl )
|
---|
[2347] | 58 | {
|
---|
| 59 | char filename[1024];
|
---|
| 60 | int filenamelen;
|
---|
| 61 | OFSTRUCT fileinfo;
|
---|
| 62 |
|
---|
| 63 | fileinfo.cBytes = sizeof(OFSTRUCT);
|
---|
| 64 |
|
---|
| 65 | strcpy(filename, path);
|
---|
| 66 | filenamelen = strlen(filename);
|
---|
| 67 |
|
---|
| 68 | /* Add a trailing \ if necessary */
|
---|
| 69 | if(filenamelen) {
|
---|
| 70 | if(filename[filenamelen - 1] != '\\')
|
---|
| 71 | strcat(filename, "\\");
|
---|
| 72 | }
|
---|
| 73 | else /* specify the current directory */
|
---|
| 74 | strcpy(filename, ".\\");
|
---|
| 75 |
|
---|
| 76 | /* Create the full pathname */
|
---|
| 77 | strcat(filename, file);
|
---|
| 78 |
|
---|
[10296] | 79 | return (OpenFile(filename, &fileinfo,
|
---|
| 80 | OF_EXIST | (excl ? OF_SHARE_EXCLUSIVE : 0)) != HFILE_ERROR);
|
---|
[2347] | 81 | }
|
---|
| 82 |
|
---|
| 83 | /******************************************************************************
|
---|
[10296] | 84 | * testFileExistenceW
|
---|
| 85 | */
|
---|
| 86 | static int testFileExistenceW( const WCHAR *path, const WCHAR *file, BOOL excl )
|
---|
[2347] | 87 | {
|
---|
[10296] | 88 | char *filename;
|
---|
| 89 | DWORD pathlen, filelen;
|
---|
| 90 | int ret;
|
---|
| 91 | OFSTRUCT fileinfo;
|
---|
[2347] | 92 |
|
---|
| 93 | fileinfo.cBytes = sizeof(OFSTRUCT);
|
---|
| 94 |
|
---|
[10296] | 95 | pathlen = WideCharToMultiByte( CP_ACP, 0, path, -1, NULL, 0, NULL, NULL );
|
---|
| 96 | filelen = WideCharToMultiByte( CP_ACP, 0, file, -1, NULL, 0, NULL, NULL );
|
---|
| 97 | filename = HeapAlloc( GetProcessHeap(), 0, pathlen+filelen+2 );
|
---|
[2347] | 98 |
|
---|
[10296] | 99 | WideCharToMultiByte( CP_ACP, 0, path, -1, filename, pathlen, NULL, NULL );
|
---|
[2347] | 100 | /* Add a trailing \ if necessary */
|
---|
[10296] | 101 | if (pathlen > 1)
|
---|
| 102 | {
|
---|
| 103 | if (filename[pathlen-2] != '\\') strcpy( &filename[pathlen-1], "\\" );
|
---|
[2347] | 104 | }
|
---|
| 105 | else /* specify the current directory */
|
---|
[10296] | 106 | strcpy(filename, ".\\");
|
---|
[2347] | 107 |
|
---|
[10296] | 108 | WideCharToMultiByte( CP_ACP, 0, file, -1, filename+strlen(filename), filelen, NULL, NULL );
|
---|
[2347] | 109 |
|
---|
[10296] | 110 | ret = (OpenFile(filename, &fileinfo,
|
---|
| 111 | OF_EXIST | (excl ? OF_SHARE_EXCLUSIVE : 0)) != HFILE_ERROR);
|
---|
| 112 | HeapFree( GetProcessHeap(), 0, filename );
|
---|
| 113 | return ret;
|
---|
[2347] | 114 | }
|
---|
| 115 |
|
---|
| 116 | /*****************************************************************************
|
---|
[10296] | 117 | * VerFindFileA [VERSION.@]
|
---|
[2347] | 118 | *
|
---|
| 119 | * Determines where to install a file based on whether it locates another
|
---|
| 120 | * version of the file in the system. The values VerFindFile returns are
|
---|
| 121 | * used in a subsequent call to the VerInstallFile function.
|
---|
| 122 | *
|
---|
| 123 | * Revision history:
|
---|
| 124 | * 30-May-1997 Dave Cuthbert (dacut@ece.cmu.edu)
|
---|
| 125 | * Reimplementation of VerFindFile from original stub.
|
---|
[10296] | 126 | */
|
---|
[2347] | 127 | DWORD WINAPI VerFindFileA(
|
---|
| 128 | UINT flags,
|
---|
| 129 | LPCSTR lpszFilename,
|
---|
| 130 | LPCSTR lpszWinDir,
|
---|
| 131 | LPCSTR lpszAppDir,
|
---|
| 132 | LPSTR lpszCurDir,
|
---|
| 133 | UINT *lpuCurDirLen,
|
---|
| 134 | LPSTR lpszDestDir,
|
---|
| 135 | UINT *lpuDestDirLen )
|
---|
| 136 | {
|
---|
[10296] | 137 | DWORD retval = 0;
|
---|
| 138 | const char *curDir;
|
---|
| 139 | const char *destDir;
|
---|
[2347] | 140 | unsigned int curDirSizeReq;
|
---|
| 141 | unsigned int destDirSizeReq;
|
---|
[10296] | 142 | char systemDir[MAX_PATH];
|
---|
[2347] | 143 |
|
---|
| 144 | /* Print out debugging information */
|
---|
[10300] | 145 | dprintf(("flags = %x filename=%s windir=%s appdir=%s curdirlen=%p(%u) destdirlen=%p(%u)\n",
|
---|
[10296] | 146 | flags, debugstr_a(lpszFilename), debugstr_a(lpszWinDir), debugstr_a(lpszAppDir),
|
---|
| 147 | lpuCurDirLen, lpuCurDirLen ? *lpuCurDirLen : 0,
|
---|
[10300] | 148 | lpuDestDirLen, lpuDestDirLen ? *lpuDestDirLen : 0 ));
|
---|
[2347] | 149 |
|
---|
| 150 | /* Figure out where the file should go; shared files default to the
|
---|
| 151 | system directory */
|
---|
| 152 |
|
---|
[10296] | 153 | GetSystemDirectoryA(systemDir, sizeof(systemDir));
|
---|
| 154 | curDir = "";
|
---|
| 155 | destDir = "";
|
---|
[2347] | 156 |
|
---|
[10296] | 157 | if(flags & VFFF_ISSHAREDFILE)
|
---|
| 158 | {
|
---|
| 159 | destDir = systemDir;
|
---|
| 160 | /* Were we given a filename? If so, try to find the file. */
|
---|
| 161 | if(lpszFilename)
|
---|
| 162 | {
|
---|
| 163 | if(testFileExistenceA(destDir, lpszFilename, FALSE)) curDir = destDir;
|
---|
| 164 | else if(lpszAppDir && testFileExistenceA(lpszAppDir, lpszFilename, FALSE))
|
---|
| 165 | {
|
---|
| 166 | curDir = lpszAppDir;
|
---|
| 167 | retval |= VFF_CURNEDEST;
|
---|
| 168 | }
|
---|
| 169 | }
|
---|
| 170 | }
|
---|
| 171 | else /* not a shared file */
|
---|
| 172 | {
|
---|
| 173 | if(lpszAppDir)
|
---|
| 174 | {
|
---|
| 175 | destDir = lpszAppDir;
|
---|
| 176 | if(lpszFilename)
|
---|
| 177 | {
|
---|
| 178 | if(testFileExistenceA(destDir, lpszFilename, FALSE)) curDir = destDir;
|
---|
| 179 | else if(testFileExistenceA(systemDir, lpszFilename, FALSE))
|
---|
| 180 | {
|
---|
| 181 | curDir = systemDir;
|
---|
| 182 | retval |= VFF_CURNEDEST;
|
---|
| 183 | }
|
---|
| 184 | }
|
---|
| 185 | }
|
---|
| 186 | }
|
---|
[2347] | 187 |
|
---|
[10296] | 188 | if (lpszFilename && !testFileExistenceA(curDir, lpszFilename, TRUE))
|
---|
| 189 | retval |= VFF_FILEINUSE;
|
---|
[2347] | 190 |
|
---|
[10296] | 191 | curDirSizeReq = strlen(curDir) + 1;
|
---|
| 192 | destDirSizeReq = strlen(destDir) + 1;
|
---|
[2347] | 193 |
|
---|
[10296] | 194 | /* Make sure that the pointers to the size of the buffers are
|
---|
| 195 | valid; if not, do NOTHING with that buffer. If that pointer
|
---|
| 196 | is valid, then make sure that the buffer pointer is valid, too! */
|
---|
| 197 |
|
---|
| 198 | if(lpuDestDirLen && lpszDestDir)
|
---|
| 199 | {
|
---|
| 200 | if (*lpuDestDirLen < destDirSizeReq) retval |= VFF_BUFFTOOSMALL;
|
---|
| 201 | lstrcpynA(lpszDestDir, destDir, *lpuDestDirLen);
|
---|
| 202 | *lpuDestDirLen = destDirSizeReq;
|
---|
[2347] | 203 | }
|
---|
[10296] | 204 | if(lpuCurDirLen && lpszCurDir)
|
---|
| 205 | {
|
---|
| 206 | if(*lpuCurDirLen < curDirSizeReq) retval |= VFF_BUFFTOOSMALL;
|
---|
| 207 | lstrcpynA(lpszCurDir, curDir, *lpuCurDirLen);
|
---|
| 208 | *lpuCurDirLen = curDirSizeReq;
|
---|
| 209 | }
|
---|
[2347] | 210 |
|
---|
[10300] | 211 | dprintf(("ret = %lu (%s%s%s) curdir=%s destdir=%s\n", retval,
|
---|
[10296] | 212 | (retval & VFF_CURNEDEST) ? "VFF_CURNEDEST " : "",
|
---|
| 213 | (retval & VFF_FILEINUSE) ? "VFF_FILEINUSE " : "",
|
---|
| 214 | (retval & VFF_BUFFTOOSMALL) ? "VFF_BUFFTOOSMALL " : "",
|
---|
[10300] | 215 | debugstr_a(lpszCurDir), debugstr_a(lpszDestDir)));
|
---|
[2347] | 216 |
|
---|
[10296] | 217 | return retval;
|
---|
| 218 | }
|
---|
[2347] | 219 |
|
---|
[10296] | 220 | /*****************************************************************************
|
---|
| 221 | * VerFindFileW [VERSION.@]
|
---|
| 222 | */
|
---|
| 223 | DWORD WINAPI VerFindFileW( UINT flags,LPCWSTR lpszFilename,LPCWSTR lpszWinDir,
|
---|
| 224 | LPCWSTR lpszAppDir, LPWSTR lpszCurDir,UINT *lpuCurDirLen,
|
---|
| 225 | LPWSTR lpszDestDir,UINT *lpuDestDirLen )
|
---|
| 226 | {
|
---|
| 227 | static const WCHAR emptyW;
|
---|
| 228 | DWORD retval = 0;
|
---|
| 229 | const WCHAR *curDir;
|
---|
| 230 | const WCHAR *destDir;
|
---|
| 231 | unsigned int curDirSizeReq;
|
---|
| 232 | unsigned int destDirSizeReq;
|
---|
| 233 | WCHAR systemDir[MAX_PATH];
|
---|
[2347] | 234 |
|
---|
[10296] | 235 | /* Print out debugging information */
|
---|
[10300] | 236 | dprintf(("flags = %x filename=%s windir=%s appdir=%s curdirlen=%p(%u) destdirlen=%p(%u)\n",
|
---|
[10296] | 237 | flags, debugstr_w(lpszFilename), debugstr_w(lpszWinDir), debugstr_w(lpszAppDir),
|
---|
| 238 | lpuCurDirLen, lpuCurDirLen ? *lpuCurDirLen : 0,
|
---|
[10300] | 239 | lpuDestDirLen, lpuDestDirLen ? *lpuDestDirLen : 0 ));
|
---|
[10296] | 240 |
|
---|
| 241 | /* Figure out where the file should go; shared files default to the
|
---|
| 242 | system directory */
|
---|
| 243 |
|
---|
| 244 | GetSystemDirectoryW(systemDir, sizeof(systemDir)/sizeof(WCHAR));
|
---|
| 245 | curDir = &emptyW;
|
---|
| 246 | destDir = &emptyW;
|
---|
| 247 |
|
---|
| 248 | if(flags & VFFF_ISSHAREDFILE)
|
---|
| 249 | {
|
---|
| 250 | destDir = systemDir;
|
---|
| 251 | /* Were we given a filename? If so, try to find the file. */
|
---|
| 252 | if(lpszFilename)
|
---|
| 253 | {
|
---|
| 254 | if(testFileExistenceW(destDir, lpszFilename, FALSE)) curDir = destDir;
|
---|
| 255 | else if(lpszAppDir && testFileExistenceW(lpszAppDir, lpszFilename, FALSE))
|
---|
| 256 | {
|
---|
| 257 | curDir = lpszAppDir;
|
---|
| 258 | retval |= VFF_CURNEDEST;
|
---|
| 259 | }
|
---|
| 260 | }
|
---|
[2347] | 261 | }
|
---|
[10296] | 262 | else /* not a shared file */
|
---|
| 263 | {
|
---|
| 264 | if(lpszAppDir)
|
---|
| 265 | {
|
---|
| 266 | destDir = lpszAppDir;
|
---|
| 267 | if(lpszFilename)
|
---|
| 268 | {
|
---|
| 269 | if(testFileExistenceW(destDir, lpszFilename, FALSE)) curDir = destDir;
|
---|
| 270 | else if(testFileExistenceW(systemDir, lpszFilename, FALSE))
|
---|
| 271 | {
|
---|
| 272 | curDir = systemDir;
|
---|
| 273 | retval |= VFF_CURNEDEST;
|
---|
| 274 | }
|
---|
| 275 | }
|
---|
| 276 | }
|
---|
| 277 | }
|
---|
[2347] | 278 |
|
---|
[10296] | 279 | if (lpszFilename && !testFileExistenceW(curDir, lpszFilename, TRUE))
|
---|
| 280 | retval |= VFF_FILEINUSE;
|
---|
[2347] | 281 |
|
---|
[10296] | 282 | curDirSizeReq = strlenW(curDir) + 1;
|
---|
| 283 | destDirSizeReq = strlenW(destDir) + 1;
|
---|
[2347] | 284 |
|
---|
| 285 | /* Make sure that the pointers to the size of the buffers are
|
---|
| 286 | valid; if not, do NOTHING with that buffer. If that pointer
|
---|
| 287 | is valid, then make sure that the buffer pointer is valid, too! */
|
---|
| 288 |
|
---|
[10296] | 289 | if(lpuDestDirLen && lpszDestDir)
|
---|
| 290 | {
|
---|
| 291 | if (*lpuDestDirLen < destDirSizeReq) retval |= VFF_BUFFTOOSMALL;
|
---|
| 292 | lstrcpynW(lpszDestDir, destDir, *lpuDestDirLen);
|
---|
| 293 | *lpuDestDirLen = destDirSizeReq;
|
---|
[2347] | 294 | }
|
---|
[10296] | 295 | if(lpuCurDirLen && lpszCurDir)
|
---|
| 296 | {
|
---|
| 297 | if(*lpuCurDirLen < curDirSizeReq) retval |= VFF_BUFFTOOSMALL;
|
---|
| 298 | lstrcpynW(lpszCurDir, curDir, *lpuCurDirLen);
|
---|
| 299 | *lpuCurDirLen = curDirSizeReq;
|
---|
[2347] | 300 | }
|
---|
| 301 |
|
---|
[10300] | 302 | dprintf(("ret = %lu (%s%s%s) curdir=%s destdir=%s\n", retval,
|
---|
[10296] | 303 | (retval & VFF_CURNEDEST) ? "VFF_CURNEDEST " : "",
|
---|
| 304 | (retval & VFF_FILEINUSE) ? "VFF_FILEINUSE " : "",
|
---|
| 305 | (retval & VFF_BUFFTOOSMALL) ? "VFF_BUFFTOOSMALL " : "",
|
---|
[10300] | 306 | debugstr_w(lpszCurDir), debugstr_w(lpszDestDir)));
|
---|
[2347] | 307 | return retval;
|
---|
| 308 | }
|
---|
| 309 |
|
---|
| 310 | static LPBYTE
|
---|
| 311 | _fetch_versioninfo(LPSTR fn,VS_FIXEDFILEINFO **vffi) {
|
---|
| 312 | DWORD alloclen;
|
---|
| 313 | LPBYTE buf;
|
---|
| 314 | DWORD ret;
|
---|
| 315 |
|
---|
| 316 | alloclen = 1000;
|
---|
[10296] | 317 | buf=HeapAlloc(GetProcessHeap(), 0, alloclen);
|
---|
| 318 | if(buf == NULL) {
|
---|
[10300] | 319 | dprintf(("Memory exausted while fetching version info!\n"));
|
---|
[10296] | 320 | return NULL;
|
---|
| 321 | }
|
---|
[2347] | 322 | while (1) {
|
---|
| 323 | ret = GetFileVersionInfoA(fn,0,alloclen,buf);
|
---|
| 324 | if (!ret) {
|
---|
[10296] | 325 | HeapFree(GetProcessHeap(), 0, buf);
|
---|
| 326 | return NULL;
|
---|
[2347] | 327 | }
|
---|
| 328 | if (alloclen<*(WORD*)buf) {
|
---|
| 329 | alloclen = *(WORD*)buf;
|
---|
[10296] | 330 | HeapFree(GetProcessHeap(), 0, buf);
|
---|
| 331 | buf = HeapAlloc(GetProcessHeap(), 0, alloclen);
|
---|
| 332 | if(buf == NULL) {
|
---|
[10300] | 333 | dprintf(("Memory exausted while fetching version info!\n"));
|
---|
[10296] | 334 | return NULL;
|
---|
| 335 | }
|
---|
[2347] | 336 | } else {
|
---|
| 337 | *vffi = (VS_FIXEDFILEINFO*)(buf+0x14);
|
---|
| 338 | if ((*vffi)->dwSignature == 0x004f0049) /* hack to detect unicode */
|
---|
| 339 | *vffi = (VS_FIXEDFILEINFO*)(buf+0x28);
|
---|
| 340 | if ((*vffi)->dwSignature != VS_FFI_SIGNATURE)
|
---|
[10300] | 341 | dprintf(("Bad VS_FIXEDFILEINFO signature 0x%08lx\n",(*vffi)->dwSignature));
|
---|
[2347] | 342 | return buf;
|
---|
| 343 | }
|
---|
| 344 | }
|
---|
| 345 | }
|
---|
| 346 |
|
---|
| 347 | static DWORD
|
---|
| 348 | _error2vif(DWORD error) {
|
---|
| 349 | switch (error) {
|
---|
| 350 | case ERROR_ACCESS_DENIED:
|
---|
| 351 | return VIF_ACCESSVIOLATION;
|
---|
| 352 | case ERROR_SHARING_VIOLATION:
|
---|
| 353 | return VIF_SHARINGVIOLATION;
|
---|
| 354 | default:
|
---|
| 355 | return 0;
|
---|
| 356 | }
|
---|
| 357 | }
|
---|
| 358 |
|
---|
| 359 |
|
---|
| 360 | /******************************************************************************
|
---|
[10296] | 361 | * VerInstallFileA [VERSION.@]
|
---|
[2347] | 362 | */
|
---|
| 363 | DWORD WINAPI VerInstallFileA(
|
---|
| 364 | UINT flags,LPCSTR srcfilename,LPCSTR destfilename,LPCSTR srcdir,
|
---|
| 365 | LPCSTR destdir,LPCSTR curdir,LPSTR tmpfile,UINT *tmpfilelen )
|
---|
| 366 | {
|
---|
| 367 | LPCSTR pdest;
|
---|
| 368 | char destfn[260],tmpfn[260],srcfn[260];
|
---|
| 369 | HFILE hfsrc,hfdst;
|
---|
| 370 | DWORD attr,ret,xret,tmplast;
|
---|
| 371 | LPBYTE buf1,buf2;
|
---|
| 372 | OFSTRUCT ofs;
|
---|
| 373 |
|
---|
[10300] | 374 | dprintf(("(%x,%s,%s,%s,%s,%s,%p,%d)\n",
|
---|
[2347] | 375 | flags,srcfilename,destfilename,srcdir,destdir,curdir,tmpfile,*tmpfilelen
|
---|
[10300] | 376 | ));
|
---|
[2347] | 377 | xret = 0;
|
---|
| 378 | sprintf(srcfn,"%s\\%s",srcdir,srcfilename);
|
---|
| 379 | if (!destdir || !*destdir) pdest = srcdir;
|
---|
| 380 | else pdest = destdir;
|
---|
| 381 | sprintf(destfn,"%s\\%s",pdest,destfilename);
|
---|
| 382 | hfsrc=LZOpenFileA(srcfn,&ofs,OF_READ);
|
---|
[10296] | 383 | if (hfsrc < 0)
|
---|
[2347] | 384 | return VIF_CANNOTREADSRC;
|
---|
| 385 | sprintf(tmpfn,"%s\\%s",pdest,destfilename);
|
---|
| 386 | tmplast=strlen(pdest)+1;
|
---|
| 387 | attr = GetFileAttributesA(tmpfn);
|
---|
[10296] | 388 | if (attr != INVALID_FILE_ATTRIBUTES) {
|
---|
[2347] | 389 | if (attr & FILE_ATTRIBUTE_READONLY) {
|
---|
| 390 | LZClose(hfsrc);
|
---|
| 391 | return VIF_WRITEPROT;
|
---|
| 392 | }
|
---|
| 393 | /* FIXME: check if file currently in use and return VIF_FILEINUSE */
|
---|
| 394 | }
|
---|
[10296] | 395 | attr = INVALID_FILE_ATTRIBUTES;
|
---|
[2347] | 396 | if (flags & VIFF_FORCEINSTALL) {
|
---|
| 397 | if (tmpfile[0]) {
|
---|
| 398 | sprintf(tmpfn,"%s\\%s",pdest,tmpfile);
|
---|
| 399 | tmplast = strlen(pdest)+1;
|
---|
| 400 | attr = GetFileAttributesA(tmpfn);
|
---|
| 401 | /* if it exists, it has been copied by the call before.
|
---|
[10296] | 402 | * we jump over the copy part...
|
---|
[2347] | 403 | */
|
---|
| 404 | }
|
---|
| 405 | }
|
---|
[10296] | 406 | if (attr == INVALID_FILE_ATTRIBUTES) {
|
---|
[2347] | 407 | char *s;
|
---|
| 408 |
|
---|
| 409 | GetTempFileNameA(pdest,"ver",0,tmpfn); /* should not fail ... */
|
---|
| 410 | s=strrchr(tmpfn,'\\');
|
---|
| 411 | if (s)
|
---|
| 412 | tmplast = s-tmpfn;
|
---|
| 413 | else
|
---|
| 414 | tmplast = 0;
|
---|
| 415 | hfdst = OpenFile(tmpfn,&ofs,OF_CREATE);
|
---|
| 416 | if (hfdst == HFILE_ERROR) {
|
---|
| 417 | LZClose(hfsrc);
|
---|
| 418 | return VIF_CANNOTCREATE; /* | translated dos error */
|
---|
| 419 | }
|
---|
| 420 | ret = LZCopy(hfsrc,hfdst);
|
---|
| 421 | _lclose(hfdst);
|
---|
| 422 | if (((long) ret) < 0) {
|
---|
| 423 | /* translate LZ errors into VIF_xxx */
|
---|
| 424 | switch (ret) {
|
---|
| 425 | case LZERROR_BADINHANDLE:
|
---|
| 426 | case LZERROR_READ:
|
---|
| 427 | case LZERROR_BADVALUE:
|
---|
| 428 | case LZERROR_UNKNOWNALG:
|
---|
| 429 | ret = VIF_CANNOTREADSRC;
|
---|
| 430 | break;
|
---|
| 431 | case LZERROR_BADOUTHANDLE:
|
---|
| 432 | case LZERROR_WRITE:
|
---|
[10296] | 433 | ret = VIF_OUTOFSPACE;
|
---|
[2347] | 434 | break;
|
---|
| 435 | case LZERROR_GLOBALLOC:
|
---|
| 436 | case LZERROR_GLOBLOCK:
|
---|
[10296] | 437 | ret = VIF_OUTOFMEMORY;
|
---|
[2347] | 438 | break;
|
---|
| 439 | default: /* unknown error, should not happen */
|
---|
| 440 | ret = 0;
|
---|
| 441 | break;
|
---|
| 442 | }
|
---|
| 443 | if (ret) {
|
---|
| 444 | LZClose(hfsrc);
|
---|
| 445 | return ret;
|
---|
| 446 | }
|
---|
| 447 | }
|
---|
| 448 | }
|
---|
| 449 | xret = 0;
|
---|
| 450 | if (!(flags & VIFF_FORCEINSTALL)) {
|
---|
| 451 | VS_FIXEDFILEINFO *destvffi,*tmpvffi;
|
---|
| 452 | buf1 = _fetch_versioninfo(destfn,&destvffi);
|
---|
| 453 | if (buf1) {
|
---|
| 454 | buf2 = _fetch_versioninfo(tmpfn,&tmpvffi);
|
---|
| 455 | if (buf2) {
|
---|
| 456 | char *tbuf1,*tbuf2;
|
---|
| 457 | UINT len1,len2;
|
---|
| 458 |
|
---|
| 459 | len1=len2=40;
|
---|
| 460 |
|
---|
| 461 | /* compare file versions */
|
---|
| 462 | if ((destvffi->dwFileVersionMS > tmpvffi->dwFileVersionMS)||
|
---|
| 463 | ((destvffi->dwFileVersionMS==tmpvffi->dwFileVersionMS)&&
|
---|
| 464 | (destvffi->dwFileVersionLS > tmpvffi->dwFileVersionLS)
|
---|
| 465 | )
|
---|
| 466 | )
|
---|
| 467 | xret |= VIF_MISMATCH|VIF_SRCOLD;
|
---|
| 468 | /* compare filetypes and filesubtypes */
|
---|
| 469 | if ((destvffi->dwFileType!=tmpvffi->dwFileType) ||
|
---|
| 470 | (destvffi->dwFileSubtype!=tmpvffi->dwFileSubtype)
|
---|
| 471 | )
|
---|
| 472 | xret |= VIF_MISMATCH|VIF_DIFFTYPE;
|
---|
| 473 | if (VerQueryValueA(buf1,"\\VarFileInfo\\Translation",(LPVOID*)&tbuf1,&len1) &&
|
---|
| 474 | VerQueryValueA(buf2,"\\VarFileInfo\\Translation",(LPVOID*)&tbuf2,&len2)
|
---|
| 475 | ) {
|
---|
[10296] | 476 | /* irgendwas mit tbuf1 und tbuf2 machen
|
---|
[2347] | 477 | * generiert DIFFLANG|MISMATCH
|
---|
| 478 | */
|
---|
| 479 | }
|
---|
[10296] | 480 | HeapFree(GetProcessHeap(), 0, buf2);
|
---|
[2347] | 481 | } else
|
---|
| 482 | xret=VIF_MISMATCH|VIF_SRCOLD;
|
---|
[10296] | 483 | HeapFree(GetProcessHeap(), 0, buf1);
|
---|
[2347] | 484 | }
|
---|
| 485 | }
|
---|
| 486 | if (xret) {
|
---|
| 487 | if (*tmpfilelen<strlen(tmpfn+tmplast)) {
|
---|
| 488 | xret|=VIF_BUFFTOOSMALL;
|
---|
| 489 | DeleteFileA(tmpfn);
|
---|
| 490 | } else {
|
---|
| 491 | strcpy(tmpfile,tmpfn+tmplast);
|
---|
| 492 | *tmpfilelen = strlen(tmpfn+tmplast)+1;
|
---|
| 493 | xret|=VIF_TEMPFILE;
|
---|
| 494 | }
|
---|
| 495 | } else {
|
---|
| 496 | if (-1!=GetFileAttributesA(destfn))
|
---|
| 497 | if (!DeleteFileA(destfn)) {
|
---|
| 498 | xret|=_error2vif(GetLastError())|VIF_CANNOTDELETE;
|
---|
| 499 | DeleteFileA(tmpfn);
|
---|
| 500 | LZClose(hfsrc);
|
---|
| 501 | return xret;
|
---|
| 502 | }
|
---|
[10296] | 503 | if ((!(flags & VIFF_DONTDELETEOLD)) &&
|
---|
| 504 | curdir &&
|
---|
[2347] | 505 | *curdir &&
|
---|
| 506 | lstrcmpiA(curdir,pdest)
|
---|
| 507 | ) {
|
---|
| 508 | char curfn[260];
|
---|
| 509 |
|
---|
| 510 | sprintf(curfn,"%s\\%s",curdir,destfilename);
|
---|
[10296] | 511 | if (INVALID_FILE_ATTRIBUTES != GetFileAttributesA(curfn)) {
|
---|
[2347] | 512 | /* FIXME: check if in use ... if it is, VIF_CANNOTDELETECUR */
|
---|
| 513 | if (!DeleteFileA(curfn))
|
---|
| 514 | xret|=_error2vif(GetLastError())|VIF_CANNOTDELETECUR;
|
---|
| 515 | }
|
---|
| 516 | }
|
---|
| 517 | if (!MoveFileA(tmpfn,destfn)) {
|
---|
| 518 | xret|=_error2vif(GetLastError())|VIF_CANNOTRENAME;
|
---|
| 519 | DeleteFileA(tmpfn);
|
---|
| 520 | }
|
---|
| 521 | }
|
---|
| 522 | LZClose(hfsrc);
|
---|
| 523 | return xret;
|
---|
| 524 | }
|
---|
| 525 |
|
---|
| 526 |
|
---|
[10296] | 527 | /******************************************************************************
|
---|
| 528 | * VerInstallFileW [VERSION.@]
|
---|
| 529 | */
|
---|
[2347] | 530 | DWORD WINAPI VerInstallFileW(
|
---|
| 531 | UINT flags,LPCWSTR srcfilename,LPCWSTR destfilename,LPCWSTR srcdir,
|
---|
| 532 | LPCWSTR destdir,LPCWSTR curdir,LPWSTR tmpfile,UINT *tmpfilelen )
|
---|
| 533 | {
|
---|
[10296] | 534 | LPSTR wsrcf = NULL, wsrcd = NULL, wdestf = NULL, wdestd = NULL, wtmpf = NULL, wcurd = NULL;
|
---|
[2347] | 535 | DWORD ret;
|
---|
[10296] | 536 | UINT len;
|
---|
[2347] | 537 |
|
---|
[10296] | 538 | if (srcfilename)
|
---|
| 539 | {
|
---|
| 540 | len = WideCharToMultiByte( CP_ACP, 0, srcfilename, -1, NULL, 0, NULL, NULL );
|
---|
| 541 | if ((wsrcf = HeapAlloc( GetProcessHeap(), 0, len )))
|
---|
| 542 | WideCharToMultiByte( CP_ACP, 0, srcfilename, -1, wsrcf, len, NULL, NULL );
|
---|
| 543 | }
|
---|
| 544 | if (srcdir)
|
---|
| 545 | {
|
---|
| 546 | len = WideCharToMultiByte( CP_ACP, 0, srcdir, -1, NULL, 0, NULL, NULL );
|
---|
| 547 | if ((wsrcd = HeapAlloc( GetProcessHeap(), 0, len )))
|
---|
| 548 | WideCharToMultiByte( CP_ACP, 0, srcdir, -1, wsrcd, len, NULL, NULL );
|
---|
| 549 | }
|
---|
| 550 | if (destfilename)
|
---|
| 551 | {
|
---|
| 552 | len = WideCharToMultiByte( CP_ACP, 0, destfilename, -1, NULL, 0, NULL, NULL );
|
---|
| 553 | if ((wdestf = HeapAlloc( GetProcessHeap(), 0, len )))
|
---|
| 554 | WideCharToMultiByte( CP_ACP, 0, destfilename, -1, wdestf, len, NULL, NULL );
|
---|
| 555 | }
|
---|
| 556 | if (destdir)
|
---|
| 557 | {
|
---|
| 558 | len = WideCharToMultiByte( CP_ACP, 0, destdir, -1, NULL, 0, NULL, NULL );
|
---|
| 559 | if ((wdestd = HeapAlloc( GetProcessHeap(), 0, len )))
|
---|
| 560 | WideCharToMultiByte( CP_ACP, 0, destdir, -1, wdestd, len, NULL, NULL );
|
---|
| 561 | }
|
---|
| 562 | if (curdir)
|
---|
| 563 | {
|
---|
| 564 | len = WideCharToMultiByte( CP_ACP, 0, curdir, -1, NULL, 0, NULL, NULL );
|
---|
| 565 | if ((wcurd = HeapAlloc( GetProcessHeap(), 0, len )))
|
---|
| 566 | WideCharToMultiByte( CP_ACP, 0, curdir, -1, wcurd, len, NULL, NULL );
|
---|
| 567 | }
|
---|
| 568 | len = *tmpfilelen * sizeof(WCHAR);
|
---|
| 569 | wtmpf = HeapAlloc( GetProcessHeap(), 0, len );
|
---|
| 570 | ret = VerInstallFileA(flags,wsrcf,wdestf,wsrcd,wdestd,wcurd,wtmpf,&len);
|
---|
[2347] | 571 | if (!ret)
|
---|
[10296] | 572 | *tmpfilelen = MultiByteToWideChar( CP_ACP, 0, wtmpf, -1, tmpfile, *tmpfilelen );
|
---|
| 573 | else if (ret & VIF_BUFFTOOSMALL)
|
---|
| 574 | *tmpfilelen = len; /* FIXME: not correct */
|
---|
| 575 |
|
---|
[2347] | 576 | HeapFree( GetProcessHeap(), 0, wsrcf );
|
---|
| 577 | HeapFree( GetProcessHeap(), 0, wsrcd );
|
---|
| 578 | HeapFree( GetProcessHeap(), 0, wdestf );
|
---|
| 579 | HeapFree( GetProcessHeap(), 0, wdestd );
|
---|
| 580 | HeapFree( GetProcessHeap(), 0, wtmpf );
|
---|
[10296] | 581 | HeapFree( GetProcessHeap(), 0, wcurd );
|
---|
[2347] | 582 | return ret;
|
---|
| 583 | }
|
---|