include: Fix typo in shlwapi.h.
[wine.git] / dlls / setupx.dll16 / virtcopy.c
bloba15f1a1d2b183d7c4324e6bdf4f7c2a9a39aa990
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;
214 RETERR16 cbres;
216 while (vn_last < vn_num)
218 if (pvnlist[vn_last] == NULL)
219 break;
220 vn_last++;
222 heap = GetProcessHeap();
223 if (vn_last == vn_num)
225 vn_num += 20;
226 if (pvnlist)
227 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
228 sizeof(LPVIRTNODE *) * vn_num);
229 else
230 pvnlist = HeapAlloc(heap, HEAP_ZERO_MEMORY,
231 sizeof(LPVIRTNODE *) * vn_num);
233 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
234 lpvn = pvnlist[vn_last];
235 vn_last++;
237 lpvn->cbSize = sizeof(VIRTNODE);
239 if (vfsSrc)
240 lpvn->vfsSrc = *vfsSrc;
242 if (vfsDst)
243 lpvn->vfsDst = *vfsDst;
245 lpvn->fl = fl;
246 lpvn->lParam = lParam;
247 lpvn->lpExpandVtbl = lpExpandVtbl;
249 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
251 cbres = VCP_Callback(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
252 lpvn->fl |= VFNL_CREATED;
253 cbres = VCP_Callback(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);
255 return OK;
258 /***********************************************************************
259 * VcpOpen (SETUPX.200)
261 * Sets up a virtual copy operation.
262 * This means that functions such as GenInstall()
263 * create a VIRTNODE struct for every file to be touched in a .INF file
264 * instead of actually touching the file.
265 * The actual copy/move/rename gets started when VcpClose or
266 * VcpFlush is called; several different callbacks are made
267 * (copy, rename, open, close, version conflicts, ...) on every file copied.
269 RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
271 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
272 if (VCP_opened)
273 return ERR_VCP_BUSY;
275 VCP_Proc = (FARPROC16)vifproc;
276 VCP_MsgRef = lparamMsgRef;
278 VCP_opened = TRUE;
279 return OK;
282 /***********************************************************************
283 * VcpQueueCopy [SETUPX.13]
285 * lpExpandVtbl seems to be deprecated.
286 * fl are the CNFL_xxx and VNFL_xxx flags.
287 * lParam are the VNLP_xxx flags.
289 RETERR16 WINAPI VcpQueueCopy16(
290 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
291 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
292 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
293 LPEXPANDVTBL lpExpandVtbl,
294 WORD fl, LPARAM lParam
297 VCPFILESPEC vfsSrc, vfsDst;
299 if (!VCP_opened)
300 return ERR_VCP_NOTOPEN;
302 TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
303 lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
305 TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
307 vfsSrc.ldid = ldidSrc;
308 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
309 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
311 vfsDst.ldid = ldidDst;
312 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
313 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
315 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
316 lpExpandVtbl);
319 /***********************************************************************
320 * VcpQueueDelete [SETUPX.17]
322 * Is lParamRef the same as lParam in VcpQueueCopy ?
323 * Damn docu !! Err... which docu ?
325 RETERR16 WINAPI VcpQueueDelete16(
326 LPCSTR lpszDstFileName,
327 LPCSTR lpszDstDir,
328 LOGDISKID16 ldidDst,
329 LPARAM lParamRef
332 VCPFILESPEC vfsDst;
334 if (!VCP_opened)
335 return ERR_VCP_NOTOPEN;
337 vfsDst.ldid = ldidDst;
338 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
339 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
341 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
344 /***********************************************************************
345 * VcpQueueRename [SETUPX.204]
348 RETERR16 WINAPI VcpQueueRename16(
349 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
350 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
351 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
352 LPARAM lParam
355 VCPFILESPEC vfsSrc, vfsDst;
357 if (!VCP_opened)
358 return ERR_VCP_NOTOPEN;
360 vfsSrc.ldid = ldidSrc;
361 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
362 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
364 vfsDst.ldid = ldidDst;
365 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
366 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
368 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
372 /***********************************************************************
373 * VcpEnumFiles (SETUPX.@)
375 INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
377 WORD n;
379 for (n = 0; n < vn_last; n++)
380 vep(pvnlist[n], lParamRef);
382 return 0; /* FIXME: return value ? */
385 /***********************************************************************
386 * VcpExplain (SETUPX.411)
388 LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
390 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
391 buffer[0] = '\0';
392 switch (dwWhat)
394 case VCPEX_SRC_FULL:
395 case VCPEX_DST_FULL:
397 LPVCPFILESPEC lpvfs =
398 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
400 /* if we have an ldid, use it, otherwise use the string */
401 /* from the vhstrlist array */
402 if (lpvfs->ldid != 0xffff)
403 CtlGetLddPath16(lpvfs->ldid, buffer);
404 else
405 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
407 strcat(buffer, "\\");
408 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
410 break;
411 default:
412 FIXME("%d unimplemented !\n", dwWhat);
413 strcpy(buffer, "Unknown error");
414 break;
416 return buffer;
419 static RETERR16 VCP_CheckPaths(void)
421 DWORD n;
422 LPVIRTNODE lpvn;
423 RETERR16 cbres;
425 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
426 for (n = 0; n < vn_num; n++)
428 lpvn = pvnlist[n];
429 if (!lpvn) continue;
430 /* FIXME: check paths of all VIRTNODEs here ! */
431 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
433 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
434 return OK;
437 static RETERR16 VCP_CopyFiles(void)
439 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
440 RETERR16 res = OK, cbres;
441 DWORD n;
442 LPVIRTNODE lpvn;
444 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
445 for (n = 0; n < vn_num; n++)
447 lpvn = pvnlist[n];
448 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
449 /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
450 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
451 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
452 /* FIXME: what is this VCPM_VSTATWRITE here for ?
453 * I guess it's to signal successful destination file creation */
454 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
456 /* FIXME: need to do the file copy in small chunks for notifications */
457 TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
458 /* perform the file copy */
459 if (!(CopyFileA(fn_src, fn_dst,
460 (lpvn->fl & VNLP_COPYIFEXISTS) ? FALSE : TRUE )))
462 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
463 res = ERR_VCP_IOFAIL;
466 vcp_status.prgFileRead.dwSoFar++;
467 cbres = VCP_Callback(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
468 vcp_status.prgFileWrite.dwSoFar++;
469 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
472 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
473 return res;
476 /***********************************************************************
477 * VcpClose (SETUPX.201)
479 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
480 * VCPM_VSTATCLOSEEND.
482 * fl gets VCPFL_xxx flags to indicate what to do with the
483 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
485 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
487 RETERR16 res = OK;
488 WORD cbres = VCPN_PROCEED;
490 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
492 /* FIXME: needs to sort VIRTNODEs in case VCPFL_INSPECIFIEDORDER
493 * is not set. This is done by VCP_Callback(VCPM_NODECOMPARE) */
495 TRACE("#1\n");
496 memset(&vcp_status, 0, sizeof(VCPSTATUS));
497 /* yes, vcp_status.cbSize is 0 ! */
498 TRACE("#2\n");
499 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
500 TRACE("#3\n");
502 res = VCP_CheckPaths();
503 TRACE("#4\n");
504 if (res != OK)
505 return res; /* is this ok ? */
506 VCP_CopyFiles();
508 TRACE("#5\n");
509 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
510 TRACE("#6\n");
511 VCP_Proc = NULL;
512 VCP_opened = FALSE;
513 return OK;
516 /***********************************************************************
517 * vcpDefCallbackProc (SETUPX.202)
519 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
520 LPARAM lParam, LPARAM lParamRef)
522 static int count = 0;
523 if (count < 10)
524 FIXME("(%p, %04x, %04lx, %08lx, %08lx) - what to do here ?\n",
525 lpvObj, uMsg, wParam, lParam, lParamRef);
526 count++;
527 return OK;
530 /********************* point-and-click stuff from here ***********************/
532 static HWND hDlgCopy = 0;
533 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
534 static char BackupDir[12];
536 static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
538 INT_PTR retval = FALSE;
540 if (iMsg == WM_INITDIALOG)
542 ShowWindow(hWndDlg, SW_SHOWNORMAL);
543 UpdateWindow(hWndDlg);
544 retval = TRUE;
546 return retval;
549 static BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
551 HRSRC hResInfo;
552 HGLOBAL hDlgTmpl32;
554 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), (LPSTR)RT_DIALOG)))
555 return FALSE;
556 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
557 !(*template32 = LockResource( hDlgTmpl32 )))
558 return FALSE;
559 return TRUE;
562 static LRESULT WINAPI
563 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
565 if (uMsg != WM_CREATE)
566 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
568 switch (uMsg)
570 case WM_CREATE:
571 return 0;
572 default:
573 FIXME("%04x: unhandled.\n", uMsg);
576 return 0;
579 static void VCP_UI_RegisterProgressClass(void)
581 static BOOL registered = FALSE;
582 WNDCLASSA wndClass;
584 if (registered)
585 return;
587 registered = TRUE;
588 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
589 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
590 wndClass.lpfnWndProc = VCP_UI_FileCopyWndProc;
591 wndClass.cbClsExtra = 0;
592 wndClass.cbWndExtra = 0;
593 wndClass.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
594 wndClass.hbrBackground = NULL;
595 wndClass.lpszClassName = "setupx_progress";
597 RegisterClassA (&wndClass);
599 SETUPAPI_hInstance = LoadLibraryA( "setupapi.dll" );
602 static RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
604 LPCSTR file1, file2;
605 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
606 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
607 return (RETERR16)strcmp(file1, file2);
610 static RETERR16 VCP_UI_CopyStart(void)
612 LPCVOID template32;
613 char buf[256]; /* plenty */
614 BOOL dirty;
615 DWORD len;
617 /* FIXME: should be registered at DLL startup instead */
618 VCP_UI_RegisterProgressClass();
619 if (!(VCP_UI_GetDialogTemplate(&template32)))
620 return VCPN_FAIL;
622 if (vn_num > 10) /* hack */
624 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
625 VCP_UI_FileCopyDlgProc, 0);
626 if (!hDlgCopy)
627 return VCPN_FAIL;
628 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
629 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
631 strcpy(buf, REG_INSTALLEDFILES);
632 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
633 return VCPN_FAIL;
634 strcat(buf, REGPART_RENAME);
635 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
636 return VCPN_FAIL;
637 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
638 return VCPN_FAIL;
639 len = 1;
640 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
642 /* FIXME: what does SETUPX.DLL do in this case ? */
643 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
644 return VCPN_FAIL;
646 dirty = TRUE;
647 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
648 return VCPN_FAIL;
649 len = 12;
650 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, (LPBYTE)BackupDir, &len)))
651 strcpy(BackupDir, "VCM");
653 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
654 GetWindowsDirectoryA(buf, 256);
655 strcat(buf, "\\");
656 strcat(buf, BackupDir);
657 if (!(CreateDirectoryA(buf, NULL)))
658 return VCPN_FAIL;
659 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
660 return VCPN_FAIL;
661 RegCloseKey(hKeyConflict);
663 return VCPN_OK;
666 /***********************************************************************
667 * vcpUICallbackProc (SETUPX.213)
669 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
670 LPARAM lParam, LPARAM lParamRef)
672 static int count = 0;
673 RETERR16 res = VCPN_OK, cbres;
675 if (count < 5)
676 FIXME("(%p, %04x, %04lx, %08lx, %08lx) - semi-stub\n",
677 lpvObj, uMsg, wParam, lParam, lParamRef);
678 count++;
679 switch (uMsg)
681 /* unused messages, it seems */
682 case VCPM_DISKPREPINFO:
684 case VCPM_FILENEEDED:
686 case VCPM_NODECREATE:
687 case VCPM_NODEACCEPT:
689 case VCPM_VSTATCLOSESTART:
690 case VCPM_VSTATPATHCHECKSTART:
691 case VCPM_VSTATPATHCHECKEND:
693 case VCPM_CHECKPATH:
694 break;
696 /* the real stuff */
697 case VCPM_NODECOMPARE:
698 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
699 break;
700 case VCPM_VSTATREAD:
701 break;
702 case VCPM_VSTATWRITE:
703 cbres = VCP_Callback(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
704 break;
705 case VCPM_VSTATCLOSEEND:
706 RegCloseKey(hKeyFiles);
707 RegCloseKey(hKeyRename);
708 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
709 break;
710 case VCPM_VSTATCOPYSTART:
711 res = VCP_UI_CopyStart();
712 break;
713 case VCPM_VSTATCOPYEND:
714 if (hDlgCopy) DestroyWindow(hDlgCopy);
715 break;
716 default:
717 FIXME("unhandled msg 0x%04x\n", uMsg);
719 return res;