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.
29 #include "setupapi_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
34 /* ### start build ### */
35 extern WORD CALLBACK VCP_CallTo16_word_lwwll(FARPROC16,LPVOID,UINT16,WPARAM,LPARAM,LPARAM);
36 /* ### stop build ### */
38 static FARPROC16 VCP_Proc = NULL;
39 static LPARAM VCP_MsgRef = 0;
41 #define VCP_CALLBACK(obj,msg,wParam,lParam,lParamRef) \
43 VCP_CallTo16_word_lwwll(VCP_Proc, obj,msg,wParam,lParam,lParamRef) : OK;
45 static BOOL VCP_opened = FALSE;
47 static VCPSTATUS vcp_status;
49 static HINSTANCE SETUPAPI_hInstance;
51 /****************************** VHSTR management ******************************/
54 * This is a totally braindead implementation for now;
55 * I don't care about speed at all ! Size and implementation time
56 * is much more important IMHO. I could have created some sophisticated
57 * tree structure, but... what the hell ! :-)
64 static VHSTR_STRUCT **vhstrlist = NULL;
65 static VHSTR vhstr_alloc = 0;
67 #define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount))
69 /***********************************************************************
70 * vsmStringAdd (SETUPX.207)
72 VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName)
78 TRACE("add string '%s'\n", lpszName);
79 /* search whether string already inserted */
80 TRACE("searching for existing string...\n");
81 for (n = 0; n < vhstr_alloc; n++)
83 if ((vhstrlist[n]) && (vhstrlist[n]->refcount))
85 TRACE("checking item: %d\n", n);
86 if (!strcmp(vhstrlist[n]->pStr, lpszName))
89 vhstrlist[n]->refcount++;
95 /* hmm, not found yet, let's insert it */
96 TRACE("inserting item\n");
97 for (n = 0; n < vhstr_alloc; n++)
99 if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount)))
105 heap = GetProcessHeap();
106 if (n == vhstr_alloc) /* hmm, no free index found yet */
110 vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
111 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
114 return 0xffff; /* failure */
115 if (!vhstrlist[index])
116 vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT));
117 vhstrlist[index]->refcount = 1;
118 vhstrlist[index]->pStr = HeapAlloc(heap, 0, strlen(lpszName)+1);
119 strcpy((LPSTR)vhstrlist[index]->pStr, lpszName);
123 /***********************************************************************
124 * vsmStringDelete (SETUPX.206)
126 INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
128 if (VALID_VHSTR(vhstr))
130 vhstrlist[vhstr]->refcount--;
131 if (!vhstrlist[vhstr]->refcount)
133 HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
134 vhstrlist[vhstr]->pStr = NULL;
139 /* string not found */
144 * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
146 VHSTR WINAPI vsmStringFind16(LPCSTR lpszName)
149 for (n = 0; n < vhstr_alloc; n++)
150 if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName)))
155 /***********************************************************************
156 * vsmGetStringName (SETUPX.205)
158 * Pretty correct, I guess
160 INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
162 if (VALID_VHSTR(vhstr))
164 int len = strlen(vhstrlist[vhstr]->pStr)+1;
168 strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
175 /***********************************************************************
176 * vsmStringCompare (not exported from a standard SETUPX.DLL, it seems)
178 INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB)
180 if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB)))
181 return VCPN_FAIL; /* correct ? */
182 return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr);
185 /***********************************************************************
186 * vsmGetStringRawName (SETUPX.208)
188 LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
190 return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
194 /***************************** VIRTNODE management ****************************/
195 static LPVIRTNODE *pvnlist = NULL;
196 static DWORD vn_num = 0;
197 static DWORD vn_last = 0;
199 RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
205 while (vn_last < vn_num)
207 if (pvnlist[vn_last] == NULL)
211 heap = GetProcessHeap();
212 if (vn_last == vn_num)
215 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
216 sizeof(LPVIRTNODE *) * vn_num);
218 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
219 lpvn = pvnlist[vn_last];
222 lpvn->cbSize = sizeof(VIRTNODE);
225 memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC));
228 memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC));
231 lpvn->lParam = lParam;
232 lpvn->lpExpandVtbl = lpExpandVtbl;
234 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
236 cbres = VCP_CALLBACK(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
237 lpvn->fl |= VFNL_CREATED;
238 cbres = VCP_CALLBACK(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);
243 BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
248 for (n = 0; n < vn_last; n++)
250 if (pvnlist[n] == lpvnDel)
252 cbres = VCP_CALLBACK(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
253 HeapFree(GetProcessHeap(), 0, lpvnDel);
261 /***********************************************************************
262 * VcpOpen (SETUPX.200)
264 * Sets up a virtual copy operation.
265 * This means that functions such as GenInstall()
266 * create a VIRTNODE struct for every file to be touched in a .INF file
267 * instead of actually touching the file.
268 * The actual copy/move/rename gets started when VcpClose or
269 * VcpFlush is called; several different callbacks are made
270 * (copy, rename, open, close, version conflicts, ...) on every file copied.
272 RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
274 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
278 VCP_Proc = (FARPROC16)vifproc;
279 VCP_MsgRef = lparamMsgRef;
281 /* load SETUPAPI needed for dialog resources etc. */
282 SETUPAPI_hInstance = LoadLibraryA("setupapi.dll");
283 if (!SETUPAPI_hInstance)
285 ERR("Could not load sibling setupapi.dll\n");
286 return ERR_VCP_NOMEM;
292 /***********************************************************************
293 * VcpQueueCopy [SETUPX.13]
295 * lpExpandVtbl seems to be deprecated.
296 * fl are the CNFL_xxx and VNFL_xxx flags.
297 * lParam are the VNLP_xxx flags.
299 RETERR16 WINAPI VcpQueueCopy16(
300 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
301 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
302 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
303 LPEXPANDVTBL lpExpandVtbl,
304 WORD fl, LPARAM lParam
307 VCPFILESPEC vfsSrc, vfsDst;
310 return ERR_VCP_NOTOPEN;
312 TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
313 lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
315 TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
317 vfsSrc.ldid = ldidSrc;
318 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
319 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
321 vfsDst.ldid = ldidDst;
322 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
323 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
325 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
329 /***********************************************************************
330 * VcpQueueDelete [SETUPX.17]
332 * Is lParamRef the same as lParam in VcpQueueCopy ?
333 * Damn docu !! Err... which docu ?
335 RETERR16 WINAPI VcpQueueDelete16(
336 LPCSTR lpszDstFileName,
345 return ERR_VCP_NOTOPEN;
347 vfsDst.ldid = ldidDst;
348 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
349 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
351 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
354 /***********************************************************************
355 * VcpQueueRename [SETUPX.204]
358 RETERR16 WINAPI VcpQueueRename16(
359 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
360 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
361 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
365 VCPFILESPEC vfsSrc, vfsDst;
368 return ERR_VCP_NOTOPEN;
370 vfsSrc.ldid = ldidSrc;
371 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
372 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
374 vfsDst.ldid = ldidDst;
375 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
376 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
378 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
382 /***********************************************************************
383 * VcpEnumFiles (SETUPX.@)
385 INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
389 for (n = 0; n < vn_last; n++)
390 vep(pvnlist[n], lParamRef);
392 return 0; /* FIXME: return value ? */
395 /***********************************************************************
396 * VcpExplain (SETUPX.411)
398 LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
400 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
407 LPVCPFILESPEC lpvfs =
408 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
410 /* if we have an ldid, use it, otherwise use the string */
411 /* from the vhstrlist array */
412 if (lpvfs->ldid != 0xffff)
413 CtlGetLddPath16(lpvfs->ldid, buffer);
415 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
417 strcat(buffer, "\\");
418 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
422 FIXME("%ld unimplemented !\n", dwWhat);
423 strcpy(buffer, "Unknown error");
429 RETERR16 VCP_CheckPaths(void)
435 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
436 for (n = 0; n < vn_num; n++)
440 /* FIXME: check paths of all VIRTNODEs here ! */
441 cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
443 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
447 RETERR16 VCP_CopyFiles(void)
449 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
450 RETERR16 res = OK, cbres;
454 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
455 for (n = 0; n < vn_num; n++)
458 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
459 /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
460 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
461 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
462 /* FIXME: what is this VCPM_VSTATWRITE here for ?
463 * I guess it's to signal successful destination file creation */
464 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
466 /* FIXME: need to do the file copy in small chunks for notifications */
467 TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
468 /* perform the file copy */
469 if (!(CopyFileA(fn_src, fn_dst, TRUE)))
471 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
472 res = ERR_VCP_IOFAIL;
475 vcp_status.prgFileRead.dwSoFar++;
476 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
477 vcp_status.prgFileWrite.dwSoFar++;
478 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
481 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
485 /***********************************************************************
486 * VcpFlush - internal (not exported), but documented
488 * VNFL_NOW is used for VcpFlush.
490 RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
495 /***********************************************************************
496 * VcpClose (SETUPX.201)
498 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
499 * VCPM_VSTATCLOSEEND.
501 * fl gets VCPFL_xxx flags to indicate what to do with the
502 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
504 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
507 WORD cbres = VCPN_PROCEED;
509 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
511 /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER
512 * is not set. This is done by VCP_CALLBACK(VCPM_NODECOMPARE) */
515 memset(&vcp_status, 0, sizeof(VCPSTATUS));
516 /* yes, vcp_status.cbSize is 0 ! */
518 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
521 res = VCP_CheckPaths();
524 return res; /* is this ok ? */
528 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
531 FreeLibrary(SETUPAPI_hInstance);
536 RETERR16 VCP_RenameFiles(void)
538 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
539 RETERR16 res = OK, cbres;
543 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
544 for (n = 0; n < vn_num; n++)
547 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
548 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
549 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
550 cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
551 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
552 res = ERR_VCP_IOFAIL;
554 VCP_VirtnodeDelete(lpvn);
556 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
560 /***********************************************************************
561 * vcpDefCallbackProc (SETUPX.202)
563 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
564 LPARAM lParam, LPARAM lParamRef)
566 static int count = 0;
568 FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
569 lpvObj, uMsg, wParam, lParam, lParamRef);
574 /********************* point-and-click stuff from here ***********************/
576 static HWND hDlgCopy = 0;
577 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
578 static char BackupDir[12];
580 static BOOL CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
584 if (iMsg == WM_INITDIALOG)
586 ShowWindow(hWndDlg, SW_SHOWNORMAL);
587 UpdateWindow(hWndDlg);
593 BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
595 HANDLE hResInfo, hDlgTmpl32;
597 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), RT_DIALOGA)))
599 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
600 !(*template32 = LockResource( hDlgTmpl32 )))
605 static LRESULT WINAPI
606 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
608 if (uMsg != WM_CREATE)
609 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
616 FIXME("%04x: unhandled.\n", uMsg);
622 void VCP_UI_RegisterProgressClass(void)
624 static BOOL registered = FALSE;
631 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
632 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
633 wndClass.lpfnWndProc = (WNDPROC)VCP_UI_FileCopyWndProc;
634 wndClass.cbClsExtra = 0;
635 wndClass.cbWndExtra = 0;
636 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
637 wndClass.hbrBackground = (HBRUSH)NULL;
638 wndClass.lpszClassName = "setupx_progress";
640 RegisterClassA (&wndClass);
643 RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
646 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
647 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
648 return (RETERR16)strcmp(file1, file2);
651 RETERR16 VCP_UI_CopyStart(void)
654 char buf[256]; /* plenty */
658 /* FIXME: should be registered at DLL startup instead */
659 VCP_UI_RegisterProgressClass();
660 if (!(VCP_UI_GetDialogTemplate(&template32)))
663 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
664 VCP_UI_FileCopyDlgProc, 0);
667 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
668 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
669 strcpy(buf, REG_INSTALLEDFILES);
670 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
672 strcat(buf, REGPART_RENAME);
673 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
675 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
678 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
680 /* FIXME: what does SETUPX.DLL do in this case ? */
681 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
685 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
688 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len)))
689 strcpy(BackupDir, "VCM");
691 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
692 GetWindowsDirectoryA(buf, 256);
694 strcat(buf, BackupDir);
695 if (!(CreateDirectoryA(buf, NULL)))
697 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
699 RegCloseKey(hKeyConflict);
704 /***********************************************************************
705 * vcpUICallbackProc (SETUPX.213)
707 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
708 LPARAM lParam, LPARAM lParamRef)
710 static int count = 0;
711 RETERR16 res = VCPN_OK, cbres;
714 FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n",
715 lpvObj, uMsg, wParam, lParam, lParamRef);
719 /* unused messages, it seems */
720 case VCPM_DISKPREPINFO:
722 case VCPM_FILENEEDED:
724 case VCPM_NODECREATE:
725 case VCPM_NODEACCEPT:
727 case VCPM_VSTATCLOSESTART:
728 case VCPM_VSTATPATHCHECKSTART:
729 case VCPM_VSTATPATHCHECKEND:
735 case VCPM_NODECOMPARE:
736 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
740 case VCPM_VSTATWRITE:
741 cbres = VCP_CALLBACK(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
743 case VCPM_VSTATCLOSEEND:
744 RegCloseKey(hKeyFiles);
745 RegCloseKey(hKeyRename);
746 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
748 case VCPM_VSTATCOPYSTART:
749 res = VCP_UI_CopyStart();
751 case VCPM_VSTATCOPYEND:
752 DestroyWindow(hDlgCopy);
755 FIXME("unhandled msg 0x%04x\n", uMsg);