xref: /reactos/dll/win32/powrprof/powrprof.c (revision f3c75078)
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
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
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
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
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
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
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
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
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
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
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
443 IsAdminOverrideActive(PADMINISTRATOR_POWER_POLICY p)
444 {
445     FIXME("( %p) stub!\n", p);
446     return FALSE;
447 }
448 
449 BOOLEAN WINAPI
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
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
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
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 PowerSetActiveScheme(HKEY UserRootPowerKey, GUID *polguid)
514 {
515    FIXME("(%p,%s) stub!\n", UserRootPowerKey, wine_dbgstr_guid(polguid));
516    return ERROR_SUCCESS;
517 }
518 
519 DWORD WINAPI
520 PowerReadDCValue(HKEY RootPowerKey, const GUID *Scheme, const GUID *SubGroup, const GUID *PowerSettings, PULONG Type, PUCHAR Buffer, DWORD *BufferSize)
521 {
522    FIXME("(%p,%s,%s,%s,%p,%p,%p) stub!\n", RootPowerKey, debugstr_guid(Scheme), debugstr_guid(SubGroup), debugstr_guid(PowerSettings), Type, Buffer, BufferSize);
523    return ERROR_CALL_NOT_IMPLEMENTED;
524 }
525 
526 DWORD WINAPI PowerReadFriendlyName(HKEY RootPowerKey, const GUID *Scheme,
527 	const GUID *SubGroup, const GUID *PowerSettings, UCHAR *Buffer,
528 	DWORD *BufferSize)
529 {
530    FIXME("(%p,%s,%s,%s,%p,%p) stub!\n", RootPowerKey, debugstr_guid(Scheme), debugstr_guid(SubGroup), debugstr_guid(PowerSettings), Buffer, BufferSize);
531    return ERROR_CALL_NOT_IMPLEMENTED;
532 }
533 
534 POWER_PLATFORM_ROLE WINAPI PowerDeterminePlatformRole(void)
535 {
536    FIXME("stub\n");
537    return PlatformRoleDesktop;
538 }
539 
540 POWER_PLATFORM_ROLE WINAPI PowerDeterminePlatformRoleEx(ULONG version)
541 {
542     FIXME("%lu stub.\n", version);
543     return PlatformRoleDesktop;
544 }
545 
546 DWORD WINAPI PowerEnumerate(HKEY key, const GUID *scheme, const GUID *subgroup, POWER_DATA_ACCESSOR flags,
547                         ULONG index, UCHAR *buffer, DWORD *buffer_size)
548 {
549    FIXME("(%p,%s,%s,%d,%ld,%p,%p) stub!\n", key, debugstr_guid(scheme), debugstr_guid(subgroup),
550                 flags, index, buffer, buffer_size);
551    return ERROR_CALL_NOT_IMPLEMENTED;
552 }
553 
554 DWORD WINAPI PowerRegisterSuspendResumeNotification(DWORD flags, HANDLE recipient, PHPOWERNOTIFY handle)
555 {
556     FIXME("(0x%08lx,%p,%p) stub!\n", flags, recipient, handle);
557     *handle = (HPOWERNOTIFY)0xdeadbeef;
558     return ERROR_SUCCESS;
559 }
560 
561 DWORD WINAPI PowerUnregisterSuspendResumeNotification(HPOWERNOTIFY handle)
562 {
563     FIXME("(%p) stub!\n", handle);
564     return ERROR_SUCCESS;
565 }
566 
567 DWORD WINAPI PowerSettingRegisterNotification(const GUID *setting, DWORD flags, HANDLE recipient, PHPOWERNOTIFY handle)
568 {
569     FIXME("(%s,0x%08lx,%p,%p) stub!\n", debugstr_guid(setting), flags, recipient, handle);
570     *handle = (PHPOWERNOTIFY)0xdeadbeef;
571     return ERROR_SUCCESS;
572 }
573 
574 DWORD WINAPI PowerSettingUnregisterNotification(HPOWERNOTIFY handle)
575 {
576     FIXME("(%p) stub!\n", handle);
577     return ERROR_SUCCESS;
578 }
579 
580 DWORD WINAPI PowerWriteACValueIndex(HKEY key, const GUID *scheme, const GUID *subgroup, const GUID *setting, DWORD index)
581 {
582    FIXME("(%p,%s,%s,%s,0x%08lx) stub!\n", key, debugstr_guid(scheme), debugstr_guid(subgroup), debugstr_guid(setting), index);
583    return ERROR_SUCCESS;
584 }
585 
586 #ifdef __REACTOS__
587 DWORD WINAPI PowerWriteDCValueIndex(
588    HKEY       key,
589    const GUID *scheme,
590    const GUID *subgroup,
591    const GUID *setting,
592    DWORD      index
593 )
594 {
595    FIXME("(%p,%s,%s,%s,0x%08lx) stub!\n", key, debugstr_guid(scheme), debugstr_guid(subgroup), debugstr_guid(setting), index);
596    return ERROR_SUCCESS;
597 }
598 
599 DWORD WINAPI PowerReadACValueIndex(
600    HKEY       key,
601    const GUID *scheme,
602    const GUID *subgroup,
603    const GUID *setting,
604    LPDWORD    AcValueIndex
605 )
606 {
607     FIXME("(%p,%s,%s,%s,0x%08lx) stub!\n", key, debugstr_guid(scheme), debugstr_guid(subgroup), debugstr_guid(setting));
608     return ERROR_SUCCESS;
609 }
610 
611 DWORD WINAPI PowerReadDCValueIndex(
612     HKEY       key,
613     const GUID *scheme,
614     const GUID *subgroup,
615     const GUID *setting,
616     LPDWORD    DcValuetIndex
617 )
618 {
619     FIXME("(%p,%s,%s,%s,0x%08lx) stub!\n", key, debugstr_guid(scheme), debugstr_guid(subgroup), debugstr_guid(setting));
620     return ERROR_SUCCESS;
621 }
622 
623 DWORD WINAPI
624 PowerReadACValue(HKEY RootPowerKey, const GUID *Scheme, const GUID *SubGroup, const GUID *PowerSettings, PULONG Type, PUCHAR Buffer, DWORD *BufferSize)
625 {
626    FIXME("(%p,%s,%s,%s,%p,%p,%p) stub!\n", RootPowerKey, debugstr_guid(Scheme), debugstr_guid(SubGroup), debugstr_guid(PowerSettings), Type, Buffer, BufferSize);
627    return ERROR_CALL_NOT_IMPLEMENTED;
628 }
629 #endif
630 
631 BOOLEAN WINAPI
632 ReadGlobalPwrPolicy(PGLOBAL_POWER_POLICY pGlobalPowerPolicy)
633 {
634     GLOBAL_MACHINE_POWER_POLICY glMachPwrPolicy;
635     GLOBAL_USER_POWER_POLICY glUserPwrPolicy;
636     HKEY hKey = NULL;
637     DWORD dwSize;
638     LONG Err;
639     BOOL bRet = FALSE;
640 
641     ReleaseSemaphore(PPRegSemaphore, 1, NULL);
642 
643     // Getting user global power policy
644     Err = RegOpenKeyExW(HKEY_CURRENT_USER, L"Control Panel\\PowerCfg\\GlobalPowerPolicy", 0, KEY_READ, &hKey);
645     if (Err != ERROR_SUCCESS)
646     {
647         ERR("RegOpenKeyW failed: %d\n", Err);
648         SetLastError(Err);
649         goto cleanup;
650     }
651 
652     dwSize = sizeof(glUserPwrPolicy);
653     Err = RegQueryValueExW(hKey, L"Policies", NULL, NULL, (LPBYTE)&glUserPwrPolicy, &dwSize);
654     if (Err != ERROR_SUCCESS)
655     {
656         ERR("RegQueryValueExW failed: %d\n", Err);
657         SetLastError(Err);
658         goto cleanup;
659     }
660 
661     RegCloseKey(hKey);
662 
663     // Getting machine global power policy
664     Err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\GlobalPowerPolicy", 0, KEY_READ, &hKey);
665     if (Err != ERROR_SUCCESS)
666     {
667         ERR("RegOpenKeyW failed: %d\n", Err);
668         SetLastError(Err);
669         goto cleanup;
670     }
671 
672     dwSize = sizeof(glMachPwrPolicy);
673     Err = RegQueryValueExW(hKey, L"Policies", NULL, NULL, (LPBYTE)&glMachPwrPolicy, &dwSize);
674     if (Err != ERROR_SUCCESS)
675     {
676         ERR("RegQueryValueExW failed: %d\n", Err);
677         SetLastError(Err);
678         goto cleanup;
679     }
680 
681     memcpy(&pGlobalPowerPolicy->user, &glUserPwrPolicy, sizeof(GLOBAL_USER_POWER_POLICY));
682     memcpy(&pGlobalPowerPolicy->mach, &glMachPwrPolicy, sizeof(GLOBAL_MACHINE_POWER_POLICY));
683     bRet = TRUE;
684 
685 cleanup:
686     if(hKey)
687         RegCloseKey(hKey);
688     ReleaseSemaphore(PPRegSemaphore, 1, NULL);
689 
690     return bRet;
691 }
692 
693 
694 BOOLEAN WINAPI
695 ReadProcessorPwrScheme(UINT uiID,
696                        PMACHINE_PROCESSOR_POWER_POLICY pMachineProcessorPowerPolicy)
697 {
698     HKEY hKey;
699     WCHAR szPath[MAX_PATH];
700     DWORD dwSize = sizeof(MACHINE_PROCESSOR_POWER_POLICY);
701 
702     swprintf(szPath, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\ProcessorPolicies\\%i", uiID);
703     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
704         return FALSE;
705 
706     if (RegQueryValueExW(hKey, szPolicies, NULL, 0, (LPBYTE)pMachineProcessorPowerPolicy, &dwSize) == ERROR_SUCCESS)
707     {
708         RegCloseKey(hKey);
709         return TRUE;
710     }
711 
712     RegCloseKey(hKey);
713     if (uiID != 0)
714         return ReadProcessorPwrScheme(0, pMachineProcessorPowerPolicy);
715 
716     return FALSE;
717 }
718 
719 
720 BOOLEAN WINAPI
721 ReadPwrScheme(UINT uiID,
722     PPOWER_POLICY pPowerPolicy)
723 {
724     USER_POWER_POLICY userPwrPolicy;
725     MACHINE_POWER_POLICY machinePwrPolicy;
726     WCHAR szNum[16]; // max number - 999
727 
728     ReleaseSemaphore(PPRegSemaphore, 1, NULL);
729 
730     swprintf(szNum, L"%d", uiID);
731 
732     if (!POWRPROF_GetUserPowerPolicy(szNum, &userPwrPolicy, 0, NULL, 0, NULL))
733     {
734         ReleaseSemaphore(PPRegSemaphore, 1, NULL);
735         return FALSE;
736     }
737 
738     if (!POWRPROF_GetMachinePowerPolicy(szNum, &machinePwrPolicy))
739     {
740         ReleaseSemaphore(PPRegSemaphore, 1, NULL);
741         return FALSE;
742     }
743 
744     memcpy(&pPowerPolicy->user, &userPwrPolicy, sizeof(userPwrPolicy));
745     memcpy(&pPowerPolicy->mach, &machinePwrPolicy, sizeof(machinePwrPolicy));
746 
747     ReleaseSemaphore(PPRegSemaphore, 1, NULL);
748 
749     return TRUE;
750 }
751 
752 BOOLEAN WINAPI
753 SetActivePwrScheme(UINT uiID,
754                    PGLOBAL_POWER_POLICY lpGlobalPowerPolicy,
755                    PPOWER_POLICY lpPowerPolicy)
756 {
757     POWER_POLICY tmp;
758     HKEY hKey;
759     WCHAR Buf[16];
760 
761     if (!ReadPwrScheme(uiID, &tmp))
762         return FALSE;
763 
764     if (RegOpenKeyEx(HKEY_CURRENT_USER, szUserPowerConfigSubKey, 0, KEY_WRITE, &hKey) != ERROR_SUCCESS)
765         return FALSE;
766 
767     swprintf(Buf, L"%i", uiID);
768 
769     if (RegSetValueExW(hKey, szCurrentPowerPolicies, 0, REG_SZ, (PBYTE)Buf, strlenW(Buf)*sizeof(WCHAR)) != ERROR_SUCCESS)
770     {
771         RegCloseKey(hKey);
772         return FALSE;
773     }
774     RegCloseKey(hKey);
775 
776     if (lpGlobalPowerPolicy != NULL || lpPowerPolicy != NULL)
777     {
778         if (!ValidatePowerPolicies(lpGlobalPowerPolicy, lpPowerPolicy))
779             return FALSE;
780 
781         if (lpGlobalPowerPolicy != NULL && !WriteGlobalPwrPolicy(lpGlobalPowerPolicy))
782             return FALSE;
783 
784         if (lpPowerPolicy != NULL && !WritePwrPolicy(&uiID,lpPowerPolicy))
785             return FALSE;
786     }
787 
788     return TRUE;
789 }
790 
791 BOOLEAN WINAPI
792 SetSuspendState(BOOLEAN Hibernate,
793                 BOOLEAN ForceCritical,
794                 BOOLEAN DisableWakeEvent)
795 {
796     FIXME("(%d, %d, %d) stub!\n", Hibernate, ForceCritical, DisableWakeEvent);
797     return TRUE;
798 }
799 
800 BOOLEAN WINAPI
801 WriteGlobalPwrPolicy(PGLOBAL_POWER_POLICY pGlobalPowerPolicy)
802 {
803     HKEY hKey;
804     GLOBAL_USER_POWER_POLICY gupp;
805     GLOBAL_MACHINE_POWER_POLICY gmpp;
806 
807     gupp = pGlobalPowerPolicy->user;
808     gmpp = pGlobalPowerPolicy->mach;
809 
810     if (RegOpenKeyEx(HKEY_CURRENT_USER,
811                     L"Control Panel\\PowerCfg\\GlobalPowerPolicy",
812                     0,
813                     KEY_WRITE,
814                     &hKey) != ERROR_SUCCESS)
815         return FALSE;
816 
817     if (RegSetValueExW(hKey, szPolicies, 0, REG_BINARY, (PBYTE)&gupp, sizeof(gupp)) != ERROR_SUCCESS)
818     {
819         RegCloseKey(hKey);
820         return FALSE;
821     }
822 
823     RegCloseKey(hKey);
824 
825     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
826                      L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\GlobalPowerPolicy",
827                      0,
828                      KEY_ALL_ACCESS,
829                      &hKey))
830         return FALSE;
831 
832     if (RegSetValueExW(hKey,szPolicies, 0, REG_BINARY, (PBYTE)&gmpp, sizeof(gmpp)) != ERROR_SUCCESS)
833     {
834         RegCloseKey(hKey);
835         return FALSE;
836     }
837 
838     RegCloseKey(hKey);
839     return TRUE;
840 }
841 
842 BOOLEAN WINAPI
843 WriteProcessorPwrScheme(UINT ID,
844                         PMACHINE_PROCESSOR_POWER_POLICY pMachineProcessorPowerPolicy)
845 {
846     WCHAR Buf[MAX_PATH];
847     HKEY hKey;
848 
849     swprintf(Buf, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\ProcessorPolicies\\%i", ID);
850 
851     if (RegCreateKey(HKEY_LOCAL_MACHINE, Buf, &hKey) != ERROR_SUCCESS)
852         return FALSE;
853 
854     RegSetValueExW(hKey, szPolicies, 0, REG_BINARY, (PBYTE)pMachineProcessorPowerPolicy, sizeof(MACHINE_PROCESSOR_POWER_POLICY));
855     RegCloseKey(hKey);
856     return TRUE;
857 }
858 
859 static VOID
860 SetLastID(VOID)
861 {
862     WCHAR Buf[16];
863     HKEY hKey;
864 
865     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
866                     szPowerCfgSubKey,
867                     0,
868                     KEY_WRITE,
869                     &hKey) != ERROR_SUCCESS)
870         return;
871     swprintf(Buf, L"%i", g_LastID);
872     RegSetValueExW(hKey, szLastID, 0, REG_SZ, (PBYTE)Buf, strlenW(Buf)*sizeof(WCHAR));
873     RegCloseKey(hKey);
874 }
875 
876 BOOLEAN WINAPI
877 WritePwrScheme(PUINT puiID,
878                LPWSTR lpszName,
879                LPWSTR lpszDescription,
880                PPOWER_POLICY pPowerPolicy)
881 {
882     WCHAR Buf[MAX_PATH];
883     HKEY hKey;
884 
885     if (*puiID == -1)
886     {
887         g_LastID++;
888         *puiID = g_LastID;
889         SetLastID();
890     }
891 
892     swprintf(Buf, L"Control Panel\\PowerCfg\\PowerPolicies\\%i", *puiID);
893 
894     if (RegCreateKey(HKEY_CURRENT_USER, Buf, &hKey) != ERROR_SUCCESS)
895         return FALSE;
896 
897     RegSetValueExW(hKey, szName, 0, REG_SZ, (PBYTE)lpszName, strlenW(lpszName)*sizeof(WCHAR));
898     RegSetValueExW(hKey, szDescription, 0, REG_SZ, (PBYTE)lpszDescription, strlenW(lpszDescription)*sizeof(WCHAR));
899     RegCloseKey(hKey);
900     return WritePwrPolicy(puiID, pPowerPolicy);
901 }
902 
903 static BOOLEAN
904 CheckPowerActionPolicy(PPOWER_ACTION_POLICY pPAP, SYSTEM_POWER_CAPABILITIES PowerCaps)
905 {
906 /*
907    Lohnegrim: this is an Helper function, it checks if the POWERACTIONPOLICY is valid
908    Also, if the System doesn't support Hibernation, then change the PowerAction
909 */
910     switch (pPAP->Action)
911     {
912     case PowerActionNone:
913         return TRUE;
914     case PowerActionReserved:
915         if (PowerCaps.SystemS1 || PowerCaps.SystemS2 || PowerCaps.SystemS3)
916             pPAP->Action = PowerActionSleep;
917         else
918             pPAP->Action = PowerActionReserved;
919     case PowerActionSleep:
920         return TRUE;
921     case PowerActionHibernate:
922         if (!(PowerCaps.SystemS4 && PowerCaps.HiberFilePresent))
923         {
924             if (PowerCaps.SystemS1 || PowerCaps.SystemS2 || PowerCaps.SystemS3)
925                 pPAP->Action = PowerActionSleep;
926             else
927                 pPAP->Action = PowerActionReserved;
928         }
929     case PowerActionShutdown:
930     case PowerActionShutdownReset:
931     case PowerActionShutdownOff:
932     case PowerActionWarmEject:
933         return TRUE;
934     default:
935         SetLastError(ERROR_INVALID_DATA);
936         return FALSE;
937     };
938 }
939 
940 /**
941  * @brief
942  * Creates a security descriptor for the power
943  * management registry semaphore.
944  *
945  * @param[out] PowrProfSd
946  * A pointer to an allocated security descriptor
947  * for the semaphore.
948  *
949  * @return
950  * Returns TRUE if the function succeeds, otherwise
951  * FALSE is returned.
952  *
953  * @remarks
954  * Authenticated users are only given a subset of specific
955  * rights for the semaphore access, local system and admins
956  * have full power.
957  */
958 static BOOLEAN
959 CreatePowrProfSemaphoreSecurity(_Out_ PSECURITY_DESCRIPTOR *PowrProfSd)
960 {
961     BOOLEAN Success = FALSE;
962     PACL Dacl;
963     ULONG DaclSize, RelSDSize = 0;
964     PSID AuthenticatedUsersSid = NULL, SystemSid = NULL, AdminsSid = NULL;
965     SECURITY_DESCRIPTOR AbsSd;
966     PSECURITY_DESCRIPTOR RelSd = NULL;
967     static SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
968 
969     if (!AllocateAndInitializeSid(&NtAuthority,
970                                   1,
971                                   SECURITY_AUTHENTICATED_USER_RID,
972                                   0, 0, 0, 0, 0, 0, 0,
973                                   &AuthenticatedUsersSid))
974     {
975         return FALSE;
976     }
977 
978     if (!AllocateAndInitializeSid(&NtAuthority,
979                                   1,
980                                   SECURITY_LOCAL_SYSTEM_RID,
981                                   0, 0, 0, 0, 0, 0, 0,
982                                   &SystemSid))
983     {
984         goto Quit;
985     }
986 
987     if (!AllocateAndInitializeSid(&NtAuthority,
988                                   2,
989                                   SECURITY_BUILTIN_DOMAIN_RID,
990                                   DOMAIN_ALIAS_RID_ADMINS,
991                                   0, 0, 0, 0, 0, 0,
992                                   &AdminsSid))
993     {
994         goto Quit;
995     }
996 
997     if (!InitializeSecurityDescriptor(&AbsSd, SECURITY_DESCRIPTOR_REVISION))
998     {
999         goto Quit;
1000     }
1001 
1002     DaclSize = sizeof(ACL) +
1003                sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(AuthenticatedUsersSid) +
1004                sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(SystemSid) +
1005                sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(AdminsSid);
1006 
1007     Dacl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, DaclSize);
1008     if (!Dacl)
1009     {
1010         goto Quit;
1011     }
1012 
1013     if (!InitializeAcl(Dacl, DaclSize, ACL_REVISION))
1014     {
1015         goto Quit;
1016     }
1017 
1018     if (!AddAccessAllowedAce(Dacl,
1019                              ACL_REVISION,
1020                              SYNCHRONIZE | STANDARD_RIGHTS_READ | 0x3,
1021                              AuthenticatedUsersSid))
1022     {
1023         goto Quit;
1024     }
1025 
1026     if (!AddAccessAllowedAce(Dacl,
1027                              ACL_REVISION,
1028                              SEMAPHORE_ALL_ACCESS,
1029                              SystemSid))
1030     {
1031         goto Quit;
1032     }
1033 
1034     if (!AddAccessAllowedAce(Dacl,
1035                              ACL_REVISION,
1036                              SEMAPHORE_ALL_ACCESS,
1037                              AdminsSid))
1038     {
1039         goto Quit;
1040     }
1041 
1042     if (!SetSecurityDescriptorDacl(&AbsSd, TRUE, Dacl, FALSE))
1043     {
1044         goto Quit;
1045     }
1046 
1047     if (!SetSecurityDescriptorOwner(&AbsSd, AdminsSid, FALSE))
1048     {
1049         goto Quit;
1050     }
1051 
1052     if (!SetSecurityDescriptorGroup(&AbsSd, SystemSid, FALSE))
1053     {
1054         goto Quit;
1055     }
1056 
1057     if (!MakeSelfRelativeSD(&AbsSd, NULL, &RelSDSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1058     {
1059         RelSd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, RelSDSize);
1060         if (RelSd == NULL)
1061         {
1062             goto Quit;
1063         }
1064 
1065         if (!MakeSelfRelativeSD(&AbsSd, RelSd, &RelSDSize))
1066         {
1067             goto Quit;
1068         }
1069     }
1070 
1071     *PowrProfSd = RelSd;
1072     Success = TRUE;
1073 
1074 Quit:
1075     if (AuthenticatedUsersSid)
1076     {
1077         FreeSid(AuthenticatedUsersSid);
1078     }
1079 
1080     if (SystemSid)
1081     {
1082         FreeSid(SystemSid);
1083     }
1084 
1085     if (AdminsSid)
1086     {
1087         FreeSid(AdminsSid);
1088     }
1089 
1090     if (Dacl)
1091     {
1092         HeapFree(GetProcessHeap(), 0, Dacl);
1093     }
1094 
1095     if (!Success)
1096     {
1097         if (RelSd)
1098         {
1099             HeapFree(GetProcessHeap(), 0, RelSd);
1100         }
1101     }
1102 
1103     return Success;
1104 }
1105 
1106 static VOID
1107 FixSystemPowerState(PSYSTEM_POWER_STATE Psps, SYSTEM_POWER_CAPABILITIES PowerCaps)
1108 {
1109 	//Lohnegrim: If the System doesn't support the Powerstates, then we have to change them
1110     if (!PowerCaps.SystemS1 && *Psps == PowerSystemSleeping1)
1111         *Psps = PowerSystemSleeping2;
1112     if (!PowerCaps.SystemS2 && *Psps == PowerSystemSleeping2)
1113         *Psps = PowerSystemSleeping3;
1114     if (!PowerCaps.SystemS3 && *Psps == PowerSystemSleeping3)
1115         *Psps = PowerSystemHibernate;
1116     if (!(PowerCaps.SystemS4 && PowerCaps.HiberFilePresent) && *Psps == PowerSystemHibernate)
1117         *Psps = PowerSystemSleeping2;
1118     if (!PowerCaps.SystemS1 && *Psps == PowerSystemSleeping1)
1119         *Psps = PowerSystemSleeping2;
1120     if (!PowerCaps.SystemS2 && *Psps == PowerSystemSleeping2)
1121         *Psps = PowerSystemSleeping3;
1122     if (!PowerCaps.SystemS3 && *Psps == PowerSystemSleeping3)
1123         *Psps = PowerSystemShutdown;
1124 
1125 }
1126 
1127 BOOLEAN WINAPI
1128 ValidatePowerPolicies(PGLOBAL_POWER_POLICY pGPP, PPOWER_POLICY pPP)
1129 {
1130     SYSTEM_POWER_CAPABILITIES PowerCaps;
1131     NTSTATUS ret;
1132     BOOLEAN old;
1133 
1134     RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &old);
1135     ret = NtPowerInformation(SystemPowerCapabilities, NULL, 0, &PowerCaps, sizeof(PowerCaps));
1136     if (ret != STATUS_SUCCESS)
1137     {
1138         SetLastError(RtlNtStatusToDosError(ret));
1139         return FALSE;
1140     }
1141 
1142     if (pGPP)
1143     {
1144         if (pGPP->user.Revision != 1 || pGPP->mach.Revision != 1)
1145         {
1146             SetLastError(ERROR_REVISION_MISMATCH);
1147             return FALSE;
1148         }
1149         if (pGPP->mach.LidOpenWakeAc == PowerSystemUnspecified)
1150         {
1151             SetLastError(ERROR_GEN_FAILURE);
1152             return FALSE;
1153         }
1154         if ((int)pGPP->mach.LidOpenWakeAc > PowerSystemShutdown)
1155         {
1156             SetLastError(ERROR_GEN_FAILURE);
1157             return FALSE;
1158         }
1159         if (pGPP->mach.LidOpenWakeDc < PowerSystemWorking)
1160         {
1161             SetLastError(ERROR_GEN_FAILURE);
1162             return FALSE;
1163         }
1164         if ((int)pGPP->mach.LidOpenWakeDc > PowerSystemShutdown)
1165         {
1166             SetLastError(ERROR_GEN_FAILURE);
1167             return FALSE;
1168         }
1169 		//Lohnegrim: unneeded
1170         /*if ((pGPP->mach.LidOpenWakeDc < PowerSystemWorking) || (pGPP->mach.LidOpenWakeDc >= PowerSystemMaximum))
1171         {
1172             SetLastError(ERROR_GEN_FAILURE);
1173             return FALSE;
1174         }*/
1175         if (!CheckPowerActionPolicy(&pGPP->user.LidCloseAc,PowerCaps))
1176         {
1177             return FALSE;
1178         }
1179         if (!CheckPowerActionPolicy(&pGPP->user.LidCloseDc,PowerCaps))
1180         {
1181             return FALSE;
1182         }
1183         if (!CheckPowerActionPolicy(&pGPP->user.PowerButtonAc,PowerCaps))
1184         {
1185             return FALSE;
1186         }
1187         if (!CheckPowerActionPolicy(&pGPP->user.PowerButtonDc,PowerCaps))
1188         {
1189             return FALSE;
1190         }
1191         if (!CheckPowerActionPolicy(&pGPP->user.SleepButtonAc,PowerCaps))
1192         {
1193             return FALSE;
1194         }
1195         if (!CheckPowerActionPolicy(&pGPP->user.SleepButtonDc,PowerCaps))
1196         {
1197             return FALSE;
1198         }
1199         //Lohnegrim: The BroadcastCapacityResolution presents the Powerlevel in Percent, if invalid set th 100 == FULL
1200         if (pGPP->mach.BroadcastCapacityResolution > 100)
1201             pGPP->mach.BroadcastCapacityResolution = 100;
1202 
1203 		//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
1204         //pGPP->user.DischargePolicy[1].PowerPolicy.EventCode = pGPP->user.DischargePolicy[1].PowerPolicy.EventCode | 0x010000;
1205         //pGPP->user.DischargePolicy[2].PowerPolicy.EventCode = pGPP->user.DischargePolicy[2].PowerPolicy.EventCode | 0x020000;
1206         //pGPP->user.DischargePolicy[3].PowerPolicy.EventCode = pGPP->user.DischargePolicy[3].PowerPolicy.EventCode | 0x030000;
1207 
1208         FixSystemPowerState(&pGPP->mach.LidOpenWakeAc,PowerCaps);
1209         FixSystemPowerState(&pGPP->mach.LidOpenWakeDc,PowerCaps);
1210 
1211     }
1212 
1213     if (pPP)
1214     {
1215         if (pPP->user.Revision != 1 || pPP->mach.Revision != 1)
1216         {
1217             SetLastError(ERROR_REVISION_MISMATCH);
1218             return FALSE;
1219         }
1220 
1221 		//Lohnegrim: unneeded
1222         //if (pPP->mach.MinSleepAc < PowerSystemWorking)
1223         //{
1224         //    SetLastError(ERROR_GEN_FAILURE);
1225         //    return FALSE;
1226         //}
1227         if ((int)pPP->mach.MinSleepAc >= PowerSystemShutdown)
1228         {
1229             SetLastError(ERROR_GEN_FAILURE);
1230             return FALSE;
1231         }
1232 		//Lohnegrim: unneeded
1233         //if (pPP->mach.MinSleepDc < PowerSystemWorking)
1234         //{
1235         //    SetLastError(ERROR_GEN_FAILURE);
1236         //    return FALSE;
1237         //}
1238         if ((int)pPP->mach.MinSleepDc >= PowerSystemShutdown)
1239         {
1240             SetLastError(ERROR_GEN_FAILURE);
1241             return FALSE;
1242         }
1243         if ((int)pPP->mach.ReducedLatencySleepAc == PowerSystemUnspecified)
1244         {
1245             SetLastError(ERROR_GEN_FAILURE);
1246             return FALSE;
1247         }
1248         if ((int)pPP->mach.ReducedLatencySleepAc > PowerSystemShutdown)
1249         {
1250             SetLastError(ERROR_GEN_FAILURE);
1251             return FALSE;
1252         }
1253         if ((int)pPP->mach.ReducedLatencySleepDc < PowerSystemWorking)
1254         {
1255             SetLastError(ERROR_GEN_FAILURE);
1256             return FALSE;
1257         }
1258         if ((int)pPP->mach.ReducedLatencySleepDc > PowerSystemShutdown)
1259         {
1260             SetLastError(ERROR_GEN_FAILURE);
1261             return FALSE;
1262         }
1263 
1264         if (!CheckPowerActionPolicy(&pPP->mach.OverThrottledAc,PowerCaps))
1265         {
1266             return FALSE;
1267         }
1268         if (!CheckPowerActionPolicy(&pPP->mach.OverThrottledDc,PowerCaps))
1269         {
1270             return FALSE;
1271         }
1272         if (!CheckPowerActionPolicy(&pPP->user.IdleAc,PowerCaps))
1273         {
1274             return FALSE;
1275         }
1276         if (!CheckPowerActionPolicy(&pPP->user.IdleDc,PowerCaps))
1277         {
1278             return FALSE;
1279         }
1280         if (pPP->user.MaxSleepAc < PowerSystemWorking)
1281         {
1282             SetLastError(ERROR_GEN_FAILURE);
1283             return FALSE;
1284         }
1285 		//Lohnegrim: unneeded
1286         /*if ((int)pPP->user.MaxSleepAc > PowerSystemShutdown)
1287         {
1288             SetLastError(ERROR_GEN_FAILURE);
1289             return FALSE;
1290         }*/
1291         if (pPP->user.MaxSleepDc < PowerSystemWorking)
1292         {
1293             SetLastError(ERROR_GEN_FAILURE);
1294             return FALSE;
1295         }
1296 		//Lohnegrim: unneeded
1297         /*if ((int)pPP->user.MaxSleepDc >= PowerSystemShutdown)
1298         {
1299             SetLastError(ERROR_GEN_FAILURE);
1300             return FALSE;
1301         }*/
1302         if (PowerCaps.SystemS1)
1303         {
1304             pPP->mach.MinSleepAc=PowerSystemSleeping1;
1305             pPP->mach.MinSleepDc=PowerSystemSleeping1;
1306         }
1307         else if (PowerCaps.SystemS2)
1308         {
1309             pPP->mach.MinSleepAc=PowerSystemSleeping2;
1310             pPP->mach.MinSleepDc=PowerSystemSleeping2;
1311         }
1312         else if (PowerCaps.SystemS3)
1313         {
1314             pPP->mach.MinSleepAc=PowerSystemSleeping3;
1315             pPP->mach.MinSleepDc=PowerSystemSleeping3;
1316         }
1317 
1318         if (PowerCaps.SystemS4)
1319         {
1320             pPP->user.MaxSleepAc=PowerSystemSleeping3;
1321             pPP->user.MaxSleepDc=PowerSystemSleeping3;
1322         }
1323         else if (PowerCaps.SystemS3)
1324         {
1325             pPP->user.MaxSleepAc=PowerSystemSleeping2;
1326             pPP->user.MaxSleepDc=PowerSystemSleeping2;
1327         }
1328         else if (PowerCaps.SystemS1)
1329         {
1330             pPP->user.MaxSleepAc=PowerSystemSleeping1;
1331             pPP->user.MaxSleepDc=PowerSystemSleeping1;
1332         }
1333 		//Lohnegrim: I don't know where to get this info from, so I removed it
1334         //pPP->user.OptimizeForPowerAc=TRUE;
1335         //pPP->user.OptimizeForPowerDc=TRUE;
1336 
1337         FixSystemPowerState(&pPP->mach.ReducedLatencySleepAc,PowerCaps);
1338         FixSystemPowerState(&pPP->mach.ReducedLatencySleepDc,PowerCaps);
1339     }
1340 
1341     SetLastError(ERROR_SUCCESS);
1342     return TRUE;
1343 }
1344 
1345 BOOLEAN WINAPI WritePwrPolicy(PUINT puiID, PPOWER_POLICY pPowerPolicy)
1346 {
1347     WCHAR Buf[MAX_PATH];
1348     HKEY hKey;
1349 
1350     swprintf(Buf, L"Control Panel\\PowerCfg\\PowerPolicies\\%i", *puiID);
1351 
1352     if (RegCreateKey(HKEY_CURRENT_USER, Buf, &hKey) != ERROR_SUCCESS)
1353         return FALSE;
1354 
1355     RegSetValueExW(hKey, szPolicies, 0, REG_BINARY, (const unsigned char *)&pPowerPolicy->user, sizeof(USER_POWER_POLICY));
1356     RegCloseKey(hKey);
1357 
1358     swprintf(Buf, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\PowerPolicies\\%i", *puiID);
1359 
1360     if (RegCreateKey(HKEY_LOCAL_MACHINE, Buf, &hKey) != ERROR_SUCCESS)
1361         return FALSE;
1362 
1363     RegSetValueExW(hKey, szPolicies, 0, REG_BINARY, (const unsigned char *)&pPowerPolicy->mach, sizeof(MACHINE_POWER_POLICY));
1364     RegCloseKey(hKey);
1365 
1366     return TRUE;
1367 }
1368 
1369 BOOL WINAPI
1370 DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1371 {
1372     switch(fdwReason)
1373     {
1374         case DLL_PROCESS_ATTACH:
1375         {
1376             HKEY hKey;
1377             LONG Err;
1378             SECURITY_ATTRIBUTES SecAttrs;
1379             PSECURITY_DESCRIPTOR Sd;
1380 
1381             DisableThreadLibraryCalls(hinstDLL);
1382 
1383             Err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPowerCfgSubKey, 0, KEY_READ, &hKey);
1384 
1385             if (Err != ERROR_SUCCESS)
1386             {
1387                 TRACE("Couldn't open registry key HKLM\\%s, using some sane(?) defaults\n", debugstr_w(szPowerCfgSubKey));
1388             }
1389             else
1390             {
1391                 WCHAR lpValue[MAX_PATH];
1392                 DWORD cbValue = sizeof(lpValue);
1393 
1394                 Err = RegQueryValueExW(hKey, szLastID, 0, 0, (BYTE*)lpValue, &cbValue);
1395                 if (Err == ERROR_SUCCESS)
1396                 {
1397                     g_LastID = _wtoi(lpValue);
1398                 }
1399                 else
1400                 {
1401                     TRACE("Couldn't open registry entry HKLM\\%s\\LastID, using some sane(?) defaults\n", debugstr_w(szPowerCfgSubKey));
1402                 }
1403                 RegCloseKey(hKey);
1404             }
1405 
1406             if (!CreatePowrProfSemaphoreSecurity(&Sd))
1407             {
1408                 ERR("Couldn't create POWRPROF semaphore security descriptor!\n");
1409                 return FALSE;
1410             }
1411 
1412             SecAttrs.nLength = sizeof(SECURITY_ATTRIBUTES);
1413             SecAttrs.lpSecurityDescriptor = Sd;
1414             SecAttrs.bInheritHandle = FALSE;
1415 
1416             PPRegSemaphore = CreateSemaphoreW(&SecAttrs, 1, 1, szSemaphoreName);
1417             HeapFree(GetProcessHeap(), 0, Sd);
1418             if (PPRegSemaphore == NULL)
1419             {
1420                 ERR("Couldn't create Semaphore: %d\n", GetLastError());
1421                 return FALSE;
1422             }
1423             break;
1424         }
1425         case DLL_PROCESS_DETACH:
1426             CloseHandle(PPRegSemaphore);
1427             break;
1428     }
1429     return TRUE;
1430 }
1431