push 88479ebf0db14cda4b93d4622f90fdb1c98221ae
[wine/hacks.git] / dlls / setupapi / virtcopy.c
blobc2fded22ccc64de3544545d3ce448cfaae671aea
1 /*
2 * SetupAPI virtual copy operations
4 * Copyright 2001 Andreas Mohr
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * FIXME: we now rely on builtin setupapi.dll for dialog resources.
21 * This is bad ! We ought to have 16bit resource handling working.
24 #include <stdarg.h>
25 #include <string.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winreg.h"
30 #include "wownt32.h"
31 #include "winnls.h"
32 #include "setupapi.h"
33 #include "setupx16.h"
34 #include "setupapi_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
39 static FARPROC16 VCP_Proc = NULL;
40 static LPARAM VCP_MsgRef = 0;
42 static BOOL VCP_opened = FALSE;
44 static VCPSTATUS vcp_status;
46 static WORD VCP_Callback( LPVOID obj, UINT16 msg, WPARAM16 wParam, LPARAM lParam, LPARAM lParamRef )
48 WORD args[8];
49 DWORD ret = OK;
50 if (VCP_Proc)
52 args[7] = HIWORD(obj);
53 args[6] = LOWORD(obj);
54 args[5] = msg;
55 args[4] = wParam;
56 args[3] = HIWORD(lParam);
57 args[2] = LOWORD(lParam);
58 args[1] = HIWORD(lParamRef);
59 args[0] = LOWORD(lParamRef);
60 WOWCallback16Ex( (DWORD)VCP_Proc, WCB16_PASCAL, sizeof(args), args, &ret );
62 return (WORD)ret;
65 /****************************** VHSTR management ******************************/
68 * This is a totally braindead implementation for now;
69 * I don't care about speed at all ! Size and implementation time
70 * is much more important IMHO. I could have created some sophisticated
71 * tree structure, but... what the hell ! :-)
73 typedef struct {
74 DWORD refcount;
75 LPCSTR pStr;
76 } VHSTR_STRUCT;
78 static VHSTR_STRUCT **vhstrlist = NULL;
79 static VHSTR vhstr_alloc = 0;
81 #define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount))
83 /***********************************************************************
84 * vsmStringAdd (SETUPX.207)
86 VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName)
88 VHSTR n;
89 VHSTR index = 0xffff;
90 HANDLE heap;
91 LPSTR str;
93 TRACE("add string '%s'\n", lpszName);
94 /* search whether string already inserted */
95 TRACE("searching for existing string...\n");
96 for (n = 0; n < vhstr_alloc; n++)
98 if ((vhstrlist[n]) && (vhstrlist[n]->refcount))
100 TRACE("checking item: %d\n", n);
101 if (!strcmp(vhstrlist[n]->pStr, lpszName))
103 TRACE("found\n");
104 vhstrlist[n]->refcount++;
105 return n;
110 /* hmm, not found yet, let's insert it */
111 TRACE("inserting item\n");
112 for (n = 0; n < vhstr_alloc; n++)
114 if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount)))
116 index = n;
117 break;
120 heap = GetProcessHeap();
121 if (n == vhstr_alloc) /* hmm, no free index found yet */
123 index = vhstr_alloc;
124 vhstr_alloc += 20;
126 if (vhstrlist)
127 vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
128 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
129 else
130 vhstrlist = HeapAlloc(heap, HEAP_ZERO_MEMORY,
131 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
133 if (index == 0xffff)
134 return 0xffff; /* failure */
135 if (!vhstrlist[index])
136 vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT));
137 vhstrlist[index]->refcount = 1;
138 str = HeapAlloc(heap, 0, strlen(lpszName)+1);
139 strcpy(str, lpszName);
140 vhstrlist[index]->pStr = str;
141 return index;
144 /***********************************************************************
145 * vsmStringDelete (SETUPX.206)
147 INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
149 if (VALID_VHSTR(vhstr))
151 vhstrlist[vhstr]->refcount--;
152 if (!vhstrlist[vhstr]->refcount)
154 HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
155 vhstrlist[vhstr]->pStr = NULL;
157 return VCPN_OK;
160 /* string not found */
161 return VCPN_FAIL;
165 * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
167 VHSTR WINAPI vsmStringFind16(LPCSTR lpszName)
169 WORD n;
170 for (n = 0; n < vhstr_alloc; n++)
171 if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName)))
172 return n;
173 return 0xffff;
176 /***********************************************************************
177 * vsmGetStringName (SETUPX.205)
179 * Pretty correct, I guess
181 INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
183 if (VALID_VHSTR(vhstr))
185 int len = strlen(vhstrlist[vhstr]->pStr)+1;
186 if (cbBuffer >= len)
188 if (lpszBuffer)
189 strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
190 return len;
193 return VCPN_FAIL;
196 /***********************************************************************
197 * vsmStringCompare (not exported from a standard SETUPX.DLL, it seems)
199 INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB)
201 if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB)))
202 return VCPN_FAIL; /* correct ? */
203 return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr);
206 /***********************************************************************
207 * vsmGetStringRawName (SETUPX.208)
209 LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
211 return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
215 /***************************** VIRTNODE management ****************************/
216 static LPVIRTNODE *pvnlist = NULL;
217 static DWORD vn_num = 0;
218 static DWORD vn_last = 0;
220 static RETERR16 VCP_VirtnodeCreate(const VCPFILESPEC *vfsSrc, const VCPFILESPEC *vfsDst,
221 WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
223 HANDLE heap;
224 LPVIRTNODE lpvn;
225 RETERR16 cbres;
227 while (vn_last < vn_num)
229 if (pvnlist[vn_last] == NULL)
230 break;
231 vn_last++;
233 heap = GetProcessHeap();
234 if (vn_last == vn_num)
236 vn_num += 20;
237 if (pvnlist)
238 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
239 sizeof(LPVIRTNODE *) * vn_num);
240 else
241 pvnlist = HeapAlloc(heap, HEAP_ZERO_MEMORY,
242 sizeof(LPVIRTNODE *) * vn_num);
244 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
245 lpvn = pvnlist[vn_last];
246 vn_last++;
248 lpvn->cbSize = sizeof(VIRTNODE);
250 if (vfsSrc)
251 lpvn->vfsSrc = *vfsSrc;
253 if (vfsDst)
254 lpvn->vfsDst = *vfsDst;
256 lpvn->fl = fl;
257 lpvn->lParam = lParam;
258 lpvn->lpExpandVtbl = lpExpandVtbl;
260 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
262 cbres = VCP_Callback(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
263 lpvn->fl |= VFNL_CREATED;
264 cbres = VCP_Callback(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);
266 return OK;
269 #if 0
270 static BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
272 DWORD n;
273 RETERR16 cbres;
275 for (n = 0; n < vn_last; n++)
277 if (pvnlist[n] == lpvnDel)
279 cbres = VCP_Callback(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
280 HeapFree(GetProcessHeap(), 0, lpvnDel);
281 pvnlist[n] = NULL;
282 return TRUE;
285 return FALSE;
287 #endif
289 /***********************************************************************
290 * VcpOpen (SETUPX.200)
292 * Sets up a virtual copy operation.
293 * This means that functions such as GenInstall()
294 * create a VIRTNODE struct for every file to be touched in a .INF file
295 * instead of actually touching the file.
296 * The actual copy/move/rename gets started when VcpClose or
297 * VcpFlush is called; several different callbacks are made
298 * (copy, rename, open, close, version conflicts, ...) on every file copied.
300 RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
302 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
303 if (VCP_opened)
304 return ERR_VCP_BUSY;
306 VCP_Proc = (FARPROC16)vifproc;
307 VCP_MsgRef = lparamMsgRef;
309 VCP_opened = TRUE;
310 return OK;
313 /***********************************************************************
314 * VcpQueueCopy [SETUPX.13]
316 * lpExpandVtbl seems to be deprecated.
317 * fl are the CNFL_xxx and VNFL_xxx flags.
318 * lParam are the VNLP_xxx flags.
320 RETERR16 WINAPI VcpQueueCopy16(
321 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
322 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
323 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
324 LPEXPANDVTBL lpExpandVtbl,
325 WORD fl, LPARAM lParam
328 VCPFILESPEC vfsSrc, vfsDst;
330 if (!VCP_opened)
331 return ERR_VCP_NOTOPEN;
333 TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
334 lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
336 TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
338 vfsSrc.ldid = ldidSrc;
339 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
340 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
342 vfsDst.ldid = ldidDst;
343 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
344 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
346 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
347 lpExpandVtbl);
350 /***********************************************************************
351 * VcpQueueDelete [SETUPX.17]
353 * Is lParamRef the same as lParam in VcpQueueCopy ?
354 * Damn docu !! Err... which docu ?
356 RETERR16 WINAPI VcpQueueDelete16(
357 LPCSTR lpszDstFileName,
358 LPCSTR lpszDstDir,
359 LOGDISKID16 ldidDst,
360 LPARAM lParamRef
363 VCPFILESPEC vfsDst;
365 if (!VCP_opened)
366 return ERR_VCP_NOTOPEN;
368 vfsDst.ldid = ldidDst;
369 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
370 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
372 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
375 /***********************************************************************
376 * VcpQueueRename [SETUPX.204]
379 RETERR16 WINAPI VcpQueueRename16(
380 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
381 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
382 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
383 LPARAM lParam
386 VCPFILESPEC vfsSrc, vfsDst;
388 if (!VCP_opened)
389 return ERR_VCP_NOTOPEN;
391 vfsSrc.ldid = ldidSrc;
392 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
393 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
395 vfsDst.ldid = ldidDst;
396 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
397 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
399 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
403 /***********************************************************************
404 * VcpEnumFiles (SETUPX.@)
406 INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
408 WORD n;
410 for (n = 0; n < vn_last; n++)
411 vep(pvnlist[n], lParamRef);
413 return 0; /* FIXME: return value ? */
416 /***********************************************************************
417 * VcpExplain (SETUPX.411)
419 LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
421 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
422 buffer[0] = '\0';
423 switch (dwWhat)
425 case VCPEX_SRC_FULL:
426 case VCPEX_DST_FULL:
428 LPVCPFILESPEC lpvfs =
429 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
431 /* if we have an ldid, use it, otherwise use the string */
432 /* from the vhstrlist array */
433 if (lpvfs->ldid != 0xffff)
434 CtlGetLddPath16(lpvfs->ldid, buffer);
435 else
436 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
438 strcat(buffer, "\\");
439 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
441 break;
442 default:
443 FIXME("%d unimplemented !\n", dwWhat);
444 strcpy(buffer, "Unknown error");
445 break;
447 return buffer;
450 static RETERR16 VCP_CheckPaths(void)
452 DWORD n;
453 LPVIRTNODE lpvn;
454 RETERR16 cbres;
456 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
457 for (n = 0; n < vn_num; n++)
459 lpvn = pvnlist[n];
460 if (!lpvn) continue;
461 /* FIXME: check paths of all VIRTNODEs here ! */
462 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
464 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
465 return OK;
468 static RETERR16 VCP_CopyFiles(void)
470 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
471 RETERR16 res = OK, cbres;
472 DWORD n;
473 LPVIRTNODE lpvn;
475 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
476 for (n = 0; n < vn_num; n++)
478 lpvn = pvnlist[n];
479 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
480 /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
481 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
482 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
483 /* FIXME: what is this VCPM_VSTATWRITE here for ?
484 * I guess it's to signal successful destination file creation */
485 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
487 /* FIXME: need to do the file copy in small chunks for notifications */
488 TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
489 /* perform the file copy */
490 if (!(CopyFileA(fn_src, fn_dst,
491 (lpvn->fl & VNLP_COPYIFEXISTS) ? FALSE : TRUE )))
493 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
494 res = ERR_VCP_IOFAIL;
497 vcp_status.prgFileRead.dwSoFar++;
498 cbres = VCP_Callback(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
499 vcp_status.prgFileWrite.dwSoFar++;
500 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
503 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
504 return res;
507 /***********************************************************************
508 * VcpFlush - internal (not exported), but documented
510 * VNFL_NOW is used for VcpFlush.
512 RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
514 return OK;
517 /***********************************************************************
518 * VcpClose (SETUPX.201)
520 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
521 * VCPM_VSTATCLOSEEND.
523 * fl gets VCPFL_xxx flags to indicate what to do with the
524 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
526 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
528 RETERR16 res = OK;
529 WORD cbres = VCPN_PROCEED;
531 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
533 /* FIXME: needs to sort VIRTNODEs in case VCPFL_INSPECIFIEDORDER
534 * is not set. This is done by VCP_Callback(VCPM_NODECOMPARE) */
536 TRACE("#1\n");
537 memset(&vcp_status, 0, sizeof(VCPSTATUS));
538 /* yes, vcp_status.cbSize is 0 ! */
539 TRACE("#2\n");
540 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
541 TRACE("#3\n");
543 res = VCP_CheckPaths();
544 TRACE("#4\n");
545 if (res != OK)
546 return res; /* is this ok ? */
547 VCP_CopyFiles();
549 TRACE("#5\n");
550 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
551 TRACE("#6\n");
552 VCP_Proc = NULL;
553 VCP_opened = FALSE;
554 return OK;
557 #if 0
558 static RETERR16 VCP_RenameFiles(void)
560 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
561 RETERR16 res = OK, cbres;
562 DWORD n;
563 LPVIRTNODE lpvn;
565 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
566 for (n = 0; n < vn_num; n++)
568 lpvn = pvnlist[n];
569 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
570 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
571 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
572 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
573 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
574 res = ERR_VCP_IOFAIL;
575 else
576 VCP_VirtnodeDelete(lpvn);
578 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
579 return res;
581 #endif
583 /***********************************************************************
584 * vcpDefCallbackProc (SETUPX.202)
586 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
587 LPARAM lParam, LPARAM lParamRef)
589 static int count = 0;
590 if (count < 10)
591 FIXME("(%p, %04x, %04lx, %08lx, %08lx) - what to do here ?\n",
592 lpvObj, uMsg, wParam, lParam, lParamRef);
593 count++;
594 return OK;
597 /********************* point-and-click stuff from here ***********************/
599 static HWND hDlgCopy = 0;
600 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
601 static char BackupDir[12];
603 static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
605 INT_PTR retval = FALSE;
607 if (iMsg == WM_INITDIALOG)
609 ShowWindow(hWndDlg, SW_SHOWNORMAL);
610 UpdateWindow(hWndDlg);
611 retval = TRUE;
613 return retval;
616 static BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
618 HRSRC hResInfo;
619 HGLOBAL hDlgTmpl32;
621 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), (LPSTR)RT_DIALOG)))
622 return FALSE;
623 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
624 !(*template32 = LockResource( hDlgTmpl32 )))
625 return FALSE;
626 return TRUE;
629 static LRESULT WINAPI
630 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
632 if (uMsg != WM_CREATE)
633 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
635 switch (uMsg)
637 case WM_CREATE:
638 return 0;
639 default:
640 FIXME("%04x: unhandled.\n", uMsg);
643 return 0;
646 static void VCP_UI_RegisterProgressClass(void)
648 static BOOL registered = FALSE;
649 WNDCLASSA wndClass;
651 if (registered)
652 return;
654 registered = TRUE;
655 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
656 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
657 wndClass.lpfnWndProc = VCP_UI_FileCopyWndProc;
658 wndClass.cbClsExtra = 0;
659 wndClass.cbWndExtra = 0;
660 wndClass.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
661 wndClass.hbrBackground = NULL;
662 wndClass.lpszClassName = "setupx_progress";
664 RegisterClassA (&wndClass);
667 static RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
669 LPCSTR file1, file2;
670 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
671 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
672 return (RETERR16)strcmp(file1, file2);
675 static RETERR16 VCP_UI_CopyStart(void)
677 LPCVOID template32;
678 char buf[256]; /* plenty */
679 BOOL dirty;
680 DWORD len;
682 /* FIXME: should be registered at DLL startup instead */
683 VCP_UI_RegisterProgressClass();
684 if (!(VCP_UI_GetDialogTemplate(&template32)))
685 return VCPN_FAIL;
687 if (vn_num > 10) /* hack */
689 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
690 VCP_UI_FileCopyDlgProc, 0);
691 if (!hDlgCopy)
692 return VCPN_FAIL;
693 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
694 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
696 strcpy(buf, REG_INSTALLEDFILES);
697 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
698 return VCPN_FAIL;
699 strcat(buf, REGPART_RENAME);
700 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
701 return VCPN_FAIL;
702 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
703 return VCPN_FAIL;
704 len = 1;
705 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
707 /* FIXME: what does SETUPX.DLL do in this case ? */
708 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
709 return VCPN_FAIL;
711 dirty = TRUE;
712 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
713 return VCPN_FAIL;
714 len = 12;
715 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, (LPBYTE)BackupDir, &len)))
716 strcpy(BackupDir, "VCM");
718 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
719 GetWindowsDirectoryA(buf, 256);
720 strcat(buf, "\\");
721 strcat(buf, BackupDir);
722 if (!(CreateDirectoryA(buf, NULL)))
723 return VCPN_FAIL;
724 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
725 return VCPN_FAIL;
726 RegCloseKey(hKeyConflict);
728 return VCPN_OK;
731 /***********************************************************************
732 * vcpUICallbackProc (SETUPX.213)
734 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
735 LPARAM lParam, LPARAM lParamRef)
737 static int count = 0;
738 RETERR16 res = VCPN_OK, cbres;
740 if (count < 5)
741 FIXME("(%p, %04x, %04lx, %08lx, %08lx) - semi-stub\n",
742 lpvObj, uMsg, wParam, lParam, lParamRef);
743 count++;
744 switch (uMsg)
746 /* unused messages, it seems */
747 case VCPM_DISKPREPINFO:
749 case VCPM_FILENEEDED:
751 case VCPM_NODECREATE:
752 case VCPM_NODEACCEPT:
754 case VCPM_VSTATCLOSESTART:
755 case VCPM_VSTATPATHCHECKSTART:
756 case VCPM_VSTATPATHCHECKEND:
758 case VCPM_CHECKPATH:
759 break;
761 /* the real stuff */
762 case VCPM_NODECOMPARE:
763 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
764 break;
765 case VCPM_VSTATREAD:
766 break;
767 case VCPM_VSTATWRITE:
768 cbres = VCP_Callback(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
769 break;
770 case VCPM_VSTATCLOSEEND:
771 RegCloseKey(hKeyFiles);
772 RegCloseKey(hKeyRename);
773 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
774 break;
775 case VCPM_VSTATCOPYSTART:
776 res = VCP_UI_CopyStart();
777 break;
778 case VCPM_VSTATCOPYEND:
779 if (hDlgCopy) DestroyWindow(hDlgCopy);
780 break;
781 default:
782 FIXME("unhandled msg 0x%04x\n", uMsg);
784 return res;