From: Robert Lippmann robert.lippmann.development@gmail.com
--- dlls/powrprof/Makefile.in | 2 +- dlls/powrprof/powersetting.c | 130 +++++++++++++++++++++++++++++++++-- 2 files changed, 125 insertions(+), 7 deletions(-)
diff --git a/dlls/powrprof/Makefile.in b/dlls/powrprof/Makefile.in index 3d606f88574..c165b76d54c 100644 --- a/dlls/powrprof/Makefile.in +++ b/dlls/powrprof/Makefile.in @@ -1,6 +1,6 @@ MODULE = powrprof.dll IMPORTLIB = powrprof -IMPORTS = advapi32 +IMPORTS = advapi32 kernelbase ole32
SOURCES = \ powrprof.c \ diff --git a/dlls/powrprof/powersetting.c b/dlls/powrprof/powersetting.c index dd6c8e2f786..2558c74f71b 100644 --- a/dlls/powrprof/powersetting.c +++ b/dlls/powrprof/powersetting.c @@ -16,23 +16,141 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
- - +#include <string.h> +#include <stdarg.h> +#include <wchar.h> +#include <initguid.h> +#include "windows.h" +#include "objbase.h" #include "powersetting.h" -#include "winerror.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(powrprof);
+ +static const char active_power_scheme_key[] = + "SYSTEM\CurrentControlSet\Control\Power\User\PowerSchemes"; +static const char active_power_scheme_value[] = "ActivePowerScheme"; + +/* Windows stores these GUIDs in the registry without braces for some reason */ +static DWORD guid_to_registry(const GUID * const pguid, char *guid_str, int guid_str_size) +{ + int ret; + + ret = snprintf(guid_str, guid_str_size, + "%08lX-%04X-%04X-%04X-%012llX", + pguid->Data1, pguid->Data2, + pguid->Data3, + (pguid->Data4[0] << 8) | pguid->Data4[1], + ((ULONGLONG)pguid->Data4[2] << 40) | + ((ULONGLONG)pguid->Data4[3] << 32) | + ((ULONGLONG)pguid->Data4[4] << 24) | + ((ULONGLONG)pguid->Data4[5] << 16) | + ((ULONGLONG)pguid->Data4[6] << 8) | + (ULONGLONG)pguid->Data4[7]); + if(ret >= guid_str_size) + { + ERR("Buffer overflow, expected %u bytes, got %u\n", guid_str_size, ret); + SetLastError(ERROR_BUFFER_OVERFLOW); + return ERROR_BUFFER_OVERFLOW; + } + return ERROR_SUCCESS; +} +static DWORD get_or_create_active_power_scheme_key(HKEY *hkey) +{ + DWORD key_disposition, ret; + char default_scheme[39]; + + ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, active_power_scheme_key, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, hkey, &key_disposition); + if (ret != ERROR_SUCCESS) + { + return ret; + } + if (key_disposition != REG_CREATED_NEW_KEY) + { + return ERROR_SUCCESS; + } + /* Create the default power profile value */ + ret = guid_to_registry(&GUID_TYPICAL_POWER_SAVINGS, default_scheme, sizeof(default_scheme)); + if(ret != ERROR_SUCCESS) + { + return ret; + } + TRACE("Creating default power profile value %s\n", debugstr_a(active_power_scheme_value)); + return(RegSetValueExA(*hkey, active_power_scheme_value, 0, REG_SZ, (const BYTE *)default_scheme, strlen(default_scheme) + 1)); +} + DWORD WINAPI PowerGetActiveScheme(HKEY UserRootPowerKey, GUID **polguid) { - FIXME("(%p,%p) stub!\n", UserRootPowerKey, polguid); - return ERROR_CALL_NOT_IMPLEMENTED; + DWORD ret; + HKEY hkey; + char scheme_guid[39]; + WCHAR scheme_guid_w[39]; + DWORD scheme_guid_size = sizeof(scheme_guid); + + ret = get_or_create_active_power_scheme_key(&hkey); + if(ret != ERROR_SUCCESS) + { + return ret; + } + /* Windows SDK docs say this can be freed with LocalFree() */ + *polguid = LocalAlloc(LPTR, sizeof(GUID)); + if(*polguid == NULL) + { + return GetLastError(); + } + ret = RegQueryValueExA(hkey, active_power_scheme_value, NULL, NULL, (LPBYTE)scheme_guid, &scheme_guid_size); + if(ret != ERROR_SUCCESS) + { + return ret; + } + snprintf(scheme_guid, sizeof(scheme_guid),"{%s}", scheme_guid); + /* Windows SDK docs say this can be freed with LocalFree() */ + *polguid = LocalAlloc(LPTR, sizeof(GUID)); + if(*polguid == NULL) + { + return GetLastError(); + } + mbstowcs(scheme_guid_w, scheme_guid, sizeof(scheme_guid_w)); + ret = CLSIDFromString(scheme_guid_w, *polguid); + if(ret != S_OK) + { + return ERROR_INVALID_PARAMETER; + } + RegCloseKey(hkey); + return ERROR_SUCCESS; }
DWORD WINAPI PowerSetActiveScheme(HKEY UserRootPowerKey, GUID *polguid) { - FIXME("(%p,%s) stub!\n", UserRootPowerKey, wine_dbgstr_guid(polguid)); + DWORD ret; + HKEY hkey; + char scheme_guid[39]; + const DWORD guid_size = sizeof(scheme_guid); + + FIXME("Should use EnumeratePowerSettings to validate passed in GUID\n"); + if(!(IsEqualGUID(polguid, &GUID_MAX_POWER_SAVINGS)|| + IsEqualGUID(polguid, &GUID_MIN_POWER_SAVINGS)|| + IsEqualGUID(polguid, &GUID_TYPICAL_POWER_SAVINGS))) + { + return(ERROR_INVALID_PARAMETER); + } + ret = get_or_create_active_power_scheme_key(&hkey); + if(ret != ERROR_SUCCESS) + { + return ret; + } + ret = guid_to_registry(polguid, scheme_guid, guid_size); + if(ret != ERROR_SUCCESS) + { + return ret; + } + ret=RegSetValueExA(hkey, active_power_scheme_value, 0, REG_SZ, (const BYTE *)scheme_guid, strlen(scheme_guid) + 1); + if(ret != ERROR_SUCCESS) + { + return ret; + } + RegCloseKey(hkey); return ERROR_SUCCESS; }
\ No newline at end of file