source: trunk/src/setupapi/virtcopy.c@ 8667

Last change on this file since 8667 was 8667, checked in by sandervl, 23 years ago

wine update

File size: 21.0 KB
Line 
1/*
2 * SetupAPI virtual copy operations
3 *
4 * Copyright 2001 Andreas Mohr
5 *
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.
10 *
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.
15 *
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
19 *
20 * FIXME: we now rely on builtin setupapi.dll for dialog resources.
21 * This is bad ! We ought to have 16bit resource handling working.
22 */
23
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"
32
33WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
34
35/* ### start build ### */
36extern WORD CALLBACK VCP_CallTo16_word_lwwll(FARPROC16,LPVOID,UINT16,WPARAM,LPARAM,LPARAM);
37/* ### stop build ### */
38
39static FARPROC16 VCP_Proc = NULL;
40static LPARAM VCP_MsgRef = 0;
41
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;
45
46static BOOL VCP_opened = FALSE;
47
48static VCPSTATUS vcp_status;
49
50static HINSTANCE SETUPAPI_hInstance;
51
52/****************************** VHSTR management ******************************/
53
54/*
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 ! :-)
59 */
60typedef struct {
61 DWORD refcount;
62 LPCSTR pStr;
63} VHSTR_STRUCT;
64
65static VHSTR_STRUCT **vhstrlist = NULL;
66static VHSTR vhstr_alloc = 0;
67
68#define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount))
69
70/***********************************************************************
71 * vsmStringAdd (SETUPX.207)
72 */
73VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName)
74{
75 VHSTR n;
76 VHSTR index = 0xffff;
77 HANDLE heap;
78
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++)
83 {
84 if ((vhstrlist[n]) && (vhstrlist[n]->refcount))
85 {
86 TRACE("checking item: %d\n", n);
87 if (!strcmp(vhstrlist[n]->pStr, lpszName))
88 {
89 TRACE("found\n");
90 vhstrlist[n]->refcount++;
91 return n;
92 }
93 }
94 }
95
96 /* hmm, not found yet, let's insert it */
97 TRACE("inserting item\n");
98 for (n = 0; n < vhstr_alloc; n++)
99 {
100 if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount)))
101 {
102 index = n;
103 break;
104 }
105 }
106 heap = GetProcessHeap();
107 if (n == vhstr_alloc) /* hmm, no free index found yet */
108 {
109 index = vhstr_alloc;
110 vhstr_alloc += 20;
111 vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
112 sizeof(VHSTR_STRUCT *) * vhstr_alloc);
113 }
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;
122}
123
124/***********************************************************************
125 * vsmStringDelete (SETUPX.206)
126 */
127INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
128{
129 if (VALID_VHSTR(vhstr))
130 {
131 vhstrlist[vhstr]->refcount--;
132 if (!vhstrlist[vhstr]->refcount)
133 {
134 HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
135 vhstrlist[vhstr]->pStr = NULL;
136 }
137 return VCPN_OK;
138 }
139
140 /* string not found */
141 return VCPN_FAIL;
142}
143
144/*
145 * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
146 */
147VHSTR WINAPI vsmStringFind16(LPCSTR lpszName)
148{
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;
154}
155
156/***********************************************************************
157 * vsmGetStringName (SETUPX.205)
158 *
159 * Pretty correct, I guess
160 */
161INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
162{
163 if (VALID_VHSTR(vhstr))
164 {
165 int len = strlen(vhstrlist[vhstr]->pStr)+1;
166 if (cbBuffer >= len)
167 {
168 if (lpszBuffer)
169 strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
170 return len;
171 }
172 }
173 return VCPN_FAIL;
174}
175
176/***********************************************************************
177 * vsmStringCompare (not exported from a standard SETUPX.DLL, it seems)
178 */
179INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB)
180{
181 if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB)))
182 return VCPN_FAIL; /* correct ? */
183 return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr);
184}
185
186/***********************************************************************
187 * vsmGetStringRawName (SETUPX.208)
188 */
189LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
190{
191 return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
192}
193
194
195/***************************** VIRTNODE management ****************************/
196static LPVIRTNODE *pvnlist = NULL;
197static DWORD vn_num = 0;
198static DWORD vn_last = 0;
199
200RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
201{
202 HANDLE heap;
203 LPVIRTNODE lpvn;
204 RETERR16 cbres;
205
206 while (vn_last < vn_num)
207 {
208 if (pvnlist[vn_last] == NULL)
209 break;
210 vn_last++;
211 }
212 heap = GetProcessHeap();
213 if (vn_last == vn_num)
214 {
215 vn_num += 20;
216 pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
217 sizeof(LPVIRTNODE *) * vn_num);
218 }
219 pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
220 lpvn = pvnlist[vn_last];
221 vn_last++;
222
223 lpvn->cbSize = sizeof(VIRTNODE);
224
225 if (vfsSrc)
226 memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC));
227
228 if (vfsDst)
229 memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC));
230
231 lpvn->fl = fl;
232 lpvn->lParam = lParam;
233 lpvn->lpExpandVtbl = lpExpandVtbl;
234
235 lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
236
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);
240
241 return OK;
242}
243
244BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
245{
246 DWORD n;
247 RETERR16 cbres;
248
249 for (n = 0; n < vn_last; n++)
250 {
251 if (pvnlist[n] == lpvnDel)
252 {
253 cbres = VCP_CALLBACK(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
254 HeapFree(GetProcessHeap(), 0, lpvnDel);
255 pvnlist[n] = NULL;
256 return TRUE;
257 }
258 }
259 return FALSE;
260}
261
262/***********************************************************************
263 * VcpOpen (SETUPX.200)
264 *
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.
272 */
273RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
274{
275 TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
276 if (VCP_opened)
277 return ERR_VCP_BUSY;
278
279 VCP_Proc = (FARPROC16)vifproc;
280 VCP_MsgRef = lparamMsgRef;
281
282 /* load SETUPAPI needed for dialog resources etc. */
283 SETUPAPI_hInstance = LoadLibraryA("setupapi.dll");
284 if (!SETUPAPI_hInstance)
285 {
286 ERR("Could not load sibling setupapi.dll\n");
287 return ERR_VCP_NOMEM;
288 }
289 VCP_opened = TRUE;
290 return OK;
291}
292
293/***********************************************************************
294 * VcpQueueCopy [SETUPX.13]
295 *
296 * lpExpandVtbl seems to be deprecated.
297 * fl are the CNFL_xxx and VNFL_xxx flags.
298 * lParam are the VNLP_xxx flags.
299 */
300RETERR16 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
306)
307{
308 VCPFILESPEC vfsSrc, vfsDst;
309
310 if (!VCP_opened)
311 return ERR_VCP_NOTOPEN;
312
313 TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
314 lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
315
316 TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
317
318 vfsSrc.ldid = ldidSrc;
319 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
320 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
321
322 vfsDst.ldid = ldidDst;
323 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
324 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
325
326 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
327 lpExpandVtbl);
328}
329
330/***********************************************************************
331 * VcpQueueDelete [SETUPX.17]
332 *
333 * Is lParamRef the same as lParam in VcpQueueCopy ?
334 * Damn docu !! Err... which docu ?
335 */
336RETERR16 WINAPI VcpQueueDelete16(
337 LPCSTR lpszDstFileName,
338 LPCSTR lpszDstDir,
339 LOGDISKID16 ldidDst,
340 LPARAM lParamRef
341)
342{
343 VCPFILESPEC vfsDst;
344
345 if (!VCP_opened)
346 return ERR_VCP_NOTOPEN;
347
348 vfsDst.ldid = ldidDst;
349 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
350 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
351
352 return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
353}
354
355/***********************************************************************
356 * VcpQueueRename [SETUPX.204]
357 *
358 */
359RETERR16 WINAPI VcpQueueRename16(
360 LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
361 LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
362 LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
363 LPARAM lParam
364)
365{
366 VCPFILESPEC vfsSrc, vfsDst;
367
368 if (!VCP_opened)
369 return ERR_VCP_NOTOPEN;
370
371 vfsSrc.ldid = ldidSrc;
372 vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
373 vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
374
375 vfsDst.ldid = ldidDst;
376 vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
377 vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
378
379 return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
380 0);
381}
382
383/***********************************************************************
384 * VcpEnumFiles (SETUPX.@)
385 */
386INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
387{
388 WORD n;
389
390 for (n = 0; n < vn_last; n++)
391 vep(pvnlist[n], lParamRef);
392
393 return 0; /* FIXME: return value ? */
394}
395
396/***********************************************************************
397 * VcpExplain (SETUPX.411)
398 */
399LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
400{
401 static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
402 buffer[0] = '\0';
403 switch (dwWhat)
404 {
405 case VCPEX_SRC_FULL:
406 case VCPEX_DST_FULL:
407 {
408 LPVCPFILESPEC lpvfs =
409 (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
410
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));
417
418 strcat(buffer, "\\");
419 strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
420 }
421 break;
422 default:
423 FIXME("%ld unimplemented !\n", dwWhat);
424 strcpy(buffer, "Unknown error");
425 break;
426 }
427 return buffer;
428}
429
430RETERR16 VCP_CheckPaths(void)
431{
432 DWORD n;
433 LPVIRTNODE lpvn;
434 RETERR16 cbres;
435
436 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
437 for (n = 0; n < vn_num; n++)
438 {
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);
443 }
444 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
445 return OK;
446}
447
448RETERR16 VCP_CopyFiles(void)
449{
450 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
451 RETERR16 res = OK, cbres;
452 DWORD n;
453 LPVIRTNODE lpvn;
454
455 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
456 for (n = 0; n < vn_num; n++)
457 {
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);
466
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, TRUE)))
471 {
472 ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
473 res = ERR_VCP_IOFAIL;
474 }
475
476 vcp_status.prgFileRead.dwSoFar++;
477 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
478 vcp_status.prgFileWrite.dwSoFar++;
479 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
480 }
481
482 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
483 return res;
484}
485
486/***********************************************************************
487 * VcpFlush - internal (not exported), but documented
488 *
489 * VNFL_NOW is used for VcpFlush.
490 */
491RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
492{
493 return OK;
494}
495
496/***********************************************************************
497 * VcpClose (SETUPX.201)
498 *
499 * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
500 * VCPM_VSTATCLOSEEND.
501 *
502 * fl gets VCPFL_xxx flags to indicate what to do with the
503 * VIRTNODEs (files to mess with) created by e.g. GenInstall()
504 */
505RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
506{
507 RETERR16 res = OK;
508 WORD cbres = VCPN_PROCEED;
509
510 TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
511
512 /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER
513 * is not set. This is done by VCP_CALLBACK(VCPM_NODECOMPARE) */
514
515 TRACE("#1\n");
516 memset(&vcp_status, 0, sizeof(VCPSTATUS));
517 /* yes, vcp_status.cbSize is 0 ! */
518 TRACE("#2\n");
519 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
520 TRACE("#3\n");
521
522 res = VCP_CheckPaths();
523 TRACE("#4\n");
524 if (res != OK)
525 return res; /* is this ok ? */
526 VCP_CopyFiles();
527
528 TRACE("#5\n");
529 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
530 TRACE("#6\n");
531 VCP_Proc = NULL;
532 FreeLibrary(SETUPAPI_hInstance);
533 VCP_opened = FALSE;
534 return OK;
535}
536
537RETERR16 VCP_RenameFiles(void)
538{
539 char fn_src[MAX_PATH], fn_dst[MAX_PATH];
540 RETERR16 res = OK, cbres;
541 DWORD n;
542 LPVIRTNODE lpvn;
543
544 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
545 for (n = 0; n < vn_num; n++)
546 {
547 lpvn = pvnlist[n];
548 if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
549 strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
550 strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
551 cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
552 if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
553 res = ERR_VCP_IOFAIL;
554 else
555 VCP_VirtnodeDelete(lpvn);
556 }
557 cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
558 return res;
559}
560
561/***********************************************************************
562 * vcpDefCallbackProc (SETUPX.202)
563 */
564RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
565 LPARAM lParam, LPARAM lParamRef)
566{
567 static int count = 0;
568 if (count < 10)
569 FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
570 lpvObj, uMsg, wParam, lParam, lParamRef);
571 count++;
572 return OK;
573}
574
575/********************* point-and-click stuff from here ***********************/
576
577static HWND hDlgCopy = 0;
578static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
579static char BackupDir[12];
580
581static BOOL CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
582{
583 BOOL retval = FALSE;
584
585 if (iMsg == WM_INITDIALOG)
586 {
587 ShowWindow(hWndDlg, SW_SHOWNORMAL);
588 UpdateWindow(hWndDlg);
589 retval = TRUE;
590 }
591 return retval;
592}
593
594BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
595{
596 HANDLE hResInfo, hDlgTmpl32;
597
598 if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), RT_DIALOGA)))
599 return FALSE;
600 if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
601 !(*template32 = LockResource( hDlgTmpl32 )))
602 return FALSE;
603 return TRUE;
604}
605
606static LRESULT WINAPI
607VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
608{
609 if (uMsg != WM_CREATE)
610 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
611
612 switch (uMsg)
613 {
614 case WM_CREATE:
615 return 0;
616 default:
617 FIXME("%04x: unhandled.\n", uMsg);
618 }
619
620 return 0;
621}
622
623void VCP_UI_RegisterProgressClass(void)
624{
625 static BOOL registered = FALSE;
626 WNDCLASSA wndClass;
627
628 if (registered)
629 return;
630
631 registered = TRUE;
632 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
633 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
634 wndClass.lpfnWndProc = (WNDPROC)VCP_UI_FileCopyWndProc;
635 wndClass.cbClsExtra = 0;
636 wndClass.cbWndExtra = 0;
637 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
638 wndClass.hbrBackground = (HBRUSH)NULL;
639 wndClass.lpszClassName = "setupx_progress";
640
641 RegisterClassA (&wndClass);
642}
643
644RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
645{
646 LPCSTR file1, file2;
647 file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
648 file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
649 return (RETERR16)strcmp(file1, file2);
650}
651
652RETERR16 VCP_UI_CopyStart(void)
653{
654 LPCVOID template32;
655 char buf[256]; /* plenty */
656 BOOL dirty;
657 DWORD len;
658
659 /* FIXME: should be registered at DLL startup instead */
660 VCP_UI_RegisterProgressClass();
661 if (!(VCP_UI_GetDialogTemplate(&template32)))
662 return VCPN_FAIL;
663
664 if (vn_num > 10) /* hack */
665 {
666 hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
667 VCP_UI_FileCopyDlgProc, 0);
668 if (!hDlgCopy)
669 return VCPN_FAIL;
670 SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
671 SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
672 }
673 strcpy(buf, REG_INSTALLEDFILES);
674 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
675 return VCPN_FAIL;
676 strcat(buf, REGPART_RENAME);
677 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
678 return VCPN_FAIL;
679 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
680 return VCPN_FAIL;
681 len = 1;
682 if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
683 {
684 /* FIXME: what does SETUPX.DLL do in this case ? */
685 MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
686 return VCPN_FAIL;
687 }
688 dirty = TRUE;
689 if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
690 return VCPN_FAIL;
691 len = 12;
692 if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len)))
693 strcpy(BackupDir, "VCM");
694
695 /* create C:\WINDOWS\[BackupDir] and set registry key to it */
696 GetWindowsDirectoryA(buf, 256);
697 strcat(buf, "\\");
698 strcat(buf, BackupDir);
699 if (!(CreateDirectoryA(buf, NULL)))
700 return VCPN_FAIL;
701 if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
702 return VCPN_FAIL;
703 RegCloseKey(hKeyConflict);
704
705 return VCPN_OK;
706}
707
708/***********************************************************************
709 * vcpUICallbackProc (SETUPX.213)
710 */
711RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
712 LPARAM lParam, LPARAM lParamRef)
713{
714 static int count = 0;
715 RETERR16 res = VCPN_OK, cbres;
716
717 if (count < 5)
718 FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n",
719 lpvObj, uMsg, wParam, lParam, lParamRef);
720 count++;
721 switch (uMsg)
722 {
723 /* unused messages, it seems */
724 case VCPM_DISKPREPINFO:
725
726 case VCPM_FILENEEDED:
727
728 case VCPM_NODECREATE:
729 case VCPM_NODEACCEPT:
730
731 case VCPM_VSTATCLOSESTART:
732 case VCPM_VSTATPATHCHECKSTART:
733 case VCPM_VSTATPATHCHECKEND:
734
735 case VCPM_CHECKPATH:
736 break;
737
738 /* the real stuff */
739 case VCPM_NODECOMPARE:
740 res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
741 break;
742 case VCPM_VSTATREAD:
743 break;
744 case VCPM_VSTATWRITE:
745 cbres = VCP_CALLBACK(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
746 break;
747 case VCPM_VSTATCLOSEEND:
748 RegCloseKey(hKeyFiles);
749 RegCloseKey(hKeyRename);
750 RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
751 break;
752 case VCPM_VSTATCOPYSTART:
753 res = VCP_UI_CopyStart();
754 break;
755 case VCPM_VSTATCOPYEND:
756 if (hDlgCopy) DestroyWindow(hDlgCopy);
757 break;
758 default:
759 FIXME("unhandled msg 0x%04x\n", uMsg);
760 }
761 return res;
762}
Note: See TracBrowser for help on using the repository browser.