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.
31 #include "setupapi_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
36 static FARPROC16 VCP_Proc = NULL;
37 static LPARAM VCP_MsgRef = 0;
39 static BOOL VCP_opened = FALSE;
41 static VCPSTATUS vcp_status;
43 static HINSTANCE SETUPAPI_hInstance;
45 static WORD VCP_Callback( LPVOID obj, UINT16 msg, WPARAM16 wParam, LPARAM lParam, LPARAM lParamRef )
51 args[7] = HIWORD(obj);
52 args[6] = LOWORD(obj);
55 args[3] = HIWORD(lParam);
56 args[2] = LOWORD(lParam);
57 args[1] = HIWORD(lParamRef);
58 args[0] = LOWORD(lParamRef);
59 WOWCallback16Ex( (DWORD)VCP_Proc, WCB16_PASCAL, sizeof(args), args, &ret );
64 /****************************** VHSTR management ******************************/
67 * This is a totally braindead implementation for now;
68 * I don't care about speed at all ! Size and implementation time
69 * is much more important IMHO. I could have created some sophisticated
70 * tree structure, but... what the hell ! :-)
77 static VHSTR_STRUCT **vhstrlist = NULL;
78 static VHSTR vhstr_alloc = 0;
80 #define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount))
82 /***********************************************************************
83 * vsmStringAdd (SETUPX.207)
85 VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName)
91 TRACE("add string '%s'\n", lpszName);
92 /* search whether string already inserted */
93 TRACE("searching for existing string...\n");
94 for (n = 0; n < vhstr_alloc; n++)
96 if ((vhstrlist[n]) && (vhstrlist[n]->refcount))
98 TRACE("checking item: %d\n", n);
99 if (!strcmp(vhstrlist[n]->pStr, lpszName))
102 vhstrlist[n]->refcount++;
108 /* hmm, not found yet, let's insert it */
109 TRACE("inserting item\n");
110 for (n = 0; n < vhstr_alloc; n++)
112 if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount)))
118 heap = GetProcessHeap();
119 if (n == vhstr_alloc) /* hmm, no free index found yet */
123 vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
124 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
127 return 0xffff; /* failure */
128 if (!vhstrlist[index])
129 vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT));
130 vhstrlist[index]->refcount = 1;
131 vhstrlist[index]->pStr = HeapAlloc(heap, 0, strlen(lpszName)+1);
132 strcpy((LPSTR)vhstrlist[index]->pStr, lpszName);
136 /***********************************************************************
137 * vsmStringDelete (SETUPX.206)
139 INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
141 if (VALID_VHSTR(vhstr))
143 vhstrlist[vhstr]->refcount--;
144 if (!vhstrlist[vhstr]->refcount)
146 HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
147 vhstrlist[vhstr]->pStr = NULL;
152 /* string not found */
157 * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
159 VHSTR WINAPI vsmStringFind16(LPCSTR lpszName)
162 for (n = 0; n < vhstr_alloc; n++)
163 if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName)))
168 /***********************************************************************
169 * vsmGetStringName (SETUPX.205)
171 * Pretty correct, I guess
173 INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
175 if (VALID_VHSTR(vhstr))
177 int len = strlen(vhstrlist[vhstr]->pStr)+1;
181 strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
188 /***********************************************************************
189 * vsmStringCompare (not exported from a standard SETUPX.DLL, it seems)
191 INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB)
193 if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB)))
194 return VCPN_FAIL; /* correct ? */
195 return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr);
198 /***********************************************************************
199 * vsmGetStringRawName (SETUPX.208)
201 LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
203 return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
207 /***************************** VIRTNODE management ****************************/
208 static LPVIRTNODE *pvnlist = NULL;
209 static DWORD vn_num = 0;
210 static DWORD vn_last = 0;
212 RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
218 while (vn_last < vn_num)
220 if (pvnlist[vn_last] == NULL)
224 heap = GetProcessHeap();
225 if (vn_last == vn_num)
228 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
229 sizeof(LPVIRTNODE *) * vn_num);
231 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
232 lpvn = pvnlist[vn_last];
235 lpvn->cbSize = sizeof(VIRTNODE);
238 memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC));
241 memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC));
244 lpvn->lParam = lParam;
245 lpvn->lpExpandVtbl = lpExpandVtbl;
247 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
249 cbres = VCP_Callback(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
250 lpvn->fl |= VFNL_CREATED;
251 cbres = VCP_Callback(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);
256 BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
261 for (n = 0; n < vn_last; n++)
263 if (pvnlist[n] == lpvnDel)
265 cbres = VCP_Callback(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
266 HeapFree(GetProcessHeap(), 0, lpvnDel);
274 /***********************************************************************
275 * VcpOpen (SETUPX.200)
277 * Sets up a virtual copy operation.
278 * This means that functions such as GenInstall()
279 * create a VIRTNODE struct for every file to be touched in a .INF file
280 * instead of actually touching the file.
281 * The actual copy/move/rename gets started when VcpClose or
282 * VcpFlush is called; several different callbacks are made
283 * (copy, rename, open, close, version conflicts, ...) on every file copied.
285 RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
287 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
291 VCP_Proc = (FARPROC16)vifproc;
292 VCP_MsgRef = lparamMsgRef;
294 /* load SETUPAPI needed for dialog resources etc. */
295 SETUPAPI_hInstance = LoadLibraryA("setupapi.dll");
296 if (!SETUPAPI_hInstance)
298 ERR("Could not load sibling setupapi.dll\n");
299 return ERR_VCP_NOMEM;
305 /***********************************************************************
306 * VcpQueueCopy [SETUPX.13]
308 * lpExpandVtbl seems to be deprecated.
309 * fl are the CNFL_xxx and VNFL_xxx flags.
310 * lParam are the VNLP_xxx flags.
312 RETERR16 WINAPI VcpQueueCopy16(
313 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
314 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
315 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
316 LPEXPANDVTBL lpExpandVtbl,
317 WORD fl, LPARAM lParam
320 VCPFILESPEC vfsSrc, vfsDst;
323 return ERR_VCP_NOTOPEN;
325 TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
326 lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
328 TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
330 vfsSrc.ldid = ldidSrc;
331 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
332 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
334 vfsDst.ldid = ldidDst;
335 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
336 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
338 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
342 /***********************************************************************
343 * VcpQueueDelete [SETUPX.17]
345 * Is lParamRef the same as lParam in VcpQueueCopy ?
346 * Damn docu !! Err... which docu ?
348 RETERR16 WINAPI VcpQueueDelete16(
349 LPCSTR lpszDstFileName,
358 return ERR_VCP_NOTOPEN;
360 vfsDst.ldid = ldidDst;
361 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
362 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
364 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
367 /***********************************************************************
368 * VcpQueueRename [SETUPX.204]
371 RETERR16 WINAPI VcpQueueRename16(
372 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
373 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
374 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
378 VCPFILESPEC vfsSrc, vfsDst;
381 return ERR_VCP_NOTOPEN;
383 vfsSrc.ldid = ldidSrc;
384 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
385 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
387 vfsDst.ldid = ldidDst;
388 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
389 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
391 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
395 /***********************************************************************
396 * VcpEnumFiles (SETUPX.@)
398 INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
402 for (n = 0; n < vn_last; n++)
403 vep(pvnlist[n], lParamRef);
405 return 0; /* FIXME: return value ? */
408 /***********************************************************************
409 * VcpExplain (SETUPX.411)
411 LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
413 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
420 LPVCPFILESPEC lpvfs =
421 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
423 /* if we have an ldid, use it, otherwise use the string */
424 /* from the vhstrlist array */
425 if (lpvfs->ldid != 0xffff)
426 CtlGetLddPath16(lpvfs->ldid, buffer);
428 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
430 strcat(buffer, "\\");
431 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
435 FIXME("%ld unimplemented !\n", dwWhat);
436 strcpy(buffer, "Unknown error");
442 RETERR16 VCP_CheckPaths(void)
448 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
449 for (n = 0; n < vn_num; n++)
453 /* FIXME: check paths of all VIRTNODEs here ! */
454 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
456 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
460 RETERR16 VCP_CopyFiles(void)
462 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
463 RETERR16 res = OK, cbres;
467 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
468 for (n = 0; n < vn_num; n++)
471 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
472 /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
473 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
474 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
475 /* FIXME: what is this VCPM_VSTATWRITE here for ?
476 * I guess it's to signal successful destination file creation */
477 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
479 /* FIXME: need to do the file copy in small chunks for notifications */
480 TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
481 /* perform the file copy */
482 if (!(CopyFileA(fn_src, fn_dst,
483 (lpvn->fl & VNLP_COPYIFEXISTS) ? FALSE : TRUE )))
485 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
486 res = ERR_VCP_IOFAIL;
489 vcp_status.prgFileRead.dwSoFar++;
490 cbres = VCP_Callback(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
491 vcp_status.prgFileWrite.dwSoFar++;
492 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
495 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
499 /***********************************************************************
500 * VcpFlush - internal (not exported), but documented
502 * VNFL_NOW is used for VcpFlush.
504 RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
509 /***********************************************************************
510 * VcpClose (SETUPX.201)
512 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
513 * VCPM_VSTATCLOSEEND.
515 * fl gets VCPFL_xxx flags to indicate what to do with the
516 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
518 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
521 WORD cbres = VCPN_PROCEED;
523 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
525 /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER
526 * is not set. This is done by VCP_Callback(VCPM_NODECOMPARE) */
529 memset(&vcp_status, 0, sizeof(VCPSTATUS));
530 /* yes, vcp_status.cbSize is 0 ! */
532 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
535 res = VCP_CheckPaths();
538 return res; /* is this ok ? */
542 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
545 FreeLibrary(SETUPAPI_hInstance);
550 RETERR16 VCP_RenameFiles(void)
552 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
553 RETERR16 res = OK, cbres;
557 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
558 for (n = 0; n < vn_num; n++)
561 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
562 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
563 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
564 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
565 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
566 res = ERR_VCP_IOFAIL;
568 VCP_VirtnodeDelete(lpvn);
570 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
574 /***********************************************************************
575 * vcpDefCallbackProc (SETUPX.202)
577 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
578 LPARAM lParam, LPARAM lParamRef)
580 static int count = 0;
582 FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
583 lpvObj, uMsg, wParam, lParam, lParamRef);
588 /********************* point-and-click stuff from here ***********************/
590 static HWND hDlgCopy = 0;
591 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
592 static char BackupDir[12];
594 static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
596 INT_PTR retval = FALSE;
598 if (iMsg == WM_INITDIALOG)
600 ShowWindow(hWndDlg, SW_SHOWNORMAL);
601 UpdateWindow(hWndDlg);
607 BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
612 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), RT_DIALOGA)))
614 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
615 !(*template32 = LockResource( hDlgTmpl32 )))
620 static LRESULT WINAPI
621 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
623 if (uMsg != WM_CREATE)
624 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
631 FIXME("%04x: unhandled.\n", uMsg);
637 void VCP_UI_RegisterProgressClass(void)
639 static BOOL registered = FALSE;
646 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
647 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
648 wndClass.lpfnWndProc = (WNDPROC)VCP_UI_FileCopyWndProc;
649 wndClass.cbClsExtra = 0;
650 wndClass.cbWndExtra = 0;
651 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
652 wndClass.hbrBackground = NULL;
653 wndClass.lpszClassName = "setupx_progress";
655 RegisterClassA (&wndClass);
658 RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
661 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
662 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
663 return (RETERR16)strcmp(file1, file2);
666 RETERR16 VCP_UI_CopyStart(void)
669 char buf[256]; /* plenty */
673 /* FIXME: should be registered at DLL startup instead */
674 VCP_UI_RegisterProgressClass();
675 if (!(VCP_UI_GetDialogTemplate(&template32)))
678 if (vn_num > 10) /* hack */
680 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
681 VCP_UI_FileCopyDlgProc, 0);
684 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
685 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
687 strcpy(buf, REG_INSTALLEDFILES);
688 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
690 strcat(buf, REGPART_RENAME);
691 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
693 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
696 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
698 /* FIXME: what does SETUPX.DLL do in this case ? */
699 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
703 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
706 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len)))
707 strcpy(BackupDir, "VCM");
709 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
710 GetWindowsDirectoryA(buf, 256);
712 strcat(buf, BackupDir);
713 if (!(CreateDirectoryA(buf, NULL)))
715 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
717 RegCloseKey(hKeyConflict);
722 /***********************************************************************
723 * vcpUICallbackProc (SETUPX.213)
725 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
726 LPARAM lParam, LPARAM lParamRef)
728 static int count = 0;
729 RETERR16 res = VCPN_OK, cbres;
732 FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n",
733 lpvObj, uMsg, wParam, lParam, lParamRef);
737 /* unused messages, it seems */
738 case VCPM_DISKPREPINFO:
740 case VCPM_FILENEEDED:
742 case VCPM_NODECREATE:
743 case VCPM_NODEACCEPT:
745 case VCPM_VSTATCLOSESTART:
746 case VCPM_VSTATPATHCHECKSTART:
747 case VCPM_VSTATPATHCHECKEND:
753 case VCPM_NODECOMPARE:
754 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
758 case VCPM_VSTATWRITE:
759 cbres = VCP_Callback(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
761 case VCPM_VSTATCLOSEEND:
762 RegCloseKey(hKeyFiles);
763 RegCloseKey(hKeyRename);
764 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
766 case VCPM_VSTATCOPYSTART:
767 res = VCP_UI_CopyStart();
769 case VCPM_VSTATCOPYEND:
770 if (hDlgCopy) DestroyWindow(hDlgCopy);
773 FIXME("unhandled msg 0x%04x\n", uMsg);