Add support for impersonating a token.
[wine/multimedia.git] / dlls / setupapi / virtcopy.c
blob14c017fa804dfaa291658c5627dd6513a763cc10
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 = GetModuleHandleA("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 VCP_opened = FALSE;
559 return OK;
562 RETERR16 VCP_RenameFiles(void)
564 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
565 RETERR16 res = OK, cbres;
566 DWORD n;
567 LPVIRTNODE lpvn;
569 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
570 for (n = 0; n < vn_num; n++)
572 lpvn = pvnlist[n];
573 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
574 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
575 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
576 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
577 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
578 res = ERR_VCP_IOFAIL;
579 else
580 VCP_VirtnodeDelete(lpvn);
582 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
583 return res;
586 /***********************************************************************
587 * vcpDefCallbackProc (SETUPX.202)
589 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
590 LPARAM lParam, LPARAM lParamRef)
592 static int count = 0;
593 if (count < 10)
594 FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
595 lpvObj, uMsg, wParam, lParam, lParamRef);
596 count++;
597 return OK;
600 /********************* point-and-click stuff from here ***********************/
602 static HWND hDlgCopy = 0;
603 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
604 static char BackupDir[12];
606 static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
608 INT_PTR retval = FALSE;
610 if (iMsg == WM_INITDIALOG)
612 ShowWindow(hWndDlg, SW_SHOWNORMAL);
613 UpdateWindow(hWndDlg);
614 retval = TRUE;
616 return retval;
619 BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
621 HRSRC hResInfo;
622 HGLOBAL hDlgTmpl32;
624 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), (LPSTR)RT_DIALOG)))
625 return FALSE;
626 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
627 !(*template32 = LockResource( hDlgTmpl32 )))
628 return FALSE;
629 return TRUE;
632 static LRESULT WINAPI
633 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
635 if (uMsg != WM_CREATE)
636 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
638 switch (uMsg)
640 case WM_CREATE:
641 return 0;
642 default:
643 FIXME("%04x: unhandled.\n", uMsg);
646 return 0;
649 void VCP_UI_RegisterProgressClass(void)
651 static BOOL registered = FALSE;
652 WNDCLASSA wndClass;
654 if (registered)
655 return;
657 registered = TRUE;
658 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
659 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
660 wndClass.lpfnWndProc = VCP_UI_FileCopyWndProc;
661 wndClass.cbClsExtra = 0;
662 wndClass.cbWndExtra = 0;
663 wndClass.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
664 wndClass.hbrBackground = NULL;
665 wndClass.lpszClassName = "setupx_progress";
667 RegisterClassA (&wndClass);
670 RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
672 LPCSTR file1, file2;
673 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
674 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
675 return (RETERR16)strcmp(file1, file2);
678 RETERR16 VCP_UI_CopyStart(void)
680 LPCVOID template32;
681 char buf[256]; /* plenty */
682 BOOL dirty;
683 DWORD len;
685 /* FIXME: should be registered at DLL startup instead */
686 VCP_UI_RegisterProgressClass();
687 if (!(VCP_UI_GetDialogTemplate(&template32)))
688 return VCPN_FAIL;
690 if (vn_num > 10) /* hack */
692 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
693 VCP_UI_FileCopyDlgProc, 0);
694 if (!hDlgCopy)
695 return VCPN_FAIL;
696 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
697 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
699 strcpy(buf, REG_INSTALLEDFILES);
700 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
701 return VCPN_FAIL;
702 strcat(buf, REGPART_RENAME);
703 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
704 return VCPN_FAIL;
705 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
706 return VCPN_FAIL;
707 len = 1;
708 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
710 /* FIXME: what does SETUPX.DLL do in this case ? */
711 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
712 return VCPN_FAIL;
714 dirty = TRUE;
715 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
716 return VCPN_FAIL;
717 len = 12;
718 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len)))
719 strcpy(BackupDir, "VCM");
721 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
722 GetWindowsDirectoryA(buf, 256);
723 strcat(buf, "\\");
724 strcat(buf, BackupDir);
725 if (!(CreateDirectoryA(buf, NULL)))
726 return VCPN_FAIL;
727 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
728 return VCPN_FAIL;
729 RegCloseKey(hKeyConflict);
731 return VCPN_OK;
734 /***********************************************************************
735 * vcpUICallbackProc (SETUPX.213)
737 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
738 LPARAM lParam, LPARAM lParamRef)
740 static int count = 0;
741 RETERR16 res = VCPN_OK, cbres;
743 if (count < 5)
744 FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n",
745 lpvObj, uMsg, wParam, lParam, lParamRef);
746 count++;
747 switch (uMsg)
749 /* unused messages, it seems */
750 case VCPM_DISKPREPINFO:
752 case VCPM_FILENEEDED:
754 case VCPM_NODECREATE:
755 case VCPM_NODEACCEPT:
757 case VCPM_VSTATCLOSESTART:
758 case VCPM_VSTATPATHCHECKSTART:
759 case VCPM_VSTATPATHCHECKEND:
761 case VCPM_CHECKPATH:
762 break;
764 /* the real stuff */
765 case VCPM_NODECOMPARE:
766 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
767 break;
768 case VCPM_VSTATREAD:
769 break;
770 case VCPM_VSTATWRITE:
771 cbres = VCP_Callback(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
772 break;
773 case VCPM_VSTATCLOSEEND:
774 RegCloseKey(hKeyFiles);
775 RegCloseKey(hKeyRename);
776 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
777 break;
778 case VCPM_VSTATCOPYSTART:
779 res = VCP_UI_CopyStart();
780 break;
781 case VCPM_VSTATCOPYEND:
782 if (hDlgCopy) DestroyWindow(hDlgCopy);
783 break;
784 default:
785 FIXME("unhandled msg 0x%04x\n", uMsg);
787 return res;