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.
35 #include "setupapi_private.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
40 static FARPROC16 VCP_Proc = NULL;
41 static LPARAM VCP_MsgRef = 0;
43 static BOOL VCP_opened = FALSE;
45 static VCPSTATUS vcp_status;
47 static HINSTANCE SETUPAPI_hInstance;
49 static WORD VCP_Callback( LPVOID obj, UINT16 msg, WPARAM16 wParam, LPARAM lParam, LPARAM lParamRef )
55 args[7] = HIWORD(obj);
56 args[6] = LOWORD(obj);
59 args[3] = HIWORD(lParam);
60 args[2] = LOWORD(lParam);
61 args[1] = HIWORD(lParamRef);
62 args[0] = LOWORD(lParamRef);
63 WOWCallback16Ex( (DWORD)VCP_Proc, WCB16_PASCAL, sizeof(args), args, &ret );
68 /****************************** VHSTR management ******************************/
71 * This is a totally braindead implementation for now;
72 * I don't care about speed at all ! Size and implementation time
73 * is much more important IMHO. I could have created some sophisticated
74 * tree structure, but... what the hell ! :-)
81 static VHSTR_STRUCT **vhstrlist = NULL;
82 static VHSTR vhstr_alloc = 0;
84 #define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount))
86 /***********************************************************************
87 * vsmStringAdd (SETUPX.207)
89 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 */
127 vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
128 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
131 return 0xffff; /* failure */
132 if (!vhstrlist[index])
133 vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT));
134 vhstrlist[index]->refcount = 1;
135 vhstrlist[index]->pStr = HeapAlloc(heap, 0, strlen(lpszName)+1);
136 strcpy((LPSTR)vhstrlist[index]->pStr, lpszName);
140 /***********************************************************************
141 * vsmStringDelete (SETUPX.206)
143 INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
145 if (VALID_VHSTR(vhstr))
147 vhstrlist[vhstr]->refcount--;
148 if (!vhstrlist[vhstr]->refcount)
150 HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
151 vhstrlist[vhstr]->pStr = NULL;
156 /* string not found */
161 * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
163 VHSTR WINAPI vsmStringFind16(LPCSTR lpszName)
166 for (n = 0; n < vhstr_alloc; n++)
167 if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName)))
172 /***********************************************************************
173 * vsmGetStringName (SETUPX.205)
175 * Pretty correct, I guess
177 INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
179 if (VALID_VHSTR(vhstr))
181 int len = strlen(vhstrlist[vhstr]->pStr)+1;
185 strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
192 /***********************************************************************
193 * vsmStringCompare (not exported from a standard SETUPX.DLL, it seems)
195 INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB)
197 if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB)))
198 return VCPN_FAIL; /* correct ? */
199 return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr);
202 /***********************************************************************
203 * vsmGetStringRawName (SETUPX.208)
205 LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
207 return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
211 /***************************** VIRTNODE management ****************************/
212 static LPVIRTNODE *pvnlist = NULL;
213 static DWORD vn_num = 0;
214 static DWORD vn_last = 0;
216 RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
222 while (vn_last < vn_num)
224 if (pvnlist[vn_last] == NULL)
228 heap = GetProcessHeap();
229 if (vn_last == vn_num)
232 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
233 sizeof(LPVIRTNODE *) * vn_num);
235 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
236 lpvn = pvnlist[vn_last];
239 lpvn->cbSize = sizeof(VIRTNODE);
242 memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC));
245 memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC));
248 lpvn->lParam = lParam;
249 lpvn->lpExpandVtbl = lpExpandVtbl;
251 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
253 cbres = VCP_Callback(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
254 lpvn->fl |= VFNL_CREATED;
255 cbres = VCP_Callback(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);
260 BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
265 for (n = 0; n < vn_last; n++)
267 if (pvnlist[n] == lpvnDel)
269 cbres = VCP_Callback(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
270 HeapFree(GetProcessHeap(), 0, lpvnDel);
278 /***********************************************************************
279 * VcpOpen (SETUPX.200)
281 * Sets up a virtual copy operation.
282 * This means that functions such as GenInstall()
283 * create a VIRTNODE struct for every file to be touched in a .INF file
284 * instead of actually touching the file.
285 * The actual copy/move/rename gets started when VcpClose or
286 * VcpFlush is called; several different callbacks are made
287 * (copy, rename, open, close, version conflicts, ...) on every file copied.
289 RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
291 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
295 VCP_Proc = (FARPROC16)vifproc;
296 VCP_MsgRef = lparamMsgRef;
298 /* load SETUPAPI needed for dialog resources etc. */
299 SETUPAPI_hInstance = LoadLibraryA("setupapi.dll");
300 if (!SETUPAPI_hInstance)
302 ERR("Could not load sibling setupapi.dll\n");
303 return ERR_VCP_NOMEM;
309 /***********************************************************************
310 * VcpQueueCopy [SETUPX.13]
312 * lpExpandVtbl seems to be deprecated.
313 * fl are the CNFL_xxx and VNFL_xxx flags.
314 * lParam are the VNLP_xxx flags.
316 RETERR16 WINAPI VcpQueueCopy16(
317 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
318 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
319 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
320 LPEXPANDVTBL lpExpandVtbl,
321 WORD fl, LPARAM lParam
324 VCPFILESPEC vfsSrc, vfsDst;
327 return ERR_VCP_NOTOPEN;
329 TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
330 lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
332 TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
334 vfsSrc.ldid = ldidSrc;
335 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
336 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
338 vfsDst.ldid = ldidDst;
339 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
340 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
342 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
346 /***********************************************************************
347 * VcpQueueDelete [SETUPX.17]
349 * Is lParamRef the same as lParam in VcpQueueCopy ?
350 * Damn docu !! Err... which docu ?
352 RETERR16 WINAPI VcpQueueDelete16(
353 LPCSTR lpszDstFileName,
362 return ERR_VCP_NOTOPEN;
364 vfsDst.ldid = ldidDst;
365 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
366 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
368 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
371 /***********************************************************************
372 * VcpQueueRename [SETUPX.204]
375 RETERR16 WINAPI VcpQueueRename16(
376 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
377 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
378 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
382 VCPFILESPEC vfsSrc, vfsDst;
385 return ERR_VCP_NOTOPEN;
387 vfsSrc.ldid = ldidSrc;
388 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
389 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
391 vfsDst.ldid = ldidDst;
392 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
393 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
395 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
399 /***********************************************************************
400 * VcpEnumFiles (SETUPX.@)
402 INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
406 for (n = 0; n < vn_last; n++)
407 vep(pvnlist[n], lParamRef);
409 return 0; /* FIXME: return value ? */
412 /***********************************************************************
413 * VcpExplain (SETUPX.411)
415 LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
417 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
424 LPVCPFILESPEC lpvfs =
425 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
427 /* if we have an ldid, use it, otherwise use the string */
428 /* from the vhstrlist array */
429 if (lpvfs->ldid != 0xffff)
430 CtlGetLddPath16(lpvfs->ldid, buffer);
432 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
434 strcat(buffer, "\\");
435 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
439 FIXME("%ld unimplemented !\n", dwWhat);
440 strcpy(buffer, "Unknown error");
446 RETERR16 VCP_CheckPaths(void)
452 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
453 for (n = 0; n < vn_num; n++)
457 /* FIXME: check paths of all VIRTNODEs here ! */
458 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
460 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
464 RETERR16 VCP_CopyFiles(void)
466 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
467 RETERR16 res = OK, cbres;
471 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
472 for (n = 0; n < vn_num; n++)
475 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
476 /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
477 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
478 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
479 /* FIXME: what is this VCPM_VSTATWRITE here for ?
480 * I guess it's to signal successful destination file creation */
481 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
483 /* FIXME: need to do the file copy in small chunks for notifications */
484 TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
485 /* perform the file copy */
486 if (!(CopyFileA(fn_src, fn_dst,
487 (lpvn->fl & VNLP_COPYIFEXISTS) ? FALSE : TRUE )))
489 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
490 res = ERR_VCP_IOFAIL;
493 vcp_status.prgFileRead.dwSoFar++;
494 cbres = VCP_Callback(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
495 vcp_status.prgFileWrite.dwSoFar++;
496 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
499 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
503 /***********************************************************************
504 * VcpFlush - internal (not exported), but documented
506 * VNFL_NOW is used for VcpFlush.
508 RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
513 /***********************************************************************
514 * VcpClose (SETUPX.201)
516 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
517 * VCPM_VSTATCLOSEEND.
519 * fl gets VCPFL_xxx flags to indicate what to do with the
520 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
522 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
525 WORD cbres = VCPN_PROCEED;
527 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
529 /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER
530 * is not set. This is done by VCP_Callback(VCPM_NODECOMPARE) */
533 memset(&vcp_status, 0, sizeof(VCPSTATUS));
534 /* yes, vcp_status.cbSize is 0 ! */
536 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
539 res = VCP_CheckPaths();
542 return res; /* is this ok ? */
546 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
549 FreeLibrary(SETUPAPI_hInstance);
554 RETERR16 VCP_RenameFiles(void)
556 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
557 RETERR16 res = OK, cbres;
561 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
562 for (n = 0; n < vn_num; n++)
565 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
566 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
567 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
568 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
569 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
570 res = ERR_VCP_IOFAIL;
572 VCP_VirtnodeDelete(lpvn);
574 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
578 /***********************************************************************
579 * vcpDefCallbackProc (SETUPX.202)
581 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
582 LPARAM lParam, LPARAM lParamRef)
584 static int count = 0;
586 FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
587 lpvObj, uMsg, wParam, lParam, lParamRef);
592 /********************* point-and-click stuff from here ***********************/
594 static HWND hDlgCopy = 0;
595 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
596 static char BackupDir[12];
598 static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
600 INT_PTR retval = FALSE;
602 if (iMsg == WM_INITDIALOG)
604 ShowWindow(hWndDlg, SW_SHOWNORMAL);
605 UpdateWindow(hWndDlg);
611 BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
616 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), (LPSTR)RT_DIALOG)))
618 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
619 !(*template32 = LockResource( hDlgTmpl32 )))
624 static LRESULT WINAPI
625 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
627 if (uMsg != WM_CREATE)
628 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
635 FIXME("%04x: unhandled.\n", uMsg);
641 void VCP_UI_RegisterProgressClass(void)
643 static BOOL registered = FALSE;
650 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
651 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
652 wndClass.lpfnWndProc = (WNDPROC)VCP_UI_FileCopyWndProc;
653 wndClass.cbClsExtra = 0;
654 wndClass.cbWndExtra = 0;
655 wndClass.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
656 wndClass.hbrBackground = NULL;
657 wndClass.lpszClassName = "setupx_progress";
659 RegisterClassA (&wndClass);
662 RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
665 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
666 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
667 return (RETERR16)strcmp(file1, file2);
670 RETERR16 VCP_UI_CopyStart(void)
673 char buf[256]; /* plenty */
677 /* FIXME: should be registered at DLL startup instead */
678 VCP_UI_RegisterProgressClass();
679 if (!(VCP_UI_GetDialogTemplate(&template32)))
682 if (vn_num > 10) /* hack */
684 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
685 VCP_UI_FileCopyDlgProc, 0);
688 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
689 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
691 strcpy(buf, REG_INSTALLEDFILES);
692 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
694 strcat(buf, REGPART_RENAME);
695 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
697 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
700 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
702 /* FIXME: what does SETUPX.DLL do in this case ? */
703 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
707 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
710 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len)))
711 strcpy(BackupDir, "VCM");
713 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
714 GetWindowsDirectoryA(buf, 256);
716 strcat(buf, BackupDir);
717 if (!(CreateDirectoryA(buf, NULL)))
719 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
721 RegCloseKey(hKeyConflict);
726 /***********************************************************************
727 * vcpUICallbackProc (SETUPX.213)
729 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
730 LPARAM lParam, LPARAM lParamRef)
732 static int count = 0;
733 RETERR16 res = VCPN_OK, cbres;
736 FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n",
737 lpvObj, uMsg, wParam, lParam, lParamRef);
741 /* unused messages, it seems */
742 case VCPM_DISKPREPINFO:
744 case VCPM_FILENEEDED:
746 case VCPM_NODECREATE:
747 case VCPM_NODEACCEPT:
749 case VCPM_VSTATCLOSESTART:
750 case VCPM_VSTATPATHCHECKSTART:
751 case VCPM_VSTATPATHCHECKEND:
757 case VCPM_NODECOMPARE:
758 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
762 case VCPM_VSTATWRITE:
763 cbres = VCP_Callback(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
765 case VCPM_VSTATCLOSEEND:
766 RegCloseKey(hKeyFiles);
767 RegCloseKey(hKeyRename);
768 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
770 case VCPM_VSTATCOPYSTART:
771 res = VCP_UI_CopyStart();
773 case VCPM_VSTATCOPYEND:
774 if (hDlgCopy) DestroyWindow(hDlgCopy);
777 FIXME("unhandled msg 0x%04x\n", uMsg);