Removed trailing whitespace.
[wine/wine-gecko.git] / dlls / setupapi / virtcopy.c
blob597ae10f4063e7d54de7e1594985f297b936de72
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 <string.h>
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "winreg.h"
28 #include "setupapi.h"
29 #include "setupx16.h"
30 #include "setupapi_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
35 /* ### start build ### */
36 extern WORD CALLBACK VCP_CallTo16_word_lwwll(FARPROC16,LPVOID,UINT16,WPARAM,LPARAM,LPARAM);
37 /* ### stop build ### */
39 static FARPROC16 VCP_Proc = NULL;
40 static LPARAM VCP_MsgRef = 0;
42 #define VCP_CALLBACK(obj,msg,wParam,lParam,lParamRef) \
43 (VCP_Proc) ? \
44 VCP_CallTo16_word_lwwll(VCP_Proc, obj,msg,wParam,lParam,lParamRef) : OK;
46 static BOOL VCP_opened = FALSE;
48 static VCPSTATUS vcp_status;
50 static HINSTANCE SETUPAPI_hInstance;
52 /****************************** VHSTR management ******************************/
55 * This is a totally braindead implementation for now;
56 * I don't care about speed at all ! Size and implementation time
57 * is much more important IMHO. I could have created some sophisticated
58 * tree structure, but... what the hell ! :-)
60 typedef struct {
61 DWORD refcount;
62 LPCSTR pStr;
63 } VHSTR_STRUCT;
65 static VHSTR_STRUCT **vhstrlist = NULL;
66 static VHSTR vhstr_alloc = 0;
68 #define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount))
70 /***********************************************************************
71 * vsmStringAdd (SETUPX.207)
73 VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName)
75 VHSTR n;
76 VHSTR index = 0xffff;
77 HANDLE heap;
79 TRACE("add string '%s'\n", lpszName);
80 /* search whether string already inserted */
81 TRACE("searching for existing string...\n");
82 for (n = 0; n < vhstr_alloc; n++)
84 if ((vhstrlist[n]) && (vhstrlist[n]->refcount))
86 TRACE("checking item: %d\n", n);
87 if (!strcmp(vhstrlist[n]->pStr, lpszName))
89 TRACE("found\n");
90 vhstrlist[n]->refcount++;
91 return n;
96 /* hmm, not found yet, let's insert it */
97 TRACE("inserting item\n");
98 for (n = 0; n < vhstr_alloc; n++)
100 if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount)))
102 index = n;
103 break;
106 heap = GetProcessHeap();
107 if (n == vhstr_alloc) /* hmm, no free index found yet */
109 index = vhstr_alloc;
110 vhstr_alloc += 20;
111 vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
112 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
114 if (index == 0xffff)
115 return 0xffff; /* failure */
116 if (!vhstrlist[index])
117 vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT));
118 vhstrlist[index]->refcount = 1;
119 vhstrlist[index]->pStr = HeapAlloc(heap, 0, strlen(lpszName)+1);
120 strcpy((LPSTR)vhstrlist[index]->pStr, lpszName);
121 return index;
124 /***********************************************************************
125 * vsmStringDelete (SETUPX.206)
127 INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
129 if (VALID_VHSTR(vhstr))
131 vhstrlist[vhstr]->refcount--;
132 if (!vhstrlist[vhstr]->refcount)
134 HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
135 vhstrlist[vhstr]->pStr = NULL;
137 return VCPN_OK;
140 /* string not found */
141 return VCPN_FAIL;
145 * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
147 VHSTR WINAPI vsmStringFind16(LPCSTR lpszName)
149 WORD n;
150 for (n = 0; n < vhstr_alloc; n++)
151 if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName)))
152 return n;
153 return 0xffff;
156 /***********************************************************************
157 * vsmGetStringName (SETUPX.205)
159 * Pretty correct, I guess
161 INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
163 if (VALID_VHSTR(vhstr))
165 int len = strlen(vhstrlist[vhstr]->pStr)+1;
166 if (cbBuffer >= len)
168 if (lpszBuffer)
169 strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
170 return len;
173 return VCPN_FAIL;
176 /***********************************************************************
177 * vsmStringCompare (not exported from a standard SETUPX.DLL, it seems)
179 INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB)
181 if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB)))
182 return VCPN_FAIL; /* correct ? */
183 return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr);
186 /***********************************************************************
187 * vsmGetStringRawName (SETUPX.208)
189 LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
191 return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
195 /***************************** VIRTNODE management ****************************/
196 static LPVIRTNODE *pvnlist = NULL;
197 static DWORD vn_num = 0;
198 static DWORD vn_last = 0;
200 RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
202 HANDLE heap;
203 LPVIRTNODE lpvn;
204 RETERR16 cbres;
206 while (vn_last < vn_num)
208 if (pvnlist[vn_last] == NULL)
209 break;
210 vn_last++;
212 heap = GetProcessHeap();
213 if (vn_last == vn_num)
215 vn_num += 20;
216 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
217 sizeof(LPVIRTNODE *) * vn_num);
219 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
220 lpvn = pvnlist[vn_last];
221 vn_last++;
223 lpvn->cbSize = sizeof(VIRTNODE);
225 if (vfsSrc)
226 memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC));
228 if (vfsDst)
229 memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC));
231 lpvn->fl = fl;
232 lpvn->lParam = lParam;
233 lpvn->lpExpandVtbl = lpExpandVtbl;
235 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
237 cbres = VCP_CALLBACK(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
238 lpvn->fl |= VFNL_CREATED;
239 cbres = VCP_CALLBACK(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);
241 return OK;
244 BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
246 DWORD n;
247 RETERR16 cbres;
249 for (n = 0; n < vn_last; n++)
251 if (pvnlist[n] == lpvnDel)
253 cbres = VCP_CALLBACK(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
254 HeapFree(GetProcessHeap(), 0, lpvnDel);
255 pvnlist[n] = NULL;
256 return TRUE;
259 return FALSE;
262 /***********************************************************************
263 * VcpOpen (SETUPX.200)
265 * Sets up a virtual copy operation.
266 * This means that functions such as GenInstall()
267 * create a VIRTNODE struct for every file to be touched in a .INF file
268 * instead of actually touching the file.
269 * The actual copy/move/rename gets started when VcpClose or
270 * VcpFlush is called; several different callbacks are made
271 * (copy, rename, open, close, version conflicts, ...) on every file copied.
273 RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
275 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
276 if (VCP_opened)
277 return ERR_VCP_BUSY;
279 VCP_Proc = (FARPROC16)vifproc;
280 VCP_MsgRef = lparamMsgRef;
282 /* load SETUPAPI needed for dialog resources etc. */
283 SETUPAPI_hInstance = LoadLibraryA("setupapi.dll");
284 if (!SETUPAPI_hInstance)
286 ERR("Could not load sibling setupapi.dll\n");
287 return ERR_VCP_NOMEM;
289 VCP_opened = TRUE;
290 return OK;
293 /***********************************************************************
294 * VcpQueueCopy [SETUPX.13]
296 * lpExpandVtbl seems to be deprecated.
297 * fl are the CNFL_xxx and VNFL_xxx flags.
298 * lParam are the VNLP_xxx flags.
300 RETERR16 WINAPI VcpQueueCopy16(
301 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
302 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
303 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
304 LPEXPANDVTBL lpExpandVtbl,
305 WORD fl, LPARAM lParam
308 VCPFILESPEC vfsSrc, vfsDst;
310 if (!VCP_opened)
311 return ERR_VCP_NOTOPEN;
313 TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
314 lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
316 TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
318 vfsSrc.ldid = ldidSrc;
319 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
320 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
322 vfsDst.ldid = ldidDst;
323 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
324 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
326 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
327 lpExpandVtbl);
330 /***********************************************************************
331 * VcpQueueDelete [SETUPX.17]
333 * Is lParamRef the same as lParam in VcpQueueCopy ?
334 * Damn docu !! Err... which docu ?
336 RETERR16 WINAPI VcpQueueDelete16(
337 LPCSTR lpszDstFileName,
338 LPCSTR lpszDstDir,
339 LOGDISKID16 ldidDst,
340 LPARAM lParamRef
343 VCPFILESPEC vfsDst;
345 if (!VCP_opened)
346 return ERR_VCP_NOTOPEN;
348 vfsDst.ldid = ldidDst;
349 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
350 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
352 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
355 /***********************************************************************
356 * VcpQueueRename [SETUPX.204]
359 RETERR16 WINAPI VcpQueueRename16(
360 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
361 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
362 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
363 LPARAM lParam
366 VCPFILESPEC vfsSrc, vfsDst;
368 if (!VCP_opened)
369 return ERR_VCP_NOTOPEN;
371 vfsSrc.ldid = ldidSrc;
372 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
373 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
375 vfsDst.ldid = ldidDst;
376 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
377 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
379 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
383 /***********************************************************************
384 * VcpEnumFiles (SETUPX.@)
386 INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
388 WORD n;
390 for (n = 0; n < vn_last; n++)
391 vep(pvnlist[n], lParamRef);
393 return 0; /* FIXME: return value ? */
396 /***********************************************************************
397 * VcpExplain (SETUPX.411)
399 LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
401 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
402 buffer[0] = '\0';
403 switch (dwWhat)
405 case VCPEX_SRC_FULL:
406 case VCPEX_DST_FULL:
408 LPVCPFILESPEC lpvfs =
409 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
411 /* if we have an ldid, use it, otherwise use the string */
412 /* from the vhstrlist array */
413 if (lpvfs->ldid != 0xffff)
414 CtlGetLddPath16(lpvfs->ldid, buffer);
415 else
416 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
418 strcat(buffer, "\\");
419 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
421 break;
422 default:
423 FIXME("%ld unimplemented !\n", dwWhat);
424 strcpy(buffer, "Unknown error");
425 break;
427 return buffer;
430 RETERR16 VCP_CheckPaths(void)
432 DWORD n;
433 LPVIRTNODE lpvn;
434 RETERR16 cbres;
436 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
437 for (n = 0; n < vn_num; n++)
439 lpvn = pvnlist[n];
440 if (!lpvn) continue;
441 /* FIXME: check paths of all VIRTNODEs here ! */
442 cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
444 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
445 return OK;
448 RETERR16 VCP_CopyFiles(void)
450 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
451 RETERR16 res = OK, cbres;
452 DWORD n;
453 LPVIRTNODE lpvn;
455 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
456 for (n = 0; n < vn_num; n++)
458 lpvn = pvnlist[n];
459 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
460 /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
461 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
462 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
463 /* FIXME: what is this VCPM_VSTATWRITE here for ?
464 * I guess it's to signal successful destination file creation */
465 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
467 /* FIXME: need to do the file copy in small chunks for notifications */
468 TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
469 /* perform the file copy */
470 if (!(CopyFileA(fn_src, fn_dst, TRUE)))
472 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
473 res = ERR_VCP_IOFAIL;
476 vcp_status.prgFileRead.dwSoFar++;
477 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
478 vcp_status.prgFileWrite.dwSoFar++;
479 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
482 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
483 return res;
486 /***********************************************************************
487 * VcpFlush - internal (not exported), but documented
489 * VNFL_NOW is used for VcpFlush.
491 RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
493 return OK;
496 /***********************************************************************
497 * VcpClose (SETUPX.201)
499 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
500 * VCPM_VSTATCLOSEEND.
502 * fl gets VCPFL_xxx flags to indicate what to do with the
503 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
505 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
507 RETERR16 res = OK;
508 WORD cbres = VCPN_PROCEED;
510 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
512 /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER
513 * is not set. This is done by VCP_CALLBACK(VCPM_NODECOMPARE) */
515 TRACE("#1\n");
516 memset(&vcp_status, 0, sizeof(VCPSTATUS));
517 /* yes, vcp_status.cbSize is 0 ! */
518 TRACE("#2\n");
519 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
520 TRACE("#3\n");
522 res = VCP_CheckPaths();
523 TRACE("#4\n");
524 if (res != OK)
525 return res; /* is this ok ? */
526 VCP_CopyFiles();
528 TRACE("#5\n");
529 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
530 TRACE("#6\n");
531 VCP_Proc = NULL;
532 FreeLibrary(SETUPAPI_hInstance);
533 VCP_opened = FALSE;
534 return OK;
537 RETERR16 VCP_RenameFiles(void)
539 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
540 RETERR16 res = OK, cbres;
541 DWORD n;
542 LPVIRTNODE lpvn;
544 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
545 for (n = 0; n < vn_num; n++)
547 lpvn = pvnlist[n];
548 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
549 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
550 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
551 cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
552 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
553 res = ERR_VCP_IOFAIL;
554 else
555 VCP_VirtnodeDelete(lpvn);
557 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
558 return res;
561 /***********************************************************************
562 * vcpDefCallbackProc (SETUPX.202)
564 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
565 LPARAM lParam, LPARAM lParamRef)
567 static int count = 0;
568 if (count < 10)
569 FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
570 lpvObj, uMsg, wParam, lParam, lParamRef);
571 count++;
572 return OK;
575 /********************* point-and-click stuff from here ***********************/
577 static HWND hDlgCopy = 0;
578 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
579 static char BackupDir[12];
581 static BOOL CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
583 BOOL retval = FALSE;
585 if (iMsg == WM_INITDIALOG)
587 ShowWindow(hWndDlg, SW_SHOWNORMAL);
588 UpdateWindow(hWndDlg);
589 retval = TRUE;
591 return retval;
594 BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
596 HANDLE hResInfo, hDlgTmpl32;
598 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), RT_DIALOGA)))
599 return FALSE;
600 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
601 !(*template32 = LockResource( hDlgTmpl32 )))
602 return FALSE;
603 return TRUE;
606 static LRESULT WINAPI
607 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
609 if (uMsg != WM_CREATE)
610 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
612 switch (uMsg)
614 case WM_CREATE:
615 return 0;
616 default:
617 FIXME("%04x: unhandled.\n", uMsg);
620 return 0;
623 void VCP_UI_RegisterProgressClass(void)
625 static BOOL registered = FALSE;
626 WNDCLASSA wndClass;
628 if (registered)
629 return;
631 registered = TRUE;
632 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
633 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
634 wndClass.lpfnWndProc = (WNDPROC)VCP_UI_FileCopyWndProc;
635 wndClass.cbClsExtra = 0;
636 wndClass.cbWndExtra = 0;
637 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
638 wndClass.hbrBackground = (HBRUSH)NULL;
639 wndClass.lpszClassName = "setupx_progress";
641 RegisterClassA (&wndClass);
644 RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
646 LPCSTR file1, file2;
647 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
648 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
649 return (RETERR16)strcmp(file1, file2);
652 RETERR16 VCP_UI_CopyStart(void)
654 LPCVOID template32;
655 char buf[256]; /* plenty */
656 BOOL dirty;
657 DWORD len;
659 /* FIXME: should be registered at DLL startup instead */
660 VCP_UI_RegisterProgressClass();
661 if (!(VCP_UI_GetDialogTemplate(&template32)))
662 return VCPN_FAIL;
664 if (vn_num > 10) /* hack */
666 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
667 VCP_UI_FileCopyDlgProc, 0);
668 if (!hDlgCopy)
669 return VCPN_FAIL;
670 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
671 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
673 strcpy(buf, REG_INSTALLEDFILES);
674 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
675 return VCPN_FAIL;
676 strcat(buf, REGPART_RENAME);
677 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
678 return VCPN_FAIL;
679 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
680 return VCPN_FAIL;
681 len = 1;
682 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
684 /* FIXME: what does SETUPX.DLL do in this case ? */
685 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
686 return VCPN_FAIL;
688 dirty = TRUE;
689 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
690 return VCPN_FAIL;
691 len = 12;
692 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len)))
693 strcpy(BackupDir, "VCM");
695 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
696 GetWindowsDirectoryA(buf, 256);
697 strcat(buf, "\\");
698 strcat(buf, BackupDir);
699 if (!(CreateDirectoryA(buf, NULL)))
700 return VCPN_FAIL;
701 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
702 return VCPN_FAIL;
703 RegCloseKey(hKeyConflict);
705 return VCPN_OK;
708 /***********************************************************************
709 * vcpUICallbackProc (SETUPX.213)
711 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
712 LPARAM lParam, LPARAM lParamRef)
714 static int count = 0;
715 RETERR16 res = VCPN_OK, cbres;
717 if (count < 5)
718 FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n",
719 lpvObj, uMsg, wParam, lParam, lParamRef);
720 count++;
721 switch (uMsg)
723 /* unused messages, it seems */
724 case VCPM_DISKPREPINFO:
726 case VCPM_FILENEEDED:
728 case VCPM_NODECREATE:
729 case VCPM_NODEACCEPT:
731 case VCPM_VSTATCLOSESTART:
732 case VCPM_VSTATPATHCHECKSTART:
733 case VCPM_VSTATPATHCHECKEND:
735 case VCPM_CHECKPATH:
736 break;
738 /* the real stuff */
739 case VCPM_NODECOMPARE:
740 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
741 break;
742 case VCPM_VSTATREAD:
743 break;
744 case VCPM_VSTATWRITE:
745 cbres = VCP_CALLBACK(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
746 break;
747 case VCPM_VSTATCLOSEEND:
748 RegCloseKey(hKeyFiles);
749 RegCloseKey(hKeyRename);
750 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
751 break;
752 case VCPM_VSTATCOPYSTART:
753 res = VCP_UI_CopyStart();
754 break;
755 case VCPM_VSTATCOPYEND:
756 if (hDlgCopy) DestroyWindow(hDlgCopy);
757 break;
758 default:
759 FIXME("unhandled msg 0x%04x\n", uMsg);
761 return res;