source: trunk/src/setupapi/virtcopy.c@ 9403

Last change on this file since 9403 was 9403, checked in by sandervl, 23 years ago

Wine resync

File size: 21.1 KB
Line 
1/*
2 * SetupAPI virtual copy operations
3 *
4 * Copyright 2001 Andreas Mohr
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * FIXME: we now rely on builtin setupapi.dll for dialog resources.
21 * This is bad ! We ought to have 16bit resource handling working.
22 */
23
24#include <string.h>
25#include "winbase.h"
26#include "winuser.h"
27#include "winreg.h"
28#include "setupapi.h"
29#include "setupx16.h"
30#include "setupapi_private.h"
31#include "wine/debug.h"
32
33WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
34
35/* ### start build ### */
36extern WORD CALLBACK VCP_CallTo16_word_lwwll(FARPROC16,LPVOID,UINT16,WPARAM,LPARAM,LPARAM);
37/* ### stop build ### */
38
39static FARPROC16 VCP_Proc = NULL;
40static LPARAM VCP_MsgRef = 0;
41
42#define VCP_CALLBACK(obj,msg,wParam,lParam,lParamRef) \
43 (VCP_Proc) ? \
44 VCP_CallTo16_word_lwwll(VCP_Proc, obj,msg,wParam,lParam,lParamRef) : OK;
45
46static BOOL VCP_opened = FALSE;
47
48static VCPSTATUS vcp_status;
49
50static HINSTANCE SETUPAPI_hInstance;
51
52/****************************** VHSTR management ******************************/
53
54/*
55 * This is a totally braindead implementation for now;
56 * I don't care about speed at all ! Size and implementation time
57 * is much more important IMHO. I could have created some sophisticated
58 * tree structure, but... what the hell ! :-)
59 */
60typedef struct {
61 DWORD refcount;
62 LPCSTR pStr;
63} VHSTR_STRUCT;
64
65static VHSTR_STRUCT **vhstrlist = NULL;
66static VHSTR vhstr_alloc = 0;
67
68#define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount))
69
70/***********************************************************************
71 * vsmStringAdd (SETUPX.207)
72 */
73VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName)
74{
75 VHSTR n;
76 VHSTR index = 0xffff;
77 HANDLE heap;
78
79 TRACE("add string '%s'\n", lpszName);
80 /* search whether string already inserted */
81 TRACE("searching for existing string...\n");
82 for (n = 0; n < vhstr_alloc; n++)
83 {
84 if ((vhstrlist[n]) && (vhstrlist[n]->refcount))
85 {
86 TRACE("checking item: %d\n", n);
87 if (!strcmp(vhstrlist[n]->pStr, lpszName))
88 {
89 TRACE("found\n");
90 vhstrlist[n]->refcount++;
91 return n;
92 }
93 }
94 }
95
96 /* hmm, not found yet, let's insert it */
97 TRACE("inserting item\n");
98 for (n = 0; n < vhstr_alloc; n++)
99 {
100 if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount)))
101 {
102 index = n;
103 break;
104 }
105 }
106 heap = GetProcessHeap();
107 if (n == vhstr_alloc) /* hmm, no free index found yet */
108 {
109 index = vhstr_alloc;
110 vhstr_alloc += 20;
111 vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
112 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
113 }
114 if (index == 0xffff)
115 return 0xffff; /* failure */
116 if (!vhstrlist[index])
117 vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT));
118 vhstrlist[index]->refcount = 1;
119 vhstrlist[index]->pStr = HeapAlloc(heap, 0, strlen(lpszName)+1);
120 strcpy((LPSTR)vhstrlist[index]->pStr, lpszName);
121 return index;
122}
123
124/***********************************************************************
125 * vsmStringDelete (SETUPX.206)
126 */
127INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
128{
129 if (VALID_VHSTR(vhstr))
130 {
131 vhstrlist[vhstr]->refcount--;
132 if (!vhstrlist[vhstr]->refcount)
133 {
134 HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
135 vhstrlist[vhstr]->pStr = NULL;
136 }
137 return VCPN_OK;
138 }
139
140 /* string not found */
141 return VCPN_FAIL;
142}
143
144/*
145 * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
146 */
147VHSTR WINAPI vsmStringFind16(LPCSTR lpszName)
148{
149 WORD n;
150 for (n = 0; n < vhstr_alloc; n++)
151 if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName)))
152 return n;
153 return 0xffff;
154}
155
156/***********************************************************************
157 * vsmGetStringName (SETUPX.205)
158 *
159 * Pretty correct, I guess
160 */
161INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
162{
163 if (VALID_VHSTR(vhstr))
164 {
165 int len = strlen(vhstrlist[vhstr]->pStr)+1;
166 if (cbBuffer >= len)
167 {
168 if (lpszBuffer)
169 strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
170 return len;
171 }
172 }
173 return VCPN_FAIL;
174}
175
176/***********************************************************************
177 * vsmStringCompare (not exported from a standard SETUPX.DLL, it seems)
178 */
179INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB)
180{
181 if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB)))
182 return VCPN_FAIL; /* correct ? */
183 return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr);
184}
185
186/***********************************************************************
187 * vsmGetStringRawName (SETUPX.208)
188 */
189LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
190{
191 return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
192}
193
194
195/***************************** VIRTNODE management ****************************/
196static LPVIRTNODE *pvnlist = NULL;
197static DWORD vn_num = 0;
198static DWORD vn_last = 0;
199
200RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
201{
202 HANDLE heap;
203 LPVIRTNODE lpvn;
204 RETERR16 cbres;
205
206 while (vn_last < vn_num)
207 {
208 if (pvnlist[vn_last] == NULL)
209 break;
210 vn_last++;
211 }
212 heap = GetProcessHeap();
213 if (vn_last == vn_num)
214 {
215 vn_num += 20;
216 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
217 sizeof(LPVIRTNODE *) * vn_num);
218 }
219 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
220 lpvn = pvnlist[vn_last];
221 vn_last++;
222
223 lpvn->cbSize = sizeof(VIRTNODE);
224
225 if (vfsSrc)
226 memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC));
227
228 if (vfsDst)
229 memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC));
230
231 lpvn->fl = fl;
232 lpvn->lParam = lParam;
233 lpvn->lpExpandVtbl = lpExpandVtbl;
234
235 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
236
237 cbres = VCP_CALLBACK(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
238 lpvn->fl |= VFNL_CREATED;
239 cbres = VCP_CALLBACK(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);
240
241 return OK;
242}
243
244BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
245{
246 DWORD n;
247 RETERR16 cbres;
248
249 for (n = 0; n < vn_last; n++)
250 {
251 if (pvnlist[n] == lpvnDel)
252 {
253 cbres = VCP_CALLBACK(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
254 HeapFree(GetProcessHeap(), 0, lpvnDel);
255 pvnlist[n] = NULL;
256 return TRUE;
257 }
258 }
259 return FALSE;
260}
261
262/***********************************************************************
263 * VcpOpen (SETUPX.200)
264 *
265 * Sets up a virtual copy operation.
266 * This means that functions such as GenInstall()
267 * create a VIRTNODE struct for every file to be touched in a .INF file
268 * instead of actually touching the file.
269 * The actual copy/move/rename gets started when VcpClose or
270 * VcpFlush is called; several different callbacks are made
271 * (copy, rename, open, close, version conflicts, ...) on every file copied.
272 */
273RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
274{
275 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
276 if (VCP_opened)
277 return ERR_VCP_BUSY;
278
279 VCP_Proc = (FARPROC16)vifproc;
280 VCP_MsgRef = lparamMsgRef;
281
282 /* load SETUPAPI needed for dialog resources etc. */
283 SETUPAPI_hInstance = LoadLibraryA("setupapi.dll");
284 if (!SETUPAPI_hInstance)
285 {
286 ERR("Could not load sibling setupapi.dll\n");
287 return ERR_VCP_NOMEM;
288 }
289 VCP_opened = TRUE;
290 return OK;
291}
292
293/***********************************************************************
294 * VcpQueueCopy [SETUPX.13]
295 *
296 * lpExpandVtbl seems to be deprecated.
297 * fl are the CNFL_xxx and VNFL_xxx flags.
298 * lParam are the VNLP_xxx flags.
299 */
300RETERR16 WINAPI VcpQueueCopy16(
301 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
302 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
303 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
304 LPEXPANDVTBL lpExpandVtbl,
305 WORD fl, LPARAM lParam
306)
307{
308 VCPFILESPEC vfsSrc, vfsDst;
309
310 if (!VCP_opened)
311 return ERR_VCP_NOTOPEN;
312
313 TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
314 lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
315
316 TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
317
318 vfsSrc.ldid = ldidSrc;
319 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
320 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
321
322 vfsDst.ldid = ldidDst;
323 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
324 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
325
326 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
327 lpExpandVtbl);
328}
329
330/***********************************************************************
331 * VcpQueueDelete [SETUPX.17]
332 *
333 * Is lParamRef the same as lParam in VcpQueueCopy ?
334 * Damn docu !! Err... which docu ?
335 */
336RETERR16 WINAPI VcpQueueDelete16(
337 LPCSTR lpszDstFileName,
338 LPCSTR lpszDstDir,
339 LOGDISKID16 ldidDst,
340 LPARAM lParamRef
341)
342{
343 VCPFILESPEC vfsDst;
344
345 if (!VCP_opened)
346 return ERR_VCP_NOTOPEN;
347
348 vfsDst.ldid = ldidDst;
349 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
350 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
351
352 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
353}
354
355/***********************************************************************
356 * VcpQueueRename [SETUPX.204]
357 *
358 */
359RETERR16 WINAPI VcpQueueRename16(
360 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
361 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
362 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
363 LPARAM lParam
364)
365{
366 VCPFILESPEC vfsSrc, vfsDst;
367
368 if (!VCP_opened)
369 return ERR_VCP_NOTOPEN;
370
371 vfsSrc.ldid = ldidSrc;
372 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
373 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
374
375 vfsDst.ldid = ldidDst;
376 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
377 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
378
379 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
380 0);
381}
382
383/***********************************************************************
384 * VcpEnumFiles (SETUPX.@)
385 */
386INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
387{
388 WORD n;
389
390 for (n = 0; n < vn_last; n++)
391 vep(pvnlist[n], lParamRef);
392
393 return 0; /* FIXME: return value ? */
394}
395
396/***********************************************************************
397 * VcpExplain (SETUPX.411)
398 */
399LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
400{
401 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
402 buffer[0] = '\0';
403 switch (dwWhat)
404 {
405 case VCPEX_SRC_FULL:
406 case VCPEX_DST_FULL:
407 {
408 LPVCPFILESPEC lpvfs =
409 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
410
411 /* if we have an ldid, use it, otherwise use the string */
412 /* from the vhstrlist array */
413 if (lpvfs->ldid != 0xffff)
414 CtlGetLddPath16(lpvfs->ldid, buffer);
415 else
416 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
417
418 strcat(buffer, "\\");
419 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
420 }
421 break;
422 default:
423 FIXME("%ld unimplemented !\n", dwWhat);
424 strcpy(buffer, "Unknown error");
425 break;
426 }
427 return buffer;
428}
429
430RETERR16 VCP_CheckPaths(void)
431{
432 DWORD n;
433 LPVIRTNODE lpvn;
434 RETERR16 cbres;
435
436 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
437 for (n = 0; n < vn_num; n++)
438 {
439 lpvn = pvnlist[n];
440 if (!lpvn) continue;
441 /* FIXME: check paths of all VIRTNODEs here ! */
442 cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
443 }
444 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
445 return OK;
446}
447
448RETERR16 VCP_CopyFiles(void)
449{
450 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
451 RETERR16 res = OK, cbres;
452 DWORD n;
453 LPVIRTNODE lpvn;
454
455 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
456 for (n = 0; n < vn_num; n++)
457 {
458 lpvn = pvnlist[n];
459 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
460 /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
461 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
462 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
463 /* FIXME: what is this VCPM_VSTATWRITE here for ?
464 * I guess it's to signal successful destination file creation */
465 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
466
467 /* FIXME: need to do the file copy in small chunks for notifications */
468 TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
469 /* perform the file copy */
470 if (!(CopyFileA(fn_src, fn_dst,
471 (lpvn->fl & VNLP_COPYIFEXISTS) ? FALSE : TRUE )))
472 {
473 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
474 res = ERR_VCP_IOFAIL;
475 }
476
477 vcp_status.prgFileRead.dwSoFar++;
478 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
479 vcp_status.prgFileWrite.dwSoFar++;
480 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
481 }
482
483 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
484 return res;
485}
486
487/***********************************************************************
488 * VcpFlush - internal (not exported), but documented
489 *
490 * VNFL_NOW is used for VcpFlush.
491 */
492RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
493{
494 return OK;
495}
496
497/***********************************************************************
498 * VcpClose (SETUPX.201)
499 *
500 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
501 * VCPM_VSTATCLOSEEND.
502 *
503 * fl gets VCPFL_xxx flags to indicate what to do with the
504 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
505 */
506RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
507{
508 RETERR16 res = OK;
509 WORD cbres = VCPN_PROCEED;
510
511 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
512
513 /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER
514 * is not set. This is done by VCP_CALLBACK(VCPM_NODECOMPARE) */
515
516 TRACE("#1\n");
517 memset(&vcp_status, 0, sizeof(VCPSTATUS));
518 /* yes, vcp_status.cbSize is 0 ! */
519 TRACE("#2\n");
520 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
521 TRACE("#3\n");
522
523 res = VCP_CheckPaths();
524 TRACE("#4\n");
525 if (res != OK)
526 return res; /* is this ok ? */
527 VCP_CopyFiles();
528
529 TRACE("#5\n");
530 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
531 TRACE("#6\n");
532 VCP_Proc = NULL;
533 FreeLibrary(SETUPAPI_hInstance);
534 VCP_opened = FALSE;
535 return OK;
536}
537
538RETERR16 VCP_RenameFiles(void)
539{
540 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
541 RETERR16 res = OK, cbres;
542 DWORD n;
543 LPVIRTNODE lpvn;
544
545 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
546 for (n = 0; n < vn_num; n++)
547 {
548 lpvn = pvnlist[n];
549 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
550 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
551 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
552 cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
553 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
554 res = ERR_VCP_IOFAIL;
555 else
556 VCP_VirtnodeDelete(lpvn);
557 }
558 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
559 return res;
560}
561
562/***********************************************************************
563 * vcpDefCallbackProc (SETUPX.202)
564 */
565RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
566 LPARAM lParam, LPARAM lParamRef)
567{
568 static int count = 0;
569 if (count < 10)
570 FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
571 lpvObj, uMsg, wParam, lParam, lParamRef);
572 count++;
573 return OK;
574}
575
576/********************* point-and-click stuff from here ***********************/
577
578static HWND hDlgCopy = 0;
579static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
580static char BackupDir[12];
581
582static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
583{
584 INT_PTR retval = FALSE;
585
586 if (iMsg == WM_INITDIALOG)
587 {
588 ShowWindow(hWndDlg, SW_SHOWNORMAL);
589 UpdateWindow(hWndDlg);
590 retval = TRUE;
591 }
592 return retval;
593}
594
595BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
596{
597 HRSRC hResInfo;
598 HGLOBAL hDlgTmpl32;
599
600 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), RT_DIALOGA)))
601 return FALSE;
602 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
603 !(*template32 = LockResource( hDlgTmpl32 )))
604 return FALSE;
605 return TRUE;
606}
607
608static LRESULT WINAPI
609VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
610{
611 if (uMsg != WM_CREATE)
612 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
613
614 switch (uMsg)
615 {
616 case WM_CREATE:
617 return 0;
618 default:
619 FIXME("%04x: unhandled.\n", uMsg);
620 }
621
622 return 0;
623}
624
625void VCP_UI_RegisterProgressClass(void)
626{
627 static BOOL registered = FALSE;
628 WNDCLASSA wndClass;
629
630 if (registered)
631 return;
632
633 registered = TRUE;
634 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
635 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
636 wndClass.lpfnWndProc = (WNDPROC)VCP_UI_FileCopyWndProc;
637 wndClass.cbClsExtra = 0;
638 wndClass.cbWndExtra = 0;
639 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
640 wndClass.hbrBackground = (HBRUSH)NULL;
641 wndClass.lpszClassName = "setupx_progress";
642
643 RegisterClassA (&wndClass);
644}
645
646RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
647{
648 LPCSTR file1, file2;
649 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
650 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
651 return (RETERR16)strcmp(file1, file2);
652}
653
654RETERR16 VCP_UI_CopyStart(void)
655{
656 LPCVOID template32;
657 char buf[256]; /* plenty */
658 BOOL dirty;
659 DWORD len;
660
661 /* FIXME: should be registered at DLL startup instead */
662 VCP_UI_RegisterProgressClass();
663 if (!(VCP_UI_GetDialogTemplate(&template32)))
664 return VCPN_FAIL;
665
666 if (vn_num > 10) /* hack */
667 {
668 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
669 VCP_UI_FileCopyDlgProc, 0);
670 if (!hDlgCopy)
671 return VCPN_FAIL;
672 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
673 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
674 }
675 strcpy(buf, REG_INSTALLEDFILES);
676 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
677 return VCPN_FAIL;
678 strcat(buf, REGPART_RENAME);
679 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
680 return VCPN_FAIL;
681 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
682 return VCPN_FAIL;
683 len = 1;
684 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
685 {
686 /* FIXME: what does SETUPX.DLL do in this case ? */
687 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
688 return VCPN_FAIL;
689 }
690 dirty = TRUE;
691 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
692 return VCPN_FAIL;
693 len = 12;
694 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len)))
695 strcpy(BackupDir, "VCM");
696
697 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
698 GetWindowsDirectoryA(buf, 256);
699 strcat(buf, "\\");
700 strcat(buf, BackupDir);
701 if (!(CreateDirectoryA(buf, NULL)))
702 return VCPN_FAIL;
703 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
704 return VCPN_FAIL;
705 RegCloseKey(hKeyConflict);
706
707 return VCPN_OK;
708}
709
710/***********************************************************************
711 * vcpUICallbackProc (SETUPX.213)
712 */
713RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
714 LPARAM lParam, LPARAM lParamRef)
715{
716 static int count = 0;
717 RETERR16 res = VCPN_OK, cbres;
718
719 if (count < 5)
720 FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n",
721 lpvObj, uMsg, wParam, lParam, lParamRef);
722 count++;
723 switch (uMsg)
724 {
725 /* unused messages, it seems */
726 case VCPM_DISKPREPINFO:
727
728 case VCPM_FILENEEDED:
729
730 case VCPM_NODECREATE:
731 case VCPM_NODEACCEPT:
732
733 case VCPM_VSTATCLOSESTART:
734 case VCPM_VSTATPATHCHECKSTART:
735 case VCPM_VSTATPATHCHECKEND:
736
737 case VCPM_CHECKPATH:
738 break;
739
740 /* the real stuff */
741 case VCPM_NODECOMPARE:
742 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
743 break;
744 case VCPM_VSTATREAD:
745 break;
746 case VCPM_VSTATWRITE:
747 cbres = VCP_CALLBACK(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
748 break;
749 case VCPM_VSTATCLOSEEND:
750 RegCloseKey(hKeyFiles);
751 RegCloseKey(hKeyRename);
752 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
753 break;
754 case VCPM_VSTATCOPYSTART:
755 res = VCP_UI_CopyStart();
756 break;
757 case VCPM_VSTATCOPYEND:
758 if (hDlgCopy) DestroyWindow(hDlgCopy);
759 break;
760 default:
761 FIXME("unhandled msg 0x%04x\n", uMsg);
762 }
763 return res;
764}
Note: See TracBrowser for help on using the repository browser.