Convert MRULists to Unicode.
[wine/testsucceed.git] / dlls / setupapi / virtcopy.c
blob2501315fcdb56aa69b5732755cd7e9d6612f72ea
1 /*
2 * SetupAPI virtual copy operations
4 * FIXME: we now rely on builtin setupapi.dll for dialog resources.
5 * This is bad ! We ought to have 16bit resource handling working.
6 */
8 #include <string.h>
9 #include "winbase.h"
10 #include "winuser.h"
11 #include "setupx16.h"
12 #include "winreg.h"
13 #include "setupapi_private.h"
14 #include "debugtools.h"
16 DEFAULT_DEBUG_CHANNEL(setupapi);
18 /* ### start build ### */
19 extern WORD CALLBACK VCP_CallTo16_word_lwwll(FARPROC16,LPVOID,UINT16,WPARAM,LPARAM,LPARAM);
20 /* ### stop build ### */
22 static FARPROC16 VCP_Proc = NULL;
23 static LPARAM VCP_MsgRef = 0;
25 #define VCP_CALLBACK(obj,msg,wParam,lParam,lParamRef) \
26 (VCP_Proc) ? \
27 VCP_CallTo16_word_lwwll(VCP_Proc, obj,msg,wParam,lParam,lParamRef) : OK;
29 static BOOL VCP_opened = FALSE;
31 static VCPSTATUS vcp_status;
33 static HINSTANCE SETUPAPI_hInstance;
35 /****************************** VHSTR management ******************************/
38 * This is a totally braindead implementation for now;
39 * I don't care about speed at all ! Size and implementation time
40 * is much more important IMHO. I could have created some sophisticated
41 * tree structure, but... what the hell ! :-)
43 typedef struct {
44 DWORD refcount;
45 LPCSTR pStr;
46 } VHSTR_STRUCT;
48 static VHSTR_STRUCT **vhstrlist = NULL;
49 static VHSTR vhstr_alloc = 0;
51 #define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount))
53 /***********************************************************************
54 * vsmStringAdd (SETUPX.207)
56 VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName)
58 VHSTR n;
59 VHSTR index = 0xffff;
60 HANDLE heap;
62 TRACE("add string '%s'\n", lpszName);
63 /* search whether string already inserted */
64 TRACE("searching for existing string...\n");
65 for (n = 0; n < vhstr_alloc; n++)
67 if ((vhstrlist[n]) && (vhstrlist[n]->refcount))
69 TRACE("checking item: %d\n", n);
70 if (!strcmp(vhstrlist[n]->pStr, lpszName))
72 TRACE("found\n");
73 vhstrlist[n]->refcount++;
74 return n;
79 /* hmm, not found yet, let's insert it */
80 TRACE("inserting item\n");
81 for (n = 0; n < vhstr_alloc; n++)
83 if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount)))
85 index = n;
86 break;
89 heap = GetProcessHeap();
90 if (n == vhstr_alloc) /* hmm, no free index found yet */
92 index = vhstr_alloc;
93 vhstr_alloc += 20;
94 vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
95 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
97 if (index == 0xffff)
98 return 0xffff; /* failure */
99 if (!vhstrlist[index])
100 vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT));
101 vhstrlist[index]->refcount = 1;
102 vhstrlist[index]->pStr = HeapAlloc(heap, 0, strlen(lpszName)+1);
103 strcpy((LPSTR)vhstrlist[index]->pStr, lpszName);
104 return index;
107 /***********************************************************************
108 * vsmStringDelete (SETUPX.206)
110 INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
112 if (VALID_VHSTR(vhstr))
114 vhstrlist[vhstr]->refcount--;
115 if (!vhstrlist[vhstr]->refcount)
117 HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
118 vhstrlist[vhstr]->pStr = NULL;
120 return VCPN_OK;
123 /* string not found */
124 return VCPN_FAIL;
128 * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
130 VHSTR WINAPI vsmStringFind16(LPCSTR lpszName)
132 WORD n;
133 for (n = 0; n < vhstr_alloc; n++)
134 if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName)))
135 return n;
136 return 0xffff;
139 /***********************************************************************
140 * vsmGetStringName (SETUPX.205)
142 * Pretty correct, I guess
144 INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
146 if (VALID_VHSTR(vhstr))
148 int len = strlen(vhstrlist[vhstr]->pStr)+1;
149 if (cbBuffer >= len)
151 if (lpszBuffer)
152 strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
153 return len;
156 return VCPN_FAIL;
159 /***********************************************************************
160 * vsmStringCompare (not exported from a standard SETUPX.DLL, it seems)
162 INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB)
164 if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB)))
165 return VCPN_FAIL; /* correct ? */
166 return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr);
169 /***********************************************************************
170 * vsmGetStringRawName (SETUPX.208)
172 LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
174 return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
178 /***************************** VIRTNODE management ****************************/
179 static LPVIRTNODE *pvnlist = NULL;
180 static DWORD vn_num = 0;
181 static DWORD vn_last = 0;
183 RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
185 HANDLE heap;
186 LPVIRTNODE lpvn;
187 RETERR16 cbres;
189 while (vn_last < vn_num)
191 if (pvnlist[vn_last] == NULL)
192 break;
193 vn_last++;
195 heap = GetProcessHeap();
196 if (vn_last == vn_num)
198 vn_num += 20;
199 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
200 sizeof(LPVIRTNODE *) * vn_num);
202 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
203 lpvn = pvnlist[vn_last];
204 vn_last++;
206 lpvn->cbSize = sizeof(VIRTNODE);
208 if (vfsSrc)
209 memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC));
211 if (vfsDst)
212 memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC));
214 lpvn->fl = fl;
215 lpvn->lParam = lParam;
216 lpvn->lpExpandVtbl = lpExpandVtbl;
218 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
220 cbres = VCP_CALLBACK(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
221 lpvn->fl |= VFNL_CREATED;
222 cbres = VCP_CALLBACK(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);
224 return OK;
227 BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
229 DWORD n;
230 RETERR16 cbres;
232 for (n = 0; n < vn_last; n++)
234 if (pvnlist[n] == lpvnDel)
236 cbres = VCP_CALLBACK(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
237 HeapFree(GetProcessHeap(), 0, lpvnDel);
238 pvnlist[n] = NULL;
239 return TRUE;
242 return FALSE;
245 /***********************************************************************
246 * VcpOpen (SETUPX.200)
248 * Sets up a virtual copy operation.
249 * This means that functions such as GenInstall()
250 * create a VIRTNODE struct for every file to be touched in a .INF file
251 * instead of actually touching the file.
252 * The actual copy/move/rename gets started when VcpClose or
253 * VcpFlush is called; several different callbacks are made
254 * (copy, rename, open, close, version conflicts, ...) on every file copied.
256 RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
258 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
259 if (VCP_opened)
260 return ERR_VCP_BUSY;
262 VCP_Proc = (FARPROC16)vifproc;
263 VCP_MsgRef = lparamMsgRef;
265 /* load SETUPAPI needed for dialog resources etc. */
266 SETUPAPI_hInstance = LoadLibraryA("setupapi.dll");
267 if (!SETUPAPI_hInstance)
269 ERR("Could not load sibling setupapi.dll\n");
270 return ERR_VCP_NOMEM;
272 VCP_opened = TRUE;
273 return OK;
276 /***********************************************************************
277 * VcpQueueCopy [SETUPX.13]
279 * lpExpandVtbl seems to be deprecated.
280 * fl are the CNFL_xxx and VNFL_xxx flags.
281 * lParam are the VNLP_xxx flags.
283 RETERR16 WINAPI VcpQueueCopy16(
284 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
285 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
286 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
287 LPEXPANDVTBL lpExpandVtbl,
288 WORD fl, LPARAM lParam
291 VCPFILESPEC vfsSrc, vfsDst;
293 if (!VCP_opened)
294 return ERR_VCP_NOTOPEN;
296 TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
297 lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
299 TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
301 vfsSrc.ldid = ldidSrc;
302 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
303 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
305 vfsDst.ldid = ldidDst;
306 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
307 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
309 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
310 lpExpandVtbl);
313 /***********************************************************************
314 * VcpQueueDelete [SETUPX.17]
316 * Is lParamRef the same as lParam in VcpQueueCopy ?
317 * Damn docu !! Err... which docu ?
319 RETERR16 WINAPI VcpQueueDelete16(
320 LPCSTR lpszDstFileName,
321 LPCSTR lpszDstDir,
322 LOGDISKID16 ldidDst,
323 LPARAM lParamRef
326 VCPFILESPEC vfsDst;
328 if (!VCP_opened)
329 return ERR_VCP_NOTOPEN;
331 vfsDst.ldid = ldidDst;
332 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
333 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
335 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
338 /***********************************************************************
339 * VcpQueueRename [SETUPX.204]
342 RETERR16 WINAPI VcpQueueRename16(
343 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
344 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
345 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
346 LPARAM lParam
349 VCPFILESPEC vfsSrc, vfsDst;
351 if (!VCP_opened)
352 return ERR_VCP_NOTOPEN;
354 vfsSrc.ldid = ldidSrc;
355 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
356 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
358 vfsDst.ldid = ldidDst;
359 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
360 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
362 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
366 /***********************************************************************
367 * VcpEnumFiles (SETUPX.@)
369 INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
371 WORD n;
373 for (n = 0; n < vn_last; n++)
374 vep(pvnlist[n], lParamRef);
376 return 0; /* FIXME: return value ? */
379 /***********************************************************************
380 * VcpExplain (SETUPX.411)
382 LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
384 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
385 buffer[0] = '\0';
386 switch (dwWhat)
388 case VCPEX_SRC_FULL:
389 case VCPEX_DST_FULL:
391 LPVCPFILESPEC lpvfs =
392 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
394 /* if we have an ldid, use it, otherwise use the string */
395 /* from the vhstrlist array */
396 if (lpvfs->ldid != 0xffff)
397 CtlGetLddPath16(lpvfs->ldid, buffer);
398 else
399 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
401 strcat(buffer, "\\");
402 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
404 break;
405 default:
406 FIXME("%ld unimplemented !\n", dwWhat);
407 strcpy(buffer, "Unknown error");
408 break;
410 return buffer;
413 RETERR16 VCP_CheckPaths(void)
415 DWORD n;
416 LPVIRTNODE lpvn;
417 RETERR16 cbres;
419 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
420 for (n = 0; n < vn_num; n++)
422 lpvn = pvnlist[n];
423 if (!lpvn) continue;
424 /* FIXME: check paths of all VIRTNODEs here ! */
425 cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
427 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
428 return OK;
431 RETERR16 VCP_CopyFiles(void)
433 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
434 RETERR16 res = OK, cbres;
435 DWORD n;
436 LPVIRTNODE lpvn;
438 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
439 for (n = 0; n < vn_num; n++)
441 lpvn = pvnlist[n];
442 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
443 /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
444 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
445 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
446 /* FIXME: what is this VCPM_VSTATWRITE here for ?
447 * I guess it's to signal successful destination file creation */
448 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
450 /* FIXME: need to do the file copy in small chunks for notifications */
451 TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
452 /* perform the file copy */
453 if (!(CopyFileA(fn_src, fn_dst, TRUE)))
455 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
456 res = ERR_VCP_IOFAIL;
459 vcp_status.prgFileRead.dwSoFar++;
460 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
461 vcp_status.prgFileWrite.dwSoFar++;
462 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
465 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
466 return res;
469 /***********************************************************************
470 * VcpFlush - internal (not exported), but documented
472 * VNFL_NOW is used for VcpFlush.
474 RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
476 return OK;
479 /***********************************************************************
480 * VcpClose (SETUPX.201)
482 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
483 * VCPM_VSTATCLOSEEND.
485 * fl gets VCPFL_xxx flags to indicate what to do with the
486 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
488 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
490 RETERR16 res = OK;
491 WORD cbres = VCPN_PROCEED;
493 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
495 /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER
496 * is not set. This is done by VCP_CALLBACK(VCPM_NODECOMPARE) */
498 TRACE("#1\n");
499 memset(&vcp_status, 0, sizeof(VCPSTATUS));
500 /* yes, vcp_status.cbSize is 0 ! */
501 TRACE("#2\n");
502 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
503 TRACE("#3\n");
505 res = VCP_CheckPaths();
506 TRACE("#4\n");
507 if (res != OK)
508 return res; /* is this ok ? */
509 VCP_CopyFiles();
511 TRACE("#5\n");
512 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
513 TRACE("#6\n");
514 VCP_Proc = NULL;
515 FreeLibrary(SETUPAPI_hInstance);
516 VCP_opened = FALSE;
517 return OK;
520 RETERR16 VCP_RenameFiles(void)
522 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
523 RETERR16 res = OK, cbres;
524 DWORD n;
525 LPVIRTNODE lpvn;
527 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
528 for (n = 0; n < vn_num; n++)
530 lpvn = pvnlist[n];
531 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
532 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
533 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
534 cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
535 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
536 res = ERR_VCP_IOFAIL;
537 else
538 VCP_VirtnodeDelete(lpvn);
540 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
541 return res;
544 /***********************************************************************
545 * vcpDefCallbackProc (SETUPX.202)
547 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
548 LPARAM lParam, LPARAM lParamRef)
550 static int count = 0;
551 if (count < 10)
552 FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
553 lpvObj, uMsg, wParam, lParam, lParamRef);
554 count++;
555 return OK;
558 /********************* point-and-click stuff from here ***********************/
560 static HWND hDlgCopy = 0;
561 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
562 static char BackupDir[12];
564 static BOOL CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
566 BOOL retval = FALSE;
568 if (iMsg == WM_INITDIALOG)
570 ShowWindow(hWndDlg, SW_SHOWNORMAL);
571 UpdateWindow(hWndDlg);
572 retval = TRUE;
574 return retval;
577 BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
579 HANDLE hResInfo, hDlgTmpl32;
581 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), RT_DIALOGA)))
582 return FALSE;
583 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
584 !(*template32 = LockResource( hDlgTmpl32 )))
585 return FALSE;
586 return TRUE;
589 static LRESULT WINAPI
590 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
592 if (uMsg != WM_CREATE)
593 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
595 switch (uMsg)
597 case WM_CREATE:
598 return 0;
599 default:
600 FIXME("%04x: unhandled.\n", uMsg);
603 return 0;
606 void VCP_UI_RegisterProgressClass(void)
608 static BOOL registered = FALSE;
609 WNDCLASSA wndClass;
611 if (registered)
612 return;
614 registered = TRUE;
615 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
616 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
617 wndClass.lpfnWndProc = (WNDPROC)VCP_UI_FileCopyWndProc;
618 wndClass.cbClsExtra = 0;
619 wndClass.cbWndExtra = 0;
620 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
621 wndClass.hbrBackground = (HBRUSH)NULL;
622 wndClass.lpszClassName = "setupx_progress";
624 RegisterClassA (&wndClass);
627 RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
629 LPCSTR file1, file2;
630 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
631 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
632 return (RETERR16)strcmp(file1, file2);
635 RETERR16 VCP_UI_CopyStart(void)
637 LPCVOID template32;
638 char buf[256]; /* plenty */
639 BOOL dirty;
640 DWORD len;
642 /* FIXME: should be registered at DLL startup instead */
643 VCP_UI_RegisterProgressClass();
644 if (!(VCP_UI_GetDialogTemplate(&template32)))
645 return VCPN_FAIL;
647 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
648 VCP_UI_FileCopyDlgProc, 0);
649 if (!hDlgCopy)
650 return VCPN_FAIL;
651 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
652 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
653 strcpy(buf, REG_INSTALLEDFILES);
654 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
655 return VCPN_FAIL;
656 strcat(buf, REGPART_RENAME);
657 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
658 return VCPN_FAIL;
659 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
660 return VCPN_FAIL;
661 len = 1;
662 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
664 /* FIXME: what does SETUPX.DLL do in this case ? */
665 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
666 return VCPN_FAIL;
668 dirty = TRUE;
669 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
670 return VCPN_FAIL;
671 len = 12;
672 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len)))
673 strcpy(BackupDir, "VCM");
675 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
676 GetWindowsDirectoryA(buf, 256);
677 strcat(buf, "\\");
678 strcat(buf, BackupDir);
679 if (!(CreateDirectoryA(buf, NULL)))
680 return VCPN_FAIL;
681 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
682 return VCPN_FAIL;
683 RegCloseKey(hKeyConflict);
685 return VCPN_OK;
688 /***********************************************************************
689 * vcpUICallbackProc (SETUPX.213)
691 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
692 LPARAM lParam, LPARAM lParamRef)
694 static int count = 0;
695 RETERR16 res = VCPN_OK, cbres;
697 if (count < 5)
698 FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n",
699 lpvObj, uMsg, wParam, lParam, lParamRef);
700 count++;
701 switch (uMsg)
703 /* unused messages, it seems */
704 case VCPM_DISKPREPINFO:
706 case VCPM_FILENEEDED:
708 case VCPM_NODECREATE:
709 case VCPM_NODEACCEPT:
711 case VCPM_VSTATCLOSESTART:
712 case VCPM_VSTATPATHCHECKSTART:
713 case VCPM_VSTATPATHCHECKEND:
715 case VCPM_CHECKPATH:
716 break;
718 /* the real stuff */
719 case VCPM_NODECOMPARE:
720 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
721 break;
722 case VCPM_VSTATREAD:
723 break;
724 case VCPM_VSTATWRITE:
725 cbres = VCP_CALLBACK(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
726 break;
727 case VCPM_VSTATCLOSEEND:
728 RegCloseKey(hKeyFiles);
729 RegCloseKey(hKeyRename);
730 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
731 break;
732 case VCPM_VSTATCOPYSTART:
733 res = VCP_UI_CopyStart();
734 break;
735 case VCPM_VSTATCOPYEND:
736 DestroyWindow(hDlgCopy);
737 break;
738 default:
739 FIXME("unhandled msg 0x%04x\n", uMsg);
741 return res;