Release 1.6-rc2.
[wine/testsucceed.git] / dlls / setupx.dll16 / virtcopy.c
blobd6bcab6611f0632e9871b1b1a7c5940228f4dac6
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, !(lpvn->fl & VNLP_COPYIFEXISTS)))
459 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
460 res = ERR_VCP_IOFAIL;
463 vcp_status.prgFileRead.dwSoFar++;
464 VCP_Callback(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
465 vcp_status.prgFileWrite.dwSoFar++;
466 VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
469 VCP_Callback(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
470 return res;
473 /***********************************************************************
474 * VcpClose (SETUPX.201)
476 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
477 * VCPM_VSTATCLOSEEND.
479 * fl gets VCPFL_xxx flags to indicate what to do with the
480 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
482 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
484 RETERR16 res = OK;
486 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
488 /* FIXME: needs to sort VIRTNODEs in case VCPFL_INSPECIFIEDORDER
489 * is not set. This is done by VCP_Callback(VCPM_NODECOMPARE) */
491 TRACE("#1\n");
492 memset(&vcp_status, 0, sizeof(VCPSTATUS));
493 /* yes, vcp_status.cbSize is 0 ! */
494 TRACE("#2\n");
495 VCP_Callback(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
496 TRACE("#3\n");
498 res = VCP_CheckPaths();
499 TRACE("#4\n");
500 if (res != OK)
501 return res; /* is this ok ? */
502 VCP_CopyFiles();
504 TRACE("#5\n");
505 VCP_Callback(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
506 TRACE("#6\n");
507 VCP_Proc = NULL;
508 VCP_opened = FALSE;
509 return OK;
512 /***********************************************************************
513 * vcpDefCallbackProc (SETUPX.202)
515 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
516 LPARAM lParam, LPARAM lParamRef)
518 static int count = 0;
519 if (count < 10)
520 FIXME("(%p, %04x, %04lx, %08lx, %08lx) - what to do here ?\n",
521 lpvObj, uMsg, wParam, lParam, lParamRef);
522 count++;
523 return OK;
526 /********************* point-and-click stuff from here ***********************/
528 static HWND hDlgCopy = 0;
529 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
530 static char BackupDir[12];
532 static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
534 INT_PTR retval = FALSE;
536 if (iMsg == WM_INITDIALOG)
538 ShowWindow(hWndDlg, SW_SHOWNORMAL);
539 UpdateWindow(hWndDlg);
540 retval = TRUE;
542 return retval;
545 static BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
547 HRSRC hResInfo;
548 HGLOBAL hDlgTmpl32;
550 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), (LPSTR)RT_DIALOG)))
551 return FALSE;
552 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
553 !(*template32 = LockResource( hDlgTmpl32 )))
554 return FALSE;
555 return TRUE;
558 static LRESULT WINAPI
559 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
561 if (uMsg != WM_CREATE)
562 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
564 return 0;
567 static void VCP_UI_RegisterProgressClass(void)
569 static BOOL registered = FALSE;
570 WNDCLASSA wndClass;
572 if (registered)
573 return;
575 registered = TRUE;
576 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
577 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
578 wndClass.lpfnWndProc = VCP_UI_FileCopyWndProc;
579 wndClass.cbClsExtra = 0;
580 wndClass.cbWndExtra = 0;
581 wndClass.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
582 wndClass.hbrBackground = NULL;
583 wndClass.lpszClassName = "setupx_progress";
585 RegisterClassA (&wndClass);
587 SETUPAPI_hInstance = LoadLibraryA( "setupapi.dll" );
590 static RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
592 LPCSTR file1, file2;
593 int ret;
594 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
595 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
597 ret = strcmp(file1, file2);
598 /* Looks too complicated, but in optimized strcpy we might get
599 * a 32bit wide difference and would truncate it to 16 bit, so
600 * erroneously returning equality. */
601 if (ret < 0) return -1;
602 if (ret > 0) return 1;
603 return 0;
606 static RETERR16 VCP_UI_CopyStart(void)
608 LPCVOID template32;
609 char buf[256]; /* plenty */
610 BOOL dirty;
611 DWORD len;
613 /* FIXME: should be registered at DLL startup instead */
614 VCP_UI_RegisterProgressClass();
615 if (!(VCP_UI_GetDialogTemplate(&template32)))
616 return VCPN_FAIL;
618 if (vn_num > 10) /* hack */
620 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
621 VCP_UI_FileCopyDlgProc, 0);
622 if (!hDlgCopy)
623 return VCPN_FAIL;
624 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
625 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
627 strcpy(buf, REG_INSTALLEDFILES);
628 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
629 return VCPN_FAIL;
630 strcat(buf, REGPART_RENAME);
631 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
632 return VCPN_FAIL;
633 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
634 return VCPN_FAIL;
635 len = 1;
636 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
638 /* FIXME: what does SETUPX.DLL do in this case ? */
639 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
640 return VCPN_FAIL;
642 dirty = TRUE;
643 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
644 return VCPN_FAIL;
645 len = 12;
646 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, (LPBYTE)BackupDir, &len)))
647 strcpy(BackupDir, "VCM");
649 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
650 GetWindowsDirectoryA(buf, 256);
651 strcat(buf, "\\");
652 strcat(buf, BackupDir);
653 if (!(CreateDirectoryA(buf, NULL)))
654 return VCPN_FAIL;
655 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
656 return VCPN_FAIL;
657 RegCloseKey(hKeyConflict);
659 return VCPN_OK;
662 /***********************************************************************
663 * vcpUICallbackProc (SETUPX.213)
665 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
666 LPARAM lParam, LPARAM lParamRef)
668 static int count = 0;
669 RETERR16 res = VCPN_OK;
671 if (count < 5)
672 FIXME("(%p, %04x, %04lx, %08lx, %08lx) - semi-stub\n",
673 lpvObj, uMsg, wParam, lParam, lParamRef);
674 count++;
675 switch (uMsg)
677 /* unused messages, it seems */
678 case VCPM_DISKPREPINFO:
680 case VCPM_FILENEEDED:
682 case VCPM_NODECREATE:
683 case VCPM_NODEACCEPT:
685 case VCPM_VSTATCLOSESTART:
686 case VCPM_VSTATPATHCHECKSTART:
687 case VCPM_VSTATPATHCHECKEND:
689 case VCPM_CHECKPATH:
690 break;
692 /* the real stuff */
693 case VCPM_NODECOMPARE:
694 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
695 break;
696 case VCPM_VSTATREAD:
697 break;
698 case VCPM_VSTATWRITE:
699 VCP_Callback(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
700 break;
701 case VCPM_VSTATCLOSEEND:
702 RegCloseKey(hKeyFiles);
703 RegCloseKey(hKeyRename);
704 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
705 break;
706 case VCPM_VSTATCOPYSTART:
707 res = VCP_UI_CopyStart();
708 break;
709 case VCPM_VSTATCOPYEND:
710 if (hDlgCopy) DestroyWindow(hDlgCopy);
711 break;
712 default:
713 FIXME("unhandled msg 0x%04x\n", uMsg);
715 return res;