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