Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2329 lines
65 KiB

#include "StdAfx.h"
#include <stddef.h>
#include <objidl.h>
#include <objbase.h>
#include <shlobj.h>
#include <wtsapi32.h>
#include <psapi.h>
// Log file created by "winnt32 /checkupgradeonly"
#define TEXT_UPGRADE_LOG TEXT("%SystemRoot%\\Upgrade.txt")
// Value name in registry to keep track of machine state
#define CLMT_MACHINE_STATE_REG_VALUE TEXT("MachineState")
// Read me file name
#define TEXT_README_FILE TEXT("Readme.txt")
// constants used to determine SKU
#define SKU_SRV 1
#define SKU_ADS 2
#define SKU_DTC 3
// Maximum entries for list of applications running on the system
#define MAX_APP_ENTRIES 100
typedef struct _UPGRADE_LOG_PARAM
{
LPVOID lpText;
size_t cbText;
BOOL fUnicode;
} UPGRADE_LOG_PARAM, *PUPGRADE_LOG_PARAM;
typedef struct _stAppListParam
{
DWORD dwNumEntries;
LPTSTR lpAppName[MAX_APP_ENTRIES];
} APPLIST_PARAM, *PAPPLIST_PARAM;
typedef UINT (WINAPI* PFNGETMODULENAME)(HWND, LPTSTR, UINT);
typedef HMODULE (WINAPI* PFNGETMODULEHANDLE)(LPCTSTR);
typedef struct _GETMODULENAME
{
PFNGETMODULENAME pfn;
PFNGETMODULEHANDLE pfnGetModuleHandle;
TCHAR szfname[MAX_PATH];
TCHAR szUser32[8];
HWND hWnd;
PVOID pvCode;
} GETMODULENAME, *PGETMODULENAME;
BOOL LaunchWinnt32(LPCTSTR);
BOOL AskUserForDotNetCDPath(LPTSTR);
BOOL FindUpgradeLog(VOID);
BOOL IsDotNetWinnt32(LPCTSTR);
INT ShowUpgradeLog(VOID);
BOOL CheckUnsupportComponent(LPVOID, BOOL);
BOOL CALLBACK UpgradeLogDlgProc(HWND, UINT, WPARAM, LPARAM);
HRESULT ReadTextFromFile(LPCTSTR, LPVOID*, size_t*, BOOL*);
BOOL IsOperationOK(DWORD, DWORD, LPDWORD, PUINT);
BOOL CALLBACK EnumWindowProc();
BOOL CALLBACK StartUpDlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL StartProcess(LPCTSTR, LPTSTR, LPCTSTR);
LPCTSTR GetWindowModuleFileNameOnly(HWND hWnd, LPTSTR lpszFile, DWORD cchFile);
//-----------------------------------------------------------------------------
//
// Function: CheckSystemCriteria
//
// Synopsis:
//
// Returns: - Ok the continue the tool
// - Not ok to continue the tools
// - Unexpected error occured
//
// History: 09/14/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL CheckSystemCriteria(VOID)
{
HRESULT hr;
LCID lcid;
OSVERSIONINFOEX osviex;
if (IsNEC98())
{
DoMessageBox(GetConsoleWindow(), IDS_NEC98, IDS_MAIN_TITLE, MB_OK);
return FALSE;
}
if (IsIA64())
{
DoMessageBox(GetConsoleWindow(), IDS_IA64, IDS_MAIN_TITLE, MB_OK);
return FALSE;
}
if (g_dwRunningStatus == CLMT_DOMIG)
{
if (!IsNT5())
{
DoMessageBox(GetConsoleWindow(), IDS_NT5, IDS_MAIN_TITLE, MB_OK);
return FALSE;
}
if (IsDomainController())
{
// If this machine is a domain controller, we need W2K SP2
ZeroMemory(&osviex, sizeof(OSVERSIONINFOEX));
osviex.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx((LPOSVERSIONINFO) &osviex);
if (osviex.wServicePackMajor < 2)
{
DoMessageBox(GetConsoleWindow(), IDS_NT5SP2, IDS_MAIN_TITLE, MB_OK);
return FALSE;
}
//
// Also pop up the message asking admin to take machine
// off the network if it is in DC replication servers
//
DoMessageBox(GetConsoleWindow(),
IDS_DC_REPLICA_OFFLINE,
IDS_MAIN_TITLE,
MB_OK);
}
}
else if (g_dwRunningStatus == CLMT_CLEANUP_AFTER_UPGRADE)
{
if (!IsDotNet())
{
return FALSE;
}
}
else
{
// noop
}
if (IsOnTSClient())
{
DoMessageBox(GetConsoleWindow(), IDS_ON_TS_CLIENT, IDS_MAIN_TITLE, MB_OK);
return FALSE;
}
if (IsOtherSessionOnTS())
{
DoMessageBox(GetConsoleWindow(), IDS_TS_CLOSE_SESSION, IDS_MAIN_TITLE, MB_OK);
return FALSE;
}
hr = GetSavedInstallLocale(&lcid);
if (HRESULT_CODE(hr) == ERROR_FILE_NOT_FOUND)
{
hr = SaveInstallLocale();
if (FAILED(hr))
{
return FALSE;
}
}
return TRUE;
}
BOOL IsOneInstance(VOID)
{
HRESULT hr;
TCHAR szGlobalText[MAX_PATH];
hr = StringCchPrintf(szGlobalText,
ARRAYSIZE(szGlobalText),
TEXT("Global\\%s"),
TEXT("CLMT Is Running"));
if (FAILED(hr))
{
return FALSE;
}
g_hMutex = CreateMutex(NULL, FALSE, szGlobalText);
if ((g_hMutex == NULL) && (GetLastError() == ERROR_PATH_NOT_FOUND))
{
g_hMutex = CreateMutex(NULL, FALSE, TEXT("CLMT Is Running"));
if (g_hMutex == NULL)
{
//
// An error (like out of memory) has occurred.
// Bail now.
//
DoMessageBox(GetConsoleWindow(), IDS_OUT_OF_MEMORY, IDS_MAIN_TITLE, MB_OK);
return FALSE;
}
}
//
// Make sure we are the only process with a handle to our named mutex.
//
if ((g_hMutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS))
{
DoMessageBox(GetConsoleWindow(), IDS_ALREADY_RUNNING, IDS_MAIN_TITLE, MB_OK);
return FALSE;
}
return TRUE;
}
BOOL CheckAdminPrivilege(VOID)
{
BOOL bIsAdmin;
BOOL bRet = FALSE;
if (!IsAdmin())
{
if (g_dwRunningStatus == CLMT_DOMIG)
{
DoMessageBox(GetConsoleWindow(), IDS_ADMIN, IDS_MAIN_TITLE, MB_OK);
}
else if ( (g_dwRunningStatus == CLMT_CURE_PROGRAM_FILES)
|| (g_dwRunningStatus == CLMT_CURE_ALL) )
{
DoMessageBox(GetConsoleWindow(), IDS_ADMIN_RELOGON, IDS_MAIN_TITLE, MB_OK);
}
else if (g_dwRunningStatus == CLMT_CLEANUP_AFTER_UPGRADE)
{
DoMessageBox(GetConsoleWindow(), IDS_ADMIN_LOGON_DOTNET, IDS_MAIN_TITLE, MB_OK);
}
return FALSE;
}
if(!DoesUserHavePrivilege(SE_SHUTDOWN_NAME)
|| !DoesUserHavePrivilege(SE_BACKUP_NAME)
|| !DoesUserHavePrivilege(SE_RESTORE_NAME)
|| !DoesUserHavePrivilege(SE_SYSTEM_ENVIRONMENT_NAME))
{
DoMessageBox(GetConsoleWindow(), IDS_ADMIN, IDS_MAIN_TITLE, MB_OK);
return FALSE;
}
if(!EnablePrivilege(SE_SHUTDOWN_NAME,TRUE)
|| !EnablePrivilege(SE_BACKUP_NAME,TRUE)
|| !EnablePrivilege(SE_RESTORE_NAME,TRUE)
|| !EnablePrivilege(SE_SYSTEM_ENVIRONMENT_NAME,TRUE))
{
DoMessageBox(GetConsoleWindow(), IDS_ADMIN, IDS_MAIN_TITLE, MB_OK);
return FALSE;
}
return TRUE;
}
//-----------------------------------------------------------------------------
//
// Function: CheckCLMTStatus
//
// Synopsis: Check the machine status and CLMT running mode.
//
// Returns: S_OK - Ok the continue the tool
// S_FALSE - Not ok to continue the tools
// Else - Unexpected error occured
//
// History: 03/12/2002 rerkboos created
// 07/09/2002 rerkboos modified
//
// Notes: none
//
//-----------------------------------------------------------------------------
HRESULT CheckCLMTStatus(
LPDWORD lpdwCurrentState, // Current machine state before the operation
LPDWORD lpdwNextState, // Next state if the operation finish successfully
PUINT lpuResourceID // Resource ID of the error string
)
{
HRESULT hr;
BOOL bIsOK;
if (lpdwCurrentState == NULL || lpdwNextState == NULL)
{
return E_INVALIDARG;
}
// Get the current machine state
hr = CLMTGetMachineState(lpdwCurrentState);
if (SUCCEEDED(hr))
{
bIsOK = IsOperationOK(*lpdwCurrentState,
g_dwRunningStatus,
lpdwNextState,
lpuResourceID);
hr = (bIsOK == TRUE ? S_OK : S_FALSE);
}
return hr;
}
//-----------------------------------------------------------------------------
//
// Function: IsOperationOK
//
// Synopsis: Verify that the current operation is okay to perform on current
// state of the system.
//
// Returns: TRUE - ok to perform operation
// FALSE - otherwise
//
// History: 03/12/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL IsOperationOK(
DWORD dwCurrentState, // Current state of the system
DWORD dwAction, // Action to perform
LPDWORD lpdwNextState, // Next state after performing the action
LPUINT lpuResourceID // Resource ID for the error message
)
{
BOOL bRet = FALSE;
int i;
struct CLMT_STATE_MACHINE
{
DWORD dwCurrentState;
DWORD dwAction;
DWORD dwNextState;
};
const struct CLMT_STATE_MACHINE smCLMT[] =
{
CLMT_STATE_ORIGINAL, CLMT_DOMIG, CLMT_STATE_MIGRATION_DONE,
CLMT_STATE_MIGRATION_DONE, CLMT_UNDO_PROGRAM_FILES, CLMT_STATE_PROGRAMFILES_UNDONE,
CLMT_STATE_MIGRATION_DONE, CLMT_UNDO_APPLICATION_DATA, CLMT_STATE_APPDATA_UNDONE,
CLMT_STATE_MIGRATION_DONE, CLMT_UNDO_ALL, CLMT_STATE_ORIGINAL,
CLMT_STATE_MIGRATION_DONE, CLMT_CLEANUP_AFTER_UPGRADE, CLMT_STATE_FINISH,
CLMT_STATE_MIGRATION_DONE, CLMT_CURE_PROGRAM_FILES, CLMT_STATE_PROGRAMFILES_CURED,
CLMT_STATE_MIGRATION_DONE, CLMT_CURE_AND_CLEANUP, CLMT_STATE_MIGRATION_DONE,
CLMT_STATE_MIGRATION_DONE, CLMT_CURE_ALL, CLMT_STATE_PROGRAMFILES_CURED,
CLMT_STATE_PROGRAMFILES_CURED, CLMT_CURE_ALL, CLMT_STATE_PROGRAMFILES_CURED,
CLMT_STATE_PROGRAMFILES_CURED, CLMT_CLEANUP_AFTER_UPGRADE, CLMT_STATE_FINISH,
CLMT_STATE_PROGRAMFILES_CURED, CLMT_CURE_AND_CLEANUP, CLMT_STATE_FINISH,
CLMT_STATE_PROGRAMFILES_UNDONE, CLMT_UNDO_APPLICATION_DATA, CLMT_STATE_ORIGINAL,
CLMT_STATE_PROGRAMFILES_UNDONE, CLMT_UNDO_ALL, CLMT_STATE_ORIGINAL,
CLMT_STATE_PROGRAMFILES_UNDONE, CLMT_DOMIG, CLMT_STATE_MIGRATION_DONE,
CLMT_STATE_APPDATA_UNDONE, CLMT_UNDO_PROGRAM_FILES, CLMT_STATE_ORIGINAL,
CLMT_STATE_APPDATA_UNDONE, CLMT_UNDO_ALL, CLMT_STATE_ORIGINAL,
CLMT_STATE_APPDATA_UNDONE, CLMT_DOMIG, CLMT_STATE_MIGRATION_DONE,
CLMT_STATE_PROGRAMFILES_CURED, CLMT_CURE_PROGRAM_FILES, CLMT_STATE_PROGRAMFILES_CURED,
CLMT_STATE_FINISH, CLMT_CURE_PROGRAM_FILES, CLMT_STATE_FINISH,
CLMT_STATE_FINISH, CLMT_CURE_ALL, CLMT_STATE_FINISH,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
};
for (i = 0 ; smCLMT[i].dwCurrentState != 0xFFFFFFFF ; i++)
{
if (smCLMT[i].dwCurrentState == dwCurrentState)
{
if (smCLMT[i].dwAction == dwAction)
{
*lpdwNextState = smCLMT[i].dwNextState;
bRet = TRUE;
}
}
}
if (!bRet)
{
switch (dwCurrentState)
{
case CLMT_STATE_ORIGINAL:
*lpuResourceID = IDS_BAD_OPERATION_ORIGINAL;
break;
case CLMT_STATE_MIGRATION_DONE:
case CLMT_STATE_PROGRAMFILES_CURED:
*lpuResourceID = IDS_BAD_OPERATION_MIGDONE;
break;
case CLMT_STATE_FINISH:
*lpuResourceID = IDS_BAD_OPERATION_FINISH;
break;
default:
*lpuResourceID = IDS_OPERATION_NOT_LEGAL;
}
}
return bRet;
}
//-----------------------------------------------------------------------------
//
// Function: CLMTSetMachineState
//
// Synopsis: Set the machine state to CLMT registry
//
// Returns: S_OK if value is successfully saved in registry
//
// History: 03/13/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------------
HRESULT CLMTSetMachineState(
DWORD dwMachineState // Machine state
)
{
LONG lStatus;
lStatus = SetRegistryValue(HKEY_LOCAL_MACHINE,
CLMT_REGROOT,
CLMT_MACHINE_STATE_REG_VALUE,
REG_DWORD,
(LPBYTE) &dwMachineState,
sizeof(dwMachineState));
return HRESULT_FROM_WIN32(lStatus);
}
//-----------------------------------------------------------------------------
//
// Function: CLMTGetMachineState
//
// Synopsis: Get the machine state from CLMT registry key.
// If the key does not exist, this function will also set the value
// of reg key to ORIGINAL state.
//
// Returns: S_OK if value is successfully retrieved in registry
//
// History: 03/13/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------------
HRESULT CLMTGetMachineState(
LPDWORD lpdwMachineState
)
{
HRESULT hr;
LONG lStatus;
DWORD dwSize;
if (lpdwMachineState == NULL)
{
return E_INVALIDARG;
}
dwSize = sizeof(DWORD);
lStatus = GetRegistryValue(HKEY_LOCAL_MACHINE,
CLMT_REGROOT,
CLMT_MACHINE_STATE_REG_VALUE,
(LPBYTE) lpdwMachineState,
&dwSize);
if (lStatus == ERROR_FILE_NOT_FOUND)
{
// First time running the tool, we don't have the value in registry yet.
// Set the machine state to ORIGINAL
*lpdwMachineState = CLMT_STATE_ORIGINAL;
hr = CLMTSetMachineState(CLMT_STATE_ORIGINAL);
}
else
{
hr = HRESULT_FROM_WIN32(lStatus);
}
return hr;
}
//-----------------------------------------------------------------------------
//
// Function: IsUserOKWithCheckUpgrade
//
// Synopsis:
//
// Returns:
//
// History: 02/07/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL IsUserOKWithCheckUpgrade(VOID)
{
TCHAR szI386Path[MAX_PATH];
BOOL fRet = FALSE;
DoMessageBox(GetConsoleWindow(), IDS_ASKFORWINNT32, IDS_MAIN_TITLE, MB_OK);
// Ask user for path to winnt32.exe
if (AskUserForDotNetCDPath(szI386Path))
{
// Launch Winnt32.exe with checkupgrade switch
if (LaunchWinnt32(szI386Path))
{
// Show upgrade.txt to user, ask them to uninstall
// incompatible components before running CLMT
if (FindUpgradeLog())
{
if (ShowUpgradeLog() == ID_CONTINUE)
{
fRet = TRUE;
}
else
{
DoMessageBox(GetConsoleWindow(), IDS_WINNT32_CANCEL, IDS_MAIN_TITLE, MB_OK);
DPF(dlError, TEXT("User choose to stop the process"));
}
}
else
{
DPF(dlError, TEXT("Upgrade.txt not found"));
}
}
else
{
DPF(dlError, TEXT("Unable to launch Winnt32.exe"));
}
}
else
{
DPF(dlError, TEXT("User does not supply the path of Winnt32.exe"));
}
return fRet;
}
//-----------------------------------------------------------------------------
//
// Function: FindUpgradeLog
//
// Synopsis:
//
// Returns:
//
// History: 02/07/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL FindUpgradeLog(VOID)
{
const TCHAR szUpgradeLog[] = TEXT("%systemroot%\\Upgrade.txt");
TCHAR szExpUpgradeLog[MAX_PATH];
BOOL fRet = FALSE;
SYSTEMTIME stUTC, stNow;
WIN32_FILE_ATTRIBUTE_DATA attFileAttr;
if ( ExpandEnvironmentStrings(szUpgradeLog, szExpUpgradeLog, MAX_PATH) )
{
if ( GetFileAttributesEx(szExpUpgradeLog, GetFileExInfoStandard, &attFileAttr) )
{
// Upgrade.txt exists, check if it's updated today or not
if ( FileTimeToSystemTime(&attFileAttr.ftLastWriteTime, &stUTC) )
{
GetSystemTime(&stNow);
if (stUTC.wYear == stNow.wYear &&
stUTC.wMonth == stNow.wMonth &&
stUTC.wDay == stNow.wDay)
{
fRet = TRUE;
}
}
}
}
return fRet;
}
//-----------------------------------------------------------------------------
//
// Function: LaunchWinnt32
//
// Synopsis: Launch Winnt32.exe with "checkupgradeonly" switch
//
// Returns: TRUE if winnt32.exe is executed successfully
// FALSE otherwise
//
// History: 02/07/2002 rerkboos created
// 05/20/2002 rerkboos change parameter to receive CD path
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL LaunchWinnt32(
LPCTSTR lpCDPath // Path to Server 2003 CD
)
{
TCHAR szWinnt32[MAX_PATH];
TCHAR szI386Path[MAX_PATH];
BOOL bRet = FALSE;
HRESULT hr;
STARTUPINFO siWinnt32;
PROCESS_INFORMATION piWinnt32;
TCHAR szCmdLine[] = TEXT("Winnt32.exe /#u:anylocale /checkupgradeonly /unattend /dudisable");
if (lpCDPath == NULL)
{
return FALSE;
}
// Construct absolute path to Winnt32.exe
hr = StringCchCopy(szI386Path, ARRAYSIZE(szI386Path), lpCDPath);
if (SUCCEEDED(hr))
{
ConcatenatePaths(szI386Path, TEXT("i386"), ARRAYSIZE(szI386Path));
hr = StringCchCopy(szWinnt32, ARRAYSIZE(szWinnt32), szI386Path);
if (SUCCEEDED(hr))
{
ConcatenatePaths(szWinnt32, TEXT("winnt32.exe"), ARRAYSIZE(szWinnt32));
}
}
if ( IsDotNetWinnt32(szWinnt32) )
{
ZeroMemory(&siWinnt32, sizeof(STARTUPINFO));
siWinnt32.cb = sizeof(STARTUPINFO);
// CreateProcess call conforms to security guideline
bRet = CreateProcess(szWinnt32,
szCmdLine,
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS,
NULL,
szI386Path,
&siWinnt32,
&piWinnt32);
if (bRet)
{
// Wait until winnt32.exe finished before return back to CLM tool
WaitForSingleObject(piWinnt32.hProcess, INFINITE);
CloseHandle(piWinnt32.hProcess);
CloseHandle(piWinnt32.hThread);
}
}
return bRet;
}
//-----------------------------------------------------------------------------
//
// Function: AskUserForDotNetCDPath
//
// Synopsis: Ask user to supply the path to Server 2003 CD
//
// Returns: TRUE if the path is valid
// FALSE otherwise
//
// History: 02/07/2002 rerkboos created
// 05/20/2002 rerkboos check for Server 2003 SRV/ADS CD
// 06/10/2002 rerkboos check for Server 2003 DTC cd
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL AskUserForDotNetCDPath(
LPTSTR lpCDPath // Buffer to store path to CD
)
{
HRESULT hr;
BOOL fRet = FALSE;
BOOL bDoBrowseDialog;
LPMALLOC piMalloc;
INT iRet;
DWORD dwSKU;
OSVERSIONINFOEX osviex;
if (lpCDPath == NULL)
{
return FALSE;
}
//
// Check the SKU of current system
//
osviex.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx((LPOSVERSIONINFO) &osviex);
if (osviex.wProductType == VER_NT_DOMAIN_CONTROLLER
|| osviex.wProductType == VER_NT_SERVER)
{
dwSKU = SKU_SRV;
if (osviex.wSuiteMask & VER_SUITE_ENTERPRISE)
{
dwSKU = SKU_ADS;
}
if (osviex.wSuiteMask & VER_SUITE_DATACENTER)
{
dwSKU = SKU_DTC;
}
}
hr = SHGetMalloc(&piMalloc);
if (SUCCEEDED(hr))
{
BROWSEINFO biCDPath;
LPITEMIDLIST lpiList;
ZeroMemory(&biCDPath, sizeof(BROWSEINFO));
biCDPath.hwndOwner = NULL;
biCDPath.lpszTitle = TEXT("Please supply the Windows Server 2003 CD path");
biCDPath.pszDisplayName = lpCDPath;
biCDPath.ulFlags = BIF_EDITBOX |
BIF_NONEWFOLDERBUTTON |
BIF_RETURNONLYFSDIRS;
bDoBrowseDialog = TRUE;
while (bDoBrowseDialog)
{
// Show the Browse dialog
lpiList = SHBrowseForFolder(&biCDPath);
if (lpiList == NULL)
{
//
// if lpiList == NULL, user click Cancel in browse dialog
//
iRet = MessageBox(GetConsoleWindow(),
TEXT("You did not supply the path to Windows Server 2003 CD.\nDo you want to continue running CLMT?"),
TEXT("CLMT"),
MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2);
if (iRet != IDYES)
{
// User choose not to run CLMT any further
bDoBrowseDialog = FALSE;
}
}
else
{
//
// User supply path in Browse dialog,
// check whether it is valid Server 2003 SRV/ADS CD or not
//
if (SHGetPathFromIDListW(lpiList, lpCDPath))
{
LPTSTR lpFile;
DWORD cchFile;
DWORD dwAttr;
cchFile = lstrlen(lpCDPath) + MAX_PATH;
lpFile = MEMALLOC(cchFile * sizeof(TCHAR));
if (lpFile)
{
switch (dwSKU)
{
case SKU_SRV:
// Check if it is SRV CD or not
hr = StringCchCopy(lpFile, cchFile, lpCDPath);
ConcatenatePaths(lpFile, TEXT("win51is"), cchFile);
dwAttr = GetFileAttributes(lpFile);
if (dwAttr != INVALID_FILE_ATTRIBUTES)
{
// This is SRV CD
fRet = TRUE;
bDoBrowseDialog = FALSE;
}
else
{
// We also allow W2K SRV -> Server 2003 ADS
hr = StringCchCopy(lpFile, cchFile, lpCDPath);
ConcatenatePaths(lpFile, TEXT("win51ia"), cchFile);
dwAttr = GetFileAttributes(lpFile);
if (dwAttr != INVALID_FILE_ATTRIBUTES)
{
// This is ADS CD
fRet = TRUE;
bDoBrowseDialog = FALSE;
}
}
break;
case SKU_ADS:
// Check if it is ADS CD or not
hr = StringCchCopy(lpFile, cchFile, lpCDPath);
ConcatenatePaths(lpFile, TEXT("win51ia"), cchFile);
dwAttr = GetFileAttributes(lpFile);
if (dwAttr != INVALID_FILE_ATTRIBUTES)
{
// This is ADS CD
fRet = TRUE;
bDoBrowseDialog = FALSE;
}
break;
case SKU_DTC:
// Check if it is DTC CD or not
hr = StringCchCopy(lpFile, cchFile, lpCDPath);
ConcatenatePaths(lpFile, TEXT("win51id"), cchFile);
dwAttr = GetFileAttributes(lpFile);
if (dwAttr != INVALID_FILE_ATTRIBUTES)
{
// This is DTC CD
fRet = TRUE;
bDoBrowseDialog = FALSE;
}
break;
default:
fRet = FALSE;
bDoBrowseDialog = TRUE;
}
if (!fRet)
{
TCHAR szErrorMsg[512];
INT iRead;
iRead = LoadString(GetModuleHandle(NULL),
IDS_WRONG_CD,
szErrorMsg,
ARRAYSIZE(szErrorMsg));
if (iRead > 0)
{
MessageBox(GetConsoleWindow(),
szErrorMsg,
TEXT("CLMT"),
MB_OK);
}
}
MEMFREE(lpFile);
}
}
}
}
if (lpiList)
{
IMalloc_Free(piMalloc, lpiList);
}
IMalloc_Release(piMalloc);
}
return fRet;
}
//-----------------------------------------------------------------------------
//
// Function: IsDotNetWinnt32
//
// Synopsis: Check if the specified path is Server 2003 family CD
// lpWinnt32 contains absolute path with winnt32.exe
//
// Returns: TRUE if it is Server 2003 winnt32,
// FALSE otherwise
//
// History: 02/07/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL IsDotNetWinnt32(
LPCTSTR lpWinnt32 // Absolute path to Winnt32.exe
)
{
BOOL fRet = FALSE;
LPVOID lpBuffer;
DWORD cbBuffer;
UINT cbFileInfo;
VS_FIXEDFILEINFO* pFileInfo;
if (lpWinnt32 == NULL)
{
return FALSE;
}
// Get the size needed to allocate buffer
cbBuffer = GetFileVersionInfoSize((LPTSTR) lpWinnt32, NULL);
if (cbBuffer > 0)
{
lpBuffer = MEMALLOC(cbBuffer);
if (lpBuffer)
{
// Get the version info of user's specified winnt32.exe
if (GetFileVersionInfo((LPTSTR) lpWinnt32, 0, cbBuffer, lpBuffer))
{
if (VerQueryValue(lpBuffer,
TEXT("\\"),
(LPVOID*) &pFileInfo,
&cbFileInfo))
{
// Server 2003 Family version is 5.2
if (pFileInfo->dwFileVersionMS == 0x00050002)
{
fRet = TRUE;
}
}
}
MEMFREE(lpBuffer);
}
}
return fRet;
}
//-----------------------------------------------------------------------------
//
// Function: ShowUpgradeLog
//
// Synopsis: Display the content of %SystemRoot%\Upgrade.txt
//
// Returns: User selection to Stop or Continue operation from dialog box
//
// History: 02/07/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------------
INT ShowUpgradeLog(VOID)
{
HRESULT hr;
BOOL fRet;
HMODULE hExe;
LPTSTR lpBuffer;
size_t cchBuffer;
TCHAR szUpgradeLog[MAX_PATH];
INT_PTR nRet = 0;
UPGRADE_LOG_PARAM lParam;
// Get the absolute path name for upgrade.txt
if ( !ExpandEnvironmentStrings(TEXT_UPGRADE_LOG, szUpgradeLog, MAX_PATH) )
{
return 0;
}
// Read content of upgrade.txt
// Caller needs to free the buffer if function succeeded
hr = ReadTextFromFile(szUpgradeLog,
&lParam.lpText,
&lParam.cbText,
&lParam.fUnicode);
if ( SUCCEEDED(hr) )
{
hExe = GetModuleHandle(NULL);
// Display content of Upgrade.txt in modal dialog
// The dialog will ask user to continue or stop operation
nRet = DialogBoxParam(hExe,
MAKEINTRESOURCE(IDD_UPGRADE_LOG_TEXT),
GetConsoleWindow(),
(DLGPROC) UpgradeLogDlgProc,
(LPARAM) &lParam);
MEMFREE(lParam.lpText);
}
return (INT) nRet;
}
//-----------------------------------------------------------------------------
//
// Function: UpgradeLogDlgProc
//
// Synopsis: Dialog box procedure
//
// Returns:
//
// History: 02/07/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL
CALLBACK
UpgradeLogDlgProc(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
BOOL fBlock;
WCHAR wszWarning[512];
switch (uMsg)
{
case WM_INITDIALOG:
// Init the dialog
ShowWindow(hwndDlg, SW_SHOWNORMAL);
// Search for unsupport component in the text context from upgrade.txt
fBlock = CheckUnsupportComponent(
((PUPGRADE_LOG_PARAM) lParam)->lpText,
((PUPGRADE_LOG_PARAM) lParam)->fUnicode );
if (fBlock)
{
LoadString(g_hInstDll,
IDS_BLOCKING_WARNING,
wszWarning,
ARRAYSIZE(wszWarning));
SendMessage(GetDlgItem(hwndDlg, ID_CAPTION2),
WM_SETTEXT,
wParam,
(LPARAM) wszWarning);
// Disable 'Continue' button if found the unsupport component
EnableWindow(GetDlgItem(hwndDlg, ID_CONTINUE),
FALSE);
}
else
{
LoadString(g_hInstDll,
IDS_UNLOCALIZED_WARNING,
wszWarning,
ARRAYSIZE(wszWarning));
SendMessage(GetDlgItem(hwndDlg, ID_CAPTION2),
WM_SETTEXT,
wParam,
(LPARAM) wszWarning);
}
// Display text using A or W function depending on type of data
if ( ((PUPGRADE_LOG_PARAM) lParam)->fUnicode )
{
SendMessageW(GetDlgItem(hwndDlg, IDC_TEXT),
WM_SETTEXT,
wParam,
(LPARAM) (((PUPGRADE_LOG_PARAM) lParam)->lpText));
}
else
{
SendMessageA(GetDlgItem(hwndDlg, IDC_TEXT),
WM_SETTEXT,
wParam,
(LPARAM) (((PUPGRADE_LOG_PARAM) lParam)->lpText));
}
SetForegroundWindow(hwndDlg);
break;
case WM_COMMAND:
// Handle command buttons
switch (wParam)
{
case ID_CONTINUE:
EndDialog(hwndDlg, ID_CONTINUE);
break;
case ID_STOP:
EndDialog(hwndDlg, ID_STOP);
break;
}
break;
case WM_CLOSE:
EndDialog(hwndDlg, ID_STOP);
break;
default:
break;
}
return FALSE;
}
//-----------------------------------------------------------------------------
//
// Function: CheckUnsupportComponent
//
// Synopsis: Search for unsupport component in upgrade.txt.
//
// Returns: TRUE if unsupport component is found,
// FALSE otherwise
//
// History: 02/07/2002 rerkboos created
//
// Notes: We determined unsupport component by searching for word
// "must uninstall" in buffer.
//
//-----------------------------------------------------------------------------
BOOL CheckUnsupportComponent(
LPVOID lpBuffer, // Text buffer
BOOL fUnicode // Flag indicate if text is Unicode or ANSI
)
{
BOOL fRet = FALSE;
LPVOID lpStr;
if (fUnicode)
{
lpStr = (LPWSTR) StrStrW((LPCWSTR) lpBuffer, L"must uninstall");
}
else
{
lpStr = (LPSTR) StrStrA((LPCSTR) lpBuffer, "must uninstall");
}
if (lpStr)
{
fRet = TRUE;
}
return fRet;
}
//-----------------------------------------------------------------------------
//
// Function: ReadTextFromFile
//
// Synopsis: Read text from file into buffer
//
// Returns: HRESULT
//
// History: 02/07/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------------
HRESULT ReadTextFromFile(
LPCTSTR lpTextFile, // Text file name
LPVOID *lplpText, // Pointer to a newly allocated buffer
size_t *lpcbText, // Size of allocated buffer in bytes
BOOL *lpfUnicode // Flag indicates if data is unicode or not (optional)
)
{
HRESULT hr;
HANDLE hFile;
DWORD cbRead;
BOOL fRet = FALSE;
if (lpTextFile == NULL || lplpText == NULL || lpcbText == NULL)
{
return fRet;
}
hFile = CreateFile(lpTextFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
// Get the size of memory big enough to store text file,
// plus a null terminator
*lpcbText = GetFileSize(hFile, NULL) + sizeof(TCHAR);
*lplpText = MEMALLOC(*lpcbText);
if (*lplpText != NULL)
{
fRet = ReadFile(hFile, *lplpText, *lpcbText, &cbRead, NULL);
if (fRet)
{
// Set the unicode flag if user supplied the pointer
if (lpfUnicode != NULL)
{
*lpfUnicode = IsTextUnicode(*lplpText, cbRead, NULL);
}
}
else
{
// Failed to read text file
MEMFREE(*lplpText);
*lplpText = NULL;
*lpcbText = 0;
}
}
else
{
// HeapAlloc failed
*lpcbText = 0;
}
CloseHandle(hFile);
}
if (fRet)
{
hr = S_OK;
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
return hr;
}
//-----------------------------------------------------------------------
//
// Function: IsNT5
//
// Descrip: Check whether current OS is NT5 (Server class)
//
// Returns: BOOL
//
// Notes: none
//
// History: 09/17/2001 xiaoz created
// 02/18/2002 rerkboos add code to check more criteria
// 06/10/2002 rerkboos allow DTC to run
//
// Notes: none
//
//-----------------------------------------------------------------------
BOOL IsNT5(VOID)
{
OSVERSIONINFOEX osviex;
ZeroMemory( &osviex,sizeof(OSVERSIONINFOEX) );
osviex.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if ( GetVersionEx((LPOSVERSIONINFO) &osviex) )
{
return ( (osviex.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
(osviex.dwMajorVersion == 5) &&
(osviex.dwMinorVersion == 0) &&
( (osviex.wSuiteMask & VER_SUITE_ENTERPRISE) ||
(osviex.wProductType == VER_NT_SERVER) ||
(osviex.wProductType == VER_NT_DOMAIN_CONTROLLER) ) &&
(osviex.wProductType != VER_NT_WORKSTATION) );
}
return FALSE;
}
//-----------------------------------------------------------------------
//
// Function: IsDotNet
//
// Descrip: Check whether current OS is Windows Server 2003
//
// Returns: BOOL
//
// Notes: none
//
// History: 07/09/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------
BOOL IsDotNet(VOID)
{
OSVERSIONINFOEX osviex;
ZeroMemory( &osviex,sizeof(OSVERSIONINFOEX) );
osviex.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if ( GetVersionEx((LPOSVERSIONINFO) &osviex) )
{
return ( (osviex.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
(osviex.dwMajorVersion == 5) &&
(osviex.dwMinorVersion == 2) &&
( (osviex.wSuiteMask & VER_SUITE_ENTERPRISE) ||
(osviex.wProductType == VER_NT_SERVER) ||
(osviex.wProductType == VER_NT_DOMAIN_CONTROLLER) ) &&
(osviex.wProductType != VER_NT_WORKSTATION) );
}
return FALSE;
}
//-----------------------------------------------------------------------------
//
// Function: IsNEC98
//
// Synopsis: Check whether this machine is NEC98 platform or not.
//
// Returns: TRUE if it is NEC98 machine, FALSE otherwise
//
// History: 02/18/2001 Rerkboos Created
//
// Notes: Code is stolen from Winnt32
//
//-----------------------------------------------------------------------------
BOOL IsNEC98(VOID)
{
BOOL IsNEC98;
IsNEC98 = ( (GetKeyboardType(0) == 7) &&
((GetKeyboardType(1) & 0xff00) == 0x0d00) );
return (IsNEC98);
}
//-----------------------------------------------------------------------------
//
// Function: IsIA64
//
// Synopsis: Check whether the program is running on 64-bit machine or not
//
// Returns: TRUE if it is running on 64-bit machine, FALSE otherwise
//
// History: 02/18/2001 Rerkboos Created
//
// Notes: Code is stolen from Winnt32
//
//-----------------------------------------------------------------------------
BOOL IsIA64(VOID)
{
ULONG_PTR p;
NTSTATUS status;
status = NtQueryInformationProcess(NtCurrentProcess(),
ProcessWow64Information,
&p,
sizeof(p),
NULL);
return (NT_SUCCESS(status) && p);
}
//-----------------------------------------------------------------------------
//
// Function: IsDomainController
//
// Synopsis: Check whether the machine is a domain controller or not
//
// Returns: BOOL
//
// History: 08/13/2002 Rerkboos Created
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL IsDomainController(VOID)
{
HRESULT hr;
BOOL bIsDC = FALSE;
TCHAR szDCName[MAX_PATH];
DWORD cchDCName;
cchDCName = ARRAYSIZE(szDCName);
hr = GetDCInfo(&bIsDC, szDCName, &cchDCName);
return bIsDC;
}
//-----------------------------------------------------------------------------
//
// Function: IsOnTSClient
//
// Synopsis: Check whether the program is running in terminal session or not
//
// Returns: TRUE if it is running in terminal session, FALSE otherwise
//
// History: 02/18/2001 Rerkboos Created
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL IsOnTSClient(VOID)
{
return GetSystemMetrics(SM_REMOTESESSION);
}
//-----------------------------------------------------------------------------
//
// Function: IsTSInstalled
//
// Synopsis: Check whether Terminal Services is installed
//
// Returns: TRUE if TS is installed, FALSE otherwise
//
// History: 02/18/2001 Rerkboos Created
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL IsTSInstalled(VOID)
{
ULONGLONG ullConditionMask;
OSVERSIONINFOEX osviex;
BOOL fRet = FALSE;
ullConditionMask = 0;
ullConditionMask = VerSetConditionMask(ullConditionMask,
VER_SUITENAME,
VER_AND);
ZeroMemory(&osviex, sizeof(osviex));
osviex.dwOSVersionInfoSize = sizeof(osviex);
osviex.wSuiteMask = VER_SUITE_TERMINAL;
fRet = VerifyVersionInfo(&osviex, VER_SUITENAME, ullConditionMask);
return fRet;
}
//-----------------------------------------------------------------------------
//
// Function: IsTSConnectionEnabled
//
// Synopsis: Check whether the connection to Terminal Services is enabled
//
// Returns: TRUE if it is enabled, FALSE otherwise
//
// History: 02/18/2001 Rerkboos Created
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL IsTSConnectionEnabled(VOID)
{
HKEY hKey;
HKEY hConnKey;
TCHAR szKeyName[MAX_PATH];
DWORD cchKeyName;
DWORD dwIndex;
DWORD dwType;
DWORD dwfEnableWinStation;
DWORD cbfEnableWinStation;
LONG lEnumRet;
LONG lRet;
BOOL fRet = FALSE;
FILETIME ft;
HRESULT hr;
cchKeyName = ARRAYSIZE(szKeyName);
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT_WINSTATION_KEY,
0,
KEY_ENUMERATE_SUB_KEYS,
&hKey);
if (ERROR_SUCCESS != lRet)
{
return FALSE;
}
dwIndex = 0;
do
{
cchKeyName = ARRAYSIZE(szKeyName);
lEnumRet = RegEnumKeyEx(hKey,
dwIndex,
szKeyName,
&cchKeyName,
NULL,
NULL,
NULL,
&ft);
if (ERROR_SUCCESS == lEnumRet)
{
// While there is more key to enumerate
if (CompareString(LOCALE_ENGLISH,
NORM_IGNORECASE,
szKeyName,
-1,
TEXT("Console"),
-1)
!= CSTR_EQUAL)
{
// Only check for other connection's key, not Console key
lRet = RegOpenKeyEx(hKey,
szKeyName,
0,
KEY_READ,
&hConnKey);
if (ERROR_SUCCESS != lRet)
{
fRet = FALSE;
break;
}
cbfEnableWinStation = sizeof(dwfEnableWinStation);
lRet = RegQueryValueEx(hConnKey,
TEXT("fEnableWinStation"),
NULL,
&dwType,
(LPBYTE) &dwfEnableWinStation,
&cbfEnableWinStation);
RegCloseKey(hConnKey);
if (ERROR_SUCCESS == lRet)
{
// If there is at lease one of connection have WinStation
// flag enabled, TS connection can still be made
if ( dwfEnableWinStation )
{
fRet = TRUE;
break;
}
}
}
}
dwIndex++;
} while(ERROR_SUCCESS == lEnumRet);
RegCloseKey(hKey);
return fRet;
}
//-----------------------------------------------------------------------------
//
// Function: IsTSServiceRunning
//
// Synopsis: Check whether the TS service is runnning or not
//
// Returns: TRUE if it is running, FALSE otherwise
//
// History: 02/18/2001 Rerkboos Created
//
// Notes: Stolen from Termsrv test code
//
//-----------------------------------------------------------------------------
BOOL IsTSServiceRunning(VOID)
{
BOOL fRet = FALSE;
SC_HANDLE hServiceController = OpenSCManager(NULL, NULL, GENERIC_READ);
if (hServiceController)
{
SC_HANDLE hTermServ = OpenService(hServiceController,
TEXT("TermService"),
SERVICE_QUERY_STATUS);
if (hTermServ)
{
SERVICE_STATUS tTermServStatus;
if (QueryServiceStatus(hTermServ, &tTermServStatus))
{
fRet = (tTermServStatus.dwCurrentState == SERVICE_RUNNING);
}
CloseServiceHandle(hTermServ);
}
CloseServiceHandle(hServiceController);
}
return fRet;
}
//-----------------------------------------------------------------------------
//
// Function: IsOtherSessionOnTS
//
// Synopsis: Check whether there is other TS sessions are connected.
//
// Returns: TRUE if there is remote session connected, FALSE otherwise
//
// History: 02/18/2001 Rerkboos Created
// 04/17/2002 Rerkboon Fix bug 558942
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL IsOtherSessionOnTS(VOID)
{
BOOL fRet;
DWORD dwSessionCount;
PWTS_SESSION_INFO pwtsSessionInfo;
fRet = WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE,
0,
1,
&pwtsSessionInfo,
&dwSessionCount);
if (fRet)
{
DWORD i;
DWORD dwClients = 0;
for (i = 0 ; i < dwSessionCount ; i++)
{
// Check to see how many clients connect to TS server
if (pwtsSessionInfo[i].State != WTSListen
&& pwtsSessionInfo[i].State != WTSIdle
&& pwtsSessionInfo[i].State != WTSReset
&& pwtsSessionInfo[i].State != WTSDown
&& pwtsSessionInfo[i].State != WTSInit)
{
dwClients++;
}
}
fRet = (dwClients > 1 ? TRUE : FALSE);
// BUG 558942: free the memory
WTSFreeMemory(pwtsSessionInfo);
}
return fRet;
}
#define TS_POLICY_SUB_TREE TEXT("Software\\Policies\\Microsoft\\Windows NT\\Terminal Services")
#define POLICY_DENY_TS_CONNECTIONS TEXT("fDenyTSConnections")
#define APPLICATION_NAME TEXT("Winlogon")
#define WINSTATIONS_DISABLED TEXT("WinStationsDisabled")
HRESULT DisableWinstations(
DWORD dwDisabled,
LPDWORD lpdwPrevStatus
)
{
HRESULT hr = S_OK;
LONG lRet;
BOOL bRet;
BOOL bPolicyOK;
DWORD fDenyTSConnections;
DWORD cbfDenyTSConnections;
TCHAR szCurrentState[2];
LPTSTR lpStopString;
if (IsTSServiceRunning())
{
//
// Get the current state of WinStations
//
if (lpdwPrevStatus)
{
GetProfileString(APPLICATION_NAME,
WINSTATIONS_DISABLED,
TEXT("0"),
szCurrentState,
ARRAYSIZE(szCurrentState));
*lpdwPrevStatus = _tcstoul(szCurrentState, &lpStopString, 10);
}
//
// Check if group policy has thrown the big switch, if so, inform and refuse any changes
//
fDenyTSConnections = 0;
cbfDenyTSConnections = sizeof(fDenyTSConnections);
lRet = GetRegistryValue(HKEY_LOCAL_MACHINE,
TS_POLICY_SUB_TREE,
POLICY_DENY_TS_CONNECTIONS,
(LPBYTE) &fDenyTSConnections,
&cbfDenyTSConnections);
if (lRet == ERROR_SUCCESS)
{
if (fDenyTSConnections)
{
// Machine policy deny TS connection
bPolicyOK = FALSE;
}
else
{
// Machine policy allows TS connection
bPolicyOK = TRUE;
}
}
else if (lRet == ERROR_FILE_NOT_FOUND)
{
bPolicyOK = TRUE;
}
else
{
hr = HRESULT_FROM_WIN32(lRet);
}
//
// If policy allows to change connection status
//
if (SUCCEEDED(hr) && bPolicyOK)
{
if (dwDisabled)
{
bRet = WriteProfileString(APPLICATION_NAME,
WINSTATIONS_DISABLED,
TEXT("1"));
}
else
{
bRet = WriteProfileString(APPLICATION_NAME,
WINSTATIONS_DISABLED,
TEXT("0"));
}
if (!bRet)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
}
return hr;
}
//-----------------------------------------------------------------------------
//
// Function: DisplayTaskList
//
// Synopsis: Display the list of running task on the system
//
// Returns: TRUE if there is tasks running
// FALSE if there is no other tasks running
//
// History: 07/09/2002 Rerkboos Created
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL DisplayTaskList()
{
HRESULT hr;
BOOL bRet = FALSE;
DWORD i;
DWORD cchTaskList;
LPTSTR lpTaskList = NULL;
DWORD cchTask;
LPTSTR lpTask = NULL;
DWORD dwMaxCchLen;
TCHAR szTemp[512];
TCHAR szCaption[MAX_PATH];
TCHAR szHeader[MAX_PATH];
APPLIST_PARAM AppListParam;
// Init the AppList structure
AppListParam.dwNumEntries = 0;
for (i = 0 ; i < MAX_APP_ENTRIES ; i++)
{
AppListParam.lpAppName[i] = NULL;
}
if (LoadString(g_hInstDll, IDS_PRODUCT_NAME, szCaption, ARRAYSIZE(szCaption)) <= 0
|| LoadString(g_hInstDll, IDS_CLOSE_APP_TEXT, szHeader, ARRAYSIZE(szHeader)) <= 0)
{
goto CLEANUP;
}
bRet = EnumDesktopWindows(NULL, (WNDENUMPROC) &EnumWindowProc, (LPARAM) &AppListParam);
if (AppListParam.dwNumEntries > 0)
{
cchTaskList = lstrlen(szHeader);
dwMaxCchLen = 0;
for (i = 0 ; i < AppListParam.dwNumEntries ; i++)
{
cchTask = lstrlen(AppListParam.lpAppName[i]) + 4;
if (cchTask > dwMaxCchLen)
{
dwMaxCchLen = cchTask;
}
cchTaskList += cchTask;
}
// Allocate the string long enough to store a Task name
lpTask = (LPTSTR) MEMALLOC(dwMaxCchLen * sizeof(TCHAR));
if (lpTask != NULL)
{
// Allocate the string for all the tasks
lpTaskList = (LPTSTR) MEMALLOC(cchTaskList * sizeof(TCHAR));
if (lpTaskList != NULL)
{
hr = StringCchCopy(lpTaskList, cchTaskList, szHeader);
for (i = 0 ; i < AppListParam.dwNumEntries ; i++)
{
hr = StringCchPrintf(lpTask,
dwMaxCchLen,
TEXT("- %s\n"),
AppListParam.lpAppName[i]);
if (SUCCEEDED(hr))
{
hr = StringCchCat(lpTaskList,
cchTaskList,
lpTask);
if (FAILED(hr))
{
goto CLEANUP;
}
}
}
}
}
MessageBox(GetConsoleWindow(), lpTaskList, szCaption, MB_OK);
bRet = TRUE;
}
else
{
bRet = FALSE;
}
CLEANUP:
if (lpTask != NULL)
{
MEMFREE(lpTask);
}
if (lpTaskList != NULL)
{
MEMFREE(lpTaskList);
}
for (i = 0 ; i < MAX_APP_ENTRIES ; i++)
{
if (AppListParam.lpAppName[i] != NULL)
{
MEMFREE(AppListParam.lpAppName[i]);
}
}
return bRet;
}
//-----------------------------------------------------------------------------
//
// Function: EnumWindowProc
//
// Synopsis: A callback function for EnumDesktopWindows() in
// DisplayTaskList() function.
//
// Returns: TRUE if no error occured
// FALSE if something was wrong
//
// History: 07/09/2002 Rerkboos Created
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL CALLBACK EnumWindowProc(
HWND hwnd,
LPARAM lParam
)
{
BOOL bRet = FALSE;
HRESULT hr;
TCHAR szTitle[MAX_PATH];
TCHAR szOwnerFile[MAX_PATH];
LPCTSTR lpFileName;
DWORD dwIndex;
DWORD cchLen;
UINT ui;
PFNGETMODULENAME pfnGetWindowModuleFileName;
if (GetWindow(hwnd, GW_OWNER) || !IsWindowVisible(hwnd))
{
// Skip child windows or invisible windows
return TRUE;
}
GetWindowText(hwnd, szTitle, MAX_PATH);
if (szTitle[0] == TEXT('\0'))
{
return TRUE;
}
if (MyStrCmpI(szTitle, TEXT("Program Manager")) == LSTR_EQUAL)
{
return TRUE;
}
if (hwnd == GetConsoleWindow())
{
// Ignore itself
return TRUE;
}
// Ignore Explorer windows
lpFileName = GetWindowModuleFileNameOnly(hwnd, szOwnerFile, ARRAYSIZE(szOwnerFile));
if (StrStrI(szOwnerFile, TEXT("browseui")))
{
return TRUE;
}
dwIndex = ((PAPPLIST_PARAM) lParam)->dwNumEntries;
hr = DuplicateString(&(((PAPPLIST_PARAM) lParam)->lpAppName[dwIndex]),
&cchLen,
szTitle);
if (SUCCEEDED(hr))
{
bRet = TRUE;
((PAPPLIST_PARAM) lParam)->dwNumEntries++;
}
return bRet;
}
//-----------------------------------------------------------------------------
//
// Function: ShowStartUpDialog
//
// Synopsis: Display startup dialog
//
// Returns: none
//
// History: 08/14/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------------
INT ShowStartUpDialog()
{
return (INT) DialogBoxParam(GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_STARTUP_DLG),
GetConsoleWindow(),
(DLGPROC) StartUpDlgProc,
(LPARAM) NULL);
}
//-----------------------------------------------------------------------------
//
// Function: StartUpDlgProc
//
// Synopsis: Dialog box procedure
//
// Returns:
//
// History: 02/07/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL
CALLBACK
StartUpDlgProc(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
WCHAR wszInfo[1024];
switch (uMsg)
{
case WM_INITDIALOG:
// Init the dialog
ShowWindow(hwndDlg, SW_SHOWNORMAL);
if (LoadStringW(g_hInstDll,
IDS_STARTUP_DLG_INFO,
wszInfo,
ARRAYSIZE(wszInfo)))
{
SendMessage(GetDlgItem(hwndDlg, ID_STARTUP_DLG_INFO),
WM_SETTEXT,
wParam,
(LPARAM) wszInfo);
}
case WM_COMMAND:
// Handle command buttons
switch (wParam)
{
case ID_STARTUP_DLG_NEXT:
EndDialog(hwndDlg, ID_STARTUP_DLG_NEXT);
break;
case ID_STARTUP_DLG_CANCEL:
EndDialog(hwndDlg, ID_STARTUP_DLG_CANCEL);
break;
case ID_STARTUP_DLG_README:
ShowReadMe();
break;
}
break;
case WM_CLOSE:
EndDialog(hwndDlg, ID_STARTUP_DLG_CANCEL);
break;
default:
break;
}
return FALSE;
}
//-----------------------------------------------------------------------------
//
// Function: ShowReadMe
//
// Synopsis: Launch notepad to display CLMT readme.txt
//
// Returns: none
//
// History: 08/14/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------------
VOID ShowReadMe()
{
HRESULT hr;
DWORD dwErr;
DWORD i;
TCHAR szReadmePath[MAX_PATH];
TCHAR szNotepad[MAX_PATH];
TCHAR szCmdLine[MAX_PATH];
dwErr = GetModuleFileName(NULL, szReadmePath, ARRAYSIZE(szReadmePath));
if (dwErr == 0)
{
szReadmePath[0] = TEXT('\0');
}
else
{
i = lstrlen(szReadmePath);
while (i > 0 && szReadmePath[i] != TEXT('\\'))
{
i--;
}
szReadmePath[i + 1] = TEXT('\0');
}
hr = StringCchCat(szReadmePath, ARRAYSIZE(szReadmePath), TEXT_README_FILE);
dwErr = GetFileAttributes(szReadmePath);
if (dwErr == INVALID_FILE_ATTRIBUTES)
{
DoMessageBox(GetConsoleWindow(), IDS_README_NOT_FOUND, IDS_MAIN_TITLE, MB_OK);
}
else
{
ExpandEnvironmentStrings(TEXT("%systemroot%\\system32\\Notepad.exe"),
szNotepad,
ARRAYSIZE(szNotepad));
hr = StringCchCopy(szCmdLine, ARRAYSIZE(szCmdLine), szNotepad);
hr = StringCchCat(szCmdLine, ARRAYSIZE(szCmdLine), TEXT(" "));
hr = StringCchCat(szCmdLine, ARRAYSIZE(szCmdLine), szReadmePath);
StartProcess(szNotepad,
szCmdLine,
TEXT("."));
}
}
//-----------------------------------------------------------------------------
//
// Function: StartProcess
//
// Synopsis: Start a Windows application
//
// Returns: TRUE if an application is started
// FALSE otherwise
//
// History: 08/14/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL StartProcess(
LPCTSTR lpAppName, // Application name
LPTSTR lpCmdLine, // Application command line
LPCTSTR lpCurrentDir // Working directory
)
{
BOOL bRet = FALSE;
STARTUPINFO siApp;
PROCESS_INFORMATION piApp;
ZeroMemory(&siApp, sizeof(STARTUPINFO));
siApp.cb = sizeof(STARTUPINFO);
// CreateProcess call conforms to security guideline
bRet = CreateProcess(lpAppName,
lpCmdLine,
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS,
NULL,
lpCurrentDir,
&siApp,
&piApp);
return bRet;
}
//-----------------------------------------------------------------------------
//
// Function: ThreadProc
//
// Synopsis: A procedure that will be run on remote thread
//
// Returns:
//
// History: 08/20/2002 rerkboos created
//
// Notes: Code is copied from Fontspy
//
//-----------------------------------------------------------------------------
DWORD WINAPI ThreadProc(
PGETMODULENAME pgmn
)
{
pgmn->szfname[0] = 0;
if (pgmn->pfnGetModuleHandle(pgmn->szUser32))
{
pgmn->pfn(pgmn->hWnd, pgmn->szfname, MAX_PATH);
}
return 0;
}
//-----------------------------------------------------------------------------
//
// Function: GetWindowModuleFileNameOnly
//
// Synopsis: Get the module name that load the current window
//
// Returns:
//
// History: 08/20/2002 rerkboos created
//
// Notes: Code is copied from FontSpy
//
//-----------------------------------------------------------------------------
LPCTSTR GetWindowModuleFileNameOnly(
HWND hWnd,
LPTSTR lpszFile,
DWORD cchFile
)
{
HRESULT hr;
DWORD dwProcessID;
DWORD dwThreadID;
HANDLE hProcess;
HANDLE hThread = NULL;
DWORD dwXfer;
PBYTE pv = NULL;
LPCTSTR psz;
UINT uCodeSize;
GETMODULENAME gmn;
uCodeSize = (ULONG) GetWindowModuleFileNameOnly - (ULONG) ThreadProc;
ZeroMemory(&gmn, sizeof(gmn));
__try
{
GetWindowThreadProcessId(hWnd, &dwProcessID);
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);
if (!hProcess)
{
hr = StringCchCopy(lpszFile, cchFile, TEXT("Access Denied"));
__leave;
}
gmn.hWnd = hWnd;
hr = StringCchCopy(gmn.szUser32, ARRAYSIZE(gmn.szUser32), TEXT("user32"));
if (FAILED(hr))
{
__leave;
}
gmn.pfn = (PFNGETMODULENAME) GetProcAddress(
GetModuleHandle(_T("user32")),
#ifdef UNICODE
"GetWindowModuleFileNameW"
#else
"GetWindowModuleFileNameA"
#endif
);
if (!gmn.pfn)
{
__leave;
}
gmn.pfnGetModuleHandle = (PFNGETMODULEHANDLE)GetProcAddress(
GetModuleHandle(_T("kernel32")),
#ifdef UNICODE
"GetModuleHandleW"
#else
"GetModuleHandleA"
#endif
);
if (!gmn.pfnGetModuleHandle)
{
__leave;
}
pv = (PBYTE)VirtualAllocEx(
hProcess,
0,
uCodeSize + sizeof(gmn),
MEM_COMMIT,
PAGE_EXECUTE_READWRITE
);
if (!pv)
{
__leave;
}
WriteProcessMemory(
hProcess,
pv,
&gmn,
sizeof(gmn),
&dwXfer
);
WriteProcessMemory(
hProcess,
pv+offsetof(GETMODULENAME, pvCode),
ThreadProc,
uCodeSize,
&dwXfer
);
hThread = CreateRemoteThread(
hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE) (pv + offsetof(GETMODULENAME, pvCode)),
pv,
0,
&dwThreadID
);
WaitForSingleObject(hThread, INFINITE);
ReadProcessMemory(hProcess, pv, &gmn, sizeof(gmn), &dwXfer);
}
__finally
{
if (pv)
{
//VirtualFreeEx(hProcess, pv, uCodeSize+sizeof(gmn), MEM_DECOMMIT);
VirtualFreeEx(hProcess, pv, 0, MEM_RELEASE);
}
if (hProcess != NULL)
{
CloseHandle(hProcess);
}
if (hThread != NULL)
{
CloseHandle(hThread);
}
}
hr = StringCchCopy(lpszFile, cchFile, gmn.szfname);
psz = _tcsrchr(lpszFile, _T('\\'))+1;
if (!psz)
{
psz = lpszFile;
}
return psz;
}