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