1 /* 2 * Copyright (C) 2005 Benjamin Cutler 3 * Copyright (C) 2008 Dmitry Chapyshev 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20 21 #include <stdarg.h> 22 23 #define WIN32_NO_STATUS 24 #include <windef.h> 25 #include <winbase.h> 26 #include <winreg.h> 27 #define NTOS_MODE_USER 28 #include <ndk/pofuncs.h> 29 #include <ndk/rtlfuncs.h> 30 #include <ndk/setypes.h> 31 #include <powrprof.h> 32 #include <wine/debug.h> 33 #include <wine/unicode.h> 34 35 WINE_DEFAULT_DEBUG_CHANNEL(powrprof); 36 37 38 static const WCHAR szPowerCfgSubKey[] = 39 L"Software\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg"; 40 static const WCHAR szUserPowerConfigSubKey[] = 41 L"Control Panel\\PowerCfg"; 42 static const WCHAR szCurrentPowerPolicies[] = 43 L"CurrentPowerPolicy"; 44 static const WCHAR szPolicies[] = L"Policies"; 45 static const WCHAR szName[] = L"Name"; 46 static const WCHAR szDescription[] = L"Description"; 47 static const WCHAR szSemaphoreName[] = L"PowerProfileRegistrySemaphore"; 48 static const WCHAR szDiskMax[] = L"DiskSpindownMax"; 49 static const WCHAR szDiskMin[] = L"DiskSpindownMin"; 50 static const WCHAR szLastID[] = L"LastID"; 51 52 UINT g_LastID = (UINT)-1; 53 54 BOOLEAN WINAPI WritePwrPolicy(PUINT puiID, PPOWER_POLICY pPowerPolicy); 55 56 HANDLE PPRegSemaphore = NULL; 57 58 NTSTATUS WINAPI 59 CallNtPowerInformation(POWER_INFORMATION_LEVEL InformationLevel, 60 PVOID lpInputBuffer, 61 ULONG nInputBufferSize, 62 PVOID lpOutputBuffer, 63 ULONG nOutputBufferSize) 64 { 65 BOOLEAN old; 66 67 //Lohnegrim: In order to get the right results, we have to adjust our Privileges 68 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &old); 69 RtlAdjustPrivilege(SE_CREATE_PAGEFILE_PRIVILEGE, TRUE, FALSE, &old); 70 71 return NtPowerInformation(InformationLevel, 72 lpInputBuffer, 73 nInputBufferSize, 74 lpOutputBuffer, 75 nOutputBufferSize); 76 } 77 78 BOOLEAN WINAPI 79 CanUserWritePwrScheme(VOID) 80 { 81 HKEY hKey = NULL; 82 LONG Ret; 83 84 TRACE("()\n"); 85 86 Ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPowerCfgSubKey, 0, KEY_READ | KEY_WRITE, &hKey); 87 if (Ret != ERROR_SUCCESS) 88 { 89 TRACE("RegOpenKeyEx failed: %d\n", Ret); 90 SetLastError(Ret); 91 return FALSE; 92 } 93 94 RegCloseKey(hKey); 95 return TRUE; 96 } 97 98 BOOLEAN WINAPI 99 DeletePwrScheme(UINT uiIndex) 100 { 101 WCHAR Buf[MAX_PATH]; 102 UINT Current; 103 LONG Err; 104 105 swprintf(Buf, L"Control Panel\\PowerCfg\\PowerPolicies\\%d", uiIndex); 106 107 if (!GetActivePwrScheme(&Current)) 108 return FALSE; 109 110 if (Current == uiIndex) 111 { 112 SetLastError(ERROR_ACCESS_DENIED); 113 return FALSE; 114 } 115 116 Err = RegDeleteKey(HKEY_CURRENT_USER, (LPCTSTR)Buf); 117 if (Err != ERROR_SUCCESS) 118 { 119 TRACE("RegDeleteKey failed: %d\n", Err); 120 SetLastError(Err); 121 return FALSE; 122 } 123 124 return TRUE; 125 } 126 127 static BOOLEAN 128 POWRPROF_GetUserPowerPolicy(LPWSTR szNum, 129 PUSER_POWER_POLICY puserPwrPolicy, 130 DWORD cchName, LPWSTR szName, 131 DWORD cchDesc, LPWSTR szDesc) 132 { 133 HKEY hSubKey = NULL; 134 DWORD dwSize; 135 LONG Err; 136 WCHAR szPath[MAX_PATH]; 137 BOOL bRet = FALSE; 138 139 swprintf(szPath, L"Control Panel\\PowerCfg\\PowerPolicies\\%s", szNum); 140 141 Err = RegOpenKeyExW(HKEY_CURRENT_USER, szPath, 0, KEY_READ, &hSubKey); 142 if (Err != ERROR_SUCCESS) 143 { 144 ERR("RegOpenKeyExW failed: %d\n", Err); 145 SetLastError(Err); 146 return FALSE; 147 } 148 149 dwSize = cchName * sizeof(WCHAR); 150 Err = RegQueryValueExW(hSubKey, L"Name", NULL, NULL, (LPBYTE)szName, &dwSize); 151 if (Err != ERROR_SUCCESS) 152 { 153 ERR("RegQueryValueExW failed: %d\n", Err); 154 SetLastError(Err); 155 goto cleanup; 156 } 157 158 dwSize = cchDesc * sizeof(WCHAR); 159 Err = RegQueryValueExW(hSubKey, L"Description", NULL, NULL, (LPBYTE)szDesc, &dwSize); 160 if (Err != ERROR_SUCCESS) 161 { 162 ERR("RegQueryValueExW failed: %d\n", Err); 163 SetLastError(Err); 164 goto cleanup; 165 } 166 167 dwSize = sizeof(USER_POWER_POLICY); 168 Err = RegQueryValueExW(hSubKey, L"Policies", NULL, NULL, (LPBYTE)puserPwrPolicy, &dwSize); 169 if (Err != ERROR_SUCCESS) 170 { 171 ERR("RegQueryValueExW failed: %d\n", Err); 172 SetLastError(Err); 173 goto cleanup; 174 } 175 176 bRet = TRUE; 177 178 cleanup: 179 RegCloseKey(hSubKey); 180 181 return bRet; 182 } 183 184 static BOOLEAN 185 POWRPROF_GetMachinePowerPolicy(LPWSTR szNum, PMACHINE_POWER_POLICY pmachinePwrPolicy) 186 { 187 HKEY hKey; 188 LONG Err; 189 WCHAR szPath[MAX_PATH]; 190 DWORD dwSize; 191 192 swprintf(szPath, L"Software\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg\\PowerPolicies\\%s", szNum); 193 194 Err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPath, 0, KEY_READ, &hKey); 195 if (Err != ERROR_SUCCESS) 196 { 197 ERR("RegOpenKeyExW failed: %d\n", Err); 198 SetLastError(Err); 199 return FALSE; 200 } 201 202 dwSize = sizeof(MACHINE_POWER_POLICY); 203 Err = RegQueryValueExW(hKey, L"Policies", NULL, NULL, (LPBYTE)pmachinePwrPolicy, &dwSize); 204 205 if (Err != ERROR_SUCCESS) 206 { 207 ERR("RegQueryValueExW failed: %d\n", Err); 208 SetLastError(Err); 209 RegCloseKey(hKey); 210 return FALSE; 211 } 212 213 RegCloseKey(hKey); 214 215 return TRUE; 216 } 217 218 BOOLEAN WINAPI 219 EnumPwrSchemes(PWRSCHEMESENUMPROC lpfnPwrSchemesEnumProc, 220 LPARAM lParam) 221 { 222 HKEY hKey; 223 LONG Err; 224 DWORD dwSize, dwNameSize = MAX_PATH, dwDescSize = MAX_PATH, dwIndex = 0; 225 WCHAR szNum[3 + 1], szName[MAX_PATH], szDesc[MAX_PATH]; 226 POWER_POLICY PwrPolicy; 227 USER_POWER_POLICY userPwrPolicy; 228 MACHINE_POWER_POLICY machinePwrPolicy; 229 BOOLEAN bRet = FALSE; 230 231 if (!lpfnPwrSchemesEnumProc) 232 { 233 SetLastError(ERROR_INVALID_PARAMETER); 234 return FALSE; 235 } 236 237 Err = RegOpenKeyExW(HKEY_CURRENT_USER, L"Control Panel\\PowerCfg\\PowerPolicies", 0, KEY_READ, &hKey); 238 if (Err != ERROR_SUCCESS) 239 { 240 ERR("RegOpenKeyW failed: %d\n", Err); 241 SetLastError(Err); 242 return FALSE; 243 } 244 245 ReleaseSemaphore(PPRegSemaphore, 1, NULL); 246 247 dwSize = sizeof(szNum) / sizeof(WCHAR); 248 249 while (RegEnumKeyExW(hKey, dwIndex, szNum, &dwSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) 250 { 251 if (!POWRPROF_GetUserPowerPolicy(szNum, &userPwrPolicy, 252 dwNameSize, szName, 253 dwDescSize, szDesc)) 254 { 255 WARN("POWRPROF_GetUserPowerPolicy failed\n"); 256 goto cleanup; 257 } 258 259 if (!POWRPROF_GetMachinePowerPolicy(szNum, &machinePwrPolicy)) 260 { 261 WARN("POWRPROF_GetMachinePowerPolicy failed\n"); 262 goto cleanup; 263 } 264 265 memcpy(&PwrPolicy.user, &userPwrPolicy, sizeof(USER_POWER_POLICY)); 266 memcpy(&PwrPolicy.mach, &machinePwrPolicy, sizeof(MACHINE_POWER_POLICY)); 267 268 if (!lpfnPwrSchemesEnumProc(_wtoi(szNum), (wcslen(szName) + 1) * sizeof(WCHAR), szName, (wcslen(szDesc) + 1) * sizeof(WCHAR), szDesc, &PwrPolicy, lParam)) 269 goto cleanup; 270 else 271 bRet = TRUE; 272 273 dwSize = sizeof(szNum) / sizeof(WCHAR); 274 dwIndex++; 275 } 276 277 cleanup: 278 RegCloseKey(hKey); 279 ReleaseSemaphore(PPRegSemaphore, 1, NULL); 280 281 return bRet; 282 } 283 284 BOOLEAN WINAPI 285 GetActivePwrScheme(PUINT puiID) 286 { 287 HKEY hKey; 288 WCHAR szBuf[MAX_PATH]; 289 DWORD dwSize; 290 LONG Err; 291 292 TRACE("GetActivePwrScheme(%u)", puiID); 293 294 Err = RegOpenKeyExW(HKEY_CURRENT_USER, L"Control Panel\\PowerCfg", 0, KEY_READ, &hKey); 295 if (Err != ERROR_SUCCESS) 296 { 297 ERR("RegOpenKey failed: %d\n", Err); 298 SetLastError(Err); 299 return FALSE; 300 } 301 302 dwSize = sizeof(szBuf); 303 Err = RegQueryValueExW(hKey, L"CurrentPowerPolicy", 304 NULL, NULL, 305 (LPBYTE)&szBuf, &dwSize); 306 if (Err != ERROR_SUCCESS) 307 { 308 ERR("RegQueryValueEx failed: %d\n", Err); 309 RegCloseKey(hKey); 310 SetLastError(Err); 311 return FALSE; 312 } 313 314 RegCloseKey(hKey); 315 *puiID = _wtoi(szBuf); 316 317 return TRUE; 318 } 319 320 BOOLEAN WINAPI 321 GetCurrentPowerPolicies(PGLOBAL_POWER_POLICY pGlobalPowerPolicy, 322 PPOWER_POLICY pPowerPolicy) 323 { 324 /* 325 SYSTEM_POWER_POLICY ACPower, DCPower; 326 327 FIXME("(%p, %p) stub!\n", pGlobalPowerPolicy, pPowerPolicy); 328 329 NtPowerInformation(SystemPowerPolicyAc, 0, 0, &ACPower, sizeof(SYSTEM_POWER_POLICY)); 330 NtPowerInformation(SystemPowerPolicyDc, 0, 0, &DCPower, sizeof(SYSTEM_POWER_POLICY)); 331 332 return FALSE; 333 */ 334 /* 335 Lohnegrim: I don't know why this Function should call NtPowerInformation, because as far as I know, 336 it simply returns the GlobalPowerPolicy and the AktivPowerScheme! 337 */ 338 UINT uiID; 339 340 if (pGlobalPowerPolicy != NULL) 341 { 342 if (!ReadGlobalPwrPolicy(pGlobalPowerPolicy)) 343 return FALSE; 344 } 345 if (pPowerPolicy != NULL) 346 { 347 if (!GetActivePwrScheme(&uiID)) 348 return FALSE; 349 350 if (!ReadPwrScheme(uiID, pPowerPolicy)) 351 return FALSE; 352 } 353 354 return TRUE; 355 } 356 357 BOOLEAN WINAPI 358 GetPwrCapabilities(PSYSTEM_POWER_CAPABILITIES lpSystemPowerCapabilities) 359 { 360 NTSTATUS Status; 361 362 TRACE("(%p)\n", lpSystemPowerCapabilities); 363 364 if (!lpSystemPowerCapabilities) 365 { 366 SetLastError(ERROR_INVALID_PARAMETER); 367 return FALSE; 368 } 369 370 Status = NtPowerInformation(SystemPowerCapabilities, 0, 0, lpSystemPowerCapabilities, sizeof(SYSTEM_POWER_CAPABILITIES)); 371 if(!NT_SUCCESS(Status)) 372 { 373 SetLastError(RtlNtStatusToDosError(Status)); 374 return FALSE; 375 } 376 377 return TRUE; 378 } 379 380 BOOLEAN WINAPI 381 GetPwrDiskSpindownRange(PUINT RangeMax, PUINT RangeMin) 382 { 383 HKEY hKey; 384 BYTE lpValue[40]; 385 LONG Ret; 386 DWORD cbValue = sizeof(lpValue); 387 388 TRACE("(%p, %p)\n", RangeMax, RangeMin); 389 390 if (RangeMax == NULL || RangeMin == NULL) 391 { 392 SetLastError(ERROR_INVALID_PARAMETER); 393 return FALSE; 394 } 395 396 WaitForSingleObject(PPRegSemaphore, INFINITE); 397 398 Ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPowerCfgSubKey, 0, KEY_READ, &hKey); 399 if (Ret != ERROR_SUCCESS) 400 { 401 TRACE("RegOpenKeyEx failed: %d\n", Ret); 402 TRACE("Using defaults: 3600, 3\n"); 403 *RangeMax = 3600; 404 *RangeMin = 3; 405 ReleaseSemaphore(PPRegSemaphore, 1, NULL); 406 return TRUE; 407 } 408 409 Ret = RegQueryValueExW(hKey, szDiskMax, 0, 0, lpValue, &cbValue); 410 if (Ret != ERROR_SUCCESS) 411 { 412 TRACE("Couldn't open DiskSpinDownMax: %d\n", Ret); 413 TRACE("Using default: 3600\n"); 414 *RangeMax = 3600; 415 } 416 else 417 { 418 *RangeMax = _wtoi((LPCWSTR)lpValue); 419 } 420 421 cbValue = sizeof(lpValue); 422 423 Ret = RegQueryValueExW(hKey, szDiskMin, 0, 0, lpValue, &cbValue); 424 if (Ret != ERROR_SUCCESS) 425 { 426 TRACE("Couldn't open DiskSpinDownMin: %d\n", Ret); 427 TRACE("Using default: 3\n"); 428 *RangeMin = 3; 429 } 430 else 431 { 432 *RangeMin = _wtoi((LPCWSTR)lpValue); 433 } 434 435 RegCloseKey(hKey); 436 437 ReleaseSemaphore(PPRegSemaphore, 1, NULL); 438 439 return TRUE; 440 } 441 442 BOOLEAN WINAPI 443 IsAdminOverrideActive(PADMINISTRATOR_POWER_POLICY p) 444 { 445 FIXME("( %p) stub!\n", p); 446 return FALSE; 447 } 448 449 BOOLEAN WINAPI 450 IsPwrHibernateAllowed(VOID) 451 { 452 SYSTEM_POWER_CAPABILITIES PowerCaps; 453 NTSTATUS Status; 454 BOOLEAN old; 455 456 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &old); 457 458 Status = NtPowerInformation(SystemPowerCapabilities, NULL, 0, &PowerCaps, sizeof(PowerCaps)); 459 if (!NT_SUCCESS(Status)) 460 { 461 SetLastError(RtlNtStatusToDosError(Status)); 462 return FALSE; 463 } 464 465 return PowerCaps.SystemS4 && PowerCaps.HiberFilePresent; // IsHiberfilPresent(); 466 } 467 468 BOOLEAN WINAPI 469 IsPwrShutdownAllowed(VOID) 470 { 471 SYSTEM_POWER_CAPABILITIES PowerCaps; 472 NTSTATUS Status; 473 BOOLEAN old; 474 475 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &old); 476 477 Status = NtPowerInformation(SystemPowerCapabilities, NULL, 0, &PowerCaps, sizeof(PowerCaps)); 478 if (!NT_SUCCESS(Status)) 479 { 480 SetLastError(RtlNtStatusToDosError(Status)); 481 return FALSE; 482 } 483 484 return PowerCaps.SystemS5; 485 } 486 487 BOOLEAN WINAPI 488 IsPwrSuspendAllowed(VOID) 489 { 490 SYSTEM_POWER_CAPABILITIES PowerCaps; 491 NTSTATUS Status; 492 BOOLEAN old; 493 494 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &old); 495 496 Status = NtPowerInformation(SystemPowerCapabilities, NULL, 0, &PowerCaps, sizeof(PowerCaps)); 497 if (!NT_SUCCESS(Status)) 498 { 499 SetLastError(RtlNtStatusToDosError(Status)); 500 return FALSE; 501 } 502 503 return PowerCaps.SystemS1 || PowerCaps.SystemS2 || PowerCaps.SystemS3; 504 } 505 506 DWORD WINAPI 507 PowerGetActiveScheme(HKEY UserRootPowerKey, GUID **polguid) 508 { 509 FIXME("(%p,%p) stub!\n", UserRootPowerKey, polguid); 510 return ERROR_CALL_NOT_IMPLEMENTED; 511 } 512 513 DWORD WINAPI 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 Helper function, it checks if the POWERACTIONPOLICY is valid 797 Also, if the System doesn't support Hibernation, 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 doesn'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 > 100) 924 pGPP->mach.BroadcastCapacityResolution = 100; 925 926 //Lohnegrim: I have no idea, if they are really needed, or if they are specific for my System, or what they mean, so I removed them 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 ((int)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 ((int)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 don't 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 } 1141