#include "StdAfx.h" #include #include #include #include #include #include // 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; }