Fixed some issues found by winapi_check.
[wine/dcerpc.git] / dlls / setupapi / virtcopy.c
blob632b4c4bdf3d21101e4bb892e11176c0a3d3749b
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 /***********************************************************************
56 * vsmStringAdd (SETUPX.207)
58 VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName)
60 VHSTR n;
61 VHSTR index = 0xffff;
62 HANDLE heap;
64 TRACE("add string '%s'\n", lpszName);
65 /* search whether string already inserted */
66 for (n = 0; n < vhstr_alloc; n++)
68 if ((vhstrlist[n]) && (vhstrlist[n]->refcount))
70 TRACE("comp %d\n", n);
71 if (!strcmp(vhstrlist[n]->pStr, lpszName))
73 vhstrlist[n]->refcount++;
74 return n;
79 /* hmm, not found yet, let's insert it */
80 for (n = 0; n < vhstr_alloc; n++)
82 if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount)))
84 index = n;
85 break;
88 heap = GetProcessHeap();
89 if (n == vhstr_alloc) /* hmm, no free index found yet */
91 index = vhstr_alloc;
92 vhstr_alloc += 20;
93 vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
94 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
96 if (index == 0xffff)
97 return 0xffff; /* failure */
98 if (!vhstrlist[index])
99 vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT));
100 vhstrlist[index]->refcount = 1;
101 vhstrlist[index]->pStr = HeapAlloc(heap, 0, strlen(lpszName)+1);
102 strcpy((LPSTR)vhstrlist[index]->pStr, lpszName);
103 return index;
106 /***********************************************************************
107 * vsmStringDelete (SETUPX.206)
109 INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
111 if (VALID_VHSTR(vhstr))
113 vhstrlist[vhstr]->refcount--;
114 if (!vhstrlist[vhstr]->refcount)
116 HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
117 vhstrlist[vhstr]->pStr = NULL;
119 return VCPN_OK;
122 /* string not found */
123 return VCPN_FAIL;
127 * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
129 VHSTR WINAPI vsmStringFind16(LPCSTR lpszName)
131 WORD n;
132 for (n = 0; n < vhstr_alloc; n++)
133 if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName)))
134 return n;
135 return 0xffff;
138 /***********************************************************************
139 * vsmGetStringName (SETUPX.205)
141 * Pretty correct, I guess
143 INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
145 if (VALID_VHSTR(vhstr))
147 int len = strlen(vhstrlist[vhstr]->pStr)+1;
148 if (cbBuffer >= len)
150 if (lpszBuffer)
151 strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
152 return len;
155 return VCPN_FAIL;
158 /***********************************************************************
159 * vsmStringCompare (not exported from a standard SETUPX.DLL, it seems)
161 INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB)
163 if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB)))
164 return VCPN_FAIL; /* correct ? */
165 return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr);
168 /***********************************************************************
169 * vsmGetStringRawName (SETUPX.208)
171 LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
173 return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
177 /***************************** VIRTNODE management ****************************/
178 static LPVIRTNODE *pvnlist = NULL;
179 static DWORD vn_num = 0;
180 static DWORD vn_last = 0;
182 RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
184 HANDLE heap;
185 LPVIRTNODE lpvn;
186 RETERR16 cbres;
188 while (vn_last < vn_num)
190 if (pvnlist[vn_last] == NULL)
191 break;
192 vn_last++;
194 heap = GetProcessHeap();
195 if (vn_last == vn_num)
197 vn_num += 20;
198 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
199 sizeof(LPVIRTNODE *) * vn_num);
201 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
202 lpvn = pvnlist[vn_last];
203 vn_last++;
205 lpvn->cbSize = sizeof(VIRTNODE);
207 if (vfsSrc)
208 memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC));
210 if (vfsDst)
211 memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC));
213 lpvn->fl = fl;
214 lpvn->lParam = lParam;
215 lpvn->lpExpandVtbl = lpExpandVtbl;
217 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
219 cbres = VCP_CALLBACK(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
220 lpvn->fl |= VFNL_CREATED;
221 cbres = VCP_CALLBACK(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);
223 return OK;
226 BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
228 DWORD n;
229 RETERR16 cbres;
231 for (n = 0; n < vn_last; n++)
233 if (pvnlist[n] == lpvnDel)
235 cbres = VCP_CALLBACK(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
236 HeapFree(GetProcessHeap(), 0, lpvnDel);
237 pvnlist[n] = NULL;
238 return TRUE;
241 return FALSE;
244 /***********************************************************************
245 * VcpOpen (SETUPX.200)
247 * Sets up a virtual copy operation.
248 * This means that functions such as GenInstall()
249 * create a VIRTNODE struct for every file to be touched in a .INF file
250 * instead of actually touching the file.
251 * The actual copy/move/rename gets started when VcpClose or
252 * VcpFlush is called; several different callbacks are made
253 * (copy, rename, open, close, version conflicts, ...) on every file copied.
255 RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
257 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
258 if (VCP_opened)
259 return ERR_VCP_BUSY;
261 VCP_Proc = (FARPROC16)vifproc;
262 VCP_MsgRef = lparamMsgRef;
264 /* load SETUPAPI needed for dialog resources etc. */
265 SETUPAPI_hInstance = LoadLibraryA("setupapi.dll");
266 if (!SETUPAPI_hInstance)
268 ERR("Could not load sibling setupapi.dll\n");
269 return ERR_VCP_NOMEM;
271 VCP_opened = TRUE;
272 return OK;
275 /***********************************************************************
276 * VcpQueueCopy [SETUPX.13]
278 * lpExpandVtbl seems to be deprecated.
279 * fl are the CNFL_xxx and VNFL_xxx flags.
280 * lParam are the VNLP_xxx flags.
282 RETERR16 WINAPI VcpQueueCopy16(
283 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
284 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
285 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
286 LPEXPANDVTBL lpExpandVtbl,
287 WORD fl, LPARAM lParam
290 VCPFILESPEC vfsSrc, vfsDst;
292 if (!VCP_opened)
293 return ERR_VCP_NOTOPEN;
295 vfsSrc.ldid = ldidSrc;
296 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
297 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
299 vfsDst.ldid = ldidDst;
300 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
301 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
303 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
304 lpExpandVtbl);
307 /***********************************************************************
308 * VcpQueueDelete [SETUPX.17]
310 * Is lParamRef the same as lParam in VcpQueueCopy ?
311 * Damn docu !! Err... which docu ?
313 RETERR16 WINAPI VcpQueueDelete16(
314 LPCSTR lpszDstFileName,
315 LPCSTR lpszDstDir,
316 LOGDISKID16 ldidDst,
317 LPEXPANDVTBL lpExpandVtbl,
318 LPARAM lParamRef
321 VCPFILESPEC vfsDst;
323 if (!VCP_opened)
324 return ERR_VCP_NOTOPEN;
326 vfsDst.ldid = ldidDst;
327 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
328 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
330 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef,
331 lpExpandVtbl);
334 /***********************************************************************
335 * VcpQueueRename [SETUPX.204]
338 RETERR16 WINAPI VcpQueueRename16(
339 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
340 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
341 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
342 LPARAM lParam
345 VCPFILESPEC vfsSrc, vfsDst;
347 if (!VCP_opened)
348 return ERR_VCP_NOTOPEN;
350 vfsSrc.ldid = ldidSrc;
351 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
352 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
354 vfsDst.ldid = ldidDst;
355 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
356 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
358 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
362 /***********************************************************************
363 * VcpEnumFiles (SETUPX.@)
365 INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
367 WORD n;
369 for (n = 0; n < vn_last; n++)
370 vep(pvnlist[n], lParamRef);
372 return 0; /* FIXME: return value ? */
375 /***********************************************************************
376 * VcpExplain (SETUPX.?)
378 LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
380 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
381 buffer[0] = '\0';
382 switch (dwWhat)
384 case VCPEX_SRC_FULL:
385 case VCPEX_DST_FULL:
387 LPVCPFILESPEC lpvfs =
388 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
390 if (lpvfs->ldid != 0xffff)
391 CtlGetLddPath16(lpvfs->ldid, buffer);
392 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
393 strcat(buffer, "\\");
394 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
396 break;
397 default:
398 FIXME("%ld unimplemented !\n", dwWhat);
399 strcpy(buffer, "Unknown error");
400 break;
402 return buffer;
405 RETERR16 VCP_CheckPaths(void)
407 DWORD n;
408 LPVIRTNODE lpvn;
409 RETERR16 cbres;
411 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
412 for (n = 0; n < vn_num; n++)
414 lpvn = pvnlist[n];
415 if (!lpvn) continue;
416 /* FIXME: check paths of all VIRTNODEs here ! */
417 cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
419 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
420 return OK;
423 RETERR16 VCP_CopyFiles(void)
425 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
426 RETERR16 res = OK, cbres;
427 DWORD n;
428 LPVIRTNODE lpvn;
430 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
431 for (n = 0; n < vn_num; n++)
433 lpvn = pvnlist[n];
434 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
435 /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
436 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
437 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
438 /* FIXME: what is this VCPM_VSTATWRITE here for ?
439 * I guess it's to signal successful destination file creation */
440 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
441 /* FIXME: need to do the file copy in small chunks for notifications */
442 TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
443 #if DO_A_REAL_COPY
444 if (!(CopyFileA(fn_src, fn_dst, TRUE)))
445 res = ERR_VCP_IOFAIL;
446 #endif
447 vcp_status.prgFileRead.dwSoFar++;
448 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
449 vcp_status.prgFileWrite.dwSoFar++;
450 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
453 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
454 return res;
457 /***********************************************************************
458 * VcpFlush - internal (not exported), but documented
460 * VNFL_NOW is used for VcpFlush.
462 RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
464 return OK;
467 /***********************************************************************
468 * VcpClose (SETUPX.201)
470 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
471 * VCPM_VSTATCLOSEEND.
473 * fl gets VCPFL_xxx flags to indicate what to do with the
474 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
476 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
478 RETERR16 res = OK;
479 WORD cbres = VCPN_PROCEED;
481 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
483 /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER
484 * is not set. This is done by VCP_CALLBACK(VCPM_NODECOMPARE) */
486 TRACE("#1\n");
487 memset(&vcp_status, 0, sizeof(VCPSTATUS));
488 /* yes, vcp_status.cbSize is 0 ! */
489 TRACE("#2\n");
490 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
491 TRACE("#3\n");
493 res = VCP_CheckPaths();
494 TRACE("#4\n");
495 if (res != OK)
496 return res; /* is this ok ? */
497 VCP_CopyFiles();
499 TRACE("#5\n");
500 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
501 TRACE("#6\n");
502 VCP_Proc = NULL;
503 FreeLibrary(SETUPAPI_hInstance);
504 VCP_opened = FALSE;
505 return OK;
508 RETERR16 VCP_RenameFiles(void)
510 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
511 RETERR16 res = OK, cbres;
512 DWORD n;
513 LPVIRTNODE lpvn;
515 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
516 for (n = 0; n < vn_num; n++)
518 lpvn = pvnlist[n];
519 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
520 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
521 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
522 cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
523 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
524 res = ERR_VCP_IOFAIL;
525 else
526 VCP_VirtnodeDelete(lpvn);
528 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
529 return res;
532 /***********************************************************************
533 * vcpDefCallbackProc (SETUPX.202)
535 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
536 LPARAM lParam, LPARAM lParamRef)
538 static int count = 0;
539 if (count < 10)
540 FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
541 lpvObj, uMsg, wParam, lParam, lParamRef);
542 count++;
543 return OK;
546 /********************* point-and-click stuff from here ***********************/
548 static HWND hDlgCopy = 0;
549 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
550 static char BackupDir[12];
552 static BOOL CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
554 BOOL retval = FALSE;
556 if (iMsg == WM_INITDIALOG)
558 ShowWindow(hWndDlg, SW_SHOWNORMAL);
559 UpdateWindow(hWndDlg);
560 retval = TRUE;
562 return retval;
565 BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
567 HANDLE hResInfo, hDlgTmpl32;
569 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), RT_DIALOGA)))
570 return FALSE;
571 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
572 !(*template32 = LockResource( hDlgTmpl32 )))
573 return FALSE;
574 return TRUE;
577 static LRESULT WINAPI
578 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
580 if (uMsg != WM_CREATE)
581 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
583 switch (uMsg)
585 case WM_CREATE:
586 return 0;
587 default:
588 FIXME("%04x: unhandled.\n", uMsg);
591 return 0;
594 void VCP_UI_RegisterProgressClass(void)
596 static BOOL registered = FALSE;
597 WNDCLASSA wndClass;
599 if (registered)
600 return;
602 registered = TRUE;
603 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
604 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
605 wndClass.lpfnWndProc = (WNDPROC)VCP_UI_FileCopyWndProc;
606 wndClass.cbClsExtra = 0;
607 wndClass.cbWndExtra = 0;
608 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
609 wndClass.hbrBackground = (HBRUSH)NULL;
610 wndClass.lpszClassName = "setupx_progress";
612 RegisterClassA (&wndClass);
615 RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
617 LPCSTR file1, file2;
618 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
619 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
620 return (RETERR16)strcmp(file1, file2);
623 RETERR16 VCP_UI_CopyStart(void)
625 LPCVOID template32;
626 char buf[256]; /* plenty */
627 BOOL dirty;
628 DWORD len;
630 /* FIXME: should be registered at DLL startup instead */
631 VCP_UI_RegisterProgressClass();
632 if (!(VCP_UI_GetDialogTemplate(&template32)))
633 return VCPN_FAIL;
635 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
636 VCP_UI_FileCopyDlgProc, 0);
637 if (!hDlgCopy)
638 return VCPN_FAIL;
639 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
640 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
641 strcpy(buf, REG_INSTALLEDFILES);
642 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
643 return VCPN_FAIL;
644 strcat(buf, REGPART_RENAME);
645 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
646 return VCPN_FAIL;
647 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
648 return VCPN_FAIL;
649 len = 1;
650 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
652 /* FIXME: what does SETUPX.DLL do in this case ? */
653 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
654 return VCPN_FAIL;
656 dirty = TRUE;
657 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
658 return VCPN_FAIL;
659 len = 12;
660 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len)))
661 strcpy(BackupDir, "VCM");
663 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
664 GetWindowsDirectoryA(buf, 256);
665 strcat(buf, "\\");
666 strcat(buf, BackupDir);
667 if (!(CreateDirectoryA(buf, NULL)))
668 return VCPN_FAIL;
669 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
670 return VCPN_FAIL;
671 RegCloseKey(hKeyConflict);
673 return VCPN_OK;
676 /***********************************************************************
677 * vcpUICallbackProc (SETUPX.213)
679 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
680 LPARAM lParam, LPARAM lParamRef)
682 static int count = 0;
683 RETERR16 res = VCPN_OK, cbres;
685 if (count < 5)
686 FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n",
687 lpvObj, uMsg, wParam, lParam, lParamRef);
688 count++;
689 switch (uMsg)
691 /* unused messages, it seems */
692 case VCPM_DISKPREPINFO:
694 case VCPM_FILENEEDED:
696 case VCPM_NODECREATE:
697 case VCPM_NODEACCEPT:
699 case VCPM_VSTATCLOSESTART:
700 case VCPM_VSTATPATHCHECKSTART:
701 case VCPM_VSTATPATHCHECKEND:
703 case VCPM_CHECKPATH:
704 break;
706 /* the real stuff */
707 case VCPM_NODECOMPARE:
708 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
709 break;
710 case VCPM_VSTATREAD:
711 break;
712 case VCPM_VSTATWRITE:
713 cbres = VCP_CALLBACK(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
714 break;
715 case VCPM_VSTATCLOSEEND:
716 RegCloseKey(hKeyFiles);
717 RegCloseKey(hKeyRename);
718 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
719 break;
720 case VCPM_VSTATCOPYSTART:
721 res = VCP_UI_CopyStart();
722 break;
723 case VCPM_VSTATCOPYEND:
724 DestroyWindow(hDlgCopy);
725 break;
726 default:
727 FIXME("unhandled msg 0x%04x\n", uMsg);
729 return res;