Silence one FIXME(). Implement ITypeInfo::GetDocumentation for
[wine.git] / dlls / setupapi / virtcopy.c
blobdd91bec04b3a74351f910517263c5e08f3dbb533
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,
471 (lpvn->fl & VNLP_COPYIFEXISTS) ? FALSE : TRUE )))
473 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
474 res = ERR_VCP_IOFAIL;
477 vcp_status.prgFileRead.dwSoFar++;
478 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
479 vcp_status.prgFileWrite.dwSoFar++;
480 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
483 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
484 return res;
487 /***********************************************************************
488 * VcpFlush - internal (not exported), but documented
490 * VNFL_NOW is used for VcpFlush.
492 RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
494 return OK;
497 /***********************************************************************
498 * VcpClose (SETUPX.201)
500 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
501 * VCPM_VSTATCLOSEEND.
503 * fl gets VCPFL_xxx flags to indicate what to do with the
504 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
506 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
508 RETERR16 res = OK;
509 WORD cbres = VCPN_PROCEED;
511 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
513 /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER
514 * is not set. This is done by VCP_CALLBACK(VCPM_NODECOMPARE) */
516 TRACE("#1\n");
517 memset(&vcp_status, 0, sizeof(VCPSTATUS));
518 /* yes, vcp_status.cbSize is 0 ! */
519 TRACE("#2\n");
520 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
521 TRACE("#3\n");
523 res = VCP_CheckPaths();
524 TRACE("#4\n");
525 if (res != OK)
526 return res; /* is this ok ? */
527 VCP_CopyFiles();
529 TRACE("#5\n");
530 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
531 TRACE("#6\n");
532 VCP_Proc = NULL;
533 FreeLibrary(SETUPAPI_hInstance);
534 VCP_opened = FALSE;
535 return OK;
538 RETERR16 VCP_RenameFiles(void)
540 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
541 RETERR16 res = OK, cbres;
542 DWORD n;
543 LPVIRTNODE lpvn;
545 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
546 for (n = 0; n < vn_num; n++)
548 lpvn = pvnlist[n];
549 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
550 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
551 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
552 cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
553 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
554 res = ERR_VCP_IOFAIL;
555 else
556 VCP_VirtnodeDelete(lpvn);
558 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
559 return res;
562 /***********************************************************************
563 * vcpDefCallbackProc (SETUPX.202)
565 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
566 LPARAM lParam, LPARAM lParamRef)
568 static int count = 0;
569 if (count < 10)
570 FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
571 lpvObj, uMsg, wParam, lParam, lParamRef);
572 count++;
573 return OK;
576 /********************* point-and-click stuff from here ***********************/
578 static HWND hDlgCopy = 0;
579 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
580 static char BackupDir[12];
582 static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
584 INT_PTR retval = FALSE;
586 if (iMsg == WM_INITDIALOG)
588 ShowWindow(hWndDlg, SW_SHOWNORMAL);
589 UpdateWindow(hWndDlg);
590 retval = TRUE;
592 return retval;
595 BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
597 HRSRC hResInfo;
598 HGLOBAL hDlgTmpl32;
600 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), RT_DIALOGA)))
601 return FALSE;
602 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
603 !(*template32 = LockResource( hDlgTmpl32 )))
604 return FALSE;
605 return TRUE;
608 static LRESULT WINAPI
609 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
611 if (uMsg != WM_CREATE)
612 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
614 switch (uMsg)
616 case WM_CREATE:
617 return 0;
618 default:
619 FIXME("%04x: unhandled.\n", uMsg);
622 return 0;
625 void VCP_UI_RegisterProgressClass(void)
627 static BOOL registered = FALSE;
628 WNDCLASSA wndClass;
630 if (registered)
631 return;
633 registered = TRUE;
634 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
635 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
636 wndClass.lpfnWndProc = (WNDPROC)VCP_UI_FileCopyWndProc;
637 wndClass.cbClsExtra = 0;
638 wndClass.cbWndExtra = 0;
639 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
640 wndClass.hbrBackground = (HBRUSH)NULL;
641 wndClass.lpszClassName = "setupx_progress";
643 RegisterClassA (&wndClass);
646 RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
648 LPCSTR file1, file2;
649 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
650 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
651 return (RETERR16)strcmp(file1, file2);
654 RETERR16 VCP_UI_CopyStart(void)
656 LPCVOID template32;
657 char buf[256]; /* plenty */
658 BOOL dirty;
659 DWORD len;
661 /* FIXME: should be registered at DLL startup instead */
662 VCP_UI_RegisterProgressClass();
663 if (!(VCP_UI_GetDialogTemplate(&template32)))
664 return VCPN_FAIL;
666 if (vn_num > 10) /* hack */
668 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
669 VCP_UI_FileCopyDlgProc, 0);
670 if (!hDlgCopy)
671 return VCPN_FAIL;
672 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
673 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
675 strcpy(buf, REG_INSTALLEDFILES);
676 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
677 return VCPN_FAIL;
678 strcat(buf, REGPART_RENAME);
679 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
680 return VCPN_FAIL;
681 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
682 return VCPN_FAIL;
683 len = 1;
684 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
686 /* FIXME: what does SETUPX.DLL do in this case ? */
687 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
688 return VCPN_FAIL;
690 dirty = TRUE;
691 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
692 return VCPN_FAIL;
693 len = 12;
694 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len)))
695 strcpy(BackupDir, "VCM");
697 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
698 GetWindowsDirectoryA(buf, 256);
699 strcat(buf, "\\");
700 strcat(buf, BackupDir);
701 if (!(CreateDirectoryA(buf, NULL)))
702 return VCPN_FAIL;
703 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
704 return VCPN_FAIL;
705 RegCloseKey(hKeyConflict);
707 return VCPN_OK;
710 /***********************************************************************
711 * vcpUICallbackProc (SETUPX.213)
713 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
714 LPARAM lParam, LPARAM lParamRef)
716 static int count = 0;
717 RETERR16 res = VCPN_OK, cbres;
719 if (count < 5)
720 FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n",
721 lpvObj, uMsg, wParam, lParam, lParamRef);
722 count++;
723 switch (uMsg)
725 /* unused messages, it seems */
726 case VCPM_DISKPREPINFO:
728 case VCPM_FILENEEDED:
730 case VCPM_NODECREATE:
731 case VCPM_NODEACCEPT:
733 case VCPM_VSTATCLOSESTART:
734 case VCPM_VSTATPATHCHECKSTART:
735 case VCPM_VSTATPATHCHECKEND:
737 case VCPM_CHECKPATH:
738 break;
740 /* the real stuff */
741 case VCPM_NODECOMPARE:
742 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
743 break;
744 case VCPM_VSTATREAD:
745 break;
746 case VCPM_VSTATWRITE:
747 cbres = VCP_CALLBACK(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
748 break;
749 case VCPM_VSTATCLOSEEND:
750 RegCloseKey(hKeyFiles);
751 RegCloseKey(hKeyRename);
752 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
753 break;
754 case VCPM_VSTATCOPYSTART:
755 res = VCP_UI_CopyStart();
756 break;
757 case VCPM_VSTATCOPYEND:
758 if (hDlgCopy) DestroyWindow(hDlgCopy);
759 break;
760 default:
761 FIXME("unhandled msg 0x%04x\n", uMsg);
763 return res;