server: Send WM_WINE_SETCURSOR with the thread input cursor handle.
[wine.git] / dlls / version / version.c
blobbed2d0c7bac06ab74e0dfe75cd1dbd305f01d59e
1 /*
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
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
30 #include <sys/types.h>
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winver.h"
35 #include "winnls.h"
36 #include "lzexpand.h"
37 #include "winerror.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(ver);
42 static LPBYTE
43 _fetch_versioninfo(LPSTR fn,VS_FIXEDFILEINFO **vffi) {
44 DWORD alloclen;
45 LPBYTE buf;
46 DWORD ret;
48 alloclen = 1000;
49 buf=HeapAlloc(GetProcessHeap(), 0, alloclen);
50 if(buf == NULL) {
51 WARN("Memory exhausted while fetching version info!\n");
52 return NULL;
54 while (1) {
55 ret = GetFileVersionInfoA(fn,0,alloclen,buf);
56 if (!ret) {
57 HeapFree(GetProcessHeap(), 0, buf);
58 return NULL;
60 if (alloclen<*(WORD*)buf) {
61 alloclen = *(WORD*)buf;
62 HeapFree(GetProcessHeap(), 0, buf);
63 buf = HeapAlloc(GetProcessHeap(), 0, alloclen);
64 if(buf == NULL) {
65 WARN("Memory exhausted while fetching version info!\n");
66 return NULL;
68 } else {
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);
74 return buf;
79 static DWORD
80 _error2vif(DWORD error) {
81 switch (error) {
82 case ERROR_ACCESS_DENIED:
83 return VIF_ACCESSVIOLATION;
84 case ERROR_SHARING_VIOLATION:
85 return VIF_SHARINGVIOLATION;
86 default:
87 return 0;
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 )
99 LPCSTR pdest;
100 char destfn[260],tmpfn[260],srcfn[260];
101 HFILE hfsrc,hfdst;
102 DWORD attr,xret,tmplast;
103 LONG ret;
104 LPBYTE buf1,buf2;
105 OFSTRUCT ofs;
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);
111 xret = 0;
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);
118 if (hfsrc < 0)
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) {
125 LZClose(hfsrc);
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) {
132 if (tmpfile[0]) {
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) {
142 char *s;
144 GetTempFileNameA(pdest,"ver",0,tmpfn); /* should not fail ... */
145 s=strrchr(tmpfn,'\\');
146 if (s)
147 tmplast = s-tmpfn;
148 else
149 tmplast = 0;
150 hfdst = OpenFile(tmpfn,&ofs,OF_CREATE);
151 if (hfdst == HFILE_ERROR) {
152 LZClose(hfsrc);
153 return VIF_CANNOTCREATE; /* | translated dos error */
155 ret = LZCopy(hfsrc,hfdst);
156 _lclose(hfdst);
157 if (ret < 0) {
158 /* translate LZ errors into VIF_xxx */
159 switch (ret) {
160 case LZERROR_BADINHANDLE:
161 case LZERROR_READ:
162 case LZERROR_BADVALUE:
163 case LZERROR_UNKNOWNALG:
164 xret = VIF_CANNOTREADSRC;
165 break;
166 case LZERROR_BADOUTHANDLE:
167 case LZERROR_WRITE:
168 xret = VIF_OUTOFSPACE;
169 break;
170 case LZERROR_GLOBALLOC:
171 case LZERROR_GLOBLOCK:
172 xret = VIF_OUTOFMEMORY;
173 break;
174 default: /* unknown error, should not happen */
175 FIXME("Unknown LZCopy error %ld, ignoring.\n", ret);
176 xret = 0;
177 break;
179 if (xret) {
180 LZClose(hfsrc);
181 return xret;
185 if (!(flags & VIFF_FORCEINSTALL)) {
186 VS_FIXEDFILEINFO *destvffi,*tmpvffi;
187 buf1 = _fetch_versioninfo(destfn,&destvffi);
188 if (buf1) {
189 buf2 = _fetch_versioninfo(tmpfn,&tmpvffi);
190 if (buf2) {
191 char *tbuf1,*tbuf2;
192 static const CHAR trans_array[] = "\\VarFileInfo\\Translation";
193 UINT len1,len2;
195 len1=len2=40;
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);
217 } else
218 xret=VIF_MISMATCH|VIF_SRCOLD;
219 HeapFree(GetProcessHeap(), 0, buf1);
222 if (xret) {
223 if (*tmpfilelen<strlen(tmpfn+tmplast)) {
224 xret|=VIF_BUFFTOOSMALL;
225 DeleteFileA(tmpfn);
226 } else {
227 strcpy(tmpfile,tmpfn+tmplast);
228 *tmpfilelen = strlen(tmpfn+tmplast)+1;
229 xret|=VIF_TEMPFILE;
231 } else {
232 if (INVALID_FILE_ATTRIBUTES!=GetFileAttributesA(destfn))
233 if (!DeleteFileA(destfn)) {
234 xret|=_error2vif(GetLastError())|VIF_CANNOTDELETE;
235 DeleteFileA(tmpfn);
236 LZClose(hfsrc);
237 return xret;
239 if ((!(flags & VIFF_DONTDELETEOLD)) &&
240 curdir &&
241 *curdir &&
242 lstrcmpiA(curdir,pdest)
244 char curfn[260];
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;
255 DeleteFileA(tmpfn);
258 LZClose(hfsrc);
259 return xret;
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;
271 DWORD ret = 0;
272 UINT len;
274 if (srcfilename)
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 );
279 else
280 ret = VIF_OUTOFMEMORY;
282 if (srcdir && !ret)
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 );
287 else
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 );
295 else
296 ret = VIF_OUTOFMEMORY;
298 if (destdir && !ret)
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 );
303 else
304 ret = VIF_OUTOFMEMORY;
306 if (curdir && !ret)
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 );
311 else
312 ret = VIF_OUTOFMEMORY;
314 if (!ret)
316 len = *tmpfilelen * sizeof(WCHAR);
317 wtmpf = HeapAlloc( GetProcessHeap(), 0, len );
318 if (!wtmpf)
319 ret = VIF_OUTOFMEMORY;
321 if (!ret)
322 ret = VerInstallFileA(flags,wsrcf,wdestf,wsrcd,wdestd,wcurd,wtmpf,&len);
323 if (!ret)
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 );
334 return ret;