shell32: Added a stub for IShellDispatch2.
[wine/multimedia.git] / dlls / setupx.dll16 / virtcopy.c
bloba718ac9497f774174c2a340a9fda736c8780a86d
1 /*
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.
24 #include <stdarg.h>
25 #include <string.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winreg.h"
30 #include "wownt32.h"
31 #include "winnls.h"
32 #include "setupapi.h"
33 #include "setupx16.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
38 /* copied from setupapi */
39 #define COPYFILEDLGORD 1000
40 #define SOURCESTRORD 500
41 #define DESTSTRORD 501
42 #define PROGRESSORD 502
44 #define REG_INSTALLEDFILES "System\\CurrentControlSet\\Control\\InstalledFiles"
45 #define REGPART_RENAME "\\Rename"
46 #define REG_VERSIONCONFLICT "Software\\Microsoft\\VersionConflictManager"
48 static FARPROC16 VCP_Proc = NULL;
49 static LPARAM VCP_MsgRef = 0;
51 static BOOL VCP_opened = FALSE;
53 static VCPSTATUS vcp_status;
55 static HMODULE SETUPAPI_hInstance;
57 static WORD VCP_Callback( LPVOID obj, UINT16 msg, WPARAM16 wParam, LPARAM lParam, LPARAM lParamRef )
59 WORD args[8];
60 DWORD ret = OK;
61 if (VCP_Proc)
63 args[7] = HIWORD(obj);
64 args[6] = LOWORD(obj);
65 args[5] = msg;
66 args[4] = wParam;
67 args[3] = HIWORD(lParam);
68 args[2] = LOWORD(lParam);
69 args[1] = HIWORD(lParamRef);
70 args[0] = LOWORD(lParamRef);
71 WOWCallback16Ex( (DWORD)VCP_Proc, WCB16_PASCAL, sizeof(args), args, &ret );
73 return (WORD)ret;
76 /****************************** VHSTR management ******************************/
79 * This is a totally braindead implementation for now;
80 * I don't care about speed at all ! Size and implementation time
81 * is much more important IMHO. I could have created some sophisticated
82 * tree structure, but... what the hell ! :-)
84 typedef struct {
85 DWORD refcount;
86 LPCSTR pStr;
87 } VHSTR_STRUCT;
89 static VHSTR_STRUCT **vhstrlist = NULL;
90 static VHSTR vhstr_alloc = 0;
92 #define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount))
94 /***********************************************************************
95 * vsmStringAdd (SETUPX.207)
97 VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName)
99 VHSTR n;
100 VHSTR index = 0xffff;
101 HANDLE heap;
102 LPSTR str;
104 TRACE("add string '%s'\n", lpszName);
105 /* search whether string already inserted */
106 TRACE("searching for existing string...\n");
107 for (n = 0; n < vhstr_alloc; n++)
109 if ((vhstrlist[n]) && (vhstrlist[n]->refcount))
111 TRACE("checking item: %d\n", n);
112 if (!strcmp(vhstrlist[n]->pStr, lpszName))
114 TRACE("found\n");
115 vhstrlist[n]->refcount++;
116 return n;
121 /* hmm, not found yet, let's insert it */
122 TRACE("inserting item\n");
123 for (n = 0; n < vhstr_alloc; n++)
125 if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount)))
127 index = n;
128 break;
131 heap = GetProcessHeap();
132 if (n == vhstr_alloc) /* hmm, no free index found yet */
134 index = vhstr_alloc;
135 vhstr_alloc += 20;
137 if (vhstrlist)
138 vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
139 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
140 else
141 vhstrlist = HeapAlloc(heap, HEAP_ZERO_MEMORY,
142 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
144 if (index == 0xffff)
145 return 0xffff; /* failure */
146 if (!vhstrlist[index])
147 vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT));
148 vhstrlist[index]->refcount = 1;
149 str = HeapAlloc(heap, 0, strlen(lpszName)+1);
150 strcpy(str, lpszName);
151 vhstrlist[index]->pStr = str;
152 return index;
155 /***********************************************************************
156 * vsmStringDelete (SETUPX.206)
158 INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
160 if (VALID_VHSTR(vhstr))
162 vhstrlist[vhstr]->refcount--;
163 if (!vhstrlist[vhstr]->refcount)
165 HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
166 vhstrlist[vhstr]->pStr = NULL;
168 return VCPN_OK;
171 /* string not found */
172 return VCPN_FAIL;
175 /***********************************************************************
176 * vsmGetStringName (SETUPX.205)
178 * Pretty correct, I guess
180 INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
182 if (VALID_VHSTR(vhstr))
184 int len = strlen(vhstrlist[vhstr]->pStr)+1;
185 if (cbBuffer >= len)
187 if (lpszBuffer)
188 strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
189 return len;
192 return VCPN_FAIL;
195 /***********************************************************************
196 * vsmGetStringRawName (SETUPX.208)
198 LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
200 return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
204 /***************************** VIRTNODE management ****************************/
205 static LPVIRTNODE *pvnlist = NULL;
206 static DWORD vn_num = 0;
207 static DWORD vn_last = 0;
209 static RETERR16 VCP_VirtnodeCreate(const VCPFILESPEC *vfsSrc, const VCPFILESPEC *vfsDst,
210 WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
212 HANDLE heap;
213 LPVIRTNODE lpvn;
215 while (vn_last < vn_num)
217 if (pvnlist[vn_last] == NULL)
218 break;
219 vn_last++;
221 heap = GetProcessHeap();
222 if (vn_last == vn_num)
224 vn_num += 20;
225 if (pvnlist)
226 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
227 sizeof(*pvnlist) * vn_num);
228 else
229 pvnlist = HeapAlloc(heap, HEAP_ZERO_MEMORY,
230 sizeof(*pvnlist) * vn_num);
232 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
233 lpvn = pvnlist[vn_last];
234 vn_last++;
236 lpvn->cbSize = sizeof(VIRTNODE);
238 if (vfsSrc)
239 lpvn->vfsSrc = *vfsSrc;
241 if (vfsDst)
242 lpvn->vfsDst = *vfsDst;
244 lpvn->fl = fl;
245 lpvn->lParam = lParam;
246 lpvn->lpExpandVtbl = lpExpandVtbl;
248 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
250 VCP_Callback(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
251 lpvn->fl |= VFNL_CREATED;
252 VCP_Callback(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);
254 return OK;
257 /***********************************************************************
258 * VcpOpen (SETUPX.200)
260 * Sets up a virtual copy operation.
261 * This means that functions such as GenInstall()
262 * create a VIRTNODE struct for every file to be touched in a .INF file
263 * instead of actually touching the file.
264 * The actual copy/move/rename gets started when VcpClose or
265 * VcpFlush is called; several different callbacks are made
266 * (copy, rename, open, close, version conflicts, ...) on every file copied.
268 RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
270 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
271 if (VCP_opened)
272 return ERR_VCP_BUSY;
274 VCP_Proc = (FARPROC16)vifproc;
275 VCP_MsgRef = lparamMsgRef;
277 VCP_opened = TRUE;
278 return OK;
281 /***********************************************************************
282 * VcpQueueCopy [SETUPX.13]
284 * lpExpandVtbl seems to be deprecated.
285 * fl are the CNFL_xxx and VNFL_xxx flags.
286 * lParam are the VNLP_xxx flags.
288 RETERR16 WINAPI VcpQueueCopy16(
289 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
290 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
291 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
292 LPEXPANDVTBL lpExpandVtbl,
293 WORD fl, LPARAM lParam
296 VCPFILESPEC vfsSrc, vfsDst;
298 if (!VCP_opened)
299 return ERR_VCP_NOTOPEN;
301 TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
302 lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
304 TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
306 vfsSrc.ldid = ldidSrc;
307 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
308 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
310 vfsDst.ldid = ldidDst;
311 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
312 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
314 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
315 lpExpandVtbl);
318 /***********************************************************************
319 * VcpQueueDelete [SETUPX.17]
321 * Is lParamRef the same as lParam in VcpQueueCopy ?
322 * Damn docu !! Err... which docu ?
324 RETERR16 WINAPI VcpQueueDelete16(
325 LPCSTR lpszDstFileName,
326 LPCSTR lpszDstDir,
327 LOGDISKID16 ldidDst,
328 LPARAM lParamRef
331 VCPFILESPEC vfsDst;
333 if (!VCP_opened)
334 return ERR_VCP_NOTOPEN;
336 vfsDst.ldid = ldidDst;
337 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
338 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
340 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
343 /***********************************************************************
344 * VcpQueueRename [SETUPX.204]
347 RETERR16 WINAPI VcpQueueRename16(
348 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
349 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
350 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
351 LPARAM lParam
354 VCPFILESPEC vfsSrc, vfsDst;
356 if (!VCP_opened)
357 return ERR_VCP_NOTOPEN;
359 vfsSrc.ldid = ldidSrc;
360 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
361 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
363 vfsDst.ldid = ldidDst;
364 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
365 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
367 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
371 /***********************************************************************
372 * VcpEnumFiles (SETUPX.@)
374 INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
376 WORD n;
378 for (n = 0; n < vn_last; n++)
379 vep(pvnlist[n], lParamRef);
381 return 0; /* FIXME: return value ? */
384 /***********************************************************************
385 * VcpExplain (SETUPX.411)
387 LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
389 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
390 buffer[0] = '\0';
391 switch (dwWhat)
393 case VCPEX_SRC_FULL:
394 case VCPEX_DST_FULL:
396 LPVCPFILESPEC lpvfs =
397 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
399 /* if we have an ldid, use it, otherwise use the string */
400 /* from the vhstrlist array */
401 if (lpvfs->ldid != 0xffff)
402 CtlGetLddPath16(lpvfs->ldid, buffer);
403 else
404 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
406 strcat(buffer, "\\");
407 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
409 break;
410 default:
411 FIXME("%d unimplemented !\n", dwWhat);
412 strcpy(buffer, "Unknown error");
413 break;
415 return buffer;
418 static RETERR16 VCP_CheckPaths(void)
420 DWORD n;
421 LPVIRTNODE lpvn;
423 VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
424 for (n = 0; n < vn_num; n++)
426 lpvn = pvnlist[n];
427 if (!lpvn) continue;
428 /* FIXME: check paths of all VIRTNODEs here ! */
429 VCP_Callback(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
431 VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
432 return OK;
435 static RETERR16 VCP_CopyFiles(void)
437 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
438 RETERR16 res = OK;
439 DWORD n;
440 LPVIRTNODE lpvn;
442 VCP_Callback(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
443 for (n = 0; n < vn_num; n++)
445 lpvn = pvnlist[n];
446 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
447 /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
448 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
449 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
450 /* FIXME: what is this VCPM_VSTATWRITE here for ?
451 * I guess it's to signal successful destination file creation */
452 VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
454 /* FIXME: need to do the file copy in small chunks for notifications */
455 TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
456 /* perform the file copy */
457 if (!(CopyFileA(fn_src, fn_dst,
458 (lpvn->fl & VNLP_COPYIFEXISTS) ? FALSE : TRUE )))
460 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
461 res = ERR_VCP_IOFAIL;
464 vcp_status.prgFileRead.dwSoFar++;
465 VCP_Callback(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
466 vcp_status.prgFileWrite.dwSoFar++;
467 VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
470 VCP_Callback(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
471 return res;
474 /***********************************************************************
475 * VcpClose (SETUPX.201)
477 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
478 * VCPM_VSTATCLOSEEND.
480 * fl gets VCPFL_xxx flags to indicate what to do with the
481 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
483 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
485 RETERR16 res = OK;
487 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
489 /* FIXME: needs to sort VIRTNODEs in case VCPFL_INSPECIFIEDORDER
490 * is not set. This is done by VCP_Callback(VCPM_NODECOMPARE) */
492 TRACE("#1\n");
493 memset(&vcp_status, 0, sizeof(VCPSTATUS));
494 /* yes, vcp_status.cbSize is 0 ! */
495 TRACE("#2\n");
496 VCP_Callback(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
497 TRACE("#3\n");
499 res = VCP_CheckPaths();
500 TRACE("#4\n");
501 if (res != OK)
502 return res; /* is this ok ? */
503 VCP_CopyFiles();
505 TRACE("#5\n");
506 VCP_Callback(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
507 TRACE("#6\n");
508 VCP_Proc = NULL;
509 VCP_opened = FALSE;
510 return OK;
513 /***********************************************************************
514 * vcpDefCallbackProc (SETUPX.202)
516 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
517 LPARAM lParam, LPARAM lParamRef)
519 static int count = 0;
520 if (count < 10)
521 FIXME("(%p, %04x, %04lx, %08lx, %08lx) - what to do here ?\n",
522 lpvObj, uMsg, wParam, lParam, lParamRef);
523 count++;
524 return OK;
527 /********************* point-and-click stuff from here ***********************/
529 static HWND hDlgCopy = 0;
530 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
531 static char BackupDir[12];
533 static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
535 INT_PTR retval = FALSE;
537 if (iMsg == WM_INITDIALOG)
539 ShowWindow(hWndDlg, SW_SHOWNORMAL);
540 UpdateWindow(hWndDlg);
541 retval = TRUE;
543 return retval;
546 static BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
548 HRSRC hResInfo;
549 HGLOBAL hDlgTmpl32;
551 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), (LPSTR)RT_DIALOG)))
552 return FALSE;
553 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
554 !(*template32 = LockResource( hDlgTmpl32 )))
555 return FALSE;
556 return TRUE;
559 static LRESULT WINAPI
560 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
562 if (uMsg != WM_CREATE)
563 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
565 return 0;
568 static void VCP_UI_RegisterProgressClass(void)
570 static BOOL registered = FALSE;
571 WNDCLASSA wndClass;
573 if (registered)
574 return;
576 registered = TRUE;
577 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
578 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
579 wndClass.lpfnWndProc = VCP_UI_FileCopyWndProc;
580 wndClass.cbClsExtra = 0;
581 wndClass.cbWndExtra = 0;
582 wndClass.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
583 wndClass.hbrBackground = NULL;
584 wndClass.lpszClassName = "setupx_progress";
586 RegisterClassA (&wndClass);
588 SETUPAPI_hInstance = LoadLibraryA( "setupapi.dll" );
591 static RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
593 LPCSTR file1, file2;
594 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
595 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
596 return (RETERR16)strcmp(file1, file2);
599 static RETERR16 VCP_UI_CopyStart(void)
601 LPCVOID template32;
602 char buf[256]; /* plenty */
603 BOOL dirty;
604 DWORD len;
606 /* FIXME: should be registered at DLL startup instead */
607 VCP_UI_RegisterProgressClass();
608 if (!(VCP_UI_GetDialogTemplate(&template32)))
609 return VCPN_FAIL;
611 if (vn_num > 10) /* hack */
613 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
614 VCP_UI_FileCopyDlgProc, 0);
615 if (!hDlgCopy)
616 return VCPN_FAIL;
617 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
618 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
620 strcpy(buf, REG_INSTALLEDFILES);
621 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
622 return VCPN_FAIL;
623 strcat(buf, REGPART_RENAME);
624 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
625 return VCPN_FAIL;
626 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
627 return VCPN_FAIL;
628 len = 1;
629 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
631 /* FIXME: what does SETUPX.DLL do in this case ? */
632 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
633 return VCPN_FAIL;
635 dirty = TRUE;
636 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
637 return VCPN_FAIL;
638 len = 12;
639 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, (LPBYTE)BackupDir, &len)))
640 strcpy(BackupDir, "VCM");
642 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
643 GetWindowsDirectoryA(buf, 256);
644 strcat(buf, "\\");
645 strcat(buf, BackupDir);
646 if (!(CreateDirectoryA(buf, NULL)))
647 return VCPN_FAIL;
648 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
649 return VCPN_FAIL;
650 RegCloseKey(hKeyConflict);
652 return VCPN_OK;
655 /***********************************************************************
656 * vcpUICallbackProc (SETUPX.213)
658 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
659 LPARAM lParam, LPARAM lParamRef)
661 static int count = 0;
662 RETERR16 res = VCPN_OK;
664 if (count < 5)
665 FIXME("(%p, %04x, %04lx, %08lx, %08lx) - semi-stub\n",
666 lpvObj, uMsg, wParam, lParam, lParamRef);
667 count++;
668 switch (uMsg)
670 /* unused messages, it seems */
671 case VCPM_DISKPREPINFO:
673 case VCPM_FILENEEDED:
675 case VCPM_NODECREATE:
676 case VCPM_NODEACCEPT:
678 case VCPM_VSTATCLOSESTART:
679 case VCPM_VSTATPATHCHECKSTART:
680 case VCPM_VSTATPATHCHECKEND:
682 case VCPM_CHECKPATH:
683 break;
685 /* the real stuff */
686 case VCPM_NODECOMPARE:
687 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
688 break;
689 case VCPM_VSTATREAD:
690 break;
691 case VCPM_VSTATWRITE:
692 VCP_Callback(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
693 break;
694 case VCPM_VSTATCLOSEEND:
695 RegCloseKey(hKeyFiles);
696 RegCloseKey(hKeyRename);
697 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
698 break;
699 case VCPM_VSTATCOPYSTART:
700 res = VCP_UI_CopyStart();
701 break;
702 case VCPM_VSTATCOPYEND:
703 if (hDlgCopy) DestroyWindow(hDlgCopy);
704 break;
705 default:
706 FIXME("unhandled msg 0x%04x\n", uMsg);
708 return res;