Do not pass unnecessary flags to wrc in generated makefiles.
[wine/multimedia.git] / dlls / setupapi / virtcopy.c
blob3a31e44e5242c2972cf7c61687209a3665897874
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 "wownt32.h"
29 #include "setupapi.h"
30 #include "setupx16.h"
31 #include "setupapi_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
36 static FARPROC16 VCP_Proc = NULL;
37 static LPARAM VCP_MsgRef = 0;
39 static BOOL VCP_opened = FALSE;
41 static VCPSTATUS vcp_status;
43 static HINSTANCE SETUPAPI_hInstance;
45 static WORD VCP_Callback( LPVOID obj, UINT16 msg, WPARAM16 wParam, LPARAM lParam, LPARAM lParamRef )
47 WORD args[8];
48 DWORD ret = OK;
49 if (VCP_Proc)
51 args[7] = HIWORD(obj);
52 args[6] = LOWORD(obj);
53 args[5] = msg;
54 args[4] = wParam;
55 args[3] = HIWORD(lParam);
56 args[2] = LOWORD(lParam);
57 args[1] = HIWORD(lParamRef);
58 args[0] = LOWORD(lParamRef);
59 WOWCallback16Ex( (DWORD)VCP_Proc, WCB16_PASCAL, sizeof(args), args, &ret );
61 return (WORD)ret;
64 /****************************** VHSTR management ******************************/
67 * This is a totally braindead implementation for now;
68 * I don't care about speed at all ! Size and implementation time
69 * is much more important IMHO. I could have created some sophisticated
70 * tree structure, but... what the hell ! :-)
72 typedef struct {
73 DWORD refcount;
74 LPCSTR pStr;
75 } VHSTR_STRUCT;
77 static VHSTR_STRUCT **vhstrlist = NULL;
78 static VHSTR vhstr_alloc = 0;
80 #define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount))
82 /***********************************************************************
83 * vsmStringAdd (SETUPX.207)
85 VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName)
87 VHSTR n;
88 VHSTR index = 0xffff;
89 HANDLE heap;
91 TRACE("add string '%s'\n", lpszName);
92 /* search whether string already inserted */
93 TRACE("searching for existing string...\n");
94 for (n = 0; n < vhstr_alloc; n++)
96 if ((vhstrlist[n]) && (vhstrlist[n]->refcount))
98 TRACE("checking item: %d\n", n);
99 if (!strcmp(vhstrlist[n]->pStr, lpszName))
101 TRACE("found\n");
102 vhstrlist[n]->refcount++;
103 return n;
108 /* hmm, not found yet, let's insert it */
109 TRACE("inserting item\n");
110 for (n = 0; n < vhstr_alloc; n++)
112 if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount)))
114 index = n;
115 break;
118 heap = GetProcessHeap();
119 if (n == vhstr_alloc) /* hmm, no free index found yet */
121 index = vhstr_alloc;
122 vhstr_alloc += 20;
123 vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
124 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
126 if (index == 0xffff)
127 return 0xffff; /* failure */
128 if (!vhstrlist[index])
129 vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT));
130 vhstrlist[index]->refcount = 1;
131 vhstrlist[index]->pStr = HeapAlloc(heap, 0, strlen(lpszName)+1);
132 strcpy((LPSTR)vhstrlist[index]->pStr, lpszName);
133 return index;
136 /***********************************************************************
137 * vsmStringDelete (SETUPX.206)
139 INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
141 if (VALID_VHSTR(vhstr))
143 vhstrlist[vhstr]->refcount--;
144 if (!vhstrlist[vhstr]->refcount)
146 HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
147 vhstrlist[vhstr]->pStr = NULL;
149 return VCPN_OK;
152 /* string not found */
153 return VCPN_FAIL;
157 * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
159 VHSTR WINAPI vsmStringFind16(LPCSTR lpszName)
161 WORD n;
162 for (n = 0; n < vhstr_alloc; n++)
163 if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName)))
164 return n;
165 return 0xffff;
168 /***********************************************************************
169 * vsmGetStringName (SETUPX.205)
171 * Pretty correct, I guess
173 INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
175 if (VALID_VHSTR(vhstr))
177 int len = strlen(vhstrlist[vhstr]->pStr)+1;
178 if (cbBuffer >= len)
180 if (lpszBuffer)
181 strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
182 return len;
185 return VCPN_FAIL;
188 /***********************************************************************
189 * vsmStringCompare (not exported from a standard SETUPX.DLL, it seems)
191 INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB)
193 if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB)))
194 return VCPN_FAIL; /* correct ? */
195 return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr);
198 /***********************************************************************
199 * vsmGetStringRawName (SETUPX.208)
201 LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
203 return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
207 /***************************** VIRTNODE management ****************************/
208 static LPVIRTNODE *pvnlist = NULL;
209 static DWORD vn_num = 0;
210 static DWORD vn_last = 0;
212 RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
214 HANDLE heap;
215 LPVIRTNODE lpvn;
216 RETERR16 cbres;
218 while (vn_last < vn_num)
220 if (pvnlist[vn_last] == NULL)
221 break;
222 vn_last++;
224 heap = GetProcessHeap();
225 if (vn_last == vn_num)
227 vn_num += 20;
228 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
229 sizeof(LPVIRTNODE *) * vn_num);
231 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
232 lpvn = pvnlist[vn_last];
233 vn_last++;
235 lpvn->cbSize = sizeof(VIRTNODE);
237 if (vfsSrc)
238 memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC));
240 if (vfsDst)
241 memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC));
243 lpvn->fl = fl;
244 lpvn->lParam = lParam;
245 lpvn->lpExpandVtbl = lpExpandVtbl;
247 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
249 cbres = VCP_Callback(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
250 lpvn->fl |= VFNL_CREATED;
251 cbres = VCP_Callback(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);
253 return OK;
256 BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
258 DWORD n;
259 RETERR16 cbres;
261 for (n = 0; n < vn_last; n++)
263 if (pvnlist[n] == lpvnDel)
265 cbres = VCP_Callback(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
266 HeapFree(GetProcessHeap(), 0, lpvnDel);
267 pvnlist[n] = NULL;
268 return TRUE;
271 return FALSE;
274 /***********************************************************************
275 * VcpOpen (SETUPX.200)
277 * Sets up a virtual copy operation.
278 * This means that functions such as GenInstall()
279 * create a VIRTNODE struct for every file to be touched in a .INF file
280 * instead of actually touching the file.
281 * The actual copy/move/rename gets started when VcpClose or
282 * VcpFlush is called; several different callbacks are made
283 * (copy, rename, open, close, version conflicts, ...) on every file copied.
285 RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
287 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
288 if (VCP_opened)
289 return ERR_VCP_BUSY;
291 VCP_Proc = (FARPROC16)vifproc;
292 VCP_MsgRef = lparamMsgRef;
294 /* load SETUPAPI needed for dialog resources etc. */
295 SETUPAPI_hInstance = LoadLibraryA("setupapi.dll");
296 if (!SETUPAPI_hInstance)
298 ERR("Could not load sibling setupapi.dll\n");
299 return ERR_VCP_NOMEM;
301 VCP_opened = TRUE;
302 return OK;
305 /***********************************************************************
306 * VcpQueueCopy [SETUPX.13]
308 * lpExpandVtbl seems to be deprecated.
309 * fl are the CNFL_xxx and VNFL_xxx flags.
310 * lParam are the VNLP_xxx flags.
312 RETERR16 WINAPI VcpQueueCopy16(
313 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
314 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
315 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
316 LPEXPANDVTBL lpExpandVtbl,
317 WORD fl, LPARAM lParam
320 VCPFILESPEC vfsSrc, vfsDst;
322 if (!VCP_opened)
323 return ERR_VCP_NOTOPEN;
325 TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
326 lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
328 TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
330 vfsSrc.ldid = ldidSrc;
331 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
332 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
334 vfsDst.ldid = ldidDst;
335 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
336 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
338 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
339 lpExpandVtbl);
342 /***********************************************************************
343 * VcpQueueDelete [SETUPX.17]
345 * Is lParamRef the same as lParam in VcpQueueCopy ?
346 * Damn docu !! Err... which docu ?
348 RETERR16 WINAPI VcpQueueDelete16(
349 LPCSTR lpszDstFileName,
350 LPCSTR lpszDstDir,
351 LOGDISKID16 ldidDst,
352 LPARAM lParamRef
355 VCPFILESPEC vfsDst;
357 if (!VCP_opened)
358 return ERR_VCP_NOTOPEN;
360 vfsDst.ldid = ldidDst;
361 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
362 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
364 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
367 /***********************************************************************
368 * VcpQueueRename [SETUPX.204]
371 RETERR16 WINAPI VcpQueueRename16(
372 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
373 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
374 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
375 LPARAM lParam
378 VCPFILESPEC vfsSrc, vfsDst;
380 if (!VCP_opened)
381 return ERR_VCP_NOTOPEN;
383 vfsSrc.ldid = ldidSrc;
384 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
385 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
387 vfsDst.ldid = ldidDst;
388 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
389 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
391 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
395 /***********************************************************************
396 * VcpEnumFiles (SETUPX.@)
398 INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
400 WORD n;
402 for (n = 0; n < vn_last; n++)
403 vep(pvnlist[n], lParamRef);
405 return 0; /* FIXME: return value ? */
408 /***********************************************************************
409 * VcpExplain (SETUPX.411)
411 LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
413 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
414 buffer[0] = '\0';
415 switch (dwWhat)
417 case VCPEX_SRC_FULL:
418 case VCPEX_DST_FULL:
420 LPVCPFILESPEC lpvfs =
421 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
423 /* if we have an ldid, use it, otherwise use the string */
424 /* from the vhstrlist array */
425 if (lpvfs->ldid != 0xffff)
426 CtlGetLddPath16(lpvfs->ldid, buffer);
427 else
428 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
430 strcat(buffer, "\\");
431 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
433 break;
434 default:
435 FIXME("%ld unimplemented !\n", dwWhat);
436 strcpy(buffer, "Unknown error");
437 break;
439 return buffer;
442 RETERR16 VCP_CheckPaths(void)
444 DWORD n;
445 LPVIRTNODE lpvn;
446 RETERR16 cbres;
448 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
449 for (n = 0; n < vn_num; n++)
451 lpvn = pvnlist[n];
452 if (!lpvn) continue;
453 /* FIXME: check paths of all VIRTNODEs here ! */
454 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
456 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
457 return OK;
460 RETERR16 VCP_CopyFiles(void)
462 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
463 RETERR16 res = OK, cbres;
464 DWORD n;
465 LPVIRTNODE lpvn;
467 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
468 for (n = 0; n < vn_num; n++)
470 lpvn = pvnlist[n];
471 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
472 /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
473 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
474 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
475 /* FIXME: what is this VCPM_VSTATWRITE here for ?
476 * I guess it's to signal successful destination file creation */
477 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
479 /* FIXME: need to do the file copy in small chunks for notifications */
480 TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
481 /* perform the file copy */
482 if (!(CopyFileA(fn_src, fn_dst,
483 (lpvn->fl & VNLP_COPYIFEXISTS) ? FALSE : TRUE )))
485 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
486 res = ERR_VCP_IOFAIL;
489 vcp_status.prgFileRead.dwSoFar++;
490 cbres = VCP_Callback(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
491 vcp_status.prgFileWrite.dwSoFar++;
492 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
495 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
496 return res;
499 /***********************************************************************
500 * VcpFlush - internal (not exported), but documented
502 * VNFL_NOW is used for VcpFlush.
504 RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
506 return OK;
509 /***********************************************************************
510 * VcpClose (SETUPX.201)
512 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
513 * VCPM_VSTATCLOSEEND.
515 * fl gets VCPFL_xxx flags to indicate what to do with the
516 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
518 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
520 RETERR16 res = OK;
521 WORD cbres = VCPN_PROCEED;
523 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
525 /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER
526 * is not set. This is done by VCP_Callback(VCPM_NODECOMPARE) */
528 TRACE("#1\n");
529 memset(&vcp_status, 0, sizeof(VCPSTATUS));
530 /* yes, vcp_status.cbSize is 0 ! */
531 TRACE("#2\n");
532 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
533 TRACE("#3\n");
535 res = VCP_CheckPaths();
536 TRACE("#4\n");
537 if (res != OK)
538 return res; /* is this ok ? */
539 VCP_CopyFiles();
541 TRACE("#5\n");
542 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
543 TRACE("#6\n");
544 VCP_Proc = NULL;
545 FreeLibrary(SETUPAPI_hInstance);
546 VCP_opened = FALSE;
547 return OK;
550 RETERR16 VCP_RenameFiles(void)
552 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
553 RETERR16 res = OK, cbres;
554 DWORD n;
555 LPVIRTNODE lpvn;
557 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
558 for (n = 0; n < vn_num; n++)
560 lpvn = pvnlist[n];
561 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
562 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
563 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
564 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
565 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
566 res = ERR_VCP_IOFAIL;
567 else
568 VCP_VirtnodeDelete(lpvn);
570 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
571 return res;
574 /***********************************************************************
575 * vcpDefCallbackProc (SETUPX.202)
577 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
578 LPARAM lParam, LPARAM lParamRef)
580 static int count = 0;
581 if (count < 10)
582 FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
583 lpvObj, uMsg, wParam, lParam, lParamRef);
584 count++;
585 return OK;
588 /********************* point-and-click stuff from here ***********************/
590 static HWND hDlgCopy = 0;
591 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
592 static char BackupDir[12];
594 static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
596 INT_PTR retval = FALSE;
598 if (iMsg == WM_INITDIALOG)
600 ShowWindow(hWndDlg, SW_SHOWNORMAL);
601 UpdateWindow(hWndDlg);
602 retval = TRUE;
604 return retval;
607 BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
609 HRSRC hResInfo;
610 HGLOBAL hDlgTmpl32;
612 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), RT_DIALOGA)))
613 return FALSE;
614 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
615 !(*template32 = LockResource( hDlgTmpl32 )))
616 return FALSE;
617 return TRUE;
620 static LRESULT WINAPI
621 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
623 if (uMsg != WM_CREATE)
624 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
626 switch (uMsg)
628 case WM_CREATE:
629 return 0;
630 default:
631 FIXME("%04x: unhandled.\n", uMsg);
634 return 0;
637 void VCP_UI_RegisterProgressClass(void)
639 static BOOL registered = FALSE;
640 WNDCLASSA wndClass;
642 if (registered)
643 return;
645 registered = TRUE;
646 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
647 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
648 wndClass.lpfnWndProc = (WNDPROC)VCP_UI_FileCopyWndProc;
649 wndClass.cbClsExtra = 0;
650 wndClass.cbWndExtra = 0;
651 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
652 wndClass.hbrBackground = NULL;
653 wndClass.lpszClassName = "setupx_progress";
655 RegisterClassA (&wndClass);
658 RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
660 LPCSTR file1, file2;
661 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
662 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
663 return (RETERR16)strcmp(file1, file2);
666 RETERR16 VCP_UI_CopyStart(void)
668 LPCVOID template32;
669 char buf[256]; /* plenty */
670 BOOL dirty;
671 DWORD len;
673 /* FIXME: should be registered at DLL startup instead */
674 VCP_UI_RegisterProgressClass();
675 if (!(VCP_UI_GetDialogTemplate(&template32)))
676 return VCPN_FAIL;
678 if (vn_num > 10) /* hack */
680 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
681 VCP_UI_FileCopyDlgProc, 0);
682 if (!hDlgCopy)
683 return VCPN_FAIL;
684 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
685 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
687 strcpy(buf, REG_INSTALLEDFILES);
688 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
689 return VCPN_FAIL;
690 strcat(buf, REGPART_RENAME);
691 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
692 return VCPN_FAIL;
693 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
694 return VCPN_FAIL;
695 len = 1;
696 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
698 /* FIXME: what does SETUPX.DLL do in this case ? */
699 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
700 return VCPN_FAIL;
702 dirty = TRUE;
703 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
704 return VCPN_FAIL;
705 len = 12;
706 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len)))
707 strcpy(BackupDir, "VCM");
709 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
710 GetWindowsDirectoryA(buf, 256);
711 strcat(buf, "\\");
712 strcat(buf, BackupDir);
713 if (!(CreateDirectoryA(buf, NULL)))
714 return VCPN_FAIL;
715 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
716 return VCPN_FAIL;
717 RegCloseKey(hKeyConflict);
719 return VCPN_OK;
722 /***********************************************************************
723 * vcpUICallbackProc (SETUPX.213)
725 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
726 LPARAM lParam, LPARAM lParamRef)
728 static int count = 0;
729 RETERR16 res = VCPN_OK, cbres;
731 if (count < 5)
732 FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n",
733 lpvObj, uMsg, wParam, lParam, lParamRef);
734 count++;
735 switch (uMsg)
737 /* unused messages, it seems */
738 case VCPM_DISKPREPINFO:
740 case VCPM_FILENEEDED:
742 case VCPM_NODECREATE:
743 case VCPM_NODEACCEPT:
745 case VCPM_VSTATCLOSESTART:
746 case VCPM_VSTATPATHCHECKSTART:
747 case VCPM_VSTATPATHCHECKEND:
749 case VCPM_CHECKPATH:
750 break;
752 /* the real stuff */
753 case VCPM_NODECOMPARE:
754 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
755 break;
756 case VCPM_VSTATREAD:
757 break;
758 case VCPM_VSTATWRITE:
759 cbres = VCP_Callback(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
760 break;
761 case VCPM_VSTATCLOSEEND:
762 RegCloseKey(hKeyFiles);
763 RegCloseKey(hKeyRename);
764 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
765 break;
766 case VCPM_VSTATCOPYSTART:
767 res = VCP_UI_CopyStart();
768 break;
769 case VCPM_VSTATCOPYEND:
770 if (hDlgCopy) DestroyWindow(hDlgCopy);
771 break;
772 default:
773 FIXME("unhandled msg 0x%04x\n", uMsg);
775 return res;