#ifdef guard the declaration of type IID to be compatible with
[wine.git] / dlls / setupapi / virtcopy.c
blob47c79dcf54a09b48315e9609f73cd6c76deb5377
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 <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 "wingdi.h"
32 #include "winnls.h"
33 #include "setupapi.h"
34 #include "setupx16.h"
35 #include "setupapi_private.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
40 static FARPROC16 VCP_Proc = NULL;
41 static LPARAM VCP_MsgRef = 0;
43 static BOOL VCP_opened = FALSE;
45 static VCPSTATUS vcp_status;
47 static HINSTANCE SETUPAPI_hInstance;
49 static WORD VCP_Callback( LPVOID obj, UINT16 msg, WPARAM16 wParam, LPARAM lParam, LPARAM lParamRef )
51 WORD args[8];
52 DWORD ret = OK;
53 if (VCP_Proc)
55 args[7] = HIWORD(obj);
56 args[6] = LOWORD(obj);
57 args[5] = msg;
58 args[4] = wParam;
59 args[3] = HIWORD(lParam);
60 args[2] = LOWORD(lParam);
61 args[1] = HIWORD(lParamRef);
62 args[0] = LOWORD(lParamRef);
63 WOWCallback16Ex( (DWORD)VCP_Proc, WCB16_PASCAL, sizeof(args), args, &ret );
65 return (WORD)ret;
68 /****************************** VHSTR management ******************************/
71 * This is a totally braindead implementation for now;
72 * I don't care about speed at all ! Size and implementation time
73 * is much more important IMHO. I could have created some sophisticated
74 * tree structure, but... what the hell ! :-)
76 typedef struct {
77 DWORD refcount;
78 LPCSTR pStr;
79 } VHSTR_STRUCT;
81 static VHSTR_STRUCT **vhstrlist = NULL;
82 static VHSTR vhstr_alloc = 0;
84 #define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount))
86 /***********************************************************************
87 * vsmStringAdd (SETUPX.207)
89 VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName)
91 VHSTR n;
92 VHSTR index = 0xffff;
93 HANDLE heap;
95 TRACE("add string '%s'\n", lpszName);
96 /* search whether string already inserted */
97 TRACE("searching for existing string...\n");
98 for (n = 0; n < vhstr_alloc; n++)
100 if ((vhstrlist[n]) && (vhstrlist[n]->refcount))
102 TRACE("checking item: %d\n", n);
103 if (!strcmp(vhstrlist[n]->pStr, lpszName))
105 TRACE("found\n");
106 vhstrlist[n]->refcount++;
107 return n;
112 /* hmm, not found yet, let's insert it */
113 TRACE("inserting item\n");
114 for (n = 0; n < vhstr_alloc; n++)
116 if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount)))
118 index = n;
119 break;
122 heap = GetProcessHeap();
123 if (n == vhstr_alloc) /* hmm, no free index found yet */
125 index = vhstr_alloc;
126 vhstr_alloc += 20;
128 if (vhstrlist)
129 vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
130 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
131 else
132 vhstrlist = HeapAlloc(heap, HEAP_ZERO_MEMORY,
133 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
135 if (index == 0xffff)
136 return 0xffff; /* failure */
137 if (!vhstrlist[index])
138 vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT));
139 vhstrlist[index]->refcount = 1;
140 vhstrlist[index]->pStr = HeapAlloc(heap, 0, strlen(lpszName)+1);
141 strcpy((LPSTR)vhstrlist[index]->pStr, lpszName);
142 return index;
145 /***********************************************************************
146 * vsmStringDelete (SETUPX.206)
148 INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
150 if (VALID_VHSTR(vhstr))
152 vhstrlist[vhstr]->refcount--;
153 if (!vhstrlist[vhstr]->refcount)
155 HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
156 vhstrlist[vhstr]->pStr = NULL;
158 return VCPN_OK;
161 /* string not found */
162 return VCPN_FAIL;
166 * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
168 VHSTR WINAPI vsmStringFind16(LPCSTR lpszName)
170 WORD n;
171 for (n = 0; n < vhstr_alloc; n++)
172 if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName)))
173 return n;
174 return 0xffff;
177 /***********************************************************************
178 * vsmGetStringName (SETUPX.205)
180 * Pretty correct, I guess
182 INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
184 if (VALID_VHSTR(vhstr))
186 int len = strlen(vhstrlist[vhstr]->pStr)+1;
187 if (cbBuffer >= len)
189 if (lpszBuffer)
190 strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
191 return len;
194 return VCPN_FAIL;
197 /***********************************************************************
198 * vsmStringCompare (not exported from a standard SETUPX.DLL, it seems)
200 INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB)
202 if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB)))
203 return VCPN_FAIL; /* correct ? */
204 return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr);
207 /***********************************************************************
208 * vsmGetStringRawName (SETUPX.208)
210 LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
212 return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
216 /***************************** VIRTNODE management ****************************/
217 static LPVIRTNODE *pvnlist = NULL;
218 static DWORD vn_num = 0;
219 static DWORD vn_last = 0;
221 RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
223 HANDLE heap;
224 LPVIRTNODE lpvn;
225 RETERR16 cbres;
227 while (vn_last < vn_num)
229 if (pvnlist[vn_last] == NULL)
230 break;
231 vn_last++;
233 heap = GetProcessHeap();
234 if (vn_last == vn_num)
236 vn_num += 20;
237 if (pvnlist)
238 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
239 sizeof(LPVIRTNODE *) * vn_num);
240 else
241 pvnlist = HeapAlloc(heap, HEAP_ZERO_MEMORY,
242 sizeof(LPVIRTNODE *) * vn_num);
244 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
245 lpvn = pvnlist[vn_last];
246 vn_last++;
248 lpvn->cbSize = sizeof(VIRTNODE);
250 if (vfsSrc)
251 memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC));
253 if (vfsDst)
254 memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC));
256 lpvn->fl = fl;
257 lpvn->lParam = lParam;
258 lpvn->lpExpandVtbl = lpExpandVtbl;
260 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
262 cbres = VCP_Callback(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
263 lpvn->fl |= VFNL_CREATED;
264 cbres = VCP_Callback(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);
266 return OK;
269 BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
271 DWORD n;
272 RETERR16 cbres;
274 for (n = 0; n < vn_last; n++)
276 if (pvnlist[n] == lpvnDel)
278 cbres = VCP_Callback(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
279 HeapFree(GetProcessHeap(), 0, lpvnDel);
280 pvnlist[n] = NULL;
281 return TRUE;
284 return FALSE;
287 /***********************************************************************
288 * VcpOpen (SETUPX.200)
290 * Sets up a virtual copy operation.
291 * This means that functions such as GenInstall()
292 * create a VIRTNODE struct for every file to be touched in a .INF file
293 * instead of actually touching the file.
294 * The actual copy/move/rename gets started when VcpClose or
295 * VcpFlush is called; several different callbacks are made
296 * (copy, rename, open, close, version conflicts, ...) on every file copied.
298 RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
300 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
301 if (VCP_opened)
302 return ERR_VCP_BUSY;
304 VCP_Proc = (FARPROC16)vifproc;
305 VCP_MsgRef = lparamMsgRef;
307 /* load SETUPAPI needed for dialog resources etc. */
308 SETUPAPI_hInstance = LoadLibraryA("setupapi.dll");
309 if (!SETUPAPI_hInstance)
311 ERR("Could not load sibling setupapi.dll\n");
312 return ERR_VCP_NOMEM;
314 VCP_opened = TRUE;
315 return OK;
318 /***********************************************************************
319 * VcpQueueCopy [SETUPX.13]
321 * lpExpandVtbl seems to be deprecated.
322 * fl are the CNFL_xxx and VNFL_xxx flags.
323 * lParam are the VNLP_xxx flags.
325 RETERR16 WINAPI VcpQueueCopy16(
326 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
327 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
328 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
329 LPEXPANDVTBL lpExpandVtbl,
330 WORD fl, LPARAM lParam
333 VCPFILESPEC vfsSrc, vfsDst;
335 if (!VCP_opened)
336 return ERR_VCP_NOTOPEN;
338 TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
339 lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
341 TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
343 vfsSrc.ldid = ldidSrc;
344 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
345 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
347 vfsDst.ldid = ldidDst;
348 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
349 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
351 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
352 lpExpandVtbl);
355 /***********************************************************************
356 * VcpQueueDelete [SETUPX.17]
358 * Is lParamRef the same as lParam in VcpQueueCopy ?
359 * Damn docu !! Err... which docu ?
361 RETERR16 WINAPI VcpQueueDelete16(
362 LPCSTR lpszDstFileName,
363 LPCSTR lpszDstDir,
364 LOGDISKID16 ldidDst,
365 LPARAM lParamRef
368 VCPFILESPEC vfsDst;
370 if (!VCP_opened)
371 return ERR_VCP_NOTOPEN;
373 vfsDst.ldid = ldidDst;
374 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
375 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
377 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
380 /***********************************************************************
381 * VcpQueueRename [SETUPX.204]
384 RETERR16 WINAPI VcpQueueRename16(
385 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
386 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
387 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
388 LPARAM lParam
391 VCPFILESPEC vfsSrc, vfsDst;
393 if (!VCP_opened)
394 return ERR_VCP_NOTOPEN;
396 vfsSrc.ldid = ldidSrc;
397 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
398 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
400 vfsDst.ldid = ldidDst;
401 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
402 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
404 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
408 /***********************************************************************
409 * VcpEnumFiles (SETUPX.@)
411 INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
413 WORD n;
415 for (n = 0; n < vn_last; n++)
416 vep(pvnlist[n], lParamRef);
418 return 0; /* FIXME: return value ? */
421 /***********************************************************************
422 * VcpExplain (SETUPX.411)
424 LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
426 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
427 buffer[0] = '\0';
428 switch (dwWhat)
430 case VCPEX_SRC_FULL:
431 case VCPEX_DST_FULL:
433 LPVCPFILESPEC lpvfs =
434 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
436 /* if we have an ldid, use it, otherwise use the string */
437 /* from the vhstrlist array */
438 if (lpvfs->ldid != 0xffff)
439 CtlGetLddPath16(lpvfs->ldid, buffer);
440 else
441 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
443 strcat(buffer, "\\");
444 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
446 break;
447 default:
448 FIXME("%ld unimplemented !\n", dwWhat);
449 strcpy(buffer, "Unknown error");
450 break;
452 return buffer;
455 RETERR16 VCP_CheckPaths(void)
457 DWORD n;
458 LPVIRTNODE lpvn;
459 RETERR16 cbres;
461 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
462 for (n = 0; n < vn_num; n++)
464 lpvn = pvnlist[n];
465 if (!lpvn) continue;
466 /* FIXME: check paths of all VIRTNODEs here ! */
467 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
469 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
470 return OK;
473 RETERR16 VCP_CopyFiles(void)
475 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
476 RETERR16 res = OK, cbres;
477 DWORD n;
478 LPVIRTNODE lpvn;
480 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
481 for (n = 0; n < vn_num; n++)
483 lpvn = pvnlist[n];
484 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
485 /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
486 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
487 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
488 /* FIXME: what is this VCPM_VSTATWRITE here for ?
489 * I guess it's to signal successful destination file creation */
490 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
492 /* FIXME: need to do the file copy in small chunks for notifications */
493 TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
494 /* perform the file copy */
495 if (!(CopyFileA(fn_src, fn_dst,
496 (lpvn->fl & VNLP_COPYIFEXISTS) ? FALSE : TRUE )))
498 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
499 res = ERR_VCP_IOFAIL;
502 vcp_status.prgFileRead.dwSoFar++;
503 cbres = VCP_Callback(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
504 vcp_status.prgFileWrite.dwSoFar++;
505 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
508 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
509 return res;
512 /***********************************************************************
513 * VcpFlush - internal (not exported), but documented
515 * VNFL_NOW is used for VcpFlush.
517 RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
519 return OK;
522 /***********************************************************************
523 * VcpClose (SETUPX.201)
525 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
526 * VCPM_VSTATCLOSEEND.
528 * fl gets VCPFL_xxx flags to indicate what to do with the
529 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
531 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
533 RETERR16 res = OK;
534 WORD cbres = VCPN_PROCEED;
536 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
538 /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER
539 * is not set. This is done by VCP_Callback(VCPM_NODECOMPARE) */
541 TRACE("#1\n");
542 memset(&vcp_status, 0, sizeof(VCPSTATUS));
543 /* yes, vcp_status.cbSize is 0 ! */
544 TRACE("#2\n");
545 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
546 TRACE("#3\n");
548 res = VCP_CheckPaths();
549 TRACE("#4\n");
550 if (res != OK)
551 return res; /* is this ok ? */
552 VCP_CopyFiles();
554 TRACE("#5\n");
555 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
556 TRACE("#6\n");
557 VCP_Proc = NULL;
558 FreeLibrary(SETUPAPI_hInstance);
559 VCP_opened = FALSE;
560 return OK;
563 RETERR16 VCP_RenameFiles(void)
565 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
566 RETERR16 res = OK, cbres;
567 DWORD n;
568 LPVIRTNODE lpvn;
570 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
571 for (n = 0; n < vn_num; n++)
573 lpvn = pvnlist[n];
574 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
575 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
576 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
577 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
578 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
579 res = ERR_VCP_IOFAIL;
580 else
581 VCP_VirtnodeDelete(lpvn);
583 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
584 return res;
587 /***********************************************************************
588 * vcpDefCallbackProc (SETUPX.202)
590 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
591 LPARAM lParam, LPARAM lParamRef)
593 static int count = 0;
594 if (count < 10)
595 FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
596 lpvObj, uMsg, wParam, lParam, lParamRef);
597 count++;
598 return OK;
601 /********************* point-and-click stuff from here ***********************/
603 static HWND hDlgCopy = 0;
604 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
605 static char BackupDir[12];
607 static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
609 INT_PTR retval = FALSE;
611 if (iMsg == WM_INITDIALOG)
613 ShowWindow(hWndDlg, SW_SHOWNORMAL);
614 UpdateWindow(hWndDlg);
615 retval = TRUE;
617 return retval;
620 BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
622 HRSRC hResInfo;
623 HGLOBAL hDlgTmpl32;
625 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), (LPSTR)RT_DIALOG)))
626 return FALSE;
627 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
628 !(*template32 = LockResource( hDlgTmpl32 )))
629 return FALSE;
630 return TRUE;
633 static LRESULT WINAPI
634 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
636 if (uMsg != WM_CREATE)
637 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
639 switch (uMsg)
641 case WM_CREATE:
642 return 0;
643 default:
644 FIXME("%04x: unhandled.\n", uMsg);
647 return 0;
650 void VCP_UI_RegisterProgressClass(void)
652 static BOOL registered = FALSE;
653 WNDCLASSA wndClass;
655 if (registered)
656 return;
658 registered = TRUE;
659 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
660 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
661 wndClass.lpfnWndProc = (WNDPROC)VCP_UI_FileCopyWndProc;
662 wndClass.cbClsExtra = 0;
663 wndClass.cbWndExtra = 0;
664 wndClass.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
665 wndClass.hbrBackground = NULL;
666 wndClass.lpszClassName = "setupx_progress";
668 RegisterClassA (&wndClass);
671 RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
673 LPCSTR file1, file2;
674 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
675 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
676 return (RETERR16)strcmp(file1, file2);
679 RETERR16 VCP_UI_CopyStart(void)
681 LPCVOID template32;
682 char buf[256]; /* plenty */
683 BOOL dirty;
684 DWORD len;
686 /* FIXME: should be registered at DLL startup instead */
687 VCP_UI_RegisterProgressClass();
688 if (!(VCP_UI_GetDialogTemplate(&template32)))
689 return VCPN_FAIL;
691 if (vn_num > 10) /* hack */
693 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
694 VCP_UI_FileCopyDlgProc, 0);
695 if (!hDlgCopy)
696 return VCPN_FAIL;
697 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
698 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
700 strcpy(buf, REG_INSTALLEDFILES);
701 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
702 return VCPN_FAIL;
703 strcat(buf, REGPART_RENAME);
704 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
705 return VCPN_FAIL;
706 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
707 return VCPN_FAIL;
708 len = 1;
709 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
711 /* FIXME: what does SETUPX.DLL do in this case ? */
712 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
713 return VCPN_FAIL;
715 dirty = TRUE;
716 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
717 return VCPN_FAIL;
718 len = 12;
719 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len)))
720 strcpy(BackupDir, "VCM");
722 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
723 GetWindowsDirectoryA(buf, 256);
724 strcat(buf, "\\");
725 strcat(buf, BackupDir);
726 if (!(CreateDirectoryA(buf, NULL)))
727 return VCPN_FAIL;
728 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
729 return VCPN_FAIL;
730 RegCloseKey(hKeyConflict);
732 return VCPN_OK;
735 /***********************************************************************
736 * vcpUICallbackProc (SETUPX.213)
738 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
739 LPARAM lParam, LPARAM lParamRef)
741 static int count = 0;
742 RETERR16 res = VCPN_OK, cbres;
744 if (count < 5)
745 FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n",
746 lpvObj, uMsg, wParam, lParam, lParamRef);
747 count++;
748 switch (uMsg)
750 /* unused messages, it seems */
751 case VCPM_DISKPREPINFO:
753 case VCPM_FILENEEDED:
755 case VCPM_NODECREATE:
756 case VCPM_NODEACCEPT:
758 case VCPM_VSTATCLOSESTART:
759 case VCPM_VSTATPATHCHECKSTART:
760 case VCPM_VSTATPATHCHECKEND:
762 case VCPM_CHECKPATH:
763 break;
765 /* the real stuff */
766 case VCPM_NODECOMPARE:
767 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
768 break;
769 case VCPM_VSTATREAD:
770 break;
771 case VCPM_VSTATWRITE:
772 cbres = VCP_Callback(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
773 break;
774 case VCPM_VSTATCLOSEEND:
775 RegCloseKey(hKeyFiles);
776 RegCloseKey(hKeyRename);
777 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
778 break;
779 case VCPM_VSTATCOPYSTART:
780 res = VCP_UI_CopyStart();
781 break;
782 case VCPM_VSTATCOPYEND:
783 if (hDlgCopy) DestroyWindow(hDlgCopy);
784 break;
785 default:
786 FIXME("unhandled msg 0x%04x\n", uMsg);
788 return res;