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(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
228 while (vn_last < vn_num)
230 if (pvnlist[vn_last] == NULL)
234 heap = GetProcessHeap();
235 if (vn_last == vn_num)
239 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
240 sizeof(LPVIRTNODE *) * vn_num);
242 pvnlist = HeapAlloc(heap, HEAP_ZERO_MEMORY,
243 sizeof(LPVIRTNODE *) * vn_num);
245 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
246 lpvn = pvnlist[vn_last];
249 lpvn->cbSize = sizeof(VIRTNODE);
252 memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC));
255 memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC));
258 lpvn->lParam = lParam;
259 lpvn->lpExpandVtbl = lpExpandVtbl;
261 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
263 cbres = VCP_Callback(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
264 lpvn->fl |= VFNL_CREATED;
265 cbres = VCP_Callback(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);
271 static BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
276 for (n = 0; n < vn_last; n++)
278 if (pvnlist[n] == lpvnDel)
280 cbres = VCP_Callback(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
281 HeapFree(GetProcessHeap(), 0, lpvnDel);
290 /***********************************************************************
291 * VcpOpen (SETUPX.200)
293 * Sets up a virtual copy operation.
294 * This means that functions such as GenInstall()
295 * create a VIRTNODE struct for every file to be touched in a .INF file
296 * instead of actually touching the file.
297 * The actual copy/move/rename gets started when VcpClose or
298 * VcpFlush is called; several different callbacks are made
299 * (copy, rename, open, close, version conflicts, ...) on every file copied.
301 RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
303 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
307 VCP_Proc = (FARPROC16)vifproc;
308 VCP_MsgRef = lparamMsgRef;
310 /* load SETUPAPI needed for dialog resources etc. */
311 SETUPAPI_hInstance = GetModuleHandleA("setupapi.dll");
312 if (!SETUPAPI_hInstance)
314 ERR("Could not load sibling setupapi.dll\n");
315 return ERR_VCP_NOMEM;
321 /***********************************************************************
322 * VcpQueueCopy [SETUPX.13]
324 * lpExpandVtbl seems to be deprecated.
325 * fl are the CNFL_xxx and VNFL_xxx flags.
326 * lParam are the VNLP_xxx flags.
328 RETERR16 WINAPI VcpQueueCopy16(
329 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
330 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
331 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
332 LPEXPANDVTBL lpExpandVtbl,
333 WORD fl, LPARAM lParam
336 VCPFILESPEC vfsSrc, vfsDst;
339 return ERR_VCP_NOTOPEN;
341 TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
342 lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
344 TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
346 vfsSrc.ldid = ldidSrc;
347 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
348 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
350 vfsDst.ldid = ldidDst;
351 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
352 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
354 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
358 /***********************************************************************
359 * VcpQueueDelete [SETUPX.17]
361 * Is lParamRef the same as lParam in VcpQueueCopy ?
362 * Damn docu !! Err... which docu ?
364 RETERR16 WINAPI VcpQueueDelete16(
365 LPCSTR lpszDstFileName,
374 return ERR_VCP_NOTOPEN;
376 vfsDst.ldid = ldidDst;
377 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
378 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
380 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
383 /***********************************************************************
384 * VcpQueueRename [SETUPX.204]
387 RETERR16 WINAPI VcpQueueRename16(
388 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
389 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
390 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
394 VCPFILESPEC vfsSrc, vfsDst;
397 return ERR_VCP_NOTOPEN;
399 vfsSrc.ldid = ldidSrc;
400 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
401 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
403 vfsDst.ldid = ldidDst;
404 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
405 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
407 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
411 /***********************************************************************
412 * VcpEnumFiles (SETUPX.@)
414 INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
418 for (n = 0; n < vn_last; n++)
419 vep(pvnlist[n], lParamRef);
421 return 0; /* FIXME: return value ? */
424 /***********************************************************************
425 * VcpExplain (SETUPX.411)
427 LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
429 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
436 LPVCPFILESPEC lpvfs =
437 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
439 /* if we have an ldid, use it, otherwise use the string */
440 /* from the vhstrlist array */
441 if (lpvfs->ldid != 0xffff)
442 CtlGetLddPath16(lpvfs->ldid, buffer);
444 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
446 strcat(buffer, "\\");
447 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
451 FIXME("%d unimplemented !\n", dwWhat);
452 strcpy(buffer, "Unknown error");
458 static RETERR16 VCP_CheckPaths(void)
464 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
465 for (n = 0; n < vn_num; n++)
469 /* FIXME: check paths of all VIRTNODEs here ! */
470 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
472 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
476 static RETERR16 VCP_CopyFiles(void)
478 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
479 RETERR16 res = OK, cbres;
483 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
484 for (n = 0; n < vn_num; n++)
487 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
488 /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
489 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
490 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
491 /* FIXME: what is this VCPM_VSTATWRITE here for ?
492 * I guess it's to signal successful destination file creation */
493 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
495 /* FIXME: need to do the file copy in small chunks for notifications */
496 TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
497 /* perform the file copy */
498 if (!(CopyFileA(fn_src, fn_dst,
499 (lpvn->fl & VNLP_COPYIFEXISTS) ? FALSE : TRUE )))
501 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
502 res = ERR_VCP_IOFAIL;
505 vcp_status.prgFileRead.dwSoFar++;
506 cbres = VCP_Callback(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
507 vcp_status.prgFileWrite.dwSoFar++;
508 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
511 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
515 /***********************************************************************
516 * VcpFlush - internal (not exported), but documented
518 * VNFL_NOW is used for VcpFlush.
520 RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
525 /***********************************************************************
526 * VcpClose (SETUPX.201)
528 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
529 * VCPM_VSTATCLOSEEND.
531 * fl gets VCPFL_xxx flags to indicate what to do with the
532 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
534 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
537 WORD cbres = VCPN_PROCEED;
539 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
541 /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER
542 * is not set. This is done by VCP_Callback(VCPM_NODECOMPARE) */
545 memset(&vcp_status, 0, sizeof(VCPSTATUS));
546 /* yes, vcp_status.cbSize is 0 ! */
548 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
551 res = VCP_CheckPaths();
554 return res; /* is this ok ? */
558 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
566 static RETERR16 VCP_RenameFiles(void)
568 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
569 RETERR16 res = OK, cbres;
573 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
574 for (n = 0; n < vn_num; n++)
577 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
578 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
579 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
580 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
581 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
582 res = ERR_VCP_IOFAIL;
584 VCP_VirtnodeDelete(lpvn);
586 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
591 /***********************************************************************
592 * vcpDefCallbackProc (SETUPX.202)
594 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
595 LPARAM lParam, LPARAM lParamRef)
597 static int count = 0;
599 FIXME("(%p, %04x, %04lx, %08lx, %08lx) - what to do here ?\n",
600 lpvObj, uMsg, wParam, lParam, lParamRef);
605 /********************* point-and-click stuff from here ***********************/
607 static HWND hDlgCopy = 0;
608 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
609 static char BackupDir[12];
611 static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
613 INT_PTR retval = FALSE;
615 if (iMsg == WM_INITDIALOG)
617 ShowWindow(hWndDlg, SW_SHOWNORMAL);
618 UpdateWindow(hWndDlg);
624 static BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
629 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), (LPSTR)RT_DIALOG)))
631 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
632 !(*template32 = LockResource( hDlgTmpl32 )))
637 static LRESULT WINAPI
638 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
640 if (uMsg != WM_CREATE)
641 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
648 FIXME("%04x: unhandled.\n", uMsg);
654 static void VCP_UI_RegisterProgressClass(void)
656 static BOOL registered = FALSE;
663 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
664 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
665 wndClass.lpfnWndProc = VCP_UI_FileCopyWndProc;
666 wndClass.cbClsExtra = 0;
667 wndClass.cbWndExtra = 0;
668 wndClass.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
669 wndClass.hbrBackground = NULL;
670 wndClass.lpszClassName = "setupx_progress";
672 RegisterClassA (&wndClass);
675 static RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
678 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
679 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
680 return (RETERR16)strcmp(file1, file2);
683 static RETERR16 VCP_UI_CopyStart(void)
686 char buf[256]; /* plenty */
690 /* FIXME: should be registered at DLL startup instead */
691 VCP_UI_RegisterProgressClass();
692 if (!(VCP_UI_GetDialogTemplate(&template32)))
695 if (vn_num > 10) /* hack */
697 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
698 VCP_UI_FileCopyDlgProc, 0);
701 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
702 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
704 strcpy(buf, REG_INSTALLEDFILES);
705 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
707 strcat(buf, REGPART_RENAME);
708 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
710 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
713 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
715 /* FIXME: what does SETUPX.DLL do in this case ? */
716 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
720 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
723 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, (LPBYTE)BackupDir, &len)))
724 strcpy(BackupDir, "VCM");
726 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
727 GetWindowsDirectoryA(buf, 256);
729 strcat(buf, BackupDir);
730 if (!(CreateDirectoryA(buf, NULL)))
732 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
734 RegCloseKey(hKeyConflict);
739 /***********************************************************************
740 * vcpUICallbackProc (SETUPX.213)
742 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
743 LPARAM lParam, LPARAM lParamRef)
745 static int count = 0;
746 RETERR16 res = VCPN_OK, cbres;
749 FIXME("(%p, %04x, %04lx, %08lx, %08lx) - semi-stub\n",
750 lpvObj, uMsg, wParam, lParam, lParamRef);
754 /* unused messages, it seems */
755 case VCPM_DISKPREPINFO:
757 case VCPM_FILENEEDED:
759 case VCPM_NODECREATE:
760 case VCPM_NODEACCEPT:
762 case VCPM_VSTATCLOSESTART:
763 case VCPM_VSTATPATHCHECKSTART:
764 case VCPM_VSTATPATHCHECKEND:
770 case VCPM_NODECOMPARE:
771 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
775 case VCPM_VSTATWRITE:
776 cbres = VCP_Callback(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
778 case VCPM_VSTATCLOSEEND:
779 RegCloseKey(hKeyFiles);
780 RegCloseKey(hKeyRename);
781 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
783 case VCPM_VSTATCOPYSTART:
784 res = VCP_UI_CopyStart();
786 case VCPM_VSTATCOPYEND:
787 if (hDlgCopy) DestroyWindow(hDlgCopy);
790 FIXME("unhandled msg 0x%04x\n", uMsg);