diff --git a/dlls/setupapi/.cvsignore b/dlls/setupapi/.cvsignore index c58213593e6..8df8ae4642b 100644 --- a/dlls/setupapi/.cvsignore +++ b/dlls/setupapi/.cvsignore @@ -1,3 +1,5 @@ Makefile +setupapi.res setupapi.spec.c setupx.spec.c +virtcopy.glue.c diff --git a/dlls/setupapi/Makefile.in b/dlls/setupapi/Makefile.in index f2524b8e0c5..a77c8066c18 100644 --- a/dlls/setupapi/Makefile.in +++ b/dlls/setupapi/Makefile.in @@ -13,7 +13,14 @@ C_SRCS = \ devinst.c \ infparse.c \ setupx_main.c \ - stubs.c + stubs.c \ + virtcopy.c + +GLUE = \ + virtcopy.c + +RC_SRCS= \ + setupapi.rc @MAKE_DLL_RULES@ diff --git a/dlls/setupapi/infparse.c b/dlls/setupapi/infparse.c index 26b97b97f3c..2582dff5d71 100644 --- a/dlls/setupapi/infparse.c +++ b/dlls/setupapi/infparse.c @@ -16,9 +16,9 @@ #include "heap.h" #include "wine/winbase16.h" #include "setupx16.h" -#include "setupx_private.h" +#include "setupapi_private.h" -DEFAULT_DEBUG_CHANNEL(setupx); +DEFAULT_DEBUG_CHANNEL(setupapi); WORD InfNumEntries = 0; INF_FILE *InfList = NULL; diff --git a/dlls/setupapi/setupapi.rc b/dlls/setupapi/setupapi.rc new file mode 100644 index 00000000000..5bc79e28205 --- /dev/null +++ b/dlls/setupapi/setupapi.rc @@ -0,0 +1,34 @@ +/* + * Top level resource file for SETUPX + * + */ + +#include "windef.h" +#include "winuser.h" +#include "winnls.h" +#include "setupapi_private.h" + +/*--------------------- FIXME -------------------------- + * + * These must be seperated into the language files + * and translated. The language 0,0 is a hack to get it + * loaded properly for all languages by pretending that + * they are neutral. + * The menus are not yet properly implemented. + * Don't localize it yet. (js) + */ + +LANGUAGE 0,0 + +COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 +STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "Copying Files..." +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "Cancel", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "Source:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Destination:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP + CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP +END diff --git a/dlls/setupapi/setupapi.spec b/dlls/setupapi/setupapi.spec index 7cc43cdaf12..f030647af7a 100644 --- a/dlls/setupapi/setupapi.spec +++ b/dlls/setupapi/setupapi.spec @@ -1,11 +1,13 @@ name setupapi type win32 +rsrc setupapi.res +import user32.dll import advapi32.dll import kernel32.dll import ntdll.dll -debug_channels (setupapi setupx) +debug_channels (setupapi) # almost all functions are commented out for now. Ordinals are from setupapi.dll 4.0 diff --git a/dlls/setupapi/setupx_private.h b/dlls/setupapi/setupapi_private.h similarity index 56% rename from dlls/setupapi/setupx_private.h rename to dlls/setupapi/setupapi_private.h index dc73255cec9..e2400ce0277 100644 --- a/dlls/setupapi/setupx_private.h +++ b/dlls/setupapi/setupapi_private.h @@ -1,8 +1,18 @@ -#ifndef __SETUPX_PRIVATE_H -#define __SETUPX_PRIVATE_H +#ifndef __SETUPAPI_PRIVATE_H +#define __SETUPAPI_PRIVATE_H #include "wine/windef16.h" +#define COPYFILEDLGORD 1000 +#define SOURCESTRORD 500 +#define DESTSTRORD 501 +#define PROGRESSORD 502 + + +#define REG_INSTALLEDFILES "System\\CurrentControlSet\\Control\\InstalledFiles" +#define REGPART_RENAME "\\Rename" +#define REG_VERSIONCONFLICT "Software\\Microsoft\\VersionConflictManager" + typedef struct tagLDD_LIST { LPLOGDISKDESC pldd; struct tagLDD_LIST *next; @@ -26,4 +36,4 @@ extern WORD InfNumEntries; extern LPCSTR IP_GetFileName(HINF16 hInf); -#endif /* __SETUPX_PRIVATE_H */ +#endif /* __SETUPAPI_PRIVATE_H */ diff --git a/dlls/setupapi/setupx.spec b/dlls/setupapi/setupx.spec index b43bc44f35e..8a848166f6e 100644 --- a/dlls/setupapi/setupx.spec +++ b/dlls/setupapi/setupx.spec @@ -14,11 +14,11 @@ owner setupapi 10 stub IpGetIntField #(word ptr word ptr) 11 stub IpFindNextLine #(word ptr) 12 stub IpGetFileName #(word ptr word) -13 stub VcpQueueCopy #(str str str str word word ptr word long) +13 pascal16 VcpQueueCopy(str str str str word word ptr word long) VcpQueueCopy16 14 stub NOAUTORUNWNDPROC 15 stub __DEBUGMSG 16 stub __ASSERTMSG -17 stub VcpQueueDelete #(str str word long) +17 pascal16 VcpQueueDelete(str str word long) VcpQueueDelete16 18 stub TpOpenFile #(str ptr word) 19 stub TpCloseFile #(word) 20 stub TpOpenSection #(word ptr str word) @@ -62,6 +62,7 @@ owner setupapi 61 stub suErrorToIds #(word word) 62 stub TPWriteProfileString #(str str str) 63 stub SURPLSETUP +# does SUSTORELDIDPATH set the path of an LDID in the registry ? 64 stub SUSTORELDIDPATH 65 stub WILDCARDSTRCMPI 101 pascal16 GenInstall(word str word) GenInstall16 @@ -122,20 +123,20 @@ owner setupapi 160 stub SXUPDATEDS 170 stub SUSETMEM 171 stub WriteDMFBootData #(word ptr word) -200 pascal VcpOpen(ptr str) VcpOpen16 +200 pascal VcpOpen(segptr ptr) VcpOpen16 201 pascal VcpClose(word str) VcpClose16 -202 stub vcpDefCallbackProc #(ptr word word long long) +202 pascal16 vcpDefCallbackProc(ptr word word long long) vcpDefCallbackProc16 203 stub vcpEnumFiles #(ptr long) -204 stub VcpQueueRename #(str str str str word word long) -205 stub vsmGetStringName #(word ptr word) -206 stub vsmStringDelete #(word) -207 stub vsmStringAdd #(str) -208 stub vsmGetStringRawName #(word) +204 pascal16 VcpQueueRename(str str str str word word long) VcpQueueRename16 +205 pascal16 vsmGetStringName(word ptr word) vsmGetStringName16 +206 pascal16 vsmStringDelete(word) vsmStringDelete16 +207 pascal16 vsmStringAdd(str) vsmStringAdd16 +208 pascal vsmGetStringRawName(word) vsmGetStringRawName16 209 stub IpSaveRestorePosition #(word word) 210 pascal16 IpGetProfileString(word str str ptr word) IpGetProfileString16 211 stub IpOpenEx #(str ptr word) 212 stub IpOpenAppendEx #(str word word) -213 stub vcpUICallbackProc #(ptr word word long long) +213 pascal16 vcpUICallbackProc(ptr word word long long) vcpUICallbackProc16 214 stub VcpAddMRUPath #(str) 300 stub DiBuildCompatDrvList #(ptr) 301 stub DiBuildClassDrvList #(ptr) diff --git a/dlls/setupapi/setupx16.h b/dlls/setupapi/setupx16.h index 12292fa4e70..20940501093 100644 --- a/dlls/setupapi/setupx16.h +++ b/dlls/setupapi/setupx16.h @@ -5,6 +5,7 @@ typedef UINT16 HINF16; typedef UINT16 LOGDISKID16; +typedef UINT16 VHSTR; #define LINE_LEN 256 @@ -18,7 +19,7 @@ typedef UINT16 RETERR16; #define GEN_ERROR (UINT16)400 #define DI_ERROR (UINT16)500 -enum _IP_ERR { +enum { ERR_IP_INVALID_FILENAME = IP_ERROR+1, ERR_IP_ALLOC_ERR, ERR_IP_INVALID_SECT_NAME, @@ -37,7 +38,113 @@ enum _IP_ERR { ERR_IP_INVALID_INFTYPE }; -enum _ERR_VCP { +/****** virtual copy operations ******/ + +typedef DWORD LPEXPANDVTBL; + +typedef struct { + DWORD dwSoFar; + DWORD dwTotal; +} VCPPROGRESS, *LPVCPPROGRESS; + +typedef struct { + WORD cbSize; + LOGDISKID16 ldid; + VHSTR vhstrRoot; + VHSTR vhstrVolumeLabel; + VHSTR vhstrDiskName; + WORD wVolumeTime; + WORD wVolumeDate; + DWORD dwSerialNumber; + WORD fl; + LPARAM lparamRef; + + VCPPROGRESS prgFileRead; + VCPPROGRESS prgByteRead; + + VCPPROGRESS prgFileWrite; + VCPPROGRESS prgByteWrite; +} VCPDISKINFO, *LPVCPDISKINFO; + +typedef struct { + LOGDISKID16 ldid; + VHSTR vhstrDir; + VHSTR vhstrFileName; +} VCPFILESPEC, *LPVCPFILESPEC; + +typedef struct { + UINT16 uiMDate; + UINT16 uiMTime; + UINT16 uiADate; + UINT16 uiATime; + UINT16 uiAttr; + DWORD llenIn; + DWORD llenOut; +} VCPFATTR, *LPVCPFATTR; + +typedef struct { + UINT16 uDate; + UINT16 uTime; + DWORD dwSize; +} VCPFILESTAT, *LPVCPFILESTAT; + +typedef struct +{ + HFILE16 hFileSrc; + HFILE16 hFileDst; + VCPFATTR fAttr; + WORD dosError; + VHSTR vhstrFileName; + WPARAM vcpm; +} VIRTNODEEX, *LPVIRTNODEEX; + +typedef struct { + WORD cbSize; + VCPFILESPEC vfsSrc; + VCPFILESPEC vfsDst; + WORD fl; + LPARAM lParam; + LPEXPANDVTBL lpExpandVtbl; + LPVIRTNODEEX lpvnex; + VHSTR vhstrDstFinalName; + VCPFILESTAT vFileStat; +} VIRTNODE, *LPVIRTNODE; + +typedef struct { + WORD cbSize; + VCPPROGRESS prgDiskRead; + VCPPROGRESS prgFileRead; + VCPPROGRESS prgByteRead; + + VCPPROGRESS prgDiskWrite; + VCPPROGRESS prgFileWrite; + VCPPROGRESS prgByteWrite; + + LPVCPDISKINFO lpvdiIn; + LPVCPDISKINFO lpvdiOut; + LPVIRTNODE lpvn; +} VCPSTATUS, *LPVCPSTATUS; + +#define CNFL_BACKUP 0x0001 +#define CNFL_DELETEONFAILURE 0x0002 +#define CNFL_RENAMEONSUCCESS 0x0004 +#define CNFL_CONTINUATION 0x0008 +#define CNFL_SKIPPED 0x0010 +#define CNFL_IGNOREERRORS 0x0020 +#define CNFL_RETRYFILE 0x0040 +#define CNFL_COPIED 0x0080 +#define VNFL_UNIQUE 0x0000 +#define VNFL_MULTIPLEOK 0x0100 +#define VNFL_DESTROYOLD 0x0200 +#define VNFL_COPY 0x0000 +#define VNFL_DELETE 0x0800 +#define VNFL_RENAME 0x1000 +#define VNFL_NODE_TYPE (VNFL_RENAME|VNFL_DELETE|VNFL_COPY) +#define VNFL_CREATED 0x2000 +#define VNFL_REJECTED 0x4000 +#define VNFL_DEVICEINSTALLER 0x8000 + +enum { ERR_VCP_IOFAIL = VCP_ERROR+1, ERR_VCP_STRINGTOOLONG, ERR_VCP_NOMEM, @@ -65,6 +172,205 @@ enum _ERR_VCP { ERR_VCP_NO_DIGITAL_SIGNATURE_FILE }; +#define VCPN_OK 0 +#define VCPN_PROCEED 0 +#define VCPN_ABORT -1 +#define VCPN_RETRY -2 +#define VCPN_IGNORE -3 +#define VCPN_SKIP -4 +#define VCPN_FORCE -5 +#define VCPN_DEFER -6 +#define VCPN_FAIL -7 +#define VCPN_RETRYFILE -8 + +#define VCPFL_ABANDON 0x00 +#define VCPFL_BACKUP 0x01 +#define VCPFL_COPY 0x02 +#define VCPFL_BACKUPANDCOPY (VCPFL_BACKUP|VCPFL_COPY) +#define VCPFL_INSPECIFIEDORDER 0x04 +#define VCPFL_DELETE 0x08 +#define VCPFL_RENAME 0x10 +#define VCPFL_ALL (VCPFL_COPY|VCPFL_DELETE|VCPFL_RENAME) + +#define CFNL_BACKUP 0x0001 +#define CFNL_DELETEONFAILURE 0x0002 +#define CFNL_RENAMEONSUCCESS 0x0004 +#define CFNL_CONTINUATION 0x0008 +#define CFNL_SKIPPED 0x0010 +#define CFNL_IGNOREERRORS 0x0020 +#define CFNL_RETRYFILE 0x0040 +#define CFNL_COPIED 0x0080 +#define VFNL_MULTIPLEOK 0x0100 +#define VFNL_DESTROYOLD 0x0200 +#define VFNL_NOW 0x0400 +#define VFNL_COPY 0x0000 +#define VFNL_DELETE 0x0800 +#define VFNL_RENAME 0x1000 +#define VFNL_CREATED 0x2000 +#define VFNL_REJECTED 0x4000 +#define VCPM_DISKCLASS 0x01 +#define VCPM_DISKFIRST 0x0100 +#define VCPM_DISKLAST 0x01ff + +enum { + VCPM_DISKCREATEINFO = VCPM_DISKFIRST, + VCPM_DISKGETINFO, + VCPM_DISKDESTROYINFO, + VCPM_DISKPREPINFO, + VCPM_DISKENSURE, + VCPM_DISKPROMPT, + VCPM_DISKFORMATBEGIN, + VCPM_DISKFORMATTING, + VCPM_DISKFORMATEND +}; + +#define VCPM_FILEINCLASS 0x02 +#define VCPM_FILEOUTCLASS 0x03 +#define VCPM_FILEFIRSTIN 0x0200 +#define VCPM_FILEFIRSTOUT 0x0300 +#define VCPM_FILELAST 0x03ff + +enum { + VCPM_FILEOPENIN = VCPM_FILEFIRSTIN, + VCPM_FILEGETFATTR, + VCPM_FILECLOSEIN, + VCPM_FILECOPY, + VCPM_FILENEEDED, + + VCPM_FILEOPENOUT = VCPM_FILEFIRSTOUT, + VCPM_FILESETFATTR, + VCPM_FILECLOSEOUT, + VCPM_FILEFINALIZE, + VCPM_FILEDELETE, + VCPM_FILERENAME +}; + +#define VCPM_NODECLASS 0x04 +#define VCPM_NODEFIRST 0x0400 +#define VCPM_NODELAST 0x04ff + +enum { + VCPM_NODECREATE = VCPM_NODEFIRST, + VCPM_NODEACCEPT, + VCPM_NODEREJECT, + VCPM_NODEDESTROY, + VCPM_NODECHANGEDESTDIR, + VCPM_NODECOMPARE +}; + +#define VCPM_TALLYCLASS 0x05 +#define VCPM_TALLYFIRST 0x0500 +#define VCPM_TALLYLAST 0x05ff + +enum { + VCPM_TALLYSTART = VCPM_TALLYFIRST, + VCPM_TALLYEND, + VCPM_TALLYFILE, + VCPM_TALLYDISK +}; + +#define VCPM_VERCLASS 0x06 +#define VCPM_VERFIRST 0x0600 +#define VCPM_VERLAST 0x06ff + +enum { + VCPM_VERCHECK = VCPM_VERFIRST, + VCPM_VERCHECKDONE, + VCPM_VERRESOLVECONFLICT +}; + +#define VCPM_VSTATCLASS 0x07 +#define VCPM_VSTATFIRST 0x0700 +#define VCPM_VSTATLAST 0x07ff + +enum { + VCPM_VSTATSTART = VCPM_VSTATFIRST, + VCPM_VSTATEND, + VCPM_VSTATREAD, + VCPM_VSTATWRITE, + VCPM_VSTATNEWDISK, + VCPM_VSTATCLOSESTART, + VCPM_VSTATCLOSEEND, + VCPM_VSTATBACKUPSTART, + VCPM_VSTATBACKUPEND, + VCPM_VSTATRENAMESTART, + VCPM_VSTATRENAMEEND, + VCPM_VSTATCOPYSTART, + VCPM_VSTATCOPYEND, + VCPM_VSTATDELETESTART, + VCPM_VSTATDELETEEND, + VCPM_VSTATPATHCHECKSTART, + VCPM_VSTATPATHCHECKEND, + VCPM_VSTATCERTIFYSTART, + VCPM_VSTATCERTIFYEND, + VCPM_VSTATUSERABORT, + VCPM_VSTATYIELD +}; + +#define VCPM_PATHCLASS 0x08 +#define VCPM_PATHFIRST 0x0800 +#define VCPM_PATHLAST 0x08ff + +enum { + VCPM_BUILDPATH = VCPM_PATHFIRST, + VCPM_UNIQUEPATH, + VCPM_CHECKPATH +}; + +#define VCPM_PATCHCLASS 0x09 +#define VCPM_PATCHFIRST 0x0900 +#define VCPM_PATCHLAST 0x09ff + +enum { + VCPM_FILEPATCHBEFORECPY = VCPM_PATCHFIRST, + VCPM_FILEPATCHAFTERCPY, + VCPM_FILEPATCHINFOPEN, + VCPM_FILEPATCHINFCLOSE +}; + +#define VCPM_CERTCLASS 0x0a +#define VCPM_CERTFIRST 0x0a00 +#define VCPM_CERTLAST 0x0aff + +enum { + VCPM_FILECERTIFY = VCPM_CERTFIRST, + VCPM_FILECERTIFYWARN +}; + +typedef LRESULT CALLBACK (*VIFPROC)(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam, LPARAM lParam, LPARAM lparamRef); + +typedef int CALLBACK (*VCPENUMPROC)(LPVIRTNODE lpvn, LPARAM lparamRef); + +RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef); +RETERR16 WINAPI VcpQueueCopy16( + LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName, + LPCSTR lpszSrcDir, LPCSTR lpszDstDir, + LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst, + LPEXPANDVTBL lpExpandVtbl, + WORD fl, LPARAM lParam +); +RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest); +RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest); + +/* VcpExplain flags */ +enum { + VCPEX_SRC_DISK, + VCPEX_SRC_CABINET, + VCPEX_SRC_LOCN, + VCPEX_DST_LOCN, + VCPEX_SRC_FILE, + VCPEX_DST_FILE, + VCPEX_DST_FILE_FINAL, + VCPEX_DOS_ERROR, + VCPEX_MESSAGE, + VCPEX_DOS_SOLUTION, + VCPEX_SRC_FULL, + VCPEX_DST_FULL, + VCPEX_DST_FULL_FINAL +}; + +LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat); + /****** logical disk management ******/ typedef struct _LOGDISKDESC_S { /* ldd */ @@ -198,8 +504,6 @@ typedef struct _DEVICE_INFO } DEVICE_INFO16, *LPDEVICE_INFO16, **LPLPDEVICE_INFO16; -typedef LRESULT CALLBACK (*VIFPROC)(LPVOID lpvObj, UINT uMsg, WPARAM wParam, LPARAM lParam, LPARAM lparamRef); - extern void WINAPI GenFormStrWithoutPlaceHolders16(LPSTR,LPCSTR,HINF16); extern RETERR16 WINAPI IpOpen16(LPCSTR,HINF16 *); extern RETERR16 WINAPI IpClose16(HINF16); @@ -208,6 +512,7 @@ extern RETERR16 WINAPI CtlGetLdd16(LPLOGDISKDESC); extern RETERR16 WINAPI CtlFindLdd16(LPLOGDISKDESC); extern RETERR16 WINAPI CtlAddLdd16(LPLOGDISKDESC); extern RETERR16 WINAPI CtlDelLdd16(LOGDISKID16); +extern RETERR16 WINAPI CtlGetLddPath16(LOGDISKID16 ldid, LPSTR szPath); extern RETERR16 WINAPI GenInstall16(HINF16,LPCSTR,WORD); #endif /* __SETUPX16_H */ diff --git a/dlls/setupapi/setupx_main.c b/dlls/setupapi/setupx_main.c index e0ef93aa48e..dde4101000e 100644 --- a/dlls/setupapi/setupx_main.c +++ b/dlls/setupapi/setupx_main.c @@ -47,12 +47,12 @@ #include "winreg.h" #include "wine/winuser16.h" #include "setupx16.h" -#include "setupx_private.h" +#include "setupapi_private.h" #include "winerror.h" #include "heap.h" #include "debugtools.h" -DEFAULT_DEBUG_CHANNEL(setupx); +DEFAULT_DEBUG_CHANNEL(setupapi); /*********************************************************************** * SURegOpenKey @@ -292,7 +292,7 @@ RETERR16 WINAPI InstallHinfSection16( HWND16 hwnd, HINSTANCE16 hinst, LPCSTR lps LPSTR *pSub; DWORD count; HINF16 hInf = 0; - RETERR16 res = OK; + RETERR16 res = OK, tmp; WORD wFlags; BOOL reboot = FALSE; HMODULE hMod; @@ -310,6 +310,8 @@ RETERR16 WINAPI InstallHinfSection16( HWND16 hwnd, HINSTANCE16 hinst, LPCSTR lps res = ERROR_FILE_NOT_FOUND; /* yes, correct */ goto end; } + if (VcpOpen16(NULL, 0)) + goto end; if (GenInstall16(hInf, *(pSub+count-2), GENINSTALL_DO_ALL) != OK) goto end; wFlags = atoi(*(pSub+count-1)) & ~128; @@ -338,7 +340,12 @@ RETERR16 WINAPI InstallHinfSection16( HWND16 hwnd, HINSTANCE16 hinst, LPCSTR lps res = OK; end: - IpClose16(hInf); + tmp = VcpClose16(VCPFL_ALL, NULL); + if (tmp != OK) + res = tmp; + tmp = IpClose16(hInf); + if (tmp != OK) + res = tmp; SETUPX_FreeSubStrings(pSub); if (reboot) { @@ -502,7 +509,7 @@ static const LDID_DATA LDID_Data[34] = * LDID == Logical Device ID * * The whole LDD/LDID business might go into a separate file named - * ldd.c or logdevice.c. + * ldd.c. * At the moment I don't know what the hell these functions are really doing. * That's why I added reporting stubs. * The only thing I do know is that I need them for the LDD/LDID infrastructure. @@ -1048,28 +1055,6 @@ void WINAPI GenFormStrWithoutPlaceHolders16( LPSTR szDst, LPCSTR szSrc, HINF16 h TRACE("ret '%s'\n", szDst); } -/*********************************************************************** - * VcpOpen - * - * No idea what to do here. - */ -RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef) -{ - FIXME("(%p, %08lx), stub.\n", vifproc, lparamMsgRef); - return OK; -} - -/*********************************************************************** - * VcpClose - * - * Is fl related to VCPDISKINFO.fl ? - */ -RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest) -{ - FIXME("(%04x, '%s'), stub.\n", fl, lpszBackupDest); - return OK; -} - /* * Copy all items in a CopyFiles entry over to the destination * @@ -1077,26 +1062,29 @@ RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest) */ static BOOL SETUPX_CopyFiles(LPSTR *pSub, HINF16 hInf) { - BOOL res = FALSE; + BOOL bSingle = FALSE; unsigned int n; LPCSTR filename = IP_GetFileName(hInf); LPSTR pCopyEntry; - char pDestStr[MAX_PATH]; + char pDstStr[MAX_PATH]; LPSTR pSrcDir, pDstDir; LPSTR pFileEntries, p; WORD ldid; LOGDISKDESC_S ldd; LPSTR *pSubFile; LPSTR pSrcFile, pDstFile; + WORD flag; for (n=0; n < *(DWORD *)pSub; n++) { pCopyEntry = *(pSub+1+n); if (*pCopyEntry == '@') { - ERR("single file not handled yet !\n"); - continue; + pCopyEntry++; + bSingle = TRUE; } + else + bSingle = FALSE; /* get source directory for that entry */ INIT_LDD(ldd, LDID_SRCPATH); @@ -1105,20 +1093,35 @@ static BOOL SETUPX_CopyFiles(LPSTR *pSub, HINF16 hInf) /* get destination directory for that entry */ if (!(GetPrivateProfileStringA("DestinationDirs", pCopyEntry, "", - pDestStr, sizeof(pDestStr), filename))) - continue; + pDstStr, sizeof(pDstStr), filename))) + { + /* hmm, not found; try the default entry */ + if (!(GetPrivateProfileStringA("DestinationDirs", "DefaultDestDir", "", pDstStr, sizeof(pDstStr), filename))) + { + WARN("DefaultDestDir not found.\n"); + continue; + } + } /* translate destination dir if given as LDID */ - ldid = atoi(pDestStr); + ldid = atoi(pDstStr); if (ldid) { if (!(SETUPX_IP_TranslateLDID(ldid, &pDstDir, hInf))) continue; } else - pDstDir = pDestStr; + pDstDir = pDstStr; - /* now that we have the destination dir, iterate over files to copy */ + /* now that we have the destination dir, register file copying */ + + if (bSingle) + { + VcpQueueCopy16(pCopyEntry, pCopyEntry, pSrcDir, pDstDir, LDID_SRCPATH, ldid ? ldid : 0xffff, 0, VFNL_COPY, 0); + return TRUE; + } + + /* entry wasn't a single file, so let's iterate over section */ pFileEntries = SETUPX_GetSectionEntries(filename, pCopyEntry); for (p=pFileEntries; *p; p +=strlen(p)+1) { @@ -1126,30 +1129,34 @@ static BOOL SETUPX_CopyFiles(LPSTR *pSub, HINF16 hInf) pSrcFile = *(pSubFile+1); pDstFile = (*(DWORD *)pSubFile > 1) ? *(pSubFile+2) : pSrcFile; TRACE("copying file '%s\\%s' to '%s\\%s'\n", pSrcDir, pSrcFile, pDstDir, pDstFile); + flag = 0; if (*(DWORD *)pSubFile > 2) { - WORD flag; if ((flag = atoi(*(pSubFile+3)))) /* ah, flag */ { if (flag & 0x2c) FIXME("VNLP_xxx flag %d not handled yet.\n", flag); } else - FIXME("temp file name '%s' given. Need to register in wininit.ini !\n", *(pSubFile+3)); /* strong guess that this is VcpQueueCopy() */ + { + FIXME("temp file name '%s' given. Need to register in wininit.ini !\n", *(pSubFile+3)); + /* we probably need to set VIRTNODE.vhstrDstFinalName to + * the final destination name, and the temp name is merely + * the copy destination */ + } } + VcpQueueCopy16(pSrcFile, pDstFile, pSrcDir, pDstDir, LDID_SRCPATH, ldid ? ldid : 0xffff, 0, VFNL_COPY|flag, 0); SETUPX_FreeSubStrings(pSubFile); - /* we don't copy ANYTHING yet ! (I'm too lazy and want to verify - * this first before destroying whole partitions ;-) */ } } - return res; + return TRUE; } /*********************************************************************** * GenInstall * - * general install function for .INF file sections + * generic installer function for .INF file sections * * This is not perfect - patch whenever you can ! * diff --git a/dlls/setupapi/virtcopy.c b/dlls/setupapi/virtcopy.c new file mode 100644 index 00000000000..3cd7459c687 --- /dev/null +++ b/dlls/setupapi/virtcopy.c @@ -0,0 +1,709 @@ +/* + * SetupAPI virtual copy operations + * + * FIXME: we now rely on builtin setupapi.dll for dialog resources. + * This is bad ! We ought to have 16bit resource handling working. + */ + +#include +#include "debugtools.h" +#include "windef.h" +#include "setupx16.h" +#include "heap.h" +#include "callback.h" +#include "stackframe.h" +#include "winreg.h" +#include "setupapi_private.h" + +DEFAULT_DEBUG_CHANNEL(setupapi); + +/* ### start build ### */ +extern WORD CALLBACK VCP_CallTo16_word_lwwll(FARPROC16,LPVOID,UINT16,WPARAM,LPARAM,LPARAM); +/* ### stop build ### */ + +static FARPROC16 VCP_Proc = NULL; +static LPARAM VCP_MsgRef = 0; + +#define VCP_CALLBACK(obj,msg,wParam,lParam,lParamRef) \ + (VCP_Proc) ? \ + VCP_CallTo16_word_lwwll(VCP_Proc, obj,msg,wParam,lParam,lParamRef) : OK; + +static BOOL VCP_opened = FALSE; + +static VCPSTATUS vcp_status; + +static HINSTANCE SETUPAPI_hInstance; + +/****************************** VHSTR management ******************************/ + +/* + * This is a totally braindead implementation for now; + * I don't care about speed at all ! Size and implementation time + * is much more important IMHO. I could have created some sophisticated + * tree structure, but... what the hell ! :-) + */ +typedef struct { + DWORD refcount; + LPCSTR pStr; +} VHSTR_STRUCT; + +static VHSTR_STRUCT **vhstrlist = NULL; +static VHSTR vhstr_alloc = 0; + +#define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount)) + +VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName) +{ + VHSTR n; + VHSTR index = 0xffff; + HANDLE heap; + + TRACE("add string '%s'\n", lpszName); + /* search whether string already inserted */ + for (n = 0; n < vhstr_alloc; n++) + { + if ((vhstrlist[n]) && (vhstrlist[n]->refcount)) + { + TRACE("comp %d\n", n); + if (!strcmp(vhstrlist[n]->pStr, lpszName)) + { + vhstrlist[n]->refcount++; + return n; + } + } + } + + /* hmm, not found yet, let's insert it */ + for (n = 0; n < vhstr_alloc; n++) + { + if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount))) + { + index = n; + break; + } + } + heap = GetProcessHeap(); + if (n == vhstr_alloc) /* hmm, no free index found yet */ + { + index = vhstr_alloc; + vhstr_alloc += 20; + vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist, + sizeof(VHSTR_STRUCT *) * vhstr_alloc); + } + if (index == 0xffff) + return 0xffff; /* failure */ + if (!vhstrlist[index]) + vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT)); + vhstrlist[index]->refcount = 1; + vhstrlist[index]->pStr = HeapAlloc(heap, 0, strlen(lpszName)+1); + strcpy((LPSTR)vhstrlist[index]->pStr, lpszName); + return index; +} + +INT16 WINAPI vsmStringDelete16(VHSTR vhstr) +{ + if (VALID_VHSTR(vhstr)) + { + vhstrlist[vhstr]->refcount--; + if (!vhstrlist[vhstr]->refcount) + { + HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr); + vhstrlist[vhstr]->pStr = NULL; + } + return VCPN_OK; + } + + /* string not found */ + return VCPN_FAIL; +} + +/* + * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems + */ +VHSTR WINAPI vsmStringFind16(LPCSTR lpszName) +{ + WORD n; + for (n = 0; n < vhstr_alloc; n++) + if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName))) + return n; + return 0xffff; +} + +/* + * vsmGetStringName() + * + * Pretty correct, I guess + */ +INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer) +{ + if (VALID_VHSTR(vhstr)) + { + int len = strlen(vhstrlist[vhstr]->pStr)+1; + if (cbBuffer >= len) + { + if (lpszBuffer) + strcpy(lpszBuffer, vhstrlist[vhstr]->pStr); + return len; + } + } + return VCPN_FAIL; +} + +/* + * vsmStringCompare() - not exported from a standard SETUPX.DLL, it seems + */ +INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB) +{ + if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB))) + return VCPN_FAIL; /* correct ? */ + return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr); +} + +LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr) +{ + return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL; +} + + +/***************************** VIRTNODE management ****************************/ +static LPVIRTNODE *pvnlist = NULL; +static DWORD vn_num = 0; +static DWORD vn_last = 0; + +RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl) +{ + HANDLE heap; + LPVIRTNODE lpvn; + RETERR16 cbres; + + while (vn_last < vn_num) + { + if (pvnlist[vn_last] == NULL) + break; + vn_last++; + } + heap = GetProcessHeap(); + if (vn_last == vn_num) + { + vn_num += 20; + pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist, + sizeof(LPVIRTNODE *) * vn_num); + } + pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE)); + lpvn = pvnlist[vn_last]; + vn_last++; + + lpvn->cbSize = sizeof(VIRTNODE); + + if (vfsSrc) + memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC)); + + if (vfsDst) + memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC)); + + lpvn->fl = fl; + lpvn->lParam = lParam; + lpvn->lpExpandVtbl = lpExpandVtbl; + + lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */ + + cbres = VCP_CALLBACK(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef); + lpvn->fl |= VFNL_CREATED; + cbres = VCP_CALLBACK(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef); + + return OK; +} + +BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel) +{ + DWORD n; + RETERR16 cbres; + + for (n = 0; n < vn_last; n++) + { + if (pvnlist[n] == lpvnDel) + { + cbres = VCP_CALLBACK(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef); + HeapFree(GetProcessHeap(), 0, lpvnDel); + pvnlist[n] = NULL; + return TRUE; + } + } + return FALSE; +} + +/*********************************************************************** + * VcpOpen + * + * Sets up a virtual copy operation. + * This means that functions such as GenInstall() + * create a VIRTNODE struct for every file to be touched in a .INF file + * instead of actually touching the file. + * The actual copy/move/rename gets started when VcpClose or + * VcpFlush is called; several different callbacks are made + * (copy, rename, open, close, version conflicts, ...) on every file copied. + */ +RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef) +{ + TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef); + if (VCP_opened) + return ERR_VCP_BUSY; + + VCP_Proc = (FARPROC16)vifproc; + VCP_MsgRef = lparamMsgRef; + + /* load SETUPAPI needed for dialog resources etc. */ + SETUPAPI_hInstance = LoadLibraryA("setupapi.dll"); + if (!SETUPAPI_hInstance) + { + ERR("Could not load sibling setupapi.dll\n"); + return ERR_VCP_NOMEM; + } + VCP_opened = TRUE; + return OK; +} + +/*********************************************************************** + * VcpQueueCopy [SETUPX.13] + * + * lpExpandVtbl seems to be deprecated. + * fl are the CNFL_xxx and VNFL_xxx flags. + * lParam are the VNLP_xxx flags. + */ +RETERR16 WINAPI VcpQueueCopy16( + LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName, + LPCSTR lpszSrcDir, LPCSTR lpszDstDir, + LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst, + LPEXPANDVTBL lpExpandVtbl, + WORD fl, LPARAM lParam +) +{ + VCPFILESPEC vfsSrc, vfsDst; + + if (!VCP_opened) + return ERR_VCP_NOTOPEN; + + vfsSrc.ldid = ldidSrc; + vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir); + vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName); + + vfsDst.ldid = ldidDst; + vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir); + vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName); + + return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam, + lpExpandVtbl); +} + +/*********************************************************************** + * VcpQueueDelete [SETUPX.17] + * + * Is lParamRef the same as lParam in VcpQueueCopy ? + * Damn docu !! Err... which docu ? + */ +RETERR16 WINAPI VcpQueueDelete16( + LPCSTR lpszDstFileName, + LPCSTR lpszDstDir, + LOGDISKID16 ldidDst, + LPEXPANDVTBL lpExpandVtbl, + LPARAM lParamRef +) +{ + VCPFILESPEC vfsDst; + + if (!VCP_opened) + return ERR_VCP_NOTOPEN; + + vfsDst.ldid = ldidDst; + vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir); + vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName); + + return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, + lpExpandVtbl); +} + +/*********************************************************************** + * VcpQueueRename [SETUPX.204] + * + */ +RETERR16 WINAPI VcpQueueRename16( + LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName, + LPCSTR lpszSrcDir, LPCSTR lpszDstDir, + LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst, + LPARAM lParam +) +{ + VCPFILESPEC vfsSrc, vfsDst; + + if (!VCP_opened) + return ERR_VCP_NOTOPEN; + + vfsSrc.ldid = ldidSrc; + vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir); + vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName); + + vfsDst.ldid = ldidDst; + vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir); + vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName); + + return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam, + 0); +} + +INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef) +{ + WORD n; + + for (n = 0; n < vn_last; n++) + vep(pvnlist[n], lParamRef); + + return 0; /* FIXME: return value ? */ +} + +LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat) +{ + static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */ + buffer[0] = '\0'; + switch (dwWhat) + { + case VCPEX_SRC_FULL: + case VCPEX_DST_FULL: + { + LPVCPFILESPEC lpvfs = + (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst; + + if (lpvfs->ldid != 0xffff) + CtlGetLddPath16(lpvfs->ldid, buffer); + strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir)); + strcat(buffer, "\\"); + strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName)); + } + break; + default: + FIXME("%ld unimplemented !\n", dwWhat); + strcpy(buffer, "Unknown error"); + break; + } + return buffer; +} + +RETERR16 VCP_CheckPaths(void) +{ + DWORD n; + LPVIRTNODE lpvn; + RETERR16 cbres; + + cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef); + for (n = 0; n < vn_num; n++) + { + lpvn = pvnlist[n]; + if (!lpvn) continue; + /* FIXME: check paths of all VIRTNODEs here ! */ + cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef); + } + cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef); + return OK; +} + +RETERR16 VCP_CopyFiles(void) +{ + char fn_src[MAX_PATH], fn_dst[MAX_PATH]; + RETERR16 res = OK, cbres; + DWORD n; + LPVIRTNODE lpvn; + + cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef); + for (n = 0; n < vn_num; n++) + { + lpvn = pvnlist[n]; + if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue; + /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */ + strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL)); + strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL)); + /* FIXME: what is this VCPM_VSTATWRITE here for ? + * I guess it's to signal successful destination file creation */ + cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef); + /* FIXME: need to do the file copy in small chunks for notifications */ + TRACE("copying '%s' to '%s'\n", fn_src, fn_dst); +#if DO_A_REAL_COPY + if (!(CopyFileA(fn_src, fn_dst, TRUE))) + res = ERR_VCP_IOFAIL; +#endif + vcp_status.prgFileRead.dwSoFar++; + cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef); + vcp_status.prgFileWrite.dwSoFar++; + cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef); + } + + cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef); + return res; +} + +/*********************************************************************** + * VcpFlush - internal (not exported), but documented + * + * VNFL_NOW is used for VcpFlush. + */ +RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest) +{ + return OK; +} + +/*********************************************************************** + * VcpClose + * + * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART, + * VCPM_VSTATCLOSEEND. + * + * fl gets VCPFL_xxx flags to indicate what to do with the + * VIRTNODEs (files to mess with) created by e.g. GenInstall() + */ +RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest) +{ + RETERR16 res = OK; + WORD cbres = VCPN_PROCEED; + + TRACE("(%04x, '%s')\n", fl, lpszBackupDest); + + /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER + * is not set. This is done by VCP_CALLBACK(VCPM_NODECOMPARE) */ + + TRACE("#1\n"); + memset(&vcp_status, 0, sizeof(VCPSTATUS)); + /* yes, vcp_status.cbSize is 0 ! */ + TRACE("#2\n"); + cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef); + TRACE("#3\n"); + + res = VCP_CheckPaths(); + TRACE("#4\n"); + if (res != OK) + return res; /* is this ok ? */ + VCP_CopyFiles(); + + TRACE("#5\n"); + cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef); + TRACE("#6\n"); + VCP_Proc = NULL; + FreeLibrary(SETUPAPI_hInstance); + VCP_opened = FALSE; + return OK; +} + +RETERR16 VCP_RenameFiles(void) +{ + char fn_src[MAX_PATH], fn_dst[MAX_PATH]; + RETERR16 res = OK, cbres; + DWORD n; + LPVIRTNODE lpvn; + + cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef); + for (n = 0; n < vn_num; n++) + { + lpvn = pvnlist[n]; + if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue; + strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL)); + strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL)); + cbres = VCP_CALLBACK(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef); + if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING))) + res = ERR_VCP_IOFAIL; + else + VCP_VirtnodeDelete(lpvn); + } + cbres = VCP_CALLBACK(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef); + return res; +} + +RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam, + LPARAM lParam, LPARAM lParamRef) +{ + static int count = 0; + if (count < 10) + FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n", + lpvObj, uMsg, wParam, lParam, lParamRef); + count++; + return OK; +} + +/********************* point-and-click stuff from here ***********************/ + +static HWND hDlgCopy = 0; +static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0; +static char BackupDir[12]; + +static BOOL CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + BOOL retval = FALSE; + + if (iMsg == WM_INITDIALOG) + { + ShowWindow(hWndDlg, SW_SHOWNORMAL); + UpdateWindow(hWndDlg); + retval = TRUE; + } + return retval; +} + +BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32) +{ + HANDLE hResInfo, hDlgTmpl32; + + if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), RT_DIALOGA))) + return FALSE; + if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) || + !(*template32 = LockResource( hDlgTmpl32 ))) + return FALSE; + return TRUE; +} + +static LRESULT WINAPI +VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg != WM_CREATE) + return DefWindowProcA (hwnd, uMsg, wParam, lParam); + + switch (uMsg) + { + case WM_CREATE: + return 0; + default: + FIXME("%04x: unhandled.\n", uMsg); + } + + return 0; +} + +void VCP_UI_RegisterProgressClass(void) +{ + static BOOL registered = FALSE; + WNDCLASSA wndClass; + + if (registered) + return; + + registered = TRUE; + ZeroMemory (&wndClass, sizeof(WNDCLASSA)); + wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; + wndClass.lpfnWndProc = (WNDPROC)VCP_UI_FileCopyWndProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hCursor = LoadCursorA (0, IDC_ARROWA); + wndClass.hbrBackground = (HBRUSH)NULL; + wndClass.lpszClassName = "setupx_progress"; + + RegisterClassA (&wndClass); +} + +RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2) +{ + LPCSTR file1, file2; + file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName); + file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName); + return (RETERR16)strcmp(file1, file2); +} + +RETERR16 VCP_UI_CopyStart(void) +{ + LPCVOID template32; + char buf[256]; /* plenty */ + BOOL dirty; + DWORD len; + + /* FIXME: should be registered at DLL startup instead */ + VCP_UI_RegisterProgressClass(); + if (!(VCP_UI_GetDialogTemplate(&template32))) + return VCPN_FAIL; + + hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0, + VCP_UI_FileCopyDlgProc, 0); + if (!hDlgCopy) + return VCPN_FAIL; + SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ..."); + SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET"); + strcpy(buf, REG_INSTALLEDFILES); + if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles)) + return VCPN_FAIL; + strcat(buf, REGPART_RENAME); + if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename)) + return VCPN_FAIL; + if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict)) + return VCPN_FAIL; + len = 1; + if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len))) + { + /* FIXME: what does SETUPX.DLL do in this case ? */ + MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n"); + return VCPN_FAIL; + } + dirty = TRUE; + if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1)) + return VCPN_FAIL; + len = 12; + if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len))) + strcpy(BackupDir, "VCM"); + + /* create C:\WINDOWS\[BackupDir] and set registry key to it */ + GetWindowsDirectoryA(buf, 256); + strcat(buf, "\\"); + strcat(buf, BackupDir); + if (!(CreateDirectoryA(buf, NULL))) + return VCPN_FAIL; + if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1)) + return VCPN_FAIL; + RegCloseKey(hKeyConflict); + + return VCPN_OK; +} + +RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam, + LPARAM lParam, LPARAM lParamRef) +{ + static int count = 0; + RETERR16 res = VCPN_OK, cbres; + + if (count < 5) + FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n", + lpvObj, uMsg, wParam, lParam, lParamRef); + count++; + switch (uMsg) + { + /* unused messages, it seems */ + case VCPM_DISKPREPINFO: + + case VCPM_FILENEEDED: + + case VCPM_NODECREATE: + case VCPM_NODEACCEPT: + + case VCPM_VSTATCLOSESTART: + case VCPM_VSTATPATHCHECKSTART: + case VCPM_VSTATPATHCHECKEND: + + case VCPM_CHECKPATH: + break; + + /* the real stuff */ + case VCPM_NODECOMPARE: + res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam); + break; + case VCPM_VSTATREAD: + break; + case VCPM_VSTATWRITE: + cbres = VCP_CALLBACK(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef); + break; + case VCPM_VSTATCLOSEEND: + RegCloseKey(hKeyFiles); + RegCloseKey(hKeyRename); + RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT); + break; + case VCPM_VSTATCOPYSTART: + res = VCP_UI_CopyStart(); + break; + case VCPM_VSTATCOPYEND: + DestroyWindow(hDlgCopy); + break; + default: + FIXME("unhandled msg 0x%04x\n", uMsg); + } + return res; +}