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