/*
 * Copyright (C) 2005 Benjamin Cutler
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */


#include <stdarg.h>

#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winnt.h"
#include "winreg.h"
#include "winternl.h"
#include "powrprof.h"
#include "wine/debug.h"
#include "wine/unicode.h"

WINE_DEFAULT_DEBUG_CHANNEL(powrprof);

/* Notes to implementors:
 * #1: The native implementation of these functions attempted to read in
 * registry entries that I was unable to locate on any of the Windows
 * machines I checked, but I only had desktops available, so maybe
 * laptop users will have better luck. They return FNF errors because
 * that's what the native DLL was returning during my tests.
 * #2: These functions call NtPowerInformation but I don't know what they
 * do with the results, and NtPowerInformation doesn't do much in WINE yet
 * anyway.
 * #3: Since I can't get several other functions working (see note #1),
 * implementing these functions is going to have to wait until somebody can
 * cobble together some sane test input. */

static const WCHAR szPowerCfgSubKey[] = { 'S', 'o', 'f', 't', 'w', 'a', 'r', 'e',
	'\\', 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\', 'W', 'i',
	'n', 'd', 'o', 'w', 's', '\\', 'C', 'u', 'r', 'r', 'e', 'n', 't',
	'V', 'e', 'r', 's', 'i', 'o', 'n', '\\', 'C', 'o', 'n', 't', 'r',
	'o', 'l', 's', ' ', 'F', 'o', 'l', 'd', 'e', 'r', '\\', 'P', 'o',
	'w', 'e', 'r', 'C', 'f', 'g', 0 };
static const WCHAR szSemaphoreName[] = { 'P', 'o', 'w', 'e', 'r', 'P', 'r', 'o',
	'f', 'i', 'l', 'e', 'R', 'e', 'g', 'i', 's', 't', 'r', 'y', 'S',
	'e', 'm', 'a', 'p', 'h', 'o', 'r', 'e', 0 };
static const WCHAR szDiskMax[] = { 'D', 'i', 's', 'k', 'S', 'p', 'i', 'n', 'd',
	'o', 'w', 'n', 'M', 'a', 'x', 0 };
static const WCHAR szDiskMin[] = { 'D', 'i', 's', 'k', 'S', 'p', 'i', 'n', 'd',
	'o', 'w', 'n', 'M', 'i', 'n', 0 };
static const WCHAR szLastID[] = { 'L', 'a', 's', 't', 'I', 'D', 0 };
static HANDLE PPRegSemaphore = NULL;

NTSTATUS WINAPI CallNtPowerInformation(
	POWER_INFORMATION_LEVEL InformationLevel,
	PVOID lpInputBuffer, ULONG nInputBufferSize,
	PVOID lpOutputBuffer, ULONG nOutputBufferSize)
{
   return NtPowerInformation(InformationLevel, lpInputBuffer,
      nInputBufferSize, lpOutputBuffer, nOutputBufferSize);
}

BOOLEAN WINAPI CanUserWritePwrScheme(VOID)
{
   HKEY hKey = NULL;
   LONG r;
   BOOLEAN bSuccess = TRUE;

   TRACE("()\n");

   r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPowerCfgSubKey, 0, KEY_READ | KEY_WRITE, &hKey);

   if (r != ERROR_SUCCESS) {
      TRACE("RegOpenKeyEx failed: %d\n", r);
      bSuccess = FALSE;
   }

   SetLastError(r);
   RegCloseKey(hKey);
   return bSuccess;
}

BOOLEAN WINAPI DeletePwrScheme(UINT uiIndex)
{
   /* FIXME: See note #1 */
   FIXME("(%d) stub!\n", uiIndex);
   SetLastError(ERROR_FILE_NOT_FOUND);
   return FALSE;
}

BOOLEAN WINAPI EnumPwrSchemes(PWRSCHEMESENUMPROC lpfnPwrSchemesEnumProc,
			LPARAM lParam)
{
   /* FIXME: See note #1 */
   FIXME("(%p, %ld) stub!\n", lpfnPwrSchemesEnumProc, lParam);
   SetLastError(ERROR_FILE_NOT_FOUND);
   return FALSE;
}

BOOLEAN WINAPI GetActivePwrScheme(PUINT puiID)
{
   /* FIXME: See note #1 */
   FIXME("(%p) stub!\n", puiID);
   SetLastError(ERROR_FILE_NOT_FOUND);
   return FALSE;
}

