msacm: Fix acmMetrics(ACM_METRIC_DRIVER_PRIORITY) return on error.
[wine/multimedia.git] / dlls / setupapi / virtcopy.c
blobc506f4a8239b4f7aece372079734902418b23b51
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 static 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 #if 0
270 static BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
272 DWORD n;
273 RETERR16 cbres;
275 for (n = 0; n < vn_last; n++)
277 if (pvnlist[n] == lpvnDel)
279 cbres = VCP_Callback(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
280 HeapFree(GetProcessHeap(), 0, lpvnDel);
281 pvnlist[n] = NULL;
282 return TRUE;
285 return FALSE;
287 #endif
289 /***********************************************************************
290 * VcpOpen (SETUPX.200)
292 * Sets up a virtual copy operation.
293 * This means that functions such as GenInstall()
294 * create a VIRTNODE struct for every file to be touched in a .INF file
295 * instead of actually touching the file.
296 * The actual copy/move/rename gets started when VcpClose or
297 * VcpFlush is called; several different callbacks are made
298 * (copy, rename, open, close, version conflicts, ...) on every file copied.
300 RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
302 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
303 if (VCP_opened)
304 return ERR_VCP_BUSY;
306 VCP_Proc = (FARPROC16)vifproc;
307 VCP_MsgRef = lparamMsgRef;
309 /* load SETUPAPI needed for dialog resources etc. */
310 SETUPAPI_hInstance = GetModuleHandleA("setupapi.dll");
311 if (!SETUPAPI_hInstance)
313 ERR("Could not load sibling setupapi.dll\n");
314 return ERR_VCP_NOMEM;
316 VCP_opened = TRUE;
317 return OK;
320 /***********************************************************************
321 * VcpQueueCopy [SETUPX.13]
323 * lpExpandVtbl seems to be deprecated.
324 * fl are the CNFL_xxx and VNFL_xxx flags.
325 * lParam are the VNLP_xxx flags.
327 RETERR16 WINAPI VcpQueueCopy16(
328 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
329 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
330 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
331 LPEXPANDVTBL lpExpandVtbl,
332 WORD fl, LPARAM lParam
335 VCPFILESPEC vfsSrc, vfsDst;
337 if (!VCP_opened)
338 return ERR_VCP_NOTOPEN;
340 TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
341 lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
343 TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
345 vfsSrc.ldid = ldidSrc;
346 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
347 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
349 vfsDst.ldid = ldidDst;
350 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
351 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
353 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
354 lpExpandVtbl);
357 /***********************************************************************
358 * VcpQueueDelete [SETUPX.17]
360 * Is lParamRef the same as lParam in VcpQueueCopy ?
361 * Damn docu !! Err... which docu ?
363 RETERR16 WINAPI VcpQueueDelete16(
364 LPCSTR lpszDstFileName,
365 LPCSTR lpszDstDir,
366 LOGDISKID16 ldidDst,
367 LPARAM lParamRef
370 VCPFILESPEC vfsDst;
372 if (!VCP_opened)
373 return ERR_VCP_NOTOPEN;
375 vfsDst.ldid = ldidDst;
376 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
377 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
379 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
382 /***********************************************************************
383 * VcpQueueRename [SETUPX.204]
386 RETERR16 WINAPI VcpQueueRename16(
387 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
388 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
389 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
390 LPARAM lParam
393 VCPFILESPEC vfsSrc, vfsDst;
395 if (!VCP_opened)
396 return ERR_VCP_NOTOPEN;
398 vfsSrc.ldid = ldidSrc;
399 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
400 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
402 vfsDst.ldid = ldidDst;
403 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
404 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
406 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
410 /***********************************************************************
411 * VcpEnumFiles (SETUPX.@)
413 INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
415 WORD n;
417 for (n = 0; n < vn_last; n++)
418 vep(pvnlist[n], lParamRef);
420 return 0; /* FIXME: return value ? */
423 /***********************************************************************
424 * VcpExplain (SETUPX.411)
426 LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
428 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
429 buffer[0] = '\0';
430 switch (dwWhat)
432 case VCPEX_SRC_FULL:
433 case VCPEX_DST_FULL:
435 LPVCPFILESPEC lpvfs =
436 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
438 /* if we have an ldid, use it, otherwise use the string */
439 /* from the vhstrlist array */
440 if (lpvfs->ldid != 0xffff)
441 CtlGetLddPath16(lpvfs->ldid, buffer);
442 else
443 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
445 strcat(buffer, "\\");
446 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
448 break;
449 default:
450 FIXME("%ld unimplemented !\n", dwWhat);
451 strcpy(buffer, "Unknown error");
452 break;
454 return buffer;
457 static RETERR16 VCP_CheckPaths(void)
459 DWORD n;
460 LPVIRTNODE lpvn;
461 RETERR16 cbres;
463 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
464 for (n = 0; n < vn_num; n++)
466 lpvn = pvnlist[n];
467 if (!lpvn) continue;
468 /* FIXME: check paths of all VIRTNODEs here ! */
469 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
471 cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
472 return OK;
475 static RETERR16 VCP_CopyFiles(void)
477 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
478 RETERR16 res = OK, cbres;
479 DWORD n;
480 LPVIRTNODE lpvn;
482 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
483 for (n = 0; n < vn_num; n++)
485 lpvn = pvnlist[n];
486 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
487 /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
488 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
489 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
490 /* FIXME: what is this VCPM_VSTATWRITE here for ?
491 * I guess it's to signal successful destination file creation */
492 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
494 /* FIXME: need to do the file copy in small chunks for notifications */
495 TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
496 /* perform the file copy */
497 if (!(CopyFileA(fn_src, fn_dst,
498 (lpvn->fl & VNLP_COPYIFEXISTS) ? FALSE : TRUE )))
500 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
501 res = ERR_VCP_IOFAIL;
504 vcp_status.prgFileRead.dwSoFar++;
505 cbres = VCP_Callback(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
506 vcp_status.prgFileWrite.dwSoFar++;
507 cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
510 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
511 return res;
514 /***********************************************************************
515 * VcpFlush - internal (not exported), but documented
517 * VNFL_NOW is used for VcpFlush.
519 RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
521 return OK;
524 /***********************************************************************
525 * VcpClose (SETUPX.201)
527 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
528 * VCPM_VSTATCLOSEEND.
530 * fl gets VCPFL_xxx flags to indicate what to do with the
531 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
533 RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
535 RETERR16 res = OK;
536 WORD cbres = VCPN_PROCEED;
538 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
540 /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER
541 * is not set. This is done by VCP_Callback(VCPM_NODECOMPARE) */
543 TRACE("#1\n");
544 memset(&vcp_status, 0, sizeof(VCPSTATUS));
545 /* yes, vcp_status.cbSize is 0 ! */
546 TRACE("#2\n");
547 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
548 TRACE("#3\n");
550 res = VCP_CheckPaths();
551 TRACE("#4\n");
552 if (res != OK)
553 return res; /* is this ok ? */
554 VCP_CopyFiles();
556 TRACE("#5\n");
557 cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
558 TRACE("#6\n");
559 VCP_Proc = NULL;
560 VCP_opened = FALSE;
561 return OK;
564 #if 0
565 static RETERR16 VCP_RenameFiles(void)
567 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
568 RETERR16 res = OK, cbres;
569 DWORD n;
570 LPVIRTNODE lpvn;
572 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
573 for (n = 0; n < vn_num; n++)
575 lpvn = pvnlist[n];
576 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
577 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
578 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
579 cbres = VCP_Callback(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
580 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
581 res = ERR_VCP_IOFAIL;
582 else
583 VCP_VirtnodeDelete(lpvn);
585 cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
586 return res;
588 #endif
590 /***********************************************************************
591 * vcpDefCallbackProc (SETUPX.202)
593 RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
594 LPARAM lParam, LPARAM lParamRef)
596 static int count = 0;
597 if (count < 10)
598 FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
599 lpvObj, uMsg, wParam, lParam, lParamRef);
600 count++;
601 return OK;
604 /********************* point-and-click stuff from here ***********************/
606 static HWND hDlgCopy = 0;
607 static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
608 static char BackupDir[12];
610 static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
612 INT_PTR retval = FALSE;
614 if (iMsg == WM_INITDIALOG)
616 ShowWindow(hWndDlg, SW_SHOWNORMAL);
617 UpdateWindow(hWndDlg);
618 retval = TRUE;
620 return retval;
623 static BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
625 HRSRC hResInfo;
626 HGLOBAL hDlgTmpl32;
628 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), (LPSTR)RT_DIALOG)))
629 return FALSE;
630 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
631 !(*template32 = LockResource( hDlgTmpl32 )))
632 return FALSE;
633 return TRUE;
636 static LRESULT WINAPI
637 VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
639 if (uMsg != WM_CREATE)
640 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
642 switch (uMsg)
644 case WM_CREATE:
645 return 0;
646 default:
647 FIXME("%04x: unhandled.\n", uMsg);
650 return 0;
653 static void VCP_UI_RegisterProgressClass(void)
655 static BOOL registered = FALSE;
656 WNDCLASSA wndClass;
658 if (registered)
659 return;
661 registered = TRUE;
662 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
663 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
664 wndClass.lpfnWndProc = VCP_UI_FileCopyWndProc;
665 wndClass.cbClsExtra = 0;
666 wndClass.cbWndExtra = 0;
667 wndClass.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
668 wndClass.hbrBackground = NULL;
669 wndClass.lpszClassName = "setupx_progress";
671 RegisterClassA (&wndClass);
674 static RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
676 LPCSTR file1, file2;
677 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
678 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
679 return (RETERR16)strcmp(file1, file2);
682 static RETERR16 VCP_UI_CopyStart(void)
684 LPCVOID template32;
685 char buf[256]; /* plenty */
686 BOOL dirty;
687 DWORD len;
689 /* FIXME: should be registered at DLL startup instead */
690 VCP_UI_RegisterProgressClass();
691 if (!(VCP_UI_GetDialogTemplate(&template32)))
692 return VCPN_FAIL;
694 if (vn_num > 10) /* hack */
696 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
697 VCP_UI_FileCopyDlgProc, 0);
698 if (!hDlgCopy)
699 return VCPN_FAIL;
700 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
701 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
703 strcpy(buf, REG_INSTALLEDFILES);
704 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
705 return VCPN_FAIL;
706 strcat(buf, REGPART_RENAME);
707 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
708 return VCPN_FAIL;
709 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
710 return VCPN_FAIL;
711 len = 1;
712 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
714 /* FIXME: what does SETUPX.DLL do in this case ? */
715 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
716 return VCPN_FAIL;
718 dirty = TRUE;
719 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
720 return VCPN_FAIL;
721 len = 12;
722 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, (LPBYTE)BackupDir, &len)))
723 strcpy(BackupDir, "VCM");
725 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
726 GetWindowsDirectoryA(buf, 256);
727 strcat(buf, "\\");
728 strcat(buf, BackupDir);
729 if (!(CreateDirectoryA(buf, NULL)))
730 return VCPN_FAIL;
731 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
732 return VCPN_FAIL;
733 RegCloseKey(hKeyConflict);
735 return VCPN_OK;
738 /***********************************************************************
739 * vcpUICallbackProc (SETUPX.213)
741 RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
742 LPARAM lParam, LPARAM lParamRef)
744 static int count = 0;
745 RETERR16 res = VCPN_OK, cbres;
747 if (count < 5)
748 FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n",
749 lpvObj, uMsg, wParam, lParam, lParamRef);
750 count++;
751 switch (uMsg)
753 /* unused messages, it seems */
754 case VCPM_DISKPREPINFO:
756 case VCPM_FILENEEDED:
758 case VCPM_NODECREATE:
759 case VCPM_NODEACCEPT:
761 case VCPM_VSTATCLOSESTART:
762 case VCPM_VSTATPATHCHECKSTART:
763 case VCPM_VSTATPATHCHECKEND:
765 case VCPM_CHECKPATH:
766 break;
768 /* the real stuff */
769 case VCPM_NODECOMPARE:
770 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
771 break;
772 case VCPM_VSTATREAD:
773 break;
774 case VCPM_VSTATWRITE:
775 cbres = VCP_Callback(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
776 break;
777 case VCPM_VSTATCLOSEEND:
778 RegCloseKey(hKeyFiles);
779 RegCloseKey(hKeyRename);
780 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
781 break;
782 case VCPM_VSTATCOPYSTART:
783 res = VCP_UI_CopyStart();
784 break;
785 case VCPM_VSTATCOPYEND:
786 if (hDlgCopy) DestroyWindow(hDlgCopy);
787 break;
788 default:
789 FIXME("unhandled msg 0x%04x\n", uMsg);
791 return res;