[CMAKE]
[reactos.git] / 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 DWORD WINAPI PowerGetActiveScheme(HKEY UserRootPowerKey, GUID **polguid)
538 {
539 FIXME("(%p,%p) stub!\n", UserRootPowerKey, polguid);
540 return ERROR_CALL_NOT_IMPLEMENTED;
541 }
542
543 DWORD WINAPI PowerReadDCValue(HKEY RootPowerKey, const GUID *Scheme, const GUID *SubGroup, const GUID *PowerSettings, PULONG Type, PUCHAR Buffer, DWORD *BufferSize)
544 {
545 FIXME("(%p,%s,%s,%s,%p,%p,%p) stub!\n", RootPowerKey, debugstr_guid(Scheme), debugstr_guid(SubGroup), debugstr_guid(PowerSettings), Type, Buffer, BufferSize);
546 return ERROR_CALL_NOT_IMPLEMENTED;
547 }
548
549 BOOLEAN WINAPI
550 ReadGlobalPwrPolicy(PGLOBAL_POWER_POLICY pGlobalPowerPolicy)
551 {
552 GLOBAL_MACHINE_POWER_POLICY glMachPwrPolicy;
553 GLOBAL_USER_POWER_POLICY glUserPwrPolicy;
554 HKEY hKey;
555 DWORD dwSize;
556 LONG Err;
557
558 ReleaseSemaphore(PPRegSemaphore, 1, NULL);
559
560 // Getting user global power policy
561 Err = RegOpenKeyW(HKEY_CURRENT_USER, L"Control Panel\\PowerCfg\\GlobalPowerPolicy", &hKey);
562 if (Err != ERROR_SUCCESS)
563 {
564 ERR("RegOpenKeyW failed: %d\n", Err);
565 ReleaseSemaphore(PPRegSemaphore, 1, NULL);
566 SetLastError(Err);
567 return FALSE;
568 }
569
570 dwSize = sizeof(glUserPwrPolicy);
571 Err = RegQueryValueExW(hKey, L"Policies", NULL, NULL, (LPBYTE)&glUserPwrPolicy, &dwSize);
572 if (Err != ERROR_SUCCESS)
573 {
574 ERR("RegQueryValueExW failed: %d\n", Err);
575 ReleaseSemaphore(PPRegSemaphore, 1, NULL);
576 SetLastError(Err);
577 return FALSE;
578 }
579
580 RegCloseKey(hKey);
581
582 // Getting machine global power policy
583 Err = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\GlobalPowerPolicy", &hKey);
584 if (Err != ERROR_SUCCESS)
585 {
586 ERR("RegOpenKeyW failed: %d\n", Err);
587 ReleaseSemaphore(PPRegSemaphore, 1, NULL);
588 SetLastError(Err);
589 return FALSE;
590 }
591
592 dwSize = sizeof(glMachPwrPolicy);
593 Err = RegQueryValueExW(hKey, L"Policies", NULL, NULL, (LPBYTE)&glMachPwrPolicy, &dwSize);
594 if (Err != ERROR_SUCCESS)
595 {
596 ERR("RegQueryValueExW failed: %d\n", Err);
597 ReleaseSemaphore(PPRegSemaphore, 1, NULL);
598 SetLastError(Err);
599 return FALSE;
600 }
601
602 RegCloseKey(hKey);
603
604 memcpy(&pGlobalPowerPolicy->user, &glUserPwrPolicy, sizeof(GLOBAL_USER_POWER_POLICY));
605 memcpy(&pGlobalPowerPolicy->mach, &glMachPwrPolicy, sizeof(GLOBAL_MACHINE_POWER_POLICY));
606
607 ReleaseSemaphore(PPRegSemaphore, 1, NULL);
608 SetLastError(ERROR_SUCCESS);
609
610 return TRUE;
611 }
612
613
614 BOOLEAN WINAPI
615 ReadProcessorPwrScheme(UINT uiID,
616 PMACHINE_PROCESSOR_POWER_POLICY pMachineProcessorPowerPolicy)
617 {
618 HKEY hKey;
619 WCHAR szPath[MAX_PATH];
620 DWORD len=sizeof(MACHINE_PROCESSOR_POWER_POLICY);
621
622 swprintf(szPath, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\ProcessorPolicies\\%i", uiID);
623 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
624 szPath,
625 0,
626 KEY_ALL_ACCESS,
627 &hKey) == ERROR_SUCCESS)
628 {
629 if (RegQueryValueExW(hKey,szPolicies,NULL,0,(LPBYTE)pMachineProcessorPowerPolicy,&len) == ERROR_SUCCESS)
630 {
631 RegCloseKey(hKey);
632 return TRUE;
633 }
634 else
635 {
636 RegCloseKey(hKey);
637 if (uiID != 0)
638 {
639 return ReadProcessorPwrScheme(0,pMachineProcessorPowerPolicy);
640 }
641 else
642 {
643 return FALSE;
644 }
645 }
646 }
647 else
648 {
649 RegCloseKey(hKey);
650 return FALSE;
651 }
652 return FALSE;
653 }
654
655
656 BOOLEAN WINAPI
657 ReadPwrScheme(UINT uiID,
658 PPOWER_POLICY pPowerPolicy)
659 {
660 USER_POWER_POLICY userPwrPolicy;
661 MACHINE_POWER_POLICY machinePwrPolicy;
662 WCHAR szNum[3 + 1]; // max number - 999
663
664 ReleaseSemaphore(PPRegSemaphore, 1, NULL);
665
666 swprintf(szNum, L"%d", uiID);
667
668 if (!POWRPROF_GetUserPowerPolicy(szNum, &userPwrPolicy, 0, NULL, 0, NULL))
669 {
670 ReleaseSemaphore(PPRegSemaphore, 1, NULL);
671 return FALSE;
672 }
673
674 if (!POWRPROF_GetMachinePowerPolicy(szNum, &machinePwrPolicy))
675 {
676 ReleaseSemaphore(PPRegSemaphore, 1, NULL);
677 return FALSE;
678 }
679
680 memcpy(&pPowerPolicy->user, &userPwrPolicy, sizeof(USER_POWER_POLICY));
681 memcpy(&pPowerPolicy->mach, &machinePwrPolicy, sizeof(MACHINE_POWER_POLICY));
682
683 ReleaseSemaphore(PPRegSemaphore, 1, NULL);
684 SetLastError(ERROR_SUCCESS);
685
686 return TRUE;
687 }
688
689
690 BOOLEAN WINAPI
691 SetActivePwrScheme(UINT uiID,
692 PGLOBAL_POWER_POLICY lpGlobalPowerPolicy,
693 PPOWER_POLICY lpPowerPolicy)
694 {
695 POWER_POLICY tmp;
696 HKEY hKey;
697 WCHAR Buf[MAX_PATH];
698 BOOLEAN ret;
699
700 if (ReadPwrScheme(uiID,&tmp))
701 {
702 if (RegOpenKeyEx(HKEY_CURRENT_USER,szUserPowerConfigSubKey,0,KEY_ALL_ACCESS,&hKey) != ERROR_SUCCESS)
703 {
704 return FALSE;
705 }
706 swprintf(Buf,L"%i",uiID);
707
708 if (RegSetValueExW(hKey,szCurrentPowerPolicies,0,REG_SZ,(CONST BYTE *)Buf,strlenW(Buf)*sizeof(WCHAR)) == ERROR_SUCCESS)
709 {
710 RegCloseKey(hKey);
711 if ((lpGlobalPowerPolicy != NULL) || (lpPowerPolicy != NULL))
712 {
713 ret = ValidatePowerPolicies(lpGlobalPowerPolicy,lpPowerPolicy);
714 if (ret)
715 {
716 ret = TRUE;
717 if (lpGlobalPowerPolicy != NULL)
718 {
719 ret = WriteGlobalPwrPolicy(lpGlobalPowerPolicy);
720 }
721 if (ret && lpPowerPolicy != NULL)
722 {
723 ret = WritePwrPolicy(&uiID,lpPowerPolicy);
724 }
725 }
726 return ret;
727 }
728 else
729 {
730 return TRUE;
731 }
732 }
733 else
734 {
735 RegCloseKey(hKey);
736 return FALSE;
737 }
738 }
739 else
740 {
741 return FALSE;
742 }
743 }
744
745
746 BOOLEAN WINAPI
747 SetSuspendState(BOOLEAN Hibernate,
748 BOOLEAN ForceCritical,
749 BOOLEAN DisableWakeEvent)
750 {
751 FIXME("(%d, %d, %d) stub!\n", Hibernate, ForceCritical, DisableWakeEvent);
752 return TRUE;
753 }
754
755
756 BOOLEAN WINAPI
757 WriteGlobalPwrPolicy(PGLOBAL_POWER_POLICY pGlobalPowerPolicy)
758 {
759 HKEY hKey;
760 GLOBAL_USER_POWER_POLICY gupp;
761 GLOBAL_MACHINE_POWER_POLICY gmpp;
762
763 gupp = pGlobalPowerPolicy->user;
764 gmpp = pGlobalPowerPolicy->mach;
765
766 if (RegOpenKeyEx(HKEY_CURRENT_USER,
767 L"Control Panel\\PowerCfg\\GlobalPowerPolicy",
768 0,
769 KEY_ALL_ACCESS,
770 &hKey))
771 return FALSE;
772
773 if (RegSetValueExW(hKey,szPolicies,0,REG_BINARY,(const unsigned char *)&gupp,sizeof(GLOBAL_USER_POWER_POLICY)) == ERROR_SUCCESS)
774 {
775 RegCloseKey(hKey);
776
777 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
778 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\GlobalPowerPolicy",
779 0,
780 KEY_ALL_ACCESS,
781 &hKey))
782 return FALSE;
783
784 if (RegSetValueExW(hKey,szPolicies,0,REG_BINARY,(const unsigned char *)&gmpp,sizeof(GLOBAL_MACHINE_POWER_POLICY)) == ERROR_SUCCESS)
785 {
786 RegCloseKey(hKey);
787 return TRUE;
788 }
789 else
790 {
791 return FALSE;
792 }
793 }
794 else
795 {
796 RegCloseKey(hKey);
797 return FALSE;
798 }
799 }
800
801
802 BOOLEAN WINAPI
803 WriteProcessorPwrScheme(UINT ID,
804 PMACHINE_PROCESSOR_POWER_POLICY pMachineProcessorPowerPolicy)
805 {
806 WCHAR Buf[MAX_PATH];
807 HKEY hKey;
808
809 swprintf(Buf,L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\ProcessorPolicies\\%i",ID);
810
811 if (RegCreateKey(HKEY_LOCAL_MACHINE,Buf, &hKey) == ERROR_SUCCESS)
812 {
813 RegSetValueExW(hKey,szPolicies,0,REG_BINARY,(const unsigned char *)pMachineProcessorPowerPolicy,sizeof(MACHINE_PROCESSOR_POWER_POLICY));
814 RegCloseKey(hKey);
815 return TRUE;
816 }
817 else
818 {
819 return FALSE;
820 }
821 }
822
823 void SetLastID()
824 {
825 WCHAR Buf[MAX_PATH];
826 HKEY hKey;
827
828 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
829 szPowerCfgSubKey,
830 0,
831 KEY_WRITE,
832 &hKey) != ERROR_SUCCESS)
833 return;
834 swprintf(Buf,L"%i",g_LastID);
835 RegSetValueExW(hKey,szLastID,0,REG_SZ,(CONST BYTE *)Buf,strlenW(Buf)*sizeof(WCHAR));
836 RegCloseKey(hKey);
837 }
838
839 BOOLEAN WINAPI
840 WritePwrScheme(PUINT puiID,
841 LPWSTR lpszName,
842 LPWSTR lpszDescription,
843 PPOWER_POLICY pPowerPolicy)
844 {
845 WCHAR Buf[MAX_PATH];
846 HKEY hKey;
847
848 if (*puiID == -1)
849 {
850 g_LastID++;
851 *puiID = g_LastID;
852 SetLastID();
853 }
854
855 swprintf(Buf,L"Control Panel\\PowerCfg\\PowerPolicies\\%i",*puiID);
856
857 if (RegCreateKey(HKEY_CURRENT_USER,Buf,&hKey) == ERROR_SUCCESS)
858 {
859 RegSetValueExW(hKey,szName,0,REG_SZ,(const unsigned char *)lpszName,strlenW((const char *)lpszName)*sizeof(WCHAR));
860 RegSetValueExW(hKey,szDescription,0,REG_SZ,(const unsigned char *)lpszDescription,strlenW((const char *)lpszDescription)*sizeof(WCHAR));
861 RegCloseKey(hKey);
862 return WritePwrPolicy(puiID,pPowerPolicy);
863 }
864 else
865 {
866 return FALSE;
867 }
868 return FALSE;
869 }
870
871 BOOLEAN CheckPowerActionPolicy(PPOWER_ACTION_POLICY pPAP, SYSTEM_POWER_CAPABILITIES PowerCaps)
872 {
873 /*
874 Lohnegrim: this is an Helperfunction, it checks if the POWERACTIONPOLICY is valid
875 Also, if the System dosn't support Hipernation, then change the PowerAction
876 */
877 switch (pPAP->Action)
878 {
879 case PowerActionNone:
880 return TRUE;
881 case PowerActionReserved:
882 if (PowerCaps.SystemS1 || PowerCaps.SystemS2 || PowerCaps.SystemS3)
883 pPAP->Action = PowerActionSleep;
884 else
885 pPAP->Action = PowerActionReserved;
886 case PowerActionSleep:
887 return TRUE;
888 case PowerActionHibernate:
889 if (!(PowerCaps.SystemS4 && PowerCaps.HiberFilePresent))
890 {
891 if (PowerCaps.SystemS1 || PowerCaps.SystemS2 || PowerCaps.SystemS3)
892 pPAP->Action = PowerActionSleep;
893 else
894 pPAP->Action = PowerActionReserved;
895 }
896 case PowerActionShutdown:
897 case PowerActionShutdownReset:
898 case PowerActionShutdownOff:
899 case PowerActionWarmEject:
900 return TRUE;
901 default:
902 SetLastError(ERROR_INVALID_DATA);
903 return FALSE;
904 };
905 }
906
907 VOID FixSystemPowerState(PSYSTEM_POWER_STATE Psps, SYSTEM_POWER_CAPABILITIES PowerCaps)
908 {
909
910 //Lohnegrim: If the System dosn't support the Powerstates, then we have to change them
911 if (!PowerCaps.SystemS1 && *Psps == PowerSystemSleeping1)
912 *Psps = PowerSystemSleeping2;
913 if (!PowerCaps.SystemS2 && *Psps == PowerSystemSleeping2)
914 *Psps = PowerSystemSleeping3;
915 if (!PowerCaps.SystemS3 && *Psps == PowerSystemSleeping3)
916 *Psps = PowerSystemHibernate;
917 if (!(PowerCaps.SystemS4 && PowerCaps.HiberFilePresent) && *Psps == PowerSystemHibernate)
918 *Psps = PowerSystemSleeping2;
919 if (!PowerCaps.SystemS1 && *Psps == PowerSystemSleeping1)
920 *Psps = PowerSystemSleeping2;
921 if (!PowerCaps.SystemS2 && *Psps == PowerSystemSleeping2)
922 *Psps = PowerSystemSleeping3;
923 if (!PowerCaps.SystemS3 && *Psps == PowerSystemSleeping3)
924 *Psps = PowerSystemShutdown;
925
926 }
927
928
929 BOOLEAN WINAPI
930 ValidatePowerPolicies(PGLOBAL_POWER_POLICY pGPP, PPOWER_POLICY pPP)
931 {
932 SYSTEM_POWER_CAPABILITIES PowerCaps;
933 NTSTATUS ret;
934 BOOLEAN old;
935
936 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &old);
937 ret = NtPowerInformation(SystemPowerCapabilities, NULL, 0, &PowerCaps, sizeof(PowerCaps));
938 if (ret != STATUS_SUCCESS)
939 {
940 SetLastError(RtlNtStatusToDosError(ret));
941 return FALSE;
942 }
943
944 if (pGPP)
945 {
946 if (pGPP->user.Revision != 1 || pGPP->mach.Revision != 1)
947 {
948 SetLastError(ERROR_REVISION_MISMATCH);
949 return FALSE;
950 }
951 if (pGPP->mach.LidOpenWakeAc == PowerSystemUnspecified)
952 {
953 SetLastError(ERROR_GEN_FAILURE);
954 return FALSE;
955 }
956 if ((int)pGPP->mach.LidOpenWakeAc >= PowerSystemShutdown)
957 {
958 SetLastError(ERROR_GEN_FAILURE);
959 return FALSE;
960 }
961 if (pGPP->mach.LidOpenWakeDc < PowerSystemWorking)
962 {
963 SetLastError(ERROR_GEN_FAILURE);
964 return FALSE;
965 }
966 if ((int)pGPP->mach.LidOpenWakeDc >= PowerSystemShutdown)
967 {
968 SetLastError(ERROR_GEN_FAILURE);
969 return FALSE;
970 }
971 //Lohnegrim: unneeded
972 /*if ((pGPP->mach.LidOpenWakeDc < PowerSystemWorking) || (pGPP->mach.LidOpenWakeDc >= PowerSystemMaximum))
973 {
974 SetLastError(ERROR_GEN_FAILURE);
975 return FALSE;
976 }*/
977 if (!CheckPowerActionPolicy(&pGPP->user.LidCloseAc,PowerCaps))
978 {
979 return FALSE;
980 }
981 if (!CheckPowerActionPolicy(&pGPP->user.LidCloseDc,PowerCaps))
982 {
983 return FALSE;
984 }
985 if (!CheckPowerActionPolicy(&pGPP->user.PowerButtonAc,PowerCaps))
986 {
987 return FALSE;
988 }
989 if (!CheckPowerActionPolicy(&pGPP->user.PowerButtonDc,PowerCaps))
990 {
991 return FALSE;
992 }
993 if (!CheckPowerActionPolicy(&pGPP->user.SleepButtonAc,PowerCaps))
994 {
995 return FALSE;
996 }
997 if (!CheckPowerActionPolicy(&pGPP->user.SleepButtonDc,PowerCaps))
998 {
999 return FALSE;
1000 }
1001 //Lohnegrim: The BroadcastCapacityResolution presents the Powerlevel in Percent, if invalid set th 100 == FULL
1002 if ((pGPP->mach.BroadcastCapacityResolution < 0) || (pGPP->mach.BroadcastCapacityResolution > 100))
1003 pGPP->mach.BroadcastCapacityResolution=100;
1004
1005 //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
1006 //pGPP->user.DischargePolicy[1].PowerPolicy.EventCode = pGPP->user.DischargePolicy[1].PowerPolicy.EventCode | 0x010000;
1007 //pGPP->user.DischargePolicy[2].PowerPolicy.EventCode = pGPP->user.DischargePolicy[2].PowerPolicy.EventCode | 0x020000;
1008 //pGPP->user.DischargePolicy[3].PowerPolicy.EventCode = pGPP->user.DischargePolicy[3].PowerPolicy.EventCode | 0x030000;
1009
1010 FixSystemPowerState(&pGPP->mach.LidOpenWakeAc,PowerCaps);
1011 FixSystemPowerState(&pGPP->mach.LidOpenWakeDc,PowerCaps);
1012
1013 }
1014
1015 if (pPP)
1016 {
1017 if (pPP->user.Revision != 1 || pPP->mach.Revision != 1)
1018 {
1019 SetLastError(ERROR_REVISION_MISMATCH);
1020 return FALSE;
1021 }
1022
1023 //Lohnegrim: unneeded
1024 //if (pPP->mach.MinSleepAc < PowerSystemWorking)
1025 //{
1026 // SetLastError(ERROR_GEN_FAILURE);
1027 // return FALSE;
1028 //}
1029 if ((int)pPP->mach.MinSleepAc >= PowerSystemShutdown)
1030 {
1031 SetLastError(ERROR_GEN_FAILURE);
1032 return FALSE;
1033 }
1034 //Lohnegrim: unneeded
1035 //if (pPP->mach.MinSleepDc < PowerSystemWorking)
1036 //{
1037 // SetLastError(ERROR_GEN_FAILURE);
1038 // return FALSE;
1039 //}
1040 if ((int)pPP->mach.MinSleepDc >= PowerSystemShutdown)
1041 {
1042 SetLastError(ERROR_GEN_FAILURE);
1043 return FALSE;
1044 }
1045 if (pPP->mach.ReducedLatencySleepAc == PowerSystemUnspecified)
1046 {
1047 SetLastError(ERROR_GEN_FAILURE);
1048 return FALSE;
1049 }
1050 if ((int)pPP->mach.ReducedLatencySleepAc >= PowerSystemShutdown)
1051 {
1052 SetLastError(ERROR_GEN_FAILURE);
1053 return FALSE;
1054 }
1055 if (pPP->mach.ReducedLatencySleepDc < PowerSystemWorking)
1056 {
1057 SetLastError(ERROR_GEN_FAILURE);
1058 return FALSE;
1059 }
1060 if ((int)pPP->mach.ReducedLatencySleepDc >= PowerSystemShutdown)
1061 {
1062 SetLastError(ERROR_GEN_FAILURE);
1063 return FALSE;
1064 }
1065
1066 if (!CheckPowerActionPolicy(&pPP->mach.OverThrottledAc,PowerCaps))
1067 {
1068 return FALSE;
1069 }
1070 if (!CheckPowerActionPolicy(&pPP->mach.OverThrottledDc,PowerCaps))
1071 {
1072 return FALSE;
1073 }
1074 if (!CheckPowerActionPolicy(&pPP->user.IdleAc,PowerCaps))
1075 {
1076 return FALSE;
1077 }
1078 if (!CheckPowerActionPolicy(&pPP->user.IdleDc,PowerCaps))
1079 {
1080 return FALSE;
1081 }
1082 if (pPP->user.MaxSleepAc < PowerSystemWorking)
1083 {
1084 SetLastError(ERROR_GEN_FAILURE);
1085 return FALSE;
1086 }
1087 //Lohnegrim: unneeded
1088 /*if ((int)pPP->user.MaxSleepAc > PowerSystemShutdown)
1089 {
1090 SetLastError(ERROR_GEN_FAILURE);
1091 return FALSE;
1092 }*/
1093 if (pPP->user.MaxSleepDc < PowerSystemWorking)
1094 {
1095 SetLastError(ERROR_GEN_FAILURE);
1096 return FALSE;
1097 }
1098 //Lohnegrim: unneeded
1099 /*if ((int)pPP->user.MaxSleepDc >= PowerSystemShutdown)
1100 {
1101 SetLastError(ERROR_GEN_FAILURE);
1102 return FALSE;
1103 }*/
1104 if (PowerCaps.SystemS1)
1105 {
1106 pPP->mach.MinSleepAc=PowerSystemSleeping1;
1107 pPP->mach.MinSleepDc=PowerSystemSleeping1;
1108 }
1109 else if (PowerCaps.SystemS2)
1110 {
1111 pPP->mach.MinSleepAc=PowerSystemSleeping2;
1112 pPP->mach.MinSleepDc=PowerSystemSleeping2;
1113 }
1114 else if (PowerCaps.SystemS3)
1115 {
1116 pPP->mach.MinSleepAc=PowerSystemSleeping3;
1117 pPP->mach.MinSleepDc=PowerSystemSleeping3;
1118 }
1119
1120 if (PowerCaps.SystemS4)
1121 {
1122 pPP->user.MaxSleepAc=PowerSystemSleeping3;
1123 pPP->user.MaxSleepDc=PowerSystemSleeping3;
1124 }
1125 else if (PowerCaps.SystemS3)
1126 {
1127 pPP->user.MaxSleepAc=PowerSystemSleeping2;
1128 pPP->user.MaxSleepDc=PowerSystemSleeping2;
1129 }
1130 else if (PowerCaps.SystemS1)
1131 {
1132 pPP->user.MaxSleepAc=PowerSystemSleeping1;
1133 pPP->user.MaxSleepDc=PowerSystemSleeping1;
1134 }
1135 //Lohnegrim: I dont know where to get this info from, so i removed it
1136 //pPP->user.OptimizeForPowerAc=TRUE;
1137 //pPP->user.OptimizeForPowerDc=TRUE;
1138
1139 FixSystemPowerState(&pPP->mach.ReducedLatencySleepAc,PowerCaps);
1140 FixSystemPowerState(&pPP->mach.ReducedLatencySleepDc,PowerCaps);
1141 }
1142
1143 SetLastError(ERROR_SUCCESS);
1144 return TRUE;
1145 }
1146
1147 BOOLEAN WINAPI WritePwrPolicy(PUINT puiID, PPOWER_POLICY pPowerPolicy)
1148 {
1149
1150 WCHAR Buf[MAX_PATH];
1151 HKEY hKey;
1152
1153 swprintf(Buf,L"Control Panel\\PowerCfg\\PowerPolicies\\%i",*puiID);
1154
1155 if (RegCreateKey(HKEY_CURRENT_USER,Buf,&hKey) == ERROR_SUCCESS)
1156 {
1157 RegSetValueExW(hKey,szPolicies,0,REG_BINARY,(const unsigned char *)&pPowerPolicy->user,sizeof(USER_POWER_POLICY));
1158 RegCloseKey(hKey);
1159 swprintf(Buf,L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\PowerPolicies\\%i",*puiID);
1160
1161 if (RegCreateKey(HKEY_LOCAL_MACHINE,Buf,&hKey) == ERROR_SUCCESS)
1162 {
1163 RegSetValueExW(hKey,szPolicies,0,REG_BINARY,(const unsigned char *)&pPowerPolicy->mach,sizeof(MACHINE_POWER_POLICY));
1164 RegCloseKey(hKey);
1165 return TRUE;
1166 }
1167 else
1168 {
1169 return FALSE;
1170 }
1171 }
1172 else
1173 {
1174 return FALSE;
1175 }
1176 }
1177 BOOL WINAPI
1178 DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1179 {
1180 FIXME("(%p, %d, %p) not fully implemented\n", hinstDLL, fdwReason, lpvReserved);
1181
1182 switch(fdwReason)
1183 {
1184 case DLL_PROCESS_ATTACH:
1185 {
1186
1187 HKEY hKey;
1188 LONG r;
1189
1190 DisableThreadLibraryCalls(hinstDLL);
1191
1192 r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPowerCfgSubKey, 0, KEY_READ | KEY_WRITE, &hKey);
1193
1194 if (r != ERROR_SUCCESS)
1195 {
1196 TRACE("Couldn't open registry key HKLM\\%s, using some sane(?) defaults\n", debugstr_w(szPowerCfgSubKey));
1197 }
1198 else
1199 {
1200 WCHAR lpValue[MAX_PATH];
1201 DWORD cbValue = sizeof(lpValue);
1202 r = RegQueryValueExW(hKey, szLastID, 0, 0, (BYTE*)lpValue, &cbValue);
1203 if (r == ERROR_SUCCESS)
1204 {
1205 g_LastID = _wtoi(lpValue);
1206 }
1207 else
1208 {
1209 TRACE("Couldn't open registry entry HKLM\\%s\\LastID, using some sane(?) defaults\n", debugstr_w(szPowerCfgSubKey));
1210 }
1211 RegCloseKey(hKey);
1212 }
1213
1214 PPRegSemaphore = CreateSemaphoreW(NULL, 1, 1, szSemaphoreName);
1215 if (PPRegSemaphore == NULL)
1216 {
1217 ERR("Couldn't create Semaphore: %d\n", GetLastError());
1218 return FALSE;
1219 }
1220 break;
1221 }
1222 case DLL_PROCESS_DETACH:
1223 CloseHandle(PPRegSemaphore);
1224 break;
1225 }
1226 return TRUE;
1227 }