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>
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(ver
);
45 _fetch_versioninfo(LPSTR fn
,VS_FIXEDFILEINFO
**vffi
) {
51 buf
=HeapAlloc(GetProcessHeap(), 0, alloclen
);
53 WARN("Memory exhausted while fetching version info!\n");
57 ret
= GetFileVersionInfoA(fn
,0,alloclen
,buf
);
59 HeapFree(GetProcessHeap(), 0, buf
);
62 if (alloclen
<*(WORD
*)buf
) {
63 alloclen
= *(WORD
*)buf
;
64 HeapFree(GetProcessHeap(), 0, buf
);
65 buf
= HeapAlloc(GetProcessHeap(), 0, alloclen
);
67 WARN("Memory exhausted while fetching version info!\n");
71 *vffi
= (VS_FIXEDFILEINFO
*)(buf
+0x14);
72 if ((*vffi
)->dwSignature
== 0x004f0049) /* hack to detect unicode */
73 *vffi
= (VS_FIXEDFILEINFO
*)(buf
+0x28);
74 if ((*vffi
)->dwSignature
!= VS_FFI_SIGNATURE
)
75 WARN("Bad VS_FIXEDFILEINFO signature 0x%08lx\n",(*vffi
)->dwSignature
);
82 _error2vif(DWORD error
) {
84 case ERROR_ACCESS_DENIED
:
85 return VIF_ACCESSVIOLATION
;
86 case ERROR_SHARING_VIOLATION
:
87 return VIF_SHARINGVIOLATION
;
94 /******************************************************************************
95 * VerInstallFileA [VERSION.@]
97 DWORD WINAPI
VerInstallFileA(
98 DWORD flags
,LPCSTR srcfilename
,LPCSTR destfilename
,LPCSTR srcdir
,
99 LPCSTR destdir
,LPCSTR curdir
,LPSTR tmpfile
,PUINT tmpfilelen
)
102 char destfn
[260],tmpfn
[260],srcfn
[260];
104 DWORD attr
,xret
,tmplast
;
109 TRACE("(%lx,%s,%s,%s,%s,%s,%p,%d)\n",
110 flags
,debugstr_a(srcfilename
),debugstr_a(destfilename
),
111 debugstr_a(srcdir
),debugstr_a(destdir
),debugstr_a(curdir
),
112 tmpfile
,*tmpfilelen
);
114 if (!srcdir
|| !srcfilename
) return VIF_CANNOTREADSRC
;
115 sprintf(srcfn
,"%s\\%s",srcdir
,srcfilename
);
116 if (!destdir
|| !*destdir
) pdest
= srcdir
;
117 else pdest
= destdir
;
118 sprintf(destfn
,"%s\\%s",pdest
,destfilename
);
119 hfsrc
=LZOpenFileA(srcfn
,&ofs
,OF_READ
);
121 return VIF_CANNOTREADSRC
;
122 sprintf(tmpfn
,"%s\\%s",pdest
,destfilename
);
123 tmplast
=strlen(pdest
)+1;
124 attr
= GetFileAttributesA(tmpfn
);
125 if (attr
!= INVALID_FILE_ATTRIBUTES
) {
126 if (attr
& FILE_ATTRIBUTE_READONLY
) {
128 return VIF_WRITEPROT
;
130 /* FIXME: check if file currently in use and return VIF_FILEINUSE */
132 attr
= INVALID_FILE_ATTRIBUTES
;
133 if (flags
& VIFF_FORCEINSTALL
) {
135 sprintf(tmpfn
,"%s\\%s",pdest
,tmpfile
);
136 tmplast
= strlen(pdest
)+1;
137 attr
= GetFileAttributesA(tmpfn
);
138 /* if it exists, it has been copied by the call before.
139 * we jump over the copy part...
143 if (attr
== INVALID_FILE_ATTRIBUTES
) {
146 GetTempFileNameA(pdest
,"ver",0,tmpfn
); /* should not fail ... */
147 s
=strrchr(tmpfn
,'\\');
152 hfdst
= OpenFile(tmpfn
,&ofs
,OF_CREATE
);
153 if (hfdst
== HFILE_ERROR
) {
155 return VIF_CANNOTCREATE
; /* | translated dos error */
157 ret
= LZCopy(hfsrc
,hfdst
);
160 /* translate LZ errors into VIF_xxx */
162 case LZERROR_BADINHANDLE
:
164 case LZERROR_BADVALUE
:
165 case LZERROR_UNKNOWNALG
:
166 xret
= VIF_CANNOTREADSRC
;
168 case LZERROR_BADOUTHANDLE
:
170 xret
= VIF_OUTOFSPACE
;
172 case LZERROR_GLOBALLOC
:
173 case LZERROR_GLOBLOCK
:
174 xret
= VIF_OUTOFMEMORY
;
176 default: /* unknown error, should not happen */
177 FIXME("Unknown LZCopy error %ld, ignoring.\n", ret
);
187 if (!(flags
& VIFF_FORCEINSTALL
)) {
188 VS_FIXEDFILEINFO
*destvffi
,*tmpvffi
;
189 buf1
= _fetch_versioninfo(destfn
,&destvffi
);
191 buf2
= _fetch_versioninfo(tmpfn
,&tmpvffi
);
194 static const CHAR trans_array
[] = "\\VarFileInfo\\Translation";
199 /* compare file versions */
200 if ((destvffi
->dwFileVersionMS
> tmpvffi
->dwFileVersionMS
)||
201 ((destvffi
->dwFileVersionMS
==tmpvffi
->dwFileVersionMS
)&&
202 (destvffi
->dwFileVersionLS
> tmpvffi
->dwFileVersionLS
)
205 xret
|= VIF_MISMATCH
|VIF_SRCOLD
;
206 /* compare filetypes and filesubtypes */
207 if ((destvffi
->dwFileType
!=tmpvffi
->dwFileType
) ||
208 (destvffi
->dwFileSubtype
!=tmpvffi
->dwFileSubtype
)
210 xret
|= VIF_MISMATCH
|VIF_DIFFTYPE
;
211 if (VerQueryValueA(buf1
,trans_array
,(LPVOID
*)&tbuf1
,&len1
) &&
212 VerQueryValueA(buf2
,trans_array
,(LPVOID
*)&tbuf2
,&len2
)
214 /* Do something with tbuf1 and tbuf2
215 * generates DIFFLANG|MISMATCH
218 HeapFree(GetProcessHeap(), 0, buf2
);
220 xret
=VIF_MISMATCH
|VIF_SRCOLD
;
221 HeapFree(GetProcessHeap(), 0, buf1
);
225 if (*tmpfilelen
<strlen(tmpfn
+tmplast
)) {
226 xret
|=VIF_BUFFTOOSMALL
;
229 strcpy(tmpfile
,tmpfn
+tmplast
);
230 *tmpfilelen
= strlen(tmpfn
+tmplast
)+1;
234 if (INVALID_FILE_ATTRIBUTES
!=GetFileAttributesA(destfn
))
235 if (!DeleteFileA(destfn
)) {
236 xret
|=_error2vif(GetLastError())|VIF_CANNOTDELETE
;
241 if ((!(flags
& VIFF_DONTDELETEOLD
)) &&
244 lstrcmpiA(curdir
,pdest
)
248 sprintf(curfn
,"%s\\%s",curdir
,destfilename
);
249 if (INVALID_FILE_ATTRIBUTES
!= GetFileAttributesA(curfn
)) {
250 /* FIXME: check if in use ... if it is, VIF_CANNOTDELETECUR */
251 if (!DeleteFileA(curfn
))
252 xret
|=_error2vif(GetLastError())|VIF_CANNOTDELETECUR
;
255 if (!MoveFileA(tmpfn
,destfn
)) {
256 xret
|=_error2vif(GetLastError())|VIF_CANNOTRENAME
;
265 /******************************************************************************
266 * VerInstallFileW [VERSION.@]
268 DWORD WINAPI
VerInstallFileW(
269 DWORD flags
,LPCWSTR srcfilename
,LPCWSTR destfilename
,LPCWSTR srcdir
,
270 LPCWSTR destdir
,LPCWSTR curdir
,LPWSTR tmpfile
,PUINT tmpfilelen
)
272 LPSTR wsrcf
= NULL
, wsrcd
= NULL
, wdestf
= NULL
, wdestd
= NULL
, wtmpf
= NULL
, wcurd
= NULL
;
278 len
= WideCharToMultiByte( CP_ACP
, 0, srcfilename
, -1, NULL
, 0, NULL
, NULL
);
279 if ((wsrcf
= HeapAlloc( GetProcessHeap(), 0, len
)))
280 WideCharToMultiByte( CP_ACP
, 0, srcfilename
, -1, wsrcf
, len
, NULL
, NULL
);
282 ret
= VIF_OUTOFMEMORY
;
286 len
= WideCharToMultiByte( CP_ACP
, 0, srcdir
, -1, NULL
, 0, NULL
, NULL
);
287 if ((wsrcd
= HeapAlloc( GetProcessHeap(), 0, len
)))
288 WideCharToMultiByte( CP_ACP
, 0, srcdir
, -1, wsrcd
, len
, NULL
, NULL
);
290 ret
= VIF_OUTOFMEMORY
;
292 if (destfilename
&& !ret
)
294 len
= WideCharToMultiByte( CP_ACP
, 0, destfilename
, -1, NULL
, 0, NULL
, NULL
);
295 if ((wdestf
= HeapAlloc( GetProcessHeap(), 0, len
)))
296 WideCharToMultiByte( CP_ACP
, 0, destfilename
, -1, wdestf
, len
, NULL
, NULL
);
298 ret
= VIF_OUTOFMEMORY
;
302 len
= WideCharToMultiByte( CP_ACP
, 0, destdir
, -1, NULL
, 0, NULL
, NULL
);
303 if ((wdestd
= HeapAlloc( GetProcessHeap(), 0, len
)))
304 WideCharToMultiByte( CP_ACP
, 0, destdir
, -1, wdestd
, len
, NULL
, NULL
);
306 ret
= VIF_OUTOFMEMORY
;
310 len
= WideCharToMultiByte( CP_ACP
, 0, curdir
, -1, NULL
, 0, NULL
, NULL
);
311 if ((wcurd
= HeapAlloc( GetProcessHeap(), 0, len
)))
312 WideCharToMultiByte( CP_ACP
, 0, curdir
, -1, wcurd
, len
, NULL
, NULL
);
314 ret
= VIF_OUTOFMEMORY
;
318 len
= *tmpfilelen
* sizeof(WCHAR
);
319 wtmpf
= HeapAlloc( GetProcessHeap(), 0, len
);
321 ret
= VIF_OUTOFMEMORY
;
324 ret
= VerInstallFileA(flags
,wsrcf
,wdestf
,wsrcd
,wdestd
,wcurd
,wtmpf
,&len
);
326 *tmpfilelen
= MultiByteToWideChar( CP_ACP
, 0, wtmpf
, -1, tmpfile
, *tmpfilelen
);
327 else if (ret
& VIF_BUFFTOOSMALL
)
328 *tmpfilelen
= len
; /* FIXME: not correct */
330 HeapFree( GetProcessHeap(), 0, wsrcf
);
331 HeapFree( GetProcessHeap(), 0, wsrcd
);
332 HeapFree( GetProcessHeap(), 0, wdestf
);
333 HeapFree( GetProcessHeap(), 0, wdestd
);
334 HeapFree( GetProcessHeap(), 0, wtmpf
);
335 HeapFree( GetProcessHeap(), 0, wcurd
);