BOOLEAN WINAPI GetCurrentPowerPolicies(
	PGLOBAL_POWER_POLICY pGlobalPowerPolicy,
	PPOWER_POLICY pPowerPolicy)
{
   /* FIXME: See note #2 */
   SYSTEM_POWER_POLICY ACPower, DCPower;

   FIXME("(%p, %p) stub!\n", pGlobalPowerPolicy, pPowerPolicy);

   NtPowerInformation(SystemPowerPolicyAc, 0, 0, &ACPower, sizeof(SYSTEM_POWER_POLICY));
   NtPowerInformation(SystemPowerPolicyDc, 0, 0, &DCPower, sizeof(SYSTEM_POWER_POLICY));

   return FALSE;
}

BOOLEAN WINAPI GetPwrCapabilities(
	PSYSTEM_POWER_CAPABILITIES lpSystemPowerCapabilities)
{
   NTSTATUS r;

   TRACE("(%p)\n", lpSystemPowerCapabilities);

   r = NtPowerInformation(SystemPowerCapabilities, 0, 0, lpSystemPowerCapabilities, sizeof(SYSTEM_POWER_CAPABILITIES));

   SetLastError(RtlNtStatusToDosError(r));

   return r == STATUS_SUCCESS;
}

BOOLEAN WINAPI GetPwrDiskSpindownRange(PUINT RangeMax, PUINT RangeMin)
{
   HKEY hKey;
   BYTE lpValue[40];
   LONG r;
   DWORD cbValue = sizeof(lpValue);

   TRACE("(%p, %p)\n", RangeMax, RangeMin);

   if (RangeMax == NULL || RangeMin == NULL) {
      SetLastError(ERROR_INVALID_PARAMETER);
      return FALSE;
   }

   SetLastError(ERROR_SUCCESS);

   WaitForSingleObject(PPRegSemaphore, INFINITE);

   r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPowerCfgSubKey, 0, KEY_READ, &hKey);
   if (r != ERROR_SUCCESS) {
      TRACE("RegOpenKeyEx failed: %d\n", r);
      TRACE("Using defaults: 3600, 3\n");
      *RangeMax = 3600;
      *RangeMin = 3;
      ReleaseSemaphore(PPRegSemaphore, 1, NULL);
      return TRUE;
   }

   r = RegQueryValueExW(hKey, szDiskMax, 0, 0, lpValue, &cbValue);
   if (r != ERROR_SUCCESS) {
      TRACE("Couldn't open DiskSpinDownMax: %d\n", r);
      TRACE("Using default: 3600\n");
      *RangeMax = 3600;
   } else {
      *RangeMax = atoiW((LPCWSTR)lpValue);
   }

   cbValue = sizeof(lpValue);

   r = RegQueryValueExW(hKey, szDiskMin, 0, 0, lpValue, &cbValue);
   if (r != ERROR_SUCCESS) {
      TRACE("Couldn't open DiskSpinDownMin: %d\n", r);
      TRACE("Using default: 3\n");
      *RangeMin = 3;
   } else {
      *RangeMin = atoiW((LPCWSTR)lpValue);
   }

   RegCloseKey(hKey);

   ReleaseSemaphore(PPRegSemaphore, 1, NULL);

   return TRUE;
}

BOOLEAN WINAPI IsAdminOverrideActive(PADMINISTRATOR_POWER_POLICY p)
{
   FIXME("( %p) stub!\n", p);
   return FALSE;
}

BOOLEAN WINAPI IsPwrHibernateAllowed(VOID)
{
   SYSTEM_POWER_CAPABILITIES PowerCaps;
   NtPowerInformation(SystemPowerCapabilities, NULL, 0, &PowerCaps, sizeof(PowerCaps));
   return PowerCaps.SystemS4 && PowerCaps.HiberFilePresent;
}

BOOLEAN WINAPI IsPwrShutdownAllowed(VOID)
{
   SYSTEM_POWER_CAPABILITIES PowerCaps;
   NtPowerInformation(SystemPowerCapabilities, NULL, 0, &PowerCaps, sizeof(PowerCaps));
   return PowerCaps.SystemS5;
}

BOOLEAN WINAPI IsPwrSuspendAllowed(VOID)
{
   SYSTEM_POWER_CAPABILITIES PowerCaps;
   NtPowerInformation(SystemPowerCapabilities, NULL, 0, &PowerCaps, sizeof(PowerCaps));
   return PowerCaps.SystemS1 && PowerCaps.SystemS2 && PowerCaps.SystemS3;
}

BOOLEAN WINAPI ReadGlobalPwrPolicy(PGLOBAL_POWER_POLICY pGlobalPowerPolicy)
{
   /* FIXME: See note #1 */
   FIXME("(%p) stub!\n", pGlobalPowerPolicy);
   SetLastError(ERROR_FILE_NOT_FOUND);
   return FALSE;
}

