1049 lines
22 KiB
C
1049 lines
22 KiB
C
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
caller.c
|
|
|
|
Abstract:
|
|
|
|
Calls the entry points for a specific DLL.
|
|
|
|
Author:
|
|
|
|
Jim Schmidt (jimschm) 14-Jan-1998
|
|
|
|
Revision History:
|
|
|
|
jimschm 23-Sep-1998 Updated for new IPC mechanism
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
#include "plugin.h"
|
|
#include "migdllp.h"
|
|
|
|
#define DBG_MIGDLLS "MigDLLs"
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
PBYTE g_Data;
|
|
DWORD g_DataSize;
|
|
BOOL g_UseMigIsol = TRUE;
|
|
|
|
TCHAR g_OldDirectory[MAX_TCHAR_PATH];
|
|
HINSTANCE g_MigDllLib;
|
|
P_QUERY_VERSION TestQueryVersion;
|
|
P_INITIALIZE_9X TestInitialize9x;
|
|
P_MIGRATE_USER_9X TestMigrateUser9x;
|
|
P_MIGRATE_SYSTEM_9X TestMigrateSystem9x;
|
|
P_INITIALIZE_NT TestInitializeNT;
|
|
P_MIGRATE_USER_NT TestMigrateUserNT;
|
|
P_MIGRATE_SYSTEM_NT TestMigrateSystemNT;
|
|
PCSTR g_DllName;
|
|
CHAR g_DllPath[MAX_MBCHAR_PATH];
|
|
|
|
//
|
|
// Local prototypes
|
|
//
|
|
|
|
VOID
|
|
pFreeGlobalIpcBuffer (
|
|
VOID
|
|
);
|
|
|
|
DWORD
|
|
pFinishHandshake9x(
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// Implementation
|
|
//
|
|
|
|
|
|
BOOL
|
|
OpenMigrationDll (
|
|
IN PCSTR MigrationDllPath,
|
|
IN PCSTR WorkingDir
|
|
)
|
|
{
|
|
CHAR MigIsolPath[MAX_MBCHAR_PATH];
|
|
PCSTR TempDir;
|
|
|
|
StringCopyA (g_DllPath, MigrationDllPath);
|
|
if (!g_DllName) {
|
|
g_DllName = g_DllPath;
|
|
}
|
|
|
|
GetCurrentDirectory (MAX_TCHAR_PATH, g_OldDirectory);
|
|
|
|
if (!g_UseMigIsol) {
|
|
|
|
//
|
|
// Load the library and verify that all required functions exist
|
|
//
|
|
|
|
g_MigDllLib = LoadLibrary (MigrationDllPath);
|
|
if (!g_MigDllLib) {
|
|
return FALSE;
|
|
}
|
|
|
|
TestQueryVersion = (P_QUERY_VERSION) GetProcAddress (g_MigDllLib, PLUGIN_QUERY_VERSION);
|
|
TestInitialize9x = (P_INITIALIZE_9X) GetProcAddress (g_MigDllLib, PLUGIN_INITIALIZE_9X);
|
|
TestMigrateUser9x = (P_MIGRATE_USER_9X) GetProcAddress (g_MigDllLib, PLUGIN_MIGRATE_USER_9X);
|
|
TestMigrateSystem9x = (P_MIGRATE_SYSTEM_9X) GetProcAddress (g_MigDllLib, PLUGIN_MIGRATE_SYSTEM_9X);
|
|
TestInitializeNT = (P_INITIALIZE_NT) GetProcAddress (g_MigDllLib, PLUGIN_INITIALIZE_NT);
|
|
TestMigrateUserNT = (P_MIGRATE_USER_NT) GetProcAddress (g_MigDllLib, PLUGIN_MIGRATE_USER_NT);
|
|
TestMigrateSystemNT = (P_MIGRATE_SYSTEM_NT) GetProcAddress (g_MigDllLib, PLUGIN_MIGRATE_SYSTEM_NT);
|
|
|
|
if (!TestQueryVersion ||
|
|
!TestInitialize9x ||
|
|
!TestMigrateUser9x ||
|
|
!TestMigrateSystem9x ||
|
|
!TestInitializeNT ||
|
|
!TestMigrateUserNT ||
|
|
!TestMigrateSystemNT
|
|
) {
|
|
FreeLibrary (g_MigDllLib);
|
|
g_MigDllLib = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// Generate path to migisol.exe, installed by the copy thread in UI
|
|
//
|
|
|
|
TempDir = ConvertAtoT (g_TempDir);
|
|
MYASSERT (TempDir);
|
|
wsprintfA (MigIsolPath, "%s\\%s", TempDir, S_MIGISOL_EXE);
|
|
FreeAtoT (TempDir);
|
|
|
|
if (!OpenIpc (
|
|
TRUE, // TRUE: Win95 side
|
|
MigIsolPath,
|
|
MigrationDllPath,
|
|
WorkingDir
|
|
)) {
|
|
|
|
LOG ((
|
|
LOG_WARNING,
|
|
"Can't establish IPC connection for %s",
|
|
MigrationDllPath
|
|
));
|
|
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
CloseMigrationDll (
|
|
VOID
|
|
)
|
|
{
|
|
if (!g_UseMigIsol) {
|
|
if (g_MigDllLib) {
|
|
FreeLibrary (g_MigDllLib);
|
|
g_MigDllLib = NULL;
|
|
}
|
|
|
|
SetCurrentDirectory (g_OldDirectory);
|
|
|
|
} else {
|
|
CloseIpc();
|
|
}
|
|
|
|
pFreeGlobalIpcBuffer();
|
|
}
|
|
|
|
|
|
BOOL
|
|
pValidateBinary (
|
|
IN PBYTE Data,
|
|
IN UINT Size
|
|
)
|
|
{
|
|
BYTE Remember;
|
|
|
|
if (!Data || !Size) {
|
|
return TRUE;
|
|
}
|
|
|
|
__try {
|
|
Remember = Data[0];
|
|
Data[0] = Remember;
|
|
Remember = Data[Size - 1];
|
|
Data[Size - 1] = Remember;
|
|
}
|
|
__except (TRUE) {
|
|
DEBUGMSG ((DBG_MIGDLLS, "pValidateBinary failed for %u bytes", Size));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
pValidateNonNullString (
|
|
IN PCSTR String
|
|
)
|
|
{
|
|
__try {
|
|
SizeOfStringA (String);
|
|
if (*String == 0) {
|
|
DEBUGMSG ((DBG_MIGDLLS, "pValidateNonNullString found zero-length string"));
|
|
return FALSE;
|
|
}
|
|
}
|
|
__except (TRUE) {
|
|
DEBUGMSG ((DBG_MIGDLLS, "pValidateNonNullString failed"));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
pValidateIntArray (
|
|
IN PINT Array
|
|
)
|
|
{
|
|
PINT End;
|
|
|
|
if (!Array) {
|
|
return TRUE;
|
|
}
|
|
|
|
__try {
|
|
End = Array;
|
|
while (*End != -1) {
|
|
End++;
|
|
}
|
|
}
|
|
__except (TRUE) {
|
|
DEBUGMSG ((DBG_MIGDLLS, "Int Array is invalid (or not terminated with -1)"));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
pValidateMultiString (
|
|
IN PCSTR Strings
|
|
)
|
|
{
|
|
if (!Strings) {
|
|
return TRUE;
|
|
}
|
|
|
|
__try {
|
|
while (*Strings) {
|
|
Strings = GetEndOfStringA (Strings) + 1;
|
|
}
|
|
}
|
|
__except (TRUE) {
|
|
DEBUGMSG ((DBG_MIGDLLS, "pValidateMultiString failed"));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
DWORD
|
|
pRemoteQueryVersion(
|
|
OUT PCSTR *ProductId,
|
|
OUT PUINT DllVersion,
|
|
OUT PDWORD *CodePageArray,
|
|
OUT PCSTR *ExeNamesBuf,
|
|
IN PCSTR WorkingDir,
|
|
OUT PVENDORINFO *VendorInfo
|
|
)
|
|
{
|
|
PBYTE DataPtr;
|
|
INT ReturnArraySize;
|
|
PDWORD ReturnArray;
|
|
DWORD rc = ERROR_SUCCESS;
|
|
GROWBUFFER GrowBuf = GROWBUF_INIT;
|
|
PCTSTR p;
|
|
DWORD DataSize;
|
|
|
|
//
|
|
// Free any previous data... but do not free before we return, because the
|
|
// new data buffer will be used directly by the caller. (The caller will
|
|
// make copies of all the settings.)
|
|
//
|
|
|
|
pFreeGlobalIpcBuffer();
|
|
|
|
__try {
|
|
|
|
//
|
|
// Send the working directory, since migisol will need to set this before
|
|
// calling QueryVersion.
|
|
//
|
|
|
|
MultiSzAppendA (&GrowBuf, WorkingDir);
|
|
|
|
DEBUGMSG ((DBG_MIGDLLS, "Calling QueryVersion via migisol.exe"));
|
|
|
|
if (!SendIpcCommand (
|
|
IPC_QUERY,
|
|
GrowBuf.Buf,
|
|
GrowBuf.End
|
|
)) {
|
|
|
|
LOG ((LOG_ERROR,"pRemoteQueryVersion failed to send command"));
|
|
rc = GetLastError();
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Finish transaction. Caller will interpret return code.
|
|
//
|
|
|
|
DEBUGMSG ((DBG_MIGDLLS, "Getting results from migisol.exe"));
|
|
|
|
rc = pFinishHandshake9x();
|
|
|
|
//
|
|
// Unpack the buffer, if received.
|
|
//
|
|
if (g_Data) {
|
|
|
|
DEBUGMSG ((DBG_MIGDLLS, "Parsing QueryVersion return data"));
|
|
|
|
__try {
|
|
DataPtr = g_Data;
|
|
|
|
//
|
|
// Unpack product ID
|
|
//
|
|
*ProductId = DataPtr;
|
|
DataPtr = GetEndOfStringA ((PCSTR) DataPtr) + 1;
|
|
|
|
//
|
|
// Unpack DLL version
|
|
//
|
|
*DllVersion = *((PINT) DataPtr);
|
|
DataPtr += sizeof(INT);
|
|
|
|
//
|
|
// Unpack the CP array
|
|
//
|
|
ReturnArraySize = *((PINT) DataPtr);
|
|
DataPtr += sizeof(INT);
|
|
|
|
if (ReturnArraySize) {
|
|
ReturnArray = (PDWORD) DataPtr;
|
|
DataPtr += ReturnArraySize * sizeof (DWORD);
|
|
} else {
|
|
ReturnArray = NULL;
|
|
}
|
|
|
|
*CodePageArray = ReturnArray;
|
|
|
|
//
|
|
// Unpack Exe name buffer
|
|
//
|
|
*ExeNamesBuf = (PCSTR) DataPtr;
|
|
|
|
p = *ExeNamesBuf;
|
|
while (*p) {
|
|
p = GetEndOfStringA (p) + 1;
|
|
}
|
|
DataPtr = (PBYTE) (p + 1);
|
|
|
|
*VendorInfo = *((PVENDORINFO *) DataPtr);
|
|
DataPtr += sizeof (PVENDORINFO);
|
|
|
|
DEBUGMSG ((DBG_MIGDLLS, "Unpacked VendorInfo pointer is 0x%X", *VendorInfo));
|
|
|
|
if (*VendorInfo) {
|
|
DataSize = *((PDWORD) DataPtr);
|
|
DataPtr += sizeof (DWORD);
|
|
MYASSERT (DataSize == sizeof (VENDORINFO));
|
|
|
|
*VendorInfo = (PVENDORINFO) PoolMemDuplicateMemory (g_MigDllPool, DataPtr, sizeof (VENDORINFO));
|
|
DataPtr += sizeof (VENDORINFO);
|
|
}
|
|
|
|
DEBUGMSG ((DBG_MIGDLLS, "QueryVersion is complete, rc=%u", rc));
|
|
}
|
|
|
|
__except(TRUE) {
|
|
LOG ((LOG_ERROR, "An error occurred while unpacking params"));
|
|
rc = ERROR_INVALID_PARAMETER;
|
|
}
|
|
} else {
|
|
DEBUGMSG ((DBG_WARNING, "pRemoteQueryVersion: No OUT params received"));
|
|
|
|
//
|
|
// We should never return ERROR_SUCCESS if no buffer is received.
|
|
//
|
|
if (rc == ERROR_SUCCESS) {
|
|
rc = ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
}
|
|
__finally {
|
|
FreeGrowBuffer (&GrowBuf);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
DWORD
|
|
pRemoteInitialize9x(
|
|
IN PCSTR WorkingDir,
|
|
IN PCSTR SourceDirs,
|
|
PVOID *Reserved,
|
|
DWORD SizeOfReserved
|
|
)
|
|
{
|
|
DWORD rc = ERROR_SUCCESS;
|
|
GROWBUFFER GrowBuf = GROWBUF_INIT;
|
|
PCSTR p;
|
|
PBYTE Data;
|
|
DWORD ReturnSize;
|
|
|
|
pFreeGlobalIpcBuffer();
|
|
|
|
__try {
|
|
//
|
|
// Send working dir and source dirs
|
|
//
|
|
MultiSzAppendA (&GrowBuf, WorkingDir);
|
|
|
|
for (p = SourceDirs ; *p ; p = GetEndOfStringA (p) + 1) {
|
|
MultiSzAppendA (&GrowBuf, p);
|
|
}
|
|
|
|
MultiSzAppendA (&GrowBuf, p);
|
|
GrowBufAppendDword (&GrowBuf, SizeOfReserved);
|
|
|
|
if (SizeOfReserved) {
|
|
Data = GrowBuffer (&GrowBuf, SizeOfReserved);
|
|
CopyMemory (Data, *Reserved, SizeOfReserved);
|
|
}
|
|
|
|
//
|
|
// Send command to migisol
|
|
//
|
|
|
|
if (!SendIpcCommand (
|
|
IPC_INITIALIZE,
|
|
GrowBuf.Buf,
|
|
GrowBuf.End
|
|
)) {
|
|
|
|
LOG ((LOG_ERROR,"pRemoteInitialize9x failed to send command"));
|
|
rc = GetLastError();
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Finish transaction. Caller will interpret return code.
|
|
//
|
|
rc = pFinishHandshake9x();
|
|
|
|
//
|
|
// The reserved parameter may come back
|
|
//
|
|
|
|
if (g_Data) {
|
|
Data = g_Data;
|
|
ReturnSize = *((PDWORD) Data);
|
|
if (ReturnSize) {
|
|
Data += sizeof (DWORD);
|
|
CopyMemory (*Reserved, Data, ReturnSize);
|
|
} else if (SizeOfReserved) {
|
|
ZeroMemory (*Reserved, SizeOfReserved);
|
|
}
|
|
}
|
|
}
|
|
__finally {
|
|
FreeGrowBuffer (&GrowBuf);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
VOID
|
|
pGetParentWindowTitleAndId (
|
|
IN HWND ParentWnd,
|
|
OUT PSTR TitleBuf,
|
|
OUT PDWORD IdPtr
|
|
)
|
|
{
|
|
*IdPtr = 0;
|
|
|
|
if (ParentWnd) {
|
|
GetWindowTextA (ParentWnd, TitleBuf, MAX_PATH);
|
|
GetWindowThreadProcessId (ParentWnd, IdPtr);
|
|
} else {
|
|
TitleBuf[0] = 0;
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
pRemoteMigrateUser9x (
|
|
IN HWND ParentWnd, OPTIONAL
|
|
IN PCSTR UnattendFile,
|
|
IN PCSTR RootKey,
|
|
IN PCSTR User OPTIONAL
|
|
)
|
|
{
|
|
DWORD rc = ERROR_SUCCESS;
|
|
GROWBUFFER GrowBuf = GROWBUF_INIT;
|
|
CHAR ParentWindowTitle[MAX_PATH];
|
|
DWORD ProcessId;
|
|
|
|
pGetParentWindowTitleAndId (ParentWnd, ParentWindowTitle, &ProcessId);
|
|
|
|
pFreeGlobalIpcBuffer();
|
|
|
|
__try {
|
|
MultiSzAppendA (&GrowBuf, ParentWindowTitle);
|
|
GrowBufAppendDword (&GrowBuf, ProcessId);
|
|
MultiSzAppendA (&GrowBuf, UnattendFile);
|
|
MultiSzAppendA (&GrowBuf, RootKey);
|
|
MultiSzAppendA (&GrowBuf, (NULL == User ? S_EMPTY : User));
|
|
|
|
if (!SendIpcCommand (
|
|
IPC_MIGRATEUSER,
|
|
GrowBuf.Buf,
|
|
GrowBuf.End
|
|
)) {
|
|
|
|
LOG ((LOG_ERROR, "pRemoteMigrateUser9x failed to send command"));
|
|
rc = GetLastError();
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Complete the transaction. The caller will interpret the return
|
|
// value.
|
|
//
|
|
rc = pFinishHandshake9x();
|
|
|
|
//
|
|
// No data buffer is coming back at this time
|
|
//
|
|
}
|
|
|
|
__finally {
|
|
FreeGrowBuffer (&GrowBuf);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
DWORD
|
|
pRemoteMigrateSystem9x (
|
|
IN HWND ParentWnd, OPTIONAL
|
|
IN PCSTR UnattendFile
|
|
)
|
|
{
|
|
DWORD rc = ERROR_SUCCESS;
|
|
GROWBUFFER GrowBuf = GROWBUF_INIT;
|
|
CHAR ParentWindowTitle[MAX_PATH];
|
|
DWORD ProcessId;
|
|
|
|
pGetParentWindowTitleAndId (ParentWnd, ParentWindowTitle, &ProcessId);
|
|
|
|
pFreeGlobalIpcBuffer();
|
|
|
|
__try {
|
|
MultiSzAppendA (&GrowBuf, ParentWindowTitle);
|
|
GrowBufAppendDword (&GrowBuf, ProcessId);
|
|
MultiSzAppendA (&GrowBuf, UnattendFile);
|
|
|
|
if (!SendIpcCommand (
|
|
IPC_MIGRATESYSTEM,
|
|
GrowBuf.Buf,
|
|
GrowBuf.End
|
|
)) {
|
|
|
|
LOG ((LOG_ERROR,"pRemoteMigrateSystem9x failed to send command"));
|
|
rc = GetLastError();
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Finish transaction. Caller will interpret return value.
|
|
//
|
|
|
|
rc = pFinishHandshake9x();
|
|
|
|
//
|
|
// No data buffer is coming back at this time
|
|
//
|
|
}
|
|
|
|
__finally {
|
|
FreeGrowBuffer (&GrowBuf);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
VOID
|
|
pFreeGlobalIpcBuffer (
|
|
VOID
|
|
)
|
|
{
|
|
//
|
|
// Free old return param buffer
|
|
//
|
|
if (g_Data) {
|
|
MemFree (g_hHeap, 0, g_Data);
|
|
g_Data = NULL;
|
|
}
|
|
|
|
g_DataSize = 0;
|
|
}
|
|
|
|
|
|
DWORD
|
|
pFinishHandshake9x(
|
|
VOID
|
|
)
|
|
{
|
|
DWORD TechnicalLogId;
|
|
DWORD GuiLogId;
|
|
DWORD rc = ERROR_SUCCESS;
|
|
DWORD DataSize = 0;
|
|
PBYTE Data = NULL;
|
|
BOOL b;
|
|
|
|
pFreeGlobalIpcBuffer();
|
|
|
|
do {
|
|
b = GetIpcCommandResults (
|
|
IPC_GET_RESULTS_WIN9X,
|
|
&Data,
|
|
&DataSize,
|
|
&rc,
|
|
&TechnicalLogId,
|
|
&GuiLogId
|
|
);
|
|
|
|
if (g_AbortDllEvent) {
|
|
if (WaitForSingleObject (g_AbortDllEvent, 0) == WAIT_OBJECT_0) {
|
|
rc = ERROR_CANCELLED;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Loop if no data received, but process is alive
|
|
//
|
|
if (!b) {
|
|
if (!IsIpcProcessAlive()) {
|
|
rc = ERROR_NOACCESS;
|
|
break;
|
|
}
|
|
|
|
if (*g_CancelFlagPtr) {
|
|
rc = ERROR_CANCELLED;
|
|
break;
|
|
}
|
|
}
|
|
|
|
} while (!b);
|
|
|
|
if (b) {
|
|
//
|
|
// Save return param block and loop back for IPC_LOG or IPC_DONE
|
|
//
|
|
|
|
g_DataSize = DataSize;
|
|
g_Data = Data;
|
|
|
|
//
|
|
// Recognize log messages
|
|
//
|
|
if (!CANCELLED()) {
|
|
if (TechnicalLogId) {
|
|
|
|
//
|
|
// LOG message with three args: DllDesc, DllPath, User
|
|
//
|
|
LOG ((
|
|
LOG_ERROR,
|
|
(PCSTR) TechnicalLogId,
|
|
g_DllPath,
|
|
g_DllName,
|
|
S_EMPTY,
|
|
S_EMPTY
|
|
));
|
|
}
|
|
if (GuiLogId) {
|
|
LOG ((
|
|
LOG_ERROR,
|
|
(PCSTR) GuiLogId,
|
|
g_DllPath,
|
|
g_DllName,
|
|
S_EMPTY,
|
|
S_EMPTY
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
BOOL
|
|
pIsCodePageArrayValid (
|
|
IN PDWORD CodePageArray
|
|
)
|
|
{
|
|
DWORD CodePage;
|
|
UINT u;
|
|
|
|
if (!CodePageArray) {
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Scan system's code pages
|
|
//
|
|
|
|
CodePage = GetACP();
|
|
|
|
__try {
|
|
for (u = 0 ; CodePageArray[u] != -1 ; u++) {
|
|
if (CodePage == CodePageArray[u]) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
__except (TRUE) {
|
|
LOG ((LOG_ERROR, "Caugh an exception while validating array of code pages."));
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
LONG
|
|
CallQueryVersion (
|
|
IN PCSTR WorkingDir,
|
|
OUT PCSTR *ProductId,
|
|
OUT PUINT DllVersion,
|
|
OUT PCSTR *ExeNamesBuf,
|
|
OUT PVENDORINFO *VendorInfo
|
|
)
|
|
{
|
|
PDWORD CodePageArray = NULL;
|
|
LONG rc;
|
|
|
|
if (!g_UseMigIsol) {
|
|
//
|
|
// Call the entry point directly
|
|
//
|
|
|
|
MYASSERT (TestQueryVersion);
|
|
|
|
*ProductId = NULL;
|
|
*DllVersion = 1;
|
|
*ExeNamesBuf = NULL;
|
|
*VendorInfo = NULL;
|
|
|
|
SetCurrentDirectory (WorkingDir);
|
|
|
|
rc = TestQueryVersion (
|
|
ProductId,
|
|
DllVersion,
|
|
&CodePageArray,
|
|
ExeNamesBuf,
|
|
VendorInfo
|
|
);
|
|
|
|
} else {
|
|
|
|
rc = pRemoteQueryVersion (
|
|
ProductId,
|
|
DllVersion,
|
|
&CodePageArray,
|
|
ExeNamesBuf,
|
|
WorkingDir,
|
|
VendorInfo
|
|
);
|
|
|
|
}
|
|
|
|
DEBUGMSG ((DBG_MIGDLLS, "VendorInfo pointer is 0x%X", *VendorInfo));
|
|
|
|
if (rc == ERROR_SUCCESS) {
|
|
//
|
|
// Trim whitespace off of product ID
|
|
//
|
|
|
|
if (pValidateNonNullString (*ProductId)) {
|
|
*ProductId = SkipSpace (*ProductId);
|
|
if (pValidateBinary ((PBYTE) (*ProductId), SizeOfStringA (*ProductId))) {
|
|
TruncateTrailingSpace ((PSTR) (*ProductId));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate inbound parameters
|
|
//
|
|
|
|
if (!pValidateNonNullString (*ProductId) ||
|
|
!pValidateIntArray (CodePageArray) ||
|
|
!pValidateMultiString (*ExeNamesBuf) ||
|
|
!pValidateBinary ((PBYTE) (*VendorInfo), sizeof (VENDORINFO))
|
|
) {
|
|
LOG ((LOG_ERROR, "One or more parameters from the DLL are invalid."));
|
|
return ERROR_NOT_INSTALLED;
|
|
}
|
|
|
|
if (!pIsCodePageArrayValid (CodePageArray)) {
|
|
return ERROR_NOT_INSTALLED;
|
|
}
|
|
|
|
//
|
|
// Trim the product ID
|
|
//
|
|
|
|
if (ByteCountA (*ProductId) > MAX_PATH) {
|
|
*CharCountToPointerA (*ProductId, MAX_PATH) = 0;
|
|
}
|
|
|
|
//
|
|
// Make sure VENDORINFO is valid
|
|
//
|
|
if (!(*VendorInfo)) {
|
|
LOG ((LOG_ERROR, "DLL %s did not provide a VENDORINFO struct", *ProductId));
|
|
return ERROR_NOT_INSTALLED;
|
|
}
|
|
|
|
g_DllName = *ProductId;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
LONG
|
|
CallInitialize9x (
|
|
IN PCSTR WorkingDir,
|
|
IN PCSTR SourceDirList,
|
|
IN OUT PVOID Reserved,
|
|
IN DWORD ReservedSize
|
|
)
|
|
{
|
|
LONG rc;
|
|
CHAR WorkingDirCopy[MAX_MBCHAR_PATH];
|
|
PSTR SourceDirListCopy = NULL;
|
|
PCSTR p;
|
|
PVOID CopyOfReserved;
|
|
|
|
if (!g_UseMigIsol) {
|
|
//
|
|
// Call the entry point directly
|
|
//
|
|
|
|
MYASSERT (TestInitialize9x);
|
|
|
|
SetCurrentDirectory (WorkingDir);
|
|
|
|
//
|
|
// Make a copy of all the supplied params, so if the migration DLL changes
|
|
// them, the rest of the upgrade isn't changed.
|
|
//
|
|
|
|
StringCopyA (WorkingDirCopy, WorkingDir);
|
|
p = SourceDirList;
|
|
while (*p) {
|
|
p = GetEndOfStringA (p) + 1;
|
|
}
|
|
p++;
|
|
|
|
SourceDirListCopy = AllocText (p - SourceDirList);
|
|
MYASSERT (SourceDirListCopy);
|
|
if (SourceDirListCopy) {
|
|
CopyMemory (SourceDirListCopy, SourceDirList, p - SourceDirList);
|
|
}
|
|
|
|
//
|
|
// Call the entry point
|
|
//
|
|
|
|
rc = TestInitialize9x (
|
|
WorkingDirCopy,
|
|
SourceDirListCopy,
|
|
Reserved
|
|
);
|
|
|
|
FreeText (SourceDirListCopy);
|
|
|
|
} else {
|
|
|
|
//
|
|
// Call the entry point via migisol.exe. Make a copy of the
|
|
// reserved because currently reserved is only an IN (an
|
|
// undocumented feature actually).
|
|
//
|
|
|
|
CopyOfReserved = MemAlloc (g_hHeap, 0, ReservedSize);
|
|
CopyMemory (CopyOfReserved, Reserved, ReservedSize);
|
|
|
|
rc = pRemoteInitialize9x (
|
|
WorkingDir,
|
|
SourceDirList,
|
|
&CopyOfReserved,
|
|
ReservedSize
|
|
);
|
|
|
|
//
|
|
// CopyOfReserved now has the return value. We don't
|
|
// use it currently.
|
|
//
|
|
|
|
MemFree (g_hHeap, 0, CopyOfReserved);
|
|
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
LONG
|
|
CallMigrateUser9x (
|
|
IN HWND ParentWnd,
|
|
IN PCSTR UserName,
|
|
IN PCSTR UnattendTxt,
|
|
IN OUT PVOID Reserved,
|
|
IN DWORD ReservedSize
|
|
)
|
|
{
|
|
LONG rc;
|
|
CHAR UserNameBuf[MAX_USER_NAME];
|
|
CHAR UnattendTxtCopy[MAX_USER_NAME];
|
|
PSTR UserNameCopy = NULL;
|
|
HKEY UserHandle;
|
|
|
|
if (!g_UseMigIsol) {
|
|
//
|
|
// Call the entry point directly
|
|
//
|
|
|
|
MYASSERT (TestMigrateUser9x);
|
|
|
|
//
|
|
// Prepare copies of params
|
|
//
|
|
|
|
if (UserName && *UserName) {
|
|
UserNameCopy = UserNameBuf;
|
|
StringCopyA (UserNameCopy, UserName);
|
|
}
|
|
|
|
StringCopyA (UnattendTxtCopy, UnattendTxt);
|
|
|
|
MYASSERT(g_UserKey);
|
|
if (!g_UserKey) {
|
|
g_UserKey = S_EMPTY;
|
|
}
|
|
|
|
UserHandle = OpenRegKeyStr (g_UserKey);
|
|
if (!UserHandle) {
|
|
DEBUGMSG ((DBG_WHOOPS, "Cannot open %s", g_UserKey));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Call the migration DLL
|
|
//
|
|
|
|
rc = TestMigrateUser9x (
|
|
ParentWnd,
|
|
UnattendTxtCopy,
|
|
UserHandle,
|
|
UserNameCopy,
|
|
Reserved
|
|
);
|
|
|
|
} else {
|
|
//
|
|
// Call the entry point via migisol.exe
|
|
//
|
|
|
|
rc = pRemoteMigrateUser9x (
|
|
ParentWnd,
|
|
UnattendTxt,
|
|
g_UserKey,
|
|
UserName
|
|
);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
LONG
|
|
CallMigrateSystem9x (
|
|
IN HWND ParentWnd,
|
|
IN PCSTR UnattendTxt,
|
|
IN PVOID Reserved,
|
|
IN DWORD ReservedSize
|
|
)
|
|
{
|
|
LONG rc;
|
|
CHAR UnattendTxtCopy[MAX_MBCHAR_PATH];
|
|
|
|
if (!g_UseMigIsol) {
|
|
//
|
|
// Call the entry point directly
|
|
//
|
|
|
|
MYASSERT (TestMigrateSystem9x);
|
|
|
|
StringCopyA (UnattendTxtCopy, UnattendTxt);
|
|
|
|
rc = TestMigrateSystem9x (
|
|
ParentWnd,
|
|
UnattendTxtCopy,
|
|
Reserved
|
|
);
|
|
|
|
} else {
|
|
|
|
rc = pRemoteMigrateSystem9x (
|
|
ParentWnd,
|
|
UnattendTxt
|
|
);
|
|
|
|
}
|
|
|
|
g_DllName = NULL;
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|