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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
30 #include "setupapi_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
35 /* ### start build ### */
36 extern WORD CALLBACK VCP_CallTo16_word_lwwll(FARPROC16,LPVOID,UINT16,WPARAM,LPARAM,LPARAM);
37 /* ### stop build ### */
39 static FARPROC16 VCP_Proc = NULL;
40 static LPARAM VCP_MsgRef = 0;
42 #define VCP_CALLBACK(obj,msg,wParam,lParam,lParamRef) \
44 VCP_CallTo16_word_lwwll(VCP_Proc, obj,msg,wParam,lParam,lParamRef) : OK;
46 static BOOL VCP_opened = FALSE;
48 static VCPSTATUS vcp_status;
50 static HINSTANCE SETUPAPI_hInstance;
52 /****************************** VHSTR management ******************************/
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 ! :-)
65 static VHSTR_STRUCT **vhstrlist = NULL;
66 static VHSTR vhstr_alloc = 0;
68 #define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount))
70 /***********************************************************************
71 * vsmStringAdd (SETUPX.207)
73 VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName)
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++)
84 if ((vhstrlist[n]) && (vhstrlist[n]->refcount))
86 TRACE("checking item: %d\n", n);
87 if (!strcmp(vhstrlist[n]->pStr, lpszName))
90 vhstrlist[n]->refcount++;
96 /* hmm, not found yet, let's insert it */
97 TRACE("inserting item\n");
98 for (n = 0; n < vhstr_alloc; n++)
100 if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount)))
106 heap = GetProcessHeap();
107 if (n == vhstr_alloc) /* hmm, no free index found yet */
111 vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
112 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
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);
124 /***********************************************************************
125 * vsmStringDelete (SETUPX.206)
127 INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
129 if (VALID_VHSTR(vhstr))
131 vhstrlist[vhstr]->refcount--;
132 if (!vhstrlist[vhstr]->refcount)
134 HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
135 vhstrlist[vhstr]->pStr = NULL;
140 /* string not found */
145 * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
147 VHSTR WINAPI vsmStringFind16(LPCSTR lpszName)
150 for (n = 0; n < vhstr_alloc; n++)
151 if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName)))
156 /***********************************************************************
157 * vsmGetStringName (SETUPX.205)
159 * Pretty correct, I guess
161 INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
163 if (VALID_VHSTR(vhstr))
165 int len = strlen(vhstrlist[vhstr]->pStr)+1;
169 strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
176 /***********************************************************************
177 * vsmStringCompare (not exported from a standard SETUPX.DLL, it seems)
179 INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB)
181 if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB)))
182 return VCPN_FAIL; /* correct ? */
183 return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr);
186 /***********************************************************************
187 * vsmGetStringRawName (SETUPX.208)
189 LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
191 return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
195 /***************************** VIRTNODE management ****************************/
196 static LPVIRTNODE *pvnlist = NULL;
197 static DWORD vn_num = 0;
198 static DWORD vn_last = 0;
200 RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
206 while (vn_last < vn_num)
208 if (pvnlist[vn_last] == NULL)
212 heap = GetProcessHeap();
213 if (vn_last == vn_num)
216 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
217 sizeof(LPVIRTNODE *) * vn_num);
219 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
220 lpvn = pvnlist[vn_last];
223 lpvn->cbSize = sizeof(VIRTNODE);
226 memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC));
229 memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC));
232 lpvn->lParam = lParam;
233 lpvn->lpExpandVtbl = lpExpandVtbl;
235 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
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);
244 BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
249 for (n = 0; n < vn_last; n++)
251 if (pvnlist[n] == lpvnDel)
253 cbres = VCP_CALLBACK(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
254 HeapFree(GetProcessHeap(), 0, lpvnDel);
262 /***********************************************************************
263 * VcpOpen (SETUPX.200)
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.
273 RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
275 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
279 VCP_Proc = (FARPROC16)vifproc;
280 VCP_MsgRef = lparamMsgRef;
282 /* load SETUPAPI needed for dialog resources etc. */
283 SETUPAPI_hInstance = LoadLibraryA("setupapi.dll");
284 if (!SETUPAPI_hInstance)
286 ERR("Could not load sibling setupapi.dll\n");
287 return ERR_VCP_NOMEM;
293 /***********************************************************************
294 * VcpQueueCopy [SETUPX.13]
296 * lpExpandVtbl seems to be deprecated.
297 * fl are the CNFL_xxx and VNFL_xxx flags.
298 * lParam are the VNLP_xxx flags.
300 RETERR16 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
308 VCPFILESPEC vfsSrc, vfsDst;
311 return ERR_VCP_NOTOPEN;
313 TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
314 lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
316 TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
318 vfsSrc.ldid = ldidSrc;
319 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
320 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
322 vfsDst.ldid = ldidDst;
323 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
324 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
326 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
330 /***********************************************************************
331 * VcpQueueDelete [SETUPX.17]
333 * Is lParamRef the same as lParam in VcpQueueCopy ?
334 * Damn docu !! Err... which docu ?
336 RETERR16 WINAPI VcpQueueDelete16(
337 LPCSTR lpszDstFileName,
346 return ERR_VCP_NOTOPEN;
348 vfsDst.ldid = ldidDst;
349 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
350 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
352 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
355 /***********************************************************************
356 * VcpQueueRename [SETUPX.204]
359 RETERR16 WINAPI VcpQueueRename16(
360 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
361 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
362 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
366 VCPFILESPEC vfsSrc, vfsDst;
369 return ERR_VCP_NOTOPEN;
371 vfsSrc.ldid = ldidSrc;
372 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
373 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
375 vfsDst.ldid = ldidDst;
376 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
377 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
379 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
383 /***********************************************************************
384 * VcpEnumFiles (SETUPX.@)
386 INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
390 for (n = 0; n < vn_last; n++)
391 vep(pvnlist[n], lParamRef);
393 return 0; /* FIXME: return value ? */
396 /***********************************************************************
397 * VcpExplain (SETUPX.411)
399 LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
401 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
408 LPVCPFILESPEC lpvfs =
409 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
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);
416 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
418 strcat(buffer, "\\");
419 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
423 FIXME("%ld unimplemented !\n", dwWhat);
424 strcpy(buffer, "Unknown error");
430 RETERR16 VCP_CheckPaths(void)
436 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
437 for (n = 0; n < vn_num; n++)
441 /* FIXME: check paths of all VIRTNODEs here ! */
442 cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
444 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
448 RETERR16 VCP_CopyFiles(void)
450 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
451 RETERR16 res = OK, cbres;
455 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
456 for (n = 0; n < vn_num; 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);
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, TRUE)))
472 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
473 res = ERR_VCP_IOFAIL;
476 vcp_status.prgFileRead.dwSoFar++;
477 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
478 vcp_status.prgFileWrite.dwSoFar++;
479 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
482 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
486 /***********************************************************************
487 * VcpFlush - internal (not exported), but documented
489 * VNFL_NOW is used for VcpFlush.
491 RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
496 /***********************************************************************
497 * VcpClose (SETUPX.201)
499 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
500 * VCPM_VSTATCLOSEEND.
502 * fl gets VCPFL_xxx flags to indicate what to do with the
503 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
505 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
508 WORD cbres = VCPN_PROCEED;
510 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
512 /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER
513 * is not set. This is done by VCP_CALLBACK(VCPM_NODECOMPARE) */
516 memset(&vcp_status, 0, sizeof(VCPSTATUS));
517 /* yes, vcp_status.cbSize is 0 ! */
519 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
522 res = VCP_CheckPaths();
525 return res; /* is this ok ? */
529 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
532 FreeLibrary(SETUPAPI_hInstance);
537 RETERR16 VCP_RenameFiles(void)
539 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
540 RETERR16 res = OK, cbres;
544 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
545 for (n = 0; n < vn_num; n++)
548 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
549 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
550 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
551 cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
552 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
553 res = ERR_VCP_IOFAIL;
555 VCP_VirtnodeDelete(lpvn);
557 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
561 /***********************************************************************
562 * vcpDefCallbackProc (SETUPX.202)
564 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
565 LPARAM lParam, LPARAM lParamRef)
567 static int count = 0;
569 FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
570 lpvObj, uMsg, wParam, lParam, lParamRef);
575 /********************* point-and-click stuff from here ***********************/
577 static HWND hDlgCopy = 0;
578 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
579 static char BackupDir[12];
581 static BOOL CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
585 if (iMsg == WM_INITDIALOG)
587 ShowWindow(hWndDlg, SW_SHOWNORMAL);
588 UpdateWindow(hWndDlg);
594 BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
596 HANDLE hResInfo, hDlgTmpl32;
598 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), RT_DIALOGA)))
600 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
601 !(*template32 = LockResource( hDlgTmpl32 )))
606 static LRESULT WINAPI
607 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
609 if (uMsg != WM_CREATE)
610 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
617 FIXME("%04x: unhandled.\n", uMsg);
623 void VCP_UI_RegisterProgressClass(void)
625 static BOOL registered = FALSE;
632 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
633 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
634 wndClass.lpfnWndProc = (WNDPROC)VCP_UI_FileCopyWndProc;
635 wndClass.cbClsExtra = 0;
636 wndClass.cbWndExtra = 0;
637 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
638 wndClass.hbrBackground = (HBRUSH)NULL;
639 wndClass.lpszClassName = "setupx_progress";
641 RegisterClassA (&wndClass);
644 RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
647 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
648 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
649 return (RETERR16)strcmp(file1, file2);
652 RETERR16 VCP_UI_CopyStart(void)
655 char buf[256]; /* plenty */
659 /* FIXME: should be registered at DLL startup instead */
660 VCP_UI_RegisterProgressClass();
661 if (!(VCP_UI_GetDialogTemplate(&template32)))
664 if (vn_num > 10) /* hack */
666 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
667 VCP_UI_FileCopyDlgProc, 0);
670 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
671 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
673 strcpy(buf, REG_INSTALLEDFILES);
674 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
676 strcat(buf, REGPART_RENAME);
677 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
679 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
682 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
684 /* FIXME: what does SETUPX.DLL do in this case ? */
685 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
689 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
692 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len)))
693 strcpy(BackupDir, "VCM");
695 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
696 GetWindowsDirectoryA(buf, 256);
698 strcat(buf, BackupDir);
699 if (!(CreateDirectoryA(buf, NULL)))
701 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
703 RegCloseKey(hKeyConflict);
708 /***********************************************************************
709 * vcpUICallbackProc (SETUPX.213)
711 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
712 LPARAM lParam, LPARAM lParamRef)
714 static int count = 0;
715 RETERR16 res = VCPN_OK, cbres;
718 FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n",
719 lpvObj, uMsg, wParam, lParam, lParamRef);
723 /* unused messages, it seems */
724 case VCPM_DISKPREPINFO:
726 case VCPM_FILENEEDED:
728 case VCPM_NODECREATE:
729 case VCPM_NODEACCEPT:
731 case VCPM_VSTATCLOSESTART:
732 case VCPM_VSTATPATHCHECKSTART:
733 case VCPM_VSTATPATHCHECKEND:
739 case VCPM_NODECOMPARE:
740 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
744 case VCPM_VSTATWRITE:
745 cbres = VCP_CALLBACK(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
747 case VCPM_VSTATCLOSEEND:
748 RegCloseKey(hKeyFiles);
749 RegCloseKey(hKeyRename);
750 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
752 case VCPM_VSTATCOPYSTART:
753 res = VCP_UI_CopyStart();
755 case VCPM_VSTATCOPYEND:
756 if (hDlgCopy) DestroyWindow(hDlgCopy);
759 FIXME("unhandled msg 0x%04x\n", uMsg);