BOOLEAN WINAPI ReadProcessorPwrScheme(UINT uiID,
			PMACHINE_PROCESSOR_POWER_POLICY pMachineProcessorPowerPolicy)
{
   /* FIXME: See note #1 */
   FIXME("(%d, %p) stub!\n", uiID, pMachineProcessorPowerPolicy);
   SetLastError(ERROR_FILE_NOT_FOUND);
   return FALSE;
}

BOOLEAN WINAPI ReadPwrScheme(UINT uiID,
	PPOWER_POLICY pPowerPolicy)
{
   /* FIXME: See note #1 */
   FIXME("(%d, %p) stub!\n", uiID, pPowerPolicy);
   SetLastError(ERROR_FILE_NOT_FOUND);
   return FALSE;
}

BOOLEAN WINAPI SetActivePwrScheme(UINT uiID,
	PGLOBAL_POWER_POLICY lpGlobalPowerPolicy,
	PPOWER_POLICY lpPowerPolicy)
{
   /* FIXME: See note #1 */
   FIXME("(%d, %p, %p) stub!\n", uiID, lpGlobalPowerPolicy, lpPowerPolicy);
   SetLastError(ERROR_FILE_NOT_FOUND);
   return FALSE;
}

BOOLEAN WINAPI SetSuspendState(BOOLEAN Hibernate, BOOLEAN ForceCritical,
	BOOLEAN DisableWakeEvent)
{
   /* FIXME: I have NO idea how you're supposed to call NtInitiatePowerAction
    * here, because it's not a documented function that I can find */
   FIXME("(%d, %d, %d) stub!\n", Hibernate, ForceCritical, DisableWakeEvent);
   return TRUE;
}

BOOLEAN WINAPI WriteGlobalPwrPolicy(PGLOBAL_POWER_POLICY pGlobalPowerPolicy)
{
   /* FIXME: See note #3 */
   FIXME("(%p) stub!\n", pGlobalPowerPolicy);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
}

BOOLEAN WINAPI WriteProcessorPwrScheme(UINT ID,
	PMACHINE_PROCESSOR_POWER_POLICY pMachineProcessorPowerPolicy)
{
   /* FIXME: See note #3 */
   FIXME("(%d, %p) stub!\n", ID, pMachineProcessorPowerPolicy);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
}

BOOLEAN WINAPI WritePwrScheme(PUINT puiID, LPWSTR lpszName, LPWSTR lpszDescription,
	PPOWER_POLICY pPowerPolicy)
{
   /* FIXME: See note #3 */
   FIXME("(%p, %s, %s, %p) stub!\n", puiID, debugstr_w(lpszName), debugstr_w(lpszDescription), pPowerPolicy);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
}

DWORD WINAPI PowerGetActiveScheme(HKEY UserRootPowerKey, GUID **polguid)
{
   FIXME("(%p,%p) stub!\n", UserRootPowerKey, polguid);
   return ERROR_CALL_NOT_IMPLEMENTED;
}

DWORD WINAPI PowerReadDCValue(HKEY RootPowerKey, const GUID *Scheme, const GUID *SubGroup, const GUID *PowerSettings, PULONG Type, PUCHAR Buffer, DWORD *BufferSize)
{
   FIXME("(%p,%s,%s,%s,%p,%p,%p) stub!\n", RootPowerKey, debugstr_guid(Scheme), debugstr_guid(SubGroup), debugstr_guid(PowerSettings), Type, Buffer, BufferSize);
   return ERROR_CALL_NOT_IMPLEMENTED;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
   switch(fdwReason) {
      case DLL_PROCESS_ATTACH: {

         HKEY hKey;
         LONG r;

         DisableThreadLibraryCalls(hinstDLL);

         r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPowerCfgSubKey, 0, KEY_READ | KEY_WRITE, &hKey);

         if (r != ERROR_SUCCESS) {
            TRACE("Couldn't open registry key HKLM\\%s, using some sane(?) defaults\n", debugstr_w(szPowerCfgSubKey));
         } else {
            BYTE lpValue[40];
            DWORD cbValue = sizeof(lpValue);
            r = RegQueryValueExW(hKey, szLastID, 0, 0, lpValue, &cbValue);
            if (r != ERROR_SUCCESS) {
               TRACE("Couldn't open registry entry HKLM\\%s\\LastID, using some sane(?) defaults\n", debugstr_w(szPowerCfgSubKey));
            }
            RegCloseKey(hKey);
         }

         PPRegSemaphore = CreateSemaphoreW(NULL, 1, 1, szSemaphoreName);
         if (PPRegSemaphore == NULL) {
            ERR("Couldn't create Semaphore: %d\n", GetLastError());
            return FALSE;
         }
         break;
      }
      case DLL_PROCESS_DETACH:
         if (lpvReserved) break;
         CloseHandle(PPRegSemaphore);
         break;
    }
    return TRUE;
}
