Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

955 lines
27 KiB

//+---------------------------------------------------------------------------
//
// 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;
}