mirror of https://github.com/tongzx/nt5src
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.
1064 lines
30 KiB
1064 lines
30 KiB
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORP., 1996
|
|
*
|
|
* TITLE: REGHELP.C
|
|
*
|
|
* VERSION: 2.0
|
|
*
|
|
* AUTHOR: ReedB
|
|
*
|
|
* DATE: 17 Oct, 1996
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
|
|
#include <windows.h>
|
|
#include <string.h>
|
|
#include <regstr.h>
|
|
#include <commctrl.h>
|
|
|
|
#include <ntpoapi.h>
|
|
|
|
#include "powrprofp.h"
|
|
#include "reghelp.h"
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* G L O B A L D A T A
|
|
*
|
|
*******************************************************************************/
|
|
|
|
extern HINSTANCE g_hInstance; // Global instance handle of this DLL.
|
|
extern HANDLE g_hSemRegistry; // Registry semaphore.
|
|
extern UINT g_uiLastID; // The last ID value used, per machine.
|
|
|
|
extern TCHAR c_szREGSTR_PATH_MACHINE_POWERCFG[];
|
|
extern TCHAR c_szREGSTR_VAL_LASTID[];
|
|
|
|
// Global semaphore name.
|
|
const TCHAR c_szSemRegistry[] = TEXT("PowerProfileRegistrySemaphore");
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* OpenCurrentUser
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
DWORD OpenCurrentUser2(PHKEY phKey)
|
|
{
|
|
#ifdef WINNT
|
|
|
|
// Since powerprof can be called in the Winlogon context when
|
|
// a user is being impersonated, use RegOpenCurrentUser to get HKCU.
|
|
LONG lRet = RegOpenCurrentUser(KEY_ALL_ACCESS, phKey);
|
|
if (lRet != ERROR_SUCCESS)
|
|
{
|
|
DebugPrint("RegOpenCurrentUser, failed, LastError: 0x%08X", lRet);
|
|
}
|
|
|
|
return lRet;
|
|
|
|
#else
|
|
*phKey = HKEY_CURRENT_USER;
|
|
return ERROR_SUCCESS;
|
|
#endif
|
|
}
|
|
|
|
|
|
BOOLEAN OpenCurrentUser(PHKEY phKey)
|
|
{
|
|
DWORD dwError = OpenCurrentUser2(phKey);
|
|
BOOLEAN fSucceeded = TRUE;
|
|
|
|
if (ERROR_SUCCESS != dwError)
|
|
{
|
|
fSucceeded = FALSE;
|
|
SetLastError(dwError);
|
|
}
|
|
|
|
return fSucceeded;
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* CloseCurrentUser
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
BOOLEAN CloseCurrentUser(HKEY hKey)
|
|
{
|
|
#ifdef WINNT
|
|
RegCloseKey(hKey);
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* OpenMachineUserKeys
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
DWORD OpenMachineUserKeys2(
|
|
LPTSTR lpszUserKeyName,
|
|
LPTSTR lpszMachineKeyName,
|
|
PHKEY phKeyUser,
|
|
PHKEY phKeyMachine
|
|
)
|
|
{
|
|
HKEY hKeyCurrentUser;
|
|
DWORD dwError = OpenCurrentUser2(&hKeyCurrentUser);
|
|
|
|
if (ERROR_SUCCESS == dwError) // Sets Last Error
|
|
{
|
|
dwError = RegOpenKey(hKeyCurrentUser, lpszUserKeyName, phKeyUser);
|
|
if (dwError == ERROR_SUCCESS)
|
|
{
|
|
dwError = RegOpenKey(HKEY_LOCAL_MACHINE, lpszMachineKeyName, phKeyMachine);
|
|
if (dwError == ERROR_SUCCESS)
|
|
{
|
|
CloseCurrentUser(hKeyCurrentUser);
|
|
return dwError;
|
|
}
|
|
else
|
|
{
|
|
DebugPrint("OpenMachineUserKeys, failure opening HKEY_LOCAL_MACHINE\\%s", lpszMachineKeyName);
|
|
}
|
|
|
|
RegCloseKey(*phKeyUser);
|
|
}
|
|
else
|
|
{
|
|
DebugPrint("OpenMachineUserKeys, failure opening HKEY_CURRENT_USER\\%s", lpszUserKeyName);
|
|
}
|
|
|
|
CloseCurrentUser(hKeyCurrentUser);
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
DebugPrint("OpenMachineUserKeys, failed, LastError: 0x%08X", dwError);
|
|
return dwError;
|
|
}
|
|
|
|
|
|
BOOLEAN OpenMachineUserKeys(
|
|
LPTSTR lpszUserKeyName,
|
|
LPTSTR lpszMachineKeyName,
|
|
PHKEY phKeyUser,
|
|
PHKEY phKeyMachine)
|
|
{
|
|
DWORD dwError = OpenMachineUserKeys2(lpszUserKeyName, lpszMachineKeyName, phKeyUser, phKeyMachine);
|
|
BOOLEAN fSucceeded = TRUE;
|
|
|
|
if (ERROR_SUCCESS != dwError)
|
|
{
|
|
fSucceeded = FALSE;
|
|
SetLastError(dwError);
|
|
}
|
|
|
|
return fSucceeded;
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* OpenPathKeys
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
DWORD OpenPathKeys(
|
|
LPTSTR lpszUserKeyName,
|
|
LPTSTR lpszMachineKeyName,
|
|
LPTSTR lpszSchemeName,
|
|
PHKEY phKeyUser,
|
|
PHKEY phKeyMachine,
|
|
BOOLEAN bMustExist,
|
|
REGSAM sam
|
|
)
|
|
{
|
|
HKEY hKeyUser, hKeyMachine;
|
|
|
|
DWORD dwError = OpenMachineUserKeys2(lpszUserKeyName, lpszMachineKeyName, &hKeyUser, &hKeyMachine);
|
|
if (ERROR_SUCCESS == dwError)
|
|
{
|
|
DWORD dwDisposition;
|
|
|
|
dwError = RegCreateKeyEx(hKeyUser, lpszSchemeName, 0, TEXT(""), REG_OPTION_NON_VOLATILE, sam, NULL, phKeyUser, &dwDisposition);
|
|
if (dwError == ERROR_SUCCESS)
|
|
{
|
|
if (!bMustExist || (dwDisposition == REG_OPENED_EXISTING_KEY))
|
|
{
|
|
dwError = RegCreateKeyEx(hKeyMachine,
|
|
lpszSchemeName,
|
|
0,
|
|
TEXT(""),
|
|
REG_OPTION_NON_VOLATILE,
|
|
sam,
|
|
NULL,
|
|
phKeyMachine,
|
|
&dwDisposition);
|
|
if (dwError == ERROR_SUCCESS)
|
|
{
|
|
if (!bMustExist ||
|
|
(dwDisposition == REG_OPENED_EXISTING_KEY))
|
|
{
|
|
// This is the success case.
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_ACCESS_DENIED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RegCloseKey(*phKeyUser);
|
|
DebugPrint("OpenPathKeys, unable to create machine key %s\\%s", lpszMachineKeyName, lpszSchemeName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_ACCESS_DENIED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DebugPrint("OpenPathKeys, unable to create user key %s\\%s", lpszUserKeyName, lpszSchemeName);
|
|
}
|
|
|
|
RegCloseKey(hKeyUser);
|
|
RegCloseKey(hKeyMachine);
|
|
|
|
if (ERROR_SUCCESS != dwError)
|
|
{
|
|
DebugPrint("OpenPathKeys, failed, LastError: 0x%08X", dwError);
|
|
}
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
PACL BuildSemaphoreACL (void)
|
|
|
|
// 2000-06-22 vtan:
|
|
//
|
|
// This function builds an ACL which allows everybody access to the named
|
|
// semaphore for SYNCHRONIZE | READ_CONTROL | SEMAPHORE_QUERY_STATE | SEMAPHORE_MODIFY_STATE.
|
|
// It gives full access for the local SYSTEM or members of the local administrators
|
|
// group. If something goes wrong the return result is NULL and no security descriptor
|
|
// is built then.
|
|
|
|
{
|
|
static SID_IDENTIFIER_AUTHORITY worldSIDAuthority = SECURITY_WORLD_SID_AUTHORITY;
|
|
static SID_IDENTIFIER_AUTHORITY securityNTAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
PSID pSIDWorld;
|
|
PACL pACL;
|
|
|
|
pACL = NULL;
|
|
if (AllocateAndInitializeSid(&worldSIDAuthority,
|
|
1,
|
|
SECURITY_WORLD_RID,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
&pSIDWorld) != FALSE)
|
|
{
|
|
PSID pSIDLocalSystem;
|
|
|
|
if (AllocateAndInitializeSid(&securityNTAuthority,
|
|
1,
|
|
SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
&pSIDLocalSystem) != FALSE)
|
|
{
|
|
PSID pSIDLocalAdministrators;
|
|
|
|
if (AllocateAndInitializeSid(&securityNTAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0, 0, 0, 0, 0, 0,
|
|
&pSIDLocalAdministrators) != FALSE)
|
|
{
|
|
DWORD dwACLSize;
|
|
|
|
dwACLSize = sizeof(ACL) +
|
|
((sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG)) * 3) +
|
|
GetLengthSid(pSIDWorld) +
|
|
GetLengthSid(pSIDLocalSystem) +
|
|
GetLengthSid(pSIDLocalAdministrators);
|
|
pACL = (PACL)LocalAlloc(LMEM_FIXED, dwACLSize);
|
|
if (pACL != NULL)
|
|
{
|
|
if ((InitializeAcl(pACL, dwACLSize, ACL_REVISION) == FALSE) ||
|
|
(AddAccessAllowedAce(pACL,
|
|
ACL_REVISION,
|
|
SYNCHRONIZE | READ_CONTROL | SEMAPHORE_QUERY_STATE | SEMAPHORE_MODIFY_STATE,
|
|
pSIDWorld) == FALSE) ||
|
|
(AddAccessAllowedAce(pACL,
|
|
ACL_REVISION,
|
|
SEMAPHORE_ALL_ACCESS,
|
|
pSIDLocalSystem) == FALSE) ||
|
|
(AddAccessAllowedAce(pACL,
|
|
ACL_REVISION,
|
|
SEMAPHORE_ALL_ACCESS,
|
|
pSIDLocalAdministrators) == FALSE))
|
|
{
|
|
(HLOCAL)LocalFree(pACL);
|
|
pACL = NULL;
|
|
}
|
|
}
|
|
(PVOID)FreeSid(pSIDLocalAdministrators);
|
|
}
|
|
(PVOID)FreeSid(pSIDLocalSystem);
|
|
}
|
|
(PVOID)FreeSid(pSIDWorld);
|
|
}
|
|
return(pACL);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* CreateRegSemaphore
|
|
*
|
|
* DESCRIPTION: Attempts to open/create the registry semaphore. g_hSemRegistry
|
|
* is initialized on success.
|
|
*
|
|
* PARAMETERS: None
|
|
*
|
|
*******************************************************************************/
|
|
|
|
BOOLEAN CreateRegSemaphore(VOID)
|
|
{
|
|
HANDLE Semaphore=NULL;
|
|
|
|
// First try to open the named semaphore with only required access.
|
|
|
|
// NOTE: the named object is per terminal server session. Therefore
|
|
// this semaphore is really bogus because it protects HKEY_LOCAL_MACHINE
|
|
// as well as HKEY_CURRENT_USER. Making it "Global\" is very dangerous
|
|
// and you don't know the side effects without complete retesting.
|
|
// Not worth it.
|
|
|
|
Semaphore = OpenSemaphore(SYNCHRONIZE | SEMAPHORE_QUERY_STATE | SEMAPHORE_MODIFY_STATE,
|
|
FALSE,
|
|
c_szSemRegistry);
|
|
if ((Semaphore == NULL) && (GetLastError() != ERROR_ACCESS_DENIED))
|
|
{
|
|
SECURITY_ATTRIBUTES securityAttributes, *pSA;
|
|
SECURITY_DESCRIPTOR securityDescriptor;
|
|
PACL pACL;
|
|
|
|
// If this fails then create the semaphore and ACL it so that everybody
|
|
// can get SYNCHRONIZE | SEMAPHORE_QUERY_STATE | SEMAPHORE_MODIFY_STATE
|
|
// access. This allows a service (such as UPS) running in the SYSTEM context
|
|
// to grant limited access to anybody who needs it to synchronize against
|
|
// this semaphore. It also prevents C2 violation by NOT putting a NULL
|
|
// DACL on the named semaphore. If an ACL for the semaphore cannot be
|
|
// built then no security descriptor is given and the default ACL is used.
|
|
|
|
pSA = NULL;
|
|
pACL = BuildSemaphoreACL();
|
|
if (pACL != NULL)
|
|
{
|
|
if ((InitializeSecurityDescriptor(&securityDescriptor, SECURITY_DESCRIPTOR_REVISION) != FALSE) &&
|
|
(SetSecurityDescriptorDacl(&securityDescriptor, TRUE, pACL, FALSE) != FALSE))
|
|
{
|
|
securityAttributes.nLength = sizeof(securityAttributes);
|
|
securityAttributes.bInheritHandle = FALSE;
|
|
securityAttributes.lpSecurityDescriptor = &securityDescriptor;
|
|
pSA = &securityAttributes;
|
|
}
|
|
}
|
|
|
|
// Create the registry semaphore.
|
|
Semaphore = CreateSemaphore(pSA, 1, 1, c_szSemRegistry);
|
|
|
|
if (pACL != NULL)
|
|
{
|
|
(HLOCAL)LocalFree(pACL);
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we successfully opened a handle, update the global g_hSemRegistry now
|
|
//
|
|
if (Semaphore) {
|
|
if (InterlockedCompareExchangePointer(&g_hSemRegistry, Semaphore, NULL) != NULL) {
|
|
CloseHandle(Semaphore);
|
|
}
|
|
return(TRUE);
|
|
} else {
|
|
return(FALSE);
|
|
}
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* TakeRegSemaphore
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
BOOLEAN TakeRegSemaphore(VOID)
|
|
{
|
|
if (g_hSemRegistry == NULL) {
|
|
if (!CreateRegSemaphore()) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
if (WaitForSingleObject(g_hSemRegistry, SEMAPHORE_TIMEOUT) != WAIT_OBJECT_0) {
|
|
ReleaseSemaphore(g_hSemRegistry, 1, NULL);
|
|
DebugPrint("WaitForSingleObject, failed");
|
|
SetLastError(ERROR_INVALID_ACCESS);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* ReadPowerValueOptional
|
|
*
|
|
* DESCRIPTION:
|
|
* Value may not exist.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
BOOLEAN ReadPowerValueOptional(
|
|
HKEY hKey,
|
|
LPTSTR lpszPath,
|
|
LPTSTR lpszValueName,
|
|
LPTSTR lpszValue,
|
|
LPDWORD lpdwSize
|
|
)
|
|
{
|
|
HKEY hKeyPath;
|
|
BOOLEAN bRet = FALSE;
|
|
DWORD dwSize;
|
|
LONG lRet;
|
|
|
|
if ((lRet = RegOpenKey(hKey,
|
|
lpszPath,
|
|
&hKeyPath)) != ERROR_SUCCESS) {
|
|
goto RPVO_exit;
|
|
}
|
|
|
|
if ((lRet = RegQueryValueEx(hKeyPath,
|
|
lpszValueName,
|
|
NULL,
|
|
NULL,
|
|
(PBYTE) lpszValue,
|
|
lpdwSize)) == ERROR_SUCCESS) {
|
|
bRet = TRUE;
|
|
}
|
|
|
|
RegCloseKey(hKeyPath);
|
|
|
|
RPVO_exit:
|
|
return bRet;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* ReadPowerIntOptional
|
|
*
|
|
* DESCRIPTION:
|
|
* Integer value may not exist.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
BOOLEAN ReadPowerIntOptional(
|
|
HKEY hKey,
|
|
LPTSTR lpszPath,
|
|
LPTSTR lpszValueName,
|
|
PINT piVal
|
|
)
|
|
{
|
|
HKEY hKeyPath;
|
|
BOOLEAN bRet = FALSE;
|
|
DWORD dwSize;
|
|
TCHAR szNum[NUM_DEC_DIGITS];
|
|
LONG lRet;
|
|
|
|
if ((lRet = RegOpenKey(hKey,
|
|
lpszPath,
|
|
&hKeyPath)) != ERROR_SUCCESS) {
|
|
goto RPVO_exit;
|
|
}
|
|
|
|
dwSize = sizeof(szNum);
|
|
if ((lRet = RegQueryValueEx(hKeyPath,
|
|
lpszValueName,
|
|
NULL,
|
|
NULL,
|
|
(PBYTE) szNum,
|
|
&dwSize)) == ERROR_SUCCESS) {
|
|
if (MyStrToInt(szNum, piVal)) {
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKeyPath);
|
|
|
|
RPVO_exit:
|
|
return bRet;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* CreatePowerValue
|
|
*
|
|
* DESCRIPTION:
|
|
* Value may not exist.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
BOOLEAN CreatePowerValue(
|
|
HKEY hKey,
|
|
LPCTSTR lpszPath,
|
|
LPCTSTR lpszValueName,
|
|
LPCTSTR lpszValue
|
|
)
|
|
{
|
|
DWORD dwDisposition, dwDescSize;
|
|
HKEY hKeyPath;
|
|
BOOLEAN bRet = FALSE;
|
|
DWORD dwSize;
|
|
LONG lRet;
|
|
|
|
// Wait on/take the registry semaphore.
|
|
if (!TakeRegSemaphore()) // Will SetLastError
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ((lRet = RegCreateKeyEx(hKey,
|
|
lpszPath,
|
|
0,
|
|
TEXT(""),
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE,
|
|
NULL,
|
|
&hKeyPath,
|
|
&dwDisposition)) == ERROR_SUCCESS)
|
|
{
|
|
if (lpszValue)
|
|
{
|
|
dwSize = (lstrlen(lpszValue) + 1) * sizeof(TCHAR);
|
|
if ((lRet = RegSetValueEx(hKeyPath,
|
|
lpszValueName,
|
|
0,
|
|
REG_SZ,
|
|
(PBYTE) lpszValue,
|
|
dwSize)) == ERROR_SUCCESS)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lRet = ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
RegCloseKey(hKeyPath);
|
|
}
|
|
|
|
if (!bRet)
|
|
{
|
|
SetLastError(lRet);
|
|
}
|
|
|
|
ReleaseSemaphore(g_hSemRegistry, 1, NULL);
|
|
return bRet;
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* ReadWritePowerValue
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
BOOLEAN ReadWritePowerValue(
|
|
HKEY hKey,
|
|
LPTSTR lpszPath,
|
|
LPTSTR lpszValueName,
|
|
LPTSTR lpszValue,
|
|
LPDWORD lpdwSize,
|
|
BOOLEAN bWrite,
|
|
BOOLEAN bTakeSemaphore
|
|
)
|
|
{
|
|
// This function will set the Last Error correctly on failure
|
|
HKEY hKeyPath;
|
|
BOOLEAN bRet = FALSE;
|
|
DWORD dwSize;
|
|
LONG lRet;
|
|
|
|
if ((lRet = RegOpenKey(hKey,
|
|
lpszPath,
|
|
&hKeyPath)) != ERROR_SUCCESS)
|
|
{
|
|
goto RWPV_exit;
|
|
}
|
|
|
|
// Wait on/take the registry semaphore.
|
|
if (bTakeSemaphore)
|
|
{
|
|
if (!TakeRegSemaphore()) // Will Set last error
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (bWrite)
|
|
{
|
|
// Write current case.
|
|
if (lpszValue)
|
|
{
|
|
dwSize = (lstrlen(lpszValue) + 1) * sizeof(TCHAR);
|
|
if ((lRet = RegSetValueEx(hKeyPath,
|
|
lpszValueName,
|
|
0,
|
|
REG_SZ,
|
|
(PBYTE) lpszValue,
|
|
dwSize)) == ERROR_SUCCESS)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lRet = ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Read current case.
|
|
if ((lRet = RegQueryValueEx(hKeyPath,
|
|
lpszValueName,
|
|
NULL,
|
|
NULL,
|
|
(PBYTE) lpszValue,
|
|
lpdwSize)) == ERROR_SUCCESS)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
if (bTakeSemaphore)
|
|
{
|
|
ReleaseSemaphore(g_hSemRegistry, 1, NULL);
|
|
}
|
|
RegCloseKey(hKeyPath);
|
|
|
|
RWPV_exit:
|
|
if (!bRet)
|
|
{
|
|
if (lRet == ERROR_SUCCESS)
|
|
{
|
|
lRet = GetLastError();
|
|
}
|
|
|
|
SetLastError(lRet);
|
|
|
|
// Access denied is a valid result.
|
|
if (lRet != ERROR_ACCESS_DENIED)
|
|
{
|
|
DebugPrint("ReadWritePowerValue, failed, lpszValueName: %s, LastError: 0x%08X", lpszValueName, lRet);
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* ReadPwrPolicyEx
|
|
*
|
|
* DESCRIPTION:
|
|
* Supports ReadPwrScheme and ReadGlobalPwrPolicy
|
|
*
|
|
* PARAMETERS:
|
|
* lpdwDescSize - Pointer to size of optional description buffer.
|
|
* lpszDesc - Optional description buffer.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
DWORD ReadPwrPolicyEx2(
|
|
LPTSTR lpszUserKeyName,
|
|
LPTSTR lpszMachineKeyName,
|
|
LPTSTR lpszSchemeName,
|
|
LPTSTR lpszDesc,
|
|
LPDWORD lpdwDescSize,
|
|
LPVOID lpvUser,
|
|
DWORD dwcbUserSize,
|
|
LPVOID lpvMachine,
|
|
DWORD dwcbMachineSize
|
|
)
|
|
{
|
|
HKEY hKeyUser, hKeyMachine;
|
|
DWORD dwType, dwSize;
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
BOOLEAN bRet = FALSE;
|
|
|
|
if ((!lpszUserKeyName || !lpszMachineKeyName) ||
|
|
(!lpszSchemeName || !lpvUser || !lpvMachine) ||
|
|
(!lpdwDescSize && lpszDesc) ||
|
|
(lpdwDescSize && !lpszDesc))
|
|
{
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
// Wait on/take the registry semaphore.
|
|
if (!TakeRegSemaphore()) // Will Set Last Error
|
|
{
|
|
return GetLastError();
|
|
}
|
|
|
|
dwError = OpenPathKeys(lpszUserKeyName, lpszMachineKeyName, lpszSchemeName, &hKeyUser, &hKeyMachine, TRUE, KEY_READ);
|
|
if (ERROR_SUCCESS != dwError)
|
|
{
|
|
ReleaseSemaphore(g_hSemRegistry, 1, NULL);
|
|
return dwError;
|
|
}
|
|
|
|
dwSize = dwcbUserSize;
|
|
dwError = RegQueryValueEx(hKeyUser,
|
|
TEXT("Policies"),
|
|
NULL,
|
|
&dwType,
|
|
(PBYTE) lpvUser,
|
|
&dwSize);
|
|
|
|
if (dwError == ERROR_SUCCESS)
|
|
{
|
|
if (dwType == REG_BINARY)
|
|
{
|
|
dwSize = dwcbMachineSize;
|
|
dwError = RegQueryValueEx(hKeyMachine,
|
|
TEXT("Policies"),
|
|
NULL,
|
|
&dwType,
|
|
(PBYTE) lpvMachine,
|
|
&dwSize);
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_INVALID_DATATYPE;
|
|
}
|
|
}
|
|
|
|
if (dwError == ERROR_SUCCESS)
|
|
{
|
|
if (dwType == REG_BINARY)
|
|
{
|
|
if (lpdwDescSize)
|
|
{
|
|
dwError = RegQueryValueEx(hKeyUser, TEXT("Description"), NULL, &dwType, (PBYTE) lpszDesc, lpdwDescSize);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_INVALID_DATATYPE;
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKeyUser);
|
|
RegCloseKey(hKeyMachine);
|
|
ReleaseSemaphore(g_hSemRegistry, 1, NULL);
|
|
}
|
|
|
|
if (ERROR_SUCCESS != dwError)
|
|
{
|
|
DebugPrint("ReadPwrPolicyEx, failed, LastError: 0x%08X", dwError);
|
|
DebugPrint(" lpszUserKeyName: %s, lpszSchemeName: %s", lpszUserKeyName, lpszSchemeName);
|
|
SetLastError(dwError);
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
DWORD
|
|
ReadProcessorPwrPolicy(
|
|
LPTSTR lpszMachineKeyName,
|
|
LPTSTR lpszSchemeName,
|
|
LPVOID lpvMachineProcessor,
|
|
DWORD dwcbMachineProcessorSize
|
|
)
|
|
{
|
|
HKEY hKeyMachine = NULL;
|
|
HKEY hKeyPolicy = NULL;
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
DWORD dwDisposition, dwSize, dwType;
|
|
|
|
if (!lpszMachineKeyName || !lpvMachineProcessor) {
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
goto ReadProcessorPwrPolicyEnd;
|
|
}
|
|
|
|
// Wait on/take the registry semaphore.
|
|
if (!TakeRegSemaphore()) // Will Set Last Error
|
|
{
|
|
return GetLastError();
|
|
}
|
|
|
|
dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszMachineKeyName, 0, KEY_READ, &hKeyMachine);
|
|
if (ERROR_SUCCESS != dwError) goto ReadProcessorPwrPolicyExit;
|
|
|
|
dwError = RegCreateKeyEx(hKeyMachine, lpszSchemeName, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hKeyPolicy, &dwDisposition);
|
|
if (ERROR_SUCCESS != dwError) goto ReadProcessorPwrPolicyExit;
|
|
|
|
dwSize = dwcbMachineProcessorSize;
|
|
dwError = RegQueryValueEx(hKeyPolicy,
|
|
TEXT("Policies"),
|
|
NULL,
|
|
&dwType,
|
|
(PBYTE) lpvMachineProcessor,
|
|
&dwSize);
|
|
|
|
if (REG_BINARY != dwType) {
|
|
dwError = ERROR_INVALID_DATATYPE;
|
|
}
|
|
|
|
ReadProcessorPwrPolicyExit:
|
|
|
|
if (hKeyPolicy) RegCloseKey(hKeyPolicy);
|
|
if (hKeyMachine) RegCloseKey(hKeyMachine);
|
|
ReleaseSemaphore(g_hSemRegistry, 1, NULL);
|
|
|
|
ReadProcessorPwrPolicyEnd:
|
|
|
|
if (ERROR_SUCCESS != dwError)
|
|
{
|
|
DebugPrint("ReadProcessorPwrPolicy, failed, LastError: 0x%08X", dwError);
|
|
DebugPrint(" lpszMachineKeyName: %s, lpszSchemeName: %s", lpszMachineKeyName, lpszSchemeName);
|
|
SetLastError(dwError);
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
DWORD
|
|
WriteProcessorPwrPolicy(
|
|
LPTSTR lpszMachineKeyName,
|
|
LPTSTR lpszSchemeName,
|
|
LPVOID lpvMachineProcessor,
|
|
DWORD dwcbMachineProcessorSize
|
|
)
|
|
{
|
|
HKEY hKeyMachine = NULL;
|
|
HKEY hKeyPolicy = NULL;
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
DWORD dwDisposition;
|
|
|
|
if (!lpszMachineKeyName || !lpvMachineProcessor) {
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
goto WriteProcessorPwrPolicyEnd;
|
|
}
|
|
|
|
// Wait on/take the registry semaphore.
|
|
if (!TakeRegSemaphore()) // Will Set Last Error
|
|
{
|
|
return GetLastError();
|
|
}
|
|
|
|
dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszMachineKeyName, 0, KEY_WRITE, &hKeyMachine);
|
|
if (ERROR_SUCCESS != dwError) goto WriteProcessorPwrPolicyExit;
|
|
|
|
dwError = RegCreateKeyEx(hKeyMachine, lpszSchemeName, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKeyPolicy, &dwDisposition);
|
|
if (ERROR_SUCCESS != dwError) goto WriteProcessorPwrPolicyExit;
|
|
|
|
dwError = RegSetValueEx(hKeyPolicy,
|
|
TEXT("Policies"),
|
|
0,
|
|
REG_BINARY,
|
|
(PBYTE) lpvMachineProcessor,
|
|
dwcbMachineProcessorSize);
|
|
|
|
WriteProcessorPwrPolicyExit:
|
|
|
|
if (hKeyPolicy) RegCloseKey(hKeyPolicy);
|
|
if (hKeyMachine) RegCloseKey(hKeyMachine);
|
|
ReleaseSemaphore(g_hSemRegistry, 1, NULL);
|
|
|
|
WriteProcessorPwrPolicyEnd:
|
|
|
|
if (ERROR_SUCCESS != dwError)
|
|
{
|
|
DebugPrint("WriteProcessorPwrPolicy, failed, LastError: 0x%08X", dwError);
|
|
DebugPrint(" lpszMachineKeyName: %s, lpszSchemeName: %s", lpszMachineKeyName, lpszSchemeName);
|
|
SetLastError(dwError);
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* WritePwrPolicyEx
|
|
*
|
|
* DESCRIPTION:
|
|
* Supports WritePwrScheme and
|
|
* WriteGlobalPwrPolicy
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
BOOLEAN WritePwrPolicyEx(
|
|
LPTSTR lpszUserKeyName,
|
|
LPTSTR lpszMachineKeyName,
|
|
PUINT puiID,
|
|
LPTSTR lpszName,
|
|
LPTSTR lpszDescription,
|
|
LPVOID lpvUser,
|
|
DWORD dwcbUserSize,
|
|
LPVOID lpvMachine,
|
|
DWORD dwcbMachineSize
|
|
)
|
|
{
|
|
// The function will set the last error if it fails.
|
|
HKEY hKeyUser, hKeyMachine;
|
|
LONG lRet = ERROR_SUCCESS;
|
|
DWORD dwDisposition, dwSize;
|
|
TCHAR szNum[NUM_DEC_DIGITS];
|
|
LPTSTR lpszKeyName;
|
|
|
|
if ((!lpszUserKeyName || !lpszMachineKeyName || !lpvUser || !lpvMachine) || (!puiID && !lpszName))
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
lRet = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
// If a scheme ID was passed
|
|
if (puiID)
|
|
{
|
|
if (*puiID == NEWSCHEME)
|
|
{
|
|
*puiID = ++g_uiLastID;
|
|
wsprintf(szNum, TEXT("%d"), *puiID);
|
|
|
|
// This ReadWritePowerValue will SetLastError
|
|
if (!ReadWritePowerValue(HKEY_LOCAL_MACHINE,
|
|
c_szREGSTR_PATH_MACHINE_POWERCFG,
|
|
c_szREGSTR_VAL_LASTID,
|
|
szNum, &dwSize, TRUE, TRUE))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wsprintf(szNum, TEXT("%d"), *puiID);
|
|
}
|
|
lpszKeyName = szNum;
|
|
}
|
|
else
|
|
{
|
|
lpszKeyName = lpszName;
|
|
}
|
|
|
|
// Wait on/take the registry semaphore.
|
|
if (!TakeRegSemaphore()) // Will set last error
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
lRet = OpenPathKeys(lpszUserKeyName, lpszMachineKeyName, lpszKeyName, &hKeyUser, &hKeyMachine, FALSE, KEY_WRITE);
|
|
if (ERROR_SUCCESS != lRet)
|
|
{
|
|
ReleaseSemaphore(g_hSemRegistry, 1, FALSE);
|
|
SetLastError(lRet);
|
|
return FALSE;
|
|
}
|
|
|
|
// Write the binary policies data
|
|
if ((lRet = RegSetValueEx(hKeyUser,
|
|
TEXT("Policies"),
|
|
0,
|
|
REG_BINARY,
|
|
(PBYTE) lpvUser,
|
|
dwcbUserSize)) == ERROR_SUCCESS)
|
|
{
|
|
// Write the binary policies data
|
|
if ((lRet = RegSetValueEx(hKeyMachine,
|
|
TEXT("Policies"),
|
|
0,
|
|
REG_BINARY,
|
|
(PBYTE) lpvMachine,
|
|
dwcbMachineSize)) == ERROR_SUCCESS)
|
|
{
|
|
// Write the name text if an ID was provided.
|
|
if (lpszName && puiID)
|
|
{
|
|
dwSize = (lstrlen(lpszName) + 1) * sizeof(TCHAR);
|
|
lRet = RegSetValueEx(hKeyUser, TEXT("Name"), 0, REG_SZ, (PBYTE) lpszName, dwSize);
|
|
}
|
|
|
|
// Write the description text.
|
|
if (lpszDescription && (lRet == ERROR_SUCCESS))
|
|
{
|
|
dwSize = (lstrlen(lpszDescription) + 1) * sizeof(TCHAR);
|
|
lRet = RegSetValueEx(hKeyUser, TEXT("Description"), 0, REG_SZ, (PBYTE) lpszDescription, dwSize);
|
|
}
|
|
}
|
|
}
|
|
RegCloseKey(hKeyUser);
|
|
RegCloseKey(hKeyMachine);
|
|
ReleaseSemaphore(g_hSemRegistry, 1, NULL);
|
|
}
|
|
|
|
if (lRet != ERROR_SUCCESS)
|
|
{
|
|
DebugPrint("WritePwrPolicyEx, failed, LastError: 0x%08X", lRet);
|
|
DebugPrint(" lpszUserKeyName: %s, lpszKeyName: %s", lpszUserKeyName, lpszKeyName);
|
|
|
|
SetLastError(lRet);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|