mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-10 01:29:59 +00:00
added files for platform API
This commit is contained in:
parent
2d3941a43e
commit
81b16de62b
7 changed files with 359 additions and 15 deletions
145
hyperdbg/include/platform/general/header/nt-list.h
Normal file
145
hyperdbg/include/platform/general/header/nt-list.h
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* @file nt-list.h
|
||||
* @author Max Raulea (max.raulea@gmail.com)
|
||||
* @brief Cross-platform NT-style intrusive doubly-linked list helpers + CONTAINING_RECORD
|
||||
* @details The shared debugger code uses the NT LIST_ENTRY API (InitializeListHead,
|
||||
* InsertHeadList, RemoveEntryList, CONTAINING_RECORD, ...). On Windows these
|
||||
* come from <windows.h> (or, under USE_NATIVE_SDK_HEADERS, from the in-tree
|
||||
* platform/user/header/Windows.h). Platforms whose system headers don't ship
|
||||
* them (Linux) get them here, so the shared code compiles unchanged.
|
||||
*
|
||||
* These operate on the exact LIST_ENTRY {Flink, Blink} layout defined in
|
||||
* SDK/headers/DataTypes.h, which is part of the kernel<->user IOCTL ABI --
|
||||
* that's why we mirror the NT list rather than reaching for sys/queue.h
|
||||
* (different layout + a colliding LIST_ENTRY name).
|
||||
*
|
||||
* The body is compiled only where the OS headers don't already provide these
|
||||
* (i.e. not on Windows), so including this unconditionally is safe.
|
||||
*
|
||||
* @version 0.1
|
||||
* @date 2026-06-16
|
||||
*
|
||||
* @copyright This project is released under the GNU Public License v3.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
# include <stddef.h> // offsetof
|
||||
|
||||
//
|
||||
// Given the address of a LIST_ENTRY field embedded in a struct, recover the
|
||||
// address of the containing struct.
|
||||
//
|
||||
# ifndef CONTAINING_RECORD
|
||||
# define CONTAINING_RECORD(address, type, field) \
|
||||
((type *)((char *)(address) - offsetof(type, field)))
|
||||
# endif
|
||||
|
||||
//
|
||||
// Initialize a list head to the empty (points-to-self) state.
|
||||
//
|
||||
static inline void
|
||||
InitializeListHead(PLIST_ENTRY ListHead)
|
||||
{
|
||||
ListHead->Flink = ListHead->Blink = ListHead;
|
||||
}
|
||||
|
||||
//
|
||||
// TRUE if the list has no entries.
|
||||
//
|
||||
static inline BOOLEAN
|
||||
IsListEmpty(const LIST_ENTRY * ListHead)
|
||||
{
|
||||
return (BOOLEAN)(ListHead->Flink == ListHead);
|
||||
}
|
||||
|
||||
//
|
||||
// Unlink an entry. Returns TRUE if the list is now empty.
|
||||
//
|
||||
static inline BOOLEAN
|
||||
RemoveEntryList(PLIST_ENTRY Entry)
|
||||
{
|
||||
PLIST_ENTRY Flink = Entry->Flink;
|
||||
PLIST_ENTRY Blink = Entry->Blink;
|
||||
|
||||
Blink->Flink = Flink;
|
||||
Flink->Blink = Blink;
|
||||
|
||||
return (BOOLEAN)(Flink == Blink);
|
||||
}
|
||||
|
||||
//
|
||||
// Unlink and return the first entry.
|
||||
//
|
||||
static inline PLIST_ENTRY
|
||||
RemoveHeadList(PLIST_ENTRY ListHead)
|
||||
{
|
||||
PLIST_ENTRY Entry = ListHead->Flink;
|
||||
PLIST_ENTRY Flink = Entry->Flink;
|
||||
|
||||
ListHead->Flink = Flink;
|
||||
Flink->Blink = ListHead;
|
||||
|
||||
return Entry;
|
||||
}
|
||||
|
||||
//
|
||||
// Unlink and return the last entry.
|
||||
//
|
||||
static inline PLIST_ENTRY
|
||||
RemoveTailList(PLIST_ENTRY ListHead)
|
||||
{
|
||||
PLIST_ENTRY Entry = ListHead->Blink;
|
||||
PLIST_ENTRY Blink = Entry->Blink;
|
||||
|
||||
ListHead->Blink = Blink;
|
||||
Blink->Flink = ListHead;
|
||||
|
||||
return Entry;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert an entry at the tail of the list.
|
||||
//
|
||||
static inline void
|
||||
InsertTailList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry)
|
||||
{
|
||||
PLIST_ENTRY Blink = ListHead->Blink;
|
||||
|
||||
Entry->Flink = ListHead;
|
||||
Entry->Blink = Blink;
|
||||
Blink->Flink = Entry;
|
||||
ListHead->Blink = Entry;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert an entry at the head of the list.
|
||||
//
|
||||
static inline void
|
||||
InsertHeadList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry)
|
||||
{
|
||||
PLIST_ENTRY Flink = ListHead->Flink;
|
||||
|
||||
Entry->Flink = Flink;
|
||||
Entry->Blink = ListHead;
|
||||
Flink->Blink = Entry;
|
||||
ListHead->Flink = Entry;
|
||||
}
|
||||
|
||||
//
|
||||
// Splice the entries of ListToAppend onto the tail of ListHead.
|
||||
//
|
||||
static inline void
|
||||
AppendTailList(PLIST_ENTRY ListHead, PLIST_ENTRY ListToAppend)
|
||||
{
|
||||
PLIST_ENTRY ListEnd = ListHead->Blink;
|
||||
|
||||
ListHead->Blink->Flink = ListToAppend;
|
||||
ListHead->Blink = ListToAppend->Blink;
|
||||
ListToAppend->Blink->Flink = ListHead;
|
||||
ListToAppend->Blink = ListEnd;
|
||||
}
|
||||
|
||||
#endif // !_WIN32
|
||||
137
hyperdbg/include/platform/user/code/platform-signal.c
Normal file
137
hyperdbg/include/platform/user/code/platform-signal.c
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/**
|
||||
* @file platform-signal.c
|
||||
* @author Max Raulea (max.raulea@gmail.com)
|
||||
* @brief User mode cross-platform implementation of the console-control handler
|
||||
* @details See platform-signal.h. The Windows branch forwards to SetConsoleCtrlHandler.
|
||||
* The Linux branch blocks the handled signals and dispatches them from a
|
||||
* dedicated sigwait() thread. sigwait() (rather than a sigaction() handler)
|
||||
* is used deliberately: BreakController calls ShowMessages (printf), socket
|
||||
* I/O and Sleep, none of which are async-signal-safe. Running the handler on
|
||||
* a normal thread woken by sigwait() sidesteps that entirely and mirrors the
|
||||
* Windows model where the console-control handler also runs on its own thread.
|
||||
*
|
||||
* @version 0.1
|
||||
* @date 2026-06-16
|
||||
*
|
||||
* @copyright This project is released under the GNU Public License v3.
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
|
||||
#if defined(__linux__)
|
||||
# include "../header/platform-signal.h"
|
||||
#endif // defined(__linux__)
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
BOOLEAN
|
||||
PlatformInstallCtrlHandler(PLATFORM_CTRL_HANDLER Handler)
|
||||
{
|
||||
return (BOOLEAN)SetConsoleCtrlHandler((PHANDLER_ROUTINE)Handler, TRUE);
|
||||
}
|
||||
|
||||
#elif defined(__linux__)
|
||||
|
||||
# include <signal.h>
|
||||
# include <pthread.h>
|
||||
|
||||
//
|
||||
// The installed handler, read by the dispatch thread.
|
||||
//
|
||||
static PLATFORM_CTRL_HANDLER g_PlatformCtrlHandler = NULL;
|
||||
|
||||
//
|
||||
// Map a POSIX signal onto the Win32 console-control event the shared handler
|
||||
// understands. Only the two interactive break signals are mapped:
|
||||
// SIGINT (CTRL+C) -> CTRL_C_EVENT
|
||||
// SIGQUIT (CTRL+\) -> CTRL_BREAK_EVENT
|
||||
// SIGTERM/SIGHUP are intentionally left at their default disposition so the
|
||||
// process stays killable/terminable the usual way; the CLOSE/LOGOFF/SHUTDOWN
|
||||
// console events have no clean Linux analog.
|
||||
//
|
||||
static DWORD
|
||||
PlatformMapSignalToCtrlType(int Signal)
|
||||
{
|
||||
switch (Signal)
|
||||
{
|
||||
case SIGINT:
|
||||
return CTRL_C_EVENT;
|
||||
case SIGQUIT:
|
||||
return CTRL_BREAK_EVENT;
|
||||
default:
|
||||
return (DWORD)-1;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Dedicated thread: waits for the handled signals and dispatches them to the
|
||||
// installed handler in ordinary (async-signal-safe) thread context.
|
||||
//
|
||||
static void *
|
||||
PlatformSignalThread(void * Arg)
|
||||
{
|
||||
sigset_t WaitSet;
|
||||
int Signal;
|
||||
|
||||
(void)Arg;
|
||||
|
||||
sigemptyset(&WaitSet);
|
||||
sigaddset(&WaitSet, SIGINT);
|
||||
sigaddset(&WaitSet, SIGQUIT);
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (sigwait(&WaitSet, &Signal) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
DWORD CtrlType = PlatformMapSignalToCtrlType(Signal);
|
||||
|
||||
if (g_PlatformCtrlHandler != NULL && CtrlType != (DWORD)-1)
|
||||
{
|
||||
g_PlatformCtrlHandler(CtrlType);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
PlatformInstallCtrlHandler(PLATFORM_CTRL_HANDLER Handler)
|
||||
{
|
||||
sigset_t BlockSet;
|
||||
pthread_t Thread;
|
||||
|
||||
g_PlatformCtrlHandler = Handler;
|
||||
|
||||
//
|
||||
// Block the handled signals in this (main) thread. Done before any other
|
||||
// thread is created, the mask is inherited by every thread, guaranteeing
|
||||
// the signals are delivered to our sigwait() thread and nowhere else.
|
||||
//
|
||||
sigemptyset(&BlockSet);
|
||||
sigaddset(&BlockSet, SIGINT);
|
||||
sigaddset(&BlockSet, SIGQUIT);
|
||||
|
||||
if (pthread_sigmask(SIG_BLOCK, &BlockSet, NULL) != 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pthread_create(&Thread, NULL, PlatformSignalThread, NULL) != 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Fire-and-forget: the thread lives for the life of the process.
|
||||
//
|
||||
pthread_detach(Thread);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#else
|
||||
# error "Unsupported platform"
|
||||
#endif
|
||||
43
hyperdbg/include/platform/user/header/platform-signal.h
Normal file
43
hyperdbg/include/platform/user/header/platform-signal.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* @file platform-signal.h
|
||||
* @author Max Raulea (max.raulea@gmail.com)
|
||||
* @brief User mode cross-platform interface for the console-control (CTRL+C / CTRL+BREAK) handler
|
||||
* @details HyperDbg installs a single handler (BreakController) that pauses the
|
||||
* debuggee when the user hits CTRL+C / CTRL+BREAK. The handler body is
|
||||
* platform independent; only the OS mechanism that delivers the event
|
||||
* and the thread context it runs in are OS specific. This interface
|
||||
* isolates that registration. Windows maps onto SetConsoleCtrlHandler;
|
||||
* Linux maps onto POSIX signals serviced by a dedicated sigwait() thread
|
||||
* so the handler runs in ordinary thread context (matching Windows, which
|
||||
* also dispatches the handler on its own thread).
|
||||
*
|
||||
* @version 0.1
|
||||
* @date 2026-06-16
|
||||
*
|
||||
* @copyright This project is released under the GNU Public License v3.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if defined(__linux__)
|
||||
# include "../../../../include/SDK/HyperDbgSdk.h"
|
||||
#endif // defined(__linux__)
|
||||
|
||||
//
|
||||
// Console-control handler signature. Matches the Win32 PHANDLER_ROUTINE shape
|
||||
// (and BreakController) so the same function pointer is usable on both platforms.
|
||||
// CtrlType is one of the CTRL_*_EVENT codes.
|
||||
//
|
||||
typedef BOOL (*PLATFORM_CTRL_HANDLER)(DWORD CtrlType);
|
||||
|
||||
//
|
||||
// INSTALL the process console-control handler.
|
||||
// Windows: registers Handler via SetConsoleCtrlHandler.
|
||||
// Linux: blocks the relevant signals process-wide and starts a dedicated
|
||||
// sigwait() thread that translates them into CTRL_*_EVENT codes and
|
||||
// invokes Handler. Must be called once, before other threads spawn,
|
||||
// so the blocked-signal mask is inherited by every thread.
|
||||
// Returns TRUE on success, FALSE on failure.
|
||||
//
|
||||
BOOLEAN
|
||||
PlatformInstallCtrlHandler(PLATFORM_CTRL_HANDLER Handler);
|
||||
|
|
@ -656,6 +656,7 @@ ShowErrorMessage(UINT32 Error)
|
|||
UINT64
|
||||
DebuggerGetNtoskrnlBase()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
UINT64 NtoskrnlBase = NULL;
|
||||
PRTL_PROCESS_MODULES Modules = NULL;
|
||||
|
||||
|
|
@ -678,6 +679,14 @@ DebuggerGetNtoskrnlBase()
|
|||
free(Modules);
|
||||
|
||||
return NtoskrnlBase;
|
||||
#else
|
||||
//
|
||||
// TODO(Linux): NT-style system module enumeration (PRTL_PROCESS_MODULES via
|
||||
// NtQuerySystemInformation) has no Linux analog. The kernel-module base lookup
|
||||
// will need a Linux-specific mechanism once the kernel side exists.
|
||||
//
|
||||
return NULL64_ZERO;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -719,7 +728,7 @@ DebuggerPauseDebuggee()
|
|||
//
|
||||
// Send a pause IOCTL
|
||||
//
|
||||
StatusIoctl = DeviceIoControl(g_DeviceHandle, // Handle to device
|
||||
StatusIoctl = PlatformDeviceIoControl(g_DeviceHandle, // Handle to device
|
||||
IOCTL_PAUSE_PACKET_RECEIVED, // IO Control Code (IOCTL)
|
||||
&PauseRequest, // Input Buffer to driver.
|
||||
SIZEOF_DEBUGGER_PAUSE_PACKET_RECEIVED, // Input buffer
|
||||
|
|
@ -733,7 +742,7 @@ DebuggerPauseDebuggee()
|
|||
|
||||
if (!StatusIoctl)
|
||||
{
|
||||
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
|
||||
ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -1391,7 +1400,7 @@ SendEventToKernel(PDEBUGGER_GENERAL_EVENT_DETAIL Event,
|
|||
// Send IOCTL
|
||||
//
|
||||
|
||||
Status = DeviceIoControl(g_DeviceHandle, // Handle to device
|
||||
Status = PlatformDeviceIoControl(g_DeviceHandle, // Handle to device
|
||||
IOCTL_DEBUGGER_REGISTER_EVENT, // IO Control Code (IOCTL)
|
||||
Event, // Input Buffer to driver.
|
||||
EventBufferLength, // Input buffer length
|
||||
|
|
@ -1408,7 +1417,7 @@ SendEventToKernel(PDEBUGGER_GENERAL_EVENT_DETAIL Event,
|
|||
|
||||
if (!Status)
|
||||
{
|
||||
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
|
||||
ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1560,7 +1569,7 @@ RegisterActionToEvent(PDEBUGGER_GENERAL_EVENT_DETAIL Event,
|
|||
//
|
||||
if (ActionBreakToDebugger != NULL)
|
||||
{
|
||||
Status = DeviceIoControl(
|
||||
Status = PlatformDeviceIoControl(
|
||||
g_DeviceHandle, // Handle to device
|
||||
IOCTL_DEBUGGER_ADD_ACTION_TO_EVENT, // IO Control Code (IOCTL)
|
||||
ActionBreakToDebugger, // Input Buffer to driver.
|
||||
|
|
@ -1578,7 +1587,7 @@ RegisterActionToEvent(PDEBUGGER_GENERAL_EVENT_DETAIL Event,
|
|||
|
||||
if (!Status)
|
||||
{
|
||||
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
|
||||
ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1588,7 +1597,7 @@ RegisterActionToEvent(PDEBUGGER_GENERAL_EVENT_DETAIL Event,
|
|||
//
|
||||
if (ActionCustomCode != NULL)
|
||||
{
|
||||
Status = DeviceIoControl(
|
||||
Status = PlatformDeviceIoControl(
|
||||
g_DeviceHandle, // Handle to device
|
||||
IOCTL_DEBUGGER_ADD_ACTION_TO_EVENT, // IO Control Code (IOCTL)
|
||||
ActionCustomCode, // Input Buffer to driver.
|
||||
|
|
@ -1606,7 +1615,7 @@ RegisterActionToEvent(PDEBUGGER_GENERAL_EVENT_DETAIL Event,
|
|||
|
||||
if (!Status)
|
||||
{
|
||||
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
|
||||
ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1616,7 +1625,7 @@ RegisterActionToEvent(PDEBUGGER_GENERAL_EVENT_DETAIL Event,
|
|||
//
|
||||
if (ActionScript != NULL)
|
||||
{
|
||||
Status = DeviceIoControl(
|
||||
Status = PlatformDeviceIoControl(
|
||||
g_DeviceHandle, // Handle to device
|
||||
IOCTL_DEBUGGER_ADD_ACTION_TO_EVENT, // IO Control Code (IOCTL)
|
||||
ActionScript, // Input Buffer to driver.
|
||||
|
|
@ -1634,7 +1643,7 @@ RegisterActionToEvent(PDEBUGGER_GENERAL_EVENT_DETAIL Event,
|
|||
|
||||
if (!Status)
|
||||
{
|
||||
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
|
||||
ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1800,7 +1809,7 @@ InterpretGeneralEventAndActionsFields(
|
|||
//
|
||||
PVOID BufferOfCommandString = malloc(BufferOfCommandStringLength);
|
||||
|
||||
RtlZeroMemory(BufferOfCommandString, BufferOfCommandStringLength);
|
||||
PlatformZeroMemory(BufferOfCommandString, BufferOfCommandStringLength);
|
||||
|
||||
//
|
||||
// Copy the string to the buffer
|
||||
|
|
@ -2105,7 +2114,7 @@ InterpretGeneralEventAndActionsFields(
|
|||
LengthOfEventBuffer = sizeof(DEBUGGER_GENERAL_EVENT_DETAIL) + ConditionBufferLength;
|
||||
|
||||
TempEvent = (PDEBUGGER_GENERAL_EVENT_DETAIL)malloc(LengthOfEventBuffer);
|
||||
RtlZeroMemory(TempEvent, LengthOfEventBuffer);
|
||||
PlatformZeroMemory(TempEvent, LengthOfEventBuffer);
|
||||
|
||||
//
|
||||
// Check if buffer is available
|
||||
|
|
@ -2187,7 +2196,7 @@ InterpretGeneralEventAndActionsFields(
|
|||
|
||||
TempActionCustomCode = (PDEBUGGER_GENERAL_ACTION)malloc(LengthOfCustomCodeActionBuffer);
|
||||
|
||||
RtlZeroMemory(TempActionCustomCode, LengthOfCustomCodeActionBuffer);
|
||||
PlatformZeroMemory(TempActionCustomCode, LengthOfCustomCodeActionBuffer);
|
||||
|
||||
memcpy(
|
||||
(PVOID)((UINT64)TempActionCustomCode + sizeof(DEBUGGER_GENERAL_ACTION)),
|
||||
|
|
@ -2226,7 +2235,7 @@ InterpretGeneralEventAndActionsFields(
|
|||
LengthOfScriptActionBuffer = sizeof(DEBUGGER_GENERAL_ACTION) + ScriptBufferLength;
|
||||
TempActionScript = (PDEBUGGER_GENERAL_ACTION)malloc(LengthOfScriptActionBuffer);
|
||||
|
||||
RtlZeroMemory(TempActionScript, LengthOfScriptActionBuffer);
|
||||
PlatformZeroMemory(TempActionScript, LengthOfScriptActionBuffer);
|
||||
|
||||
memcpy((PVOID)((UINT64)TempActionScript + sizeof(DEBUGGER_GENERAL_ACTION)),
|
||||
(PVOID)ScriptBufferAddress,
|
||||
|
|
@ -2272,7 +2281,7 @@ InterpretGeneralEventAndActionsFields(
|
|||
|
||||
TempActionBreak = (PDEBUGGER_GENERAL_ACTION)malloc(LengthOfBreakActionBuffer);
|
||||
|
||||
RtlZeroMemory(TempActionBreak, LengthOfBreakActionBuffer);
|
||||
PlatformZeroMemory(TempActionBreak, LengthOfBreakActionBuffer);
|
||||
|
||||
//
|
||||
// Set the action Tag
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ msbuild "$(SolutionDir)dependencies\zydis\msvc\Zydis.sln" /m /p:Configuration="R
|
|||
<ClInclude Include="..\include\platform\user\header\platform-serial.h" />
|
||||
<ClInclude Include="..\include\platform\user\header\platform-ioctl.h" />
|
||||
<ClInclude Include="..\include\platform\user\header\platform-signal.h" />
|
||||
<ClInclude Include="..\include\platform\general\header\nt-list.h" />
|
||||
<ClInclude Include="..\include\platform\user\header\windows-only\windows-privilege.h" />
|
||||
<ClInclude Include="..\include\platform\user\header\Windows.h" />
|
||||
<ClInclude Include="header\assembler.h" />
|
||||
|
|
|
|||
|
|
@ -206,6 +206,9 @@
|
|||
<ClInclude Include="..\include\platform\user\header\platform-signal.h">
|
||||
<Filter>header\platform</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\platform\general\header\nt-list.h">
|
||||
<Filter>header\platform</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="header\messaging.h">
|
||||
<Filter>header</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -171,6 +171,12 @@ typedef const wchar_t *LPCWCHAR, *PCWCHAR;
|
|||
//
|
||||
#include "platform/user/header/platform-signal.h"
|
||||
|
||||
//
|
||||
// NT-style intrusive linked-list helpers + CONTAINING_RECORD (self-guards to
|
||||
// non-Windows; Windows gets these from <windows.h> / the native-SDK shim)
|
||||
//
|
||||
#include "platform/general/header/nt-list.h"
|
||||
|
||||
//
|
||||
// Platform-specific intrinsics
|
||||
//
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue