|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1998.
//
// File: acpienab.cpp
//
// Contents: Functions to enable ACPI on a machine which has had NT5
// installed in legacy mode
//
// Notes:
//
// Author: t-sdey 17 July 98
//
//----------------------------------------------------------------------------
#include <winnt32.h>
#include <devguid.h>
extern "C" { #include <cfgmgr32.h>
#include "idchange.h"
} #include "acpienab.h"
#include "acpirsrc.h"
// Global Variables
HINSTANCE g_hinst; TCHAR g_ACPIENAB_INF[] = TEXT(".\\acpienab.inf"); // local directory
TCHAR g_LAYOUT_INF[] = TEXT("layout.inf"); // winnt\inf directory
TCHAR g_HAL_BACKUP[] = TEXT("hal-old.dll");
//+---------------------------------------------------------------------------
//
// Function: WinMain
//
// Purpose: Run everything
//
// Arguments: Standard WinMain arguments
//
// Author: t-sdey 27 July 98
//
// Notes:
//
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { g_hinst = hInstance; // Enable ACPI
ACPIEnable(); return TRUE; }
// ----------------------------------------------------------------------
//
// Function: ACPIEnable
//
// Purpose: This function performs the steps necessary to enable ACPI
// and bring the system to a point where the user can log in
// after rebooting. It leaves finding "new" hardware to after
// the user has rebooted and logged in again.
//
// Arguments:
//
// Returns: S_OK if successful
// S_FALSE if unsuccessful
//
// Author: t-sdey 27 July 98
//
// Notes:
//
HRESULT ACPIEnable() { //
// These steps are in order from least to most crucial to the stability
// of the system, in case of errors.
//
// Step 1: Test to see if ACPI can be enabled and warn the user to close
// everything else.
// Step 2: Prepare a safe configuration in case of errors.
// Step 3: Set up keyboard and mouse for use after reboot. This involves
// removing them from the CriticalDeviceDatabase so that they will
// be reconfigured (according to the new ACPI layout) after reboot.
// The current keyboards and mice are in the CDD, but we must
// populate it with all possibilities, because their HardwareIDs
// will probably change once ACPI is enabled.
// Step 4: Add new values to the registry:
// - Add ACPI to the CriticalDeviceDatabase
// - Add keyboards and mice to the CriticalDeviceDatabase
// - Enable ACPI in the registry
// Step 5: Copy the ACPI driver.
// Step 6: Copy the new HAL.
// Step 7: Reboot.
//
//
// Step 1: Test to see if ACPI can be enabled and warn the user to close
// everything else.
//
// Make sure the user has administrative access
if (!IsAdministrator()) { DisplayDialogBox(ACPI_STR_ERROR_DIALOG_CAPTION, ACPI_STR_ADMIN_ACCESS_REQUIRED, MB_OK | MB_ICONERROR); return S_FALSE; }
// Test to see if ACPI is supported on this architecture
SYSTEM_INFO SystemInfo; // Will be used later to determine HAL
GetSystemInfo(&SystemInfo); if (SystemInfo.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL) { // Not supported
DisplayDialogBox(ACPI_STR_ERROR_DIALOG_CAPTION, ACPI_STR_NOT_SUPPORTED, MB_OK | MB_ICONERROR); return S_FALSE; }
// Warn the user to shut down any other programs
if (DisplayDialogBox(ACPI_STR_WARNING_DIALOG_CAPTION, ACPI_STR_SHUTDOWN_WARNING, MB_YESNO | MB_ICONWARNING) == IDNO) { // The user cancelled
return S_FALSE; }
//
// Step 2: Prepare a safe configuration in case of errors.
//
// Make a backup copy of the old HAL
// Get location of the system directory
TCHAR* szSystemDir = new TCHAR[MAX_PATH+1]; if (!szSystemDir) { // Out of memory
DisplayGenericErrorAndUndoChanges(); return S_FALSE; } UINT uiSysDirLen = GetSystemDirectory(szSystemDir, MAX_PATH+1); if (uiSysDirLen == 0) { // Some error occurred
DisplayGenericErrorAndUndoChanges(); if (szSystemDir) delete[] szSystemDir; return S_FALSE; } // Assemble strings with the locations of the current and backup file
TCHAR szHal[] = TEXT("hal.dll"); TCHAR* szHalCurrent = new TCHAR[uiSysDirLen + lstrlen(szHal) + 1]; TCHAR* szHalBackup = new TCHAR[uiSysDirLen + lstrlen(g_HAL_BACKUP) + 1]; if (!szHalCurrent || !szHalBackup) { // Out of memory
DisplayGenericErrorAndUndoChanges(); delete[] szSystemDir; if (szHalCurrent) delete[] szHalCurrent; if (szHalBackup) delete[] szHalBackup; return S_FALSE; } _tcscpy(szHalCurrent, szSystemDir); _tcscat(szHalCurrent, TEXT("\\")); _tcscat(szHalCurrent, szHal); _tcscpy(szHalBackup, szSystemDir); _tcscat(szHalBackup, TEXT("\\")); _tcscat(szHalBackup, g_HAL_BACKUP);
// Copy the HAL
if (CopyFile(szHalCurrent, szHalBackup, FALSE) == FALSE) { // Error copying file
DisplayGenericErrorAndUndoChanges(); delete[] szSystemDir; delete[] szHalCurrent; delete[] szHalBackup; return S_FALSE; } delete[] szSystemDir; delete[] szHalCurrent; delete[] szHalBackup;
// Make it possible to boot with the backup HAL if necessary
// Find the system partition letter
// Edit boot.ini
// -- add new NT5 boot line with "\HAL=hal-old.dll" on the end
// Temporary: tell the user to do it manually
MessageBox(NULL, TEXT("If you want to ensure that you can recover if this process fails,\nadd a line to your boot.ini with \" /HAL=hal-old.dll\""), TEXT("This is a temporary hack!"), MB_ICONWARNING | MB_OK);
//
// Step 3: Set up keyboard and mouse for use after reboot. This involves
// removing them from the CriticalDeviceDatabase so that they will
// be reconfigured (according to the new ACPI layout) after reboot.
// The current keyboards and mice are in the CDD, but we must
// populate it with all possibilities, because their HardwareIDs
// will probably change once ACPI is enabled.
//
// Set up keyboard(s) for use after reboot
if (RegDeleteDeviceKey(&GUID_DEVCLASS_KEYBOARD) == FALSE) { // Error
DisplayGenericErrorAndUndoChanges(); return S_FALSE; }
// Set up mouse (mice) for use after reboot
if (RegDeleteDeviceKey(&GUID_DEVCLASS_MOUSE) == FALSE) { // Error
DisplayGenericErrorAndUndoChanges(); return S_FALSE; }
//
// Step 4: Add new values to the registry:
// - Add ACPI to the CriticalDeviceDatabase
// - Add keyboards and mice to the CriticalDeviceDatabase
// - Enable ACPI in the registry
//
if (InstallRegistryAndFilesUsingInf(g_ACPIENAB_INF, TEXT("ACPI_REGISTRY.Install")) == 0) { // Error
DisplayGenericErrorAndUndoChanges(); return S_FALSE; }
//
// Step 5: Copy the ACPI driver.
//
// Copy the ACPI driver to the system directory
if (InstallRegistryAndFilesUsingInf(g_ACPIENAB_INF, TEXT("ACPI_DRIVER.Install")) == 0) { // Error
DisplayGenericErrorAndUndoChanges(); return S_FALSE; }
//
// Step 6: Copy the new HAL.
//
// Determine which HAL will be needed
TCHAR szHalInstall[50]; int HAL = 0; // Determine if it's a single or multi-processor machine
BOOL SingleProc = (SystemInfo.dwNumberOfProcessors == 1); if (SingleProc) { HAL += 2; } // Determine if it's a PIC or APIC machine
BOOL PIC = TRUE; if (!SingleProc) { // Don't run the UsePICHal function unless we have to
PIC = FALSE; } else { if (UsePICHal(&PIC) == FALSE) { // An error occurred
DisplayGenericErrorAndUndoChanges(); return S_FALSE; } } if (PIC) { HAL += 1; }
// Lookup table for HALs
switch (HAL) { case 3: // x86 1-proc PIC
_tcscpy(szHalInstall, TEXT("INTEL_1PROC_PIC_HAL")); break; case 2: // x86 1-proc APIC
_tcscpy(szHalInstall, TEXT("INTEL_1PROC_APIC_HAL")); break; case 1: // x86 multi-proc PIC -- doesn't exist...
_tcscpy(szHalInstall, TEXT("INTEL_MULTIPROC_PIC_HAL")); break; case 0: // x86 multi-proc APIC
_tcscpy(szHalInstall, TEXT("INTEL_MULTIPROC_APIC_HAL")); break; } _tcscat(szHalInstall, TEXT(".Install"));
// Copy the HAL to the system directory
if (InstallRegistryAndFilesUsingInf(g_ACPIENAB_INF, szHalInstall) == 0) { // Error
DisplayGenericErrorAndUndoChanges(); return S_FALSE; }
//
// Step 7: Reboot.
//
// Warn the user that we're going to reboot
DisplayDialogBox(ACPI_STR_REBOOT_DIALOG_CAPTION, ACPI_STR_REBOOT_WARNING, MB_OK);
// Get shutdown privilege by opening the process token and adjusting its
// privileges.
HANDLE hToken; TOKEN_PRIVILEGES tkp; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { // Could not open process token. Tell the user to reboot manually.
DisplayDialogBox(ACPI_STR_REBOOT_DIALOG_CAPTION, ACPI_STR_REBOOT_ERROR, MB_OK); return S_OK; } LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
// Reboot
if (ExitWindowsEx(EWX_REBOOT | EWX_FORCEIFHUNG, 0) == 0) { // An error occurred. Tell the user to reboot manually.
DisplayDialogBox(ACPI_STR_REBOOT_DIALOG_CAPTION, ACPI_STR_REBOOT_ERROR, MB_OK); }
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Function: InstallRegistryAndFilesUsingInf
//
// Purpose: Open an INF file and perform the registry addition/deletion and
// file copy operations specified there under a given install
// section.
//
// Arguments: szInfFileName [in] Name of INF file to open
// (should be located in system inf
// directory)
// szInstallSection [in] Install section (in INF) to use
//
// Returns: TRUE if successful
// FALSE otherwise
//
// Author: t-sdey 14 Aug 98
//
// Notes:
//
BOOL InstallRegistryAndFilesUsingInf(IN LPCTSTR szInfFileName, IN LPCTSTR szInstallSection) { HINF hinf;
//
// Prepare the file queue
//
// Create a file queue
HSPFILEQ FileQueue = SetupOpenFileQueue(); if(!FileQueue || (FileQueue == INVALID_HANDLE_VALUE)) { // Error
return FALSE; }
// Initialize the queue callback function
HWND Window = NULL; VOID* DefaultContext = SetupInitDefaultQueueCallback(Window);
//
// Open the INF file and perform file installation
//
// Open the source INF
hinf = SetupOpenInfFile(szInfFileName, TEXT("System"), INF_STYLE_WIN4, NULL); if (hinf == INVALID_HANDLE_VALUE) { // Error
SetupCloseFileQueue(FileQueue); return FALSE; } // Append the layout INF to get the source location for the files
if (SetupOpenAppendInfFile(g_LAYOUT_INF, hinf, NULL) == FALSE) { // Could not open file
SetupCloseInfFile(hinf); SetupCloseFileQueue(FileQueue); return FALSE; }
// Read the INF and perform the actions it dictates
if (SetupInstallFromInfSection(NULL, hinf, szInstallSection, SPINST_REGISTRY | SPINST_FILES, HKEY_LOCAL_MACHINE, NULL, // Source root path
SP_COPY_WARNIFSKIP, (PSP_FILE_CALLBACK)SetupDefaultQueueCallback, DefaultContext, NULL, NULL) == 0) { // Error
SetupCloseInfFile(hinf); SetupCloseFileQueue(FileQueue); return FALSE; }
// Commit the file queue to make sure all queued file copies are performed
if (SetupCommitFileQueue(NULL, FileQueue, (PSP_FILE_CALLBACK)SetupDefaultQueueCallback, DefaultContext) == 0) { // Error
SetupCloseInfFile(hinf); SetupCloseFileQueue(FileQueue); return FALSE; }
// Clean up
SetupCloseInfFile(hinf); SetupCloseFileQueue(FileQueue);
return TRUE; }
//+---------------------------------------------------------------------------
//
// Function: RegDeleteDeviceKey
//
// Purpose: All devices described by guid are removed from the device
// tree (HKLM\SYSTEM\CurrentControlSet\Enum\Root).
// This forces them to be reconfigured on reboot.
//
// Arguments: guid [in] GUID of device class
//
// Returns: TRUE if successful.
// FALSE otherwise.
//
// Author: t-sdey 14 Aug 98
//
// Notes:
//
BOOL RegDeleteDeviceKey(IN const GUID* guid) { // Open the Root key under Enum with administrative access
HKEY hkey = NULL; TCHAR szEnumRoot[] = TEXT("SYSTEM\\CurrentControlSet\\Enum\\Root"); PSECURITY_DESCRIPTOR psdOriginal = NULL; if (DwRegOpenKeyExWithAdminAccess(HKEY_LOCAL_MACHINE, szEnumRoot, KEY_ALL_ACCESS, &hkey, &psdOriginal) != ERROR_SUCCESS) { // Error
RegCloseKey(hkey); return FALSE; }
// Get the list of devices with this GUID on the system. Remove each
// of them from the device tree, so that the next time the computer boots
// it is re-detected and re-configured for the new ACPI setup.
// (Otherwise the device will be configured incorrectly.)
// Get the list of devices with this GUID on the system
HDEVINFO hdiDeviceClass = SetupDiGetClassDevs(guid, NULL, NULL, 0); // Prepare data structures for loop
SP_DEVINFO_DATA DeviceInfoData; DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); DWORD dwIndex = 0; unsigned long BufferMax = 5000; // 5000 chars better be enough for the HID!
unsigned long BufferLen; TCHAR* szHardwareID = new TCHAR[BufferMax]; if (szHardwareID == NULL) { // Out of memory
DisplayGenericErrorAndUndoChanges(); SetupDiDestroyDeviceInfoList(hdiDeviceClass); if (psdOriginal) delete psdOriginal; RegCloseKey(hkey); return FALSE; }
// Loop for each device with this GUID
while (SetupDiEnumDeviceInfo(hdiDeviceClass, dwIndex, &DeviceInfoData)) { // Get the Hardware ID
BufferLen = BufferMax; if (CM_Get_DevInst_Registry_Property_Ex(DeviceInfoData.DevInst, CM_DRP_HARDWAREID, NULL, szHardwareID, &BufferLen, 0, 0) != CR_SUCCESS) { // Error
DisplayGenericErrorAndUndoChanges(); SetupDiDestroyDeviceInfoList(hdiDeviceClass); if (szHardwareID) delete[] szHardwareID; if (psdOriginal) delete psdOriginal; RegCloseKey(hkey); return FALSE; } // Remove from the device tree
if (RegDeleteKeyAndSubkeys(hkey, szHardwareID, TRUE) != ERROR_SUCCESS) { // Error
DisplayGenericErrorAndUndoChanges(); SetupDiDestroyDeviceInfoList(hdiDeviceClass); if (szHardwareID) delete[] szHardwareID; if (psdOriginal) delete psdOriginal; RegCloseKey(hkey); return FALSE; }
dwIndex++; } // Reset the security on the Root key
if (psdOriginal) { RegSetKeySecurity(hkey, (SECURITY_INFORMATION) (DACL_SECURITY_INFORMATION), psdOriginal); delete psdOriginal; }
// Clean up
SetupDiDestroyDeviceInfoList(hdiDeviceClass); if (szHardwareID) delete[] szHardwareID; if (hkey) RegCloseKey(hkey);
return TRUE; }
//+---------------------------------------------------------------------------
//
// Function: DisplayGenericErrorAndUndoChanges
//
// Purpose: Pop up a message box with a generic error message and then
// undo as many changes as possible. Basically, used to recover
// from errors which occur before ACPI is fully enabled.
//
// Arguments:
//
// Author: t-sdey 31 July 98
//
// Notes:
//
void DisplayGenericErrorAndUndoChanges() { // Give a generic error message
DisplayDialogBox(ACPI_STR_ERROR_DIALOG_CAPTION, ACPI_STR_GENERAL_ERROR_MESSAGE, MB_OK | MB_ICONERROR); // Remove new entries from the CriticalDeviceDatabase
InstallRegistryAndFilesUsingInf(g_ACPIENAB_INF, TEXT("ACPI_UNDO_CHANGES.Install")); }
//+---------------------------------------------------------------------------
//
// Function: DisplayDialogBox
//
// Purpose: Display a popup informing the user of a warning or error.
//
// Arguments: dwCaptionID [in] the ID of the caption for the window
// dwMessageID [in] the ID of the message to display
// uiBoxType [in] the type of box to use
//
// Returns: integer flag, as would be returned by MessageBox
//
// Author: t-sdey 28 July 98
//
// Notes:
//
int DisplayDialogBox(IN DWORD dwCaptionID, IN DWORD dwMessageID, IN UINT uiBoxType) { // Prepare the strings
TCHAR szCaption[512]; TCHAR szMessage[5000]; if(!LoadString(g_hinst, dwCaptionID, szCaption, 512)) { szCaption[0] = 0; } if(!LoadString(g_hinst, dwMessageID, szMessage, 5000)) { szMessage[0] = 0; }
// Create the dialog box
return (MessageBox(NULL, szMessage, szCaption, uiBoxType)); }
//+---------------------------------------------------------------------------
//
// Function: RegDeleteKeyAndSubkeys
//
// Purpose: (Recursively) Remove a registry key and all of its subkeys
//
// Arguments: hKey [in] Handle to an open registry key
// lpszSubKey [in] Name of a subkey to be deleted along with all
// of its subkeys
// UseAdminAccess [in] Flag to indicate whether or not to try to
// use administrative access
//
// Returns: ERROR_SUCCESS if entire subtree was successfully deleted.
// ERROR_ACCESS_DENIED if given subkey could not be deleted.
//
// Author: t-sdey 15 July 98
//
// Notes: Modified from regedit.
// This specifically does not attempt to deal rationally with the
// case where the caller may not have access to some of the subkeys
// of the key to be deleted. In this case, all the subkeys which
// the caller can delete will be deleted, but the api will still
// return ERROR_ACCESS_DENIED.
//
LONG RegDeleteKeyAndSubkeys(IN HKEY hKey, IN LPTSTR lpszSubKey, IN BOOL UseAdminAccess) { DWORD i; HKEY Key; LONG Status; DWORD dwStatus; DWORD ClassLength=0; DWORD SubKeys; DWORD MaxSubKey; DWORD MaxClass; DWORD Values; DWORD MaxValueName; DWORD MaxValueData; DWORD SecurityLength; FILETIME LastWriteTime; LPTSTR NameBuffer; PSECURITY_DESCRIPTOR psdOriginal = NULL; // used to remember security settings
//
// First open the given key so we can enumerate its subkeys
//
if (UseAdminAccess) { dwStatus = DwRegOpenKeyExWithAdminAccess(hKey, lpszSubKey, KEY_ALL_ACCESS, &Key, &psdOriginal); if (dwStatus == ERROR_SUCCESS) { Status = ERROR_SUCCESS; } else { Status = !(ERROR_SUCCESS); // It just has to be something else
} } else { Status = RegOpenKeyEx(hKey, lpszSubKey, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &Key); }
if (Status != ERROR_SUCCESS) { //
// possibly we have delete access, but not enumerate/query.
// So go ahead and try the delete call, but don't worry about
// any subkeys. If we have any, the delete will fail anyway.
//
Status = RegDeleteKey(hKey, lpszSubKey); if (psdOriginal) { // Make sure to reset the subkey security -- probably a paranoid check
RegSetKeySecurity(Key, (SECURITY_INFORMATION) (DACL_SECURITY_INFORMATION), psdOriginal); free(psdOriginal); } return(Status); }
//
// Use RegQueryInfoKey to determine how big to allocate the buffer
// for the subkey names.
//
Status = RegQueryInfoKey(Key, NULL, &ClassLength, 0, &SubKeys, &MaxSubKey, &MaxClass, &Values, &MaxValueName, &MaxValueData, &SecurityLength, &LastWriteTime); if ((Status != ERROR_SUCCESS) && (Status != ERROR_MORE_DATA) && (Status != ERROR_INSUFFICIENT_BUFFER)) { // Make sure to reset the subkey security
if (psdOriginal) { RegSetKeySecurity(Key, (SECURITY_INFORMATION) (DACL_SECURITY_INFORMATION), psdOriginal); free(psdOriginal); }
RegCloseKey(Key); return(Status); }
NameBuffer = (LPTSTR) LocalAlloc(LPTR, (MaxSubKey + 1)*sizeof(TCHAR)); if (NameBuffer == NULL) { // Make sure to reset the subkey security
if (psdOriginal) { RegSetKeySecurity(Key, (SECURITY_INFORMATION) (DACL_SECURITY_INFORMATION), psdOriginal); free(psdOriginal); } RegCloseKey(Key); return(ERROR_NOT_ENOUGH_MEMORY); }
//
// Enumerate subkeys and apply ourselves to each one.
//
i=0; do { Status = RegEnumKey(Key, i, NameBuffer, MaxSubKey+1); if (Status == ERROR_SUCCESS) { Status = RegDeleteKeyAndSubkeys(Key, NameBuffer, UseAdminAccess); }
if (Status != ERROR_SUCCESS) { //
// Failed to delete the key at the specified index. Increment
// the index and keep going. We could probably bail out here,
// since the api is going to fail, but we might as well keep
// going and delete everything we can.
//
++i; }
} while ((Status != ERROR_NO_MORE_ITEMS) && (i < SubKeys)); LocalFree((HLOCAL) NameBuffer); RegCloseKey(Key);
// Delete the key
Status = RegDeleteKey(hKey, lpszSubKey);
if (psdOriginal) free(psdOriginal);
return (Status); }
//+---------------------------------------------------------------------------
//
// Function: IsAdministrator
//
// Purpose: Determine whether or not the current user has administrative
// access to the system.
//
// Arguments:
//
// Returns: TRUE if the current user has administrative access
// FALSE otherwise
//
// Author: t-sdey 17 Aug 98
//
// Notes: Copied from \nt\private\tapi\tomahawk\admin\setup\admin.c
//
BOOL IsAdministrator() { PTOKEN_GROUPS ptgGroups; DWORD dwSize, dwBufferSize; HANDLE hThread; HANDLE hAccessToken; PSID psidAdministrators; SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY; UINT x; BOOL bResult = FALSE;
dwSize = 1000; ptgGroups = (PTOKEN_GROUPS)GlobalAlloc(GPTR, dwSize); hThread = GetCurrentProcess(); if (!(OpenProcessToken(hThread, TOKEN_READ, &hAccessToken))) { CloseHandle(hThread); return FALSE; }
dwBufferSize = 0; while (TRUE) { if (GetTokenInformation(hAccessToken, TokenGroups, (LPVOID)ptgGroups, dwSize, &dwBufferSize)) { break; }
if (dwBufferSize > dwSize) { GlobalFree(ptgGroups); ptgGroups = (PTOKEN_GROUPS)GlobalAlloc(GPTR, dwBufferSize); dwSize = dwBufferSize; } else { CloseHandle(hThread); CloseHandle(hAccessToken); return FALSE; } }
if ( !(AllocateAndInitializeSid(&siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdministrators))) { CloseHandle(hThread); CloseHandle(hAccessToken); GlobalFree( ptgGroups ); return FALSE; }
for (x = 0; x < ptgGroups->GroupCount; x++) { if (EqualSid(psidAdministrators, ptgGroups->Groups[x].Sid)) { bResult = TRUE; break; } }
FreeSid(psidAdministrators); CloseHandle(hAccessToken); CloseHandle(hThread); GlobalFree(ptgGroups);
return bResult; }
//+---------------------------------------------------------------------------
//
// Function: UsePICHal
//
// Purpose: Determine whether this is a PIC machine or not (not=APIC).
//
// Arguments: pPIC [out] A flag saying whether or not the machine is a PIC
// machine. If it is (and there are no errors) then
// pPIC will be set to TRUE. If it is an APIC machine
// pPIC will be FALSE.
//
// Returns: TRUE if test was successful
// FALSE if an error occurred
//
// Author: t-sdey 20 Aug 98
//
// Notes:
//
BOOL UsePICHal(IN BOOL* PIC) { *PIC = TRUE;
// Find out which HAL was installed during setup by looking at
// winnt\repair\setup.log.
//
// Determine the location of the setup log
//
// Determine the location of the windows directory
TCHAR* szLogPath = new TCHAR[MAX_PATH+1]; if (!szLogPath) { // Out of memory
return FALSE; } if (GetWindowsDirectory(szLogPath, MAX_PATH+1) == 0) { // Some error occurred
if (szLogPath) delete[] szLogPath; return FALSE; } // Complete the log path
_tcscat(szLogPath, TEXT("\\repair\\setup.log"));
//
// Get the string describing the HAL that was used in setup
//
TCHAR szSetupHal[100]; int numchars= GetPrivateProfileString(TEXT("Files.WinNt"), TEXT("\\WINNT\\system32\\hal.dll"), TEXT("DEFAULT"), szSetupHal, 100, szLogPath); if (numchars == 0) { // Could not get string
if (szLogPath) delete[] szLogPath; return FALSE; }
//
// Determine if the APIC HAL was installed
//
// Test to see if the string is "halapic.dll"
TCHAR szApicHal[] = TEXT("halapic.dll"); szSetupHal[lstrlen(szApicHal)] = 0; // make sure it's null-terminated
if (_tcsstr(szSetupHal, szApicHal) != NULL) { // They match... It's an APIC HAL
*PIC = FALSE; }
delete[] szLogPath; return TRUE; }
|