2 * Implementation of VERSION.DLL
4 * Copyright 1996,1997 Marcus Meissner
5 * Copyright 1997 David Cuthbert
6 * Copyright 1999 Ulrich Weigand
7 * Copyright 2005 Paul Vriens
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include <sys/types.h>
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(ver
);
43 _fetch_versioninfo(LPSTR fn
,VS_FIXEDFILEINFO
**vffi
) {
49 buf
=HeapAlloc(GetProcessHeap(), 0, alloclen
);
51 WARN("Memory exhausted while fetching version info!\n");
55 ret
= GetFileVersionInfoA(fn
,0,alloclen
,buf
);
57 HeapFree(GetProcessHeap(), 0, buf
);
60 if (alloclen
<*(WORD
*)buf
) {
61 alloclen
= *(WORD
*)buf
;
62 HeapFree(GetProcessHeap(), 0, buf
);
63 buf
= HeapAlloc(GetProcessHeap(), 0, alloclen
);
65 WARN("Memory exhausted while fetching version info!\n");
69 *vffi
= (VS_FIXEDFILEINFO
*)(buf
+0x14);
70 if ((*vffi
)->dwSignature
== 0x004f0049) /* hack to detect unicode */
71 *vffi
= (VS_FIXEDFILEINFO
*)(buf
+0x28);
72 if ((*vffi
)->dwSignature
!= VS_FFI_SIGNATURE
)
73 WARN("Bad VS_FIXEDFILEINFO signature 0x%08lx\n",(*vffi
)->dwSignature
);
80 _error2vif(DWORD error
) {
82 case ERROR_ACCESS_DENIED
:
83 return VIF_ACCESSVIOLATION
;
84 case ERROR_SHARING_VIOLATION
:
85 return VIF_SHARINGVIOLATION
;
92 /******************************************************************************
93 * VerInstallFileA [VERSION.@]
95 DWORD WINAPI
VerInstallFileA(
96 DWORD flags
,LPCSTR srcfilename
,LPCSTR destfilename
,LPCSTR srcdir
,
97 LPCSTR destdir
,LPCSTR curdir
,LPSTR tmpfile
,PUINT tmpfilelen
)
100 char destfn
[260],tmpfn
[260],srcfn
[260];
102 DWORD attr
,xret
,tmplast
;
107 TRACE("(%lx,%s,%s,%s,%s,%s,%p,%d)\n",
108 flags
,debugstr_a(srcfilename
),debugstr_a(destfilename
),
109 debugstr_a(srcdir
),debugstr_a(destdir
),debugstr_a(curdir
),
110 tmpfile
,*tmpfilelen
);
112 if (!srcdir
|| !srcfilename
) return VIF_CANNOTREADSRC
;
113 sprintf(srcfn
,"%s\\%s",srcdir
,srcfilename
);
114 if (!destdir
|| !*destdir
) pdest
= srcdir
;
115 else pdest
= destdir
;
116 sprintf(destfn
,"%s\\%s",pdest
,destfilename
);
117 hfsrc
=LZOpenFileA(srcfn
,&ofs
,OF_READ
);
119 return VIF_CANNOTREADSRC
;
120 sprintf(tmpfn
,"%s\\%s",pdest
,destfilename
);
121 tmplast
=strlen(pdest
)+1;
122 attr
= GetFileAttributesA(tmpfn
);
123 if (attr
!= INVALID_FILE_ATTRIBUTES
) {
124 if (attr
& FILE_ATTRIBUTE_READONLY
) {
126 return VIF_WRITEPROT
;
128 /* FIXME: check if file currently in use and return VIF_FILEINUSE */
130 attr
= INVALID_FILE_ATTRIBUTES
;
131 if (flags
& VIFF_FORCEINSTALL
) {
133 sprintf(tmpfn
,"%s\\%s",pdest
,tmpfile
);
134 tmplast
= strlen(pdest
)+1;
135 attr
= GetFileAttributesA(tmpfn
);
136 /* if it exists, it has been copied by the call before.
137 * we jump over the copy part...
141 if (attr
== INVALID_FILE_ATTRIBUTES
) {
144 GetTempFileNameA(pdest
,"ver",0,tmpfn
); /* should not fail ... */
145 s
=strrchr(tmpfn
,'\\');
150 hfdst
= OpenFile(tmpfn
,&ofs
,OF_CREATE
);
151 if (hfdst
== HFILE_ERROR
) {
153 return VIF_CANNOTCREATE
; /* | translated dos error */
155 ret
= LZCopy(hfsrc
,hfdst
);
158 /* translate LZ errors into VIF_xxx */
160 case LZERROR_BADINHANDLE
:
162 case LZERROR_BADVALUE
:
163 case LZERROR_UNKNOWNALG
:
164 xret
= VIF_CANNOTREADSRC
;
166 case LZERROR_BADOUTHANDLE
:
168 xret
= VIF_OUTOFSPACE
;
170 case LZERROR_GLOBALLOC
:
171 case LZERROR_GLOBLOCK
:
172 xret
= VIF_OUTOFMEMORY
;
174 default: /* unknown error, should not happen */
175 FIXME("Unknown LZCopy error %ld, ignoring.\n", ret
);
185 if (!(flags
& VIFF_FORCEINSTALL
)) {
186 VS_FIXEDFILEINFO
*destvffi
,*tmpvffi
;
187 buf1
= _fetch_versioninfo(destfn
,&destvffi
);
189 buf2
= _fetch_versioninfo(tmpfn
,&tmpvffi
);
192 static const CHAR trans_array
[] = "\\VarFileInfo\\Translation";
197 /* compare file versions */
198 if ((destvffi
->dwFileVersionMS
> tmpvffi
->dwFileVersionMS
)||
199 ((destvffi
->dwFileVersionMS
==tmpvffi
->dwFileVersionMS
)&&
200 (destvffi
->dwFileVersionLS
> tmpvffi
->dwFileVersionLS
)
203 xret
|= VIF_MISMATCH
|VIF_SRCOLD
;
204 /* compare filetypes and filesubtypes */
205 if ((destvffi
->dwFileType
!=tmpvffi
->dwFileType
) ||
206 (destvffi
->dwFileSubtype
!=tmpvffi
->dwFileSubtype
)
208 xret
|= VIF_MISMATCH
|VIF_DIFFTYPE
;
209 if (VerQueryValueA(buf1
,trans_array
,(LPVOID
*)&tbuf1
,&len1
) &&
210 VerQueryValueA(buf2
,trans_array
,(LPVOID
*)&tbuf2
,&len2
)
212 /* Do something with tbuf1 and tbuf2
213 * generates DIFFLANG|MISMATCH
216 HeapFree(GetProcessHeap(), 0, buf2
);
218 xret
=VIF_MISMATCH
|VIF_SRCOLD
;
219 HeapFree(GetProcessHeap(), 0, buf1
);
223 if (*tmpfilelen
<strlen(tmpfn
+tmplast
)) {
224 xret
|=VIF_BUFFTOOSMALL
;
227 strcpy(tmpfile
,tmpfn
+tmplast
);
228 *tmpfilelen
= strlen(tmpfn
+tmplast
)+1;
232 if (INVALID_FILE_ATTRIBUTES
!=GetFileAttributesA(destfn
))
233 if (!DeleteFileA(destfn
)) {
234 xret
|=_error2vif(GetLastError())|VIF_CANNOTDELETE
;
239 if ((!(flags
& VIFF_DONTDELETEOLD
)) &&
242 lstrcmpiA(curdir
,pdest
)
246 sprintf(curfn
,"%s\\%s",curdir
,destfilename
);
247 if (INVALID_FILE_ATTRIBUTES
!= GetFileAttributesA(curfn
)) {
248 /* FIXME: check if in use ... if it is, VIF_CANNOTDELETECUR */
249 if (!DeleteFileA(curfn
))
250 xret
|=_error2vif(GetLastError())|VIF_CANNOTDELETECUR
;
253 if (!MoveFileA(tmpfn
,destfn
)) {
254 xret
|=_error2vif(GetLastError())|VIF_CANNOTRENAME
;
263 /******************************************************************************
264 * VerInstallFileW [VERSION.@]
266 DWORD WINAPI
VerInstallFileW(
267 DWORD flags
,LPCWSTR srcfilename
,LPCWSTR destfilename
,LPCWSTR srcdir
,
268 LPCWSTR destdir
,LPCWSTR curdir
,LPWSTR tmpfile
,PUINT tmpfilelen
)
270 LPSTR wsrcf
= NULL
, wsrcd
= NULL
, wdestf
= NULL
, wdestd
= NULL
, wtmpf
= NULL
, wcurd
= NULL
;
276 len
= WideCharToMultiByte( CP_ACP
, 0, srcfilename
, -1, NULL
, 0, NULL
, NULL
);
277 if ((wsrcf
= HeapAlloc( GetProcessHeap(), 0, len
)))
278 WideCharToMultiByte( CP_ACP
, 0, srcfilename
, -1, wsrcf
, len
, NULL
, NULL
);
280 ret
= VIF_OUTOFMEMORY
;
284 len
= WideCharToMultiByte( CP_ACP
, 0, srcdir
, -1, NULL
, 0, NULL
, NULL
);
285 if ((wsrcd
= HeapAlloc( GetProcessHeap(), 0, len
)))
286 WideCharToMultiByte( CP_ACP
, 0, srcdir
, -1, wsrcd
, len
, NULL
, NULL
);
288 ret
= VIF_OUTOFMEMORY
;
290 if (destfilename
&& !ret
)
292 len
= WideCharToMultiByte( CP_ACP
, 0, destfilename
, -1, NULL
, 0, NULL
, NULL
);
293 if ((wdestf
= HeapAlloc( GetProcessHeap(), 0, len
)))
294 WideCharToMultiByte( CP_ACP
, 0, destfilename
, -1, wdestf
, len
, NULL
, NULL
);
296 ret
= VIF_OUTOFMEMORY
;
300 len
= WideCharToMultiByte( CP_ACP
, 0, destdir
, -1, NULL
, 0, NULL
, NULL
);
301 if ((wdestd
= HeapAlloc( GetProcessHeap(), 0, len
)))
302 WideCharToMultiByte( CP_ACP
, 0, destdir
, -1, wdestd
, len
, NULL
, NULL
);
304 ret
= VIF_OUTOFMEMORY
;
308 len
= WideCharToMultiByte( CP_ACP
, 0, curdir
, -1, NULL
, 0, NULL
, NULL
);
309 if ((wcurd
= HeapAlloc( GetProcessHeap(), 0, len
)))
310 WideCharToMultiByte( CP_ACP
, 0, curdir
, -1, wcurd
, len
, NULL
, NULL
);
312 ret
= VIF_OUTOFMEMORY
;
316 len
= *tmpfilelen
* sizeof(WCHAR
);
317 wtmpf
= HeapAlloc( GetProcessHeap(), 0, len
);
319 ret
= VIF_OUTOFMEMORY
;
322 ret
= VerInstallFileA(flags
,wsrcf
,wdestf
,wsrcd
,wdestd
,wcurd
,wtmpf
,&len
);
324 *tmpfilelen
= MultiByteToWideChar( CP_ACP
, 0, wtmpf
, -1, tmpfile
, *tmpfilelen
);
325 else if (ret
& VIF_BUFFTOOSMALL
)
326 *tmpfilelen
= len
; /* FIXME: not correct */
328 HeapFree( GetProcessHeap(), 0, wsrcf
);
329 HeapFree( GetProcessHeap(), 0, wsrcd
);
330 HeapFree( GetProcessHeap(), 0, wdestf
);
331 HeapFree( GetProcessHeap(), 0, wdestd
);
332 HeapFree( GetProcessHeap(), 0, wtmpf
);
333 HeapFree( GetProcessHeap(), 0, wcurd
);