xref: /reactos/dll/win32/powrprof/powrprof.c (revision fd25e2dc)
1 /*
2  * Copyright (C) 2005 Benjamin Cutler
3  * Copyright (C) 2008 Dmitry Chapyshev
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19 
20 
21 #include <stdarg.h>
22 
23 #define WIN32_NO_STATUS
24 #include <windef.h>
25 #include <winbase.h>
26 #include <winreg.h>
27 #define NTOS_MODE_USER
28 #include <ndk/pofuncs.h>
29 #include <ndk/rtlfuncs.h>
30 #include <ndk/setypes.h>
31 #include <powrprof.h>
32 #include <wine/debug.h>
33 #include <wine/unicode.h>
34 
35 WINE_DEFAULT_DEBUG_CHANNEL(powrprof);
36 
37 
38 static const WCHAR szPowerCfgSubKey[] =
39     L"Software\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg";
40 static const WCHAR szUserPowerConfigSubKey[] =
41     L"Control Panel\\PowerCfg";
42 static const WCHAR szCurrentPowerPolicies[] =
43     L"CurrentPowerPolicy";
44 static const WCHAR szPolicies[] = L"Policies";
45 static const WCHAR szName[] = L"Name";
46 static const WCHAR szDescription[] = L"Description";
47 static const WCHAR szSemaphoreName[] = L"PowerProfileRegistrySemaphore";
48 static const WCHAR szDiskMax[] = L"DiskSpindownMax";
49 static const WCHAR szDiskMin[] = L"DiskSpindownMin";
50 static const WCHAR szLastID[] = L"LastID";
51 
52 UINT g_LastID = (UINT)-1;
53 
54 BOOLEAN WINAPI WritePwrPolicy(PUINT puiID, PPOWER_POLICY pPowerPolicy);
55 
56 HANDLE PPRegSemaphore = NULL;
57 
58 NTSTATUS WINAPI
CallNtPowerInformation(POWER_INFORMATION_LEVEL InformationLevel,PVOID lpInputBuffer,ULONG nInputBufferSize,PVOID lpOutputBuffer,ULONG nOutputBufferSize)59 CallNtPowerInformation(POWER_INFORMATION_LEVEL InformationLevel,
60                        PVOID lpInputBuffer,
61                        ULONG nInputBufferSize,
62                        PVOID lpOutputBuffer,
63                        ULONG nOutputBufferSize)
64 {
65     BOOLEAN old;
66 
67 	//Lohnegrim: In order to get the right results, we have to adjust our Privileges
68     RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &old);
69     RtlAdjustPrivilege(SE_CREATE_PAGEFILE_PRIVILEGE, TRUE, FALSE, &old);
70 
71     return NtPowerInformation(InformationLevel,
72                               lpInputBuffer,
73                               nInputBufferSize,
74                               lpOutputBuffer,
75                               nOutputBufferSize);
76 }
77 
78 BOOLEAN WINAPI
CanUserWritePwrScheme(VOID)79 CanUserWritePwrScheme(VOID)
80 {
81     HKEY hKey = NULL;
82     LONG Ret;
83 
84     TRACE("()\n");
85 
86     Ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPowerCfgSubKey, 0, KEY_READ | KEY_WRITE, &hKey);
87     if (Ret != ERROR_SUCCESS)
88     {
89         TRACE("RegOpenKeyEx failed: %d\n", Ret);
90         SetLastError(Ret);
91         return FALSE;
92     }
93 
94     RegCloseKey(hKey);
95     return TRUE;
96 }
97 
98 BOOLEAN WINAPI
DeletePwrScheme(UINT uiIndex)99 DeletePwrScheme(UINT uiIndex)
100 {
101     WCHAR Buf[MAX_PATH];
102     UINT Current;
103     LONG Err;
104 
105     swprintf(Buf, L"Control Panel\\PowerCfg\\PowerPolicies\\%d", uiIndex);
106 
107     if (!GetActivePwrScheme(&Current))
108         return FALSE;
109 
110     if (Current == uiIndex)
111     {
112         SetLastError(ERROR_ACCESS_DENIED);
113         return FALSE;
114     }
115 
116     Err = RegDeleteKey(HKEY_CURRENT_USER, (LPCTSTR)Buf);
117     if (Err != ERROR_SUCCESS)
118     {
119         TRACE("RegDeleteKey failed: %d\n", Err);
120         SetLastError(Err);
121         return FALSE;
122     }
123 
124     return TRUE;
125 }
126 
127 static BOOLEAN
POWRPROF_GetUserPowerPolicy(LPWSTR szNum,PUSER_POWER_POLICY puserPwrPolicy,DWORD cchName,LPWSTR szName,DWORD cchDesc,LPWSTR szDesc)128 POWRPROF_GetUserPowerPolicy(LPWSTR szNum,
129                             PUSER_POWER_POLICY puserPwrPolicy,
130                             DWORD cchName, LPWSTR szName,
131                             DWORD cchDesc, LPWSTR szDesc)
132 {
133     HKEY hSubKey = NULL;
134     DWORD dwSize;
135     LONG Err;
136     WCHAR szPath[MAX_PATH];
137     BOOL bRet = FALSE;
138 
139     swprintf(szPath, L"Control Panel\\PowerCfg\\PowerPolicies\\%s", szNum);
140 
141     Err = RegOpenKeyExW(HKEY_CURRENT_USER, szPath, 0, KEY_READ, &hSubKey);
142     if (Err != ERROR_SUCCESS)
143     {
144         ERR("RegOpenKeyExW failed: %d\n", Err);
145         SetLastError(Err);
146         return FALSE;
147     }
148 
149     dwSize = cchName * sizeof(WCHAR);
150     Err = RegQueryValueExW(hSubKey, L"Name", NULL, NULL, (LPBYTE)szName, &dwSize);
151     if (Err != ERROR_SUCCESS)
152     {
153         ERR("RegQueryValueExW failed: %d\n", Err);
154         SetLastError(Err);
155         goto cleanup;
156     }
157 
158     dwSize = cchDesc * sizeof(WCHAR);
159     Err = RegQueryValueExW(hSubKey, L"Description", NULL, NULL, (LPBYTE)szDesc, &dwSize);
160     if (Err != ERROR_SUCCESS)
161     {
162         ERR("RegQueryValueExW failed: %d\n", Err);
163         SetLastError(Err);
164         goto cleanup;
165     }
166 
167     dwSize = sizeof(USER_POWER_POLICY);
168     Err = RegQueryValueExW(hSubKey, L"Policies", NULL, NULL, (LPBYTE)puserPwrPolicy, &dwSize);
169     if (Err != ERROR_SUCCESS)
170     {
171         ERR("RegQueryValueExW failed: %d\n", Err);
172         SetLastError(Err);
173         goto cleanup;
174     }
175 
176     bRet = TRUE;
177 
178 cleanup:
179     RegCloseKey(hSubKey);
180 
181     return bRet;
182 }
183 
184 static BOOLEAN
POWRPROF_GetMachinePowerPolicy(LPWSTR szNum,PMACHINE_POWER_POLICY pmachinePwrPolicy)185 POWRPROF_GetMachinePowerPolicy(LPWSTR szNum, PMACHINE_POWER_POLICY pmachinePwrPolicy)
186 {
187     HKEY hKey;
188     LONG Err;
189     WCHAR szPath[MAX_PATH];
190     DWORD dwSize;
191 
192     swprintf(szPath, L"Software\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\PowerPolicies\\%s", szNum);
193 
194     Err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPath, 0, KEY_READ, &hKey);
195     if (Err != ERROR_SUCCESS)
196     {
197         ERR("RegOpenKeyExW failed: %d\n", Err);
198         SetLastError(Err);
199         return FALSE;
200     }
201 
202     dwSize = sizeof(MACHINE_POWER_POLICY);
203     Err = RegQueryValueExW(hKey, L"Policies", NULL, NULL, (LPBYTE)pmachinePwrPolicy, &dwSize);
204 
205     if (Err != ERROR_SUCCESS)
206     {
207         ERR("RegQueryValueExW failed: %d\n", Err);
208         SetLastError(Err);
209         RegCloseKey(hKey);
210         return FALSE;
211     }
212 
213     RegCloseKey(hKey);
214 
215     return TRUE;
216 }
217 
218 BOOLEAN WINAPI
EnumPwrSchemes(PWRSCHEMESENUMPROC lpfnPwrSchemesEnumProc,LPARAM lParam)219 EnumPwrSchemes(PWRSCHEMESENUMPROC lpfnPwrSchemesEnumProc,
220                LPARAM lParam)
221 {
222     HKEY hKey;
223     LONG Err;
224     DWORD dwSize, dwNameSize = MAX_PATH, dwDescSize = MAX_PATH, dwIndex = 0;
225     WCHAR szNum[3 + 1], szName[MAX_PATH], szDesc[MAX_PATH];
226     POWER_POLICY PwrPolicy;
227     USER_POWER_POLICY userPwrPolicy;
228     MACHINE_POWER_POLICY machinePwrPolicy;
229     BOOLEAN bRet = FALSE;
230 
231     if (!lpfnPwrSchemesEnumProc)
232     {
233         SetLastError(ERROR_INVALID_PARAMETER);
234         return FALSE;
235     }
236 
237     Err = RegOpenKeyExW(HKEY_CURRENT_USER, L"Control Panel\\PowerCfg\\PowerPolicies", 0, KEY_READ, &hKey);
238     if (Err != ERROR_SUCCESS)
239     {
240         ERR("RegOpenKeyW failed: %d\n", Err);
241         SetLastError(Err);
242         return FALSE;
243     }
244 
245     ReleaseSemaphore(PPRegSemaphore, 1, NULL);
246 
247     dwSize = sizeof(szNum) / sizeof(WCHAR);
248 
249     while (RegEnumKeyExW(hKey, dwIndex, szNum, &dwSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
250     {
251         if (!POWRPROF_GetUserPowerPolicy(szNum, &userPwrPolicy,
252                                          dwNameSize, szName,
253                                          dwDescSize, szDesc))
254         {
255             WARN("POWRPROF_GetUserPowerPolicy failed\n");
256             goto cleanup;
257         }
258 
259         if (!POWRPROF_GetMachinePowerPolicy(szNum, &machinePwrPolicy))
260         {
261             WARN("POWRPROF_GetMachinePowerPolicy failed\n");
262             goto cleanup;
263         }
264 
265         memcpy(&PwrPolicy.user, &userPwrPolicy, sizeof(USER_POWER_POLICY));
266         memcpy(&PwrPolicy.mach, &machinePwrPolicy, sizeof(MACHINE_POWER_POLICY));
267 
268         if (!lpfnPwrSchemesEnumProc(_wtoi(szNum), (wcslen(szName) + 1) * sizeof(WCHAR), szName, (wcslen(szDesc) + 1) * sizeof(WCHAR), szDesc, &PwrPolicy, lParam))
269             goto cleanup;
270         else
271             bRet = TRUE;
272 
273         dwSize = sizeof(szNum) / sizeof(WCHAR);
274         dwIndex++;
275     }
276 
277 cleanup:
278     RegCloseKey(hKey);
279     ReleaseSemaphore(PPRegSemaphore, 1, NULL);
280 
281     return bRet;
282 }
283 
284 BOOLEAN WINAPI
GetActivePwrScheme(PUINT puiID)285 GetActivePwrScheme(PUINT puiID)
286 {
287     HKEY hKey;
288     WCHAR szBuf[MAX_PATH];
289     DWORD dwSize;
290     LONG Err;
291 
292     TRACE("GetActivePwrScheme(%u)", puiID);
293 
294     Err = RegOpenKeyExW(HKEY_CURRENT_USER, L"Control Panel\\PowerCfg", 0, KEY_READ, &hKey);
295     if (Err != ERROR_SUCCESS)
296     {
297         ERR("RegOpenKey failed: %d\n", Err);
298         SetLastError(Err);
299         return FALSE;
300     }
301 
302     dwSize = sizeof(szBuf);
303     Err = RegQueryValueExW(hKey, L"CurrentPowerPolicy",
304                            NULL, NULL,
305                            (LPBYTE)&szBuf, &dwSize);
306     if (Err != ERROR_SUCCESS)
307     {
308         ERR("RegQueryValueEx failed: %d\n", Err);
309         RegCloseKey(hKey);
310         SetLastError(Err);
311         return FALSE;
312     }
313 
314     RegCloseKey(hKey);
315     *puiID = _wtoi(szBuf);
316 
317     return TRUE;
318 }
319 
320 BOOLEAN WINAPI
GetCurrentPowerPolicies(PGLOBAL_POWER_POLICY pGlobalPowerPolicy,PPOWER_POLICY pPowerPolicy)321 GetCurrentPowerPolicies(PGLOBAL_POWER_POLICY pGlobalPowerPolicy,
322                         PPOWER_POLICY pPowerPolicy)
323 {
324     /*
325     SYSTEM_POWER_POLICY ACPower, DCPower;
326 
327     FIXME("(%p, %p) stub!\n", pGlobalPowerPolicy, pPowerPolicy);
328 
329     NtPowerInformation(SystemPowerPolicyAc, 0, 0, &ACPower, sizeof(SYSTEM_POWER_POLICY));
330     NtPowerInformation(SystemPowerPolicyDc, 0, 0, &DCPower, sizeof(SYSTEM_POWER_POLICY));
331 
332     return FALSE;
333     */
334 /*
335    Lohnegrim: I don't know why this Function should call NtPowerInformation, because as far as I know,
336       it simply returns the GlobalPowerPolicy and the AktivPowerScheme!
337  */
338     UINT uiID;
339 
340     if (pGlobalPowerPolicy != NULL)
341     {
342         if (!ReadGlobalPwrPolicy(pGlobalPowerPolicy))
343             return FALSE;
344     }
345     if (pPowerPolicy != NULL)
346     {
347         if (!GetActivePwrScheme(&uiID))
348             return FALSE;
349 
350         if (!ReadPwrScheme(uiID, pPowerPolicy))
351             return FALSE;
352     }
353 
354     return TRUE;
355 }
356 
357 BOOLEAN WINAPI
GetPwrCapabilities(PSYSTEM_POWER_CAPABILITIES lpSystemPowerCapabilities)358 GetPwrCapabilities(PSYSTEM_POWER_CAPABILITIES lpSystemPowerCapabilities)
359 {
360     NTSTATUS Status;
361 
362     TRACE("(%p)\n", lpSystemPowerCapabilities);
363 
364     if (!lpSystemPowerCapabilities)
365     {
366         SetLastError(ERROR_INVALID_PARAMETER);
367         return FALSE;
368     }
369 
370     Status = NtPowerInformation(SystemPowerCapabilities, 0, 0, lpSystemPowerCapabilities, sizeof(SYSTEM_POWER_CAPABILITIES));
371     if(!NT_SUCCESS(Status))
372     {
373         SetLastError(RtlNtStatusToDosError(Status));
374         return FALSE;
375     }
376 
377     return TRUE;
378 }
379 
380 BOOLEAN WINAPI
GetPwrDiskSpindownRange(PUINT RangeMax,PUINT RangeMin)381 GetPwrDiskSpindownRange(PUINT RangeMax, PUINT RangeMin)
382 {
383     HKEY hKey;
384     BYTE lpValue[40];
385     LONG Ret;
386     DWORD cbValue = sizeof(lpValue);
387 
388     TRACE("(%p, %p)\n", RangeMax, RangeMin);
389 
390     if (RangeMax == NULL || RangeMin == NULL)
391     {
392         SetLastError(ERROR_INVALID_PARAMETER);
393         return FALSE;
394     }
395 
396     WaitForSingleObject(PPRegSemaphore, INFINITE);
397 
398     Ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPowerCfgSubKey, 0, KEY_READ, &hKey);
399     if (Ret != ERROR_SUCCESS)
400     {
401         TRACE("RegOpenKeyEx failed: %d\n", Ret);
402         TRACE("Using defaults: 3600, 3\n");
403         *RangeMax = 3600;
404         *RangeMin = 3;
405         ReleaseSemaphore(PPRegSemaphore, 1, NULL);
406         return TRUE;
407     }
408 
409     Ret = RegQueryValueExW(hKey, szDiskMax, 0, 0, lpValue, &cbValue);
410     if (Ret != ERROR_SUCCESS)
411     {
412         TRACE("Couldn't open DiskSpinDownMax: %d\n", Ret);
413         TRACE("Using default: 3600\n");
414         *RangeMax = 3600;
415     }
416     else
417     {
418         *RangeMax = _wtoi((LPCWSTR)lpValue);
419     }
420 
421     cbValue = sizeof(lpValue);
422 
423     Ret = RegQueryValueExW(hKey, szDiskMin, 0, 0, lpValue, &cbValue);
424     if (Ret != ERROR_SUCCESS)
425     {
426         TRACE("Couldn't open DiskSpinDownMin: %d\n", Ret);
427         TRACE("Using default: 3\n");
428         *RangeMin = 3;
429     }
430     else
431     {
432         *RangeMin = _wtoi((LPCWSTR)lpValue);
433     }
434 
435     RegCloseKey(hKey);
436 
437     ReleaseSemaphore(PPRegSemaphore, 1, NULL);
438 
439     return TRUE;
440 }
441 
442 BOOLEAN WINAPI
IsAdminOverrideActive(PADMINISTRATOR_POWER_POLICY p)443 IsAdminOverrideActive(PADMINISTRATOR_POWER_POLICY p)
444 {
445     FIXME("( %p) stub!\n", p);
446     return FALSE;
447 }
448 
449 BOOLEAN WINAPI
IsPwrHibernateAllowed(VOID)450 IsPwrHibernateAllowed(VOID)
451 {
452     SYSTEM_POWER_CAPABILITIES PowerCaps;
453     NTSTATUS Status;
454     BOOLEAN old;
455 
456     RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &old);
457 
458     Status = NtPowerInformation(SystemPowerCapabilities, NULL, 0, &PowerCaps, sizeof(PowerCaps));
459     if (!NT_SUCCESS(Status))
460     {
461         SetLastError(RtlNtStatusToDosError(Status));
462         return FALSE;
463     }
464 
465     return PowerCaps.SystemS4 && PowerCaps.HiberFilePresent; // IsHiberfilPresent();
466 }
467 
468 BOOLEAN WINAPI
IsPwrShutdownAllowed(VOID)469 IsPwrShutdownAllowed(VOID)
470 {
471     SYSTEM_POWER_CAPABILITIES PowerCaps;
472     NTSTATUS Status;
473     BOOLEAN old;
474 
475     RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &old);
476 
477     Status = NtPowerInformation(SystemPowerCapabilities, NULL, 0, &PowerCaps, sizeof(PowerCaps));
478     if (!NT_SUCCESS(Status))
479     {
480         SetLastError(RtlNtStatusToDosError(Status));
481         return FALSE;
482     }
483 
484     return PowerCaps.SystemS5;
485 }
486 
487 BOOLEAN WINAPI
IsPwrSuspendAllowed(VOID)488 IsPwrSuspendAllowed(VOID)
489 {
490     SYSTEM_POWER_CAPABILITIES PowerCaps;
491     NTSTATUS Status;
492     BOOLEAN old;
493 
494     RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &old);
495 
496     Status = NtPowerInformation(SystemPowerCapabilities, NULL, 0, &PowerCaps, sizeof(PowerCaps));
497     if (!NT_SUCCESS(Status))
498     {
499         SetLastError(RtlNtStatusToDosError(Status));
500         return FALSE;
501     }
502 
503     return PowerCaps.SystemS1 || PowerCaps.SystemS2 || PowerCaps.SystemS3;
504 }
505 
506 DWORD WINAPI
PowerGetActiveScheme(HKEY UserRootPowerKey,GUID ** polguid)507 PowerGetActiveScheme(HKEY UserRootPowerKey, GUID **polguid)
508 {
509    FIXME("(%p,%p) stub!\n", UserRootPowerKey, polguid);
510    return ERROR_CALL_NOT_IMPLEMENTED;
511 }
512 
513 DWORD WINAPI
PowerReadDCValue(HKEY RootPowerKey,const GUID * Scheme,const GUID * SubGroup,const GUID * PowerSettings,PULONG Type,PUCHAR Buffer,DWORD * BufferSize)514 PowerReadDCValue(HKEY RootPowerKey, const GUID *Scheme, const GUID *SubGroup, const GUID *PowerSettings, PULONG Type, PUCHAR Buffer, DWORD *BufferSize)
515 {
516    FIXME("(%p,%s,%s,%s,%p,%p,%p) stub!\n", RootPowerKey, debugstr_guid(Scheme), debugstr_guid(SubGroup), debugstr_guid(PowerSettings), Type, Buffer, BufferSize);
517    return ERROR_CALL_NOT_IMPLEMENTED;
518 }
519 
520 BOOLEAN WINAPI
ReadGlobalPwrPolicy(PGLOBAL_POWER_POLICY pGlobalPowerPolicy)521 ReadGlobalPwrPolicy(PGLOBAL_POWER_POLICY pGlobalPowerPolicy)
522 {
523     GLOBAL_MACHINE_POWER_POLICY glMachPwrPolicy;
524     GLOBAL_USER_POWER_POLICY glUserPwrPolicy;
525     HKEY hKey = NULL;
526     DWORD dwSize;
527     LONG Err;
528     BOOL bRet = FALSE;
529 
530     ReleaseSemaphore(PPRegSemaphore, 1, NULL);
531 
532     // Getting user global power policy
533     Err = RegOpenKeyExW(HKEY_CURRENT_USER, L"Control Panel\\PowerCfg\\GlobalPowerPolicy", 0, KEY_READ, &hKey);
534     if (Err != ERROR_SUCCESS)
535     {
536         ERR("RegOpenKeyW failed: %d\n", Err);
537         SetLastError(Err);
538         goto cleanup;
539     }
540 
541     dwSize = sizeof(glUserPwrPolicy);
542     Err = RegQueryValueExW(hKey, L"Policies", NULL, NULL, (LPBYTE)&glUserPwrPolicy, &dwSize);
543     if (Err != ERROR_SUCCESS)
544     {
545         ERR("RegQueryValueExW failed: %d\n", Err);
546         SetLastError(Err);
547         goto cleanup;
548     }
549 
550     RegCloseKey(hKey);
551 
552     // Getting machine global power policy
553     Err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\GlobalPowerPolicy", 0, KEY_READ, &hKey);
554     if (Err != ERROR_SUCCESS)
555     {
556         ERR("RegOpenKeyW failed: %d\n", Err);
557         SetLastError(Err);
558         goto cleanup;
559     }
560 
561     dwSize = sizeof(glMachPwrPolicy);
562     Err = RegQueryValueExW(hKey, L"Policies", NULL, NULL, (LPBYTE)&glMachPwrPolicy, &dwSize);
563     if (Err != ERROR_SUCCESS)
564     {
565         ERR("RegQueryValueExW failed: %d\n", Err);
566         SetLastError(Err);
567         goto cleanup;
568     }
569 
570     memcpy(&pGlobalPowerPolicy->user, &glUserPwrPolicy, sizeof(GLOBAL_USER_POWER_POLICY));
571     memcpy(&pGlobalPowerPolicy->mach, &glMachPwrPolicy, sizeof(GLOBAL_MACHINE_POWER_POLICY));
572     bRet = TRUE;
573 
574 cleanup:
575     if(hKey)
576         RegCloseKey(hKey);
577     ReleaseSemaphore(PPRegSemaphore, 1, NULL);
578 
579     return bRet;
580 }
581 
582 
583 BOOLEAN WINAPI
ReadProcessorPwrScheme(UINT uiID,PMACHINE_PROCESSOR_POWER_POLICY pMachineProcessorPowerPolicy)584 ReadProcessorPwrScheme(UINT uiID,
585                        PMACHINE_PROCESSOR_POWER_POLICY pMachineProcessorPowerPolicy)
586 {
587     HKEY hKey;
588     WCHAR szPath[MAX_PATH];
589     DWORD dwSize = sizeof(MACHINE_PROCESSOR_POWER_POLICY);
590 
591     swprintf(szPath, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\ProcessorPolicies\\%i", uiID);
592     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
593         return FALSE;
594 
595     if (RegQueryValueExW(hKey, szPolicies, NULL, 0, (LPBYTE)pMachineProcessorPowerPolicy, &dwSize) == ERROR_SUCCESS)
596     {
597         RegCloseKey(hKey);
598         return TRUE;
599     }
600 
601     RegCloseKey(hKey);
602     if (uiID != 0)
603         return ReadProcessorPwrScheme(0, pMachineProcessorPowerPolicy);
604 
605     return FALSE;
606 }
607 
608 
609 BOOLEAN WINAPI
ReadPwrScheme(UINT uiID,PPOWER_POLICY pPowerPolicy)610 ReadPwrScheme(UINT uiID,
611     PPOWER_POLICY pPowerPolicy)
612 {
613     USER_POWER_POLICY userPwrPolicy;
614     MACHINE_POWER_POLICY machinePwrPolicy;
615     WCHAR szNum[16]; // max number - 999
616 
617     ReleaseSemaphore(PPRegSemaphore, 1, NULL);
618 
619     swprintf(szNum, L"%d", uiID);
620 
621     if (!POWRPROF_GetUserPowerPolicy(szNum, &userPwrPolicy, 0, NULL, 0, NULL))
622     {
623         ReleaseSemaphore(PPRegSemaphore, 1, NULL);
624         return FALSE;
625     }
626 
627     if (!POWRPROF_GetMachinePowerPolicy(szNum, &machinePwrPolicy))
628     {
629         ReleaseSemaphore(PPRegSemaphore, 1, NULL);
630         return FALSE;
631     }
632 
633     memcpy(&pPowerPolicy->user, &userPwrPolicy, sizeof(userPwrPolicy));
634     memcpy(&pPowerPolicy->mach, &machinePwrPolicy, sizeof(machinePwrPolicy));
635 
636     ReleaseSemaphore(PPRegSemaphore, 1, NULL);
637 
638     return TRUE;
639 }
640 
641 BOOLEAN WINAPI
SetActivePwrScheme(UINT uiID,PGLOBAL_POWER_POLICY lpGlobalPowerPolicy,PPOWER_POLICY lpPowerPolicy)642 SetActivePwrScheme(UINT uiID,
643                    PGLOBAL_POWER_POLICY lpGlobalPowerPolicy,
644                    PPOWER_POLICY lpPowerPolicy)
645 {
646     POWER_POLICY tmp;
647     HKEY hKey;
648     WCHAR Buf[16];
649 
650     if (!ReadPwrScheme(uiID, &tmp))
651         return FALSE;
652 
653     if (RegOpenKeyEx(HKEY_CURRENT_USER, szUserPowerConfigSubKey, 0, KEY_WRITE, &hKey) != ERROR_SUCCESS)
654         return FALSE;
655 
656     swprintf(Buf, L"%i", uiID);
657 
658     if (RegSetValueExW(hKey, szCurrentPowerPolicies, 0, REG_SZ, (PBYTE)Buf, strlenW(Buf)*sizeof(WCHAR)) != ERROR_SUCCESS)
659     {
660         RegCloseKey(hKey);
661         return FALSE;
662     }
663     RegCloseKey(hKey);
664 
665     if (lpGlobalPowerPolicy != NULL || lpPowerPolicy != NULL)
666     {
667         if (!ValidatePowerPolicies(lpGlobalPowerPolicy, lpPowerPolicy))
668             return FALSE;
669 
670         if (lpGlobalPowerPolicy != NULL && !WriteGlobalPwrPolicy(lpGlobalPowerPolicy))
671             return FALSE;
672 
673         if (lpPowerPolicy != NULL && !WritePwrPolicy(&uiID,lpPowerPolicy))
674             return FALSE;
675     }
676 
677     return TRUE;
678 }
679 
680 BOOLEAN WINAPI
SetSuspendState(BOOLEAN Hibernate,BOOLEAN ForceCritical,BOOLEAN DisableWakeEvent)681 SetSuspendState(BOOLEAN Hibernate,
682                 BOOLEAN ForceCritical,
683                 BOOLEAN DisableWakeEvent)
684 {
685     FIXME("(%d, %d, %d) stub!\n", Hibernate, ForceCritical, DisableWakeEvent);
686     return TRUE;
687 }
688 
689 BOOLEAN WINAPI
WriteGlobalPwrPolicy(PGLOBAL_POWER_POLICY pGlobalPowerPolicy)690 WriteGlobalPwrPolicy(PGLOBAL_POWER_POLICY pGlobalPowerPolicy)
691 {
692     HKEY hKey;
693     GLOBAL_USER_POWER_POLICY gupp;
694     GLOBAL_MACHINE_POWER_POLICY gmpp;
695 
696     gupp = pGlobalPowerPolicy->user;
697     gmpp = pGlobalPowerPolicy->mach;
698 
699     if (RegOpenKeyEx(HKEY_CURRENT_USER,
700                     L"Control Panel\\PowerCfg\\GlobalPowerPolicy",
701                     0,
702                     KEY_WRITE,
703                     &hKey) != ERROR_SUCCESS)
704         return FALSE;
705 
706     if (RegSetValueExW(hKey, szPolicies, 0, REG_BINARY, (PBYTE)&gupp, sizeof(gupp)) != ERROR_SUCCESS)
707     {
708         RegCloseKey(hKey);
709         return FALSE;
710     }
711 
712     RegCloseKey(hKey);
713 
714     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
715                      L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\GlobalPowerPolicy",
716                      0,
717                      KEY_ALL_ACCESS,
718                      &hKey))
719         return FALSE;
720 
721     if (RegSetValueExW(hKey,szPolicies, 0, REG_BINARY, (PBYTE)&gmpp, sizeof(gmpp)) != ERROR_SUCCESS)
722     {
723         RegCloseKey(hKey);
724         return FALSE;
725     }
726 
727     RegCloseKey(hKey);
728     return TRUE;
729 }
730 
731 BOOLEAN WINAPI
WriteProcessorPwrScheme(UINT ID,PMACHINE_PROCESSOR_POWER_POLICY pMachineProcessorPowerPolicy)732 WriteProcessorPwrScheme(UINT ID,
733                         PMACHINE_PROCESSOR_POWER_POLICY pMachineProcessorPowerPolicy)
734 {
735     WCHAR Buf[MAX_PATH];
736     HKEY hKey;
737 
738     swprintf(Buf, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\ProcessorPolicies\\%i", ID);
739 
740     if (RegCreateKey(HKEY_LOCAL_MACHINE, Buf, &hKey) != ERROR_SUCCESS)
741         return FALSE;
742 
743     RegSetValueExW(hKey, szPolicies, 0, REG_BINARY, (PBYTE)pMachineProcessorPowerPolicy, sizeof(MACHINE_PROCESSOR_POWER_POLICY));
744     RegCloseKey(hKey);
745     return TRUE;
746 }
747 
748 static VOID
SetLastID(VOID)749 SetLastID(VOID)
750 {
751     WCHAR Buf[16];
752     HKEY hKey;
753 
754     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
755                     szPowerCfgSubKey,
756                     0,
757                     KEY_WRITE,
758                     &hKey) != ERROR_SUCCESS)
759         return;
760     swprintf(Buf, L"%i", g_LastID);
761     RegSetValueExW(hKey, szLastID, 0, REG_SZ, (PBYTE)Buf, strlenW(Buf)*sizeof(WCHAR));
762     RegCloseKey(hKey);
763 }
764 
765 BOOLEAN WINAPI
WritePwrScheme(PUINT puiID,LPWSTR lpszName,LPWSTR lpszDescription,PPOWER_POLICY pPowerPolicy)766 WritePwrScheme(PUINT puiID,
767                LPWSTR lpszName,
768                LPWSTR lpszDescription,
769                PPOWER_POLICY pPowerPolicy)
770 {
771     WCHAR Buf[MAX_PATH];
772     HKEY hKey;
773 
774     if (*puiID == -1)
775     {
776         g_LastID++;
777         *puiID = g_LastID;
778         SetLastID();
779     }
780 
781     swprintf(Buf, L"Control Panel\\PowerCfg\\PowerPolicies\\%i", *puiID);
782 
783     if (RegCreateKey(HKEY_CURRENT_USER, Buf, &hKey) != ERROR_SUCCESS)
784         return FALSE;
785 
786     RegSetValueExW(hKey, szName, 0, REG_SZ, (PBYTE)lpszName, strlenW(lpszName)*sizeof(WCHAR));
787     RegSetValueExW(hKey, szDescription, 0, REG_SZ, (PBYTE)lpszDescription, strlenW(lpszDescription)*sizeof(WCHAR));
788     RegCloseKey(hKey);
789     return WritePwrPolicy(puiID, pPowerPolicy);
790 }
791 
792 static BOOLEAN
CheckPowerActionPolicy(PPOWER_ACTION_POLICY pPAP,SYSTEM_POWER_CAPABILITIES PowerCaps)793 CheckPowerActionPolicy(PPOWER_ACTION_POLICY pPAP, SYSTEM_POWER_CAPABILITIES PowerCaps)
794 {
795 /*
796    Lohnegrim: this is an Helper function, it checks if the POWERACTIONPOLICY is valid
797    Also, if the System doesn't support Hibernation, then change the PowerAction
798 */
799     switch (pPAP->Action)
800     {
801     case PowerActionNone:
802         return TRUE;
803     case PowerActionReserved:
804         if (PowerCaps.SystemS1 || PowerCaps.SystemS2 || PowerCaps.SystemS3)
805             pPAP->Action = PowerActionSleep;
806         else
807             pPAP->Action = PowerActionReserved;
808     case PowerActionSleep:
809         return TRUE;
810     case PowerActionHibernate:
811         if (!(PowerCaps.SystemS4 && PowerCaps.HiberFilePresent))
812         {
813             if (PowerCaps.SystemS1 || PowerCaps.SystemS2 || PowerCaps.SystemS3)
814                 pPAP->Action = PowerActionSleep;
815             else
816                 pPAP->Action = PowerActionReserved;
817         }
818     case PowerActionShutdown:
819     case PowerActionShutdownReset:
820     case PowerActionShutdownOff:
821     case PowerActionWarmEject:
822         return TRUE;
823     default:
824         SetLastError(ERROR_INVALID_DATA);
825         return FALSE;
826     };
827 }
828 
829 /**
830  * @brief
831  * Creates a security descriptor for the power
832  * management registry semaphore.
833  *
834  * @param[out] PowrProfSd
835  * A pointer to an allocated security descriptor
836  * for the semaphore.
837  *
838  * @return
839  * Returns TRUE if the function succeeds, otherwise
840  * FALSE is returned.
841  *
842  * @remarks
843  * Authenticated users are only given a subset of specific
844  * rights for the semaphore access, local system and admins
845  * have full power.
846  */
847 static BOOLEAN
CreatePowrProfSemaphoreSecurity(_Out_ PSECURITY_DESCRIPTOR * PowrProfSd)848 CreatePowrProfSemaphoreSecurity(_Out_ PSECURITY_DESCRIPTOR *PowrProfSd)
849 {
850     BOOLEAN Success = FALSE;
851     PACL Dacl;
852     ULONG DaclSize, RelSDSize = 0;
853     PSID AuthenticatedUsersSid = NULL, SystemSid = NULL, AdminsSid = NULL;
854     SECURITY_DESCRIPTOR AbsSd;
855     PSECURITY_DESCRIPTOR RelSd = NULL;
856     static SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
857 
858     if (!AllocateAndInitializeSid(&NtAuthority,
859                                   1,
860                                   SECURITY_AUTHENTICATED_USER_RID,
861                                   0, 0, 0, 0, 0, 0, 0,
862                                   &AuthenticatedUsersSid))
863     {
864         return FALSE;
865     }
866 
867     if (!AllocateAndInitializeSid(&NtAuthority,
868                                   1,
869                                   SECURITY_LOCAL_SYSTEM_RID,
870                                   0, 0, 0, 0, 0, 0, 0,
871                                   &SystemSid))
872     {
873         goto Quit;
874     }
875 
876     if (!AllocateAndInitializeSid(&NtAuthority,
877                                   2,
878                                   SECURITY_BUILTIN_DOMAIN_RID,
879                                   DOMAIN_ALIAS_RID_ADMINS,
880                                   0, 0, 0, 0, 0, 0,
881                                   &AdminsSid))
882     {
883         goto Quit;
884     }
885 
886     if (!InitializeSecurityDescriptor(&AbsSd, SECURITY_DESCRIPTOR_REVISION))
887     {
888         goto Quit;
889     }
890 
891     DaclSize = sizeof(ACL) +
892                sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(AuthenticatedUsersSid) +
893                sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(SystemSid) +
894                sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(AdminsSid);
895 
896     Dacl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, DaclSize);
897     if (!Dacl)
898     {
899         goto Quit;
900     }
901 
902     if (!InitializeAcl(Dacl, DaclSize, ACL_REVISION))
903     {
904         goto Quit;
905     }
906 
907     if (!AddAccessAllowedAce(Dacl,
908                              ACL_REVISION,
909                              SYNCHRONIZE | STANDARD_RIGHTS_READ | 0x3,
910                              AuthenticatedUsersSid))
911     {
912         goto Quit;
913     }
914 
915     if (!AddAccessAllowedAce(Dacl,
916                              ACL_REVISION,
917                              SEMAPHORE_ALL_ACCESS,
918                              SystemSid))
919     {
920         goto Quit;
921     }
922 
923     if (!AddAccessAllowedAce(Dacl,
924                              ACL_REVISION,
925                              SEMAPHORE_ALL_ACCESS,
926                              AdminsSid))
927     {
928         goto Quit;
929     }
930 
931     if (!SetSecurityDescriptorDacl(&AbsSd, TRUE, Dacl, FALSE))
932     {
933         goto Quit;
934     }
935 
936     if (!SetSecurityDescriptorOwner(&AbsSd, AdminsSid, FALSE))
937     {
938         goto Quit;
939     }
940 
941     if (!SetSecurityDescriptorGroup(&AbsSd, SystemSid, FALSE))
942     {
943         goto Quit;
944     }
945 
946     if (!MakeSelfRelativeSD(&AbsSd, NULL, &RelSDSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
947     {
948         RelSd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, RelSDSize);
949         if (RelSd == NULL)
950         {
951             goto Quit;
952         }
953 
954         if (!MakeSelfRelativeSD(&AbsSd, RelSd, &RelSDSize))
955         {
956             goto Quit;
957         }
958     }
959 
960     *PowrProfSd = RelSd;
961     Success = TRUE;
962 
963 Quit:
964     if (AuthenticatedUsersSid)
965     {
966         FreeSid(AuthenticatedUsersSid);
967     }
968 
969     if (SystemSid)
970     {
971         FreeSid(SystemSid);
972     }
973 
974     if (AdminsSid)
975     {
976         FreeSid(AdminsSid);
977     }
978 
979     if (Dacl)
980     {
981         HeapFree(GetProcessHeap(), 0, Dacl);
982     }
983 
984     if (!Success)
985     {
986         if (RelSd)
987         {
988             HeapFree(GetProcessHeap(), 0, RelSd);
989         }
990     }
991 
992     return Success;
993 }
994 
995 static VOID
FixSystemPowerState(PSYSTEM_POWER_STATE Psps,SYSTEM_POWER_CAPABILITIES PowerCaps)996 FixSystemPowerState(PSYSTEM_POWER_STATE Psps, SYSTEM_POWER_CAPABILITIES PowerCaps)
997 {
998 	//Lohnegrim: If the System doesn't support the Powerstates, then we have to change them
999     if (!PowerCaps.SystemS1 && *Psps == PowerSystemSleeping1)
1000         *Psps = PowerSystemSleeping2;
1001     if (!PowerCaps.SystemS2 && *Psps == PowerSystemSleeping2)
1002         *Psps = PowerSystemSleeping3;
1003     if (!PowerCaps.SystemS3 && *Psps == PowerSystemSleeping3)
1004         *Psps = PowerSystemHibernate;
1005     if (!(PowerCaps.SystemS4 && PowerCaps.HiberFilePresent) && *Psps == PowerSystemHibernate)
1006         *Psps = PowerSystemSleeping2;
1007     if (!PowerCaps.SystemS1 && *Psps == PowerSystemSleeping1)
1008         *Psps = PowerSystemSleeping2;
1009     if (!PowerCaps.SystemS2 && *Psps == PowerSystemSleeping2)
1010         *Psps = PowerSystemSleeping3;
1011     if (!PowerCaps.SystemS3 && *Psps == PowerSystemSleeping3)
1012         *Psps = PowerSystemShutdown;
1013 
1014 }
1015 
1016 BOOLEAN WINAPI
ValidatePowerPolicies(PGLOBAL_POWER_POLICY pGPP,PPOWER_POLICY pPP)1017 ValidatePowerPolicies(PGLOBAL_POWER_POLICY pGPP, PPOWER_POLICY pPP)
1018 {
1019     SYSTEM_POWER_CAPABILITIES PowerCaps;
1020     NTSTATUS ret;
1021     BOOLEAN old;
1022 
1023     RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &old);
1024     ret = NtPowerInformation(SystemPowerCapabilities, NULL, 0, &PowerCaps, sizeof(PowerCaps));
1025     if (ret != STATUS_SUCCESS)
1026     {
1027         SetLastError(RtlNtStatusToDosError(ret));
1028         return FALSE;
1029     }
1030 
1031     if (pGPP)
1032     {
1033         if (pGPP->user.Revision != 1 || pGPP->mach.Revision != 1)
1034         {
1035             SetLastError(ERROR_REVISION_MISMATCH);
1036             return FALSE;
1037         }
1038         if (pGPP->mach.LidOpenWakeAc == PowerSystemUnspecified)
1039         {
1040             SetLastError(ERROR_GEN_FAILURE);
1041             return FALSE;
1042         }
1043         if ((int)pGPP->mach.LidOpenWakeAc > PowerSystemShutdown)
1044         {
1045             SetLastError(ERROR_GEN_FAILURE);
1046             return FALSE;
1047         }
1048         if (pGPP->mach.LidOpenWakeDc < PowerSystemWorking)
1049         {
1050             SetLastError(ERROR_GEN_FAILURE);
1051             return FALSE;
1052         }
1053         if ((int)pGPP->mach.LidOpenWakeDc > PowerSystemShutdown)
1054         {
1055             SetLastError(ERROR_GEN_FAILURE);
1056             return FALSE;
1057         }
1058 		//Lohnegrim: unneeded
1059         /*if ((pGPP->mach.LidOpenWakeDc < PowerSystemWorking) || (pGPP->mach.LidOpenWakeDc >= PowerSystemMaximum))
1060         {
1061             SetLastError(ERROR_GEN_FAILURE);
1062             return FALSE;
1063         }*/
1064         if (!CheckPowerActionPolicy(&pGPP->user.LidCloseAc,PowerCaps))
1065         {
1066             return FALSE;
1067         }
1068         if (!CheckPowerActionPolicy(&pGPP->user.LidCloseDc,PowerCaps))
1069         {
1070             return FALSE;
1071         }
1072         if (!CheckPowerActionPolicy(&pGPP->user.PowerButtonAc,PowerCaps))
1073         {
1074             return FALSE;
1075         }
1076         if (!CheckPowerActionPolicy(&pGPP->user.PowerButtonDc,PowerCaps))
1077         {
1078             return FALSE;
1079         }
1080         if (!CheckPowerActionPolicy(&pGPP->user.SleepButtonAc,PowerCaps))
1081         {
1082             return FALSE;
1083         }
1084         if (!CheckPowerActionPolicy(&pGPP->user.SleepButtonDc,PowerCaps))
1085         {
1086             return FALSE;
1087         }
1088         //Lohnegrim: The BroadcastCapacityResolution presents the Powerlevel in Percent, if invalid set th 100 == FULL
1089         if (pGPP->mach.BroadcastCapacityResolution > 100)
1090             pGPP->mach.BroadcastCapacityResolution = 100;
1091 
1092 		//Lohnegrim: I have no idea, if they are really needed, or if they are specific for my System, or what they mean, so I removed them
1093         //pGPP->user.DischargePolicy[1].PowerPolicy.EventCode = pGPP->user.DischargePolicy[1].PowerPolicy.EventCode | 0x010000;
1094         //pGPP->user.DischargePolicy[2].PowerPolicy.EventCode = pGPP->user.DischargePolicy[2].PowerPolicy.EventCode | 0x020000;
1095         //pGPP->user.DischargePolicy[3].PowerPolicy.EventCode = pGPP->user.DischargePolicy[3].PowerPolicy.EventCode | 0x030000;
1096 
1097         FixSystemPowerState(&pGPP->mach.LidOpenWakeAc,PowerCaps);
1098         FixSystemPowerState(&pGPP->mach.LidOpenWakeDc,PowerCaps);
1099 
1100     }
1101 
1102     if (pPP)
1103     {
1104         if (pPP->user.Revision != 1 || pPP->mach.Revision != 1)
1105         {
1106             SetLastError(ERROR_REVISION_MISMATCH);
1107             return FALSE;
1108         }
1109 
1110 		//Lohnegrim: unneeded
1111         //if (pPP->mach.MinSleepAc < PowerSystemWorking)
1112         //{
1113         //    SetLastError(ERROR_GEN_FAILURE);
1114         //    return FALSE;
1115         //}
1116         if ((int)pPP->mach.MinSleepAc >= PowerSystemShutdown)
1117         {
1118             SetLastError(ERROR_GEN_FAILURE);
1119             return FALSE;
1120         }
1121 		//Lohnegrim: unneeded
1122         //if (pPP->mach.MinSleepDc < PowerSystemWorking)
1123         //{
1124         //    SetLastError(ERROR_GEN_FAILURE);
1125         //    return FALSE;
1126         //}
1127         if ((int)pPP->mach.MinSleepDc >= PowerSystemShutdown)
1128         {
1129             SetLastError(ERROR_GEN_FAILURE);
1130             return FALSE;
1131         }
1132         if ((int)pPP->mach.ReducedLatencySleepAc == PowerSystemUnspecified)
1133         {
1134             SetLastError(ERROR_GEN_FAILURE);
1135             return FALSE;
1136         }
1137         if ((int)pPP->mach.ReducedLatencySleepAc > PowerSystemShutdown)
1138         {
1139             SetLastError(ERROR_GEN_FAILURE);
1140             return FALSE;
1141         }
1142         if ((int)pPP->mach.ReducedLatencySleepDc < PowerSystemWorking)
1143         {
1144             SetLastError(ERROR_GEN_FAILURE);
1145             return FALSE;
1146         }
1147         if ((int)pPP->mach.ReducedLatencySleepDc > PowerSystemShutdown)
1148         {
1149             SetLastError(ERROR_GEN_FAILURE);
1150             return FALSE;
1151         }
1152 
1153         if (!CheckPowerActionPolicy(&pPP->mach.OverThrottledAc,PowerCaps))
1154         {
1155             return FALSE;
1156         }
1157         if (!CheckPowerActionPolicy(&pPP->mach.OverThrottledDc,PowerCaps))
1158         {
1159             return FALSE;
1160         }
1161         if (!CheckPowerActionPolicy(&pPP->user.IdleAc,PowerCaps))
1162         {
1163             return FALSE;
1164         }
1165         if (!CheckPowerActionPolicy(&pPP->user.IdleDc,PowerCaps))
1166         {
1167             return FALSE;
1168         }
1169         if (pPP->user.MaxSleepAc < PowerSystemWorking)
1170         {
1171             SetLastError(ERROR_GEN_FAILURE);
1172             return FALSE;
1173         }
1174 		//Lohnegrim: unneeded
1175         /*if ((int)pPP->user.MaxSleepAc > PowerSystemShutdown)
1176         {
1177             SetLastError(ERROR_GEN_FAILURE);
1178             return FALSE;
1179         }*/
1180         if (pPP->user.MaxSleepDc < PowerSystemWorking)
1181         {
1182             SetLastError(ERROR_GEN_FAILURE);
1183             return FALSE;
1184         }
1185 		//Lohnegrim: unneeded
1186         /*if ((int)pPP->user.MaxSleepDc >= PowerSystemShutdown)
1187         {
1188             SetLastError(ERROR_GEN_FAILURE);
1189             return FALSE;
1190         }*/
1191         if (PowerCaps.SystemS1)
1192         {
1193             pPP->mach.MinSleepAc=PowerSystemSleeping1;
1194             pPP->mach.MinSleepDc=PowerSystemSleeping1;
1195         }
1196         else if (PowerCaps.SystemS2)
1197         {
1198             pPP->mach.MinSleepAc=PowerSystemSleeping2;
1199             pPP->mach.MinSleepDc=PowerSystemSleeping2;
1200         }
1201         else if (PowerCaps.SystemS3)
1202         {
1203             pPP->mach.MinSleepAc=PowerSystemSleeping3;
1204             pPP->mach.MinSleepDc=PowerSystemSleeping3;
1205         }
1206 
1207         if (PowerCaps.SystemS4)
1208         {
1209             pPP->user.MaxSleepAc=PowerSystemSleeping3;
1210             pPP->user.MaxSleepDc=PowerSystemSleeping3;
1211         }
1212         else if (PowerCaps.SystemS3)
1213         {
1214             pPP->user.MaxSleepAc=PowerSystemSleeping2;
1215             pPP->user.MaxSleepDc=PowerSystemSleeping2;
1216         }
1217         else if (PowerCaps.SystemS1)
1218         {
1219             pPP->user.MaxSleepAc=PowerSystemSleeping1;
1220             pPP->user.MaxSleepDc=PowerSystemSleeping1;
1221         }
1222 		//Lohnegrim: I don't know where to get this info from, so I removed it
1223         //pPP->user.OptimizeForPowerAc=TRUE;
1224         //pPP->user.OptimizeForPowerDc=TRUE;
1225 
1226         FixSystemPowerState(&pPP->mach.ReducedLatencySleepAc,PowerCaps);
1227         FixSystemPowerState(&pPP->mach.ReducedLatencySleepDc,PowerCaps);
1228     }
1229 
1230     SetLastError(ERROR_SUCCESS);
1231     return TRUE;
1232 }
1233 
WritePwrPolicy(PUINT puiID,PPOWER_POLICY pPowerPolicy)1234 BOOLEAN WINAPI WritePwrPolicy(PUINT puiID, PPOWER_POLICY pPowerPolicy)
1235 {
1236     WCHAR Buf[MAX_PATH];
1237     HKEY hKey;
1238 
1239     swprintf(Buf, L"Control Panel\\PowerCfg\\PowerPolicies\\%i", *puiID);
1240 
1241     if (RegCreateKey(HKEY_CURRENT_USER, Buf, &hKey) != ERROR_SUCCESS)
1242         return FALSE;
1243 
1244     RegSetValueExW(hKey, szPolicies, 0, REG_BINARY, (const unsigned char *)&pPowerPolicy->user, sizeof(USER_POWER_POLICY));
1245     RegCloseKey(hKey);
1246 
1247     swprintf(Buf, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\PowerPolicies\\%i", *puiID);
1248 
1249     if (RegCreateKey(HKEY_LOCAL_MACHINE, Buf, &hKey) != ERROR_SUCCESS)
1250         return FALSE;
1251 
1252     RegSetValueExW(hKey, szPolicies, 0, REG_BINARY, (const unsigned char *)&pPowerPolicy->mach, sizeof(MACHINE_POWER_POLICY));
1253     RegCloseKey(hKey);
1254 
1255     return TRUE;
1256 }
1257 
1258 BOOL WINAPI
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)1259 DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1260 {
1261     switch(fdwReason)
1262     {
1263         case DLL_PROCESS_ATTACH:
1264         {
1265             HKEY hKey;
1266             LONG Err;
1267             SECURITY_ATTRIBUTES SecAttrs;
1268             PSECURITY_DESCRIPTOR Sd;
1269 
1270             DisableThreadLibraryCalls(hinstDLL);
1271 
1272             Err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPowerCfgSubKey, 0, KEY_READ, &hKey);
1273 
1274             if (Err != ERROR_SUCCESS)
1275             {
1276                 TRACE("Couldn't open registry key HKLM\\%s, using some sane(?) defaults\n", debugstr_w(szPowerCfgSubKey));
1277             }
1278             else
1279             {
1280                 WCHAR lpValue[MAX_PATH];
1281                 DWORD cbValue = sizeof(lpValue);
1282 
1283                 Err = RegQueryValueExW(hKey, szLastID, 0, 0, (BYTE*)lpValue, &cbValue);
1284                 if (Err == ERROR_SUCCESS)
1285                 {
1286                     g_LastID = _wtoi(lpValue);
1287                 }
1288                 else
1289                 {
1290                     TRACE("Couldn't open registry entry HKLM\\%s\\LastID, using some sane(?) defaults\n", debugstr_w(szPowerCfgSubKey));
1291                 }
1292                 RegCloseKey(hKey);
1293             }
1294 
1295             if (!CreatePowrProfSemaphoreSecurity(&Sd))
1296             {
1297                 ERR("Couldn't create POWRPROF semaphore security descriptor!\n");
1298                 return FALSE;
1299             }
1300 
1301             SecAttrs.nLength = sizeof(SECURITY_ATTRIBUTES);
1302             SecAttrs.lpSecurityDescriptor = Sd;
1303             SecAttrs.bInheritHandle = FALSE;
1304 
1305             PPRegSemaphore = CreateSemaphoreW(&SecAttrs, 1, 1, szSemaphoreName);
1306             HeapFree(GetProcessHeap(), 0, Sd);
1307             if (PPRegSemaphore == NULL)
1308             {
1309                 ERR("Couldn't create Semaphore: %d\n", GetLastError());
1310                 return FALSE;
1311             }
1312             break;
1313         }
1314         case DLL_PROCESS_DETACH:
1315             CloseHandle(PPRegSemaphore);
1316             break;
1317     }
1318     return TRUE;
1319 }
1320