0ad/source/lib/sysdep/win/win_internal.h

503 lines
15 KiB
C
Raw Normal View History

/**
* =========================================================================
* File : win_internal.h
* Project : 0 A.D.
* Description : shared (private) header for Windows-specific code.
*
* @author Jan.Wassenberg@stud.uni-karlsruhe.de
* =========================================================================
*/
/*
* Copyright (c) 2002-2005 Jan Wassenberg
*
* Redistribution and/or modification are also permitted under the
* terms of the GNU General Public License as published by the
* Free Software Foundation (version 2 or later, at your option).
*
* This program 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.
*/
#ifndef WIN_INTERNAL_H
#define WIN_INTERNAL_H
#if !OS_WIN
#error "win_internal.h: do not include if not compiling for Windows"
#endif
#include "lib/lib.h" // BIT
#if MSC_VERSION >= 1400 // hide "pragma region" from VS2003
#pragma region WindowsHeaderAndFixes
#endif
// Win32 socket declarations aren't portable (e.g. problems with socklen_t)
// => skip winsock.h; posix_sock.h should be used instead.
#define _WINSOCKAPI_
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
// the public header, win.h, has defined _WINDOWS_ so that
// other code doesn't include <windows.h> when it shouldn't (e.g. zconf.h)
#undef _WINDOWS_
// set version; needed for EnumDisplayDevices
#define _WIN32_WINNT 0x0501
#define NOGDICAPMASKS // CC_*, LC_*, PC_*, CP_*, TC_*, RC_
//#define NOVIRTUALKEYCODES // VK_*
//#define NOWINMESSAGES // WM_*, EM_*, LB_*, CB_*
//#define NOWINSTYLES // WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_*
//#define NOSYSMETRICS // SM_*
#define NOMENUS // MF_*
//#define NOICONS // IDI_*
#define NOKEYSTATES // MK_*
//#define NOSYSCOMMANDS // SC_*
#define NORASTEROPS // Binary and Tertiary raster ops
//#define NOSHOWWINDOW // SW_*
#define OEMRESOURCE // OEM Resource values
#define NOATOM // Atom Manager routines
//#define NOCLIPBOARD // Clipboard routines
//#define NOCOLOR // Screen colors
//#define NOCTLMGR // Control and Dialog routines
#define NODRAWTEXT // DrawText() and DT_*
//#define NOGDI // All GDI defines and routines
//#define NOKERNEL // All KERNEL defines and routines
//#define NOUSER // All USER defines and routines
#define NONLS // All NLS defines and routines
//#define NOMB // MB_* and MessageBox()
#define NOMEMMGR // GMEM_*, LMEM_*, GHND, LHND, associated routines
#define NOMETAFILE // typedef METAFILEPICT
#define NOMINMAX // Macros min(a,b) and max(a,b)
//#define NOMSG // typedef MSG and associated routines
#define NOOPENFILE // OpenFile(), OemToAnsi, AnsiToOem, and OF_*
#define NOSCROLL // SB_* and scrolling routines
#define NOSERVICE // All Service Controller routines, SERVICE_ equates, etc.
//#define NOSOUND // Sound driver routines
#define NOTEXTMETRIC // typedef TEXTMETRIC and associated routines
//#define NOWH // SetWindowsHook and WH_*
//#define NOWINOFFSETS // GWL_*, GCL_*, associated routines
//#define NOCOMM // COMM driver routines
#define NOKANJI // Kanji support stuff.
#define NOHELP // Help engine interface.
#define NOPROFILER // Profiler interface.
#define NODEFERWINDOWPOS // DeferWindowPos routines
#define NOMCX // Modem Configuration Extensions
#include <windows.h>
///////////////////////////////////////////////////////////////////////////////
//
// fixes for VC6 platform SDK
//
///////////////////////////////////////////////////////////////////////////////
// VC6 windows.h doesn't define these
#ifndef DWORD_PTR
#define DWORD_PTR DWORD
#endif
#ifndef INVALID_FILE_ATTRIBUTES
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#endif
#ifndef PROCESSOR_ARCHITECTURE_AMD64
#define PROCESSOR_ARCHITECTURE_AMD64 9
#endif
#if WINVER < 0x500
// can't test for macro definition -
// actual definitions in winnt.h are typedefs.
typedef unsigned __int64 DWORDLONG;
typedef DWORD ULONG_PTR;
typedef struct _MEMORYSTATUSEX
{
DWORD dwLength;
DWORD dwMemoryLoad;
DWORDLONG ullTotalPhys;
DWORDLONG ullAvailPhys;
DWORDLONG ullTotalPageFile;
DWORDLONG ullAvailPageFile;
DWORDLONG ullTotalVirtual;
DWORDLONG ullAvailVirtual;
DWORDLONG ullAvailExtendedVirtual;
} MEMORYSTATUSEX, *LPMEMORYSTATUSEX;
#endif // #if WINVER < 0x500
///////////////////////////////////////////////////////////////////////////////
//
// powrprof.h (not there at all in VC6, missing some parts in VC7)
//
///////////////////////////////////////////////////////////////////////////////
// MinGW headers are already correct; only change on VC
#if MSC_VERSION
2005-02-26 16:14:55 +01:00
#ifndef NTSTATUS
#define NTSTATUS long
#endif
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS 0
#endif
#if WINVER < 0x500
typedef enum {
SystemPowerPolicyAc,
SystemPowerPolicyDc,
VerifySystemPolicyAc,
VerifySystemPolicyDc,
SystemPowerCapabilities,
SystemBatteryState,
SystemPowerStateHandler,
ProcessorStateHandler,
SystemPowerPolicyCurrent,
AdministratorPowerPolicy,
SystemReserveHiberFile,
ProcessorInformation,
SystemPowerInformation,
ProcessorStateHandler2,
LastWakeTime, // Compare with KeQueryInterruptTime()
LastSleepTime, // Compare with KeQueryInterruptTime()
SystemExecutionState,
SystemPowerStateNotifyHandler,
ProcessorPowerPolicyAc,
ProcessorPowerPolicyDc,
VerifyProcessorPowerPolicyAc,
VerifyProcessorPowerPolicyDc,
ProcessorPowerPolicyCurrent,
SystemPowerStateLogging,
SystemPowerLoggingEntry
} POWER_INFORMATION_LEVEL;
typedef struct {
DWORD Granularity;
DWORD Capacity;
} BATTERY_REPORTING_SCALE, *PBATTERY_REPORTING_SCALE;
typedef enum _SYSTEM_POWER_STATE {
PowerSystemUnspecified = 0,
PowerSystemWorking = 1,
PowerSystemSleeping1 = 2,
PowerSystemSleeping2 = 3,
PowerSystemSleeping3 = 4,
PowerSystemHibernate = 5,
PowerSystemShutdown = 6,
PowerSystemMaximum = 7
} SYSTEM_POWER_STATE, *PSYSTEM_POWER_STATE;
typedef struct {
// Misc supported system features
BOOLEAN PowerButtonPresent;
BOOLEAN SleepButtonPresent;
BOOLEAN LidPresent;
BOOLEAN SystemS1;
BOOLEAN SystemS2;
BOOLEAN SystemS3;
BOOLEAN SystemS4; // hibernate
BOOLEAN SystemS5; // off
BOOLEAN HiberFilePresent;
BOOLEAN FullWake;
BOOLEAN VideoDimPresent;
BOOLEAN ApmPresent;
BOOLEAN UpsPresent;
// Processors
BOOLEAN ThermalControl;
BOOLEAN ProcessorThrottle;
BYTE ProcessorMinThrottle;
BYTE ProcessorMaxThrottle;
BYTE spare2[4];
// Disk
BOOLEAN DiskSpinDown;
BYTE spare3[8];
// System Battery
BOOLEAN SystemBatteriesPresent;
BOOLEAN BatteriesAreShortTerm;
BATTERY_REPORTING_SCALE BatteryScale[3];
// Wake
SYSTEM_POWER_STATE AcOnLineWake;
SYSTEM_POWER_STATE SoftLidWake;
SYSTEM_POWER_STATE RtcWake;
SYSTEM_POWER_STATE MinDeviceWakeState; // note this may change on driver load
SYSTEM_POWER_STATE DefaultLowLatencyWake;
} SYSTEM_POWER_CAPABILITIES, *PSYSTEM_POWER_CAPABILITIES;
#endif // WINVER < 0x500
typedef struct _SYSTEM_POWER_INFORMATION
{
ULONG MaxIdlenessAllowed;
ULONG Idleness;
ULONG TimeRemaining;
UCHAR CoolingMode;
} SYSTEM_POWER_INFORMATION, *PSYSTEM_POWER_INFORMATION;
// SPI.CoolingMode
#define PO_TZ_INVALID_MODE 0 // The system does not support CPU throttling,
// or there is no thermal zone defined [..]
#endif // #if MSC_VERSION
2005-02-26 16:14:55 +01:00
// neither VC7.1 nor MinGW define this
typedef struct _PROCESSOR_POWER_INFORMATION
{
ULONG Number;
ULONG MaxMhz;
ULONG CurrentMhz;
ULONG MhzLimit;
ULONG MaxIdleState;
ULONG CurrentIdleState;
} PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION;
///////////////////////////////////////////////////////////////////////////////
//
// fixes for dbghelp.h 6.4
//
///////////////////////////////////////////////////////////////////////////////
// the macros defined "for those without specstrings.h" are incorrect -
// parameter definition is missing.
#ifndef __specstrings
# define __specstrings // prevent dbghelp from changing these
# define __in
# define __out
# define __inout
# define __in_opt
# define __out_opt
# define __inout_opt
# define __in_ecount(s)
# define __out_ecount(s)
# define __inout_ecount(s)
# define __in_bcount(s)
# define __out_bcount(s)
# define __inout_bcount(s)
# define __deref_opt_out
# define __deref_out
#endif
// (VC2005 defines __specstrings, but doesn't define (or use) __out_xcount,
// so this is not inside the above #ifndef section)
//
// missing from dbghelp's list
# define __out_xcount(s)
//
// not defined by dbghelp; these values are taken from DIA cvconst.h
//
enum BasicType
{
btNoType = 0,
btVoid = 1,
btChar = 2,
btWChar = 3,
btInt = 6,
btUInt = 7,
btFloat = 8,
btBCD = 9,
btBool = 10,
btLong = 13,
btULong = 14,
btCurrency = 25,
btDate = 26,
btVariant = 27,
btComplex = 28,
btBit = 29,
btBSTR = 30,
btHresult = 31
};
enum DataKind
{
DataIsUnknown,
DataIsLocal,
DataIsStaticLocal,
DataIsParam,
DataIsObjectPtr,
DataIsFileStatic,
DataIsGlobal,
DataIsMember,
DataIsStaticMember,
DataIsConstant
};
#if MSC_VERSION >= 1400 // hide "pragma region" from VS2003
#pragma endregion
#endif
//-----------------------------------------------------------------------------
// locking
// critical sections used by win-specific code
enum
{
ONCE_CS,
WTIME_CS,
WAIO_CS,
WIN_CS,
WDBG_CS,
NUM_CS
};
extern void win_lock(uint idx);
extern void win_unlock(uint idx);
// used in a desperate attempt to avoid deadlock in wdbg_exception_handler.
extern int win_is_locked(uint idx);
//-----------------------------------------------------------------------------
// module init and shutdown
// register functions to be called before libc init, before main,
// or after atexit.
//
// overview:
// participating modules store function pointer(s) to their init and/or
// shutdown function in a specific COFF section. the sections are
// grouped according to the desired notification and the order in which
// functions are to be called (useful if one module depends on another).
// they are then gathered by the linker and arranged in alphabetical order.
// placeholder variables in the sections indicate where the series of
// functions begins and ends for a given notification time.
// at runtime, all of the function pointers between the markers are invoked.
//
// details:
// the section names are of the format ".LIB${type}{group}".
// {type} is C for pre-libc init, I for pre-main init, or
// T for terminators (last of the atexit handlers).
// {group} is [B, Y]; all functions in a group are called before those of
// the next (alphabetically) higher group, but order within the group is
// undefined. this is because the linker sorts sections alphabetically,
// but doesn't specify the order in which object files are processed.
// another consequence is that groups A and Z must not be used!
// (data placed there might end up outside the start/end markers)
//
// example:
// #pragma SECTION_PRE_LIBC(G))
// WIN_REGISTER_FUNC(wtime_init);
// #pragma FORCE_INCLUDE(wtime_init)
// #pragma SECTION_POST_ATEXIT(D))
// WIN_REGISTER_FUNC(wtime_shutdown);
// #pragma FORCE_INCLUDE(wtime_shutdown)
// #pragma SECTION_RESTORE
//
// rationale:
// several methods of module init are possible: (see Large Scale C++ Design)
// - on-demand initialization: each exported function would have to check
// if init already happened. that would be brittle and hard to verify.
// - singleton: variant of the above, but not applicable to a
// procedural interface (and quite ugly to boot).
// - registration: NLSO constructors call a central notification function.
// module dependencies would be quite difficult to express - this would
// require a graph or separate lists for each priority (clunky).
// worse, a fatal flaw is that other C++ constructors may depend on the
// modules we are initializing and already have run. there is no way
// to influence ctor call order between separate source files, so
// this is out of the question.
// - linker-based registration: same as above, but the linker takes care
// of assembling various functions into one sorted table. the list of
// init functions is available before C++ ctors have run. incidentally,
// zero runtime overhead is incurred. unfortunately, this approach is
// MSVC-specific. however, the MS CRT uses a similar method for its
// init, so this is expected to remain supported.
// macros to simplify usage.
// notes:
// - #pragma cannot be packaged in macros due to expansion rules.
// - __declspec(allocate) would be tempting, since that could be
// wrapped in WIN_REGISTER_FUNC. unfortunately it inexplicably cannot
// cope with split string literals (e.g. "ab" "c"). that disqualifies
// it, since we want to hide the section name behind a macro, which
// would require the abovementioned merging.
#define SECTION_PRE_LIBC(group) data_seg(".LIB$C" #group)
#define SECTION_PRE_MAIN(group) data_seg(".LIB$I" #group)
#define SECTION_POST_ATEXIT(group) data_seg(".LIB$T" #group)
#define SECTION_RESTORE data_seg()
// use to make sure the link-stage optimizer doesn't discard the
// function pointers (happens on VC8)
#define FORCE_INCLUDE(id) comment(linker, "/include:_p"#id)
#define WIN_REGISTER_FUNC(func)\
static LibError func(void);\
extern "C" LibError (*p##func)(void) = func
//-----------------------------------------------------------------------------
// misc
extern void* win_alloc(size_t size);
extern void win_free(void* p);
// thread safe, usable in constructors
#define WIN_ONCE(code)\
{\
win_lock(ONCE_CS);\
static bool ONCE_init_; /* avoid name conflict */\
if(!ONCE_init_)\
{\
ONCE_init_ = true;\
code;\
}\
win_unlock(ONCE_CS);\
}
#define WIN_SAVE_LAST_ERROR DWORD last_err__ = GetLastError();
#define WIN_RESTORE_LAST_ERROR STMT(if(last_err__ != 0 && GetLastError() == 0) SetLastError(last_err__););
// return the LibError equivalent of GetLastError(), or ERR::FAIL if
// there's no equal.
// you should SetLastError(0) before calling whatever will set ret
// to make sure we do not return any stale errors.
extern LibError LibError_from_win32(DWORD ret, bool warn_if_failed = true);
extern char win_sys_dir[MAX_PATH+1];
extern char win_exe_dir[MAX_PATH+1];
// this isn't nice (ideally we would avoid coupling win.cpp and wdbg.cpp), but
// necessary; see rationale at function definition.
extern LONG WINAPI wdbg_exception_filter(EXCEPTION_POINTERS* ep);
#ifdef USE_WINMAIN
extern "C" int WinMainCRTStartup(void);
#else
extern "C" int mainCRTStartup(void);
#endif
#define FD_READ BIT(0)
#define FD_WRITE BIT(1)
#define FD_ACCEPT BIT(3)
#define FD_CONNECT BIT(4)
#define FD_CLOSE BIT(5)
#endif // #ifndef WIN_INTERNAL_H