- implement some more virtcopy (VCP) stuff
[wine.git] / dlls / setupapi / virtcopy.c
blob3cd7459c68797c717ca2fe945349896b4a1b7de4
1 /*
2 * SetupAPI virtual copy operations
4 * FIXME: we now rely on builtin setupapi.dll for dialog resources.
5 * This is bad ! We ought to have 16bit resource handling working.
6 */
8 #include <string.h>
9 #include "debugtools.h"
10 #include "windef.h"
11 #include "setupx16.h"
12 #include "heap.h"
13 #include "callback.h"
14 #include "stackframe.h"
15 #include "winreg.h"
16 #include "setupapi_private.h"
18 DEFAULT_DEBUG_CHANNEL(setupapi);
20 /* ### start build ### */
21 extern WORD CALLBACK VCP_CallTo16_word_lwwll(FARPROC16,LPVOID,UINT16,WPARAM,LPARAM,LPARAM);
22 /* ### stop build ### */
24 static FARPROC16 VCP_Proc = NULL;
25 static LPARAM VCP_MsgRef = 0;
27 #define VCP_CALLBACK(obj,msg,wParam,lParam,lParamRef) \
28 (VCP_Proc) ? \
29 VCP_CallTo16_word_lwwll(VCP_Proc, obj,msg,wParam,lParam,lParamRef) : OK;
31 static BOOL VCP_opened = FALSE;
33 static VCPSTATUS vcp_status;
35 static HINSTANCE SETUPAPI_hInstance;
37 /****************************** VHSTR management ******************************/
40 * This is a totally braindead implementation for now;
41 * I don't care about speed at all ! Size and implementation time
42 * is much more important IMHO. I could have created some sophisticated
43 * tree structure, but... what the hell ! :-)
45 typedef struct {
46 DWORD refcount;
47 LPCSTR pStr;
48 } VHSTR_STRUCT;
50 static VHSTR_STRUCT **vhstrlist = NULL;
51 static VHSTR vhstr_alloc = 0;
53 #define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount))
55 VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName)
57 VHSTR n;
58 VHSTR index = 0xffff;
59 HANDLE heap;
61 TRACE("add string '%s'\n", lpszName);
62 /* search whether string already inserted */
63 for (n = 0; n < vhstr_alloc; n++)
65 if ((vhstrlist[n]) && (vhstrlist[n]->refcount))
67 TRACE("comp %d\n", n);
68 if (!strcmp(vhstrlist[n]->pStr, lpszName))
70 vhstrlist[n]->refcount++;
71 return n;
76 /* hmm, not found yet, let's insert it */
77 for (n = 0; n < vhstr_alloc; n++)
79 if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount)))
81 index = n;
82 break;
85 heap = GetProcessHeap();
86 if (n == vhstr_alloc) /* hmm, no free index found yet */
88 index = vhstr_alloc;
89 vhstr_alloc += 20;
90 vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
91 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
93 if (index == 0xffff)
94 return 0xffff; /* failure */
95 if (!vhstrlist[index])
96 vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT));
97 vhstrlist[index]->refcount = 1;
98 vhstrlist[index]->pStr = HeapAlloc(heap, 0, strlen(lpszName)+1);
99 strcpy((LPSTR)vhstrlist[index]->pStr, lpszName);
100 return index;
103 INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
105 if (VALID_VHSTR(vhstr))
107 vhstrlist[vhstr]->refcount--;
108 if (!vhstrlist[vhstr]->refcount)
110 HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
111 vhstrlist[vhstr]->pStr = NULL;
113 return VCPN_OK;
116 /* string not found */
117 return VCPN_FAIL;
121 * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
123 VHSTR WINAPI vsmStringFind16(LPCSTR lpszName)
125 WORD n;
126 for (n = 0; n < vhstr_alloc; n++)
127 if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName)))
128 return n;
129 return 0xffff;
133 * vsmGetStringName()
135 * Pretty correct, I guess
137 INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
139 if (VALID_VHSTR(vhstr))
141 int len = strlen(vhstrlist[vhstr]->pStr)+1;
142 if (cbBuffer >= len)
144 if (lpszBuffer)
145 strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
146 return len;
149 return VCPN_FAIL;
153 * vsmStringCompare() - not exported from a standard SETUPX.DLL, it seems
155 INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB)
157 if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB)))
158 return VCPN_FAIL; /* correct ? */
159 return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr);
162 LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
164 return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
168 /***************************** VIRTNODE management ****************************/
169 static LPVIRTNODE *pvnlist = NULL;
170 static DWORD vn_num = 0;
171 static DWORD vn_last = 0;
173 RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
175 HANDLE heap;
176 LPVIRTNODE lpvn;
177 RETERR16 cbres;
179 while (vn_last < vn_num)
181 if (pvnlist[vn_last] == NULL)
182 break;
183 vn_last++;
185 heap = GetProcessHeap();
186 if (vn_last == vn_num)
188 vn_num += 20;
189 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
190 sizeof(LPVIRTNODE *) * vn_num);
192 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
193 lpvn = pvnlist[vn_last];
194 vn_last++;
196 lpvn->cbSize = sizeof(VIRTNODE);
198 if (vfsSrc)
199 memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC));
201 if (vfsDst)
202 memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC));
204 lpvn->fl = fl;
205 lpvn->lParam = lParam;
206 lpvn->lpExpandVtbl = lpExpandVtbl;
208 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
210 cbres = VCP_CALLBACK(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
211 lpvn->fl |= VFNL_CREATED;
212 cbres = VCP_CALLBACK(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);
214 return OK;
217 BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
219 DWORD n;
220 RETERR16 cbres;
222 for (n = 0; n < vn_last; n++)
224 if (pvnlist[n] == lpvnDel)
226 cbres = VCP_CALLBACK(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
227 HeapFree(GetProcessHeap(), 0, lpvnDel);
228 pvnlist[n] = NULL;
229 return TRUE;
232 return FALSE;
235 /***********************************************************************
236 * VcpOpen
238 * Sets up a virtual copy operation.
239 * This means that functions such as GenInstall()
240 * create a VIRTNODE struct for every file to be touched in a .INF file
241 * instead of actually touching the file.
242 * The actual copy/move/rename gets started when VcpClose or
243 * VcpFlush is called; several different callbacks are made
244 * (copy, rename, open, close, version conflicts, ...) on every file copied.
246 RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
248 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
249 if (VCP_opened)
250 return ERR_VCP_BUSY;
252 VCP_Proc = (FARPROC16)vifproc;
253 VCP_MsgRef = lparamMsgRef;
255 /* load SETUPAPI needed for dialog resources etc. */
256 SETUPAPI_hInstance = LoadLibraryA("setupapi.dll");
257 if (!SETUPAPI_hInstance)
259 ERR("Could not load sibling setupapi.dll\n");
260 return ERR_VCP_NOMEM;
262 VCP_opened = TRUE;
263 return OK;
266 /***********************************************************************
267 * VcpQueueCopy [SETUPX.13]
269 * lpExpandVtbl seems to be deprecated.
270 * fl are the CNFL_xxx and VNFL_xxx flags.
271 * lParam are the VNLP_xxx flags.
273 RETERR16 WINAPI VcpQueueCopy16(
274 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
275 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
276 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
277 LPEXPANDVTBL lpExpandVtbl,
278 WORD fl, LPARAM lParam
281 VCPFILESPEC vfsSrc, vfsDst;
283 if (!VCP_opened)
284 return ERR_VCP_NOTOPEN;
286 vfsSrc.ldid = ldidSrc;
287 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
288 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
290 vfsDst.ldid = ldidDst;
291 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
292 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
294 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
295 lpExpandVtbl);
298 /***********************************************************************
299 * VcpQueueDelete [SETUPX.17]
301 * Is lParamRef the same as lParam in VcpQueueCopy ?
302 * Damn docu !! Err... which docu ?
304 RETERR16 WINAPI VcpQueueDelete16(
305 LPCSTR lpszDstFileName,
306 LPCSTR lpszDstDir,
307 LOGDISKID16 ldidDst,
308 LPEXPANDVTBL lpExpandVtbl,
309 LPARAM lParamRef
312 VCPFILESPEC vfsDst;
314 if (!VCP_opened)
315 return ERR_VCP_NOTOPEN;
317 vfsDst.ldid = ldidDst;
318 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
319 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
321 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef,
322 lpExpandVtbl);
325 /***********************************************************************
326 * VcpQueueRename [SETUPX.204]
329 RETERR16 WINAPI VcpQueueRename16(
330 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
331 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
332 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
333 LPARAM lParam
336 VCPFILESPEC vfsSrc, vfsDst;
338 if (!VCP_opened)
339 return ERR_VCP_NOTOPEN;
341 vfsSrc.ldid = ldidSrc;
342 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
343 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
345 vfsDst.ldid = ldidDst;
346 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
347 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
349 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
353 INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
355 WORD n;
357 for (n = 0; n < vn_last; n++)
358 vep(pvnlist[n], lParamRef);
360 return 0; /* FIXME: return value ? */
363 LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
365 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
366 buffer[0] = '\0';
367 switch (dwWhat)
369 case VCPEX_SRC_FULL:
370 case VCPEX_DST_FULL:
372 LPVCPFILESPEC lpvfs =
373 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
375 if (lpvfs->ldid != 0xffff)
376 CtlGetLddPath16(lpvfs->ldid, buffer);
377 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
378 strcat(buffer, "\\");
379 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
381 break;
382 default:
383 FIXME("%ld unimplemented !\n", dwWhat);
384 strcpy(buffer, "Unknown error");
385 break;
387 return buffer;
390 RETERR16 VCP_CheckPaths(void)
392 DWORD n;
393 LPVIRTNODE lpvn;
394 RETERR16 cbres;
396 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
397 for (n = 0; n < vn_num; n++)
399 lpvn = pvnlist[n];
400 if (!lpvn) continue;
401 /* FIXME: check paths of all VIRTNODEs here ! */
402 cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
404 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
405 return OK;
408 RETERR16 VCP_CopyFiles(void)
410 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
411 RETERR16 res = OK, cbres;
412 DWORD n;
413 LPVIRTNODE lpvn;
415 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
416 for (n = 0; n < vn_num; n++)
418 lpvn = pvnlist[n];
419 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
420 /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
421 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
422 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
423 /* FIXME: what is this VCPM_VSTATWRITE here for ?
424 * I guess it's to signal successful destination file creation */
425 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
426 /* FIXME: need to do the file copy in small chunks for notifications */
427 TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
428 #if DO_A_REAL_COPY
429 if (!(CopyFileA(fn_src, fn_dst, TRUE)))
430 res = ERR_VCP_IOFAIL;
431 #endif
432 vcp_status.prgFileRead.dwSoFar++;
433 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
434 vcp_status.prgFileWrite.dwSoFar++;
435 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
438 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
439 return res;
442 /***********************************************************************
443 * VcpFlush - internal (not exported), but documented
445 * VNFL_NOW is used for VcpFlush.
447 RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
449 return OK;
452 /***********************************************************************
453 * VcpClose
455 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
456 * VCPM_VSTATCLOSEEND.
458 * fl gets VCPFL_xxx flags to indicate what to do with the
459 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
461 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
463 RETERR16 res = OK;
464 WORD cbres = VCPN_PROCEED;
466 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
468 /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER
469 * is not set. This is done by VCP_CALLBACK(VCPM_NODECOMPARE) */
471 TRACE("#1\n");
472 memset(&vcp_status, 0, sizeof(VCPSTATUS));
473 /* yes, vcp_status.cbSize is 0 ! */
474 TRACE("#2\n");
475 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
476 TRACE("#3\n");
478 res = VCP_CheckPaths();
479 TRACE("#4\n");
480 if (res != OK)
481 return res; /* is this ok ? */
482 VCP_CopyFiles();
484 TRACE("#5\n");
485 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
486 TRACE("#6\n");
487 VCP_Proc = NULL;
488 FreeLibrary(SETUPAPI_hInstance);
489 VCP_opened = FALSE;
490 return OK;
493 RETERR16 VCP_RenameFiles(void)
495 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
496 RETERR16 res = OK, cbres;
497 DWORD n;
498 LPVIRTNODE lpvn;
500 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
501 for (n = 0; n < vn_num; n++)
503 lpvn = pvnlist[n];
504 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
505 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
506 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
507 cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
508 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
509 res = ERR_VCP_IOFAIL;
510 else
511 VCP_VirtnodeDelete(lpvn);
513 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
514 return res;
517 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
518 LPARAM lParam, LPARAM lParamRef)
520 static int count = 0;
521 if (count < 10)
522 FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
523 lpvObj, uMsg, wParam, lParam, lParamRef);
524 count++;
525 return OK;
528 /********************* point-and-click stuff from here ***********************/
530 static HWND hDlgCopy = 0;
531 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
532 static char BackupDir[12];
534 static BOOL CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
536 BOOL retval = FALSE;
538 if (iMsg == WM_INITDIALOG)
540 ShowWindow(hWndDlg, SW_SHOWNORMAL);
541 UpdateWindow(hWndDlg);
542 retval = TRUE;
544 return retval;
547 BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
549 HANDLE hResInfo, hDlgTmpl32;
551 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), RT_DIALOGA)))
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 switch (uMsg)
567 case WM_CREATE:
568 return 0;
569 default:
570 FIXME("%04x: unhandled.\n", uMsg);
573 return 0;
576 void VCP_UI_RegisterProgressClass(void)
578 static BOOL registered = FALSE;
579 WNDCLASSA wndClass;
581 if (registered)
582 return;
584 registered = TRUE;
585 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
586 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
587 wndClass.lpfnWndProc = (WNDPROC)VCP_UI_FileCopyWndProc;
588 wndClass.cbClsExtra = 0;
589 wndClass.cbWndExtra = 0;
590 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
591 wndClass.hbrBackground = (HBRUSH)NULL;
592 wndClass.lpszClassName = "setupx_progress";
594 RegisterClassA (&wndClass);
597 RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
599 LPCSTR file1, file2;
600 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
601 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
602 return (RETERR16)strcmp(file1, file2);
605 RETERR16 VCP_UI_CopyStart(void)
607 LPCVOID template32;
608 char buf[256]; /* plenty */
609 BOOL dirty;
610 DWORD len;
612 /* FIXME: should be registered at DLL startup instead */
613 VCP_UI_RegisterProgressClass();
614 if (!(VCP_UI_GetDialogTemplate(&template32)))
615 return VCPN_FAIL;
617 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
618 VCP_UI_FileCopyDlgProc, 0);
619 if (!hDlgCopy)
620 return VCPN_FAIL;
621 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
622 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
623 strcpy(buf, REG_INSTALLEDFILES);
624 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
625 return VCPN_FAIL;
626 strcat(buf, REGPART_RENAME);
627 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
628 return VCPN_FAIL;
629 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
630 return VCPN_FAIL;
631 len = 1;
632 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
634 /* FIXME: what does SETUPX.DLL do in this case ? */
635 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
636 return VCPN_FAIL;
638 dirty = TRUE;
639 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
640 return VCPN_FAIL;
641 len = 12;
642 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len)))
643 strcpy(BackupDir, "VCM");
645 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
646 GetWindowsDirectoryA(buf, 256);
647 strcat(buf, "\\");
648 strcat(buf, BackupDir);
649 if (!(CreateDirectoryA(buf, NULL)))
650 return VCPN_FAIL;
651 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
652 return VCPN_FAIL;
653 RegCloseKey(hKeyConflict);
655 return VCPN_OK;
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, cbres;
664 if (count < 5)
665 FIXME("(%p, %04x, %04x, %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 cbres = 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 DestroyWindow(hDlgCopy);
704 break;
705 default:
706 FIXME("unhandled msg 0x%04x\n", uMsg);
708 return res;