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.
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
)
55 args
[7] = HIWORD(obj
);
56 args
[6] = LOWORD(obj
);
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
);
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 ! :-)
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
)
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
))
106 vhstrlist
[n
]->refcount
++;
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
)))
122 heap
= GetProcessHeap();
123 if (n
== vhstr_alloc
) /* hmm, no free index found yet */
129 vhstrlist
= HeapReAlloc(heap
, HEAP_ZERO_MEMORY
, vhstrlist
,
130 sizeof(VHSTR_STRUCT
*) * vhstr_alloc
);
132 vhstrlist
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
,
133 sizeof(VHSTR_STRUCT
*) * vhstr_alloc
);
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
);
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
;
161 /* string not found */
166 * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
168 VHSTR WINAPI
vsmStringFind16(LPCSTR lpszName
)
171 for (n
= 0; n
< vhstr_alloc
; n
++)
172 if ((vhstrlist
[n
]) && (vhstrlist
[n
]->refcount
) && (!strcmp(vhstrlist
[n
]->pStr
, lpszName
)))
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;
190 strcpy(lpszBuffer
, vhstrlist
[vhstr
]->pStr
);
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
)
227 while (vn_last
< vn_num
)
229 if (pvnlist
[vn_last
] == NULL
)
233 heap
= GetProcessHeap();
234 if (vn_last
== vn_num
)
238 pvnlist
= HeapReAlloc(heap
, HEAP_ZERO_MEMORY
, pvnlist
,
239 sizeof(LPVIRTNODE
*) * vn_num
);
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
];
248 lpvn
->cbSize
= sizeof(VIRTNODE
);
251 memcpy(&lpvn
->vfsSrc
, vfsSrc
, sizeof(VCPFILESPEC
));
254 memcpy(&lpvn
->vfsDst
, vfsDst
, sizeof(VCPFILESPEC
));
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
);
270 static BOOL
VCP_VirtnodeDelete(LPVIRTNODE lpvnDel
)
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
);
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
);
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
;
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
;
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
,
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
,
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
,
393 VCPFILESPEC vfsSrc
, vfsDst
;
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
)
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 ? */
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
);
443 strcat(buffer
, vsmGetStringRawName16(lpvfs
->vhstrDir
));
445 strcat(buffer
, "\\");
446 strcat(buffer
, vsmGetStringRawName16(lpvfs
->vhstrFileName
));
450 FIXME("%ld unimplemented !\n", dwWhat
);
451 strcpy(buffer
, "Unknown error");
457 static RETERR16
VCP_CheckPaths(void)
463 cbres
= VCP_Callback(&vcp_status
, VCPM_VSTATPATHCHECKSTART
, 0, 0, VCP_MsgRef
);
464 for (n
= 0; n
< vn_num
; n
++)
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
);
475 static RETERR16
VCP_CopyFiles(void)
477 char fn_src
[MAX_PATH
], fn_dst
[MAX_PATH
];
478 RETERR16 res
= OK
, cbres
;
482 cbres
= VCP_Callback(&vcp_status
, VCPM_VSTATCOPYSTART
, 0, 0, VCP_MsgRef
);
483 for (n
= 0; n
< vn_num
; 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
);
514 /***********************************************************************
515 * VcpFlush - internal (not exported), but documented
517 * VNFL_NOW is used for VcpFlush.
519 RETERR16
VcpFlush16(WORD fl
, LPCSTR lpszBackupDest
)
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
)
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) */
544 memset(&vcp_status
, 0, sizeof(VCPSTATUS
));
545 /* yes, vcp_status.cbSize is 0 ! */
547 cbres
= VCP_Callback(&vcp_status
, VCPM_VSTATCLOSESTART
, 0, 0, VCP_MsgRef
);
550 res
= VCP_CheckPaths();
553 return res
; /* is this ok ? */
557 cbres
= VCP_Callback(&vcp_status
, VCPM_VSTATCLOSEEND
, 0, 0, VCP_MsgRef
);
565 static RETERR16
VCP_RenameFiles(void)
567 char fn_src
[MAX_PATH
], fn_dst
[MAX_PATH
];
568 RETERR16 res
= OK
, cbres
;
572 cbres
= VCP_Callback(&vcp_status
, VCPM_VSTATRENAMESTART
, 0, 0, VCP_MsgRef
);
573 for (n
= 0; n
< vn_num
; 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
;
583 VCP_VirtnodeDelete(lpvn
);
585 cbres
= VCP_Callback(&vcp_status
, VCPM_VSTATRENAMEEND
, 0, 0, VCP_MsgRef
);
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;
598 FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
599 lpvObj
, uMsg
, wParam
, lParam
, lParamRef
);
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
);
623 static BOOL
VCP_UI_GetDialogTemplate(LPCVOID
*template32
)
628 if (!(hResInfo
= FindResourceA(SETUPAPI_hInstance
, MAKEINTRESOURCEA(COPYFILEDLGORD
), (LPSTR
)RT_DIALOG
)))
630 if (!(hDlgTmpl32
= LoadResource(SETUPAPI_hInstance
, hResInfo
)) ||
631 !(*template32
= LockResource( hDlgTmpl32
)))
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
);
647 FIXME("%04x: unhandled.\n", uMsg
);
653 static void VCP_UI_RegisterProgressClass(void)
655 static BOOL registered
= FALSE
;
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
)
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)
685 char buf
[256]; /* plenty */
689 /* FIXME: should be registered at DLL startup instead */
690 VCP_UI_RegisterProgressClass();
691 if (!(VCP_UI_GetDialogTemplate(&template32
)))
694 if (vn_num
> 10) /* hack */
696 hDlgCopy
= CreateDialogIndirectParamA(SETUPAPI_hInstance
, template32
, 0,
697 VCP_UI_FileCopyDlgProc
, 0);
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
))
706 strcat(buf
, REGPART_RENAME
);
707 if (RegCreateKeyA(HKEY_LOCAL_MACHINE
, buf
, &hKeyRename
))
709 if (RegCreateKeyA(HKEY_LOCAL_MACHINE
, REG_VERSIONCONFLICT
, &hKeyConflict
))
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");
719 if (RegSetValueExA(hKeyConflict
, "Dirty", 0, REG_BINARY
, (LPBYTE
)&dirty
, 1))
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);
728 strcat(buf
, BackupDir
);
729 if (!(CreateDirectoryA(buf
, NULL
)))
731 if (RegSetValueExA(hKeyConflict
, "BackupDirectory", 0, REG_SZ
, (LPBYTE
)buf
, strlen(buf
)+1))
733 RegCloseKey(hKeyConflict
);
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
;
748 FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n",
749 lpvObj
, uMsg
, wParam
, lParam
, lParamRef
);
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
:
769 case VCPM_NODECOMPARE
:
770 res
= VCP_UI_NodeCompare((LPVIRTNODE
)lpvObj
, (LPVIRTNODE
)lParam
);
774 case VCPM_VSTATWRITE
:
775 cbres
= VCP_Callback(&vcp_status
, VCPM_DISKPREPINFO
, 0, 0, VCP_MsgRef
);
777 case VCPM_VSTATCLOSEEND
:
778 RegCloseKey(hKeyFiles
);
779 RegCloseKey(hKeyRename
);
780 RegDeleteKeyA(HKEY_LOCAL_MACHINE
, REG_VERSIONCONFLICT
);
782 case VCPM_VSTATCOPYSTART
:
783 res
= VCP_UI_CopyStart();
785 case VCPM_VSTATCOPYEND
:
786 if (hDlgCopy
) DestroyWindow(hDlgCopy
);
789 FIXME("unhandled msg 0x%04x\n", uMsg
);