windows-nt/Source/XPSP1/NT/net/rras/cm/migrate/main.cpp
2020-09-26 16:20:57 +08:00

1120 lines
37 KiB
C++

//+----------------------------------------------------------------------------
//
// File: main.cpp
//
// Module: MIGRATE.DLL
//
// Synopsis: Main entry point for Migrate.DLL
//
// Copyright (c) 1998-1999 Microsoft Corporation
//
// Author: quintinb created 08/21/98
//
//+----------------------------------------------------------------------------
#include "migrate.h"
#include "linkdll.h" // LinkToDll and BindLinkage for cmsecure.lib
#include "linkdll.cpp" // LinkToDll and BindLinkage for cmsecure.lib
const int c_NumFiles = 28;
char OriginalNames[c_NumFiles][MAX_PATH+1] = {
"\\showicon.exe",
"\\swflash.ocx",
"\\urlmon.dll",
"\\iexpress.exe",
"\\oleaut32.dll",
"\\wextract.exe",
"\\cm32\\enu\\advapi32.dll",
"\\cm32\\enu\\advpack.dll",
"\\cm32\\enu\\cmdial32.dll",
"\\cm32\\enu\\cmdl32.exe",
"\\cm32\\enu\\cmmgr32.exe",
"\\cm32\\enu\\cmmgr32.hlp",
"\\cm32\\enu\\cmpbk32.dll",
"\\cm32\\enu\\cmstats.dll",
"\\cm32\\enu\\comctl32.dll",
"\\cm32\\enu\\ccfg95.dll",
"\\cm32\\enu\\ccfgnt.dll",
"\\cm32\\enu\\icwscrpt.exe",
"\\cm32\\enu\\cnet16.dll",
"\\cm32\\enu\\cnetcfg.dll",
"\\cm32\\enu\\mbslgn32.dll",
"\\cm32\\enu\\readme.txt",
"\\cm32\\enu\\rnaph.dll",
"\\cm32\\enu\\w95inf16.dll",
"\\cm32\\enu\\w95inf32.dll",
"\\cm32\\enu\\wininet.dll",
"\\cm32\\enu\\wintrust.dll",
"\\cm32\\enu\\cmcfg32.dll",
};
char TempNames[c_NumFiles][MAX_PATH+1] = {
"\\showicon.tmp",
"\\swflash.tmp",
"\\urlmon.tmp",
"\\iexpress.tmp",
"\\oleaut32.tmp",
"\\wextract.tmp",
"\\advapi32.tmp",
"\\advpack.tmp",
"\\cmdial32.tmp",
"\\cmdl32.tmp",
"\\cmmgr32.001",
"\\cmmgr32.002",
"\\cmpbk32.tmp",
"\\cmstats.tmp",
"\\comctl32.tmp",
"\\ccfg95.tmp",
"\\ccfgnt.tmp",
"\\icwscrpt.tmp",
"\\cnet16.tmp",
"\\cnetcfg.tmp",
"\\mbslgn32.tmp",
"\\readme.tmp",
"\\rnaph.tmp",
"\\w95inf16.tmp",
"\\w95inf32.tmp",
"\\wininet.tmp",
"\\wintrust.tmp",
"\\cmcfg32.tmp",
};
//
// Global Vars
//
BOOL g_bMigrateCmak10;
BOOL g_bMigrateCmak121;
BOOL g_bMigrateCm;
BOOL g_fInitSecureCalled;
DWORD g_dwNumValues;
DWORD g_dwTlsIndex; // thread local storage index
HINSTANCE g_hInstance;
TCHAR g_szWorkingDir[MAX_PATH+1];
TCHAR g_szCmakPath[MAX_PATH+1];
VENDORINFO g_VendorInfo;
//+---------------------------------------------------------------------------
//
// Function: DllMain
//
// Synopsis: Main initialization function for this dll. Called whenever
// a new instance of this dll is loaded or a new thread created.
//
// Arguments: HINSTANCE hinstDLL - handle to DLL module
// DWORD fdwReason - reason for calling function
// LPVOID lpvReserved - reserved
//
// Returns: BOOL - TRUE if initialization was successful, FALSE otherwise
//
// History: quintinb Created Header 01/13/2000
//
//----------------------------------------------------------------------------
extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH)
{
//
// Init Globals
//
g_hInstance = hinstDLL;
g_fInitSecureCalled = FALSE;
g_bMigrateCmak10 = FALSE;
g_bMigrateCmak121 = FALSE;
ZeroMemory(g_szCmakPath, sizeof(g_szCmakPath));
//
// alloc tls index
//
g_dwTlsIndex = TlsAlloc();
if (g_dwTlsIndex == TLS_OUT_OF_INDEXES)
{
return FALSE;
}
MYVERIFY(DisableThreadLibraryCalls(hinstDLL));
}
else if (fdwReason == DLL_PROCESS_DETACH)
{
//
// free the tls index
//
if (g_dwTlsIndex != TLS_OUT_OF_INDEXES)
{
TlsFree(g_dwTlsIndex);
}
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: QueryVersion
//
// Synopsis: Supplies the Dll's version and identification information.
//
// Arguments: OUT LPCSTR *ProductID - buffer to hold a string that uniquely
// identifies the migration dll
// OUT LPUINT DllVersion - Pointer to an Integer to hold the version
// number of the migration DLL
// OUT LPINT *CodePageArray - pointer to an array of code pages that
// the migration dll supports
// OUT LPCSTR *ExeNamesBuf - a pointer to a multi-sz string. The
// buffer contains a null separated list
// of executable file names that the
// migration engine should search for.
// Full paths to all occurences of these
// executables will be copied to the
// [Migration Paths] section of migrate.inf.
// OUT PVENDORINFO *VendorInfo - pointer to a VENDORINFO structure
//
// Returns: LONG - ERROR_NOT_INSTALLED if the component that this dll is to
// migrate isn't installed. The migration dll won't be called
// in any of the other stages if this is the return value.
// ERROR_SUCCESS if the component that this dll is to migrate
// is installed and requires migration. This will allow the
// migration dll to be called again for further migration.
//
// History: quintinb Created Header 8/27/98
//
//+----------------------------------------------------------------------------
LONG CALLBACK QueryVersion(OUT LPCSTR *ProductID, OUT LPUINT DllVersion,
OUT LPINT *CodePageArray, OUT LPCSTR *ExeNamesBuf,
OUT PVENDORINFO *VendorInfo)
{
//
// Record our version information.
//
if (NULL != ProductID)
{
*ProductID = c_pszProductIdString;
}
if (NULL != DllVersion)
{
*DllVersion = uCmMigrationVersion;
}
if (NULL != CodePageArray)
{
*CodePageArray = NULL; // no code page dependencies, language neutral
}
if (NULL != ExeNamesBuf)
{
*ExeNamesBuf = NULL; //
}
if (NULL != VendorInfo)
{
*VendorInfo= &g_VendorInfo;
ZeroMemory(&g_VendorInfo, sizeof(VENDORINFO));
//
// Use the standard MS vendor info from vendinfo.mc
//
FormatMessage(
FORMAT_MESSAGE_FROM_HMODULE,
g_hInstance,
MSG_VI_COMPANY_NAME,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
&g_VendorInfo.CompanyName[0],
sizeof(g_VendorInfo.CompanyName),
NULL
);
FormatMessage(
FORMAT_MESSAGE_FROM_HMODULE,
g_hInstance,
MSG_VI_SUPPORT_NUMBER,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
&g_VendorInfo.SupportNumber[0],
sizeof(g_VendorInfo.SupportNumber),
NULL
);
FormatMessage(
FORMAT_MESSAGE_FROM_HMODULE,
g_hInstance,
MSG_VI_SUPPORT_URL,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
&g_VendorInfo.SupportUrl[0],
sizeof(g_VendorInfo.SupportUrl),
NULL
);
FormatMessage(
FORMAT_MESSAGE_FROM_HMODULE,
g_hInstance,
MSG_VI_INSTRUCTIONS,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
&g_VendorInfo.InstructionsToUser[0],
sizeof(g_VendorInfo.InstructionsToUser),
NULL
);
}
//
// Now try to detect if CMAK or CM are installed. If they are and the versions
// are such that they need to be migrated, then return ERROR_SUCCESS. Otherwise
// we don't need to do any migration, so return ERROR_NOT_INSTALLED.
//
LONG lReturnValue = ERROR_NOT_INSTALLED;
CmVersion CmVer;
if (CmVer.IsPresent())
{
lReturnValue = ERROR_SUCCESS;
}
else
{
CmakVersion CmakVer;
//
// Okay, CM wasn't installed so look for CMAK.
//
if (CmakVer.IsPresent())
{
//
// Okay, CMAK exists
//
lReturnValue = ERROR_SUCCESS;
}
}
return lReturnValue;
}
//+----------------------------------------------------------------------------
//
// Function: Initialize9x
//
// Synopsis: This function is called so that the migration dll can initialize
// itself on the Win9x side of the migration. The migration dll
// should not make any modifications to the system in this call, as
// it is only for initialization and searching to see if your component
// is installed.
//
// Arguments: IN LPCSTR WorkingDirectory - path of the temporary storage dir for
// the migration dll.
// IN LPCSTR SourceDirectories - a multi-sz list of the Win2k source
// directory or directories
// IN LPCSTR MediaDirectory - specifies the path to the original media
// directory
//
// Returns: LONG - ERROR_NOT_INSTALLED if the component that this dll is to
// migrate isn't installed. The migration dll won't be called
// in any of the other stages if this is the return value.
// ERROR_SUCCESS if the component that this dll is to migrate
// is installed and requires migration. This will allow the
// migration dll to be called again for further migration.
//
// History: quintinb Created Header 8/27/98
//
//+----------------------------------------------------------------------------
LONG CALLBACK Initialize9x(IN LPCSTR WorkingDirectory, IN LPCSTR SourceDirectories,
IN LPCSTR MediaDirectory)
{
HKEY hKey;
//
// Check to see if we need to Migrate CMAK
//
CmakVersion CmakVer;
lstrcpy(g_szWorkingDir, WorkingDirectory);
if (CmakVer.IsPresent())
{
if (CmakVer.GetInstallLocation(g_szCmakPath))
{
//
// Then we have a CMAK path. Write this to the handled key so that
// they won't mess with our files.
//
TCHAR szTemp[MAX_PATH+1];
wsprintf(szTemp, "%s\\migrate.inf", WorkingDirectory);
MYVERIFY(0 != WritePrivateProfileString(c_pszSectionHandled, g_szCmakPath,
c_pszDirectory, szTemp));
//
// Now try to figure out what version of CMAK we have to see if we need
// to run the migration DLL or not. If the CMAK.exe version is 6.00.613.0 (1.0)
// then we should migrate it. If it is higher than that, 1.1 or 1.2 it is
// beta and we shouldn't support the upgrade anyway (I purposely am not
// going to run the migration on it). If it is IE5 IEAK CMAK, then it should
// survive upgrade without a problem.
//
if (CmakVer.Is10Cmak())
{
g_bMigrateCmak10 = TRUE;
}
else if (CmakVer.Is121Cmak())
{
g_bMigrateCmak121 = TRUE;
}
}
}
//
// Check to see if we need to migrate CM Profiles
//
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmMappings, 0,
KEY_READ, &hKey))
{
if ((ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
&g_dwNumValues, NULL, NULL, NULL, NULL)) && (g_dwNumValues > 0))
{
//
// Then we have mappings values, so we need to migrate them.
//
g_bMigrateCm = TRUE;
}
RegCloseKey(hKey);
}
if (g_bMigrateCmak10 || g_bMigrateCmak121 || g_bMigrateCm)
{
return ERROR_SUCCESS;
}
else
{
return ERROR_NOT_INSTALLED;
}
}
//+----------------------------------------------------------------------------
//
// Function: MigrateUser9x
//
// Synopsis: Called once for each Win9x user being migrated. Its purpose is to
// allow migration of per user settings.
//
// Arguments: IN HWND ParentWnd - Window handle of the parent window, used if
// the migration dll needs to display UI. If NULL,
// running in unattended mode and no UI should be
// displayed.
// IN LPCSTR AnswerFile - Supplies the path to the answer file.
// IN HKEY UserRegKey - reg key for the HKEY_CURRENT_USER key of the
// user currently being migrated.
// IN LPCSTR UserName - username of the user being migrated
// LPVOID Reserved - reserved
//
// Returns: LONG - ERROR_NOT_INSTALLED - if no per user processing is required.
// ERROR_CANCELLED - if the user wants to exit setup
// ERROR_SUCCESS - the migration dll processed this user successfully
//
// History: quintinb Created Header 8/27/98
//
//+----------------------------------------------------------------------------
LONG
CALLBACK MigrateUser9x(IN HWND ParentWnd, IN LPCSTR AnswerFile,
IN HKEY UserRegKey, IN LPCSTR UserName, LPVOID Reserved)
{
return ERROR_NOT_INSTALLED;
}
//+----------------------------------------------------------------------------
//
// Function: MigrateSystem9x
//
// Synopsis: Allows migration of system wide settings on the Windows 9x side.
//
// Arguments: IN HWND ParentWnd - parent window handle for the display of UI,
// NULL if in unattended mode
// IN LPCSTR AnswerFile - full path to the answer file
// LPVOID Reserved - reserved
//
// Returns: LONG - ERROR_NOT_INSTALLED if the component that this dll is to
// migrate isn't installed. The migration dll won't be called
// in any of the other stages if this is the return value.
// ERROR_SUCCESS if the component that this dll is to migrate
// is installed and requires migration. This will allow the
// migration dll to be called again for further migration.
//
// History: quintinb Created Header 8/27/98
//
//+----------------------------------------------------------------------------
LONG
CALLBACK MigrateSystem9x(IN HWND ParentWnd, IN LPCSTR AnswerFile, LPVOID Reserved)
{
LONG lReturn = ERROR_NOT_INSTALLED;
TCHAR szSystemDir[MAX_PATH+1];
GetSystemDirectory(szSystemDir, MAX_PATH);
//
// Setup deletes a bunch of the files that 1.0 CMAK or IEAK5 CMAK need to function.
// Since we currently don't support NT5 CMAK on WKS, we need to copy these files
// to the setup provided working directory, so that we can copy them bak once
// we boot into NT.
//
if (g_bMigrateCmak10 && (TEXT('\0') != g_szCmakPath[0]) && (TEXT('\0') != g_szWorkingDir[0]))
{
TCHAR szDest[MAX_PATH+1];
TCHAR szSrc[MAX_PATH+1];
for (int i=0; i < c_NumFiles; i++)
{
MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s%s"), g_szCmakPath, OriginalNames[i]));
MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s%s"), g_szWorkingDir, TempNames[i]));
if (FileExists(szSrc))
{
MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
}
}
lReturn &= ERROR_SUCCESS;
}
else if (g_bMigrateCmak121 && (TEXT('\0') != szSystemDir[0]) &&
(TEXT('\0') != g_szWorkingDir[0]))
{
TCHAR szDest[MAX_PATH+1];
TCHAR szSrc[MAX_PATH+1];
//
// Copy w95inf16.dll to the working directory and rename it w95inf16.tmp
//
MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s\\%s%s"), szSystemDir, c_pszW95Inf16, c_pszDll));
MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s%s"), g_szWorkingDir, c_pszW95Inf16, c_pszTmp));
if (FileExists(szSrc))
{
MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
}
//
// Copy w95inf32.dll to the working directory and rename it w95inf32.tmp
//
MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s\\%s%s"), szSystemDir, c_pszW95Inf32, c_pszDll));
MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s%s"), g_szWorkingDir, c_pszW95Inf32, c_pszTmp));
if (FileExists(szSrc))
{
MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
}
lReturn &= ERROR_SUCCESS;
}
if (g_bMigrateCm)
{
//
// Enumerate all the installed profiles on the machine. For each profile check
// for a UserInfo\<CurrentServiceNameKey>. If this key exists, then go to the next
// profile or user. If it doesn't exist, then read the data from the cmp file. If
// the cmp has data marked as being stored then we need to save the password. If
// the password isn't in the cmp then it is in the wnet cache. We must then
// retrieve it.
//
HKEY hKey;
HKEY hTempKey;
TCHAR szTemp[MAX_PATH+1];
TCHAR szLongServiceName[MAX_PATH+1];
TCHAR szCmpPath[MAX_PATH+1];
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmMappings, 0, KEY_READ,
&hKey))
{
DWORD dwIndex = 0;
DWORD dwValueSize = MAX_PATH;
DWORD dwDataSize = MAX_PATH;
DWORD dwType;
while (ERROR_SUCCESS == RegEnumValue(hKey, dwIndex, szLongServiceName,
&dwValueSize, NULL, &dwType, (LPBYTE)szCmpPath, &dwDataSize))
{
if (REG_SZ == dwType)
{
MYDBGASSERT(TEXT('\0') != szLongServiceName[0]);
MYDBGASSERT(TEXT('\0') != szCmpPath[0]);
//
// If the user saved their password or their Internet password,
// then we must make sure that it exists in the cmp (in encrypted form)
// so that when the user runs CM on the NT5 side of the migration,
// CM will move the settings to the new format. Note, that if the
// cmp doesn't specify that the password(s) be saved, then this
// function just returns as there is no password to ensure is in the
// cmp.
MYVERIFY(EnsureEncryptedPasswordInCmpIfSaved(szLongServiceName, szCmpPath));
}
dwValueSize = MAX_PATH;
dwDataSize = MAX_PATH;
dwIndex++;
if (dwIndex == g_dwNumValues)
{
break;
}
}
MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey));
}
lReturn &= ERROR_SUCCESS;
}
return lReturn;
}
//+----------------------------------------------------------------------------
//
// Function: InitializeNT
//
// Synopsis: First function called on the Win2k side of the migration, used to
// setup the Win2k migration. Similar to Initialize9x but on the Win2k
// side. No changes to the system should be made in this function.
//
// Arguments: IN LPCWSTR WorkingDirectory - temporary storage, same as path given
// on the Win9x side
// IN LPCWSTR SourceDirectories - a multi-sz list of the Win2k source
// directory or directories
// LPVOID Reserved - reserved
//
// Returns: LONG - ERROR_SUCCESS unless an init error occurs.
//
// History: quintinb Created Header 8/27/98
//
//+----------------------------------------------------------------------------
LONG
CALLBACK InitializeNT(IN LPCWSTR WorkingDirectory, IN LPCWSTR SourceDirectories, LPVOID Reserved)
{
HKEY hKey;
//
// Convert the WorkingDirectory to MultiByte
//
MYVERIFY (0 != WideCharToMultiByte(CP_THREAD_ACP, WC_COMPOSITECHECK, WorkingDirectory, -1,
g_szWorkingDir, MAX_PATH, NULL, NULL));
//
// Check to see if we need to Migrate CMAK
//
CmakVersion CmakVer;
if (CmakVer.IsPresent())
{
if (CmakVer.GetInstallLocation(g_szCmakPath))
{
//
// Now try to figure out what version of CMAK we have to see if we need
// to run the migration DLL or not. If the CMAK.exe version is 6.00.613.0 (1.0)
// then we should migrate it. If it is higher than that, 1.1 or 1.2 it is
// beta and we shouldn't support the upgrade anyway (I purposely am not
// going to run the migration on it). If it is IE5 IEAK CMAK, then it should
// survive upgrade without a problem.
//
if (CmakVer.Is10Cmak())
{
g_bMigrateCmak10 = TRUE;
}
else if (CmakVer.Is121Cmak())
{
g_bMigrateCmak121 = TRUE;
}
}
}
//
// Check to see if we need to migrate CM Profiles
//
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmMappings, 0,
KEY_READ, &hKey))
{
if ((ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
&g_dwNumValues, NULL, NULL, NULL, NULL)) && (g_dwNumValues > 0))
{
//
// Then we have mappings values, so we need to migrate them.
//
g_bMigrateCm = TRUE;
}
RegCloseKey(hKey);
}
if (g_bMigrateCmak10 || g_bMigrateCmak121 || g_bMigrateCm)
{
return ERROR_SUCCESS;
}
else
{
return ERROR_NOT_INSTALLED;
}
}
//+----------------------------------------------------------------------------
//
// Function: MigrateUserNT
//
// Synopsis: Called once per migrated user on win2k. Used to migrated any
// per user settings saved from MigrateUser9x.
//
// Arguments: IN HINF UnattendInfHandle - valid inf handle to unattend.txt,
// for use with the setup API's
// IN HKEY UserRegHandle - HKEY_CURRENT_USER of the user currently
// being migrated
// IN LPCWSTR UserName - username of the user currently being migrated
// LPVOID Reserved - reserved
//
// Returns: LONG - ERROR_SUCCESS or a win32 error code (will abort migration dll
// processing)
//
// History: quintinb Created Header 8/27/98
//
//+----------------------------------------------------------------------------
LONG
CALLBACK MigrateUserNT(IN HINF UnattendInfHandle, IN HKEY UserRegHandle,
IN LPCWSTR UserName, LPVOID Reserved)
{
return ERROR_SUCCESS;
}
//+----------------------------------------------------------------------------
//
// Function: MigrateSystemNT
//
// Synopsis: Called to allow system wide migration changes to be made on the
// Win2k side.
//
// Arguments: IN HINF UnattendInfHandle - handle to the unattend.txt file
// LPVOID Reserved - reserved
//
// Returns: LONG - ERROR_SUCCESS or a win32 error code (will abort migration dll
// processing)
//
// History: quintinb Created Header 8/27/98
//
//+----------------------------------------------------------------------------
LONG
CALLBACK MigrateSystemNT(IN HINF UnattendInfHandle, LPVOID Reserved)
{
LONG lReturn = ERROR_NOT_INSTALLED;
DWORD dwDisposition;
TCHAR szSystemDir[MAX_PATH+1];
GetSystemDirectory(szSystemDir, MAX_PATH);
const TCHAR* const c_pszSystemFmt = TEXT("%s\\system\\%s.inf");
const TCHAR* const c_pszValueString = TEXT("Connection Manager Profiles Upgrade");
const TCHAR* const c_pszRegRunKey = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
const TCHAR* const c_pszCmdLine = TEXT("cmstp.exe /m");
if (g_bMigrateCmak10 && (TEXT('\0') != g_szCmakPath[0]) && (TEXT('\0') != g_szWorkingDir[0]))
{
TCHAR szDest[MAX_PATH+1];
TCHAR szSrc[MAX_PATH+1];
for (int i=0; i < c_NumFiles; i++)
{
MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s%s"), g_szCmakPath,
OriginalNames[i]));
MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s%s"), g_szWorkingDir,
TempNames[i]));
if (FileExists(szSrc))
{
MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
}
}
lReturn &= ERROR_SUCCESS;
}
else if (g_bMigrateCmak121 && (TEXT('\0') != g_szCmakPath[0]) &&
(TEXT('\0') != szSystemDir[0]))
{
TCHAR szDest[MAX_PATH+1];
TCHAR szSrc[MAX_PATH+1];
//
// Copy w95inf16.tmp in the working dir back to the systemdir and rename it .dll
//
MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s\\%s%s"), g_szWorkingDir,
c_pszW95Inf16, c_pszTmp));
MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s%s"), szSystemDir,
c_pszW95Inf16, c_pszDll));
if (FileExists(szSrc))
{
MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
}
//
// Copy w95inf32.tmp in the working dir back to the systemdir and rename it .dll
//
MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s\\%s%s"), g_szWorkingDir,
c_pszW95Inf32, c_pszTmp));
MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s%s"), szSystemDir,
c_pszW95Inf32, c_pszDll));
if (FileExists(szSrc))
{
MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
}
lReturn &= ERROR_SUCCESS;
}
if (g_bMigrateCm)
{
//
// Enumerate all the installed profiles on the machine. For each profile check to
// see if the profile inf is located in the system (that's system not system32) dir.
// If it is, then we need to move it to system32 so that our code will know where to
// find it.
//
HKEY hKey;
HKEY hTempKey;
TCHAR szSource[MAX_PATH+1];
TCHAR szDest[MAX_PATH+1];
TCHAR szLongServiceName[MAX_PATH+1];
TCHAR szWindowsDir[MAX_PATH+1];
TCHAR szSystemDir[MAX_PATH+1];
TCHAR szCmpPath[MAX_PATH+1];
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmMappings,
0, KEY_READ, &hKey))
{
DWORD dwIndex = 0;
DWORD dwValueSize = MAX_PATH;
DWORD dwDataSize = MAX_PATH;
DWORD dwType;
while (ERROR_SUCCESS == RegEnumValue(hKey, dwIndex, szLongServiceName,
&dwValueSize, NULL, &dwType, (LPBYTE)szCmpPath, &dwDataSize))
{
if (REG_SZ == dwType)
{
MYDBGASSERT(TEXT('\0') != szLongServiceName[0]);
MYDBGASSERT(TEXT('\0') != szCmpPath[0]);
CFileNameParts CmpPath(szCmpPath);
GetWindowsDirectory(szWindowsDir, MAX_PATH);
MYDBGASSERT(TEXT('\0') != szWindowsDir[0]);
GetSystemDirectory(szSystemDir, MAX_PATH);
MYDBGASSERT(TEXT('\0') != szSystemDir[0]);
MYVERIFY(CELEMS(szSource) > (UINT)wsprintf(szSource, c_pszSystemFmt, szWindowsDir, CmpPath.m_FileName));
MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s.inf"), szSystemDir, CmpPath.m_FileName));
if (CopyFile(szSource, szDest, FALSE))
{
DeleteFile(szSource);
}
}
dwValueSize = MAX_PATH;
dwDataSize = MAX_PATH;
dwIndex++;
if (dwIndex == g_dwNumValues)
{
break;
}
}
MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey));
}
if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, c_pszRegRunKey, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL, &hKey, &dwDisposition))
{
RegSetValueEx(hKey, c_pszValueString, 0, REG_SZ, (CONST BYTE*)c_pszCmdLine,
sizeof(TCHAR)*(lstrlen(c_pszCmdLine)+1));
RegCloseKey(hKey);
}
lReturn &= ERROR_SUCCESS;
}
return lReturn;
}
//+----------------------------------------------------------------------------
//
// Function: EnsureEncryptedPasswordInCmpIfSaved
//
// Synopsis: This function is called on the Win9x side of the migration so
// that if a password is in the Win9x password cache (which only
// happens if the user has profiling enabled), it will be retrieved,
// encrypted, and written to the cmp. This enables CM to populate
// a users registry with the starting password whenever they first
// launch the CM profile. This no functionality is lost from the
// shared password feature that win9x had.
//
// Arguments: szLongServiceName - Service name of the profile to retrieve
// the password for
// szCmpPath - full path to the cmp to write the password too
//
// Returns: BOOL - returns TRUE if successful
//
// History: quintinb Created 08/27/98
// nickball CmWipePassword 08/04/99
//
//+----------------------------------------------------------------------------
BOOL EnsureEncryptedPasswordInCmpIfSaved(LPCTSTR pszLongServiceName, LPCTSTR pszCmpPath)
{
TCHAR szPassword[MAX_PATH+1] = TEXT("");
TCHAR szCacheEntryName[MAX_PATH+1];
TCHAR szEncryptedPassword[MAX_PATH+1];
DWORD dwSize;
DWORD dwCryptType = 0;
GetCachedPassword pfnGetCachedPassword = NULL;
int iTemp=0;
CDynamicLibrary MprDll(TEXT("mpr.dll"));
iTemp = GetPrivateProfileInt(c_pszCmSection, c_pszCmEntryRememberPwd, 0, pszCmpPath);
if (iTemp)
{
GetPrivateProfileString(c_pszCmSection, c_pszCmEntryPassword, TEXT(""), szPassword, MAX_PATH, pszCmpPath);
if (TEXT('\0') == szPassword[0])
{
//
// The string must be in the password cache. Build the key string
// for the cache.
//
MYVERIFY(CELEMS(szCacheEntryName) > (UINT)wsprintf(szCacheEntryName,
TEXT("%s - Sign-In (Connection Manager)"), pszLongServiceName));
pfnGetCachedPassword = (GetCachedPassword)MprDll.GetProcAddress(TEXT("WNetGetCachedPassword"));
if (NULL == pfnGetCachedPassword)
{
CmWipePassword(szPassword);
return FALSE;
}
else
{
WORD wStr = (WORD)256;
if (ERROR_SUCCESS == pfnGetCachedPassword(szCacheEntryName,
(WORD)lstrlen(szCacheEntryName), szPassword, &wStr, 80))
{
//
// Okay, we retrived the password, now lets encrypt it and write it
// to the cmp
//
if (EncryptPassword(szPassword, szEncryptedPassword, &dwSize, &dwCryptType))
{
//
// Write the encrypted password
//
WritePrivateProfileString(c_pszCmSection, c_pszCmEntryPassword, szEncryptedPassword,
pszCmpPath);
//
// Write the encryption type
//
wsprintf(szPassword, TEXT("%u"), dwCryptType);
WritePrivateProfileString(c_pszCmSection, c_pszCmEntryPcs, szPassword,
pszCmpPath);
}
}
}
}
}
//
// Now do the same for the Internet Password
//
iTemp = GetPrivateProfileInt(c_pszCmSection, c_pszCmEntryRememberInetPwd, 0, pszCmpPath);
if (iTemp)
{
GetPrivateProfileString(c_pszCmSection, c_pszCmEntryInetPassword, TEXT(""), szPassword, MAX_PATH, pszCmpPath);
if (TEXT('\0') == szPassword[0])
{
//
// The string must be in the password cache. Build the key string
// for the cache.
//
MYVERIFY(CELEMS(szCacheEntryName) > (UINT)wsprintf(szCacheEntryName,
TEXT("%s - Sign-In (Connection Manager)-tunnel"), pszLongServiceName));
pfnGetCachedPassword = (GetCachedPassword)MprDll.GetProcAddress(TEXT("WNetGetCachedPassword"));
if (NULL == pfnGetCachedPassword)
{
CmWipePassword(szPassword);
return FALSE;
}
else
{
WORD wStr = (WORD)256;
if (ERROR_SUCCESS == pfnGetCachedPassword(szCacheEntryName,
(WORD)lstrlen(szCacheEntryName), szPassword, &wStr, 80))
{
//
// Okay, we retrived the password, now lets encrypt it and write it
// to the cmp
//
dwCryptType = 0;
if (EncryptPassword(szPassword, szEncryptedPassword, &dwSize, &dwCryptType))
{
//
// Write the encrypted password
//
WritePrivateProfileString(c_pszCmSection, c_pszCmEntryInetPassword, szEncryptedPassword,
pszCmpPath);
//
// Write the encryption type
//
wsprintf(szPassword, TEXT("%u"), dwCryptType);
WritePrivateProfileString(c_pszCmSection, c_pszCmEntryPcs, szPassword,
pszCmpPath);
}
}
}
}
}
CmWipePassword(szPassword);
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: EncryptPassword
//
// Synopsis:
//
// Arguments: IN LPCTSTR pszPassword -
// OUT LPTSTR pszEncryptedPassword -
// OUT LPDWORD lpdwBufSize -
// OUT LPDWORD lpdwCryptType -
//
// Returns: BOOL -
//
// History: quintinb Created Header 8/27/98
// nickball CmWipePassword 08/04/99
//
//+----------------------------------------------------------------------------
BOOL EncryptPassword(IN LPCTSTR pszPassword, OUT LPTSTR pszEncryptedPassword, OUT LPDWORD lpdwBufSize, OUT LPDWORD lpdwCryptType)
{
MYDBGASSERT(pszPassword);
MYDBGASSERT(pszEncryptedPassword);
MYDBGASSERT(lpdwBufSize);
MYDBGASSERT(lpdwCryptType);
DWORD dwEncryptedBufferLen;
DWORD dwSize = 0;
LPTSTR pszEncryptedData = NULL;
TCHAR szSourceData[PWLEN + sizeof(TCHAR)];
if ((NULL == pszPassword) || (NULL == pszEncryptedPassword) || (NULL == lpdwBufSize))
{
return NULL;
}
//
// Standard encryption, copy the password
//
lstrcpy(szSourceData, pszPassword);
//
// It is not safe to call InitSecure more than once
//
if (!g_fInitSecureCalled)
{
BOOL bFastEncryption = FALSE;
MYVERIFY(FALSE != ReadEncryptionOption(&bFastEncryption));
InitSecure(bFastEncryption);
g_fInitSecureCalled = TRUE;
}
//
// Encrypt the provided password
//
if (EncryptData((LPBYTE)szSourceData, (lstrlen(szSourceData)+1) * sizeof(TCHAR),
(LPBYTE*)&pszEncryptedData, &dwEncryptedBufferLen, lpdwCryptType, NULL, NULL, NULL))
{
if (lpdwBufSize)
{
*lpdwBufSize = dwEncryptedBufferLen;
}
if (pszEncryptedData)
{
_tcscpy(pszEncryptedPassword, pszEncryptedData);
HeapFree(GetProcessHeap(), 0, pszEncryptedData);
pszEncryptedData = NULL;
CmWipePassword(szSourceData);
return TRUE;
}
}
CmWipePassword(szSourceData);
return FALSE;
}
//+----------------------------------------------------------------------------
//
// Function: ReadEncryptionOption
//
// Synopsis:
//
// Arguments: BOOL* pfFastEncryption - boolean to fill in with fast encryption flag
//
// Returns: BOOL - TRUE if successful
//
// History: quintinb Created Header 8/27/98
// copied from the version written by Fengsun in cmdial\connect.cpp
//
//+----------------------------------------------------------------------------
BOOL ReadEncryptionOption(BOOL* pfFastEncryption)
{
HKEY hKeyCm;
DWORD dwType;
DWORD dwSize = sizeof(DWORD);
MYDBGASSERT(pfFastEncryption != NULL);
*pfFastEncryption = FALSE;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmRoot, 0,
KEY_QUERY_VALUE ,&hKeyCm))
{
RegQueryValueEx(hKeyCm, c_pszRegCmEncryptOption, NULL, &dwType,
(BYTE*)pfFastEncryption, &dwSize);
RegCloseKey(hKeyCm);
}
return TRUE;
}