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.
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 HINSTANCE SETUPAPI_hInstance;
48 static WORD VCP_Callback( LPVOID obj, UINT16 msg, WPARAM16 wParam, LPARAM lParam, LPARAM lParamRef )
54 args[7] = HIWORD(obj);
55 args[6] = LOWORD(obj);
58 args[3] = HIWORD(lParam);
59 args[2] = LOWORD(lParam);
60 args[1] = HIWORD(lParamRef);
61 args[0] = LOWORD(lParamRef);
62 WOWCallback16Ex( (DWORD)VCP_Proc, WCB16_PASCAL, sizeof(args), args, &ret );
67 /****************************** VHSTR management ******************************/
70 * This is a totally braindead implementation for now;
71 * I don't care about speed at all ! Size and implementation time
72 * is much more important IMHO. I could have created some sophisticated
73 * tree structure, but... what the hell ! :-)
80 static VHSTR_STRUCT **vhstrlist = NULL;
81 static VHSTR vhstr_alloc = 0;
83 #define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount))
85 /***********************************************************************
86 * vsmStringAdd (SETUPX.207)
88 VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName)
95 TRACE("add string '%s'\n", lpszName);
96 /* search whether string already inserted */
97 TRACE("searching for existing string...\n");
98 for (n = 0; n < vhstr_alloc; n++)
100 if ((vhstrlist[n]) && (vhstrlist[n]->refcount))
102 TRACE("checking item: %d\n", n);
103 if (!strcmp(vhstrlist[n]->pStr, lpszName))
106 vhstrlist[n]->refcount++;
112 /* hmm, not found yet, let's insert it */
113 TRACE("inserting item\n");
114 for (n = 0; n < vhstr_alloc; n++)
116 if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount)))
122 heap = GetProcessHeap();
123 if (n == vhstr_alloc) /* hmm, no free index found yet */
129 vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
130 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
132 vhstrlist = HeapAlloc(heap, HEAP_ZERO_MEMORY,
133 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
136 return 0xffff; /* failure */
137 if (!vhstrlist[index])
138 vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT));
139 vhstrlist[index]->refcount = 1;
140 str = HeapAlloc(heap, 0, strlen(lpszName)+1);
141 strcpy(str, lpszName);
142 vhstrlist[index]->pStr = str;
146 /***********************************************************************
147 * vsmStringDelete (SETUPX.206)
149 INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
151 if (VALID_VHSTR(vhstr))
153 vhstrlist[vhstr]->refcount--;
154 if (!vhstrlist[vhstr]->refcount)
156 HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
157 vhstrlist[vhstr]->pStr = NULL;
162 /* string not found */
167 * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
169 VHSTR WINAPI vsmStringFind16(LPCSTR lpszName)
172 for (n = 0; n < vhstr_alloc; n++)
173 if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName)))
178 /***********************************************************************
179 * vsmGetStringName (SETUPX.205)
181 * Pretty correct, I guess
183 INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
185 if (VALID_VHSTR(vhstr))
187 int len = strlen(vhstrlist[vhstr]->pStr)+1;
191 strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
198 /***********************************************************************
199 * vsmStringCompare (not exported from a standard SETUPX.DLL, it seems)
201 INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB)
203 if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB)))
204 return VCPN_FAIL; /* correct ? */
205 return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr);
208 /***********************************************************************
209 * vsmGetStringRawName (SETUPX.208)
211 LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
213 return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
217 /***************************** VIRTNODE management ****************************/
218 static LPVIRTNODE *pvnlist = NULL;
219 static DWORD vn_num = 0;
220 static DWORD vn_last = 0;
222 static RETERR16 VCP_VirtnodeCreate(const VCPFILESPEC *vfsSrc, const VCPFILESPEC *vfsDst,
223 WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
229 while (vn_last < vn_num)
231 if (pvnlist[vn_last] == NULL)
235 heap = GetProcessHeap();
236 if (vn_last == vn_num)
240 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
241 sizeof(LPVIRTNODE *) * vn_num);
243 pvnlist = HeapAlloc(heap, HEAP_ZERO_MEMORY,
244 sizeof(LPVIRTNODE *) * vn_num);
246 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
247 lpvn = pvnlist[vn_last];
250 lpvn->cbSize = sizeof(VIRTNODE);
253 lpvn->vfsSrc = *vfsSrc;
256 lpvn->vfsDst = *vfsDst;
259 lpvn->lParam = lParam;
260 lpvn->lpExpandVtbl = lpExpandVtbl;
262 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
264 cbres = VCP_Callback(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
265 lpvn->fl |= VFNL_CREATED;
266 cbres = VCP_Callback(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);
272 static BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
277 for (n = 0; n < vn_last; n++)
279 if (pvnlist[n] == lpvnDel)
281 cbres = VCP_Callback(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
282 HeapFree(GetProcessHeap(), 0, lpvnDel);
291 /***********************************************************************
292 * VcpOpen (SETUPX.200)
294 * Sets up a virtual copy operation.
295 * This means that functions such as GenInstall()
296 * create a VIRTNODE struct for every file to be touched in a .INF file
297 * instead of actually touching the file.
298 * The actual copy/move/rename gets started when VcpClose or
299 * VcpFlush is called; several different callbacks are made
300 * (copy, rename, open, close, version conflicts, ...) on every file copied.
302 RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
304 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
308 VCP_Proc = (FARPROC16)vifproc;
309 VCP_MsgRef = lparamMsgRef;
311 /* load SETUPAPI needed for dialog resources etc. */
312 SETUPAPI_hInstance = GetModuleHandleA("setupapi.dll");
313 if (!SETUPAPI_hInstance)
315 ERR("Could not load sibling setupapi.dll\n");
316 return ERR_VCP_NOMEM;
322 /***********************************************************************
323 * VcpQueueCopy [SETUPX.13]
325 * lpExpandVtbl seems to be deprecated.
326 * fl are the CNFL_xxx and VNFL_xxx flags.
327 * lParam are the VNLP_xxx flags.
329 RETERR16 WINAPI VcpQueueCopy16(
330 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
331 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
332 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
333 LPEXPANDVTBL lpExpandVtbl,
334 WORD fl, LPARAM lParam
337 VCPFILESPEC vfsSrc, vfsDst;
340 return ERR_VCP_NOTOPEN;
342 TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
343 lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
345 TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
347 vfsSrc.ldid = ldidSrc;
348 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
349 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
351 vfsDst.ldid = ldidDst;
352 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
353 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
355 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
359 /***********************************************************************
360 * VcpQueueDelete [SETUPX.17]
362 * Is lParamRef the same as lParam in VcpQueueCopy ?
363 * Damn docu !! Err... which docu ?
365 RETERR16 WINAPI VcpQueueDelete16(
366 LPCSTR lpszDstFileName,
375 return ERR_VCP_NOTOPEN;
377 vfsDst.ldid = ldidDst;
378 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
379 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
381 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
384 /***********************************************************************
385 * VcpQueueRename [SETUPX.204]
388 RETERR16 WINAPI VcpQueueRename16(
389 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
390 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
391 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
395 VCPFILESPEC vfsSrc, vfsDst;
398 return ERR_VCP_NOTOPEN;
400 vfsSrc.ldid = ldidSrc;
401 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
402 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
404 vfsDst.ldid = ldidDst;
405 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
406 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
408 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
412 /***********************************************************************
413 * VcpEnumFiles (SETUPX.@)
415 INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
419 for (n = 0; n < vn_last; n++)
420 vep(pvnlist[n], lParamRef);
422 return 0; /* FIXME: return value ? */
425 /***********************************************************************
426 * VcpExplain (SETUPX.411)
428 LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
430 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
437 LPVCPFILESPEC lpvfs =
438 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
440 /* if we have an ldid, use it, otherwise use the string */
441 /* from the vhstrlist array */
442 if (lpvfs->ldid != 0xffff)
443 CtlGetLddPath16(lpvfs->ldid, buffer);
445 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
447 strcat(buffer, "\\");
448 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
452 FIXME("%d unimplemented !\n", dwWhat);
453 strcpy(buffer, "Unknown error");
459 static RETERR16 VCP_CheckPaths(void)
465 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
466 for (n = 0; n < vn_num; n++)
470 /* FIXME: check paths of all VIRTNODEs here ! */
471 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
473 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
477 static RETERR16 VCP_CopyFiles(void)
479 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
480 RETERR16 res = OK, cbres;
484 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
485 for (n = 0; n < vn_num; n++)
488 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
489 /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
490 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
491 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
492 /* FIXME: what is this VCPM_VSTATWRITE here for ?
493 * I guess it's to signal successful destination file creation */
494 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
496 /* FIXME: need to do the file copy in small chunks for notifications */
497 TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
498 /* perform the file copy */
499 if (!(CopyFileA(fn_src, fn_dst,
500 (lpvn->fl & VNLP_COPYIFEXISTS) ? FALSE : TRUE )))
502 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
503 res = ERR_VCP_IOFAIL;
506 vcp_status.prgFileRead.dwSoFar++;
507 cbres = VCP_Callback(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
508 vcp_status.prgFileWrite.dwSoFar++;
509 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
512 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
516 /***********************************************************************
517 * VcpFlush - internal (not exported), but documented
519 * VNFL_NOW is used for VcpFlush.
521 RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
526 /***********************************************************************
527 * VcpClose (SETUPX.201)
529 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
530 * VCPM_VSTATCLOSEEND.
532 * fl gets VCPFL_xxx flags to indicate what to do with the
533 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
535 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
538 WORD cbres = VCPN_PROCEED;
540 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
542 /* FIXME: needs to sort VIRTNODEs in case VCPFL_INSPECIFIEDORDER
543 * is not set. This is done by VCP_Callback(VCPM_NODECOMPARE) */
546 memset(&vcp_status, 0, sizeof(VCPSTATUS));
547 /* yes, vcp_status.cbSize is 0 ! */
549 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
552 res = VCP_CheckPaths();
555 return res; /* is this ok ? */
559 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
567 static RETERR16 VCP_RenameFiles(void)
569 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
570 RETERR16 res = OK, cbres;
574 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
575 for (n = 0; n < vn_num; n++)
578 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
579 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
580 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
581 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
582 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
583 res = ERR_VCP_IOFAIL;
585 VCP_VirtnodeDelete(lpvn);
587 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
592 /***********************************************************************
593 * vcpDefCallbackProc (SETUPX.202)
595 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
596 LPARAM lParam, LPARAM lParamRef)
598 static int count = 0;
600 FIXME("(%p, %04x, %04lx, %08lx, %08lx) - what to do here ?\n",
601 lpvObj, uMsg, wParam, lParam, lParamRef);
606 /********************* point-and-click stuff from here ***********************/
608 static HWND hDlgCopy = 0;
609 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
610 static char BackupDir[12];
612 static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
614 INT_PTR retval = FALSE;
616 if (iMsg == WM_INITDIALOG)
618 ShowWindow(hWndDlg, SW_SHOWNORMAL);
619 UpdateWindow(hWndDlg);
625 static BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
630 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), (LPSTR)RT_DIALOG)))
632 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
633 !(*template32 = LockResource( hDlgTmpl32 )))
638 static LRESULT WINAPI
639 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
641 if (uMsg != WM_CREATE)
642 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
649 FIXME("%04x: unhandled.\n", uMsg);
655 static void VCP_UI_RegisterProgressClass(void)
657 static BOOL registered = FALSE;
664 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
665 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
666 wndClass.lpfnWndProc = VCP_UI_FileCopyWndProc;
667 wndClass.cbClsExtra = 0;
668 wndClass.cbWndExtra = 0;
669 wndClass.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
670 wndClass.hbrBackground = NULL;
671 wndClass.lpszClassName = "setupx_progress";
673 RegisterClassA (&wndClass);
676 static RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
679 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
680 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
681 return (RETERR16)strcmp(file1, file2);
684 static RETERR16 VCP_UI_CopyStart(void)
687 char buf[256]; /* plenty */
691 /* FIXME: should be registered at DLL startup instead */
692 VCP_UI_RegisterProgressClass();
693 if (!(VCP_UI_GetDialogTemplate(&template32)))
696 if (vn_num > 10) /* hack */
698 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
699 VCP_UI_FileCopyDlgProc, 0);
702 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
703 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
705 strcpy(buf, REG_INSTALLEDFILES);
706 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
708 strcat(buf, REGPART_RENAME);
709 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
711 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
714 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
716 /* FIXME: what does SETUPX.DLL do in this case ? */
717 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
721 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
724 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, (LPBYTE)BackupDir, &len)))
725 strcpy(BackupDir, "VCM");
727 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
728 GetWindowsDirectoryA(buf, 256);
730 strcat(buf, BackupDir);
731 if (!(CreateDirectoryA(buf, NULL)))
733 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
735 RegCloseKey(hKeyConflict);
740 /***********************************************************************
741 * vcpUICallbackProc (SETUPX.213)
743 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
744 LPARAM lParam, LPARAM lParamRef)
746 static int count = 0;
747 RETERR16 res = VCPN_OK, cbres;
750 FIXME("(%p, %04x, %04lx, %08lx, %08lx) - semi-stub\n",
751 lpvObj, uMsg, wParam, lParam, lParamRef);
755 /* unused messages, it seems */
756 case VCPM_DISKPREPINFO:
758 case VCPM_FILENEEDED:
760 case VCPM_NODECREATE:
761 case VCPM_NODEACCEPT:
763 case VCPM_VSTATCLOSESTART:
764 case VCPM_VSTATPATHCHECKSTART:
765 case VCPM_VSTATPATHCHECKEND:
771 case VCPM_NODECOMPARE:
772 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
776 case VCPM_VSTATWRITE:
777 cbres = VCP_Callback(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
779 case VCPM_VSTATCLOSEEND:
780 RegCloseKey(hKeyFiles);
781 RegCloseKey(hKeyRename);
782 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
784 case VCPM_VSTATCOPYSTART:
785 res = VCP_UI_CopyStart();
787 case VCPM_VSTATCOPYEND:
788 if (hDlgCopy) DestroyWindow(hDlgCopy);
791 FIXME("unhandled msg 0x%04x\n", uMsg);