ciyze 2020-10-29 20:50:26 +08:00
parent 7aa2e8bcb5
commit 36f4923393
53 changed files with 62730 additions and 0 deletions

@ -0,0 +1,395 @@
Attribution 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution 4.0 International Public License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution 4.0 International Public License ("Public License"). To the
extent this Public License may be interpreted as a contract, You are
granted the Licensed Rights in consideration of Your acceptance of
these terms and conditions, and the Licensor grants You such rights in
consideration of benefits the Licensor receives from making the
Licensed Material available under these terms and conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
d. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
e. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
f. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
g. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
h. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
i. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
j. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
k. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
4. If You Share Adapted Material You produce, the Adapter's
License You apply must not prevent recipients of the Adapted
Material from complying with this Public License.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material; and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.

@ -0,0 +1,24 @@
This collection of Native API header files has been maintained since 2009 for the Process Hacker project, and is the most up-to-date set of Native API definitions that we know of. We have gathered these definitions from official Microsoft header files and symbol files, as well as a lot of reverse engineering and guessing. See `phnt.h` for more information.
## Usage
First make sure that your program is using the latest Windows SDK.
These header files are designed to be used by user-mode programs. Instead of `#include <windows.h>`, place
```
#include <phnt_windows.h>
#include <phnt.h>
```
at the top of your program. The first line provides access to the Win32 API as well as the `NTSTATUS` values. The second line provides access to the entire Native API. By default, only definitions present in Windows XP are included into your program. To change this, use one of the following:
```
#define PHNT_VERSION PHNT_WINXP // Windows XP
#define PHNT_VERSION PHNT_WS03 // Windows Server 2003
#define PHNT_VERSION PHNT_VISTA // Windows Vista
#define PHNT_VERSION PHNT_WIN7 // Windows 7
#define PHNT_VERSION PHNT_WIN8 // Windows 8
#define PHNT_VERSION PHNT_WINBLUE // Windows 8.1
#define PHNT_VERSION PHNT_THRESHOLD // Windows 10
```

@ -0,0 +1,377 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTDBG_H
#define _NTDBG_H
// Debugging
NTSYSAPI
VOID
NTAPI
DbgUserBreakPoint(
VOID
);
NTSYSAPI
VOID
NTAPI
DbgBreakPoint(
VOID
);
NTSYSAPI
VOID
NTAPI
DbgBreakPointWithStatus(
_In_ ULONG Status
);
#define DBG_STATUS_CONTROL_C 1
#define DBG_STATUS_SYSRQ 2
#define DBG_STATUS_BUGCHECK_FIRST 3
#define DBG_STATUS_BUGCHECK_SECOND 4
#define DBG_STATUS_FATAL 5
#define DBG_STATUS_DEBUG_CONTROL 6
#define DBG_STATUS_WORKER 7
NTSYSAPI
ULONG
STDAPIVCALLTYPE
DbgPrint(
_In_z_ _Printf_format_string_ PSTR Format,
...
);
NTSYSAPI
ULONG
STDAPIVCALLTYPE
DbgPrintEx(
_In_ ULONG ComponentId,
_In_ ULONG Level,
_In_z_ _Printf_format_string_ PSTR Format,
...
);
NTSYSAPI
ULONG
NTAPI
vDbgPrintEx(
_In_ ULONG ComponentId,
_In_ ULONG Level,
_In_z_ PCH Format,
_In_ va_list arglist
);
NTSYSAPI
ULONG
NTAPI
vDbgPrintExWithPrefix(
_In_z_ PCH Prefix,
_In_ ULONG ComponentId,
_In_ ULONG Level,
_In_z_ PCH Format,
_In_ va_list arglist
);
NTSYSAPI
NTSTATUS
NTAPI
DbgQueryDebugFilterState(
_In_ ULONG ComponentId,
_In_ ULONG Level
);
NTSYSAPI
NTSTATUS
NTAPI
DbgSetDebugFilterState(
_In_ ULONG ComponentId,
_In_ ULONG Level,
_In_ BOOLEAN State
);
NTSYSAPI
ULONG
NTAPI
DbgPrompt(
_In_ PCH Prompt,
_Out_writes_bytes_(Length) PCH Response,
_In_ ULONG Length
);
// Definitions
typedef struct _DBGKM_EXCEPTION
{
EXCEPTION_RECORD ExceptionRecord;
ULONG FirstChance;
} DBGKM_EXCEPTION, *PDBGKM_EXCEPTION;
typedef struct _DBGKM_CREATE_THREAD
{
ULONG SubSystemKey;
PVOID StartAddress;
} DBGKM_CREATE_THREAD, *PDBGKM_CREATE_THREAD;
typedef struct _DBGKM_CREATE_PROCESS
{
ULONG SubSystemKey;
HANDLE FileHandle;
PVOID BaseOfImage;
ULONG DebugInfoFileOffset;
ULONG DebugInfoSize;
DBGKM_CREATE_THREAD InitialThread;
} DBGKM_CREATE_PROCESS, *PDBGKM_CREATE_PROCESS;
typedef struct _DBGKM_EXIT_THREAD
{
NTSTATUS ExitStatus;
} DBGKM_EXIT_THREAD, *PDBGKM_EXIT_THREAD;
typedef struct _DBGKM_EXIT_PROCESS
{
NTSTATUS ExitStatus;
} DBGKM_EXIT_PROCESS, *PDBGKM_EXIT_PROCESS;
typedef struct _DBGKM_LOAD_DLL
{
HANDLE FileHandle;
PVOID BaseOfDll;
ULONG DebugInfoFileOffset;
ULONG DebugInfoSize;
PVOID NamePointer;
} DBGKM_LOAD_DLL, *PDBGKM_LOAD_DLL;
typedef struct _DBGKM_UNLOAD_DLL
{
PVOID BaseAddress;
} DBGKM_UNLOAD_DLL, *PDBGKM_UNLOAD_DLL;
typedef enum _DBG_STATE
{
DbgIdle,
DbgReplyPending,
DbgCreateThreadStateChange,
DbgCreateProcessStateChange,
DbgExitThreadStateChange,
DbgExitProcessStateChange,
DbgExceptionStateChange,
DbgBreakpointStateChange,
DbgSingleStepStateChange,
DbgLoadDllStateChange,
DbgUnloadDllStateChange
} DBG_STATE, *PDBG_STATE;
typedef struct _DBGUI_CREATE_THREAD
{
HANDLE HandleToThread;
DBGKM_CREATE_THREAD NewThread;
} DBGUI_CREATE_THREAD, *PDBGUI_CREATE_THREAD;
typedef struct _DBGUI_CREATE_PROCESS
{
HANDLE HandleToProcess;
HANDLE HandleToThread;
DBGKM_CREATE_PROCESS NewProcess;
} DBGUI_CREATE_PROCESS, *PDBGUI_CREATE_PROCESS;
typedef struct _DBGUI_WAIT_STATE_CHANGE
{
DBG_STATE NewState;
CLIENT_ID AppClientId;
union
{
DBGKM_EXCEPTION Exception;
DBGUI_CREATE_THREAD CreateThread;
DBGUI_CREATE_PROCESS CreateProcessInfo;
DBGKM_EXIT_THREAD ExitThread;
DBGKM_EXIT_PROCESS ExitProcess;
DBGKM_LOAD_DLL LoadDll;
DBGKM_UNLOAD_DLL UnloadDll;
} StateInfo;
} DBGUI_WAIT_STATE_CHANGE, *PDBGUI_WAIT_STATE_CHANGE;
#define DEBUG_READ_EVENT 0x0001
#define DEBUG_PROCESS_ASSIGN 0x0002
#define DEBUG_SET_INFORMATION 0x0004
#define DEBUG_QUERY_INFORMATION 0x0008
#define DEBUG_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \
DEBUG_READ_EVENT | DEBUG_PROCESS_ASSIGN | DEBUG_SET_INFORMATION | \
DEBUG_QUERY_INFORMATION)
#define DEBUG_KILL_ON_CLOSE 0x1
typedef enum _DEBUGOBJECTINFOCLASS
{
DebugObjectUnusedInformation,
DebugObjectKillProcessOnExitInformation,
MaxDebugObjectInfoClass
} DEBUGOBJECTINFOCLASS, *PDEBUGOBJECTINFOCLASS;
// System calls
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCreateDebugObject(
_Out_ PHANDLE DebugObjectHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ ULONG Flags
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtDebugActiveProcess(
_In_ HANDLE ProcessHandle,
_In_ HANDLE DebugObjectHandle
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtDebugContinue(
_In_ HANDLE DebugObjectHandle,
_In_ PCLIENT_ID ClientId,
_In_ NTSTATUS ContinueStatus
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtRemoveProcessDebug(
_In_ HANDLE ProcessHandle,
_In_ HANDLE DebugObjectHandle
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSetInformationDebugObject(
_In_ HANDLE DebugObjectHandle,
_In_ DEBUGOBJECTINFOCLASS DebugObjectInformationClass,
_In_ PVOID DebugInformation,
_In_ ULONG DebugInformationLength,
_Out_opt_ PULONG ReturnLength
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtWaitForDebugEvent(
_In_ HANDLE DebugObjectHandle,
_In_ BOOLEAN Alertable,
_In_opt_ PLARGE_INTEGER Timeout,
_Out_ PDBGUI_WAIT_STATE_CHANGE WaitStateChange
);
// Debugging UI
NTSYSAPI
NTSTATUS
NTAPI
DbgUiConnectToDbg(
VOID
);
NTSYSAPI
HANDLE
NTAPI
DbgUiGetThreadDebugObject(
VOID
);
NTSYSAPI
VOID
NTAPI
DbgUiSetThreadDebugObject(
_In_ HANDLE DebugObject
);
NTSYSAPI
NTSTATUS
NTAPI
DbgUiWaitStateChange(
_Out_ PDBGUI_WAIT_STATE_CHANGE StateChange,
_In_opt_ PLARGE_INTEGER Timeout
);
NTSYSAPI
NTSTATUS
NTAPI
DbgUiContinue(
_In_ PCLIENT_ID AppClientId,
_In_ NTSTATUS ContinueStatus
);
NTSYSAPI
NTSTATUS
NTAPI
DbgUiStopDebugging(
_In_ HANDLE Process
);
NTSYSAPI
NTSTATUS
NTAPI
DbgUiDebugActiveProcess(
_In_ HANDLE Process
);
NTSYSAPI
VOID
NTAPI
DbgUiRemoteBreakin(
_In_ PVOID Context
);
NTSYSAPI
NTSTATUS
NTAPI
DbgUiIssueRemoteBreakin(
_In_ HANDLE Process
);
NTSYSAPI
NTSTATUS
NTAPI
DbgUiConvertStateChangeStructure(
_In_ PDBGUI_WAIT_STATE_CHANGE StateChange,
_Out_ LPDEBUG_EVENT DebugEvent
);
struct _EVENT_FILTER_DESCRIPTOR;
typedef VOID (NTAPI *PENABLECALLBACK)(
_In_ LPCGUID SourceId,
_In_ ULONG IsEnabled,
_In_ UCHAR Level,
_In_ ULONGLONG MatchAnyKeyword,
_In_ ULONGLONG MatchAllKeyword,
_In_opt_ struct _EVENT_FILTER_DESCRIPTOR *FilterData,
_Inout_opt_ PVOID CallbackContext
);
typedef ULONGLONG REGHANDLE, *PREGHANDLE;
NTSYSAPI
NTSTATUS
NTAPI
EtwEventRegister(
_In_ LPCGUID ProviderId,
_In_opt_ PENABLECALLBACK EnableCallback,
_In_opt_ PVOID CallbackContext,
_Out_ PREGHANDLE RegHandle
);
#endif

File diff suppressed because it is too large Load Diff

@ -0,0 +1,132 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTGDI_H
#define _NTGDI_H
#define GDI_MAX_HANDLE_COUNT 0x4000
#define GDI_HANDLE_INDEX_SHIFT 0
#define GDI_HANDLE_INDEX_BITS 16
#define GDI_HANDLE_INDEX_MASK 0xffff
#define GDI_HANDLE_TYPE_SHIFT 16
#define GDI_HANDLE_TYPE_BITS 5
#define GDI_HANDLE_TYPE_MASK 0x1f
#define GDI_HANDLE_ALTTYPE_SHIFT 21
#define GDI_HANDLE_ALTTYPE_BITS 2
#define GDI_HANDLE_ALTTYPE_MASK 0x3
#define GDI_HANDLE_STOCK_SHIFT 23
#define GDI_HANDLE_STOCK_BITS 1
#define GDI_HANDLE_STOCK_MASK 0x1
#define GDI_HANDLE_UNIQUE_SHIFT 24
#define GDI_HANDLE_UNIQUE_BITS 8
#define GDI_HANDLE_UNIQUE_MASK 0xff
#define GDI_HANDLE_INDEX(Handle) ((ULONG)(Handle) & GDI_HANDLE_INDEX_MASK)
#define GDI_HANDLE_TYPE(Handle) (((ULONG)(Handle) >> GDI_HANDLE_TYPE_SHIFT) & GDI_HANDLE_TYPE_MASK)
#define GDI_HANDLE_ALTTYPE(Handle) (((ULONG)(Handle) >> GDI_HANDLE_ALTTYPE_SHIFT) & GDI_HANDLE_ALTTYPE_MASK)
#define GDI_HANDLE_STOCK(Handle) (((ULONG)(Handle) >> GDI_HANDLE_STOCK_SHIFT)) & GDI_HANDLE_STOCK_MASK)
#define GDI_MAKE_HANDLE(Index, Unique) ((ULONG)(((ULONG)(Unique) << GDI_HANDLE_INDEX_BITS) | (ULONG)(Index)))
// GDI server-side types
#define GDI_DEF_TYPE 0 // invalid handle
#define GDI_DC_TYPE 1
#define GDI_DD_DIRECTDRAW_TYPE 2
#define GDI_DD_SURFACE_TYPE 3
#define GDI_RGN_TYPE 4
#define GDI_SURF_TYPE 5
#define GDI_CLIENTOBJ_TYPE 6
#define GDI_PATH_TYPE 7
#define GDI_PAL_TYPE 8
#define GDI_ICMLCS_TYPE 9
#define GDI_LFONT_TYPE 10
#define GDI_RFONT_TYPE 11
#define GDI_PFE_TYPE 12
#define GDI_PFT_TYPE 13
#define GDI_ICMCXF_TYPE 14
#define GDI_ICMDLL_TYPE 15
#define GDI_BRUSH_TYPE 16
#define GDI_PFF_TYPE 17 // unused
#define GDI_CACHE_TYPE 18 // unused
#define GDI_SPACE_TYPE 19
#define GDI_DBRUSH_TYPE 20 // unused
#define GDI_META_TYPE 21
#define GDI_EFSTATE_TYPE 22
#define GDI_BMFD_TYPE 23 // unused
#define GDI_VTFD_TYPE 24 // unused
#define GDI_TTFD_TYPE 25 // unused
#define GDI_RC_TYPE 26 // unused
#define GDI_TEMP_TYPE 27 // unused
#define GDI_DRVOBJ_TYPE 28
#define GDI_DCIOBJ_TYPE 29 // unused
#define GDI_SPOOL_TYPE 30
// GDI client-side types
#define GDI_CLIENT_TYPE_FROM_HANDLE(Handle) ((ULONG)(Handle) & ((GDI_HANDLE_ALTTYPE_MASK << GDI_HANDLE_ALTTYPE_SHIFT) | \
(GDI_HANDLE_TYPE_MASK << GDI_HANDLE_TYPE_SHIFT)))
#define GDI_CLIENT_TYPE_FROM_UNIQUE(Unique) GDI_CLIENT_TYPE_FROM_HANDLE((ULONG)(Unique) << 16)
#define GDI_ALTTYPE_1 (1 << GDI_HANDLE_ALTTYPE_SHIFT)
#define GDI_ALTTYPE_2 (2 << GDI_HANDLE_ALTTYPE_SHIFT)
#define GDI_ALTTYPE_3 (3 << GDI_HANDLE_ALTTYPE_SHIFT)
#define GDI_CLIENT_BITMAP_TYPE (GDI_SURF_TYPE << GDI_HANDLE_TYPE_SHIFT)
#define GDI_CLIENT_BRUSH_TYPE (GDI_BRUSH_TYPE << GDI_HANDLE_TYPE_SHIFT)
#define GDI_CLIENT_CLIENTOBJ_TYPE (GDI_CLIENTOBJ_TYPE << GDI_HANDLE_TYPE_SHIFT)
#define GDI_CLIENT_DC_TYPE (GDI_DC_TYPE << GDI_HANDLE_TYPE_SHIFT)
#define GDI_CLIENT_FONT_TYPE (GDI_LFONT_TYPE << GDI_HANDLE_TYPE_SHIFT)
#define GDI_CLIENT_PALETTE_TYPE (GDI_PAL_TYPE << GDI_HANDLE_TYPE_SHIFT)
#define GDI_CLIENT_REGION_TYPE (GDI_RGN_TYPE << GDI_HANDLE_TYPE_SHIFT)
#define GDI_CLIENT_ALTDC_TYPE (GDI_CLIENT_DC_TYPE | GDI_ALTTYPE_1)
#define GDI_CLIENT_DIBSECTION_TYPE (GDI_CLIENT_BITMAP_TYPE | GDI_ALTTYPE_1)
#define GDI_CLIENT_EXTPEN_TYPE (GDI_CLIENT_BRUSH_TYPE | GDI_ALTTYPE_2)
#define GDI_CLIENT_METADC16_TYPE (GDI_CLIENT_CLIENTOBJ_TYPE | GDI_ALTTYPE_3)
#define GDI_CLIENT_METAFILE_TYPE (GDI_CLIENT_CLIENTOBJ_TYPE | GDI_ALTTYPE_2)
#define GDI_CLIENT_METAFILE16_TYPE (GDI_CLIENT_CLIENTOBJ_TYPE | GDI_ALTTYPE_1)
#define GDI_CLIENT_PEN_TYPE (GDI_CLIENT_BRUSH_TYPE | GDI_ALTTYPE_1)
typedef struct _GDI_HANDLE_ENTRY
{
union
{
PVOID Object;
PVOID NextFree;
};
union
{
struct
{
USHORT ProcessId;
USHORT Lock : 1;
USHORT Count : 15;
};
ULONG Value;
} Owner;
USHORT Unique;
UCHAR Type;
UCHAR Flags;
PVOID UserPointer;
} GDI_HANDLE_ENTRY, *PGDI_HANDLE_ENTRY;
typedef struct _GDI_SHARED_MEMORY
{
GDI_HANDLE_ENTRY Handles[GDI_MAX_HANDLE_COUNT];
} GDI_SHARED_MEMORY, *PGDI_SHARED_MEMORY;
#endif

File diff suppressed because it is too large Load Diff

@ -0,0 +1,176 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTKEAPI_H
#define _NTKEAPI_H
#if (PHNT_MODE != PHNT_MODE_KERNEL)
#define LOW_PRIORITY 0 // Lowest thread priority level
#define LOW_REALTIME_PRIORITY 16 // Lowest realtime priority level
#define HIGH_PRIORITY 31 // Highest thread priority level
#define MAXIMUM_PRIORITY 32 // Number of thread priority levels
#endif
typedef enum _KTHREAD_STATE
{
Initialized,
Ready,
Running,
Standby,
Terminated,
Waiting,
Transition,
DeferredReady,
GateWaitObsolete,
WaitingForProcessInSwap,
MaximumThreadState
} KTHREAD_STATE, *PKTHREAD_STATE;
// private
typedef enum _KHETERO_CPU_POLICY
{
KHeteroCpuPolicyAll,
KHeteroCpuPolicyLarge,
KHeteroCpuPolicyLargeOrIdle,
KHeteroCpuPolicySmall,
KHeteroCpuPolicySmallOrIdle,
KHeteroCpuPolicyDynamic,
KHeteroCpuPolicyStaticMax,
KHeteroCpuPolicyBiasedSmall,
KHeteroCpuPolicyBiasedLarge,
KHeteroCpuPolicyDefault,
KHeteroCpuPolicyMax
} KHETERO_CPU_POLICY, *PKHETERO_CPU_POLICY;
#if (PHNT_MODE != PHNT_MODE_KERNEL)
typedef enum _KWAIT_REASON
{
Executive,
FreePage,
PageIn,
PoolAllocation,
DelayExecution,
Suspended,
UserRequest,
WrExecutive,
WrFreePage,
WrPageIn,
WrPoolAllocation,
WrDelayExecution,
WrSuspended,
WrUserRequest,
WrEventPair,
WrQueue,
WrLpcReceive,
WrLpcReply,
WrVirtualMemory,
WrPageOut,
WrRendezvous,
WrKeyedEvent,
WrTerminated,
WrProcessInSwap,
WrCpuRateControl,
WrCalloutStack,
WrKernel,
WrResource,
WrPushLock,
WrMutex,
WrQuantumEnd,
WrDispatchInt,
WrPreempted,
WrYieldExecution,
WrFastMutex,
WrGuardedMutex,
WrRundown,
WrAlertByThreadId,
WrDeferredPreempt,
MaximumWaitReason
} KWAIT_REASON, *PKWAIT_REASON;
typedef enum _KPROFILE_SOURCE
{
ProfileTime,
ProfileAlignmentFixup,
ProfileTotalIssues,
ProfilePipelineDry,
ProfileLoadInstructions,
ProfilePipelineFrozen,
ProfileBranchInstructions,
ProfileTotalNonissues,
ProfileDcacheMisses,
ProfileIcacheMisses,
ProfileCacheMisses,
ProfileBranchMispredictions,
ProfileStoreInstructions,
ProfileFpInstructions,
ProfileIntegerInstructions,
Profile2Issue,
Profile3Issue,
Profile4Issue,
ProfileSpecialInstructions,
ProfileTotalCycles,
ProfileIcacheIssues,
ProfileDcacheAccesses,
ProfileMemoryBarrierCycles,
ProfileLoadLinkedIssues,
ProfileMaximum
} KPROFILE_SOURCE;
#endif
#if (PHNT_MODE != PHNT_MODE_KERNEL)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCallbackReturn(
_In_reads_bytes_opt_(OutputLength) PVOID OutputBuffer,
_In_ ULONG OutputLength,
_In_ NTSTATUS Status
);
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
VOID
NTAPI
NtFlushProcessWriteBuffers(
VOID
);
#endif
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryDebugFilterState(
_In_ ULONG ComponentId,
_In_ ULONG Level
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSetDebugFilterState(
_In_ ULONG ComponentId,
_In_ ULONG Level,
_In_ BOOLEAN State
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtYieldExecution(
VOID
);
#endif
#endif

@ -0,0 +1,951 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTLDR_H
#define _NTLDR_H
#if (PHNT_MODE != PHNT_MODE_KERNEL)
// DLLs
typedef BOOLEAN (NTAPI *PLDR_INIT_ROUTINE)(
_In_ PVOID DllHandle,
_In_ ULONG Reason,
_In_opt_ PVOID Context
);
// symbols
typedef struct _LDR_SERVICE_TAG_RECORD
{
struct _LDR_SERVICE_TAG_RECORD *Next;
ULONG ServiceTag;
} LDR_SERVICE_TAG_RECORD, *PLDR_SERVICE_TAG_RECORD;
// symbols
typedef struct _LDRP_CSLIST
{
PSINGLE_LIST_ENTRY Tail;
} LDRP_CSLIST, *PLDRP_CSLIST;
// symbols
typedef enum _LDR_DDAG_STATE
{
LdrModulesMerged = -5,
LdrModulesInitError = -4,
LdrModulesSnapError = -3,
LdrModulesUnloaded = -2,
LdrModulesUnloading = -1,
LdrModulesPlaceHolder = 0,
LdrModulesMapping = 1,
LdrModulesMapped = 2,
LdrModulesWaitingForDependencies = 3,
LdrModulesSnapping = 4,
LdrModulesSnapped = 5,
LdrModulesCondensed = 6,
LdrModulesReadyToInit = 7,
LdrModulesInitializing = 8,
LdrModulesReadyToRun = 9
} LDR_DDAG_STATE;
// symbols
typedef struct _LDR_DDAG_NODE
{
LIST_ENTRY Modules;
PLDR_SERVICE_TAG_RECORD ServiceTagList;
ULONG LoadCount;
ULONG LoadWhileUnloadingCount;
ULONG LowestLink;
union
{
LDRP_CSLIST Dependencies;
SINGLE_LIST_ENTRY RemovalLink;
};
LDRP_CSLIST IncomingDependencies;
LDR_DDAG_STATE State;
SINGLE_LIST_ENTRY CondenseLink;
ULONG PreorderNumber;
} LDR_DDAG_NODE, *PLDR_DDAG_NODE;
// rev
typedef struct _LDR_DEPENDENCY_RECORD
{
SINGLE_LIST_ENTRY DependencyLink;
PLDR_DDAG_NODE DependencyNode;
SINGLE_LIST_ENTRY IncomingDependencyLink;
PLDR_DDAG_NODE IncomingDependencyNode;
} LDR_DEPENDENCY_RECORD, *PLDR_DEPENDENCY_RECORD;
// symbols
typedef enum _LDR_DLL_LOAD_REASON
{
LoadReasonStaticDependency,
LoadReasonStaticForwarderDependency,
LoadReasonDynamicForwarderDependency,
LoadReasonDelayloadDependency,
LoadReasonDynamicLoad,
LoadReasonAsImageLoad,
LoadReasonAsDataLoad,
LoadReasonEnclavePrimary, // REDSTONE3
LoadReasonEnclaveDependency,
LoadReasonUnknown = -1
} LDR_DLL_LOAD_REASON, *PLDR_DLL_LOAD_REASON;
#define LDRP_PACKAGED_BINARY 0x00000001
#define LDRP_STATIC_LINK 0x00000002
#define LDRP_IMAGE_DLL 0x00000004
#define LDRP_LOAD_IN_PROGRESS 0x00001000
#define LDRP_UNLOAD_IN_PROGRESS 0x00002000
#define LDRP_ENTRY_PROCESSED 0x00004000
#define LDRP_ENTRY_INSERTED 0x00008000
#define LDRP_CURRENT_LOAD 0x00010000
#define LDRP_FAILED_BUILTIN_LOAD 0x00020000
#define LDRP_DONT_CALL_FOR_THREADS 0x00040000
#define LDRP_PROCESS_ATTACH_CALLED 0x00080000
#define LDRP_DEBUG_SYMBOLS_LOADED 0x00100000
#define LDRP_IMAGE_NOT_AT_BASE 0x00200000 // Vista and below
#define LDRP_COR_IMAGE 0x00400000
#define LDRP_DONT_RELOCATE 0x00800000 // LDR_COR_OWNS_UNMAP
#define LDRP_SYSTEM_MAPPED 0x01000000
#define LDRP_IMAGE_VERIFYING 0x02000000
#define LDRP_DRIVER_DEPENDENT_DLL 0x04000000
#define LDRP_ENTRY_NATIVE 0x08000000
#define LDRP_REDIRECTED 0x10000000
#define LDRP_NON_PAGED_DEBUG_INFO 0x20000000
#define LDRP_MM_LOADED 0x40000000
#define LDRP_COMPAT_DATABASE_PROCESSED 0x80000000
#define LDR_DATA_TABLE_ENTRY_SIZE_WINXP FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, DdagNode)
#define LDR_DATA_TABLE_ENTRY_SIZE_WIN7 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, BaseNameHashValue)
#define LDR_DATA_TABLE_ENTRY_SIZE_WIN8 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, ImplicitPathOptions)
#define LDR_DATA_TABLE_ENTRY_SIZE_WIN10 sizeof(LDR_DATA_TABLE_ENTRY)
// symbols
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
union
{
LIST_ENTRY InInitializationOrderLinks;
LIST_ENTRY InProgressLinks;
};
PVOID DllBase;
PLDR_INIT_ROUTINE EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
union
{
UCHAR FlagGroup[4];
ULONG Flags;
struct
{
ULONG PackagedBinary : 1;
ULONG MarkedForRemoval : 1;
ULONG ImageDll : 1;
ULONG LoadNotificationsSent : 1;
ULONG TelemetryEntryProcessed : 1;
ULONG ProcessStaticImport : 1;
ULONG InLegacyLists : 1;
ULONG InIndexes : 1;
ULONG ShimDll : 1;
ULONG InExceptionTable : 1;
ULONG ReservedFlags1 : 2;
ULONG LoadInProgress : 1;
ULONG LoadConfigProcessed : 1;
ULONG EntryProcessed : 1;
ULONG ProtectDelayLoad : 1;
ULONG ReservedFlags3 : 2;
ULONG DontCallForThreads : 1;
ULONG ProcessAttachCalled : 1;
ULONG ProcessAttachFailed : 1;
ULONG CorDeferredValidate : 1;
ULONG CorImage : 1;
ULONG DontRelocate : 1;
ULONG CorILOnly : 1;
ULONG ChpeImage : 1;
ULONG ReservedFlags5 : 2;
ULONG Redirected : 1;
ULONG ReservedFlags6 : 2;
ULONG CompatDatabaseProcessed : 1;
};
};
USHORT ObsoleteLoadCount;
USHORT TlsIndex;
LIST_ENTRY HashLinks;
ULONG TimeDateStamp;
struct _ACTIVATION_CONTEXT *EntryPointActivationContext;
PVOID Lock; // RtlAcquireSRWLockExclusive
PLDR_DDAG_NODE DdagNode;
LIST_ENTRY NodeModuleLink;
struct _LDRP_LOAD_CONTEXT *LoadContext;
PVOID ParentDllBase;
PVOID SwitchBackContext;
RTL_BALANCED_NODE BaseAddressIndexNode;
RTL_BALANCED_NODE MappingInfoIndexNode;
ULONG_PTR OriginalBase;
LARGE_INTEGER LoadTime;
ULONG BaseNameHashValue;
LDR_DLL_LOAD_REASON LoadReason;
ULONG ImplicitPathOptions;
ULONG ReferenceCount;
ULONG DependentLoadFlags;
UCHAR SigningLevel; // since REDSTONE2
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
#define LDR_IS_DATAFILE(DllHandle) (((ULONG_PTR)(DllHandle)) & (ULONG_PTR)1)
#define LDR_IS_IMAGEMAPPING(DllHandle) (((ULONG_PTR)(DllHandle)) & (ULONG_PTR)2)
#define LDR_IS_RESOURCE(DllHandle) (LDR_IS_IMAGEMAPPING(DllHandle) || LDR_IS_DATAFILE(DllHandle))
NTSYSAPI
NTSTATUS
NTAPI
LdrLoadDll(
_In_opt_ PWSTR DllPath,
_In_opt_ PULONG DllCharacteristics,
_In_ PUNICODE_STRING DllName,
_Out_ PVOID *DllHandle
);
NTSYSAPI
NTSTATUS
NTAPI
LdrUnloadDll(
_In_ PVOID DllHandle
);
NTSYSAPI
NTSTATUS
NTAPI
LdrGetDllHandle(
_In_opt_ PWSTR DllPath,
_In_opt_ PULONG DllCharacteristics,
_In_ PUNICODE_STRING DllName,
_Out_ PVOID *DllHandle
);
#define LDR_GET_DLL_HANDLE_EX_UNCHANGED_REFCOUNT 0x00000001
#define LDR_GET_DLL_HANDLE_EX_PIN 0x00000002
NTSYSAPI
NTSTATUS
NTAPI
LdrGetDllHandleEx(
_In_ ULONG Flags,
_In_opt_ PWSTR DllPath,
_In_opt_ PULONG DllCharacteristics,
_In_ PUNICODE_STRING DllName,
_Out_opt_ PVOID *DllHandle
);
#if (PHNT_VERSION >= PHNT_WIN7)
// rev
NTSYSAPI
NTSTATUS
NTAPI
LdrGetDllHandleByMapping(
_In_ PVOID BaseAddress,
_Out_ PVOID *DllHandle
);
#endif
#if (PHNT_VERSION >= PHNT_WIN7)
// rev
NTSYSAPI
NTSTATUS
NTAPI
LdrGetDllHandleByName(
_In_opt_ PUNICODE_STRING BaseDllName,
_In_opt_ PUNICODE_STRING FullDllName,
_Out_ PVOID *DllHandle
);
#endif
#if (PHNT_VERSION >= PHNT_WIN8)
// rev
NTSYSAPI
NTSTATUS
NTAPI
LdrGetDllFullName(
_In_ PVOID DllHandle,
_Out_ PUNICODE_STRING FullDllName
);
// rev
NTSYSAPI
NTSTATUS
NTAPI
LdrGetDllDirectory(
_Out_ PUNICODE_STRING DllDirectory
);
// rev
NTSYSAPI
NTSTATUS
NTAPI
LdrSetDllDirectory(
_In_ PUNICODE_STRING DllDirectory
);
#endif
#define LDR_ADDREF_DLL_PIN 0x00000001
NTSYSAPI
NTSTATUS
NTAPI
LdrAddRefDll(
_In_ ULONG Flags,
_In_ PVOID DllHandle
);
NTSYSAPI
NTSTATUS
NTAPI
LdrGetProcedureAddress(
_In_ PVOID DllHandle,
_In_opt_ PANSI_STRING ProcedureName,
_In_opt_ ULONG ProcedureNumber,
_Out_ PVOID *ProcedureAddress
);
// rev
#define LDR_GET_PROCEDURE_ADDRESS_DONT_RECORD_FORWARDER 0x00000001
#if (PHNT_VERSION >= PHNT_VISTA)
// private
NTSYSAPI
NTSTATUS
NTAPI
LdrGetProcedureAddressEx(
_In_ PVOID DllHandle,
_In_opt_ PANSI_STRING ProcedureName,
_In_opt_ ULONG ProcedureNumber,
_Out_ PVOID *ProcedureAddress,
_In_ ULONG Flags
);
#endif
NTSYSAPI
NTSTATUS
NTAPI
LdrGetKnownDllSectionHandle(
_In_ PCWSTR DllName,
_In_ BOOLEAN KnownDlls32,
_Out_ PHANDLE Section
);
#if (PHNT_VERSION >= PHNT_THRESHOLD)
// rev
NTSYSAPI
NTSTATUS
NTAPI
LdrGetProcedureAddressForCaller(
_In_ PVOID DllHandle,
_In_opt_ PANSI_STRING ProcedureName,
_In_opt_ ULONG ProcedureNumber,
_Out_ PVOID *ProcedureAddress,
_In_ ULONG Flags,
_In_ PVOID *Callback
);
#endif
#define LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS 0x00000001
#define LDR_LOCK_LOADER_LOCK_FLAG_TRY_ONLY 0x00000002
#define LDR_LOCK_LOADER_LOCK_DISPOSITION_INVALID 0
#define LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_ACQUIRED 1
#define LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_NOT_ACQUIRED 2
NTSYSAPI
NTSTATUS
NTAPI
LdrLockLoaderLock(
_In_ ULONG Flags,
_Out_opt_ ULONG *Disposition,
_Out_ PVOID *Cookie
);
#define LDR_UNLOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS 0x00000001
NTSYSAPI
NTSTATUS
NTAPI
LdrUnlockLoaderLock(
_In_ ULONG Flags,
_Inout_ PVOID Cookie
);
NTSYSAPI
NTSTATUS
NTAPI
LdrRelocateImage(
_In_ PVOID NewBase,
_In_ PSTR LoaderName,
_In_ NTSTATUS Success,
_In_ NTSTATUS Conflict,
_In_ NTSTATUS Invalid
);
NTSYSAPI
NTSTATUS
NTAPI
LdrRelocateImageWithBias(
_In_ PVOID NewBase,
_In_ LONGLONG Bias,
_In_ PSTR LoaderName,
_In_ NTSTATUS Success,
_In_ NTSTATUS Conflict,
_In_ NTSTATUS Invalid
);
NTSYSAPI
PIMAGE_BASE_RELOCATION
NTAPI
LdrProcessRelocationBlock(
_In_ ULONG_PTR VA,
_In_ ULONG SizeOfBlock,
_In_ PUSHORT NextOffset,
_In_ LONG_PTR Diff
);
NTSYSAPI
BOOLEAN
NTAPI
LdrVerifyMappedImageMatchesChecksum(
_In_ PVOID BaseAddress,
_In_ SIZE_T NumberOfBytes,
_In_ ULONG FileLength
);
typedef VOID (NTAPI *PLDR_IMPORT_MODULE_CALLBACK)(
_In_ PVOID Parameter,
_In_ PSTR ModuleName
);
NTSYSAPI
NTSTATUS
NTAPI
LdrVerifyImageMatchesChecksum(
_In_ HANDLE ImageFileHandle,
_In_opt_ PLDR_IMPORT_MODULE_CALLBACK ImportCallbackRoutine,
_In_ PVOID ImportCallbackParameter,
_Out_opt_ PUSHORT ImageCharacteristics
);
// private
typedef struct _LDR_IMPORT_CALLBACK_INFO
{
PLDR_IMPORT_MODULE_CALLBACK ImportCallbackRoutine;
PVOID ImportCallbackParameter;
} LDR_IMPORT_CALLBACK_INFO, *PLDR_IMPORT_CALLBACK_INFO;
// private
typedef struct _LDR_SECTION_INFO
{
HANDLE SectionHandle;
ACCESS_MASK DesiredAccess;
POBJECT_ATTRIBUTES ObjA;
ULONG SectionPageProtection;
ULONG AllocationAttributes;
} LDR_SECTION_INFO, *PLDR_SECTION_INFO;
// private
typedef struct _LDR_VERIFY_IMAGE_INFO
{
ULONG Size;
ULONG Flags;
LDR_IMPORT_CALLBACK_INFO CallbackInfo;
LDR_SECTION_INFO SectionInfo;
USHORT ImageCharacteristics;
} LDR_VERIFY_IMAGE_INFO, *PLDR_VERIFY_IMAGE_INFO;
#if (PHNT_VERSION >= PHNT_VISTA)
// private
NTSYSAPI
NTSTATUS
NTAPI
LdrVerifyImageMatchesChecksumEx(
_In_ HANDLE ImageFileHandle,
_Inout_ PLDR_VERIFY_IMAGE_INFO VerifyInfo
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
// private
NTSYSAPI
NTSTATUS
NTAPI
LdrQueryModuleServiceTags(
_In_ PVOID DllHandle,
_Out_writes_(*BufferSize) PULONG ServiceTagBuffer,
_Inout_ PULONG BufferSize
);
#endif
// begin_msdn:"DLL Load Notification"
#define LDR_DLL_NOTIFICATION_REASON_LOADED 1
#define LDR_DLL_NOTIFICATION_REASON_UNLOADED 2
typedef struct _LDR_DLL_LOADED_NOTIFICATION_DATA
{
ULONG Flags;
PUNICODE_STRING FullDllName;
PUNICODE_STRING BaseDllName;
PVOID DllBase;
ULONG SizeOfImage;
} LDR_DLL_LOADED_NOTIFICATION_DATA, *PLDR_DLL_LOADED_NOTIFICATION_DATA;
typedef struct _LDR_DLL_UNLOADED_NOTIFICATION_DATA
{
ULONG Flags;
PCUNICODE_STRING FullDllName;
PCUNICODE_STRING BaseDllName;
PVOID DllBase;
ULONG SizeOfImage;
} LDR_DLL_UNLOADED_NOTIFICATION_DATA, *PLDR_DLL_UNLOADED_NOTIFICATION_DATA;
typedef union _LDR_DLL_NOTIFICATION_DATA
{
LDR_DLL_LOADED_NOTIFICATION_DATA Loaded;
LDR_DLL_UNLOADED_NOTIFICATION_DATA Unloaded;
} LDR_DLL_NOTIFICATION_DATA, *PLDR_DLL_NOTIFICATION_DATA;
typedef VOID (NTAPI *PLDR_DLL_NOTIFICATION_FUNCTION)(
_In_ ULONG NotificationReason,
_In_ PLDR_DLL_NOTIFICATION_DATA NotificationData,
_In_opt_ PVOID Context
);
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSAPI
NTSTATUS
NTAPI
LdrRegisterDllNotification(
_In_ ULONG Flags,
_In_ PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction,
_In_ PVOID Context,
_Out_ PVOID *Cookie
);
NTSYSAPI
NTSTATUS
NTAPI
LdrUnregisterDllNotification(
_In_ PVOID Cookie
);
#endif
// end_msdn
// rev
NTSYSAPI
PUNICODE_STRING
NTAPI
LdrStandardizeSystemPath(
_In_ PUNICODE_STRING SystemPath
);
// private
typedef struct _PS_MITIGATION_OPTIONS_MAP
{
ULONG_PTR Map[2];
} PS_MITIGATION_OPTIONS_MAP, *PPS_MITIGATION_OPTIONS_MAP;
// private
typedef struct _PS_MITIGATION_AUDIT_OPTIONS_MAP
{
ULONG_PTR Map[2];
} PS_MITIGATION_AUDIT_OPTIONS_MAP, *PPS_MITIGATION_AUDIT_OPTIONS_MAP;
// private
typedef struct _PS_SYSTEM_DLL_INIT_BLOCK
{
ULONG Size;
ULONG_PTR SystemDllWowRelocation;
ULONG_PTR SystemDllNativeRelocation;
ULONG_PTR Wow64SharedInformation[16];
ULONG RngData;
union
{
ULONG Flags;
struct
{
ULONG CfgOverride : 1;
ULONG Reserved : 31;
};
};
PS_MITIGATION_OPTIONS_MAP MitigationOptionsMap;
ULONG_PTR CfgBitMap;
ULONG_PTR CfgBitMapSize;
ULONG_PTR Wow64CfgBitMap;
ULONG_PTR Wow64CfgBitMapSize;
PS_MITIGATION_AUDIT_OPTIONS_MAP MitigationAuditOptionsMap; // REDSTONE3
} PS_SYSTEM_DLL_INIT_BLOCK, *PPS_SYSTEM_DLL_INIT_BLOCK;
#if (PHNT_VERSION >= PHNT_THRESHOLD)
// rev
NTSYSAPI
PPS_SYSTEM_DLL_INIT_BLOCK
NTAPI
LdrSystemDllInitBlock(
VOID
);
#endif
// Load as data table
#if (PHNT_VERSION >= PHNT_VISTA)
// private
NTSYSAPI
NTSTATUS
NTAPI
LdrAddLoadAsDataTable(
_In_ PVOID Module,
_In_ PWSTR FilePath,
_In_ SIZE_T Size,
_In_ HANDLE Handle
);
// private
NTSYSAPI
NTSTATUS
NTAPI
LdrRemoveLoadAsDataTable(
_In_ PVOID InitModule,
_Out_opt_ PVOID *BaseModule,
_Out_opt_ PSIZE_T Size,
_In_ ULONG Flags
);
// private
NTSYSAPI
NTSTATUS
NTAPI
LdrGetFileNameFromLoadAsDataTable(
_In_ PVOID Module,
_Out_ PVOID *pFileNamePrt
);
#endif
NTSYSAPI
NTSTATUS
NTAPI
LdrDisableThreadCalloutsForDll(
_In_ PVOID DllImageBase
);
// Resources
NTSYSAPI
NTSTATUS
NTAPI
LdrAccessResource(
_In_ PVOID DllHandle,
_In_ PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry,
_Out_opt_ PVOID *ResourceBuffer,
_Out_opt_ ULONG *ResourceLength
);
typedef struct _LDR_RESOURCE_INFO
{
ULONG_PTR Type;
ULONG_PTR Name;
ULONG_PTR Language;
} LDR_RESOURCE_INFO, *PLDR_RESOURCE_INFO;
#define RESOURCE_TYPE_LEVEL 0
#define RESOURCE_NAME_LEVEL 1
#define RESOURCE_LANGUAGE_LEVEL 2
#define RESOURCE_DATA_LEVEL 3
NTSYSAPI
NTSTATUS
NTAPI
LdrFindResource_U(
_In_ PVOID DllHandle,
_In_ PLDR_RESOURCE_INFO ResourceInfo,
_In_ ULONG Level,
_Out_ PIMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry
);
NTSYSAPI
NTSTATUS
NTAPI
LdrFindResourceDirectory_U(
_In_ PVOID DllHandle,
_In_ PLDR_RESOURCE_INFO ResourceInfo,
_In_ ULONG Level,
_Out_ PIMAGE_RESOURCE_DIRECTORY *ResourceDirectory
);
// private
typedef struct _LDR_ENUM_RESOURCE_ENTRY
{
union
{
ULONG_PTR NameOrId;
PIMAGE_RESOURCE_DIRECTORY_STRING Name;
struct
{
USHORT Id;
USHORT NameIsPresent;
};
} Path[3];
PVOID Data;
ULONG Size;
ULONG Reserved;
} LDR_ENUM_RESOURCE_ENTRY, *PLDR_ENUM_RESOURCE_ENTRY;
#define NAME_FROM_RESOURCE_ENTRY(RootDirectory, Entry) \
((Entry)->NameIsString ? (ULONG_PTR)PTR_ADD_OFFSET((RootDirectory), (Entry)->NameOffset) : (Entry)->Id)
NTSYSAPI
NTSTATUS
NTAPI
LdrEnumResources(
_In_ PVOID DllHandle,
_In_ PLDR_RESOURCE_INFO ResourceInfo,
_In_ ULONG Level,
_Inout_ ULONG *ResourceCount,
_Out_writes_to_opt_(*ResourceCount, *ResourceCount) PLDR_ENUM_RESOURCE_ENTRY Resources
);
NTSYSAPI
NTSTATUS
NTAPI
LdrFindEntryForAddress(
_In_ PVOID DllHandle,
_Out_ PLDR_DATA_TABLE_ENTRY *Entry
);
#endif // (PHNT_MODE != PHNT_MODE_KERNEL)
// Module information
typedef struct _RTL_PROCESS_MODULE_INFORMATION
{
HANDLE Section;
PVOID MappedBase;
PVOID ImageBase;
ULONG ImageSize;
ULONG Flags;
USHORT LoadOrderIndex;
USHORT InitOrderIndex;
USHORT LoadCount;
USHORT OffsetToFileName;
UCHAR FullPathName[256];
} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION;
typedef struct _RTL_PROCESS_MODULES
{
ULONG NumberOfModules;
RTL_PROCESS_MODULE_INFORMATION Modules[1];
} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES;
// private
typedef struct _RTL_PROCESS_MODULE_INFORMATION_EX
{
USHORT NextOffset;
RTL_PROCESS_MODULE_INFORMATION BaseInfo;
ULONG ImageChecksum;
ULONG TimeDateStamp;
PVOID DefaultBase;
} RTL_PROCESS_MODULE_INFORMATION_EX, *PRTL_PROCESS_MODULE_INFORMATION_EX;
#if (PHNT_MODE != PHNT_MODE_KERNEL)
NTSYSAPI
NTSTATUS
NTAPI
LdrQueryProcessModuleInformation(
_In_opt_ PRTL_PROCESS_MODULES ModuleInformation,
_In_opt_ ULONG Size,
_Out_ PULONG ReturnedSize
);
typedef VOID (NTAPI *PLDR_ENUM_CALLBACK)(
_In_ PLDR_DATA_TABLE_ENTRY ModuleInformation,
_In_ PVOID Parameter,
_Out_ BOOLEAN *Stop
);
NTSYSAPI
NTSTATUS
NTAPI
LdrEnumerateLoadedModules(
_In_ BOOLEAN ReservedFlag,
_In_ PLDR_ENUM_CALLBACK EnumProc,
_In_ PVOID Context
);
NTSYSAPI
NTSTATUS
NTAPI
LdrOpenImageFileOptionsKey(
_In_ PUNICODE_STRING SubKey,
_In_ BOOLEAN Wow64,
_Out_ PHANDLE NewKeyHandle
);
NTSYSAPI
NTSTATUS
NTAPI
LdrQueryImageFileKeyOption(
_In_ HANDLE KeyHandle,
_In_ PCWSTR ValueName,
_In_ ULONG Type,
_Out_ PVOID Buffer,
_In_ ULONG BufferSize,
_Out_opt_ PULONG ReturnedLength
);
NTSYSAPI
NTSTATUS
NTAPI
LdrQueryImageFileExecutionOptions(
_In_ PUNICODE_STRING SubKey,
_In_ PCWSTR ValueName,
_In_ ULONG ValueSize,
_Out_ PVOID Buffer,
_In_ ULONG BufferSize,
_Out_opt_ PULONG ReturnedLength
);
NTSYSAPI
NTSTATUS
NTAPI
LdrQueryImageFileExecutionOptionsEx(
_In_ PUNICODE_STRING SubKey,
_In_ PCWSTR ValueName,
_In_ ULONG Type,
_Out_ PVOID Buffer,
_In_ ULONG BufferSize,
_Out_opt_ PULONG ReturnedLength,
_In_ BOOLEAN Wow64
);
// private
typedef struct _DELAYLOAD_PROC_DESCRIPTOR
{
ULONG ImportDescribedByName;
union
{
PCSTR Name;
ULONG Ordinal;
} Description;
} DELAYLOAD_PROC_DESCRIPTOR, *PDELAYLOAD_PROC_DESCRIPTOR;
// private
typedef struct _DELAYLOAD_INFO
{
ULONG Size;
PCIMAGE_DELAYLOAD_DESCRIPTOR DelayloadDescriptor;
PIMAGE_THUNK_DATA ThunkAddress;
PCSTR TargetDllName;
DELAYLOAD_PROC_DESCRIPTOR TargetApiDescriptor;
PVOID TargetModuleBase;
PVOID Unused;
ULONG LastError;
} DELAYLOAD_INFO, *PDELAYLOAD_INFO;
// private
typedef PVOID (NTAPI *PDELAYLOAD_FAILURE_DLL_CALLBACK)(
_In_ ULONG NotificationReason,
_In_ PDELAYLOAD_INFO DelayloadInfo
);
// rev
typedef PVOID (NTAPI *PDELAYLOAD_FAILURE_SYSTEM_ROUTINE)(
_In_ PCSTR DllName,
_In_ PCSTR ProcName
);
// rev
NTSYSAPI
PVOID
NTAPI
LdrResolveDelayLoadedAPI(
_In_ PVOID ParentModuleBase,
_In_ PCIMAGE_DELAYLOAD_DESCRIPTOR DelayloadDescriptor,
_In_opt_ PDELAYLOAD_FAILURE_DLL_CALLBACK FailureDllHook,
_In_opt_ PDELAYLOAD_FAILURE_SYSTEM_ROUTINE FailureSystemHook, // kernel32.DelayLoadFailureHook
_Out_ PIMAGE_THUNK_DATA ThunkAddress,
_Reserved_ ULONG Flags
);
// rev
NTSYSAPI
NTSTATUS
NTAPI
LdrResolveDelayLoadsFromDll(
_In_ PVOID ParentBase,
_In_ PCSTR TargetDllName,
_Reserved_ ULONG Flags
);
// rev
NTSYSAPI
NTSTATUS
NTAPI
LdrSetDefaultDllDirectories(
_In_ ULONG DirectoryFlags
);
// rev
NTSYSAPI
NTSTATUS
NTAPI
LdrShutdownProcess(
VOID
);
// rev
NTSYSAPI
NTSTATUS
NTAPI
LdrShutdownThread(
VOID
);
// rev
NTSYSAPI
NTSTATUS
NTAPI
LdrSetImplicitPathOptions(
_In_ ULONG ImplicitPathOptions
);
// rev
NTSYSAPI
BOOLEAN
NTAPI
LdrControlFlowGuardEnforced(
VOID
);
#if (PHNT_VERSION >= PHNT_19H1)
// rev
NTSYSAPI
BOOLEAN
NTAPI
LdrIsModuleSxsRedirected(
_In_ PVOID DllHandle
);
#endif
#endif // (PHNT_MODE != PHNT_MODE_KERNEL)
#endif

File diff suppressed because it is too large Load Diff

@ -0,0 +1,117 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTMISC_H
#define _NTMISC_H
// Filter manager
#define FLT_PORT_CONNECT 0x0001
#define FLT_PORT_ALL_ACCESS (FLT_PORT_CONNECT | STANDARD_RIGHTS_ALL)
// VDM
typedef enum _VDMSERVICECLASS
{
VdmStartExecution,
VdmQueueInterrupt,
VdmDelayInterrupt,
VdmInitialize,
VdmFeatures,
VdmSetInt21Handler,
VdmQueryDir,
VdmPrinterDirectIoOpen,
VdmPrinterDirectIoClose,
VdmPrinterInitialize,
VdmSetLdtEntries,
VdmSetProcessLdtInfo,
VdmAdlibEmulation,
VdmPMCliControl,
VdmQueryVdmProcess
} VDMSERVICECLASS, *PVDMSERVICECLASS;
NTSYSCALLAPI
NTSTATUS
NTAPI
NtVdmControl(
_In_ VDMSERVICECLASS Service,
_Inout_ PVOID ServiceData
);
// WMI/ETW
NTSYSCALLAPI
NTSTATUS
NTAPI
NtTraceEvent(
_In_ HANDLE TraceHandle,
_In_ ULONG Flags,
_In_ ULONG FieldSize,
_In_ PVOID Fields
);
typedef enum _TRACE_CONTROL_INFORMATION_CLASS
{
TraceControlStartLogger = 1,
TraceControlStopLogger = 2,
TraceControlQueryLogger = 3,
TraceControlUpdateLogger = 4,
TraceControlFlushLogger = 5,
TraceControlIncrementLoggerFile = 6,
TraceControlRealtimeConnect = 11,
TraceControlWdiDispatchControl = 13,
TraceControlRealtimeDisconnectConsumerByHandle = 14,
TraceControlReceiveNotification = 16,
TraceControlEnableGuid = 17,
TraceControlSendReplyDataBlock = 18,
TraceControlReceiveReplyDataBlock = 19,
TraceControlWdiUpdateSem = 20,
TraceControlGetTraceGuidList = 21,
TraceControlGetTraceGuidInfo = 22,
TraceControlEnumerateTraceGuids = 23,
TraceControlQueryReferenceTime = 25,
TraceControlTrackProviderBinary = 26,
TraceControlAddNotificationEvent = 27,
TraceControlUpdateDisallowList = 28,
TraceControlUseDescriptorTypeUm = 31,
TraceControlGetTraceGroupList = 32,
TraceControlGetTraceGroupInfo = 33,
TraceControlTraceSetDisallowList= 34,
TraceControlSetCompressionSettings = 35,
TraceControlGetCompressionSettings= 36,
TraceControlUpdatePeriodicCaptureState = 37,
TraceControlGetPrivateSessionTraceHandle = 38,
TraceControlRegisterPrivateSession = 39,
TraceControlQuerySessionDemuxObject = 40,
TraceControlSetProviderBinaryTracking = 41,
TraceControlMaxLoggers = 42,
TraceControlMaxPmcCounter = 43
} TRACE_CONTROL_INFORMATION_CLASS;
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtTraceControl(
_In_ TRACE_CONTROL_INFORMATION_CLASS TraceInformationClass,
_In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
_In_ ULONG InputBufferLength,
_Out_writes_bytes_opt_(TraceInformationLength) PVOID TraceInformation,
_In_ ULONG TraceInformationLength,
_Out_ PULONG ReturnLength
);
#endif
#endif

File diff suppressed because it is too large Load Diff

@ -0,0 +1,47 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTNLS_H
#define _NTNLS_H
#define MAXIMUM_LEADBYTES 12
typedef struct _CPTABLEINFO
{
USHORT CodePage;
USHORT MaximumCharacterSize;
USHORT DefaultChar;
USHORT UniDefaultChar;
USHORT TransDefaultChar;
USHORT TransUniDefaultChar;
USHORT DBCSCodePage;
UCHAR LeadByte[MAXIMUM_LEADBYTES];
PUSHORT MultiByteTable;
PVOID WideCharTable;
PUSHORT DBCSRanges;
PUSHORT DBCSOffsets;
} CPTABLEINFO, *PCPTABLEINFO;
typedef struct _NLSTABLEINFO
{
CPTABLEINFO OemTableInfo;
CPTABLEINFO AnsiTableInfo;
PUSHORT UpperCaseTable;
PUSHORT LowerCaseTable;
} NLSTABLEINFO, *PNLSTABLEINFO;
#if (PHNT_MODE != PHNT_MODE_KERNEL)
NTSYSAPI USHORT NlsAnsiCodePage;
NTSYSAPI BOOLEAN NlsMbCodePageTag;
NTSYSAPI BOOLEAN NlsMbOemCodePageTag;
#endif
#endif

@ -0,0 +1,385 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTOBAPI_H
#define _NTOBAPI_H
#if (PHNT_MODE != PHNT_MODE_KERNEL)
#define OBJECT_TYPE_CREATE 0x0001
#define OBJECT_TYPE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1)
#endif
#if (PHNT_MODE != PHNT_MODE_KERNEL)
#define DIRECTORY_QUERY 0x0001
#define DIRECTORY_TRAVERSE 0x0002
#define DIRECTORY_CREATE_OBJECT 0x0004
#define DIRECTORY_CREATE_SUBDIRECTORY 0x0008
#define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xf)
#endif
#if (PHNT_MODE != PHNT_MODE_KERNEL)
#define SYMBOLIC_LINK_QUERY 0x0001
#define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1)
#endif
#define OBJ_PROTECT_CLOSE 0x00000001
#ifndef OBJ_INHERIT
#define OBJ_INHERIT 0x00000002
#endif
#define OBJ_AUDIT_OBJECT_CLOSE 0x00000004
#if (PHNT_MODE != PHNT_MODE_KERNEL)
typedef enum _OBJECT_INFORMATION_CLASS
{
ObjectBasicInformation, // OBJECT_BASIC_INFORMATION
ObjectNameInformation, // OBJECT_NAME_INFORMATION
ObjectTypeInformation, // OBJECT_TYPE_INFORMATION
ObjectTypesInformation, // OBJECT_TYPES_INFORMATION
ObjectHandleFlagInformation, // OBJECT_HANDLE_FLAG_INFORMATION
ObjectSessionInformation,
ObjectSessionObjectInformation,
MaxObjectInfoClass
} OBJECT_INFORMATION_CLASS;
#else
#define ObjectBasicInformation 0
#define ObjectNameInformation 1
#define ObjectTypesInformation 3
#define ObjectHandleFlagInformation 4
#define ObjectSessionInformation 5
#define ObjectSessionObjectInformation 6
#endif
typedef struct _OBJECT_BASIC_INFORMATION
{
ULONG Attributes;
ACCESS_MASK GrantedAccess;
ULONG HandleCount;
ULONG PointerCount;
ULONG PagedPoolCharge;
ULONG NonPagedPoolCharge;
ULONG Reserved[3];
ULONG NameInfoSize;
ULONG TypeInfoSize;
ULONG SecurityDescriptorSize;
LARGE_INTEGER CreationTime;
} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION;
#if (PHNT_MODE != PHNT_MODE_KERNEL)
typedef struct _OBJECT_NAME_INFORMATION
{
UNICODE_STRING Name;
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
#endif
typedef struct _OBJECT_TYPE_INFORMATION
{
UNICODE_STRING TypeName;
ULONG TotalNumberOfObjects;
ULONG TotalNumberOfHandles;
ULONG TotalPagedPoolUsage;
ULONG TotalNonPagedPoolUsage;
ULONG TotalNamePoolUsage;
ULONG TotalHandleTableUsage;
ULONG HighWaterNumberOfObjects;
ULONG HighWaterNumberOfHandles;
ULONG HighWaterPagedPoolUsage;
ULONG HighWaterNonPagedPoolUsage;
ULONG HighWaterNamePoolUsage;
ULONG HighWaterHandleTableUsage;
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ULONG ValidAccessMask;
BOOLEAN SecurityRequired;
BOOLEAN MaintainHandleCount;
UCHAR TypeIndex; // since WINBLUE
CHAR ReservedByte;
ULONG PoolType;
ULONG DefaultPagedPoolCharge;
ULONG DefaultNonPagedPoolCharge;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
typedef struct _OBJECT_TYPES_INFORMATION
{
ULONG NumberOfTypes;
} OBJECT_TYPES_INFORMATION, *POBJECT_TYPES_INFORMATION;
typedef struct _OBJECT_HANDLE_FLAG_INFORMATION
{
BOOLEAN Inherit;
BOOLEAN ProtectFromClose;
} OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION;
// Objects, handles
#if (PHNT_MODE != PHNT_MODE_KERNEL)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryObject(
_In_opt_ HANDLE Handle,
_In_ OBJECT_INFORMATION_CLASS ObjectInformationClass,
_Out_writes_bytes_opt_(ObjectInformationLength) PVOID ObjectInformation,
_In_ ULONG ObjectInformationLength,
_Out_opt_ PULONG ReturnLength
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSetInformationObject(
_In_ HANDLE Handle,
_In_ OBJECT_INFORMATION_CLASS ObjectInformationClass,
_In_reads_bytes_(ObjectInformationLength) PVOID ObjectInformation,
_In_ ULONG ObjectInformationLength
);
#define DUPLICATE_CLOSE_SOURCE 0x00000001
#define DUPLICATE_SAME_ACCESS 0x00000002
#define DUPLICATE_SAME_ATTRIBUTES 0x00000004
NTSYSCALLAPI
NTSTATUS
NTAPI
NtDuplicateObject(
_In_ HANDLE SourceProcessHandle,
_In_ HANDLE SourceHandle,
_In_opt_ HANDLE TargetProcessHandle,
_Out_opt_ PHANDLE TargetHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ ULONG HandleAttributes,
_In_ ULONG Options
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtMakeTemporaryObject(
_In_ HANDLE Handle
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtMakePermanentObject(
_In_ HANDLE Handle
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSignalAndWaitForSingleObject(
_In_ HANDLE SignalHandle,
_In_ HANDLE WaitHandle,
_In_ BOOLEAN Alertable,
_In_opt_ PLARGE_INTEGER Timeout
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtWaitForSingleObject(
_In_ HANDLE Handle,
_In_ BOOLEAN Alertable,
_In_opt_ PLARGE_INTEGER Timeout
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtWaitForMultipleObjects(
_In_ ULONG Count,
_In_reads_(Count) HANDLE Handles[],
_In_ WAIT_TYPE WaitType,
_In_ BOOLEAN Alertable,
_In_opt_ PLARGE_INTEGER Timeout
);
#if (PHNT_VERSION >= PHNT_WS03)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtWaitForMultipleObjects32(
_In_ ULONG Count,
_In_reads_(Count) LONG Handles[],
_In_ WAIT_TYPE WaitType,
_In_ BOOLEAN Alertable,
_In_opt_ PLARGE_INTEGER Timeout
);
#endif
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSetSecurityObject(
_In_ HANDLE Handle,
_In_ SECURITY_INFORMATION SecurityInformation,
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQuerySecurityObject(
_In_ HANDLE Handle,
_In_ SECURITY_INFORMATION SecurityInformation,
_Out_writes_bytes_opt_(Length) PSECURITY_DESCRIPTOR SecurityDescriptor,
_In_ ULONG Length,
_Out_ PULONG LengthNeeded
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtClose(
_In_ HANDLE Handle
);
#if (PHNT_VERSION >= PHNT_THRESHOLD)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCompareObjects(
_In_ HANDLE FirstObjectHandle,
_In_ HANDLE SecondObjectHandle
);
#endif
#endif
// Directory objects
#if (PHNT_MODE != PHNT_MODE_KERNEL)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCreateDirectoryObject(
_Out_ PHANDLE DirectoryHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes
);
#if (PHNT_VERSION >= PHNT_WIN8)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCreateDirectoryObjectEx(
_Out_ PHANDLE DirectoryHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ HANDLE ShadowDirectoryHandle,
_In_ ULONG Flags
);
#endif
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenDirectoryObject(
_Out_ PHANDLE DirectoryHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes
);
typedef struct _OBJECT_DIRECTORY_INFORMATION
{
UNICODE_STRING Name;
UNICODE_STRING TypeName;
} OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION;
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryDirectoryObject(
_In_ HANDLE DirectoryHandle,
_Out_writes_bytes_opt_(Length) PVOID Buffer,
_In_ ULONG Length,
_In_ BOOLEAN ReturnSingleEntry,
_In_ BOOLEAN RestartScan,
_Inout_ PULONG Context,
_Out_opt_ PULONG ReturnLength
);
#endif
// Private namespaces
#if (PHNT_MODE != PHNT_MODE_KERNEL)
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCreatePrivateNamespace(
_Out_ PHANDLE NamespaceHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ PVOID BoundaryDescriptor
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenPrivateNamespace(
_Out_ PHANDLE NamespaceHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ PVOID BoundaryDescriptor
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtDeletePrivateNamespace(
_In_ HANDLE NamespaceHandle
);
#endif
#endif
// Symbolic links
#if (PHNT_MODE != PHNT_MODE_KERNEL)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCreateSymbolicLinkObject(
_Out_ PHANDLE LinkHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ PUNICODE_STRING LinkTarget
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenSymbolicLinkObject(
_Out_ PHANDLE LinkHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQuerySymbolicLinkObject(
_In_ HANDLE LinkHandle,
_Inout_ PUNICODE_STRING LinkTarget,
_Out_opt_ PULONG ReturnedLength
);
#endif
#endif

@ -0,0 +1,434 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTPEBTEB_H
#define _NTPEBTEB_H
typedef struct _RTL_USER_PROCESS_PARAMETERS *PRTL_USER_PROCESS_PARAMETERS;
typedef struct _RTL_CRITICAL_SECTION *PRTL_CRITICAL_SECTION;
// private
typedef struct _ACTIVATION_CONTEXT_STACK
{
struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME* ActiveFrame;
LIST_ENTRY FrameListCache;
ULONG Flags;
ULONG NextCookieSequenceNumber;
ULONG StackId;
} ACTIVATION_CONTEXT_STACK, *PACTIVATION_CONTEXT_STACK;
// private
typedef struct _API_SET_NAMESPACE
{
ULONG Version;
ULONG Size;
ULONG Flags;
ULONG Count;
ULONG EntryOffset;
ULONG HashOffset;
ULONG HashFactor;
} API_SET_NAMESPACE, *PAPI_SET_NAMESPACE;
// private
typedef struct _API_SET_HASH_ENTRY
{
ULONG Hash;
ULONG Index;
} API_SET_HASH_ENTRY, *PAPI_SET_HASH_ENTRY;
// private
typedef struct _API_SET_NAMESPACE_ENTRY
{
ULONG Flags;
ULONG NameOffset;
ULONG NameLength;
ULONG HashedLength;
ULONG ValueOffset;
ULONG ValueCount;
} API_SET_NAMESPACE_ENTRY, *PAPI_SET_NAMESPACE_ENTRY;
// private
typedef struct _API_SET_VALUE_ENTRY
{
ULONG Flags;
ULONG NameOffset;
ULONG NameLength;
ULONG ValueOffset;
ULONG ValueLength;
} API_SET_VALUE_ENTRY, *PAPI_SET_VALUE_ENTRY;
// symbols
typedef struct _PEB
{
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
union
{
BOOLEAN BitField;
struct
{
BOOLEAN ImageUsesLargePages : 1;
BOOLEAN IsProtectedProcess : 1;
BOOLEAN IsImageDynamicallyRelocated : 1;
BOOLEAN SkipPatchingUser32Forwarders : 1;
BOOLEAN IsPackagedProcess : 1;
BOOLEAN IsAppContainer : 1;
BOOLEAN IsProtectedProcessLight : 1;
BOOLEAN IsLongPathAwareProcess : 1;
};
};
HANDLE Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PRTL_CRITICAL_SECTION FastPebLock;
PVOID IFEOKey;
PSLIST_HEADER AtlThunkSListPtr;
union
{
ULONG CrossProcessFlags;
struct
{
ULONG ProcessInJob : 1;
ULONG ProcessInitializing : 1;
ULONG ProcessUsingVEH : 1;
ULONG ProcessUsingVCH : 1;
ULONG ProcessUsingFTH : 1;
ULONG ProcessPreviouslyThrottled : 1;
ULONG ProcessCurrentlyThrottled : 1;
ULONG ProcessImagesHotPatched : 1; // REDSTONE5
ULONG ReservedBits0 : 24;
};
};
union
{
PVOID KernelCallbackTable;
PVOID UserSharedInfoPtr;
};
ULONG SystemReserved;
ULONG AtlThunkSListPtr32;
PAPI_SET_NAMESPACE ApiSetMap;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[2];
PVOID ReadOnlySharedMemoryBase;
PVOID SharedData; // HotpatchInformation
PVOID *ReadOnlyStaticServerData;
PVOID AnsiCodePageData; // PCPTABLEINFO
PVOID OemCodePageData; // PCPTABLEINFO
PVOID UnicodeCaseTableData; // PNLSTABLEINFO
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
ULARGE_INTEGER CriticalSectionTimeout;
SIZE_T HeapSegmentReserve;
SIZE_T HeapSegmentCommit;
SIZE_T HeapDeCommitTotalFreeThreshold;
SIZE_T HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
PVOID *ProcessHeaps; // PHEAP
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
ULONG GdiDCAttributeList;
PRTL_CRITICAL_SECTION LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
USHORT OSBuildNumber;
USHORT OSCSDVersion;
ULONG OSPlatformId;
ULONG ImageSubsystem;
ULONG ImageSubsystemMajorVersion;
ULONG ImageSubsystemMinorVersion;
ULONG_PTR ActiveProcessAffinityMask;
GDI_HANDLE_BUFFER GdiHandleBuffer;
PVOID PostProcessInitRoutine;
PVOID TlsExpansionBitmap;
ULONG TlsExpansionBitmapBits[32];
ULONG SessionId;
ULARGE_INTEGER AppCompatFlags;
ULARGE_INTEGER AppCompatFlagsUser;
PVOID pShimData;
PVOID AppCompatInfo; // APPCOMPAT_EXE_DATA
UNICODE_STRING CSDVersion;
PVOID ActivationContextData; // ACTIVATION_CONTEXT_DATA
PVOID ProcessAssemblyStorageMap; // ASSEMBLY_STORAGE_MAP
PVOID SystemDefaultActivationContextData; // ACTIVATION_CONTEXT_DATA
PVOID SystemAssemblyStorageMap; // ASSEMBLY_STORAGE_MAP
SIZE_T MinimumStackCommit;
PVOID SparePointers[4]; // 19H1 (previously FlsCallback to FlsHighIndex)
ULONG SpareUlongs[5]; // 19H1
//PVOID* FlsCallback;
//LIST_ENTRY FlsListHead;
//PVOID FlsBitmap;
//ULONG FlsBitmapBits[FLS_MAXIMUM_AVAILABLE / (sizeof(ULONG) * 8)];
//ULONG FlsHighIndex;
PVOID WerRegistrationData;
PVOID WerShipAssertPtr;
PVOID pUnused; // pContextData
PVOID pImageHeaderHash;
union
{
ULONG TracingFlags;
struct
{
ULONG HeapTracingEnabled : 1;
ULONG CritSecTracingEnabled : 1;
ULONG LibLoaderTracingEnabled : 1;
ULONG SpareTracingBits : 29;
};
};
ULONGLONG CsrServerReadOnlySharedMemoryBase;
PRTL_CRITICAL_SECTION TppWorkerpListLock;
LIST_ENTRY TppWorkerpList;
PVOID WaitOnAddressHashTable[128];
PVOID TelemetryCoverageHeader; // REDSTONE3
ULONG CloudFileFlags;
ULONG CloudFileDiagFlags; // REDSTONE4
CHAR PlaceholderCompatibilityMode;
CHAR PlaceholderCompatibilityModeReserved[7];
struct _LEAP_SECOND_DATA *LeapSecondData; // REDSTONE5
union
{
ULONG LeapSecondFlags;
struct
{
ULONG SixtySecondEnabled : 1;
ULONG Reserved : 31;
};
};
ULONG NtGlobalFlag2;
} PEB, *PPEB;
#ifdef _WIN64
C_ASSERT(FIELD_OFFSET(PEB, SessionId) == 0x2C0);
//C_ASSERT(sizeof(PEB) == 0x7B0); // REDSTONE3
//C_ASSERT(sizeof(PEB) == 0x7B8); // REDSTONE4
C_ASSERT(sizeof(PEB) == 0x7C8); // REDSTONE5 // 19H1
#else
C_ASSERT(FIELD_OFFSET(PEB, SessionId) == 0x1D4);
//C_ASSERT(sizeof(PEB) == 0x468); // REDSTONE3
//C_ASSERT(sizeof(PEB) == 0x470); // REDSTONE4
C_ASSERT(sizeof(PEB) == 0x480); // REDSTONE5 // 19H1
#endif
#define GDI_BATCH_BUFFER_SIZE 310
typedef struct _GDI_TEB_BATCH
{
ULONG Offset;
ULONG_PTR HDC;
ULONG Buffer[GDI_BATCH_BUFFER_SIZE];
} GDI_TEB_BATCH, *PGDI_TEB_BATCH;
typedef struct _TEB_ACTIVE_FRAME_CONTEXT
{
ULONG Flags;
PSTR FrameName;
} TEB_ACTIVE_FRAME_CONTEXT, *PTEB_ACTIVE_FRAME_CONTEXT;
typedef struct _TEB_ACTIVE_FRAME
{
ULONG Flags;
struct _TEB_ACTIVE_FRAME *Previous;
PTEB_ACTIVE_FRAME_CONTEXT Context;
} TEB_ACTIVE_FRAME, *PTEB_ACTIVE_FRAME;
typedef struct _TEB
{
NT_TIB NtTib;
PVOID EnvironmentPointer;
CLIENT_ID ClientId;
PVOID ActiveRpcHandle;
PVOID ThreadLocalStoragePointer;
PPEB ProcessEnvironmentBlock;
ULONG LastErrorValue;
ULONG CountOfOwnedCriticalSections;
PVOID CsrClientThread;
PVOID Win32ThreadInfo;
ULONG User32Reserved[26];
ULONG UserReserved[5];
PVOID WOW32Reserved;
LCID CurrentLocale;
ULONG FpSoftwareStatusRegister;
PVOID ReservedForDebuggerInstrumentation[16];
#ifdef _WIN64
PVOID SystemReserved1[30];
#else
PVOID SystemReserved1[26];
#endif
CHAR PlaceholderCompatibilityMode;
CHAR PlaceholderReserved[11];
ULONG ProxiedProcessId;
ACTIVATION_CONTEXT_STACK ActivationStack;
UCHAR WorkingOnBehalfTicket[8];
NTSTATUS ExceptionCode;
PACTIVATION_CONTEXT_STACK ActivationContextStackPointer;
ULONG_PTR InstrumentationCallbackSp;
ULONG_PTR InstrumentationCallbackPreviousPc;
ULONG_PTR InstrumentationCallbackPreviousSp;
#ifdef _WIN64
ULONG TxFsContext;
#endif
BOOLEAN InstrumentationCallbackDisabled;
#ifndef _WIN64
UCHAR SpareBytes[23];
ULONG TxFsContext;
#endif
GDI_TEB_BATCH GdiTebBatch;
CLIENT_ID RealClientId;
HANDLE GdiCachedProcessHandle;
ULONG GdiClientPID;
ULONG GdiClientTID;
PVOID GdiThreadLocalInfo;
ULONG_PTR Win32ClientInfo[62];
PVOID glDispatchTable[233];
ULONG_PTR glReserved1[29];
PVOID glReserved2;
PVOID glSectionInfo;
PVOID glSection;
PVOID glTable;
PVOID glCurrentRC;
PVOID glContext;
NTSTATUS LastStatusValue;
UNICODE_STRING StaticUnicodeString;
WCHAR StaticUnicodeBuffer[261];
PVOID DeallocationStack;
PVOID TlsSlots[64];
LIST_ENTRY TlsLinks;
PVOID Vdm;
PVOID ReservedForNtRpc;
PVOID DbgSsReserved[2];
ULONG HardErrorMode;
#ifdef _WIN64
PVOID Instrumentation[11];
#else
PVOID Instrumentation[9];
#endif
GUID ActivityId;
PVOID SubProcessTag;
PVOID PerflibData;
PVOID EtwTraceData;
PVOID WinSockData;
ULONG GdiBatchCount;
union
{
PROCESSOR_NUMBER CurrentIdealProcessor;
ULONG IdealProcessorValue;
struct
{
UCHAR ReservedPad0;
UCHAR ReservedPad1;
UCHAR ReservedPad2;
UCHAR IdealProcessor;
};
};
ULONG GuaranteedStackBytes;
PVOID ReservedForPerf;
PVOID ReservedForOle;
ULONG WaitingOnLoaderLock;
PVOID SavedPriorityState;
ULONG_PTR ReservedForCodeCoverage;
PVOID ThreadPoolData;
PVOID *TlsExpansionSlots;
#ifdef _WIN64
PVOID DeallocationBStore;
PVOID BStoreLimit;
#endif
ULONG MuiGeneration;
ULONG IsImpersonating;
PVOID NlsCache;
PVOID pShimData;
USHORT HeapVirtualAffinity;
USHORT LowFragHeapDataSlot;
HANDLE CurrentTransactionHandle;
PTEB_ACTIVE_FRAME ActiveFrame;
PVOID FlsData;
PVOID PreferredLanguages;
PVOID UserPrefLanguages;
PVOID MergedPrefLanguages;
ULONG MuiImpersonation;
union
{
USHORT CrossTebFlags;
USHORT SpareCrossTebBits : 16;
};
union
{
USHORT SameTebFlags;
struct
{
USHORT SafeThunkCall : 1;
USHORT InDebugPrint : 1;
USHORT HasFiberData : 1;
USHORT SkipThreadAttach : 1;
USHORT WerInShipAssertCode : 1;
USHORT RanProcessInit : 1;
USHORT ClonedThread : 1;
USHORT SuppressDebugMsg : 1;
USHORT DisableUserStackWalk : 1;
USHORT RtlExceptionAttached : 1;
USHORT InitialThread : 1;
USHORT SessionAware : 1;
USHORT LoadOwner : 1;
USHORT LoaderWorker : 1;
USHORT SkipLoaderInit : 1;
USHORT SpareSameTebBits : 1;
};
};
PVOID TxnScopeEnterCallback;
PVOID TxnScopeExitCallback;
PVOID TxnScopeContext;
ULONG LockCount;
LONG WowTebOffset;
PVOID ResourceRetValue;
PVOID ReservedForWdf;
ULONGLONG ReservedForCrt;
GUID EffectiveContainerId;
} TEB, *PTEB;
#endif

@ -0,0 +1,282 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTPFAPI_H
#define _NTPFAPI_H
// begin_private
// Prefetch
typedef enum _PF_BOOT_PHASE_ID
{
PfKernelInitPhase = 0,
PfBootDriverInitPhase = 90,
PfSystemDriverInitPhase = 120,
PfSessionManagerInitPhase = 150,
PfSMRegistryInitPhase = 180,
PfVideoInitPhase = 210,
PfPostVideoInitPhase = 240,
PfBootAcceptedRegistryInitPhase = 270,
PfUserShellReadyPhase = 300,
PfMaxBootPhaseId = 900
} PF_BOOT_PHASE_ID;
typedef enum _PF_ENABLE_STATUS
{
PfSvNotSpecified,
PfSvEnabled,
PfSvDisabled,
PfSvMaxEnableStatus
} PF_ENABLE_STATUS;
typedef struct _PF_TRACE_LIMITS
{
ULONG MaxNumPages;
ULONG MaxNumSections;
LONGLONG TimerPeriod;
} PF_TRACE_LIMITS, *PPF_TRACE_LIMITS;
typedef struct _PF_SYSTEM_PREFETCH_PARAMETERS
{
PF_ENABLE_STATUS EnableStatus[2];
PF_TRACE_LIMITS TraceLimits[2];
ULONG MaxNumActiveTraces;
ULONG MaxNumSavedTraces;
WCHAR RootDirPath[32];
WCHAR HostingApplicationList[128];
} PF_SYSTEM_PREFETCH_PARAMETERS, *PPF_SYSTEM_PREFETCH_PARAMETERS;
#define PF_BOOT_CONTROL_VERSION 1
typedef struct _PF_BOOT_CONTROL
{
ULONG Version;
ULONG DisableBootPrefetching;
} PF_BOOT_CONTROL, *PPF_BOOT_CONTROL;
typedef enum _PREFETCHER_INFORMATION_CLASS
{
PrefetcherRetrieveTrace = 1, // q: CHAR[]
PrefetcherSystemParameters, // q: PF_SYSTEM_PREFETCH_PARAMETERS
PrefetcherBootPhase, // s: PF_BOOT_PHASE_ID
PrefetcherRetrieveBootLoaderTrace, // q: CHAR[]
PrefetcherBootControl // s: PF_BOOT_CONTROL
} PREFETCHER_INFORMATION_CLASS;
#define PREFETCHER_INFORMATION_VERSION 23 // rev
#define PREFETCHER_INFORMATION_MAGIC ('kuhC') // rev
typedef struct _PREFETCHER_INFORMATION
{
ULONG Version;
ULONG Magic;
PREFETCHER_INFORMATION_CLASS PrefetcherInformationClass;
PVOID PrefetcherInformation;
ULONG PrefetcherInformationLength;
} PREFETCHER_INFORMATION, *PPREFETCHER_INFORMATION;
// Superfetch
typedef struct _PF_SYSTEM_SUPERFETCH_PARAMETERS
{
ULONG EnabledComponents;
ULONG BootID;
ULONG SavedSectInfoTracesMax;
ULONG SavedPageAccessTracesMax;
ULONG ScenarioPrefetchTimeoutStandby;
ULONG ScenarioPrefetchTimeoutHibernate;
} PF_SYSTEM_SUPERFETCH_PARAMETERS, *PPF_SYSTEM_SUPERFETCH_PARAMETERS;
#define PF_PFN_PRIO_REQUEST_VERSION 1
#define PF_PFN_PRIO_REQUEST_QUERY_MEMORY_LIST 0x1
#define PF_PFN_PRIO_REQUEST_VALID_FLAGS 0x1
typedef struct _PF_PFN_PRIO_REQUEST
{
ULONG Version;
ULONG RequestFlags;
ULONG_PTR PfnCount;
SYSTEM_MEMORY_LIST_INFORMATION MemInfo;
MMPFN_IDENTITY PageData[256];
} PF_PFN_PRIO_REQUEST, *PPF_PFN_PRIO_REQUEST;
typedef enum _PFS_PRIVATE_PAGE_SOURCE_TYPE
{
PfsPrivateSourceKernel,
PfsPrivateSourceSession,
PfsPrivateSourceProcess,
PfsPrivateSourceMax
} PFS_PRIVATE_PAGE_SOURCE_TYPE;
typedef struct _PFS_PRIVATE_PAGE_SOURCE
{
PFS_PRIVATE_PAGE_SOURCE_TYPE Type;
union
{
ULONG SessionId;
ULONG ProcessId;
};
ULONG ImagePathHash;
ULONG_PTR UniqueProcessHash;
} PFS_PRIVATE_PAGE_SOURCE, *PPFS_PRIVATE_PAGE_SOURCE;
typedef struct _PF_PRIVSOURCE_INFO
{
PFS_PRIVATE_PAGE_SOURCE DbInfo;
PVOID EProcess;
SIZE_T WsPrivatePages;
SIZE_T TotalPrivatePages;
ULONG SessionID;
CHAR ImageName[16];
union {
ULONG_PTR WsSwapPages; // process only PF_PRIVSOURCE_QUERY_WS_SWAP_PAGES.
ULONG_PTR SessionPagedPoolPages; // session only.
ULONG_PTR StoreSizePages; // process only PF_PRIVSOURCE_QUERY_STORE_INFO.
};
ULONG_PTR WsTotalPages; // process/session only.
ULONG DeepFreezeTimeMs; // process only.
ULONG ModernApp : 1; // process only.
ULONG DeepFrozen : 1; // process only. If set, DeepFreezeTimeMs contains the time at which the freeze occurred
ULONG Foreground : 1; // process only.
ULONG PerProcessStore : 1; // process only.
ULONG Spare : 28;
} PF_PRIVSOURCE_INFO, *PPF_PRIVSOURCE_INFO;
#define PF_PRIVSOURCE_QUERY_REQUEST_VERSION 8
typedef struct _PF_PRIVSOURCE_QUERY_REQUEST
{
ULONG Version;
ULONG Flags;
ULONG InfoCount;
PF_PRIVSOURCE_INFO InfoArray[1];
} PF_PRIVSOURCE_QUERY_REQUEST, *PPF_PRIVSOURCE_QUERY_REQUEST;
typedef enum _PF_PHASED_SCENARIO_TYPE
{
PfScenarioTypeNone,
PfScenarioTypeStandby,
PfScenarioTypeHibernate,
PfScenarioTypeFUS,
PfScenarioTypeMax
} PF_PHASED_SCENARIO_TYPE;
#define PF_SCENARIO_PHASE_INFO_VERSION 4
typedef struct _PF_SCENARIO_PHASE_INFO
{
ULONG Version;
PF_PHASED_SCENARIO_TYPE ScenType;
ULONG PhaseId;
ULONG SequenceNumber;
ULONG Flags;
ULONG FUSUserId;
} PF_SCENARIO_PHASE_INFO, *PPF_SCENARIO_PHASE_INFO;
typedef struct _PF_MEMORY_LIST_NODE
{
ULONGLONG Node : 8;
ULONGLONG Spare : 56;
ULONGLONG StandbyLowPageCount;
ULONGLONG StandbyMediumPageCount;
ULONGLONG StandbyHighPageCount;
ULONGLONG FreePageCount;
ULONGLONG ModifiedPageCount;
} PF_MEMORY_LIST_NODE, *PPF_MEMORY_LIST_NODE;
#define PF_MEMORY_LIST_INFO_VERSION 1
typedef struct _PF_MEMORY_LIST_INFO
{
ULONG Version;
ULONG Size;
ULONG NodeCount;
PF_MEMORY_LIST_NODE Nodes[1];
} PF_MEMORY_LIST_INFO, *PPF_MEMORY_LIST_INFO;
typedef struct _PF_PHYSICAL_MEMORY_RANGE
{
ULONG_PTR BasePfn;
ULONG_PTR PageCount;
} PF_PHYSICAL_MEMORY_RANGE, *PPF_PHYSICAL_MEMORY_RANGE;
#define PF_PHYSICAL_MEMORY_RANGE_INFO_V1_VERSION 1
typedef struct _PF_PHYSICAL_MEMORY_RANGE_INFO_V1
{
ULONG Version;
ULONG RangeCount;
PF_PHYSICAL_MEMORY_RANGE Ranges[1];
} PF_PHYSICAL_MEMORY_RANGE_INFO_V1, *PPF_PHYSICAL_MEMORY_RANGE_INFO_V1;
#define PF_PHYSICAL_MEMORY_RANGE_INFO_V2_VERSION 2
typedef struct _PF_PHYSICAL_MEMORY_RANGE_INFO_V2
{
ULONG Version;
ULONG Flags;
ULONG RangeCount;
PF_PHYSICAL_MEMORY_RANGE Ranges[ANYSIZE_ARRAY];
} PF_PHYSICAL_MEMORY_RANGE_INFO_V2, *PPF_PHYSICAL_MEMORY_RANGE_INFO_V2;
// begin_rev
#define PF_REPURPOSED_BY_PREFETCH_INFO_VERSION 1
typedef struct _PF_REPURPOSED_BY_PREFETCH_INFO
{
ULONG Version;
ULONG RepurposedByPrefetch;
} PF_REPURPOSED_BY_PREFETCH_INFO, *PPF_REPURPOSED_BY_PREFETCH_INFO;
// end_rev
typedef enum _SUPERFETCH_INFORMATION_CLASS
{
SuperfetchRetrieveTrace = 1, // q: CHAR[]
SuperfetchSystemParameters, // q: PF_SYSTEM_SUPERFETCH_PARAMETERS
SuperfetchLogEvent,
SuperfetchGenerateTrace,
SuperfetchPrefetch,
SuperfetchPfnQuery, // q: PF_PFN_PRIO_REQUEST
SuperfetchPfnSetPriority,
SuperfetchPrivSourceQuery, // q: PF_PRIVSOURCE_QUERY_REQUEST
SuperfetchSequenceNumberQuery, // q: ULONG
SuperfetchScenarioPhase, // 10
SuperfetchWorkerPriority,
SuperfetchScenarioQuery, // q: PF_SCENARIO_PHASE_INFO
SuperfetchScenarioPrefetch,
SuperfetchRobustnessControl,
SuperfetchTimeControl,
SuperfetchMemoryListQuery, // q: PF_MEMORY_LIST_INFO
SuperfetchMemoryRangesQuery, // q: PF_PHYSICAL_MEMORY_RANGE_INFO
SuperfetchTracingControl,
SuperfetchTrimWhileAgingControl,
SuperfetchRepurposedByPrefetch, // q: PF_REPURPOSED_BY_PREFETCH_INFO // rev
SuperfetchInformationMax
} SUPERFETCH_INFORMATION_CLASS;
#define SUPERFETCH_INFORMATION_VERSION 45 // rev
#define SUPERFETCH_INFORMATION_MAGIC ('kuhC') // rev
typedef struct _SUPERFETCH_INFORMATION
{
_In_ ULONG Version;
_In_ ULONG Magic;
_In_ SUPERFETCH_INFORMATION_CLASS InfoClass;
_Inout_ PVOID Data;
_Inout_ ULONG Length;
} SUPERFETCH_INFORMATION, *PSUPERFETCH_INFORMATION;
// end_private
#endif

@ -0,0 +1,170 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTPNPAPI_H
#define _NTPNPAPI_H
typedef enum _PLUGPLAY_EVENT_CATEGORY
{
HardwareProfileChangeEvent,
TargetDeviceChangeEvent,
DeviceClassChangeEvent,
CustomDeviceEvent,
DeviceInstallEvent,
DeviceArrivalEvent,
PowerEvent,
VetoEvent,
BlockedDriverEvent,
InvalidIDEvent,
MaxPlugEventCategory
} PLUGPLAY_EVENT_CATEGORY, *PPLUGPLAY_EVENT_CATEGORY;
typedef struct _PLUGPLAY_EVENT_BLOCK
{
GUID EventGuid;
PLUGPLAY_EVENT_CATEGORY EventCategory;
PULONG Result;
ULONG Flags;
ULONG TotalSize;
PVOID DeviceObject;
union
{
struct
{
GUID ClassGuid;
WCHAR SymbolicLinkName[1];
} DeviceClass;
struct
{
WCHAR DeviceIds[1];
} TargetDevice;
struct
{
WCHAR DeviceId[1];
} InstallDevice;
struct
{
PVOID NotificationStructure;
WCHAR DeviceIds[1];
} CustomNotification;
struct
{
PVOID Notification;
} ProfileNotification;
struct
{
ULONG NotificationCode;
ULONG NotificationData;
} PowerNotification;
struct
{
PNP_VETO_TYPE VetoType;
WCHAR DeviceIdVetoNameBuffer[1]; // DeviceId<null>VetoName<null><null>
} VetoNotification;
struct
{
GUID BlockedDriverGuid;
} BlockedDriverNotification;
struct
{
WCHAR ParentId[1];
} InvalidIDNotification;
} u;
} PLUGPLAY_EVENT_BLOCK, *PPLUGPLAY_EVENT_BLOCK;
typedef enum _PLUGPLAY_CONTROL_CLASS
{
PlugPlayControlEnumerateDevice,
PlugPlayControlRegisterNewDevice,
PlugPlayControlDeregisterDevice,
PlugPlayControlInitializeDevice,
PlugPlayControlStartDevice,
PlugPlayControlUnlockDevice,
PlugPlayControlQueryAndRemoveDevice,
PlugPlayControlUserResponse,
PlugPlayControlGenerateLegacyDevice,
PlugPlayControlGetInterfaceDeviceList,
PlugPlayControlProperty,
PlugPlayControlDeviceClassAssociation,
PlugPlayControlGetRelatedDevice,
PlugPlayControlGetInterfaceDeviceAlias,
PlugPlayControlDeviceStatus,
PlugPlayControlGetDeviceDepth,
PlugPlayControlQueryDeviceRelations,
PlugPlayControlTargetDeviceRelation,
PlugPlayControlQueryConflictList,
PlugPlayControlRetrieveDock,
PlugPlayControlResetDevice,
PlugPlayControlHaltDevice,
PlugPlayControlGetBlockedDriverList,
PlugPlayControlGetDeviceInterfaceEnabled,
MaxPlugPlayControl
} PLUGPLAY_CONTROL_CLASS, *PPLUGPLAY_CONTROL_CLASS;
#if (PHNT_VERSION < PHNT_WIN8)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtGetPlugPlayEvent(
_In_ HANDLE EventHandle,
_In_opt_ PVOID Context,
_Out_writes_bytes_(EventBufferSize) PPLUGPLAY_EVENT_BLOCK EventBlock,
_In_ ULONG EventBufferSize
);
#endif
NTSYSCALLAPI
NTSTATUS
NTAPI
NtPlugPlayControl(
_In_ PLUGPLAY_CONTROL_CLASS PnPControlClass,
_Inout_updates_bytes_(PnPControlDataLength) PVOID PnPControlData,
_In_ ULONG PnPControlDataLength
);
#if (PHNT_VERSION >= PHNT_WIN7)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSerializeBoot(
VOID
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtEnableLastKnownGood(
VOID
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtDisableLastKnownGood(
VOID
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtReplacePartitionUnit(
_In_ PUNICODE_STRING TargetInstancePath,
_In_ PUNICODE_STRING SpareInstancePath,
_In_ ULONG Flags
);
#endif
#endif

@ -0,0 +1,193 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTPOAPI_H
#define _NTPOAPI_H
typedef union _POWER_STATE
{
SYSTEM_POWER_STATE SystemState;
DEVICE_POWER_STATE DeviceState;
} POWER_STATE, *PPOWER_STATE;
typedef enum _POWER_STATE_TYPE
{
SystemPowerState = 0,
DevicePowerState
} POWER_STATE_TYPE, *PPOWER_STATE_TYPE;
#if (PHNT_VERSION >= PHNT_VISTA)
// wdm
typedef struct _SYSTEM_POWER_STATE_CONTEXT
{
union
{
struct
{
ULONG Reserved1 : 8;
ULONG TargetSystemState : 4;
ULONG EffectiveSystemState : 4;
ULONG CurrentSystemState : 4;
ULONG IgnoreHibernationPath : 1;
ULONG PseudoTransition : 1;
ULONG Reserved2 : 10;
};
ULONG ContextAsUlong;
};
} SYSTEM_POWER_STATE_CONTEXT, *PSYSTEM_POWER_STATE_CONTEXT;
#endif
#if (PHNT_VERSION >= PHNT_WIN7)
/** \cond NEVER */ // disable doxygen warning
// wdm
typedef struct _COUNTED_REASON_CONTEXT
{
ULONG Version;
ULONG Flags;
union
{
struct
{
UNICODE_STRING ResourceFileName;
USHORT ResourceReasonId;
ULONG StringCount;
PUNICODE_STRING _Field_size_(StringCount) ReasonStrings;
};
UNICODE_STRING SimpleString;
};
} COUNTED_REASON_CONTEXT, *PCOUNTED_REASON_CONTEXT;
/** \endcond */
#endif
typedef enum _POWER_STATE_HANDLER_TYPE
{
PowerStateSleeping1 = 0,
PowerStateSleeping2 = 1,
PowerStateSleeping3 = 2,
PowerStateSleeping4 = 3,
PowerStateShutdownOff = 4,
PowerStateShutdownReset = 5,
PowerStateSleeping4Firmware = 6,
PowerStateMaximum = 7
} POWER_STATE_HANDLER_TYPE, *PPOWER_STATE_HANDLER_TYPE;
typedef NTSTATUS (NTAPI *PENTER_STATE_SYSTEM_HANDLER)(
_In_ PVOID SystemContext
);
typedef NTSTATUS (NTAPI *PENTER_STATE_HANDLER)(
_In_ PVOID Context,
_In_opt_ PENTER_STATE_SYSTEM_HANDLER SystemHandler,
_In_ PVOID SystemContext,
_In_ LONG NumberProcessors,
_In_ volatile PLONG Number
);
typedef struct _POWER_STATE_HANDLER
{
POWER_STATE_HANDLER_TYPE Type;
BOOLEAN RtcWake;
UCHAR Spare[3];
PENTER_STATE_HANDLER Handler;
PVOID Context;
} POWER_STATE_HANDLER, *PPOWER_STATE_HANDLER;
typedef NTSTATUS (NTAPI *PENTER_STATE_NOTIFY_HANDLER)(
_In_ POWER_STATE_HANDLER_TYPE State,
_In_ PVOID Context,
_In_ BOOLEAN Entering
);
typedef struct _POWER_STATE_NOTIFY_HANDLER
{
PENTER_STATE_NOTIFY_HANDLER Handler;
PVOID Context;
} POWER_STATE_NOTIFY_HANDLER, *PPOWER_STATE_NOTIFY_HANDLER;
typedef struct _PROCESSOR_POWER_INFORMATION
{
ULONG Number;
ULONG MaxMhz;
ULONG CurrentMhz;
ULONG MhzLimit;
ULONG MaxIdleState;
ULONG CurrentIdleState;
} PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION;
typedef struct _SYSTEM_POWER_INFORMATION
{
ULONG MaxIdlenessAllowed;
ULONG Idleness;
ULONG TimeRemaining;
UCHAR CoolingMode;
} SYSTEM_POWER_INFORMATION, *PSYSTEM_POWER_INFORMATION;
NTSYSCALLAPI
NTSTATUS
NTAPI
NtPowerInformation(
_In_ POWER_INFORMATION_LEVEL InformationLevel,
_In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
_In_ ULONG InputBufferLength,
_Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
_In_ ULONG OutputBufferLength
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSetThreadExecutionState(
_In_ EXECUTION_STATE NewFlags, // ES_* flags
_Out_ EXECUTION_STATE *PreviousFlags
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtRequestWakeupLatency(
_In_ LATENCY_TIME latency
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtInitiatePowerAction(
_In_ POWER_ACTION SystemAction,
_In_ SYSTEM_POWER_STATE LightestSystemState,
_In_ ULONG Flags, // POWER_ACTION_* flags
_In_ BOOLEAN Asynchronous
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSetSystemPowerState(
_In_ POWER_ACTION SystemAction,
_In_ SYSTEM_POWER_STATE LightestSystemState,
_In_ ULONG Flags // POWER_ACTION_* flags
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtGetDevicePowerState(
_In_ HANDLE Device,
_Out_ PDEVICE_POWER_STATE State
);
NTSYSCALLAPI
BOOLEAN
NTAPI
NtIsSystemResumeAutomatic(
VOID
);
#endif

File diff suppressed because it is too large Load Diff

@ -0,0 +1,664 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTREGAPI_H
#define _NTREGAPI_H
// Boot condition flags (NtInitializeRegistry)
#define REG_INIT_BOOT_SM 0x0000
#define REG_INIT_BOOT_SETUP 0x0001
#define REG_INIT_BOOT_ACCEPTED_BASE 0x0002
#define REG_INIT_BOOT_ACCEPTED_MAX REG_INIT_BOOT_ACCEPTED_BASE + 999
#define REG_MAX_KEY_VALUE_NAME_LENGTH 32767
#define REG_MAX_KEY_NAME_LENGTH 512
typedef enum _KEY_INFORMATION_CLASS
{
KeyBasicInformation, // KEY_BASIC_INFORMATION
KeyNodeInformation, // KEY_NODE_INFORMATION
KeyFullInformation, // KEY_FULL_INFORMATION
KeyNameInformation, // KEY_NAME_INFORMATION
KeyCachedInformation, // KEY_CACHED_INFORMATION
KeyFlagsInformation, // KEY_FLAGS_INFORMATION
KeyVirtualizationInformation, // KEY_VIRTUALIZATION_INFORMATION
KeyHandleTagsInformation, // KEY_HANDLE_TAGS_INFORMATION
KeyTrustInformation, // KEY_TRUST_INFORMATION
KeyLayerInformation, // KEY_LAYER_INFORMATION
MaxKeyInfoClass
} KEY_INFORMATION_CLASS;
typedef struct _KEY_BASIC_INFORMATION
{
LARGE_INTEGER LastWriteTime;
ULONG TitleIndex;
ULONG NameLength;
WCHAR Name[1];
} KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION;
typedef struct _KEY_NODE_INFORMATION
{
LARGE_INTEGER LastWriteTime;
ULONG TitleIndex;
ULONG ClassOffset;
ULONG ClassLength;
ULONG NameLength;
WCHAR Name[1];
// ...
// WCHAR Class[1];
} KEY_NODE_INFORMATION, *PKEY_NODE_INFORMATION;
typedef struct _KEY_FULL_INFORMATION
{
LARGE_INTEGER LastWriteTime;
ULONG TitleIndex;
ULONG ClassOffset;
ULONG ClassLength;
ULONG SubKeys;
ULONG MaxNameLen;
ULONG MaxClassLen;
ULONG Values;
ULONG MaxValueNameLen;
ULONG MaxValueDataLen;
WCHAR Class[1];
} KEY_FULL_INFORMATION, *PKEY_FULL_INFORMATION;
typedef struct _KEY_NAME_INFORMATION
{
ULONG NameLength;
WCHAR Name[1];
} KEY_NAME_INFORMATION, *PKEY_NAME_INFORMATION;
typedef struct _KEY_CACHED_INFORMATION
{
LARGE_INTEGER LastWriteTime;
ULONG TitleIndex;
ULONG SubKeys;
ULONG MaxNameLen;
ULONG Values;
ULONG MaxValueNameLen;
ULONG MaxValueDataLen;
ULONG NameLength;
WCHAR Name[1];
} KEY_CACHED_INFORMATION, *PKEY_CACHED_INFORMATION;
typedef struct _KEY_FLAGS_INFORMATION
{
ULONG UserFlags;
} KEY_FLAGS_INFORMATION, *PKEY_FLAGS_INFORMATION;
typedef struct _KEY_VIRTUALIZATION_INFORMATION
{
ULONG VirtualizationCandidate : 1; // Tells whether the key is part of the virtualization namespace scope (only HKLM\Software for now).
ULONG VirtualizationEnabled : 1; // Tells whether virtualization is enabled on this key. Can be 1 only if above flag is 1.
ULONG VirtualTarget : 1; // Tells if the key is a virtual key. Can be 1 only if above 2 are 0. Valid only on the virtual store key handles.
ULONG VirtualStore : 1; // Tells if the key is a part of the virtual store path. Valid only on the virtual store key handles.
ULONG VirtualSource : 1; // Tells if the key has ever been virtualized, can be 1 only if VirtualizationCandidate is 1.
ULONG Reserved : 27;
} KEY_VIRTUALIZATION_INFORMATION, *PKEY_VIRTUALIZATION_INFORMATION;
// private
typedef struct _KEY_TRUST_INFORMATION
{
ULONG TrustedKey : 1;
ULONG Reserved : 31;
} KEY_TRUST_INFORMATION, *PKEY_TRUST_INFORMATION;
// private
typedef struct _KEY_LAYER_INFORMATION
{
ULONG IsTombstone;
ULONG IsSupersedeLocal;
ULONG IsSupersedeTree;
ULONG ClassIsInherited;
ULONG Reserved;
} KEY_LAYER_INFORMATION, *PKEY_LAYER_INFORMATION;
typedef enum _KEY_SET_INFORMATION_CLASS
{
KeyWriteTimeInformation, // KEY_WRITE_TIME_INFORMATION
KeyWow64FlagsInformation, // KEY_WOW64_FLAGS_INFORMATION
KeyControlFlagsInformation, // KEY_CONTROL_FLAGS_INFORMATION
KeySetVirtualizationInformation, // KEY_SET_VIRTUALIZATION_INFORMATION
KeySetDebugInformation,
KeySetHandleTagsInformation, // KEY_HANDLE_TAGS_INFORMATION
KeySetLayerInformation, // KEY_SET_LAYER_INFORMATION
MaxKeySetInfoClass
} KEY_SET_INFORMATION_CLASS;
typedef struct _KEY_WRITE_TIME_INFORMATION
{
LARGE_INTEGER LastWriteTime;
} KEY_WRITE_TIME_INFORMATION, *PKEY_WRITE_TIME_INFORMATION;
typedef struct _KEY_WOW64_FLAGS_INFORMATION
{
ULONG UserFlags;
} KEY_WOW64_FLAGS_INFORMATION, *PKEY_WOW64_FLAGS_INFORMATION;
typedef struct _KEY_HANDLE_TAGS_INFORMATION
{
ULONG HandleTags;
} KEY_HANDLE_TAGS_INFORMATION, *PKEY_HANDLE_TAGS_INFORMATION;
typedef struct _KEY_SET_LAYER_INFORMATION
{
ULONG IsTombstone : 1;
ULONG IsSupersedeLocal : 1;
ULONG IsSupersedeTree : 1;
ULONG ClassIsInherited : 1;
ULONG Reserved : 28;
} KEY_SET_LAYER_INFORMATION, *PKEY_SET_LAYER_INFORMATION;
typedef struct _KEY_CONTROL_FLAGS_INFORMATION
{
ULONG ControlFlags;
} KEY_CONTROL_FLAGS_INFORMATION, *PKEY_CONTROL_FLAGS_INFORMATION;
typedef struct _KEY_SET_VIRTUALIZATION_INFORMATION
{
ULONG VirtualTarget : 1;
ULONG VirtualStore : 1;
ULONG VirtualSource : 1; // true if key has been virtualized at least once
ULONG Reserved : 29;
} KEY_SET_VIRTUALIZATION_INFORMATION, *PKEY_SET_VIRTUALIZATION_INFORMATION;
typedef enum _KEY_VALUE_INFORMATION_CLASS
{
KeyValueBasicInformation, // KEY_VALUE_BASIC_INFORMATION
KeyValueFullInformation, // KEY_VALUE_FULL_INFORMATION
KeyValuePartialInformation, // KEY_VALUE_PARTIAL_INFORMATION
KeyValueFullInformationAlign64,
KeyValuePartialInformationAlign64, // KEY_VALUE_PARTIAL_INFORMATION_ALIGN64
KeyValueLayerInformation, // KEY_VALUE_LAYER_INFORMATION
MaxKeyValueInfoClass
} KEY_VALUE_INFORMATION_CLASS;
typedef struct _KEY_VALUE_BASIC_INFORMATION
{
ULONG TitleIndex;
ULONG Type;
ULONG NameLength;
WCHAR Name[1];
} KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION;
typedef struct _KEY_VALUE_FULL_INFORMATION
{
ULONG TitleIndex;
ULONG Type;
ULONG DataOffset;
ULONG DataLength;
ULONG NameLength;
WCHAR Name[1];
// ...
// UCHAR Data[1];
} KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION;
typedef struct _KEY_VALUE_PARTIAL_INFORMATION
{
ULONG TitleIndex;
ULONG Type;
ULONG DataLength;
UCHAR Data[1];
} KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION;
typedef struct _KEY_VALUE_PARTIAL_INFORMATION_ALIGN64
{
ULONG Type;
ULONG DataLength;
UCHAR Data[1];
} KEY_VALUE_PARTIAL_INFORMATION_ALIGN64, *PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64;
// private
typedef struct _KEY_VALUE_LAYER_INFORMATION
{
ULONG IsTombstone;
ULONG Reserved;
} KEY_VALUE_LAYER_INFORMATION, *PKEY_VALUE_LAYER_INFORMATION;
typedef struct _KEY_VALUE_ENTRY
{
PUNICODE_STRING ValueName;
ULONG DataLength;
ULONG DataOffset;
ULONG Type;
} KEY_VALUE_ENTRY, *PKEY_VALUE_ENTRY;
typedef enum _REG_ACTION
{
KeyAdded,
KeyRemoved,
KeyModified
} REG_ACTION;
typedef struct _REG_NOTIFY_INFORMATION
{
ULONG NextEntryOffset;
REG_ACTION Action;
ULONG KeyLength;
WCHAR Key[1];
} REG_NOTIFY_INFORMATION, *PREG_NOTIFY_INFORMATION;
typedef struct _KEY_PID_ARRAY
{
HANDLE ProcessId;
UNICODE_STRING KeyName;
} KEY_PID_ARRAY, *PKEY_PID_ARRAY;
typedef struct _KEY_OPEN_SUBKEYS_INFORMATION
{
ULONG Count;
KEY_PID_ARRAY KeyArray[1];
} KEY_OPEN_SUBKEYS_INFORMATION, *PKEY_OPEN_SUBKEYS_INFORMATION;
// System calls
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCreateKey(
_Out_ PHANDLE KeyHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_Reserved_ ULONG TitleIndex,
_In_opt_ PUNICODE_STRING Class,
_In_ ULONG CreateOptions,
_Out_opt_ PULONG Disposition
);
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCreateKeyTransacted(
_Out_ PHANDLE KeyHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_Reserved_ ULONG TitleIndex,
_In_opt_ PUNICODE_STRING Class,
_In_ ULONG CreateOptions,
_In_ HANDLE TransactionHandle,
_Out_opt_ PULONG Disposition
);
#endif
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenKey(
_Out_ PHANDLE KeyHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes
);
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenKeyTransacted(
_Out_ PHANDLE KeyHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ HANDLE TransactionHandle
);
#endif
#if (PHNT_VERSION >= PHNT_WIN7)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenKeyEx(
_Out_ PHANDLE KeyHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ ULONG OpenOptions
);
#endif
#if (PHNT_VERSION >= PHNT_WIN7)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenKeyTransactedEx(
_Out_ PHANDLE KeyHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ ULONG OpenOptions,
_In_ HANDLE TransactionHandle
);
#endif
NTSYSCALLAPI
NTSTATUS
NTAPI
NtDeleteKey(
_In_ HANDLE KeyHandle
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtRenameKey(
_In_ HANDLE KeyHandle,
_In_ PUNICODE_STRING NewName
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtDeleteValueKey(
_In_ HANDLE KeyHandle,
_In_ PUNICODE_STRING ValueName
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryKey(
_In_ HANDLE KeyHandle,
_In_ KEY_INFORMATION_CLASS KeyInformationClass,
_Out_writes_bytes_opt_(Length) PVOID KeyInformation,
_In_ ULONG Length,
_Out_ PULONG ResultLength
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSetInformationKey(
_In_ HANDLE KeyHandle,
_In_ KEY_SET_INFORMATION_CLASS KeySetInformationClass,
_In_reads_bytes_(KeySetInformationLength) PVOID KeySetInformation,
_In_ ULONG KeySetInformationLength
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryValueKey(
_In_ HANDLE KeyHandle,
_In_ PUNICODE_STRING ValueName,
_In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
_Out_writes_bytes_opt_(Length) PVOID KeyValueInformation,
_In_ ULONG Length,
_Out_ PULONG ResultLength
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSetValueKey(
_In_ HANDLE KeyHandle,
_In_ PUNICODE_STRING ValueName,
_In_opt_ ULONG TitleIndex,
_In_ ULONG Type,
_In_reads_bytes_opt_(DataSize) PVOID Data,
_In_ ULONG DataSize
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryMultipleValueKey(
_In_ HANDLE KeyHandle,
_Inout_updates_(EntryCount) PKEY_VALUE_ENTRY ValueEntries,
_In_ ULONG EntryCount,
_Out_writes_bytes_(*BufferLength) PVOID ValueBuffer,
_Inout_ PULONG BufferLength,
_Out_opt_ PULONG RequiredBufferLength
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtEnumerateKey(
_In_ HANDLE KeyHandle,
_In_ ULONG Index,
_In_ KEY_INFORMATION_CLASS KeyInformationClass,
_Out_writes_bytes_opt_(Length) PVOID KeyInformation,
_In_ ULONG Length,
_Out_ PULONG ResultLength
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtEnumerateValueKey(
_In_ HANDLE KeyHandle,
_In_ ULONG Index,
_In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
_Out_writes_bytes_opt_(Length) PVOID KeyValueInformation,
_In_ ULONG Length,
_Out_ PULONG ResultLength
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtFlushKey(
_In_ HANDLE KeyHandle
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCompactKeys(
_In_ ULONG Count,
_In_reads_(Count) HANDLE KeyArray[]
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCompressKey(
_In_ HANDLE Key
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtLoadKey(
_In_ POBJECT_ATTRIBUTES TargetKey,
_In_ POBJECT_ATTRIBUTES SourceFile
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtLoadKey2(
_In_ POBJECT_ATTRIBUTES TargetKey,
_In_ POBJECT_ATTRIBUTES SourceFile,
_In_ ULONG Flags
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtLoadKeyEx(
_In_ POBJECT_ATTRIBUTES TargetKey,
_In_ POBJECT_ATTRIBUTES SourceFile,
_In_ ULONG Flags,
_In_opt_ HANDLE TrustClassKey,
_In_opt_ HANDLE Event,
_In_opt_ ACCESS_MASK DesiredAccess,
_Out_opt_ PHANDLE RootHandle,
_Out_opt_ PIO_STATUS_BLOCK IoStatus
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtReplaceKey(
_In_ POBJECT_ATTRIBUTES NewFile,
_In_ HANDLE TargetHandle,
_In_ POBJECT_ATTRIBUTES OldFile
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSaveKey(
_In_ HANDLE KeyHandle,
_In_ HANDLE FileHandle
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSaveKeyEx(
_In_ HANDLE KeyHandle,
_In_ HANDLE FileHandle,
_In_ ULONG Format
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSaveMergedKeys(
_In_ HANDLE HighPrecedenceKeyHandle,
_In_ HANDLE LowPrecedenceKeyHandle,
_In_ HANDLE FileHandle
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtRestoreKey(
_In_ HANDLE KeyHandle,
_In_ HANDLE FileHandle,
_In_ ULONG Flags
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtUnloadKey(
_In_ POBJECT_ATTRIBUTES TargetKey
);
//
// NtUnloadKey2 Flags (from winnt.h)
//
//#define REG_FORCE_UNLOAD 1
//#define REG_UNLOAD_LEGAL_FLAGS (REG_FORCE_UNLOAD)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtUnloadKey2(
_In_ POBJECT_ATTRIBUTES TargetKey,
_In_ ULONG Flags
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtUnloadKeyEx(
_In_ POBJECT_ATTRIBUTES TargetKey,
_In_opt_ HANDLE Event
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtNotifyChangeKey(
_In_ HANDLE KeyHandle,
_In_opt_ HANDLE Event,
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
_In_opt_ PVOID ApcContext,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_In_ ULONG CompletionFilter,
_In_ BOOLEAN WatchTree,
_Out_writes_bytes_opt_(BufferSize) PVOID Buffer,
_In_ ULONG BufferSize,
_In_ BOOLEAN Asynchronous
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtNotifyChangeMultipleKeys(
_In_ HANDLE MasterKeyHandle,
_In_opt_ ULONG Count,
_In_reads_opt_(Count) OBJECT_ATTRIBUTES SubordinateObjects[],
_In_opt_ HANDLE Event,
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
_In_opt_ PVOID ApcContext,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_In_ ULONG CompletionFilter,
_In_ BOOLEAN WatchTree,
_Out_writes_bytes_opt_(BufferSize) PVOID Buffer,
_In_ ULONG BufferSize,
_In_ BOOLEAN Asynchronous
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryOpenSubKeys(
_In_ POBJECT_ATTRIBUTES TargetKey,
_Out_ PULONG HandleCount
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryOpenSubKeysEx(
_In_ POBJECT_ATTRIBUTES TargetKey,
_In_ ULONG BufferLength,
_Out_writes_bytes_opt_(BufferLength) PVOID Buffer,
_Out_ PULONG RequiredSize
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtInitializeRegistry(
_In_ USHORT BootCondition
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtLockRegistryKey(
_In_ HANDLE KeyHandle
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtLockProductActivationKeys(
_Inout_opt_ ULONG *pPrivateVer,
_Out_opt_ ULONG *pSafeMode
);
#if (PHNT_VERSION >= PHNT_VISTA)
// private
NTSYSCALLAPI
NTSTATUS
NTAPI
NtFreezeRegistry(
_In_ ULONG TimeOutInSeconds
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
// private
NTSYSCALLAPI
NTSTATUS
NTAPI
NtThawRegistry(
VOID
);
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,630 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTSEAPI_H
#define _NTSEAPI_H
// Privileges
#define SE_MIN_WELL_KNOWN_PRIVILEGE (2L)
#define SE_CREATE_TOKEN_PRIVILEGE (2L)
#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE (3L)
#define SE_LOCK_MEMORY_PRIVILEGE (4L)
#define SE_INCREASE_QUOTA_PRIVILEGE (5L)
#define SE_MACHINE_ACCOUNT_PRIVILEGE (6L)
#define SE_TCB_PRIVILEGE (7L)
#define SE_SECURITY_PRIVILEGE (8L)
#define SE_TAKE_OWNERSHIP_PRIVILEGE (9L)
#define SE_LOAD_DRIVER_PRIVILEGE (10L)
#define SE_SYSTEM_PROFILE_PRIVILEGE (11L)
#define SE_SYSTEMTIME_PRIVILEGE (12L)
#define SE_PROF_SINGLE_PROCESS_PRIVILEGE (13L)
#define SE_INC_BASE_PRIORITY_PRIVILEGE (14L)
#define SE_CREATE_PAGEFILE_PRIVILEGE (15L)
#define SE_CREATE_PERMANENT_PRIVILEGE (16L)
#define SE_BACKUP_PRIVILEGE (17L)
#define SE_RESTORE_PRIVILEGE (18L)
#define SE_SHUTDOWN_PRIVILEGE (19L)
#define SE_DEBUG_PRIVILEGE (20L)
#define SE_AUDIT_PRIVILEGE (21L)
#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE (22L)
#define SE_CHANGE_NOTIFY_PRIVILEGE (23L)
#define SE_REMOTE_SHUTDOWN_PRIVILEGE (24L)
#define SE_UNDOCK_PRIVILEGE (25L)
#define SE_SYNC_AGENT_PRIVILEGE (26L)
#define SE_ENABLE_DELEGATION_PRIVILEGE (27L)
#define SE_MANAGE_VOLUME_PRIVILEGE (28L)
#define SE_IMPERSONATE_PRIVILEGE (29L)
#define SE_CREATE_GLOBAL_PRIVILEGE (30L)
#define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE (31L)
#define SE_RELABEL_PRIVILEGE (32L)
#define SE_INC_WORKING_SET_PRIVILEGE (33L)
#define SE_TIME_ZONE_PRIVILEGE (34L)
#define SE_CREATE_SYMBOLIC_LINK_PRIVILEGE (35L)
#define SE_DELEGATE_SESSION_USER_IMPERSONATE_PRIVILEGE (36L)
#define SE_MAX_WELL_KNOWN_PRIVILEGE SE_DELEGATE_SESSION_USER_IMPERSONATE_PRIVILEGE
// Authz
// begin_rev
// Types
#define TOKEN_SECURITY_ATTRIBUTE_TYPE_INVALID 0x00
#define TOKEN_SECURITY_ATTRIBUTE_TYPE_INT64 0x01
#define TOKEN_SECURITY_ATTRIBUTE_TYPE_UINT64 0x02
#define TOKEN_SECURITY_ATTRIBUTE_TYPE_STRING 0x03
#define TOKEN_SECURITY_ATTRIBUTE_TYPE_FQBN 0x04
#define TOKEN_SECURITY_ATTRIBUTE_TYPE_SID 0x05
#define TOKEN_SECURITY_ATTRIBUTE_TYPE_BOOLEAN 0x06
#define TOKEN_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING 0x10
// Flags
#define TOKEN_SECURITY_ATTRIBUTE_NON_INHERITABLE 0x0001
#define TOKEN_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE 0x0002
#define TOKEN_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY 0x0004
#define TOKEN_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT 0x0008
#define TOKEN_SECURITY_ATTRIBUTE_DISABLED 0x0010
#define TOKEN_SECURITY_ATTRIBUTE_MANDATORY 0x0020
#define TOKEN_SECURITY_ATTRIBUTE_COMPARE_IGNORE 0x0040
#define TOKEN_SECURITY_ATTRIBUTE_VALID_FLAGS ( \
TOKEN_SECURITY_ATTRIBUTE_NON_INHERITABLE | \
TOKEN_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE | \
TOKEN_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY | \
TOKEN_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT | \
TOKEN_SECURITY_ATTRIBUTE_DISABLED | \
TOKEN_SECURITY_ATTRIBUTE_MANDATORY)
#define TOKEN_SECURITY_ATTRIBUTE_CUSTOM_FLAGS 0xffff0000
// end_rev
// private
typedef struct _TOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE
{
ULONG64 Version;
UNICODE_STRING Name;
} TOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE, *PTOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE;
// private
typedef struct _TOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE
{
PVOID pValue;
ULONG ValueLength;
} TOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE, *PTOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE;
// private
typedef struct _TOKEN_SECURITY_ATTRIBUTE_V1
{
UNICODE_STRING Name;
USHORT ValueType;
USHORT Reserved;
ULONG Flags;
ULONG ValueCount;
union
{
PLONG64 pInt64;
PULONG64 pUint64;
PUNICODE_STRING pString;
PTOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE pFqbn;
PTOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE pOctetString;
} Values;
} TOKEN_SECURITY_ATTRIBUTE_V1, *PTOKEN_SECURITY_ATTRIBUTE_V1;
// rev
#define TOKEN_SECURITY_ATTRIBUTES_INFORMATION_VERSION_V1 1
// rev
#define TOKEN_SECURITY_ATTRIBUTES_INFORMATION_VERSION TOKEN_SECURITY_ATTRIBUTES_INFORMATION_VERSION_V1
// private
typedef struct _TOKEN_SECURITY_ATTRIBUTES_INFORMATION
{
USHORT Version;
USHORT Reserved;
ULONG AttributeCount;
union
{
PTOKEN_SECURITY_ATTRIBUTE_V1 pAttributeV1;
} Attribute;
} TOKEN_SECURITY_ATTRIBUTES_INFORMATION, *PTOKEN_SECURITY_ATTRIBUTES_INFORMATION;
// rev
typedef struct _TOKEN_PROCESS_TRUST_LEVEL
{
PSID TrustLevelSid;
} TOKEN_PROCESS_TRUST_LEVEL, *PTOKEN_PROCESS_TRUST_LEVEL;
// Tokens
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCreateToken(
_Out_ PHANDLE TokenHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ TOKEN_TYPE TokenType,
_In_ PLUID AuthenticationId,
_In_ PLARGE_INTEGER ExpirationTime,
_In_ PTOKEN_USER User,
_In_ PTOKEN_GROUPS Groups,
_In_ PTOKEN_PRIVILEGES Privileges,
_In_opt_ PTOKEN_OWNER Owner,
_In_ PTOKEN_PRIMARY_GROUP PrimaryGroup,
_In_opt_ PTOKEN_DEFAULT_DACL DefaultDacl,
_In_ PTOKEN_SOURCE TokenSource
);
#if (PHNT_VERSION >= PHNT_WIN8)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCreateLowBoxToken(
_Out_ PHANDLE TokenHandle,
_In_ HANDLE ExistingTokenHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ PSID PackageSid,
_In_ ULONG CapabilityCount,
_In_reads_opt_(CapabilityCount) PSID_AND_ATTRIBUTES Capabilities,
_In_ ULONG HandleCount,
_In_reads_opt_(HandleCount) HANDLE *Handles
);
#endif
#if (PHNT_VERSION >= PHNT_WIN8)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCreateTokenEx(
_Out_ PHANDLE TokenHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ TOKEN_TYPE TokenType,
_In_ PLUID AuthenticationId,
_In_ PLARGE_INTEGER ExpirationTime,
_In_ PTOKEN_USER User,
_In_ PTOKEN_GROUPS Groups,
_In_ PTOKEN_PRIVILEGES Privileges,
_In_opt_ PTOKEN_SECURITY_ATTRIBUTES_INFORMATION UserAttributes,
_In_opt_ PTOKEN_SECURITY_ATTRIBUTES_INFORMATION DeviceAttributes,
_In_opt_ PTOKEN_GROUPS DeviceGroups,
_In_opt_ PTOKEN_MANDATORY_POLICY TokenMandatoryPolicy,
_In_opt_ PTOKEN_OWNER Owner,
_In_ PTOKEN_PRIMARY_GROUP PrimaryGroup,
_In_opt_ PTOKEN_DEFAULT_DACL DefaultDacl,
_In_ PTOKEN_SOURCE TokenSource
);
#endif
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenProcessToken(
_In_ HANDLE ProcessHandle,
_In_ ACCESS_MASK DesiredAccess,
_Out_ PHANDLE TokenHandle
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenProcessTokenEx(
_In_ HANDLE ProcessHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ ULONG HandleAttributes,
_Out_ PHANDLE TokenHandle
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenThreadToken(
_In_ HANDLE ThreadHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ BOOLEAN OpenAsSelf,
_Out_ PHANDLE TokenHandle
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenThreadTokenEx(
_In_ HANDLE ThreadHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ BOOLEAN OpenAsSelf,
_In_ ULONG HandleAttributes,
_Out_ PHANDLE TokenHandle
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtDuplicateToken(
_In_ HANDLE ExistingTokenHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ BOOLEAN EffectiveOnly,
_In_ TOKEN_TYPE TokenType,
_Out_ PHANDLE NewTokenHandle
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryInformationToken(
_In_ HANDLE TokenHandle,
_In_ TOKEN_INFORMATION_CLASS TokenInformationClass,
_Out_writes_bytes_(TokenInformationLength) PVOID TokenInformation,
_In_ ULONG TokenInformationLength,
_Out_ PULONG ReturnLength
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSetInformationToken(
_In_ HANDLE TokenHandle,
_In_ TOKEN_INFORMATION_CLASS TokenInformationClass,
_In_reads_bytes_(TokenInformationLength) PVOID TokenInformation,
_In_ ULONG TokenInformationLength
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtAdjustPrivilegesToken(
_In_ HANDLE TokenHandle,
_In_ BOOLEAN DisableAllPrivileges,
_In_opt_ PTOKEN_PRIVILEGES NewState,
_In_ ULONG BufferLength,
_Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PTOKEN_PRIVILEGES PreviousState,
_Out_opt_ PULONG ReturnLength
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtAdjustGroupsToken(
_In_ HANDLE TokenHandle,
_In_ BOOLEAN ResetToDefault,
_In_opt_ PTOKEN_GROUPS NewState,
_In_opt_ ULONG BufferLength,
_Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PTOKEN_GROUPS PreviousState,
_Out_opt_ PULONG ReturnLength
);
#if (PHNT_VERSION >= PHNT_WIN8)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtAdjustTokenClaimsAndDeviceGroups(
_In_ HANDLE TokenHandle,
_In_ BOOLEAN UserResetToDefault,
_In_ BOOLEAN DeviceResetToDefault,
_In_ BOOLEAN DeviceGroupsResetToDefault,
_In_opt_ PTOKEN_SECURITY_ATTRIBUTES_INFORMATION NewUserState,
_In_opt_ PTOKEN_SECURITY_ATTRIBUTES_INFORMATION NewDeviceState,
_In_opt_ PTOKEN_GROUPS NewDeviceGroupsState,
_In_ ULONG UserBufferLength,
_Out_writes_bytes_to_opt_(UserBufferLength, *UserReturnLength) PTOKEN_SECURITY_ATTRIBUTES_INFORMATION PreviousUserState,
_In_ ULONG DeviceBufferLength,
_Out_writes_bytes_to_opt_(DeviceBufferLength, *DeviceReturnLength) PTOKEN_SECURITY_ATTRIBUTES_INFORMATION PreviousDeviceState,
_In_ ULONG DeviceGroupsBufferLength,
_Out_writes_bytes_to_opt_(DeviceGroupsBufferLength, *DeviceGroupsReturnBufferLength) PTOKEN_GROUPS PreviousDeviceGroups,
_Out_opt_ PULONG UserReturnLength,
_Out_opt_ PULONG DeviceReturnLength,
_Out_opt_ PULONG DeviceGroupsReturnBufferLength
);
#endif
NTSYSCALLAPI
NTSTATUS
NTAPI
NtFilterToken(
_In_ HANDLE ExistingTokenHandle,
_In_ ULONG Flags,
_In_opt_ PTOKEN_GROUPS SidsToDisable,
_In_opt_ PTOKEN_PRIVILEGES PrivilegesToDelete,
_In_opt_ PTOKEN_GROUPS RestrictedSids,
_Out_ PHANDLE NewTokenHandle
);
#if (PHNT_VERSION >= PHNT_WIN8)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtFilterTokenEx(
_In_ HANDLE ExistingTokenHandle,
_In_ ULONG Flags,
_In_opt_ PTOKEN_GROUPS SidsToDisable,
_In_opt_ PTOKEN_PRIVILEGES PrivilegesToDelete,
_In_opt_ PTOKEN_GROUPS RestrictedSids,
_In_ ULONG DisableUserClaimsCount,
_In_opt_ PUNICODE_STRING UserClaimsToDisable,
_In_ ULONG DisableDeviceClaimsCount,
_In_opt_ PUNICODE_STRING DeviceClaimsToDisable,
_In_opt_ PTOKEN_GROUPS DeviceGroupsToDisable,
_In_opt_ PTOKEN_SECURITY_ATTRIBUTES_INFORMATION RestrictedUserAttributes,
_In_opt_ PTOKEN_SECURITY_ATTRIBUTES_INFORMATION RestrictedDeviceAttributes,
_In_opt_ PTOKEN_GROUPS RestrictedDeviceGroups,
_Out_ PHANDLE NewTokenHandle
);
#endif
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCompareTokens(
_In_ HANDLE FirstTokenHandle,
_In_ HANDLE SecondTokenHandle,
_Out_ PBOOLEAN Equal
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtPrivilegeCheck(
_In_ HANDLE ClientToken,
_Inout_ PPRIVILEGE_SET RequiredPrivileges,
_Out_ PBOOLEAN Result
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtImpersonateAnonymousToken(
_In_ HANDLE ThreadHandle
);
#if (PHNT_VERSION >= PHNT_WIN7)
// rev
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQuerySecurityAttributesToken(
_In_ HANDLE TokenHandle,
_In_reads_opt_(NumberOfAttributes) PUNICODE_STRING Attributes,
_In_ ULONG NumberOfAttributes,
_Out_writes_bytes_(Length) PVOID Buffer, // PTOKEN_SECURITY_ATTRIBUTES_INFORMATION
_In_ ULONG Length,
_Out_ PULONG ReturnLength
);
#endif
// Access checking
NTSYSCALLAPI
NTSTATUS
NTAPI
NtAccessCheck(
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
_In_ HANDLE ClientToken,
_In_ ACCESS_MASK DesiredAccess,
_In_ PGENERIC_MAPPING GenericMapping,
_Out_writes_bytes_(*PrivilegeSetLength) PPRIVILEGE_SET PrivilegeSet,
_Inout_ PULONG PrivilegeSetLength,
_Out_ PACCESS_MASK GrantedAccess,
_Out_ PNTSTATUS AccessStatus
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtAccessCheckByType(
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
_In_opt_ PSID PrincipalSelfSid,
_In_ HANDLE ClientToken,
_In_ ACCESS_MASK DesiredAccess,
_In_reads_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
_In_ ULONG ObjectTypeListLength,
_In_ PGENERIC_MAPPING GenericMapping,
_Out_writes_bytes_(*PrivilegeSetLength) PPRIVILEGE_SET PrivilegeSet,
_Inout_ PULONG PrivilegeSetLength,
_Out_ PACCESS_MASK GrantedAccess,
_Out_ PNTSTATUS AccessStatus
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtAccessCheckByTypeResultList(
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
_In_opt_ PSID PrincipalSelfSid,
_In_ HANDLE ClientToken,
_In_ ACCESS_MASK DesiredAccess,
_In_reads_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
_In_ ULONG ObjectTypeListLength,
_In_ PGENERIC_MAPPING GenericMapping,
_Out_writes_bytes_(*PrivilegeSetLength) PPRIVILEGE_SET PrivilegeSet,
_Inout_ PULONG PrivilegeSetLength,
_Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccess,
_Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatus
);
// Signing
#if (PHNT_VERSION >= PHNT_THRESHOLD)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSetCachedSigningLevel(
_In_ ULONG Flags,
_In_ SE_SIGNING_LEVEL InputSigningLevel,
_In_reads_(SourceFileCount) PHANDLE SourceFiles,
_In_ ULONG SourceFileCount,
_In_opt_ HANDLE TargetFile
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtGetCachedSigningLevel(
_In_ HANDLE File,
_Out_ PULONG Flags,
_Out_ PSE_SIGNING_LEVEL SigningLevel,
_Out_writes_bytes_to_opt_(*ThumbprintSize, *ThumbprintSize) PUCHAR Thumbprint,
_Inout_opt_ PULONG ThumbprintSize,
_Out_opt_ PULONG ThumbprintAlgorithm
);
#endif
// Audit alarm
NTSYSCALLAPI
NTSTATUS
NTAPI
NtAccessCheckAndAuditAlarm(
_In_ PUNICODE_STRING SubsystemName,
_In_opt_ PVOID HandleId,
_In_ PUNICODE_STRING ObjectTypeName,
_In_ PUNICODE_STRING ObjectName,
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
_In_ ACCESS_MASK DesiredAccess,
_In_ PGENERIC_MAPPING GenericMapping,
_In_ BOOLEAN ObjectCreation,
_Out_ PACCESS_MASK GrantedAccess,
_Out_ PNTSTATUS AccessStatus,
_Out_ PBOOLEAN GenerateOnClose
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtAccessCheckByTypeAndAuditAlarm(
_In_ PUNICODE_STRING SubsystemName,
_In_opt_ PVOID HandleId,
_In_ PUNICODE_STRING ObjectTypeName,
_In_ PUNICODE_STRING ObjectName,
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
_In_opt_ PSID PrincipalSelfSid,
_In_ ACCESS_MASK DesiredAccess,
_In_ AUDIT_EVENT_TYPE AuditType,
_In_ ULONG Flags,
_In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
_In_ ULONG ObjectTypeListLength,
_In_ PGENERIC_MAPPING GenericMapping,
_In_ BOOLEAN ObjectCreation,
_Out_ PACCESS_MASK GrantedAccess,
_Out_ PNTSTATUS AccessStatus,
_Out_ PBOOLEAN GenerateOnClose
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtAccessCheckByTypeResultListAndAuditAlarm(
_In_ PUNICODE_STRING SubsystemName,
_In_opt_ PVOID HandleId,
_In_ PUNICODE_STRING ObjectTypeName,
_In_ PUNICODE_STRING ObjectName,
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
_In_opt_ PSID PrincipalSelfSid,
_In_ ACCESS_MASK DesiredAccess,
_In_ AUDIT_EVENT_TYPE AuditType,
_In_ ULONG Flags,
_In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
_In_ ULONG ObjectTypeListLength,
_In_ PGENERIC_MAPPING GenericMapping,
_In_ BOOLEAN ObjectCreation,
_Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccess,
_Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatus,
_Out_ PBOOLEAN GenerateOnClose
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtAccessCheckByTypeResultListAndAuditAlarmByHandle(
_In_ PUNICODE_STRING SubsystemName,
_In_opt_ PVOID HandleId,
_In_ HANDLE ClientToken,
_In_ PUNICODE_STRING ObjectTypeName,
_In_ PUNICODE_STRING ObjectName,
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
_In_opt_ PSID PrincipalSelfSid,
_In_ ACCESS_MASK DesiredAccess,
_In_ AUDIT_EVENT_TYPE AuditType,
_In_ ULONG Flags,
_In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
_In_ ULONG ObjectTypeListLength,
_In_ PGENERIC_MAPPING GenericMapping,
_In_ BOOLEAN ObjectCreation,
_Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccess,
_Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatus,
_Out_ PBOOLEAN GenerateOnClose
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenObjectAuditAlarm(
_In_ PUNICODE_STRING SubsystemName,
_In_opt_ PVOID HandleId,
_In_ PUNICODE_STRING ObjectTypeName,
_In_ PUNICODE_STRING ObjectName,
_In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor,
_In_ HANDLE ClientToken,
_In_ ACCESS_MASK DesiredAccess,
_In_ ACCESS_MASK GrantedAccess,
_In_opt_ PPRIVILEGE_SET Privileges,
_In_ BOOLEAN ObjectCreation,
_In_ BOOLEAN AccessGranted,
_Out_ PBOOLEAN GenerateOnClose
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtPrivilegeObjectAuditAlarm(
_In_ PUNICODE_STRING SubsystemName,
_In_opt_ PVOID HandleId,
_In_ HANDLE ClientToken,
_In_ ACCESS_MASK DesiredAccess,
_In_ PPRIVILEGE_SET Privileges,
_In_ BOOLEAN AccessGranted
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCloseObjectAuditAlarm(
_In_ PUNICODE_STRING SubsystemName,
_In_opt_ PVOID HandleId,
_In_ BOOLEAN GenerateOnClose
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtDeleteObjectAuditAlarm(
_In_ PUNICODE_STRING SubsystemName,
_In_opt_ PVOID HandleId,
_In_ BOOLEAN GenerateOnClose
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtPrivilegedServiceAuditAlarm(
_In_ PUNICODE_STRING SubsystemName,
_In_ PUNICODE_STRING ServiceName,
_In_ HANDLE ClientToken,
_In_ PPRIVILEGE_SET Privileges,
_In_ BOOLEAN AccessGranted
);
#endif

@ -0,0 +1,33 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTSMSS_H
#define _NTSMSS_H
NTSYSAPI
NTSTATUS
NTAPI
RtlConnectToSm(
_In_ PUNICODE_STRING ApiPortName,
_In_ HANDLE ApiPortHandle,
_In_ DWORD ProcessImageType,
_Out_ PHANDLE SmssConnection
);
NTSYSAPI
NTSTATUS
NTAPI
RtlSendMsgToSm(
_In_ HANDLE ApiPortHandle,
_In_ PPORT_MESSAGE MessageData
);
#endif

@ -0,0 +1,484 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTTMAPI_H
#define _NTTMAPI_H
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCreateTransactionManager(
_Out_ PHANDLE TmHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PUNICODE_STRING LogFileName,
_In_opt_ ULONG CreateOptions,
_In_opt_ ULONG CommitStrength
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenTransactionManager(
_Out_ PHANDLE TmHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PUNICODE_STRING LogFileName,
_In_opt_ LPGUID TmIdentity,
_In_opt_ ULONG OpenOptions
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtRenameTransactionManager(
_In_ PUNICODE_STRING LogFileName,
_In_ LPGUID ExistingTransactionManagerGuid
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtRollforwardTransactionManager(
_In_ HANDLE TransactionManagerHandle,
_In_opt_ PLARGE_INTEGER TmVirtualClock
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtRecoverTransactionManager(
_In_ HANDLE TransactionManagerHandle
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryInformationTransactionManager(
_In_ HANDLE TransactionManagerHandle,
_In_ TRANSACTIONMANAGER_INFORMATION_CLASS TransactionManagerInformationClass,
_Out_writes_bytes_(TransactionManagerInformationLength) PVOID TransactionManagerInformation,
_In_ ULONG TransactionManagerInformationLength,
_Out_opt_ PULONG ReturnLength
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSetInformationTransactionManager(
_In_opt_ HANDLE TmHandle,
_In_ TRANSACTIONMANAGER_INFORMATION_CLASS TransactionManagerInformationClass,
_In_reads_bytes_(TransactionManagerInformationLength) PVOID TransactionManagerInformation,
_In_ ULONG TransactionManagerInformationLength
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtEnumerateTransactionObject(
_In_opt_ HANDLE RootObjectHandle,
_In_ KTMOBJECT_TYPE QueryType,
_Inout_updates_bytes_(ObjectCursorLength) PKTMOBJECT_CURSOR ObjectCursor,
_In_ ULONG ObjectCursorLength,
_Out_ PULONG ReturnLength
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCreateTransaction(
_Out_ PHANDLE TransactionHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ LPGUID Uow,
_In_opt_ HANDLE TmHandle,
_In_opt_ ULONG CreateOptions,
_In_opt_ ULONG IsolationLevel,
_In_opt_ ULONG IsolationFlags,
_In_opt_ PLARGE_INTEGER Timeout,
_In_opt_ PUNICODE_STRING Description
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenTransaction(
_Out_ PHANDLE TransactionHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ LPGUID Uow,
_In_opt_ HANDLE TmHandle
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryInformationTransaction(
_In_ HANDLE TransactionHandle,
_In_ TRANSACTION_INFORMATION_CLASS TransactionInformationClass,
_Out_writes_bytes_(TransactionInformationLength) PVOID TransactionInformation,
_In_ ULONG TransactionInformationLength,
_Out_opt_ PULONG ReturnLength
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSetInformationTransaction(
_In_ HANDLE TransactionHandle,
_In_ TRANSACTION_INFORMATION_CLASS TransactionInformationClass,
_In_reads_bytes_(TransactionInformationLength) PVOID TransactionInformation,
_In_ ULONG TransactionInformationLength
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCommitTransaction(
_In_ HANDLE TransactionHandle,
_In_ BOOLEAN Wait
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtRollbackTransaction(
_In_ HANDLE TransactionHandle,
_In_ BOOLEAN Wait
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCreateEnlistment(
_Out_ PHANDLE EnlistmentHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ HANDLE ResourceManagerHandle,
_In_ HANDLE TransactionHandle,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ ULONG CreateOptions,
_In_ NOTIFICATION_MASK NotificationMask,
_In_opt_ PVOID EnlistmentKey
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenEnlistment(
_Out_ PHANDLE EnlistmentHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ HANDLE ResourceManagerHandle,
_In_ LPGUID EnlistmentGuid,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryInformationEnlistment(
_In_ HANDLE EnlistmentHandle,
_In_ ENLISTMENT_INFORMATION_CLASS EnlistmentInformationClass,
_Out_writes_bytes_(EnlistmentInformationLength) PVOID EnlistmentInformation,
_In_ ULONG EnlistmentInformationLength,
_Out_opt_ PULONG ReturnLength
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSetInformationEnlistment(
_In_opt_ HANDLE EnlistmentHandle,
_In_ ENLISTMENT_INFORMATION_CLASS EnlistmentInformationClass,
_In_reads_bytes_(EnlistmentInformationLength) PVOID EnlistmentInformation,
_In_ ULONG EnlistmentInformationLength
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtRecoverEnlistment(
_In_ HANDLE EnlistmentHandle,
_In_opt_ PVOID EnlistmentKey
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtPrePrepareEnlistment(
_In_ HANDLE EnlistmentHandle,
_In_opt_ PLARGE_INTEGER TmVirtualClock
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtPrepareEnlistment(
_In_ HANDLE EnlistmentHandle,
_In_opt_ PLARGE_INTEGER TmVirtualClock
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCommitEnlistment(
_In_ HANDLE EnlistmentHandle,
_In_opt_ PLARGE_INTEGER TmVirtualClock
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtRollbackEnlistment(
_In_ HANDLE EnlistmentHandle,
_In_opt_ PLARGE_INTEGER TmVirtualClock
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtPrePrepareComplete(
_In_ HANDLE EnlistmentHandle,
_In_opt_ PLARGE_INTEGER TmVirtualClock
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtPrepareComplete(
_In_ HANDLE EnlistmentHandle,
_In_opt_ PLARGE_INTEGER TmVirtualClock
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCommitComplete(
_In_ HANDLE EnlistmentHandle,
_In_opt_ PLARGE_INTEGER TmVirtualClock
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtReadOnlyEnlistment(
_In_ HANDLE EnlistmentHandle,
_In_opt_ PLARGE_INTEGER TmVirtualClock
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtRollbackComplete(
_In_ HANDLE EnlistmentHandle,
_In_opt_ PLARGE_INTEGER TmVirtualClock
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSinglePhaseReject(
_In_ HANDLE EnlistmentHandle,
_In_opt_ PLARGE_INTEGER TmVirtualClock
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCreateResourceManager(
_Out_ PHANDLE ResourceManagerHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ HANDLE TmHandle,
_In_ LPGUID RmGuid,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ ULONG CreateOptions,
_In_opt_ PUNICODE_STRING Description
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenResourceManager(
_Out_ PHANDLE ResourceManagerHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ HANDLE TmHandle,
_In_opt_ LPGUID ResourceManagerGuid,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtRecoverResourceManager(
_In_ HANDLE ResourceManagerHandle
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtGetNotificationResourceManager(
_In_ HANDLE ResourceManagerHandle,
_Out_ PTRANSACTION_NOTIFICATION TransactionNotification,
_In_ ULONG NotificationLength,
_In_opt_ PLARGE_INTEGER Timeout,
_Out_opt_ PULONG ReturnLength,
_In_ ULONG Asynchronous,
_In_opt_ ULONG_PTR AsynchronousContext
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryInformationResourceManager(
_In_ HANDLE ResourceManagerHandle,
_In_ RESOURCEMANAGER_INFORMATION_CLASS ResourceManagerInformationClass,
_Out_writes_bytes_(ResourceManagerInformationLength) PVOID ResourceManagerInformation,
_In_ ULONG ResourceManagerInformationLength,
_Out_opt_ PULONG ReturnLength
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtSetInformationResourceManager(
_In_ HANDLE ResourceManagerHandle,
_In_ RESOURCEMANAGER_INFORMATION_CLASS ResourceManagerInformationClass,
_In_reads_bytes_(ResourceManagerInformationLength) PVOID ResourceManagerInformation,
_In_ ULONG ResourceManagerInformationLength
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtRegisterProtocolAddressInformation(
_In_ HANDLE ResourceManager,
_In_ PCRM_PROTOCOL_ID ProtocolId,
_In_ ULONG ProtocolInformationSize,
_In_ PVOID ProtocolInformation,
_In_opt_ ULONG CreateOptions
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtPropagationComplete(
_In_ HANDLE ResourceManagerHandle,
_In_ ULONG RequestCookie,
_In_ ULONG BufferLength,
_In_ PVOID Buffer
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtPropagationFailed(
_In_ HANDLE ResourceManagerHandle,
_In_ ULONG RequestCookie,
_In_ NTSTATUS PropStatus
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
// private
NTSYSCALLAPI
NTSTATUS
NTAPI
NtFreezeTransactions(
_In_ PLARGE_INTEGER FreezeTimeout,
_In_ PLARGE_INTEGER ThawTimeout
);
#endif
#if (PHNT_VERSION >= PHNT_VISTA)
// private
NTSYSCALLAPI
NTSTATUS
NTAPI
NtThawTransactions(
VOID
);
#endif
#endif

@ -0,0 +1,467 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTTP_H
#define _NTTP_H
// Some types are already defined in winnt.h.
typedef struct _TP_ALPC TP_ALPC, *PTP_ALPC;
// private
typedef VOID (NTAPI *PTP_ALPC_CALLBACK)(
_Inout_ PTP_CALLBACK_INSTANCE Instance,
_Inout_opt_ PVOID Context,
_In_ PTP_ALPC Alpc
);
// rev
typedef VOID (NTAPI *PTP_ALPC_CALLBACK_EX)(
_Inout_ PTP_CALLBACK_INSTANCE Instance,
_Inout_opt_ PVOID Context,
_In_ PTP_ALPC Alpc,
_In_ PVOID ApcContext
);
#if (PHNT_VERSION >= PHNT_VISTA)
// private
_Check_return_
NTSYSAPI
NTSTATUS
NTAPI
TpAllocPool(
_Out_ PTP_POOL *PoolReturn,
_Reserved_ PVOID Reserved
);
// winbase:CloseThreadpool
NTSYSAPI
VOID
NTAPI
TpReleasePool(
_Inout_ PTP_POOL Pool
);
// winbase:SetThreadpoolThreadMaximum
NTSYSAPI
VOID
NTAPI
TpSetPoolMaxThreads(
_Inout_ PTP_POOL Pool,
_In_ ULONG MaxThreads
);
// private
NTSYSAPI
NTSTATUS
NTAPI
TpSetPoolMinThreads(
_Inout_ PTP_POOL Pool,
_In_ ULONG MinThreads
);
#if (PHNT_VERSION >= PHNT_WIN7)
// rev
NTSYSAPI
NTSTATUS
NTAPI
TpQueryPoolStackInformation(
_In_ PTP_POOL Pool,
_Out_ PTP_POOL_STACK_INFORMATION PoolStackInformation
);
#endif
#if (PHNT_VERSION >= PHNT_WIN7)
// rev
NTSYSAPI
NTSTATUS
NTAPI
TpSetPoolStackInformation(
_Inout_ PTP_POOL Pool,
_In_ PTP_POOL_STACK_INFORMATION PoolStackInformation
);
#endif
// private
_Check_return_
NTSYSAPI
NTSTATUS
NTAPI
TpAllocCleanupGroup(
_Out_ PTP_CLEANUP_GROUP *CleanupGroupReturn
);
// winbase:CloseThreadpoolCleanupGroup
NTSYSAPI
VOID
NTAPI
TpReleaseCleanupGroup(
_Inout_ PTP_CLEANUP_GROUP CleanupGroup
);
// winbase:CloseThreadpoolCleanupGroupMembers
NTSYSAPI
VOID
NTAPI
TpReleaseCleanupGroupMembers(
_Inout_ PTP_CLEANUP_GROUP CleanupGroup,
_In_ LOGICAL CancelPendingCallbacks,
_Inout_opt_ PVOID CleanupParameter
);
// winbase:SetEventWhenCallbackReturns
NTSYSAPI
VOID
NTAPI
TpCallbackSetEventOnCompletion(
_Inout_ PTP_CALLBACK_INSTANCE Instance,
_In_ HANDLE Event
);
// winbase:ReleaseSemaphoreWhenCallbackReturns
NTSYSAPI
VOID
NTAPI
TpCallbackReleaseSemaphoreOnCompletion(
_Inout_ PTP_CALLBACK_INSTANCE Instance,
_In_ HANDLE Semaphore,
_In_ ULONG ReleaseCount
);
// winbase:ReleaseMutexWhenCallbackReturns
NTSYSAPI
VOID
NTAPI
TpCallbackReleaseMutexOnCompletion(
_Inout_ PTP_CALLBACK_INSTANCE Instance,
_In_ HANDLE Mutex
);
// winbase:LeaveCriticalSectionWhenCallbackReturns
NTSYSAPI
VOID
NTAPI
TpCallbackLeaveCriticalSectionOnCompletion(
_Inout_ PTP_CALLBACK_INSTANCE Instance,
_Inout_ PRTL_CRITICAL_SECTION CriticalSection
);
// winbase:FreeLibraryWhenCallbackReturns
NTSYSAPI
VOID
NTAPI
TpCallbackUnloadDllOnCompletion(
_Inout_ PTP_CALLBACK_INSTANCE Instance,
_In_ PVOID DllHandle
);
// winbase:CallbackMayRunLong
NTSYSAPI
NTSTATUS
NTAPI
TpCallbackMayRunLong(
_Inout_ PTP_CALLBACK_INSTANCE Instance
);
// winbase:DisassociateCurrentThreadFromCallback
NTSYSAPI
VOID
NTAPI
TpDisassociateCallback(
_Inout_ PTP_CALLBACK_INSTANCE Instance
);
// winbase:TrySubmitThreadpoolCallback
_Check_return_
NTSYSAPI
NTSTATUS
NTAPI
TpSimpleTryPost(
_In_ PTP_SIMPLE_CALLBACK Callback,
_Inout_opt_ PVOID Context,
_In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron
);
// private
_Check_return_
NTSYSAPI
NTSTATUS
NTAPI
TpAllocWork(
_Out_ PTP_WORK *WorkReturn,
_In_ PTP_WORK_CALLBACK Callback,
_Inout_opt_ PVOID Context,
_In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron
);
// winbase:CloseThreadpoolWork
NTSYSAPI
VOID
NTAPI
TpReleaseWork(
_Inout_ PTP_WORK Work
);
// winbase:SubmitThreadpoolWork
NTSYSAPI
VOID
NTAPI
TpPostWork(
_Inout_ PTP_WORK Work
);
// winbase:WaitForThreadpoolWorkCallbacks
NTSYSAPI
VOID
NTAPI
TpWaitForWork(
_Inout_ PTP_WORK Work,
_In_ LOGICAL CancelPendingCallbacks
);
// private
_Check_return_
NTSYSAPI
NTSTATUS
NTAPI
TpAllocTimer(
_Out_ PTP_TIMER *Timer,
_In_ PTP_TIMER_CALLBACK Callback,
_Inout_opt_ PVOID Context,
_In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron
);
// winbase:CloseThreadpoolTimer
NTSYSAPI
VOID
NTAPI
TpReleaseTimer(
_Inout_ PTP_TIMER Timer
);
// winbase:SetThreadpoolTimer
NTSYSAPI
VOID
NTAPI
TpSetTimer(
_Inout_ PTP_TIMER Timer,
_In_opt_ PLARGE_INTEGER DueTime,
_In_ ULONG Period,
_In_opt_ ULONG WindowLength
);
#if (PHNT_VERSION >= PHNT_WIN7)
// winbase:SetThreadpoolTimerEx
NTSYSAPI
NTSTATUS
NTAPI
TpSetTimerEx(
_Inout_ PTP_TIMER Timer,
_In_opt_ PLARGE_INTEGER DueTime,
_In_ ULONG Period,
_In_opt_ ULONG WindowLength
);
#endif
// winbase:IsThreadpoolTimerSet
NTSYSAPI
LOGICAL
NTAPI
TpIsTimerSet(
_In_ PTP_TIMER Timer
);
// winbase:WaitForThreadpoolTimerCallbacks
NTSYSAPI
VOID
NTAPI
TpWaitForTimer(
_Inout_ PTP_TIMER Timer,
_In_ LOGICAL CancelPendingCallbacks
);
// private
_Check_return_
NTSYSAPI
NTSTATUS
NTAPI
TpAllocWait(
_Out_ PTP_WAIT *WaitReturn,
_In_ PTP_WAIT_CALLBACK Callback,
_Inout_opt_ PVOID Context,
_In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron
);
// winbase:CloseThreadpoolWait
NTSYSAPI
VOID
NTAPI
TpReleaseWait(
_Inout_ PTP_WAIT Wait
);
// winbase:SetThreadpoolWait
NTSYSAPI
VOID
NTAPI
TpSetWait(
_Inout_ PTP_WAIT Wait,
_In_opt_ HANDLE Handle,
_In_opt_ PLARGE_INTEGER Timeout
);
#if (PHNT_VERSION >= PHNT_WIN7)
// winbase:SetThreadpoolWaitEx
NTSYSAPI
NTSTATUS
NTAPI
TpSetWaitEx(
_Inout_ PTP_WAIT Wait,
_In_opt_ HANDLE Handle,
_In_opt_ PLARGE_INTEGER Timeout,
_In_opt_ PVOID Reserved
);
#endif
// winbase:WaitForThreadpoolWaitCallbacks
NTSYSAPI
VOID
NTAPI
TpWaitForWait(
_Inout_ PTP_WAIT Wait,
_In_ LOGICAL CancelPendingCallbacks
);
// private
typedef VOID (NTAPI *PTP_IO_CALLBACK)(
_Inout_ PTP_CALLBACK_INSTANCE Instance,
_Inout_opt_ PVOID Context,
_In_ PVOID ApcContext,
_In_ PIO_STATUS_BLOCK IoSB,
_In_ PTP_IO Io
);
// private
_Check_return_
NTSYSAPI
NTSTATUS
NTAPI
TpAllocIoCompletion(
_Out_ PTP_IO *IoReturn,
_In_ HANDLE File,
_In_ PTP_IO_CALLBACK Callback,
_Inout_opt_ PVOID Context,
_In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron
);
// winbase:CloseThreadpoolIo
NTSYSAPI
VOID
NTAPI
TpReleaseIoCompletion(
_Inout_ PTP_IO Io
);
// winbase:StartThreadpoolIo
NTSYSAPI
VOID
NTAPI
TpStartAsyncIoOperation(
_Inout_ PTP_IO Io
);
// winbase:CancelThreadpoolIo
NTSYSAPI
VOID
NTAPI
TpCancelAsyncIoOperation(
_Inout_ PTP_IO Io
);
// winbase:WaitForThreadpoolIoCallbacks
NTSYSAPI
VOID
NTAPI
TpWaitForIoCompletion(
_Inout_ PTP_IO Io,
_In_ LOGICAL CancelPendingCallbacks
);
// private
NTSYSAPI
NTSTATUS
NTAPI
TpAllocAlpcCompletion(
_Out_ PTP_ALPC *AlpcReturn,
_In_ HANDLE AlpcPort,
_In_ PTP_ALPC_CALLBACK Callback,
_Inout_opt_ PVOID Context,
_In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron
);
#if (PHNT_VERSION >= PHNT_WIN7)
// rev
NTSYSAPI
NTSTATUS
NTAPI
TpAllocAlpcCompletionEx(
_Out_ PTP_ALPC *AlpcReturn,
_In_ HANDLE AlpcPort,
_In_ PTP_ALPC_CALLBACK_EX Callback,
_Inout_opt_ PVOID Context,
_In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron
);
#endif
// private
NTSYSAPI
VOID
NTAPI
TpReleaseAlpcCompletion(
_Inout_ PTP_ALPC Alpc
);
// private
NTSYSAPI
VOID
NTAPI
TpWaitForAlpcCompletion(
_Inout_ PTP_ALPC Alpc
);
// private
typedef enum _TP_TRACE_TYPE
{
TpTraceThreadPriority = 1,
TpTraceThreadAffinity,
MaxTpTraceType
} TP_TRACE_TYPE;
// private
NTSYSAPI
VOID
NTAPI
TpCaptureCaller(
_In_ TP_TRACE_TYPE Type
);
// private
NTSYSAPI
VOID
NTAPI
TpCheckTerminateWorker(
_In_ HANDLE Thread
);
#endif
#endif

@ -0,0 +1,593 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTWOW64_H
#define _NTWOW64_H
#define WOW64_SYSTEM_DIRECTORY "SysWOW64"
#define WOW64_SYSTEM_DIRECTORY_U L"SysWOW64"
#define WOW64_X86_TAG " (x86)"
#define WOW64_X86_TAG_U L" (x86)"
// In USER_SHARED_DATA
typedef enum _WOW64_SHARED_INFORMATION
{
SharedNtdll32LdrInitializeThunk,
SharedNtdll32KiUserExceptionDispatcher,
SharedNtdll32KiUserApcDispatcher,
SharedNtdll32KiUserCallbackDispatcher,
SharedNtdll32ExpInterlockedPopEntrySListFault,
SharedNtdll32ExpInterlockedPopEntrySListResume,
SharedNtdll32ExpInterlockedPopEntrySListEnd,
SharedNtdll32RtlUserThreadStart,
SharedNtdll32pQueryProcessDebugInformationRemote,
SharedNtdll32BaseAddress,
SharedNtdll32LdrSystemDllInitBlock,
Wow64SharedPageEntriesCount
} WOW64_SHARED_INFORMATION;
// 32-bit definitions
#define WOW64_POINTER(Type) ULONG
typedef struct _RTL_BALANCED_NODE32
{
union
{
WOW64_POINTER(struct _RTL_BALANCED_NODE *) Children[2];
struct
{
WOW64_POINTER(struct _RTL_BALANCED_NODE *) Left;
WOW64_POINTER(struct _RTL_BALANCED_NODE *) Right;
};
};
union
{
WOW64_POINTER(UCHAR) Red : 1;
WOW64_POINTER(UCHAR) Balance : 2;
WOW64_POINTER(ULONG_PTR) ParentValue;
};
} RTL_BALANCED_NODE32, *PRTL_BALANCED_NODE32;
typedef struct _RTL_RB_TREE32
{
WOW64_POINTER(PRTL_BALANCED_NODE) Root;
WOW64_POINTER(PRTL_BALANCED_NODE) Min;
} RTL_RB_TREE32, *PRTL_RB_TREE32;
typedef struct _PEB_LDR_DATA32
{
ULONG Length;
BOOLEAN Initialized;
WOW64_POINTER(HANDLE) SsHandle;
LIST_ENTRY32 InLoadOrderModuleList;
LIST_ENTRY32 InMemoryOrderModuleList;
LIST_ENTRY32 InInitializationOrderModuleList;
WOW64_POINTER(PVOID) EntryInProgress;
BOOLEAN ShutdownInProgress;
WOW64_POINTER(HANDLE) ShutdownThreadId;
} PEB_LDR_DATA32, *PPEB_LDR_DATA32;
typedef struct _LDR_SERVICE_TAG_RECORD32
{
WOW64_POINTER(struct _LDR_SERVICE_TAG_RECORD *) Next;
ULONG ServiceTag;
} LDR_SERVICE_TAG_RECORD32, *PLDR_SERVICE_TAG_RECORD32;
typedef struct _LDRP_CSLIST32
{
WOW64_POINTER(PSINGLE_LIST_ENTRY) Tail;
} LDRP_CSLIST32, *PLDRP_CSLIST32;
typedef struct _LDR_DDAG_NODE32
{
LIST_ENTRY32 Modules;
WOW64_POINTER(PLDR_SERVICE_TAG_RECORD) ServiceTagList;
ULONG LoadCount;
ULONG LoadWhileUnloadingCount;
ULONG LowestLink;
union
{
LDRP_CSLIST32 Dependencies;
SINGLE_LIST_ENTRY32 RemovalLink;
};
LDRP_CSLIST32 IncomingDependencies;
LDR_DDAG_STATE State;
SINGLE_LIST_ENTRY32 CondenseLink;
ULONG PreorderNumber;
} LDR_DDAG_NODE32, *PLDR_DDAG_NODE32;
#define LDR_DATA_TABLE_ENTRY_SIZE_WINXP_32 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, DdagNode)
#define LDR_DATA_TABLE_ENTRY_SIZE_WIN7_32 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, BaseNameHashValue)
#define LDR_DATA_TABLE_ENTRY_SIZE_WIN8_32 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY32, ImplicitPathOptions)
typedef struct _LDR_DATA_TABLE_ENTRY32
{
LIST_ENTRY32 InLoadOrderLinks;
LIST_ENTRY32 InMemoryOrderLinks;
union
{
LIST_ENTRY32 InInitializationOrderLinks;
LIST_ENTRY32 InProgressLinks;
};
WOW64_POINTER(PVOID) DllBase;
WOW64_POINTER(PVOID) EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING32 FullDllName;
UNICODE_STRING32 BaseDllName;
union
{
UCHAR FlagGroup[4];
ULONG Flags;
struct
{
ULONG PackagedBinary : 1;
ULONG MarkedForRemoval : 1;
ULONG ImageDll : 1;
ULONG LoadNotificationsSent : 1;
ULONG TelemetryEntryProcessed : 1;
ULONG ProcessStaticImport : 1;
ULONG InLegacyLists : 1;
ULONG InIndexes : 1;
ULONG ShimDll : 1;
ULONG InExceptionTable : 1;
ULONG ReservedFlags1 : 2;
ULONG LoadInProgress : 1;
ULONG LoadConfigProcessed : 1;
ULONG EntryProcessed : 1;
ULONG ProtectDelayLoad : 1;
ULONG ReservedFlags3 : 2;
ULONG DontCallForThreads : 1;
ULONG ProcessAttachCalled : 1;
ULONG ProcessAttachFailed : 1;
ULONG CorDeferredValidate : 1;
ULONG CorImage : 1;
ULONG DontRelocate : 1;
ULONG CorILOnly : 1;
ULONG ChpeImage : 1;
ULONG ReservedFlags5 : 2;
ULONG Redirected : 1;
ULONG ReservedFlags6 : 2;
ULONG CompatDatabaseProcessed : 1;
};
};
USHORT ObsoleteLoadCount;
USHORT TlsIndex;
LIST_ENTRY32 HashLinks;
ULONG TimeDateStamp;
WOW64_POINTER(struct _ACTIVATION_CONTEXT *) EntryPointActivationContext;
WOW64_POINTER(PVOID) Lock;
WOW64_POINTER(PLDR_DDAG_NODE) DdagNode;
LIST_ENTRY32 NodeModuleLink;
WOW64_POINTER(struct _LDRP_LOAD_CONTEXT *) LoadContext;
WOW64_POINTER(PVOID) ParentDllBase;
WOW64_POINTER(PVOID) SwitchBackContext;
RTL_BALANCED_NODE32 BaseAddressIndexNode;
RTL_BALANCED_NODE32 MappingInfoIndexNode;
WOW64_POINTER(ULONG_PTR) OriginalBase;
LARGE_INTEGER LoadTime;
ULONG BaseNameHashValue;
LDR_DLL_LOAD_REASON LoadReason;
ULONG ImplicitPathOptions;
ULONG ReferenceCount;
ULONG DependentLoadFlags;
UCHAR SigningLevel; // since REDSTONE2
} LDR_DATA_TABLE_ENTRY32, *PLDR_DATA_TABLE_ENTRY32;
typedef struct _CURDIR32
{
UNICODE_STRING32 DosPath;
WOW64_POINTER(HANDLE) Handle;
} CURDIR32, *PCURDIR32;
typedef struct _RTL_DRIVE_LETTER_CURDIR32
{
USHORT Flags;
USHORT Length;
ULONG TimeStamp;
STRING32 DosPath;
} RTL_DRIVE_LETTER_CURDIR32, *PRTL_DRIVE_LETTER_CURDIR32;
typedef struct _RTL_USER_PROCESS_PARAMETERS32
{
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
WOW64_POINTER(HANDLE) ConsoleHandle;
ULONG ConsoleFlags;
WOW64_POINTER(HANDLE) StandardInput;
WOW64_POINTER(HANDLE) StandardOutput;
WOW64_POINTER(HANDLE) StandardError;
CURDIR32 CurrentDirectory;
UNICODE_STRING32 DllPath;
UNICODE_STRING32 ImagePathName;
UNICODE_STRING32 CommandLine;
WOW64_POINTER(PVOID) Environment;
ULONG StartingX;
ULONG StartingY;
ULONG CountX;
ULONG CountY;
ULONG CountCharsX;
ULONG CountCharsY;
ULONG FillAttribute;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING32 WindowTitle;
UNICODE_STRING32 DesktopInfo;
UNICODE_STRING32 ShellInfo;
UNICODE_STRING32 RuntimeData;
RTL_DRIVE_LETTER_CURDIR32 CurrentDirectories[RTL_MAX_DRIVE_LETTERS];
WOW64_POINTER(ULONG_PTR) EnvironmentSize;
WOW64_POINTER(ULONG_PTR) EnvironmentVersion;
WOW64_POINTER(PVOID) PackageDependencyData;
ULONG ProcessGroupId;
ULONG LoaderThreads;
UNICODE_STRING32 RedirectionDllName; // REDSTONE4
UNICODE_STRING32 HeapPartitionName; // 19H1
WOW64_POINTER(ULONG_PTR) DefaultThreadpoolCpuSetMasks;
ULONG DefaultThreadpoolCpuSetMaskCount;
} RTL_USER_PROCESS_PARAMETERS32, *PRTL_USER_PROCESS_PARAMETERS32;
typedef struct _PEB32
{
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
union
{
BOOLEAN BitField;
struct
{
BOOLEAN ImageUsesLargePages : 1;
BOOLEAN IsProtectedProcess : 1;
BOOLEAN IsImageDynamicallyRelocated : 1;
BOOLEAN SkipPatchingUser32Forwarders : 1;
BOOLEAN IsPackagedProcess : 1;
BOOLEAN IsAppContainer : 1;
BOOLEAN IsProtectedProcessLight : 1;
BOOLEAN IsLongPathAwareProcess : 1;
};
};
WOW64_POINTER(HANDLE) Mutant;
WOW64_POINTER(PVOID) ImageBaseAddress;
WOW64_POINTER(PPEB_LDR_DATA) Ldr;
WOW64_POINTER(PRTL_USER_PROCESS_PARAMETERS) ProcessParameters;
WOW64_POINTER(PVOID) SubSystemData;
WOW64_POINTER(PVOID) ProcessHeap;
WOW64_POINTER(PRTL_CRITICAL_SECTION) FastPebLock;
WOW64_POINTER(PVOID) AtlThunkSListPtr;
WOW64_POINTER(PVOID) IFEOKey;
union
{
ULONG CrossProcessFlags;
struct
{
ULONG ProcessInJob : 1;
ULONG ProcessInitializing : 1;
ULONG ProcessUsingVEH : 1;
ULONG ProcessUsingVCH : 1;
ULONG ProcessUsingFTH : 1;
ULONG ReservedBits0 : 27;
};
};
union
{
WOW64_POINTER(PVOID) KernelCallbackTable;
WOW64_POINTER(PVOID) UserSharedInfoPtr;
};
ULONG SystemReserved;
ULONG AtlThunkSListPtr32;
WOW64_POINTER(PVOID) ApiSetMap;
ULONG TlsExpansionCounter;
WOW64_POINTER(PVOID) TlsBitmap;
ULONG TlsBitmapBits[2];
WOW64_POINTER(PVOID) ReadOnlySharedMemoryBase;
WOW64_POINTER(PVOID) HotpatchInformation;
WOW64_POINTER(PVOID *) ReadOnlyStaticServerData;
WOW64_POINTER(PVOID) AnsiCodePageData;
WOW64_POINTER(PVOID) OemCodePageData;
WOW64_POINTER(PVOID) UnicodeCaseTableData;
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
LARGE_INTEGER CriticalSectionTimeout;
WOW64_POINTER(SIZE_T) HeapSegmentReserve;
WOW64_POINTER(SIZE_T) HeapSegmentCommit;
WOW64_POINTER(SIZE_T) HeapDeCommitTotalFreeThreshold;
WOW64_POINTER(SIZE_T) HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
WOW64_POINTER(PVOID *) ProcessHeaps;
WOW64_POINTER(PVOID) GdiSharedHandleTable;
WOW64_POINTER(PVOID) ProcessStarterHelper;
ULONG GdiDCAttributeList;
WOW64_POINTER(PRTL_CRITICAL_SECTION) LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
USHORT OSBuildNumber;
USHORT OSCSDVersion;
ULONG OSPlatformId;
ULONG ImageSubsystem;
ULONG ImageSubsystemMajorVersion;
ULONG ImageSubsystemMinorVersion;
WOW64_POINTER(ULONG_PTR) ActiveProcessAffinityMask;
GDI_HANDLE_BUFFER32 GdiHandleBuffer;
WOW64_POINTER(PVOID) PostProcessInitRoutine;
WOW64_POINTER(PVOID) TlsExpansionBitmap;
ULONG TlsExpansionBitmapBits[32];
ULONG SessionId;
ULARGE_INTEGER AppCompatFlags;
ULARGE_INTEGER AppCompatFlagsUser;
WOW64_POINTER(PVOID) pShimData;
WOW64_POINTER(PVOID) AppCompatInfo;
UNICODE_STRING32 CSDVersion;
WOW64_POINTER(PVOID) ActivationContextData;
WOW64_POINTER(PVOID) ProcessAssemblyStorageMap;
WOW64_POINTER(PVOID) SystemDefaultActivationContextData;
WOW64_POINTER(PVOID) SystemAssemblyStorageMap;
WOW64_POINTER(SIZE_T) MinimumStackCommit;
WOW64_POINTER(PVOID) SparePointers[4];
ULONG SpareUlongs[5];
//WOW64_POINTER(PVOID *) FlsCallback;
//LIST_ENTRY32 FlsListHead;
//WOW64_POINTER(PVOID) FlsBitmap;
//ULONG FlsBitmapBits[FLS_MAXIMUM_AVAILABLE / (sizeof(ULONG) * 8)];
//ULONG FlsHighIndex;
WOW64_POINTER(PVOID) WerRegistrationData;
WOW64_POINTER(PVOID) WerShipAssertPtr;
WOW64_POINTER(PVOID) pContextData;
WOW64_POINTER(PVOID) pImageHeaderHash;
union
{
ULONG TracingFlags;
struct
{
ULONG HeapTracingEnabled : 1;
ULONG CritSecTracingEnabled : 1;
ULONG LibLoaderTracingEnabled : 1;
ULONG SpareTracingBits : 29;
};
};
ULONGLONG CsrServerReadOnlySharedMemoryBase;
WOW64_POINTER(PVOID) TppWorkerpListLock;
LIST_ENTRY32 TppWorkerpList;
WOW64_POINTER(PVOID) WaitOnAddressHashTable[128];
WOW64_POINTER(PVOID) TelemetryCoverageHeader; // REDSTONE3
ULONG CloudFileFlags;
ULONG CloudFileDiagFlags; // REDSTONE4
CHAR PlaceholderCompatibilityMode;
CHAR PlaceholderCompatibilityModeReserved[7];
} PEB32, *PPEB32;
C_ASSERT(FIELD_OFFSET(PEB32, IFEOKey) == 0x024);
C_ASSERT(FIELD_OFFSET(PEB32, UnicodeCaseTableData) == 0x060);
C_ASSERT(FIELD_OFFSET(PEB32, SystemAssemblyStorageMap) == 0x204);
C_ASSERT(FIELD_OFFSET(PEB32, pImageHeaderHash) == 0x23c);
C_ASSERT(FIELD_OFFSET(PEB32, WaitOnAddressHashTable) == 0x25c);
//C_ASSERT(sizeof(PEB32) == 0x460); // REDSTONE3
C_ASSERT(sizeof(PEB32) == 0x470);
#define GDI_BATCH_BUFFER_SIZE 310
typedef struct _GDI_TEB_BATCH32
{
ULONG Offset;
WOW64_POINTER(ULONG_PTR) HDC;
ULONG Buffer[GDI_BATCH_BUFFER_SIZE];
} GDI_TEB_BATCH32, *PGDI_TEB_BATCH32;
typedef struct _TEB32
{
NT_TIB32 NtTib;
WOW64_POINTER(PVOID) EnvironmentPointer;
CLIENT_ID32 ClientId;
WOW64_POINTER(PVOID) ActiveRpcHandle;
WOW64_POINTER(PVOID) ThreadLocalStoragePointer;
WOW64_POINTER(PPEB) ProcessEnvironmentBlock;
ULONG LastErrorValue;
ULONG CountOfOwnedCriticalSections;
WOW64_POINTER(PVOID) CsrClientThread;
WOW64_POINTER(PVOID) Win32ThreadInfo;
ULONG User32Reserved[26];
ULONG UserReserved[5];
WOW64_POINTER(PVOID) WOW32Reserved;
LCID CurrentLocale;
ULONG FpSoftwareStatusRegister;
WOW64_POINTER(PVOID) ReservedForDebuggerInstrumentation[16];
WOW64_POINTER(PVOID) SystemReserved1[36];
UCHAR WorkingOnBehalfTicket[8];
NTSTATUS ExceptionCode;
WOW64_POINTER(PVOID) ActivationContextStackPointer;
WOW64_POINTER(ULONG_PTR) InstrumentationCallbackSp;
WOW64_POINTER(ULONG_PTR) InstrumentationCallbackPreviousPc;
WOW64_POINTER(ULONG_PTR) InstrumentationCallbackPreviousSp;
BOOLEAN InstrumentationCallbackDisabled;
UCHAR SpareBytes[23];
ULONG TxFsContext;
GDI_TEB_BATCH32 GdiTebBatch;
CLIENT_ID32 RealClientId;
WOW64_POINTER(HANDLE) GdiCachedProcessHandle;
ULONG GdiClientPID;
ULONG GdiClientTID;
WOW64_POINTER(PVOID) GdiThreadLocalInfo;
WOW64_POINTER(ULONG_PTR) Win32ClientInfo[62];
WOW64_POINTER(PVOID) glDispatchTable[233];
WOW64_POINTER(ULONG_PTR) glReserved1[29];
WOW64_POINTER(PVOID) glReserved2;
WOW64_POINTER(PVOID) glSectionInfo;
WOW64_POINTER(PVOID) glSection;
WOW64_POINTER(PVOID) glTable;
WOW64_POINTER(PVOID) glCurrentRC;
WOW64_POINTER(PVOID) glContext;
NTSTATUS LastStatusValue;
UNICODE_STRING32 StaticUnicodeString;
WCHAR StaticUnicodeBuffer[261];
WOW64_POINTER(PVOID) DeallocationStack;
WOW64_POINTER(PVOID) TlsSlots[64];
LIST_ENTRY32 TlsLinks;
WOW64_POINTER(PVOID) Vdm;
WOW64_POINTER(PVOID) ReservedForNtRpc;
WOW64_POINTER(PVOID) DbgSsReserved[2];
ULONG HardErrorMode;
WOW64_POINTER(PVOID) Instrumentation[9];
GUID ActivityId;
WOW64_POINTER(PVOID) SubProcessTag;
WOW64_POINTER(PVOID) PerflibData;
WOW64_POINTER(PVOID) EtwTraceData;
WOW64_POINTER(PVOID) WinSockData;
ULONG GdiBatchCount;
union
{
PROCESSOR_NUMBER CurrentIdealProcessor;
ULONG IdealProcessorValue;
struct
{
UCHAR ReservedPad0;
UCHAR ReservedPad1;
UCHAR ReservedPad2;
UCHAR IdealProcessor;
};
};
ULONG GuaranteedStackBytes;
WOW64_POINTER(PVOID) ReservedForPerf;
WOW64_POINTER(PVOID) ReservedForOle;
ULONG WaitingOnLoaderLock;
WOW64_POINTER(PVOID) SavedPriorityState;
WOW64_POINTER(ULONG_PTR) ReservedForCodeCoverage;
WOW64_POINTER(PVOID) ThreadPoolData;
WOW64_POINTER(PVOID *) TlsExpansionSlots;
ULONG MuiGeneration;
ULONG IsImpersonating;
WOW64_POINTER(PVOID) NlsCache;
WOW64_POINTER(PVOID) pShimData;
USHORT HeapVirtualAffinity;
USHORT LowFragHeapDataSlot;
WOW64_POINTER(HANDLE) CurrentTransactionHandle;
WOW64_POINTER(PTEB_ACTIVE_FRAME) ActiveFrame;
WOW64_POINTER(PVOID) FlsData;
WOW64_POINTER(PVOID) PreferredLanguages;
WOW64_POINTER(PVOID) UserPrefLanguages;
WOW64_POINTER(PVOID) MergedPrefLanguages;
ULONG MuiImpersonation;
union
{
USHORT CrossTebFlags;
USHORT SpareCrossTebBits : 16;
};
union
{
USHORT SameTebFlags;
struct
{
USHORT SafeThunkCall : 1;
USHORT InDebugPrint : 1;
USHORT HasFiberData : 1;
USHORT SkipThreadAttach : 1;
USHORT WerInShipAssertCode : 1;
USHORT RanProcessInit : 1;
USHORT ClonedThread : 1;
USHORT SuppressDebugMsg : 1;
USHORT DisableUserStackWalk : 1;
USHORT RtlExceptionAttached : 1;
USHORT InitialThread : 1;
USHORT SessionAware : 1;
USHORT LoadOwner : 1;
USHORT LoaderWorker : 1;
USHORT SpareSameTebBits : 2;
};
};
WOW64_POINTER(PVOID) TxnScopeEnterCallback;
WOW64_POINTER(PVOID) TxnScopeExitCallback;
WOW64_POINTER(PVOID) TxnScopeContext;
ULONG LockCount;
LONG WowTebOffset;
WOW64_POINTER(PVOID) ResourceRetValue;
WOW64_POINTER(PVOID) ReservedForWdf;
ULONGLONG ReservedForCrt;
GUID EffectiveContainerId;
} TEB32, *PTEB32;
C_ASSERT(FIELD_OFFSET(TEB32, ProcessEnvironmentBlock) == 0x030);
C_ASSERT(FIELD_OFFSET(TEB32, ExceptionCode) == 0x1a4);
C_ASSERT(FIELD_OFFSET(TEB32, TxFsContext) == 0x1d0);
C_ASSERT(FIELD_OFFSET(TEB32, glContext) == 0xbf0);
C_ASSERT(FIELD_OFFSET(TEB32, StaticUnicodeBuffer) == 0xc00);
C_ASSERT(FIELD_OFFSET(TEB32, TlsLinks) == 0xf10);
C_ASSERT(FIELD_OFFSET(TEB32, DbgSsReserved) == 0xf20);
C_ASSERT(FIELD_OFFSET(TEB32, ActivityId) == 0xf50);
C_ASSERT(FIELD_OFFSET(TEB32, GdiBatchCount) == 0xf70);
C_ASSERT(FIELD_OFFSET(TEB32, TlsExpansionSlots) == 0xf94);
C_ASSERT(FIELD_OFFSET(TEB32, FlsData) == 0xfb4);
C_ASSERT(FIELD_OFFSET(TEB32, MuiImpersonation) == 0xfc4);
C_ASSERT(FIELD_OFFSET(TEB32, ReservedForCrt) == 0xfe8);
C_ASSERT(FIELD_OFFSET(TEB32, EffectiveContainerId) == 0xff0);
C_ASSERT(sizeof(TEB32) == 0x1000);
// Conversion
FORCEINLINE VOID UStr32ToUStr(
_Out_ PUNICODE_STRING Destination,
_In_ PUNICODE_STRING32 Source
)
{
Destination->Length = Source->Length;
Destination->MaximumLength = Source->MaximumLength;
Destination->Buffer = (PWCH)UlongToPtr(Source->Buffer);
}
FORCEINLINE VOID UStrToUStr32(
_Out_ PUNICODE_STRING32 Destination,
_In_ PUNICODE_STRING Source
)
{
Destination->Length = Source->Length;
Destination->MaximumLength = Source->MaximumLength;
Destination->Buffer = PtrToUlong(Source->Buffer);
}
#endif

@ -0,0 +1,75 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _NTXCAPI_H
#define _NTXCAPI_H
NTSYSAPI
BOOLEAN
NTAPI
RtlDispatchException(
_In_ PEXCEPTION_RECORD ExceptionRecord,
_In_ PCONTEXT ContextRecord
);
NTSYSAPI
DECLSPEC_NORETURN
VOID
NTAPI
RtlRaiseStatus(
_In_ NTSTATUS Status
);
NTSYSAPI
VOID
NTAPI
RtlRaiseException(
_In_ PEXCEPTION_RECORD ExceptionRecord
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtContinue(
_In_ PCONTEXT ContextRecord,
_In_ BOOLEAN TestAlert
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtRaiseException(
_In_ PEXCEPTION_RECORD ExceptionRecord,
_In_ PCONTEXT ContextRecord,
_In_ BOOLEAN FirstChance
);
__analysis_noreturn
NTSYSCALLAPI
VOID
NTAPI
RtlAssert(
_In_ PVOID VoidFailedAssertion,
_In_ PVOID VoidFileName,
_In_ ULONG LineNumber,
_In_opt_ PSTR MutableMessage
);
#define RTL_ASSERT(exp) \
((!(exp)) ? (RtlAssert((PVOID)#exp, (PVOID)__FILE__, __LINE__, NULL), FALSE) : TRUE)
#define RTL_ASSERTMSG(msg, exp) \
((!(exp)) ? (RtlAssert((PVOID)#exp, (PVOID)__FILE__, __LINE__, msg), FALSE) : TRUE)
#define RTL_SOFT_ASSERT(_exp) \
((!(_exp)) ? (DbgPrint("%s(%d): Soft assertion failed\n Expression: %s\n", __FILE__, __LINE__, #_exp), FALSE) : TRUE)
#define RTL_SOFT_ASSERTMSG(_msg, _exp) \
((!(_exp)) ? (DbgPrint("%s(%d): Soft assertion failed\n Expression: %s\n Message: %s\n", __FILE__, __LINE__, #_exp, (_msg)), FALSE) : TRUE)
#endif

File diff suppressed because it is too large Load Diff

@ -0,0 +1,118 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _PHNT_H
#define _PHNT_H
// This header file provides access to NT APIs.
// Definitions are annotated to indicate their source. If a definition is not annotated, it has been
// retrieved from an official Microsoft source (NT headers, DDK headers, winnt.h).
// * "winbase" indicates that a definition has been reconstructed from a Win32-ized NT definition in
// winbase.h.
// * "rev" indicates that a definition has been reverse-engineered.
// * "dbg" indicates that a definition has been obtained from a debug message or assertion in a
// checked build of the kernel or file.
// Reliability:
// 1. No annotation.
// 2. dbg.
// 3. symbols, private. Types may be incorrect.
// 4. winbase. Names and types may be incorrect.
// 5. rev.
// Mode
#define PHNT_MODE_KERNEL 0
#define PHNT_MODE_USER 1
// Version
#define PHNT_WIN2K 50
#define PHNT_WINXP 51
#define PHNT_WS03 52
#define PHNT_VISTA 60
#define PHNT_WIN7 61
#define PHNT_WIN8 62
#define PHNT_WINBLUE 63
#define PHNT_THRESHOLD 100
#define PHNT_THRESHOLD2 101
#define PHNT_REDSTONE 102
#define PHNT_REDSTONE2 103
#define PHNT_REDSTONE3 104
#define PHNT_REDSTONE4 105
#define PHNT_REDSTONE5 106
#define PHNT_19H1 107
#define PHNT_19H2 108
#ifndef PHNT_MODE
#define PHNT_MODE PHNT_MODE_USER
#endif
#ifndef PHNT_VERSION
#define PHNT_VERSION PHNT_WIN7
#endif
// Options
//#define PHNT_NO_INLINE_INIT_STRING
#ifdef __cplusplus
extern "C" {
#endif
#if (PHNT_MODE != PHNT_MODE_KERNEL)
#include <phnt_ntdef.h>
#include <ntnls.h>
#include <ntkeapi.h>
#endif
#include <ntldr.h>
#include <ntexapi.h>
#include <ntmmapi.h>
#include <ntobapi.h>
#include <ntpsapi.h>
#if (PHNT_MODE != PHNT_MODE_KERNEL)
#include <cfg.h>
#include <ntdbg.h>
#include <ntioapi.h>
#include <ntlpcapi.h>
#include <ntpfapi.h>
#include <ntpnpapi.h>
#include <ntpoapi.h>
#include <ntregapi.h>
#include <ntrtl.h>
#endif
#if (PHNT_MODE != PHNT_MODE_KERNEL)
#include <ntseapi.h>
#include <nttmapi.h>
#include <nttp.h>
#include <ntxcapi.h>
#include <ntwow64.h>
#include <ntlsa.h>
#include <ntsam.h>
#include <ntmisc.h>
#include <ntzwapi.h>
#endif
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,319 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _PHNT_NTDEF_H
#define _PHNT_NTDEF_H
#ifndef _NTDEF_
#define _NTDEF_
// This header file provides basic NT types not included in Win32. If you have included winnt.h
// (perhaps indirectly), you must use this file instead of ntdef.h.
#ifndef NOTHING
#define NOTHING
#endif
// Basic types
typedef struct _QUAD
{
union
{
__int64 UseThisFieldToCopy;
double DoNotUseThisField;
};
} QUAD, *PQUAD;
// This isn't in NT, but it's useful.
typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _QUAD_PTR
{
ULONG_PTR DoNotUseThisField1;
ULONG_PTR DoNotUseThisField2;
} QUAD_PTR, *PQUAD_PTR;
typedef ULONG LOGICAL;
typedef ULONG *PLOGICAL;
typedef _Success_(return >= 0) LONG NTSTATUS;
typedef NTSTATUS *PNTSTATUS;
// Cardinal types
typedef char CCHAR;
typedef short CSHORT;
typedef ULONG CLONG;
typedef CCHAR *PCCHAR;
typedef CSHORT *PCSHORT;
typedef CLONG *PCLONG;
typedef PCSTR PCSZ;
// Specific
typedef UCHAR KIRQL, *PKIRQL;
typedef LONG KPRIORITY;
typedef USHORT RTL_ATOM, *PRTL_ATOM;
typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
// NT status macros
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define NT_INFORMATION(Status) ((((ULONG)(Status)) >> 30) == 1)
#define NT_WARNING(Status) ((((ULONG)(Status)) >> 30) == 2)
#define NT_ERROR(Status) ((((ULONG)(Status)) >> 30) == 3)
#define NT_FACILITY_MASK 0xfff
#define NT_FACILITY_SHIFT 16
#define NT_FACILITY(Status) ((((ULONG)(Status)) >> NT_FACILITY_SHIFT) & NT_FACILITY_MASK)
#define NT_NTWIN32(Status) (NT_FACILITY(Status) == FACILITY_NTWIN32)
#define WIN32_FROM_NTSTATUS(Status) (((ULONG)(Status)) & 0xffff)
// Functions
#ifndef _WIN64
#define FASTCALL __fastcall
#else
#define FASTCALL
#endif
// Synchronization enumerations
typedef enum _EVENT_TYPE
{
NotificationEvent,
SynchronizationEvent
} EVENT_TYPE;
typedef enum _TIMER_TYPE
{
NotificationTimer,
SynchronizationTimer
} TIMER_TYPE;
typedef enum _WAIT_TYPE
{
WaitAll,
WaitAny,
WaitNotification
} WAIT_TYPE;
// Strings
typedef struct _STRING
{
USHORT Length;
USHORT MaximumLength;
_Field_size_bytes_part_opt_(MaximumLength, Length) PCHAR Buffer;
} STRING, *PSTRING, ANSI_STRING, *PANSI_STRING, OEM_STRING, *POEM_STRING;
typedef const STRING *PCSTRING;
typedef const ANSI_STRING *PCANSI_STRING;
typedef const OEM_STRING *PCOEM_STRING;
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
_Field_size_bytes_part_(MaximumLength, Length) PWCH Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef const UNICODE_STRING *PCUNICODE_STRING;
#define RTL_CONSTANT_STRING(s) { sizeof(s) - sizeof((s)[0]), sizeof(s), s }
// Balanced tree node
#define RTL_BALANCED_NODE_RESERVED_PARENT_MASK 3
typedef struct _RTL_BALANCED_NODE
{
union
{
struct _RTL_BALANCED_NODE *Children[2];
struct
{
struct _RTL_BALANCED_NODE *Left;
struct _RTL_BALANCED_NODE *Right;
};
};
union
{
UCHAR Red : 1;
UCHAR Balance : 2;
ULONG_PTR ParentValue;
};
} RTL_BALANCED_NODE, *PRTL_BALANCED_NODE;
#define RTL_BALANCED_NODE_GET_PARENT_POINTER(Node) \
((PRTL_BALANCED_NODE)((Node)->ParentValue & ~RTL_BALANCED_NODE_RESERVED_PARENT_MASK))
// Portability
typedef struct _SINGLE_LIST_ENTRY32
{
ULONG Next;
} SINGLE_LIST_ENTRY32, *PSINGLE_LIST_ENTRY32;
typedef struct _STRING32
{
USHORT Length;
USHORT MaximumLength;
ULONG Buffer;
} STRING32, *PSTRING32;
typedef STRING32 UNICODE_STRING32, *PUNICODE_STRING32;
typedef STRING32 ANSI_STRING32, *PANSI_STRING32;
typedef struct _STRING64
{
USHORT Length;
USHORT MaximumLength;
ULONGLONG Buffer;
} STRING64, *PSTRING64;
typedef STRING64 UNICODE_STRING64, *PUNICODE_STRING64;
typedef STRING64 ANSI_STRING64, *PANSI_STRING64;
// Object attributes
#define OBJ_INHERIT 0x00000002
#define OBJ_PERMANENT 0x00000010
#define OBJ_EXCLUSIVE 0x00000020
#define OBJ_CASE_INSENSITIVE 0x00000040
#define OBJ_OPENIF 0x00000080
#define OBJ_OPENLINK 0x00000100
#define OBJ_KERNEL_HANDLE 0x00000200
#define OBJ_FORCE_ACCESS_CHECK 0x00000400
#define OBJ_IGNORE_IMPERSONATED_DEVICEMAP 0x00000800
#define OBJ_DONT_REPARSE 0x00001000
#define OBJ_VALID_ATTRIBUTES 0x00001ff2
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor; // PSECURITY_DESCRIPTOR;
PVOID SecurityQualityOfService; // PSECURITY_QUALITY_OF_SERVICE
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
typedef const OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES;
#define InitializeObjectAttributes(p, n, a, r, s) { \
(p)->Length = sizeof(OBJECT_ATTRIBUTES); \
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
(p)->SecurityDescriptor = s; \
(p)->SecurityQualityOfService = NULL; \
}
#define RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a) { sizeof(OBJECT_ATTRIBUTES), NULL, n, a, NULL, NULL }
#define RTL_INIT_OBJECT_ATTRIBUTES(n, a) RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a)
#define OBJ_NAME_PATH_SEPARATOR ((WCHAR)L'\\')
// Portability
typedef struct _OBJECT_ATTRIBUTES64
{
ULONG Length;
ULONG64 RootDirectory;
ULONG64 ObjectName;
ULONG Attributes;
ULONG64 SecurityDescriptor;
ULONG64 SecurityQualityOfService;
} OBJECT_ATTRIBUTES64, *POBJECT_ATTRIBUTES64;
typedef const OBJECT_ATTRIBUTES64 *PCOBJECT_ATTRIBUTES64;
typedef struct _OBJECT_ATTRIBUTES32
{
ULONG Length;
ULONG RootDirectory;
ULONG ObjectName;
ULONG Attributes;
ULONG SecurityDescriptor;
ULONG SecurityQualityOfService;
} OBJECT_ATTRIBUTES32, *POBJECT_ATTRIBUTES32;
typedef const OBJECT_ATTRIBUTES32 *PCOBJECT_ATTRIBUTES32;
// Product types
typedef enum _NT_PRODUCT_TYPE
{
NtProductWinNt = 1,
NtProductLanManNt,
NtProductServer
} NT_PRODUCT_TYPE, *PNT_PRODUCT_TYPE;
typedef enum _SUITE_TYPE
{
SmallBusiness,
Enterprise,
BackOffice,
CommunicationServer,
TerminalServer,
SmallBusinessRestricted,
EmbeddedNT,
DataCenter,
SingleUserTS,
Personal,
Blade,
EmbeddedRestricted,
SecurityAppliance,
StorageServer,
ComputeServer,
WHServer,
PhoneNT,
MaxSuiteType
} SUITE_TYPE;
// Specific
typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
typedef struct _CLIENT_ID32
{
ULONG UniqueProcess;
ULONG UniqueThread;
} CLIENT_ID32, *PCLIENT_ID32;
typedef struct _CLIENT_ID64
{
ULONGLONG UniqueProcess;
ULONGLONG UniqueThread;
} CLIENT_ID64, *PCLIENT_ID64;
#include <pshpack4.h>
typedef struct _KSYSTEM_TIME
{
ULONG LowPart;
LONG High1Time;
LONG High2Time;
} KSYSTEM_TIME, *PKSYSTEM_TIME;
#include <poppack.h>
#endif
#endif

@ -0,0 +1,83 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _PHNT_WINDOWS_H
#define _PHNT_WINDOWS_H
// This header file provides access to Win32, plus NTSTATUS values and some access mask values.
#ifndef CINTERFACE
#define CINTERFACE
#endif
#ifndef COBJMACROS
#define COBJMACROS
#endif
#ifndef INITGUID
#define INITGUID
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef WIN32_NO_STATUS
#define WIN32_NO_STATUS
#endif
#include <windows.h>
#include <windowsx.h>
#undef WIN32_NO_STATUS
#include <ntstatus.h>
#include <winioctl.h>
typedef double DOUBLE;
typedef GUID *PGUID;
// Desktop access rights
#define DESKTOP_ALL_ACCESS \
(DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE | \
DESKTOP_HOOKCONTROL | DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD | \
DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS | \
STANDARD_RIGHTS_REQUIRED)
#define DESKTOP_GENERIC_READ \
(DESKTOP_ENUMERATE | DESKTOP_READOBJECTS | STANDARD_RIGHTS_READ)
#define DESKTOP_GENERIC_WRITE \
(DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_HOOKCONTROL | \
DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD | DESKTOP_WRITEOBJECTS | \
STANDARD_RIGHTS_WRITE)
#define DESKTOP_GENERIC_EXECUTE \
(DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_EXECUTE)
// Window station access rights
#define WINSTA_GENERIC_READ \
(WINSTA_ENUMDESKTOPS | WINSTA_ENUMERATE | WINSTA_READATTRIBUTES | \
WINSTA_READSCREEN | STANDARD_RIGHTS_READ)
#define WINSTA_GENERIC_WRITE \
(WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | WINSTA_WRITEATTRIBUTES | \
STANDARD_RIGHTS_WRITE)
#define WINSTA_GENERIC_EXECUTE \
(WINSTA_ACCESSGLOBALATOMS | WINSTA_EXITWINDOWS | STANDARD_RIGHTS_EXECUTE)
// WMI access rights
#define WMIGUID_GENERIC_READ \
(WMIGUID_QUERY | WMIGUID_NOTIFICATION | WMIGUID_READ_DESCRIPTION | \
STANDARD_RIGHTS_READ)
#define WMIGUID_GENERIC_WRITE \
(WMIGUID_SET | TRACELOG_CREATE_REALTIME | TRACELOG_CREATE_ONDISK | \
STANDARD_RIGHTS_WRITE)
#define WMIGUID_GENERIC_EXECUTE \
(WMIGUID_EXECUTE | TRACELOG_GUID_ENABLE | TRACELOG_LOG_EVENT | \
TRACELOG_ACCESS_REALTIME | TRACELOG_REGISTER_GUIDS | \
STANDARD_RIGHTS_EXECUTE)
#endif

@ -0,0 +1,107 @@
/*
* This file is part of the Process Hacker project - https://processhacker.sourceforge.io/
*
* You can redistribute this file and/or modify it under the terms of the
* Attribution 4.0 International (CC BY 4.0) license.
*
* You must give appropriate credit, provide a link to the license, and
* indicate if changes were made. You may do so in any reasonable manner, but
* not in any way that suggests the licensor endorses you or your use.
*/
#ifndef _SUBPROCESSTAG_H
#define _SUBPROCESSTAG_H
// Subprocess tag information
typedef enum _TAG_INFO_LEVEL
{
eTagInfoLevelNameFromTag = 1, // TAG_INFO_NAME_FROM_TAG
eTagInfoLevelNamesReferencingModule, // TAG_INFO_NAMES_REFERENCING_MODULE
eTagInfoLevelNameTagMapping, // TAG_INFO_NAME_TAG_MAPPING
eTagInfoLevelMax
} TAG_INFO_LEVEL;
typedef enum _TAG_TYPE
{
eTagTypeService = 1,
eTagTypeMax
} TAG_TYPE;
typedef struct _TAG_INFO_NAME_FROM_TAG_IN_PARAMS
{
DWORD dwPid;
DWORD dwTag;
} TAG_INFO_NAME_FROM_TAG_IN_PARAMS, *PTAG_INFO_NAME_FROM_TAG_IN_PARAMS;
typedef struct _TAG_INFO_NAME_FROM_TAG_OUT_PARAMS
{
DWORD eTagType;
LPWSTR pszName;
} TAG_INFO_NAME_FROM_TAG_OUT_PARAMS, *PTAG_INFO_NAME_FROM_TAG_OUT_PARAMS;
typedef struct _TAG_INFO_NAME_FROM_TAG
{
TAG_INFO_NAME_FROM_TAG_IN_PARAMS InParams;
TAG_INFO_NAME_FROM_TAG_OUT_PARAMS OutParams;
} TAG_INFO_NAME_FROM_TAG, *PTAG_INFO_NAME_FROM_TAG;
typedef struct _TAG_INFO_NAMES_REFERENCING_MODULE_IN_PARAMS
{
DWORD dwPid;
LPWSTR pszModule;
} TAG_INFO_NAMES_REFERENCING_MODULE_IN_PARAMS, *PTAG_INFO_NAMES_REFERENCING_MODULE_IN_PARAMS;
typedef struct _TAG_INFO_NAMES_REFERENCING_MODULE_OUT_PARAMS
{
DWORD eTagType;
LPWSTR pmszNames;
} TAG_INFO_NAMES_REFERENCING_MODULE_OUT_PARAMS, *PTAG_INFO_NAMES_REFERENCING_MODULE_OUT_PARAMS;
typedef struct _TAG_INFO_NAMES_REFERENCING_MODULE
{
TAG_INFO_NAMES_REFERENCING_MODULE_IN_PARAMS InParams;
TAG_INFO_NAMES_REFERENCING_MODULE_OUT_PARAMS OutParams;
} TAG_INFO_NAMES_REFERENCING_MODULE, *PTAG_INFO_NAMES_REFERENCING_MODULE;
typedef struct _TAG_INFO_NAME_TAG_MAPPING_IN_PARAMS
{
DWORD dwPid;
} TAG_INFO_NAME_TAG_MAPPING_IN_PARAMS, *PTAG_INFO_NAME_TAG_MAPPING_IN_PARAMS;
typedef struct _TAG_INFO_NAME_TAG_MAPPING_ELEMENT
{
DWORD eTagType;
DWORD dwTag;
LPWSTR pszName;
LPWSTR pszGroupName;
} TAG_INFO_NAME_TAG_MAPPING_ELEMENT, *PTAG_INFO_NAME_TAG_MAPPING_ELEMENT;
typedef struct _TAG_INFO_NAME_TAG_MAPPING_OUT_PARAMS
{
DWORD cElements;
PTAG_INFO_NAME_TAG_MAPPING_ELEMENT pNameTagMappingElements;
} TAG_INFO_NAME_TAG_MAPPING_OUT_PARAMS, *PTAG_INFO_NAME_TAG_MAPPING_OUT_PARAMS;
typedef struct _TAG_INFO_NAME_TAG_MAPPING
{
TAG_INFO_NAME_TAG_MAPPING_IN_PARAMS InParams;
PTAG_INFO_NAME_TAG_MAPPING_OUT_PARAMS pOutParams;
} TAG_INFO_NAME_TAG_MAPPING, *PTAG_INFO_NAME_TAG_MAPPING;
_Must_inspect_result_
DWORD
WINAPI
I_QueryTagInformation(
_In_opt_ LPCWSTR pszMachineName,
_In_ TAG_INFO_LEVEL eInfoLevel,
_Inout_ PVOID pTagInfo
);
typedef DWORD (WINAPI *PQUERY_TAG_INFORMATION)(
_In_opt_ LPCWSTR pszMachineName,
_In_ TAG_INFO_LEVEL eInfoLevel,
_Inout_ PVOID pTagInfo
);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,748 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
//*********************************************************
#ifndef __WIL_COMMON_INCLUDED
#define __WIL_COMMON_INCLUDED
#if defined(_KERNEL_MODE ) && !defined(__WIL_MIN_KERNEL)
// This define indicates that the WIL usage is in a kernel mode context where
// a high degree of WIL functionality is desired.
//
// Use (sparingly) to change behavior based on whether WIL is being used in kernel
// mode or user mode.
#define WIL_KERNEL_MODE
#endif
// Defining WIL_HIDE_DEPRECATED will hide everything deprecated.
// Each wave of deprecation will add a new WIL_HIDE_DEPRECATED_YYMM number that can be used to lock deprecation at
// a particular point, allowing components to avoid backslide and catch up to the current independently.
#ifdef WIL_HIDE_DEPRECATED
#define WIL_HIDE_DEPRECATED_1809
#endif
#ifdef WIL_HIDE_DEPRECATED_1809
#define WIL_HIDE_DEPRECATED_1612
#endif
#ifdef WIL_HIDE_DEPRECATED_1612
#define WIL_HIDE_DEPRECATED_1611
#endif
// Implementation side note: ideally the deprecation would be done with the function-level declspec
// as it allows you to utter the error text when used. The declspec works, but doing it selectively with
// a macro makes intellisense deprecation comments not work. So we just use the #pragma deprecation.
#ifdef WIL_WARN_DEPRECATED
#define WIL_WARN_DEPRECATED_1809
#endif
#ifdef WIL_WARN_DEPRECATED_1809
#define WIL_WARN_DEPRECATED_1612
#endif
#ifdef WIL_WARN_DEPRECATED_1612
#define WIL_WARN_DEPRECATED_1611
#endif
#ifdef WIL_WARN_DEPRECATED_1809
#define WIL_WARN_DEPRECATED_1809_PRAGMA(...) __pragma(deprecated(__VA_ARGS__))
#else
#define WIL_WARN_DEPRECATED_1809_PRAGMA(...)
#endif
#ifdef WIL_WARN_DEPRECATED_1611
#define WIL_WARN_DEPRECATED_1611_PRAGMA(...) __pragma(deprecated(__VA_ARGS__))
#else
#define WIL_WARN_DEPRECATED_1611_PRAGMA(...)
#endif
#ifdef WIL_WARN_DEPRECATED_1612
#define WIL_WARN_DEPRECATED_1612_PRAGMA(...) __pragma(deprecated(__VA_ARGS__))
#else
#define WIL_WARN_DEPRECATED_1612_PRAGMA(...)
#endif
#if defined(_MSVC_LANG)
#define __WI_SUPPRESS_4127_S __pragma(warning(push)) __pragma(warning(disable:4127)) __pragma(warning(disable:26498)) __pragma(warning(disable:4245))
#define __WI_SUPPRESS_4127_E __pragma(warning(pop))
#define __WI_SUPPRESS_NULLPTR_ANALYSIS __pragma(warning(suppress:28285)) __pragma(warning(suppress:6504))
#define __WI_SUPPRESS_NONINIT_ANALYSIS __pragma(warning(suppress:26495))
#define __WI_SUPPRESS_NOEXCEPT_ANALYSIS __pragma(warning(suppress:26439))
#else
#define __WI_SUPPRESS_4127_S
#define __WI_SUPPRESS_4127_E
#define __WI_SUPPRESS_NULLPTR_ANALYSIS
#define __WI_SUPPRESS_NONINIT_ANALYSIS
#define __WI_SUPPRESS_NOEXCEPT_ANALYSIS
#endif
#include <sal.h>
// Some SAL remapping / decoration to better support Doxygen. Macros that look like function calls can
// confuse Doxygen when they are used to decorate a function or variable. We simplify some of these to
// basic macros without the function for common use cases.
/// @cond
#define _Success_return_ _Success_(return)
#define _Success_true_ _Success_(true)
#define __declspec_noinline_ __declspec(noinline)
#define __declspec_selectany_ __declspec(selectany)
/// @endcond
//! @defgroup macrobuilding Macro Composition
//! The following macros are building blocks primarily intended for authoring other macros.
//! @{
//! Re-state a macro value (indirection for composition)
#define WI_FLATTEN(...) __VA_ARGS__
/// @cond
#define __WI_PASTE_imp(a, b) a##b
/// @endcond
//! This macro is for use in other macros to paste two tokens together, such as a constant and the __LINE__ macro.
#define WI_PASTE(a, b) __WI_PASTE_imp(a, b)
/// @cond
#define __WI_HAS_VA_OPT_IMPL(F, T, ...) T
#define __WI_HAS_VA_OPT_(...) __WI_HAS_VA_OPT_IMPL(__VA_OPT__(0,) 1, 0)
/// @endcond
//! Evaluates to '1' when support for '__VA_OPT__' is available, else '0'
#define WI_HAS_VA_OPT __WI_HAS_VA_OPT_(unused)
/// @cond
#define __WI_ARGS_COUNT1(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24, A25, A26, A27, A28, A29, \
A30, A31, A32, A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, \
A60, A61, A62, A63, A64, A65, A66, A67, A68, A69, A70, A71, A72, A73, A74, A75, A76, A77, A78, A79, A80, A81, A82, A83, A84, A85, A86, A87, A88, A89, \
A90, A91, A92, A93, A94, A95, A96, A97, A98, A99, count, ...) count
#define __WI_ARGS_COUNT0(...) WI_FLATTEN(__WI_ARGS_COUNT1(__VA_ARGS__, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, \
79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \
39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
#define __WI_ARGS_COUNT_PREFIX(...) 0, __VA_ARGS__
/// @endcond
//! This variadic macro returns the number of arguments passed to it (up to 99).
#if WI_HAS_VA_OPT
#define WI_ARGS_COUNT(...) __WI_ARGS_COUNT0(0 __VA_OPT__(, __VA_ARGS__))
#else
#define WI_ARGS_COUNT(...) __WI_ARGS_COUNT0(__WI_ARGS_COUNT_PREFIX(__VA_ARGS__))
#endif
/// @cond
#define __WI_FOR_imp0( fn)
#define __WI_FOR_imp1( fn, arg) fn(arg)
#define __WI_FOR_imp2( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp1(fn, __VA_ARGS__))
#define __WI_FOR_imp3( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp2(fn, __VA_ARGS__))
#define __WI_FOR_imp4( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp3(fn, __VA_ARGS__))
#define __WI_FOR_imp5( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp4(fn, __VA_ARGS__))
#define __WI_FOR_imp6( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp5(fn, __VA_ARGS__))
#define __WI_FOR_imp7( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp6(fn, __VA_ARGS__))
#define __WI_FOR_imp8( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp7(fn, __VA_ARGS__))
#define __WI_FOR_imp9( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp8(fn, __VA_ARGS__))
#define __WI_FOR_imp10(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp9(fn, __VA_ARGS__))
#define __WI_FOR_imp11(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp10(fn, __VA_ARGS__))
#define __WI_FOR_imp12(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp11(fn, __VA_ARGS__))
#define __WI_FOR_imp13(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp12(fn, __VA_ARGS__))
#define __WI_FOR_imp14(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp13(fn, __VA_ARGS__))
#define __WI_FOR_imp15(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp14(fn, __VA_ARGS__))
#define __WI_FOR_imp16(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp15(fn, __VA_ARGS__))
#define __WI_FOR_imp17(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp16(fn, __VA_ARGS__))
#define __WI_FOR_imp18(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp17(fn, __VA_ARGS__))
#define __WI_FOR_imp19(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp18(fn, __VA_ARGS__))
#define __WI_FOR_imp20(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp19(fn, __VA_ARGS__))
#define __WI_FOR_imp21(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp20(fn, __VA_ARGS__))
#define __WI_FOR_imp22(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp21(fn, __VA_ARGS__))
#define __WI_FOR_imp23(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp22(fn, __VA_ARGS__))
#define __WI_FOR_imp24(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp23(fn, __VA_ARGS__))
#define __WI_FOR_imp25(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp24(fn, __VA_ARGS__))
#define __WI_FOR_imp26(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp25(fn, __VA_ARGS__))
#define __WI_FOR_imp27(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp26(fn, __VA_ARGS__))
#define __WI_FOR_imp28(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp27(fn, __VA_ARGS__))
#define __WI_FOR_imp29(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp28(fn, __VA_ARGS__))
#define __WI_FOR_imp30(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp29(fn, __VA_ARGS__))
#define __WI_FOR_imp31(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp30(fn, __VA_ARGS__))
#define __WI_FOR_imp32(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp31(fn, __VA_ARGS__))
#define __WI_FOR_imp33(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp32(fn, __VA_ARGS__))
#define __WI_FOR_imp34(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp33(fn, __VA_ARGS__))
#define __WI_FOR_imp35(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp34(fn, __VA_ARGS__))
#define __WI_FOR_imp36(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp35(fn, __VA_ARGS__))
#define __WI_FOR_imp37(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp36(fn, __VA_ARGS__))
#define __WI_FOR_imp38(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp37(fn, __VA_ARGS__))
#define __WI_FOR_imp39(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp38(fn, __VA_ARGS__))
#define __WI_FOR_imp40(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp39(fn, __VA_ARGS__))
#define __WI_FOR_imp41(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp40(fn, __VA_ARGS__))
#define __WI_FOR_imp42(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp41(fn, __VA_ARGS__))
#define __WI_FOR_imp43(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp42(fn, __VA_ARGS__))
#define __WI_FOR_imp44(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp43(fn, __VA_ARGS__))
#define __WI_FOR_imp45(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp44(fn, __VA_ARGS__))
#define __WI_FOR_imp46(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp45(fn, __VA_ARGS__))
#define __WI_FOR_imp47(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp46(fn, __VA_ARGS__))
#define __WI_FOR_imp48(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp47(fn, __VA_ARGS__))
#define __WI_FOR_imp49(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp48(fn, __VA_ARGS__))
#define __WI_FOR_imp50(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp49(fn, __VA_ARGS__))
#define __WI_FOR_imp51(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp50(fn, __VA_ARGS__))
#define __WI_FOR_imp52(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp51(fn, __VA_ARGS__))
#define __WI_FOR_imp53(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp52(fn, __VA_ARGS__))
#define __WI_FOR_imp54(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp53(fn, __VA_ARGS__))
#define __WI_FOR_imp55(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp54(fn, __VA_ARGS__))
#define __WI_FOR_imp56(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp55(fn, __VA_ARGS__))
#define __WI_FOR_imp57(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp56(fn, __VA_ARGS__))
#define __WI_FOR_imp58(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp57(fn, __VA_ARGS__))
#define __WI_FOR_imp59(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp58(fn, __VA_ARGS__))
#define __WI_FOR_imp60(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp59(fn, __VA_ARGS__))
#define __WI_FOR_imp61(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp60(fn, __VA_ARGS__))
#define __WI_FOR_imp62(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp61(fn, __VA_ARGS__))
#define __WI_FOR_imp63(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp62(fn, __VA_ARGS__))
#define __WI_FOR_imp64(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp63(fn, __VA_ARGS__))
#define __WI_FOR_imp65(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp64(fn, __VA_ARGS__))
#define __WI_FOR_imp66(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp65(fn, __VA_ARGS__))
#define __WI_FOR_imp67(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp66(fn, __VA_ARGS__))
#define __WI_FOR_imp68(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp67(fn, __VA_ARGS__))
#define __WI_FOR_imp69(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp68(fn, __VA_ARGS__))
#define __WI_FOR_imp70(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp69(fn, __VA_ARGS__))
#define __WI_FOR_imp71(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp70(fn, __VA_ARGS__))
#define __WI_FOR_imp72(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp71(fn, __VA_ARGS__))
#define __WI_FOR_imp73(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp72(fn, __VA_ARGS__))
#define __WI_FOR_imp74(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp73(fn, __VA_ARGS__))
#define __WI_FOR_imp75(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp74(fn, __VA_ARGS__))
#define __WI_FOR_imp76(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp75(fn, __VA_ARGS__))
#define __WI_FOR_imp77(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp76(fn, __VA_ARGS__))
#define __WI_FOR_imp78(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp77(fn, __VA_ARGS__))
#define __WI_FOR_imp79(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp78(fn, __VA_ARGS__))
#define __WI_FOR_imp80(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp79(fn, __VA_ARGS__))
#define __WI_FOR_imp81(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp80(fn, __VA_ARGS__))
#define __WI_FOR_imp82(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp81(fn, __VA_ARGS__))
#define __WI_FOR_imp83(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp82(fn, __VA_ARGS__))
#define __WI_FOR_imp84(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp83(fn, __VA_ARGS__))
#define __WI_FOR_imp85(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp84(fn, __VA_ARGS__))
#define __WI_FOR_imp86(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp85(fn, __VA_ARGS__))
#define __WI_FOR_imp87(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp86(fn, __VA_ARGS__))
#define __WI_FOR_imp88(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp87(fn, __VA_ARGS__))
#define __WI_FOR_imp89(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp88(fn, __VA_ARGS__))
#define __WI_FOR_imp90(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp89(fn, __VA_ARGS__))
#define __WI_FOR_imp91(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp90(fn, __VA_ARGS__))
#define __WI_FOR_imp92(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp91(fn, __VA_ARGS__))
#define __WI_FOR_imp93(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp92(fn, __VA_ARGS__))
#define __WI_FOR_imp94(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp93(fn, __VA_ARGS__))
#define __WI_FOR_imp95(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp94(fn, __VA_ARGS__))
#define __WI_FOR_imp96(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp95(fn, __VA_ARGS__))
#define __WI_FOR_imp97(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp96(fn, __VA_ARGS__))
#define __WI_FOR_imp98(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp97(fn, __VA_ARGS__))
#define __WI_FOR_imp99(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp98(fn, __VA_ARGS__))
#define __WI_FOR_imp(n, fnAndArgs) WI_PASTE(__WI_FOR_imp, n) fnAndArgs
/// @endcond
//! Iterates through each of the given arguments invoking the specified macro against each one.
#define WI_FOREACH(fn, ...) __WI_FOR_imp(WI_ARGS_COUNT(__VA_ARGS__), (fn, ##__VA_ARGS__))
//! Dispatches a single macro name to separate macros based on the number of arguments passed to it.
#define WI_MACRO_DISPATCH(name, ...) WI_PASTE(WI_PASTE(name, WI_ARGS_COUNT(__VA_ARGS__)), (__VA_ARGS__))
//! @} // Macro composition helpers
#if !defined(__cplusplus) || defined(__WIL_MIN_KERNEL)
#define WI_ODR_PRAGMA(NAME, TOKEN)
#define WI_NOEXCEPT
#else
#pragma warning(push)
#pragma warning(disable:4714) // __forceinline not honored
// DO NOT add *any* further includes to this file -- there should be no dependencies from its usage
#include "wistd_type_traits.h"
//! This macro inserts ODR violation protection; the macro allows it to be compatible with straight "C" code
#define WI_ODR_PRAGMA(NAME, TOKEN) __pragma(detect_mismatch("ODR_violation_" NAME "_mismatch", TOKEN))
#ifdef WIL_KERNEL_MODE
WI_ODR_PRAGMA("WIL_KERNEL_MODE", "1")
#else
WI_ODR_PRAGMA("WIL_KERNEL_MODE", "0")
#endif
#if defined(_CPPUNWIND) && !defined(WIL_SUPPRESS_EXCEPTIONS)
/** This define is automatically set when exceptions are enabled within wil.
It is automatically defined when your code is compiled with exceptions enabled (via checking for the built-in
_CPPUNWIND flag) unless you explicitly define WIL_SUPPRESS_EXCEPTIONS ahead of including your first wil
header. All exception-based WIL methods and classes are included behind:
~~~~
#ifdef WIL_ENABLE_EXCEPTIONS
// code
#endif
~~~~
This enables exception-free code to directly include WIL headers without worrying about exception-based
routines suddenly becoming available. */
#define WIL_ENABLE_EXCEPTIONS
#endif
/// @endcond
/// @cond
#if defined(WIL_EXCEPTION_MODE)
static_assert(WIL_EXCEPTION_MODE <= 2, "Invalid exception mode");
#elif !defined(WIL_LOCK_EXCEPTION_MODE)
#define WIL_EXCEPTION_MODE 0 // default, can link exception-based and non-exception based libraries together
#pragma detect_mismatch("ODR_violation_WIL_EXCEPTION_MODE_mismatch", "0")
#elif defined(WIL_ENABLE_EXCEPTIONS)
#define WIL_EXCEPTION_MODE 1 // new code optimization: ONLY support linking libraries together that have exceptions enabled
#pragma detect_mismatch("ODR_violation_WIL_EXCEPTION_MODE_mismatch", "1")
#else
#define WIL_EXCEPTION_MODE 2 // old code optimization: ONLY support linking libraries that are NOT using exceptions
#pragma detect_mismatch("ODR_violation_WIL_EXCEPTION_MODE_mismatch", "2")
#endif
#if WIL_EXCEPTION_MODE == 1 && !defined(WIL_ENABLE_EXCEPTIONS)
#error Must enable exceptions when WIL_EXCEPTION_MODE == 1
#endif
// block for documentation only
#if defined(WIL_DOXYGEN)
/** This define can be explicitly set to disable exception usage within wil.
Normally this define is never needed as the WIL_ENABLE_EXCEPTIONS macro is enabled automatically by looking
at _CPPUNWIND. If your code compiles with exceptions enabled, but does not want to enable the exception-based
classes and methods from WIL, define this macro ahead of including the first WIL header. */
#define WIL_SUPPRESS_EXCEPTIONS
/** This define can be explicitly set to lock the process exception mode to WIL_ENABLE_EXCEPTIONS.
Locking the exception mode provides optimizations to exception barriers, staging hooks and DLL load costs as it eliminates the need to
do copy-on-write initialization of various function pointers and the necessary indirection that's done within WIL to avoid ODR violations
when linking libraries together with different exception handling semantics. */
#define WIL_LOCK_EXCEPTION_MODE
/** This define explicit sets the exception mode for the process to control optimizations.
Three exception modes are available:
0) This is the default. This enables a binary to link both exception-based and non-exception based libraries together that
use WIL. This adds overhead to exception barriers, DLL copy on write pages and indirection through function pointers to avoid ODR
violations when linking libraries together with different exception handling semantics.
1) Prefer this setting when it can be used. This locks the binary to only supporting libraries which were built with exceptions enabled.
2) This locks the binary to libraries built without exceptions. */
#define WIL_EXCEPTION_MODE
#endif
#if (__cplusplus >= 201703) || (_MSVC_LANG >= 201703)
#define WIL_HAS_CXX_17 1
#else
#define WIL_HAS_CXX_17 0
#endif
// Until we'll have C++17 enabled in our code base, we're falling back to SAL
#define WI_NODISCARD __WI_LIBCPP_NODISCARD_ATTRIBUTE
#define __R_ENABLE_IF_IS_CLASS(ptrType) wistd::enable_if_t<wistd::is_class<ptrType>::value, void*> = (void*)0
#define __R_ENABLE_IF_IS_NOT_CLASS(ptrType) wistd::enable_if_t<!wistd::is_class<ptrType>::value, void*> = (void*)0
//! @defgroup bitwise Bitwise Inspection and Manipulation
//! Bitwise helpers to improve readability and reduce the error rate of bitwise operations.
//! Several macros have been constructed to assist with bitwise inspection and manipulation. These macros exist
//! for two primary purposes:
//!
//! 1. To improve the readability of bitwise comparisons and manipulation.
//!
//! The macro names are the more concise, readable form of what's being done and do not require that any flags
//! or variables be specified multiple times for the comparisons.
//!
//! 2. To reduce the error rate associated with bitwise operations.
//!
//! The readability improvements naturally lend themselves to this by cutting down the number of concepts.
//! Using `WI_IsFlagSet(var, MyEnum::Flag)` rather than `((var & MyEnum::Flag) == MyEnum::Flag)` removes the comparison
//! operator and repetition in the flag value.
//!
//! Additionally, these macros separate single flag operations (which tend to be the most common) from multi-flag
//! operations so that compile-time errors are generated for bitwise operations which are likely incorrect,
//! such as: `WI_IsFlagSet(var, MyEnum::None)` or `WI_IsFlagSet(var, MyEnum::ValidMask)`.
//!
//! Note that the single flag helpers should be used when a compile-time constant single flag is being manipulated. These
//! helpers provide compile-time errors on misuse and should be preferred over the multi-flag helpers. The multi-flag helpers
//! should be used when multiple flags are being used simultaneously or when the flag values are not compile-time constants.
//!
//! Common example usage (manipulation of flag variables):
//! ~~~~
//! WI_SetFlag(m_flags, MyFlags::Foo); // Set a single flag in the given variable
//! WI_SetAllFlags(m_flags, MyFlags::Foo | MyFlags::Bar); // Set one or more flags
//! WI_ClearFlagIf(m_flags, MyFlags::Bar, isBarClosed); // Conditionally clear a single flag based upon a bool
//! WI_ClearAllFlags(m_flags, MyFlags::Foo | MyFlags::Bar); // Clear one or more flags from the given variable
//! WI_ToggleFlag(m_flags, MyFlags::Foo); // Toggle (change to the opposite value) a single flag
//! WI_UpdateFlag(m_flags, MyFlags::Bar, isBarClosed); // Sets or Clears a single flag from the given variable based upon a bool value
//! WI_UpdateFlagsInMask(m_flags, flagsMask, newFlagValues); // Sets or Clears the flags in flagsMask to the masked values from newFlagValues
//! ~~~~
//! Common example usage (inspection of flag variables):
//! ~~~~
//! if (WI_IsFlagSet(m_flags, MyFlags::Foo)) // Is a single flag set in the given variable?
//! if (WI_IsAnyFlagSet(m_flags, MyFlags::Foo | MyFlags::Bar)) // Is at least one flag from the given mask set?
//! if (WI_AreAllFlagsClear(m_flags, MyFlags::Foo | MyFlags::Bar)) // Are all flags in the given list clear?
//! if (WI_IsSingleFlagSet(m_flags)) // Is *exactly* one flag set in the given variable?
//! ~~~~
//! @{
//! Returns the unsigned type of the same width and numeric value as the given enum
#define WI_EnumValue(val) static_cast<::wil::integral_from_enum<decltype(val)>>(val)
//! Validates that exactly ONE bit is set in compile-time constant `flag`
#define WI_StaticAssertSingleBitSet(flag) static_cast<decltype(flag)>(::wil::details::verify_single_flag_helper<static_cast<unsigned long long>(WI_EnumValue(flag))>::value)
//! @name Bitwise manipulation macros
//! @{
//! Set zero or more bitflags specified by `flags` in the variable `var`.
#define WI_SetAllFlags(var, flags) ((var) |= (flags))
//! Set a single compile-time constant `flag` in the variable `var`.
#define WI_SetFlag(var, flag) WI_SetAllFlags(var, WI_StaticAssertSingleBitSet(flag))
//! Conditionally sets a single compile-time constant `flag` in the variable `var` only if `condition` is true.
#define WI_SetFlagIf(var, flag, condition) do { if (wil::verify_bool(condition)) { WI_SetFlag(var, flag); } } while ((void)0, 0)
//! Clear zero or more bitflags specified by `flags` from the variable `var`.
#define WI_ClearAllFlags(var, flags) ((var) &= ~(flags))
//! Clear a single compile-time constant `flag` from the variable `var`.
#define WI_ClearFlag(var, flag) WI_ClearAllFlags(var, WI_StaticAssertSingleBitSet(flag))
//! Conditionally clear a single compile-time constant `flag` in the variable `var` only if `condition` is true.
#define WI_ClearFlagIf(var, flag, condition) do { if (wil::verify_bool(condition)) { WI_ClearFlag(var, flag); } } while ((void)0, 0)
//! Changes a single compile-time constant `flag` in the variable `var` to be set if `isFlagSet` is true or cleared if `isFlagSet` is false.
#define WI_UpdateFlag(var, flag, isFlagSet) (wil::verify_bool(isFlagSet) ? WI_SetFlag(var, flag) : WI_ClearFlag(var, flag))
//! Changes only the flags specified by `flagsMask` in the variable `var` to match the corresponding flags in `newFlags`.
#define WI_UpdateFlagsInMask(var, flagsMask, newFlags) wil::details::UpdateFlagsInMaskHelper(var, flagsMask, newFlags)
//! Toggles (XOR the value) of multiple bitflags specified by `flags` in the variable `var`.
#define WI_ToggleAllFlags(var, flags) ((var) ^= (flags))
//! Toggles (XOR the value) of a single compile-time constant `flag` in the variable `var`.
#define WI_ToggleFlag(var, flag) WI_ToggleAllFlags(var, WI_StaticAssertSingleBitSet(flag))
//! @} // bitwise manipulation macros
//! @name Bitwise inspection macros
//! @{
//! Evaluates as true if every bitflag specified in `flags` is set within `val`.
#define WI_AreAllFlagsSet(val, flags) wil::details::AreAllFlagsSetHelper(val, flags)
//! Evaluates as true if one or more bitflags specified in `flags` are set within `val`.
#define WI_IsAnyFlagSet(val, flags) (static_cast<decltype((val) & (flags))>(WI_EnumValue(val) & WI_EnumValue(flags)) != static_cast<decltype((val) & (flags))>(0))
//! Evaluates as true if a single compile-time constant `flag` is set within `val`.
#define WI_IsFlagSet(val, flag) WI_IsAnyFlagSet(val, WI_StaticAssertSingleBitSet(flag))
//! Evaluates as true if every bitflag specified in `flags` is clear within `val`.
#define WI_AreAllFlagsClear(val, flags) (static_cast<decltype((val) & (flags))>(WI_EnumValue(val) & WI_EnumValue(flags)) == static_cast<decltype((val) & (flags))>(0))
//! Evaluates as true if one or more bitflags specified in `flags` are clear within `val`.
#define WI_IsAnyFlagClear(val, flags) (!wil::details::AreAllFlagsSetHelper(val, flags))
//! Evaluates as true if a single compile-time constant `flag` is clear within `val`.
#define WI_IsFlagClear(val, flag) WI_AreAllFlagsClear(val, WI_StaticAssertSingleBitSet(flag))
//! Evaluates as true if exactly one bit (any bit) is set within `val`.
#define WI_IsSingleFlagSet(val) wil::details::IsSingleFlagSetHelper(val)
//! Evaluates as true if exactly one bit from within the specified `mask` is set within `val`.
#define WI_IsSingleFlagSetInMask(val, mask) wil::details::IsSingleFlagSetHelper((val) & (mask))
//! Evaluates as true if exactly one bit (any bit) is set within `val` or if there are no bits set within `val`.
#define WI_IsClearOrSingleFlagSet(val) wil::details::IsClearOrSingleFlagSetHelper(val)
//! Evaluates as true if exactly one bit from within the specified `mask` is set within `val` or if there are no bits from `mask` set within `val`.
#define WI_IsClearOrSingleFlagSetInMask(val, mask) wil::details::IsClearOrSingleFlagSetHelper((val) & (mask))
//! @}
#if defined(WIL_DOXYGEN)
/** This macro provides a C++ header with a guaranteed initialization function.
Normally, were a global object's constructor used for this purpose, the optimizer/linker might throw
the object away if it's unreferenced (which throws away the side-effects that the initialization function
was trying to achieve). Using this macro forces linker inclusion of a variable that's initialized by the
provided function to elide that optimization.
//!
This functionality is primarily provided as a building block for header-based libraries (such as WIL)
to be able to layer additional functionality into other libraries by their mere inclusion. Alternative models
of initialization should be used whenever they are available.
~~~~
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
WI_HEADER_INITITALIZATION_FUNCTION(InitializeDesktopFamilyApis, []
{
g_pfnGetModuleName = GetCurrentModuleName;
g_pfnFailFastInLoaderCallout = FailFastInLoaderCallout;
return 1;
});
#endif
~~~~
The above example is used within WIL to decide whether or not the library containing WIL is allowed to use
desktop APIs. Building this functionality as #IFDEFs within functions would create ODR violations, whereas
doing it with global function pointers and header initialization allows a runtime determination. */
#define WI_HEADER_INITITALIZATION_FUNCTION(name, fn)
#elif defined(_M_IX86)
#define WI_HEADER_INITITALIZATION_FUNCTION(name, fn) \
extern "C" { __declspec(selectany) unsigned char g_header_init_ ## name = static_cast<unsigned char>(fn()); } \
__pragma(comment(linker, "/INCLUDE:_g_header_init_" #name))
#elif defined(_M_IA64) || defined(_M_AMD64) || defined(_M_ARM) || defined(_M_ARM64)
#define WI_HEADER_INITITALIZATION_FUNCTION(name, fn) \
extern "C" { __declspec(selectany) unsigned char g_header_init_ ## name = static_cast<unsigned char>(fn()); } \
__pragma(comment(linker, "/INCLUDE:g_header_init_" #name))
#else
#error linker pragma must include g_header_init variation
#endif
/** All Windows Implementation Library classes and functions are located within the "wil" namespace.
The 'wil' namespace is an intentionally short name as the intent is for code to be able to reference
the namespace directly (example: `wil::srwlock lock;`) without a using statement. Resist adding a using
statement for wil to avoid introducing potential name collisions between wil and other namespaces. */
namespace wil
{
/// @cond
namespace details
{
template <typename T>
class pointer_range
{
public:
pointer_range(T begin_, T end_) : m_begin(begin_), m_end(end_) {}
T begin() const { return m_begin; }
T end() const { return m_end; }
private:
T m_begin;
T m_end;
};
}
/// @endcond
/** Enables using range-based for between a begin and end object pointer.
~~~~
for (auto& obj : make_range(objPointerBegin, objPointerEnd)) { }
~~~~ */
template <typename T>
details::pointer_range<T> make_range(T begin, T end)
{
return details::pointer_range<T>(begin, end);
}
/** Enables using range-based for on a range when given the base pointer and the number of objects in the range.
~~~~
for (auto& obj : make_range(objPointer, objCount)) { }
~~~~ */
template <typename T>
details::pointer_range<T> make_range(T begin, size_t count)
{
return details::pointer_range<T>(begin, begin + count);
}
//! @defgroup outparam Output Parameters
//! Improve the conciseness of assigning values to optional output parameters.
//! @{
/** Assign the given value to an optional output parameter.
Makes code more concise by removing trivial `if (outParam)` blocks. */
template <typename T>
inline void assign_to_opt_param(_Out_opt_ T *outParam, T val)
{
if (outParam != nullptr)
{
*outParam = val;
}
}
/** Assign NULL to an optional output pointer parameter.
Makes code more concise by removing trivial `if (outParam)` blocks. */
template <typename T>
inline void assign_null_to_opt_param(_Out_opt_ T *outParam)
{
if (outParam != nullptr)
{
*outParam = nullptr;
}
}
//! @} // end output parameter helpers
/** Performs a logical or of the given variadic template parameters allowing indirect compile-time boolean evaluation.
Example usage:
~~~~
template <unsigned int... Rest>
struct FeatureRequiredBy
{
static const bool enabled = wil::variadic_logical_or<WilFeature<Rest>::enabled...>::value;
};
~~~~ */
template <bool...> struct variadic_logical_or;
/// @cond
template <> struct variadic_logical_or<> : wistd::false_type { };
template <bool... Rest> struct variadic_logical_or<true, Rest...> : wistd::true_type { };
template <bool... Rest> struct variadic_logical_or<false, Rest...> : variadic_logical_or<Rest...>::type { };
/// @endcond
/// @cond
namespace details
{
template <unsigned long long flag>
struct verify_single_flag_helper
{
static_assert((flag != 0) && ((flag & (flag - 1)) == 0), "Single flag expected, zero or multiple flags found");
static const unsigned long long value = flag;
};
}
/// @endcond
//! @defgroup typesafety Type Validation
//! Helpers to validate variable types to prevent accidental, but allowed type conversions.
//! These helpers are most useful when building macros that accept a particular type. Putting these functions around the types accepted
//! prior to pushing that type through to a function (or using it within the macro) allows the macro to add an additional layer of type
//! safety that would ordinarily be stripped away by C++ implicit conversions. This system is extensively used in the error handling helper
//! macros to validate the types given to various macro parameters.
//! @{
/** Verify that `val` can be evaluated as a logical bool.
Other types will generate an intentional compilation error. Allowed types for a logical bool are bool, BOOL,
boolean, BOOLEAN, and classes with an explicit bool cast.
@param val The logical bool expression
@return A C++ bool representing the evaluation of `val`. */
template <typename T, __R_ENABLE_IF_IS_CLASS(T)>
_Post_satisfies_(return == static_cast<bool>(val))
__forceinline constexpr bool verify_bool(const T& val)
{
return static_cast<bool>(val);
}
template <typename T, __R_ENABLE_IF_IS_NOT_CLASS(T)>
__forceinline constexpr bool verify_bool(T /*val*/)
{
static_assert(!wistd::is_same<T, T>::value, "Wrong Type: bool/BOOL/BOOLEAN/boolean expected");
return false;
}
template <>
_Post_satisfies_(return == val)
__forceinline constexpr bool verify_bool<bool>(bool val)
{
return val;
}
template <>
_Post_satisfies_(return == (val != 0))
__forceinline constexpr bool verify_bool<int>(int val)
{
return (val != 0);
}
template <>
_Post_satisfies_(return == !!val)
__forceinline constexpr bool verify_bool<unsigned char>(unsigned char val)
{
return !!val;
}
/** Verify that `val` is a Win32 BOOL value.
Other types (including other logical bool expressions) will generate an intentional compilation error. Note that this will
accept any `int` value as long as that is the underlying typedef behind `BOOL`.
@param val The Win32 BOOL returning expression
@return A Win32 BOOL representing the evaluation of `val`. */
template <typename T>
_Post_satisfies_(return == val)
__forceinline constexpr int verify_BOOL(T val)
{
// Note: Written in terms of 'int' as BOOL is actually: typedef int BOOL;
static_assert((wistd::is_same<T, int>::value), "Wrong Type: BOOL expected");
return val;
}
/** Verify that `hr` is an HRESULT value.
Other types will generate an intentional compilation error. Note that this will accept any `long` value as that is the
underlying typedef behind HRESULT.
//!
Note that occasionally you might run into an HRESULT which is directly defined with a #define, such as:
~~~~
#define UIA_E_NOTSUPPORTED 0x80040204
~~~~
Though this looks like an `HRESULT`, this is actually an `unsigned long` (the hex specification forces this). When
these are encountered and they are NOT in the public SDK (have not yet shipped to the public), then you should change
their definition to match the manner in which `HRESULT` constants are defined in winerror.h:
~~~~
#define E_NOTIMPL _HRESULT_TYPEDEF_(0x80004001L)
~~~~
When these are encountered in the public SDK, their type should not be changed and you should use a static_cast
to use this value in a macro that utilizes `verify_hresult`, for example:
~~~~
RETURN_HR_IF(static_cast<HRESULT>(UIA_E_NOTSUPPORTED), (patternId != UIA_DragPatternId));
~~~~
@param val The HRESULT returning expression
@return An HRESULT representing the evaluation of `val`. */
template <typename T>
_Post_satisfies_(return == hr)
inline constexpr long verify_hresult(T hr)
{
// Note: Written in terms of 'int' as HRESULT is actually: typedef _Return_type_success_(return >= 0) long HRESULT
static_assert(wistd::is_same<T, long>::value, "Wrong Type: HRESULT expected");
return hr;
}
/// @} // end type validation routines
/// @cond
// Implementation details for macros and helper functions... do not use directly.
namespace details
{
// Use size-specific casts to avoid sign extending numbers -- avoid warning C4310: cast truncates constant value
#define __WI_MAKE_UNSIGNED(val) \
(__pragma(warning(push)) __pragma(warning(disable: 4310 4309)) (sizeof(val) == 1 ? static_cast<unsigned char>(val) : \
sizeof(val) == 2 ? static_cast<unsigned short>(val) : \
sizeof(val) == 4 ? static_cast<unsigned long>(val) : \
static_cast<unsigned long long>(val)) __pragma(warning(pop)))
#define __WI_IS_UNSIGNED_SINGLE_FLAG_SET(val) ((val) && !((val) & ((val) - 1)))
#define __WI_IS_SINGLE_FLAG_SET(val) __WI_IS_UNSIGNED_SINGLE_FLAG_SET(__WI_MAKE_UNSIGNED(val))
template <typename TVal, typename TFlags>
__forceinline constexpr bool AreAllFlagsSetHelper(TVal val, TFlags flags)
{
return ((val & flags) == static_cast<decltype(val & flags)>(flags));
}
template <typename TVal>
__forceinline constexpr bool IsSingleFlagSetHelper(TVal val)
{
return __WI_IS_SINGLE_FLAG_SET(val);
}
template <typename TVal>
__forceinline constexpr bool IsClearOrSingleFlagSetHelper(TVal val)
{
return ((val == static_cast<wistd::remove_reference_t<TVal>>(0)) || IsSingleFlagSetHelper(val));
}
template <typename TVal, typename TMask, typename TFlags>
__forceinline constexpr void UpdateFlagsInMaskHelper(_Inout_ TVal& val, TMask mask, TFlags flags)
{
val = static_cast<wistd::remove_reference_t<TVal>>((val & ~mask) | (flags & mask));
}
template <long>
struct variable_size;
template <>
struct variable_size<1>
{
typedef unsigned char type;
};
template <>
struct variable_size<2>
{
typedef unsigned short type;
};
template <>
struct variable_size<4>
{
typedef unsigned long type;
};
template <>
struct variable_size<8>
{
typedef unsigned long long type;
};
template <typename T>
struct variable_size_mapping
{
typedef typename variable_size<sizeof(T)>::type type;
};
} // details
/// @endcond
/** Defines the unsigned type of the same width (1, 2, 4, or 8 bytes) as the given type.
This allows code to generically convert any enum class to it's corresponding underlying type. */
template <typename T>
using integral_from_enum = typename details::variable_size_mapping<T>::type;
} // wil
#pragma warning(pop)
#endif // __cplusplus
#endif // __WIL_COMMON_INCLUDED

@ -0,0 +1,272 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
//*********************************************************
#ifndef __WIL_CPPWINRT_INCLUDED
#define __WIL_CPPWINRT_INCLUDED
#include "common.h"
#include <windows.h>
#include <unknwn.h>
#include <inspectable.h>
#include <hstring.h>
// WIL and C++/WinRT use two different exception types for communicating HRESULT failures. Thus, both libraries need to
// understand how to translate these exception types into the correct HRESULT values at the ABI boundary. Prior to
// C++/WinRT "2.0" this was accomplished by injecting the WINRT_EXTERNAL_CATCH_CLAUSE macro - that WIL defines below -
// into its exception handler (winrt::to_hresult). Starting with C++/WinRT "2.0" this mechanism has shifted to a global
// function pointer - winrt_to_hresult_handler - that WIL sets automatically when this header is included and
// 'CPPWINRT_SUPPRESS_STATIC_INITIALIZERS' is not defined.
/// @cond
namespace wil::details
{
// Since the C++/WinRT version macro is a string...
inline constexpr int major_version_from_string(const char* versionString)
{
int result = 0;
auto str = versionString;
while ((*str >= '0') && (*str <= '9'))
{
result = result * 10 + (*str - '0');
++str;
}
return result;
}
}
/// @endcond
#ifdef CPPWINRT_VERSION
// Prior to C++/WinRT "2.0" this header needed to be included before 'winrt/base.h' so that our definition of
// 'WINRT_EXTERNAL_CATCH_CLAUSE' would get picked up in the implementation of 'winrt::to_hresult'. This is no longer
// problematic, so only emit an error when using a version of C++/WinRT prior to 2.0
static_assert(::wil::details::major_version_from_string(CPPWINRT_VERSION) >= 2,
"Please include wil/cppwinrt.h before including any C++/WinRT headers");
#endif
// NOTE: Will eventually be removed once C++/WinRT 2.0 use can be assumed
#ifdef WINRT_EXTERNAL_CATCH_CLAUSE
#define __WI_CONFLICTING_WINRT_EXTERNAL_CATCH_CLAUSE 1
#else
#define WINRT_EXTERNAL_CATCH_CLAUSE \
catch (const wil::ResultException& e) \
{ \
return winrt::hresult_error(e.GetErrorCode(), winrt::to_hstring(e.what())).to_abi(); \
}
#endif
#include "result_macros.h"
#include <winrt/base.h>
#if __WI_CONFLICTING_WINRT_EXTERNAL_CATCH_CLAUSE
static_assert(::wil::details::major_version_from_string(CPPWINRT_VERSION) >= 2,
"C++/WinRT external catch clause already defined outside of WIL");
#endif
// In C++/WinRT 2.0 and beyond, this function pointer exists. In earlier versions it does not. It's much easier to avoid
// linker errors than it is to SFINAE on variable existence, so we declare the variable here, but are careful not to
// use it unless the version of C++/WinRT is high enough
extern std::int32_t(__stdcall* winrt_to_hresult_handler)(void*) noexcept;
/// @cond
namespace wil::details
{
inline void MaybeGetExceptionString(
const winrt::hresult_error& exception,
_Out_writes_opt_(debugStringChars) PWSTR debugString,
_When_(debugString != nullptr, _Pre_satisfies_(debugStringChars > 0)) size_t debugStringChars)
{
if (debugString)
{
StringCchPrintfW(debugString, debugStringChars, L"winrt::hresult_error: %ls", exception.message().c_str());
}
}
inline HRESULT __stdcall ResultFromCaughtException_CppWinRt(
_Inout_updates_opt_(debugStringChars) PWSTR debugString,
_When_(debugString != nullptr, _Pre_satisfies_(debugStringChars > 0)) size_t debugStringChars,
_Inout_ bool* isNormalized) noexcept
{
if (g_pfnResultFromCaughtException)
{
try
{
throw;
}
catch (const ResultException& exception)
{
*isNormalized = true;
MaybeGetExceptionString(exception, debugString, debugStringChars);
return exception.GetErrorCode();
}
catch (const winrt::hresult_error& exception)
{
MaybeGetExceptionString(exception, debugString, debugStringChars);
return exception.to_abi();
}
catch (const std::bad_alloc& exception)
{
MaybeGetExceptionString(exception, debugString, debugStringChars);
return E_OUTOFMEMORY;
}
catch (const std::out_of_range& exception)
{
MaybeGetExceptionString(exception, debugString, debugStringChars);
return E_BOUNDS;
}
catch (const std::invalid_argument& exception)
{
MaybeGetExceptionString(exception, debugString, debugStringChars);
return E_INVALIDARG;
}
catch (...)
{
auto hr = RecognizeCaughtExceptionFromCallback(debugString, debugStringChars);
if (FAILED(hr))
{
return hr;
}
}
}
else
{
try
{
throw;
}
catch (const ResultException& exception)
{
*isNormalized = true;
MaybeGetExceptionString(exception, debugString, debugStringChars);
return exception.GetErrorCode();
}
catch (const winrt::hresult_error& exception)
{
MaybeGetExceptionString(exception, debugString, debugStringChars);
return exception.to_abi();
}
catch (const std::bad_alloc& exception)
{
MaybeGetExceptionString(exception, debugString, debugStringChars);
return E_OUTOFMEMORY;
}
catch (const std::out_of_range& exception)
{
MaybeGetExceptionString(exception, debugString, debugStringChars);
return E_BOUNDS;
}
catch (const std::invalid_argument& exception)
{
MaybeGetExceptionString(exception, debugString, debugStringChars);
return E_INVALIDARG;
}
catch (const std::exception& exception)
{
MaybeGetExceptionString(exception, debugString, debugStringChars);
return HRESULT_FROM_WIN32(ERROR_UNHANDLED_EXCEPTION);
}
catch (...)
{
// Fall through to returning 'S_OK' below
}
}
// Tell the caller that we were unable to map the exception by succeeding...
return S_OK;
}
}
/// @endcond
namespace wil
{
inline std::int32_t __stdcall winrt_to_hresult(void* returnAddress) noexcept
{
// C++/WinRT only gives us the return address (caller), so pass along an empty 'DiagnosticsInfo' since we don't
// have accurate file/line/etc. information
return static_cast<std::int32_t>(details::ReportFailure_CaughtException<FailureType::Return>(__R_DIAGNOSTICS_RA(DiagnosticsInfo{}, returnAddress)));
}
inline void WilInitialize_CppWinRT()
{
details::g_pfnResultFromCaughtException_CppWinRt = details::ResultFromCaughtException_CppWinRt;
if constexpr (details::major_version_from_string(CPPWINRT_VERSION) >= 2)
{
WI_ASSERT(winrt_to_hresult_handler == nullptr);
winrt_to_hresult_handler = winrt_to_hresult;
}
}
/// @cond
namespace details
{
#ifndef CPPWINRT_SUPPRESS_STATIC_INITIALIZERS
WI_ODR_PRAGMA("CPPWINRT_SUPPRESS_STATIC_INITIALIZERS", "0")
WI_HEADER_INITITALIZATION_FUNCTION(WilInitialize_CppWinRT, []
{
::wil::WilInitialize_CppWinRT();
return 1;
});
#else
WI_ODR_PRAGMA("CPPWINRT_SUPPRESS_STATIC_INITIALIZERS", "1")
#endif
}
/// @endcond
// Provides an overload of verify_hresult so that the WIL macros can recognize winrt::hresult as a valid "hresult" type.
inline long verify_hresult(winrt::hresult hr) noexcept
{
return hr;
}
// Provides versions of get_abi and put_abi for genericity that directly use HSTRING for convenience.
template <typename T>
auto get_abi(T const& object) noexcept
{
return winrt::get_abi(object);
}
inline auto get_abi(winrt::hstring const& object) noexcept
{
return static_cast<HSTRING>(winrt::get_abi(object));
}
template <typename T>
auto put_abi(T& object) noexcept
{
return winrt::put_abi(object);
}
inline auto put_abi(winrt::hstring& object) noexcept
{
return reinterpret_cast<HSTRING*>(winrt::put_abi(object));
}
inline ::IUnknown* com_raw_ptr(const winrt::Windows::Foundation::IUnknown& ptr) noexcept
{
return static_cast<::IUnknown*>(winrt::get_abi(ptr));
}
// Needed to power wil::cx_object_from_abi that requires IInspectable
inline ::IInspectable* com_raw_ptr(const winrt::Windows::Foundation::IInspectable& ptr) noexcept
{
return static_cast<::IInspectable*>(winrt::get_abi(ptr));
}
// Taken from the docs.microsoft.com article
template <typename T>
T convert_from_abi(::IUnknown* from)
{
T to{ nullptr }; // `T` is a projected type.
winrt::check_hresult(from->QueryInterface(winrt::guid_of<T>(), winrt::put_abi(to)));
return to;
}
}
#endif // __WIL_CPPWINRT_INCLUDED

File diff suppressed because it is too large Load Diff

@ -0,0 +1,277 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
//*********************************************************
#ifndef __WIL_REGISTRY_INCLUDED
#define __WIL_REGISTRY_INCLUDED
#ifdef _KERNEL_MODE
#error This header is not supported in kernel-mode.
#endif
#include <winreg.h>
#include <new.h> // new(std::nothrow)
#include "resource.h" // unique_hkey
namespace wil
{
//! The key name includes the absolute path of the key in the registry, always starting at a
//! base key, for example, HKEY_LOCAL_MACHINE.
size_t const max_registry_key_name_length = 255;
//! The maximum number of characters allowed in a registry value's name.
size_t const max_registry_value_name_length = 16383;
// unique_registry_watcher/unique_registry_watcher_nothrow/unique_registry_watcher_failfast
// These classes make it easy to execute a provided function when a
// registry key changes (optionally recursively). Specify the key
// either as a root key + path, or an open registry handle as wil::unique_hkey
// or a raw HKEY value (that will be duplicated).
//
// Example use with exceptions base error handling:
// auto watcher = wil::make_registry_watcher(HKEY_CURRENT_USER, L"Software\\MyApp", true, wil::RegistryChangeKind changeKind[]
// {
// if (changeKind == RegistryChangeKind::Delete)
// {
// watcher.reset();
// }
// // invalidate cached registry data here
// });
//
// Example use with error code base error handling:
// auto watcher = wil::make_registry_watcher_nothrow(HKEY_CURRENT_USER, L"Software\\MyApp", true, wil::RegistryChangeKind[]
// {
// // invalidate cached registry data here
// });
// RETURN_IF_NULL_ALLOC(watcher);
enum class RegistryChangeKind
{
Modify = 0,
Delete = 1,
};
/// @cond
namespace details
{
struct registry_watcher_state
{
registry_watcher_state(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
: m_callback(wistd::move(callback)), m_keyToWatch(wistd::move(keyToWatch)), m_isRecursive(isRecursive)
{
}
wistd::function<void(RegistryChangeKind)> m_callback;
unique_hkey m_keyToWatch;
unique_event_nothrow m_eventHandle;
// While not strictly needed since this is ref counted the thread pool wait
// should be last to ensure that the other members are valid
// when it is destructed as it will reference them.
unique_threadpool_wait m_threadPoolWait;
bool m_isRecursive;
volatile long m_refCount = 1;
srwlock m_lock;
// Returns true if the refcount can be increased from a non zero value,
// false it was zero impling that the object is in or on the way to the destructor.
// In this case ReleaseFromCallback() should not be called.
bool TryAddRef()
{
return ::InterlockedIncrement(&m_refCount) > 1;
}
void Release()
{
auto lock = m_lock.lock_exclusive();
if (0 == ::InterlockedDecrement(&m_refCount))
{
lock.reset(); // leave the lock before deleting it.
delete this;
}
}
void ReleaseFromCallback(bool rearm)
{
auto lock = m_lock.lock_exclusive();
if (0 == ::InterlockedDecrement(&m_refCount))
{
// Destroy the thread pool wait now to avoid the wait that would occur in the
// destructor. That wait would cause a deadlock since we are doing this from the callback.
::CloseThreadpoolWait(m_threadPoolWait.release());
lock.reset(); // leave the lock before deleting it.
delete this;
// Sleep(1); // Enable for testing to find use after free bugs.
}
else if (rearm)
{
::SetThreadpoolWait(m_threadPoolWait.get(), m_eventHandle.get(), nullptr);
}
}
};
inline void delete_registry_watcher_state(_In_opt_ registry_watcher_state *watcherStorage) { watcherStorage->Release(); }
typedef resource_policy<registry_watcher_state *, decltype(&details::delete_registry_watcher_state),
details::delete_registry_watcher_state, details::pointer_access_none> registry_watcher_state_resource_policy;
}
/// @endcond
template <typename storage_t, typename err_policy = err_exception_policy>
class registry_watcher_t : public storage_t
{
public:
// forward all base class constructors...
template <typename... args_t>
explicit registry_watcher_t(args_t&&... args) WI_NOEXCEPT : storage_t(wistd::forward<args_t>(args)...) {}
// HRESULT or void error handling...
typedef typename err_policy::result result;
// Exception-based constructors
registry_watcher_t(HKEY rootKey, _In_ PCWSTR subKey, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
{
static_assert(wistd::is_same<void, result>::value, "this constructor requires exceptions; use the create method");
create(rootKey, subKey, isRecursive, wistd::move(callback));
}
registry_watcher_t(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
{
static_assert(wistd::is_same<void, result>::value, "this constructor requires exceptions; use the create method");
create(wistd::move(keyToWatch), isRecursive, wistd::move(callback));
}
// Pass a root key, sub key pair or use an empty string to use rootKey as the key to watch.
result create(HKEY rootKey, _In_ PCWSTR subKey, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
{
// Most use will want to create the key, consider adding an option for open as a future design change.
unique_hkey keyToWatch;
HRESULT hr = HRESULT_FROM_WIN32(RegCreateKeyExW(rootKey, subKey, 0, nullptr, 0, KEY_NOTIFY, nullptr, &keyToWatch, nullptr));
if (FAILED(hr))
{
return err_policy::HResult(hr);
}
return err_policy::HResult(create_common(wistd::move(keyToWatch), isRecursive, wistd::move(callback)));
}
result create(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
{
return err_policy::HResult(create_common(wistd::move(keyToWatch), isRecursive, wistd::move(callback)));
}
private:
// Factored into a standalone function to support Clang which does not support conversion of stateless lambdas
// to __stdcall
static void __stdcall callback(PTP_CALLBACK_INSTANCE, void *context, TP_WAIT *, TP_WAIT_RESULT)
{
#ifndef __WIL_REGISTRY_CHANGE_CALLBACK_TEST
#define __WIL_REGISTRY_CHANGE_CALLBACK_TEST
#endif
__WIL_REGISTRY_CHANGE_CALLBACK_TEST
auto watcherState = static_cast<details::registry_watcher_state *>(context);
if (watcherState->TryAddRef())
{
// using auto reset event so don't need to manually reset.
// failure here is a programming error.
const LSTATUS error = RegNotifyChangeKeyValue(watcherState->m_keyToWatch.get(), watcherState->m_isRecursive,
REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_THREAD_AGNOSTIC,
watcherState->m_eventHandle.get(), TRUE);
// Call the client before re-arming to ensure that multiple callbacks don't
// run concurrently.
switch (error)
{
case ERROR_SUCCESS:
case ERROR_ACCESS_DENIED:
// Normal modification: send RegistryChangeKind::Modify and re-arm.
watcherState->m_callback(RegistryChangeKind::Modify);
watcherState->ReleaseFromCallback(true);
break;
case ERROR_KEY_DELETED:
// Key deleted, send RegistryChangeKind::Delete, do not re-arm.
watcherState->m_callback(RegistryChangeKind::Delete);
watcherState->ReleaseFromCallback(false);
break;
case ERROR_HANDLE_REVOKED:
// Handle revoked. This can occur if the user session ends before
// the watcher shuts-down. Disarm silently since there is generally no way to respond.
watcherState->ReleaseFromCallback(false);
break;
default:
FAIL_FAST_HR(HRESULT_FROM_WIN32(error));
}
}
}
// This function exists to avoid template expansion of this code based on err_policy.
HRESULT create_common(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
{
wistd::unique_ptr<details::registry_watcher_state> watcherState(new(std::nothrow) details::registry_watcher_state(
wistd::move(keyToWatch), isRecursive, wistd::move(callback)));
RETURN_IF_NULL_ALLOC(watcherState);
RETURN_IF_FAILED(watcherState->m_eventHandle.create());
RETURN_IF_WIN32_ERROR(RegNotifyChangeKeyValue(watcherState->m_keyToWatch.get(),
watcherState->m_isRecursive, REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_THREAD_AGNOSTIC,
watcherState->m_eventHandle.get(), TRUE));
watcherState->m_threadPoolWait.reset(CreateThreadpoolWait(&registry_watcher_t::callback, watcherState.get(), nullptr));
RETURN_LAST_ERROR_IF(!watcherState->m_threadPoolWait);
storage_t::reset(watcherState.release()); // no more failures after this, pass ownership
SetThreadpoolWait(storage_t::get()->m_threadPoolWait.get(), storage_t::get()->m_eventHandle.get(), nullptr);
return S_OK;
}
};
typedef unique_any_t<registry_watcher_t<details::unique_storage<details::registry_watcher_state_resource_policy>, err_returncode_policy>> unique_registry_watcher_nothrow;
typedef unique_any_t<registry_watcher_t<details::unique_storage<details::registry_watcher_state_resource_policy>, err_failfast_policy>> unique_registry_watcher_failfast;
inline unique_registry_watcher_nothrow make_registry_watcher_nothrow(HKEY rootKey, _In_ PCWSTR subKey, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback) WI_NOEXCEPT
{
unique_registry_watcher_nothrow watcher;
watcher.create(rootKey, subKey, isRecursive, wistd::move(callback));
return watcher; // caller must test for success using if (watcher)
}
inline unique_registry_watcher_nothrow make_registry_watcher_nothrow(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback) WI_NOEXCEPT
{
unique_registry_watcher_nothrow watcher;
watcher.create(wistd::move(keyToWatch), isRecursive, wistd::move(callback));
return watcher; // caller must test for success using if (watcher)
}
inline unique_registry_watcher_failfast make_registry_watcher_failfast(HKEY rootKey, _In_ PCWSTR subKey, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
{
return unique_registry_watcher_failfast(rootKey, subKey, isRecursive, wistd::move(callback));
}
inline unique_registry_watcher_failfast make_registry_watcher_failfast(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
{
return unique_registry_watcher_failfast(wistd::move(keyToWatch), isRecursive, wistd::move(callback));
}
#ifdef WIL_ENABLE_EXCEPTIONS
typedef unique_any_t<registry_watcher_t<details::unique_storage<details::registry_watcher_state_resource_policy>, err_exception_policy >> unique_registry_watcher;
inline unique_registry_watcher make_registry_watcher(HKEY rootKey, _In_ PCWSTR subKey, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
{
return unique_registry_watcher(rootKey, subKey, isRecursive, wistd::move(callback));
}
inline unique_registry_watcher make_registry_watcher(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
{
return unique_registry_watcher(wistd::move(keyToWatch), isRecursive, wistd::move(callback));
}
#endif // WIL_ENABLE_EXCEPTIONS
} // namespace wil
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,125 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
//*********************************************************
// Note: When origination is enabled by including this file, origination is done as part of the RETURN_* and THROW_* macros. Before originating
// a new error we will observe whether there is already an error payload associated with the current thread. If there is, and the HRESULTs match,
// then a new error will not be originated. Otherwise we will overwrite it with a new origination. The ABI boundary for WinRT APIs will check the
// per-thread error information. The act of checking the error clears it, so there should be minimal risk of failing to originate distinct errors
// simply because the HRESULTs match.
//
// For THROW_ macros we will examine the thread-local error storage once per throw. So typically once, with additional calls if the exception is
// caught and re-thrown.
//
// For RETURN_ macros we will have to examine the thread-local error storage once per frame as the call stack unwinds. Because error conditions
// -should- be uncommon the performance impact of checking TLS should be minimal. The more expensive part is originating the error because it must
// capture the entire stack and some additional data.
#ifndef __WIL_RESULT_ORIGINATE_INCLUDED
#define __WIL_RESULT_ORIGINATE_INCLUDED
#include "result.h"
#include <OleAuto.h> // RestrictedErrorInfo uses BSTRs :(
#include "resource.h"
#include "com.h"
#include <roerrorapi.h>
namespace wil
{
namespace details
{
// Note: The name must begin with "Raise" so that the !analyze auto-bucketing will ignore this stack frame. Otherwise this line of code gets all the blame.
inline void __stdcall RaiseRoOriginateOnWilExceptions(wil::FailureInfo const& failure) WI_NOEXCEPT
{
if ((failure.type == FailureType::Return) || (failure.type == FailureType::Exception))
{
bool shouldOriginate = true;
wil::com_ptr_nothrow<IRestrictedErrorInfo> restrictedErrorInformation;
if (GetRestrictedErrorInfo(&restrictedErrorInformation) == S_OK)
{
// This thread already has an error origination payload. Don't originate again if it has the same HRESULT that we are
// observing right now.
wil::unique_bstr descriptionUnused;
HRESULT existingHr = failure.hr;
wil::unique_bstr restrictedDescriptionUnused;
wil::unique_bstr capabilitySidUnused;
if (SUCCEEDED(restrictedErrorInformation->GetErrorDetails(&descriptionUnused, &existingHr, &restrictedDescriptionUnused, &capabilitySidUnused)))
{
shouldOriginate = (failure.hr != existingHr);
}
}
if (shouldOriginate)
{
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
wil::unique_hmodule errorModule;
if (GetModuleHandleExW(0, L"api-ms-win-core-winrt-error-l1-1-1.dll", &errorModule))
{
auto pfn = reinterpret_cast<decltype(&::RoOriginateError)>(GetProcAddress(errorModule.get(), "RoOriginateError"));
if (pfn != nullptr)
{
pfn(failure.hr, nullptr);
}
}
#else // DESKTOP | SYSTEM
::RoOriginateError(failure.hr, nullptr);
#endif // DESKTOP | SYSTEM
}
else if (restrictedErrorInformation)
{
// GetRestrictedErrorInfo returns ownership of the error information. If we aren't originating, and an error was already present,
// then we need to restore the error information for later observation.
SetRestrictedErrorInfo(restrictedErrorInformation.get());
}
}
}
// This method will check for the presence of stowed exception data on the current thread. If such data exists, and the HRESULT
// matches the current failure, then we will call RoFailFastWithErrorContext. RoFailFastWithErrorContext in this situation will
// result in -VASTLY- improved crash bucketing. It is hard to express just how much better. In other cases we just return and
// the calling method fails fast the same way it always has.
inline void __stdcall FailfastWithContextCallback(wil::FailureInfo const& failure) WI_NOEXCEPT
{
wil::com_ptr_nothrow<IRestrictedErrorInfo> restrictedErrorInformation;
if (GetRestrictedErrorInfo(&restrictedErrorInformation) == S_OK)
{
wil::unique_bstr descriptionUnused;
HRESULT existingHr = failure.hr;
wil::unique_bstr restrictedDescriptionUnused;
wil::unique_bstr capabilitySidUnused;
if (SUCCEEDED(restrictedErrorInformation->GetErrorDetails(&descriptionUnused, &existingHr, &restrictedDescriptionUnused, &capabilitySidUnused)) &&
(existingHr == failure.hr))
{
// GetRestrictedErrorInfo returns ownership of the error information. We want it to be available for RoFailFastWithErrorContext
// so we must restore it via SetRestrictedErrorInfo first.
SetRestrictedErrorInfo(restrictedErrorInformation.get());
RoFailFastWithErrorContext(existingHr);
}
else
{
// The error didn't match the current failure. Put it back in thread-local storage even though we aren't failing fast
// in this method, so it is available in the debugger just-in-case.
SetRestrictedErrorInfo(restrictedErrorInformation.get());
}
}
}
} // namespace details
} // namespace wil
// Automatically call RoOriginateError upon error origination by including this file
WI_HEADER_INITITALIZATION_FUNCTION(ResultStowedExceptionInitialize, []
{
::wil::SetOriginateErrorCallback(::wil::details::RaiseRoOriginateOnWilExceptions);
::wil::SetFailfastWithContextCallback(::wil::details::FailfastWithContextCallback);
return 1;
});
#endif // __WIL_RESULT_ORIGINATE_INCLUDED

@ -0,0 +1,206 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
//*********************************************************
#ifndef __WIL_RPC_HELPERS_INCLUDED
#define __WIL_RPC_HELPERS_INCLUDED
#include "result.h"
#include "resource.h"
#include "wistd_functional.h"
#include "wistd_type_traits.h"
namespace wil
{
/// @cond
namespace details
{
// This call-adapter template converts a void-returning 'wistd::invoke' into
// an HRESULT-returning 'wistd::invoke' that emits S_OK. It can be eliminated
// with 'if constexpr' when C++17 is in wide use.
template<typename TReturnType> struct call_adapter
{
template<typename... TArgs> static HRESULT call(TArgs&& ... args)
{
return wistd::invoke(wistd::forward<TArgs>(args)...);
}
};
template<> struct call_adapter<void>
{
template<typename... TArgs> static HRESULT call(TArgs&& ... args)
{
wistd::invoke(wistd::forward<TArgs>(args)...);
return S_OK;
}
};
// Some RPC exceptions are already HRESULTs. Others are in the regular Win32
// error space. If the incoming exception code isn't an HRESULT, wrap it.
constexpr HRESULT map_rpc_exception(DWORD code)
{
return IS_ERROR(code) ? code : __HRESULT_FROM_WIN32(code);
}
}
/// @endcond
/** Invokes an RPC method, mapping structured exceptions to HRESULTs
Failures encountered by the RPC infrastructure (such as server crashes, authentication
errors, client parameter issues, etc.) are emitted by raising a structured exception from
within the RPC machinery. This method wraps the requested call in the usual RpcTryExcept,
RpcTryCatch, and RpcEndExcept sequence then maps the exceptions to HRESULTs for the usual
flow control machinery to use.
Many RPC methods are defined as returning HRESULT themselves, where the HRESULT indicates
the result of the _work_. HRESULTs returned by a successful completion of the _call_ are
returned as-is.
RPC methods that have a return type of 'void' are mapped to returning S_OK when the _call_
completes successfully.
For example, consider an RPC interface method defined in idl as:
~~~
HRESULT GetKittenState([in, ref, string] const wchar_t* name, [out, retval] KittenState** state);
~~~
To call this method, use:
~~~
wil::unique_rpc_binding binding = // typically gotten elsewhere;
wil::unique_midl_ptr<KittenState> state;
HRESULT hr = wil::invoke_rpc_nothrow(GetKittenState, binding.get(), L"fluffy", state.put());
RETURN_IF_FAILED(hr);
~~~
*/
template<typename... TCall> HRESULT invoke_rpc_nothrow(TCall&&... args) WI_NOEXCEPT
{
RpcTryExcept
{
// Note: this helper type can be removed with C++17 enabled via
// 'if constexpr(wistd::is_same_v<void, result_t>)'
using result_t = typename wistd::__invoke_of<TCall...>::type;
RETURN_IF_FAILED(details::call_adapter<result_t>::call(wistd::forward<TCall>(args)...));
return S_OK;
}
RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
{
RETURN_HR(details::map_rpc_exception(RpcExceptionCode()));
}
RpcEndExcept
}
/** Invokes an RPC method, mapping structured exceptions to HRESULTs
Failures encountered by the RPC infrastructure (such as server crashes, authentication
errors, client parameter issues, etc.) are emitted by raising a structured exception from
within the RPC machinery. This method wraps the requested call in the usual RpcTryExcept,
RpcTryCatch, and RpcEndExcept sequence then maps the exceptions to HRESULTs for the usual
flow control machinery to use.
Some RPC methods return results (such as a state enumeration or other value) directly in
their signature. This adapter writes that result into a caller-provided object then
returns S_OK.
For example, consider an RPC interface method defined in idl as:
~~~
GUID GetKittenId([in, ref, string] const wchar_t* name);
~~~
To call this method, use:
~~~
wil::unique_rpc_binding binding = // typically gotten elsewhere;
GUID id;
HRESULT hr = wil::invoke_rpc_result_nothrow(id, GetKittenId, binding.get(), L"fluffy");
RETURN_IF_FAILED(hr);
~~~
*/
template<typename TResult, typename... TCall> HRESULT invoke_rpc_result_nothrow(TResult& result, TCall&&... args) WI_NOEXCEPT
{
RpcTryExcept
{
result = wistd::invoke(wistd::forward<TCall>(args)...);
return S_OK;
}
RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
{
RETURN_HR(details::map_rpc_exception(RpcExceptionCode()));
}
RpcEndExcept
}
namespace details
{
// Provides an adapter around calling the context-handle-close method on an
// RPC interface, which itself is an RPC call.
template<typename TStorage, typename close_fn_t, close_fn_t close_fn>
struct rpc_closer_t
{
static void Close(TStorage arg) WI_NOEXCEPT
{
LOG_IF_FAILED(invoke_rpc_nothrow(close_fn, &arg));
}
};
}
/** Manages explicit RPC context handles
Explicit RPC context handles are used in many RPC interfaces. Most interfaces with
context handles have an explicit `FooClose([in, out] CONTEXT*)` method that lets
the server close out the context handle. As the close method itself is an RPC call,
it can fail and raise a structured exception.
This type routes the context-handle-specific `Close` call through the `invoke_rpc_nothrow`
helper, ensuring correct cleanup and lifecycle management.
~~~
// Assume the interface has two methods:
// HRESULT OpenFoo([in] handle_t binding, [out] FOO_CONTEXT*);
// HRESULT UseFoo([in] FOO_CONTEXT context;
// void CloseFoo([in, out] PFOO_CONTEXT);
using unique_foo_context = wil::unique_rpc_context_handle<FOO_CONTEXT, decltype(&CloseFoo), CloseFoo>;
unique_foo_context context;
RETURN_IF_FAILED(wil::invoke_rpc_nothrow(OpenFoo, m_binding.get(), context.put()));
RETURN_IF_FAILED(wil::invoke_rpc_nothrow(UseFoo, context.get()));
context.reset();
~~~
*/
template<typename TContext, typename close_fn_t, close_fn_t close_fn>
using unique_rpc_context_handle = unique_any<TContext, decltype(&details::rpc_closer_t<TContext, close_fn_t, close_fn>::Close), details::rpc_closer_t<TContext, close_fn_t, close_fn>::Close>;
#ifdef WIL_ENABLE_EXCEPTIONS
/** Invokes an RPC method, mapping structured exceptions to C++ exceptions
See `wil::invoke_rpc_nothrow` for additional information. Failures during the _call_
and those returned by the _method_ are mapped to HRESULTs and thrown inside a
wil::ResultException. Using the example RPC method provided above:
~~~
wil::unique_midl_ptr<KittenState> state;
wil::invoke_rpc(GetKittenState, binding.get(), L"fluffy", state.put());
// use 'state'
~~~
*/
template<typename... TCall> void invoke_rpc(TCall&& ... args)
{
THROW_IF_FAILED(invoke_rpc_nothrow(wistd::forward<TCall>(args)...));
}
/** Invokes an RPC method, mapping structured exceptions to C++ exceptions
See `wil::invoke_rpc_result_nothrow` for additional information. Failures during the
_call_ are mapped to HRESULTs and thrown inside a `wil::ResultException`. Using the
example RPC method provided above:
~~~
GUID id = wil::invoke_rpc_result(GetKittenId, binding.get());
// use 'id'
~~~
*/
template<typename... TCall> auto invoke_rpc_result(TCall&& ... args)
{
using result_t = typename wistd::__invoke_of<TCall...>::type;
result_t result{};
THROW_IF_FAILED(invoke_rpc_result_nothrow(result, wistd::forward<TCall>(args)...));
return result;
}
#endif
}
#endif

@ -0,0 +1,369 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
//*********************************************************
#ifndef __WIL_SAFECAST_INCLUDED
#define __WIL_SAFECAST_INCLUDED
#include "result_macros.h"
#include <intsafe.h>
#include "wistd_config.h"
#include "wistd_type_traits.h"
namespace wil
{
namespace details
{
// Default error case for undefined conversions in intsafe.h
template<typename OldT, typename NewT> constexpr wistd::nullptr_t intsafe_conversion = nullptr;
// is_known_safe_static_cast_v determines if a conversion is known to be safe or not. Known
// safe conversions can be handled by static_cast, this includes conversions between the same
// type, when the new type is larger than the old type but is not a signed to unsigned
// conversion, and when the two types are the same size and signed/unsigned. All other
// conversions will be assumed to be potentially unsafe, and the conversion must be handled
// by intsafe and checked.
template <typename NewT, typename OldT>
constexpr bool is_known_safe_static_cast_v =
(sizeof(NewT) > sizeof(OldT) && !(wistd::is_signed_v<OldT> && wistd::is_unsigned_v<NewT>)) ||
(sizeof(NewT) == sizeof(OldT) && ((wistd::is_signed_v<NewT> && wistd::is_signed_v<OldT>) || (wistd::is_unsigned_v<NewT> && wistd::is_unsigned_v<OldT>)));
// Helper template to determine that NewT and OldT are both integral types. The safe_cast
// operation only supports conversions between integral types.
template <typename NewT, typename OldT>
constexpr bool both_integral_v = wistd::is_integral<NewT>::value && wistd::is_integral<OldT>::value;
// Note on native wchar_t (__wchar_t):
// Intsafe.h does not currently handle native wchar_t. When compiling with /Zc:wchar_t-, this is fine as wchar_t is
// typedef'd to unsigned short. However, when compiling with /Zc:wchar_t or wchar_t as a native type, the lack of
// support for native wchar_t in intsafe.h becomes an issue. To work around this, we treat native wchar_t as an
// unsigned short when passing it to intsafe.h, because the two on the Windows platform are the same size and
// share the same range according to MSDN. If the cast is to a native wchar_t, the result from intsafe.h is cast
// to a native wchar_t.
// Intsafe does not have a defined conversion for native wchar_t
template <typename NewT, typename OldT>
constexpr bool neither_native_wchar_v = !wistd::is_same<NewT, __wchar_t>::value && !wistd::is_same<OldT, __wchar_t>::value;
// Check to see if the cast is a conversion to native wchar_t
template <typename NewT, typename OldT>
constexpr bool is_cast_to_wchar_v = wistd::is_same<NewT, __wchar_t>::value && !wistd::is_same<OldT, __wchar_t>::value;
// Check to see if the cast is a conversion from native wchar_t
template <typename NewT, typename OldT>
constexpr bool is_cast_from_wchar_v = !wistd::is_same<NewT, __wchar_t>::value && wistd::is_same<OldT, __wchar_t>::value;
// Validate the conversion to be performed has a defined mapping to an intsafe conversion
template <typename NewT, typename OldT>
constexpr bool is_supported_intsafe_cast_v = intsafe_conversion<OldT, NewT> != nullptr;
// True when the conversion is between integral types and can be handled by static_cast
template <typename NewT, typename OldT>
constexpr bool is_supported_safe_static_cast_v = both_integral_v<NewT, OldT> && is_known_safe_static_cast_v<NewT, OldT>;
// True when the conversion is between integral types, does not involve native wchar, has
// a mapped intsafe conversion, and is unsafe.
template <typename NewT, typename OldT>
constexpr bool is_supported_unsafe_cast_no_wchar_v =
both_integral_v<NewT, OldT> &&
!is_known_safe_static_cast_v<NewT, OldT> &&
neither_native_wchar_v<NewT, OldT> &&
is_supported_intsafe_cast_v<NewT, OldT>;
// True when the conversion is between integral types, is a cast to native wchar_t, has
// a mapped intsafe conversion, and is unsafe.
template <typename NewT, typename OldT>
constexpr bool is_supported_unsafe_cast_to_wchar_v =
both_integral_v<NewT, OldT> &&
!is_known_safe_static_cast_v<NewT, OldT> &&
is_cast_to_wchar_v<NewT, OldT> &&
is_supported_intsafe_cast_v<unsigned short, OldT>;
// True when the conversion is between integral types, is a cast from native wchar_t, has
// a mapped intsafe conversion, and is unsafe.
template <typename NewT, typename OldT>
constexpr bool is_supported_unsafe_cast_from_wchar_v =
both_integral_v<NewT, OldT> &&
!is_known_safe_static_cast_v<NewT, OldT> &&
is_cast_from_wchar_v<NewT, OldT> &&
is_supported_intsafe_cast_v<NewT, unsigned short>;
// True when the conversion is supported and unsafe, and may or may not involve
// native wchar_t.
template <typename NewT, typename OldT>
constexpr bool is_supported_unsafe_cast_v =
is_supported_unsafe_cast_no_wchar_v<NewT, OldT> ||
is_supported_unsafe_cast_to_wchar_v<NewT, OldT> ||
is_supported_unsafe_cast_from_wchar_v<NewT, OldT>;
// True when T is any one of the primitive types that the variably sized types are defined as.
template <typename T>
constexpr bool is_potentially_variably_sized_type_v =
wistd::is_same<T, int>::value ||
wistd::is_same<T, unsigned int>::value ||
wistd::is_same<T, long>::value ||
wistd::is_same<T, unsigned long>::value ||
wistd::is_same<T, __int64>::value ||
wistd::is_same<T, unsigned __int64>::value;
// True when either type is potentialy variably sized (e.g. size_t, ptrdiff_t)
template <typename OldT, typename NewT>
constexpr bool is_potentially_variably_sized_cast_v =
is_potentially_variably_sized_type_v<OldT> ||
is_potentially_variably_sized_type_v<NewT>;
// Mappings of all conversions defined in intsafe.h to intsafe_conversion
// Note: Uppercase types (UINT, DWORD, SIZE_T, etc) and architecture dependent types resolve
// to the base types. The base types are used since they do not vary based on architecture.
template<> constexpr auto intsafe_conversion<__int64, char> = LongLongToChar;
template<> constexpr auto intsafe_conversion<__int64, int> = LongLongToInt;
template<> constexpr auto intsafe_conversion<__int64, long> = LongLongToLong;
template<> constexpr auto intsafe_conversion<__int64, short> = LongLongToShort;
template<> constexpr auto intsafe_conversion<__int64, signed char> = LongLongToInt8;
template<> constexpr auto intsafe_conversion<__int64, unsigned __int64> = LongLongToULongLong;
template<> constexpr auto intsafe_conversion<__int64, unsigned char> = LongLongToUChar;
template<> constexpr auto intsafe_conversion<__int64, unsigned int> = LongLongToUInt;
template<> constexpr auto intsafe_conversion<__int64, unsigned long> = LongLongToULong;
template<> constexpr auto intsafe_conversion<__int64, unsigned short> = LongLongToUShort;
template<> constexpr auto intsafe_conversion<int, char> = IntToChar;
template<> constexpr auto intsafe_conversion<int, short> = IntToShort;
template<> constexpr auto intsafe_conversion<int, signed char> = IntToInt8;
template<> constexpr auto intsafe_conversion<int, unsigned __int64> = IntToULongLong;
template<> constexpr auto intsafe_conversion<int, unsigned char> = IntToUChar;
template<> constexpr auto intsafe_conversion<int, unsigned int> = IntToUInt;
template<> constexpr auto intsafe_conversion<int, unsigned long> = IntToULong;
template<> constexpr auto intsafe_conversion<int, unsigned short> = IntToUShort;
template<> constexpr auto intsafe_conversion<long, char> = LongToChar;
template<> constexpr auto intsafe_conversion<long, int> = LongToInt;
template<> constexpr auto intsafe_conversion<long, short> = LongToShort;
template<> constexpr auto intsafe_conversion<long, signed char> = LongToInt8;
template<> constexpr auto intsafe_conversion<long, unsigned __int64> = LongToULongLong;
template<> constexpr auto intsafe_conversion<long, unsigned char> = LongToUChar;
template<> constexpr auto intsafe_conversion<long, unsigned int> = LongToUInt;
template<> constexpr auto intsafe_conversion<long, unsigned long> = LongToULong;
template<> constexpr auto intsafe_conversion<long, unsigned short> = LongToUShort;
template<> constexpr auto intsafe_conversion<short, char> = ShortToChar;
template<> constexpr auto intsafe_conversion<short, signed char> = ShortToInt8;
template<> constexpr auto intsafe_conversion<short, unsigned __int64> = ShortToULongLong;
template<> constexpr auto intsafe_conversion<short, unsigned char> = ShortToUChar;
template<> constexpr auto intsafe_conversion<short, unsigned int> = ShortToUInt;
template<> constexpr auto intsafe_conversion<short, unsigned long> = ShortToULong;
template<> constexpr auto intsafe_conversion<short, unsigned short> = ShortToUShort;
template<> constexpr auto intsafe_conversion<signed char, unsigned __int64> = Int8ToULongLong;
template<> constexpr auto intsafe_conversion<signed char, unsigned char> = Int8ToUChar;
template<> constexpr auto intsafe_conversion<signed char, unsigned int> = Int8ToUInt;
template<> constexpr auto intsafe_conversion<signed char, unsigned long> = Int8ToULong;
template<> constexpr auto intsafe_conversion<signed char, unsigned short> = Int8ToUShort;
template<> constexpr auto intsafe_conversion<unsigned __int64, __int64> = ULongLongToLongLong;
template<> constexpr auto intsafe_conversion<unsigned __int64, char> = ULongLongToChar;
template<> constexpr auto intsafe_conversion<unsigned __int64, int> = ULongLongToInt;
template<> constexpr auto intsafe_conversion<unsigned __int64, long> = ULongLongToLong;
template<> constexpr auto intsafe_conversion<unsigned __int64, short> = ULongLongToShort;
template<> constexpr auto intsafe_conversion<unsigned __int64, signed char> = ULongLongToInt8;
template<> constexpr auto intsafe_conversion<unsigned __int64, unsigned char> = ULongLongToUChar;
template<> constexpr auto intsafe_conversion<unsigned __int64, unsigned int> = ULongLongToUInt;
template<> constexpr auto intsafe_conversion<unsigned __int64, unsigned long> = ULongLongToULong;
template<> constexpr auto intsafe_conversion<unsigned __int64, unsigned short> = ULongLongToUShort;
template<> constexpr auto intsafe_conversion<unsigned char, char> = UInt8ToChar;
template<> constexpr auto intsafe_conversion<unsigned char, signed char> = UIntToInt8;
template<> constexpr auto intsafe_conversion<unsigned int, char> = UIntToChar;
template<> constexpr auto intsafe_conversion<unsigned int, int> = UIntToInt;
template<> constexpr auto intsafe_conversion<unsigned int, long> = UIntToLong;
template<> constexpr auto intsafe_conversion<unsigned int, short> = UIntToShort;
template<> constexpr auto intsafe_conversion<unsigned int, signed char> = UIntToInt8;
template<> constexpr auto intsafe_conversion<unsigned int, unsigned char> = UIntToUChar;
template<> constexpr auto intsafe_conversion<unsigned int, unsigned short> = UIntToUShort;
template<> constexpr auto intsafe_conversion<unsigned long, char> = ULongToChar;
template<> constexpr auto intsafe_conversion<unsigned long, int> = ULongToInt;
template<> constexpr auto intsafe_conversion<unsigned long, long> = ULongToLong;
template<> constexpr auto intsafe_conversion<unsigned long, short> = ULongToShort;
template<> constexpr auto intsafe_conversion<unsigned long, signed char> = ULongToInt8;
template<> constexpr auto intsafe_conversion<unsigned long, unsigned char> = ULongToUChar;
template<> constexpr auto intsafe_conversion<unsigned long, unsigned int> = ULongToUInt;
template<> constexpr auto intsafe_conversion<unsigned long, unsigned short> = ULongToUShort;
template<> constexpr auto intsafe_conversion<unsigned short, char> = UShortToChar;
template<> constexpr auto intsafe_conversion<unsigned short, short> = UShortToShort;
template<> constexpr auto intsafe_conversion<unsigned short, signed char> = UShortToInt8;
template<> constexpr auto intsafe_conversion<unsigned short, unsigned char> = UShortToUChar;
}
// Unsafe conversion where failure results in fail fast.
template <
typename NewT,
typename OldT,
wistd::enable_if_t<details::is_supported_unsafe_cast_no_wchar_v<NewT, OldT>, int> = 0
>
NewT safe_cast_failfast(const OldT var)
{
NewT newVar;
FAIL_FAST_IF_FAILED((details::intsafe_conversion<OldT, NewT>(var, &newVar)));
return newVar;
}
// Unsafe conversion where failure results in fail fast.
template <
typename NewT,
typename OldT,
wistd::enable_if_t<details::is_supported_unsafe_cast_from_wchar_v<NewT, OldT>, int> = 0
>
NewT safe_cast_failfast(const OldT var)
{
NewT newVar;
FAIL_FAST_IF_FAILED((details::intsafe_conversion<unsigned short, NewT>(static_cast<unsigned short>(var), &newVar)));
return newVar;
}
// Unsafe conversion where failure results in fail fast.
template <
typename NewT,
typename OldT,
wistd::enable_if_t<details::is_supported_unsafe_cast_to_wchar_v<NewT, OldT>, int> = 0
>
NewT safe_cast_failfast(const OldT var)
{
unsigned short newVar;
FAIL_FAST_IF_FAILED((details::intsafe_conversion<OldT, unsigned short>(var, &newVar)));
return static_cast<__wchar_t>(newVar);
}
// This conversion is always safe, therefore a static_cast is fine.
template <
typename NewT,
typename OldT,
wistd::enable_if_t<details::is_supported_safe_static_cast_v<NewT, OldT>, int> = 0
>
NewT safe_cast_failfast(const OldT var)
{
return static_cast<NewT>(var);
}
#ifdef WIL_ENABLE_EXCEPTIONS
// Unsafe conversion where failure results in a thrown exception.
template <
typename NewT,
typename OldT,
wistd::enable_if_t<details::is_supported_unsafe_cast_no_wchar_v<NewT, OldT>, int> = 0
>
NewT safe_cast(const OldT var)
{
NewT newVar;
THROW_IF_FAILED((details::intsafe_conversion<OldT, NewT>(var, &newVar)));
return newVar;
}
// Unsafe conversion where failure results in a thrown exception.
template <
typename NewT,
typename OldT,
wistd::enable_if_t<details::is_supported_unsafe_cast_from_wchar_v<NewT, OldT>, int> = 0
>
NewT safe_cast(const OldT var)
{
NewT newVar;
THROW_IF_FAILED((details::intsafe_conversion<unsigned short, NewT>(static_cast<unsigned short>(var), &newVar)));
return newVar;
}
// Unsafe conversion where failure results in a thrown exception.
template <
typename NewT,
typename OldT,
wistd::enable_if_t<details::is_supported_unsafe_cast_to_wchar_v<NewT, OldT>, int> = 0
>
NewT safe_cast(const OldT var)
{
unsigned short newVar;
THROW_IF_FAILED((details::intsafe_conversion<OldT, unsigned short>(var, &newVar)));
return static_cast<__wchar_t>(newVar);
}
// This conversion is always safe, therefore a static_cast is fine.
template <
typename NewT,
typename OldT,
wistd::enable_if_t<details::is_supported_safe_static_cast_v<NewT, OldT>, int> = 0
>
NewT safe_cast(const OldT var)
{
return static_cast<NewT>(var);
}
#endif
// This conversion is unsafe, therefore the two parameter version of safe_cast_nothrow must be used
template <
typename NewT,
typename OldT,
wistd::enable_if_t<details::is_supported_unsafe_cast_v<NewT, OldT>, int> = 0
>
NewT safe_cast_nothrow(const OldT /*var*/)
{
static_assert(!wistd::is_same_v<NewT, NewT>, "This cast has the potential to fail, use the two parameter safe_cast_nothrow instead");
}
// This conversion is always safe, therefore a static_cast is fine.
template <
typename NewT,
typename OldT,
wistd::enable_if_t<details::is_supported_safe_static_cast_v<NewT, OldT>, int> = 0
>
NewT safe_cast_nothrow(const OldT var)
{
return static_cast<NewT>(var);
}
// Unsafe conversion where an HRESULT is returned. It is up to the callee to check and handle the HRESULT
template <
typename NewT,
typename OldT,
wistd::enable_if_t<details::is_supported_unsafe_cast_no_wchar_v<NewT, OldT>, int> = 0
>
HRESULT safe_cast_nothrow(const OldT var, NewT* newTResult)
{
return details::intsafe_conversion<OldT, NewT>(var, newTResult);
}
// Unsafe conversion where an HRESULT is returned. It is up to the callee to check and handle the HRESULT
template <
typename NewT,
typename OldT,
wistd::enable_if_t<details::is_supported_unsafe_cast_from_wchar_v<NewT, OldT>, int> = 0
>
HRESULT safe_cast_nothrow(const OldT var, NewT* newTResult)
{
return details::intsafe_conversion<unsigned short, NewT>(static_cast<unsigned short>(var), newTResult);
}
// Unsafe conversion where an HRESULT is returned. It is up to the callee to check and handle the HRESULT
template <
typename NewT,
typename OldT,
wistd::enable_if_t<details::is_supported_unsafe_cast_to_wchar_v<NewT, OldT>, int> = 0
>
HRESULT safe_cast_nothrow(const OldT var, NewT* newTResult)
{
return details::intsafe_conversion<OldT, unsigned short>(var, reinterpret_cast<unsigned short *>(newTResult));
}
// This conversion is always safe, therefore a static_cast is fine. If it can be determined the conversion
// does not involve a variably sized type, then the compilation will fail and say the single parameter version
// of safe_cast_nothrow should be used instead.
template <
typename NewT,
typename OldT,
wistd::enable_if_t<details::is_supported_safe_static_cast_v<NewT, OldT>, int> = 0
>
HRESULT safe_cast_nothrow(const OldT var, NewT* newTResult)
{
static_assert(details::is_potentially_variably_sized_cast_v<OldT, NewT>, "This cast is always safe; use safe_cast_nothrow<T>(value) to avoid unnecessary error handling.");
*newTResult = static_cast<NewT>(var);
return S_OK;
}
}
#endif // __WIL_SAFECAST_INCLUDED

@ -0,0 +1,116 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
//*********************************************************
#ifndef __WIL_STL_INCLUDED
#define __WIL_STL_INCLUDED
#include "common.h"
#include "resource.h"
#include <memory>
#include <string>
#include <vector>
#if defined(WIL_ENABLE_EXCEPTIONS)
namespace wil
{
/** Secure allocator for STL containers.
The `wil::secure_allocator` allocator calls `SecureZeroMemory` before deallocating
memory. This provides a mechanism for secure STL containers such as `wil::secure_vector`,
`wil::secure_string`, and `wil::secure_wstring`. */
template <typename T>
struct secure_allocator
: public std::allocator<T>
{
template<typename Other>
struct rebind
{
typedef secure_allocator<Other> other;
};
secure_allocator()
: std::allocator<T>()
{
}
~secure_allocator() = default;
secure_allocator(const secure_allocator& a)
: std::allocator<T>(a)
{
}
template <class U>
secure_allocator(const secure_allocator<U>& a)
: std::allocator<T>(a)
{
}
T* allocate(size_t n)
{
return std::allocator<T>::allocate(n);
}
void deallocate(T* p, size_t n)
{
SecureZeroMemory(p, sizeof(T) * n);
std::allocator<T>::deallocate(p, n);
}
};
//! `wil::secure_vector` will be securely zeroed before deallocation.
template <typename Type>
using secure_vector = std::vector<Type, secure_allocator<Type>>;
//! `wil::secure_wstring` will be securely zeroed before deallocation.
using secure_wstring = std::basic_string<wchar_t, std::char_traits<wchar_t>, wil::secure_allocator<wchar_t>>;
//! `wil::secure_string` will be securely zeroed before deallocation.
using secure_string = std::basic_string<char, std::char_traits<char>, wil::secure_allocator<char>>;
/// @cond
namespace details
{
template<> struct string_maker<std::wstring>
{
HRESULT make(_In_reads_opt_(length) PCWSTR source, size_t length) WI_NOEXCEPT try
{
m_value = source ? std::wstring(source, length) : std::wstring(length, L'\0');
return S_OK;
}
catch (...)
{
return E_OUTOFMEMORY;
}
wchar_t* buffer() { return &m_value[0]; }
HRESULT trim_at_existing_null(size_t length) { m_value.erase(length); return S_OK; }
std::wstring release() { return std::wstring(std::move(m_value)); }
static PCWSTR get(const std::wstring& value) { return value.c_str(); }
private:
std::wstring m_value;
};
}
/// @endcond
// str_raw_ptr is an overloaded function that retrieves a const pointer to the first character in a string's buffer.
// This is the overload for std::wstring. Other overloads available in resource.h.
inline PCWSTR str_raw_ptr(const std::wstring& str)
{
return str.c_str();
}
} // namespace wil
#endif // WIL_ENABLE_EXCEPTIONS
#endif // __WIL_STL_INCLUDED

@ -0,0 +1,601 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
//*********************************************************
#ifndef __WIL_TOKEN_HELPERS_INCLUDED
#define __WIL_TOKEN_HELPERS_INCLUDED
#ifdef _KERNEL_MODE
#error This header is not supported in kernel-mode.
#endif
#include "resource.h"
#include <new>
#include <lmcons.h> // for UNLEN and DNLEN
#include <processthreadsapi.h>
// for GetUserNameEx()
#define SECURITY_WIN32
#include <Security.h>
namespace wil
{
/// @cond
namespace details
{
// Template specialization for TOKEN_INFORMATION_CLASS, add more mappings here as needed
// TODO: The mapping should be reversed to be MapTokenInfoClassToStruct since there may
// be an info class value that uses the same structure. That is the case for the file
// system information.
template<typename T> struct MapTokenStructToInfoClass;
template<> struct MapTokenStructToInfoClass<TOKEN_ACCESS_INFORMATION> { static const TOKEN_INFORMATION_CLASS infoClass = TokenAccessInformation; static const bool FixedSize = false; };
template<> struct MapTokenStructToInfoClass<TOKEN_APPCONTAINER_INFORMATION> { static const TOKEN_INFORMATION_CLASS infoClass = TokenAppContainerSid; static const bool FixedSize = false; };
template<> struct MapTokenStructToInfoClass<TOKEN_DEFAULT_DACL> { static const TOKEN_INFORMATION_CLASS infoClass = TokenDefaultDacl; static const bool FixedSize = false; };
template<> struct MapTokenStructToInfoClass<TOKEN_GROUPS_AND_PRIVILEGES> { static const TOKEN_INFORMATION_CLASS infoClass = TokenGroupsAndPrivileges; static const bool FixedSize = false; };
template<> struct MapTokenStructToInfoClass<TOKEN_MANDATORY_LABEL> { static const TOKEN_INFORMATION_CLASS infoClass = TokenIntegrityLevel; static const bool FixedSize = false; };
template<> struct MapTokenStructToInfoClass<TOKEN_OWNER> { static const TOKEN_INFORMATION_CLASS infoClass = TokenOwner; static const bool FixedSize = false; };
template<> struct MapTokenStructToInfoClass<TOKEN_PRIMARY_GROUP> { static const TOKEN_INFORMATION_CLASS infoClass = TokenPrimaryGroup; static const bool FixedSize = false; };
template<> struct MapTokenStructToInfoClass<TOKEN_PRIVILEGES> { static const TOKEN_INFORMATION_CLASS infoClass = TokenPrivileges; static const bool FixedSize = false; };
template<> struct MapTokenStructToInfoClass<TOKEN_USER> { static const TOKEN_INFORMATION_CLASS infoClass = TokenUser; static const bool FixedSize = false; };
// fixed size cases
template<> struct MapTokenStructToInfoClass<TOKEN_ELEVATION_TYPE> { static const TOKEN_INFORMATION_CLASS infoClass = TokenElevationType; static const bool FixedSize = true; };
template<> struct MapTokenStructToInfoClass<TOKEN_MANDATORY_POLICY> { static const TOKEN_INFORMATION_CLASS infoClass = TokenMandatoryPolicy; static const bool FixedSize = true; };
template<> struct MapTokenStructToInfoClass<TOKEN_ORIGIN> { static const TOKEN_INFORMATION_CLASS infoClass = TokenOrigin; static const bool FixedSize = true; };
template<> struct MapTokenStructToInfoClass<TOKEN_SOURCE> { static const TOKEN_INFORMATION_CLASS infoClass = TokenSource; static const bool FixedSize = true; };
template<> struct MapTokenStructToInfoClass<TOKEN_STATISTICS> { static const TOKEN_INFORMATION_CLASS infoClass = TokenStatistics; static const bool FixedSize = true; };
template<> struct MapTokenStructToInfoClass<TOKEN_TYPE> { static const TOKEN_INFORMATION_CLASS infoClass = TokenType; static const bool FixedSize = true; };
template<> struct MapTokenStructToInfoClass<SECURITY_IMPERSONATION_LEVEL> { static const TOKEN_INFORMATION_CLASS infoClass = TokenImpersonationLevel; static const bool FixedSize = true; };
template<> struct MapTokenStructToInfoClass<TOKEN_ELEVATION> { static const TOKEN_INFORMATION_CLASS infoClass = TokenElevation; static const bool FixedSize = true; };
}
/// @endcond
enum class OpenThreadTokenAs
{
Current,
Self
};
/** Open the active token.
Opens either the current thread token (if impersonating) or the current process token. Returns a token the caller
can use with methods like get_token_information<> below. By default, the token is opened for TOKEN_QUERY and as the
effective user.
Consider using GetCurrentThreadEffectiveToken() instead of this method when eventually calling get_token_information.
This method returns a real handle to the effective token, but GetCurrentThreadEffectiveToken() is a Pseudo-handle
and much easier to manage.
~~~~
wil::unique_handle theToken;
RETURN_IF_FAILED(wil::open_current_access_token_nothrow(&theToken));
~~~~
Callers who want more access to the token (such as to duplicate or modify the token) can pass
any mask of the token rights.
~~~~
wil::unique_handle theToken;
RETURN_IF_FAILED(wil::open_current_access_token_nothrow(&theToken, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES));
~~~~
Services impersonating their clients may need to request that the active token is opened on the
behalf of the service process to perform certain operations. Opening a token for impersonation access
or privilege-adjustment are examples of uses.
~~~~
wil::unique_handle callerToken;
RETURN_IF_FAILED(wil::open_current_access_token_nothrow(&theToken, TOKEN_QUERY | TOKEN_IMPERSONATE, true));
~~~~
@param tokenHandle Receives the token opened during the operation. Must be CloseHandle'd by the caller, or
(preferably) stored in a wil::unique_handle
@param access Bits from the TOKEN_* access mask which are passed to OpenThreadToken/OpenProcessToken
@param asSelf When true, and if the thread is impersonating, the thread token is opened using the
process token's rights.
*/
inline HRESULT open_current_access_token_nothrow(_Out_ HANDLE* tokenHandle, unsigned long access = TOKEN_QUERY, OpenThreadTokenAs openAs = OpenThreadTokenAs::Current)
{
HRESULT hr = (OpenThreadToken(GetCurrentThread(), access, (openAs == OpenThreadTokenAs::Self), tokenHandle) ? S_OK : HRESULT_FROM_WIN32(::GetLastError()));
if (hr == HRESULT_FROM_WIN32(ERROR_NO_TOKEN))
{
hr = (OpenProcessToken(GetCurrentProcess(), access, tokenHandle) ? S_OK : HRESULT_FROM_WIN32(::GetLastError()));
}
return hr;
}
//! Current thread or process token, consider using GetCurrentThreadEffectiveToken() instead.
inline wil::unique_handle open_current_access_token_failfast(unsigned long access = TOKEN_QUERY, OpenThreadTokenAs openAs = OpenThreadTokenAs::Current)
{
HANDLE rawTokenHandle;
FAIL_FAST_IF_FAILED(open_current_access_token_nothrow(&rawTokenHandle, access, openAs));
return wil::unique_handle(rawTokenHandle);
}
// Exception based function to open current thread/process access token and acquire pointer to it
#ifdef WIL_ENABLE_EXCEPTIONS
//! Current thread or process token, consider using GetCurrentThreadEffectiveToken() instead.
inline wil::unique_handle open_current_access_token(unsigned long access = TOKEN_QUERY, OpenThreadTokenAs openAs = OpenThreadTokenAs::Current)
{
HANDLE rawTokenHandle;
THROW_IF_FAILED(open_current_access_token_nothrow(&rawTokenHandle, access, openAs));
return wil::unique_handle(rawTokenHandle);
}
#endif // WIL_ENABLE_EXCEPTIONS
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
// Returns tokenHandle or the effective thread token if tokenHandle is null.
// Note, this returns an token handle who's lifetime is managed independently
// and it may be a pseudo token, don't free it!
inline HANDLE GetCurrentThreadEffectiveTokenWithOverride(HANDLE tokenHandle)
{
return tokenHandle ? tokenHandle : GetCurrentThreadEffectiveToken();
}
/** Fetches information about a token.
See GetTokenInformation on MSDN for what this method can return. For variable sized structs the information
is returned to the caller as a wistd::unique_ptr<T> (like TOKEN_ORIGIN, TOKEN_USER, TOKEN_ELEVATION, etc.). For
fixed sized, the struct is returned directly.
The caller must have access to read the information from the provided token. This method works with both real
(e.g. OpenCurrentAccessToken) and pseudo (e.g. GetCurrentThreadToken) token handles.
~~~~
// Retrieve the TOKEN_USER structure for the current process
wistd::unique_ptr<TOKEN_USER> user;
RETURN_IF_FAILED(wil::get_token_information_nothrow(user, GetCurrentProcessToken()));
RETURN_IF_FAILED(ConsumeSid(user->User.Sid));
~~~~
Not specifying the token handle is the same as specifying 'nullptr' and retrieves information about the effective token.
~~~~
wistd::unique_ptr<TOKEN_PRIVILEGES> privileges;
RETURN_IF_FAILED(wil::get_token_information_nothrow(privileges));
for (auto const& privilege : wil::GetRange(privileges->Privileges, privileges->PrivilegeCount))
{
RETURN_IF_FAILED(ConsumePrivilege(privilege));
}
~~~~
@param tokenInfo Receives a pointer to a structure containing the results of GetTokenInformation for the requested
type. The type of <T> selects which TOKEN_INFORMATION_CLASS will be used.
@param tokenHandle Specifies which token will be queried. When nullptr, the thread's effective current token is used.
@return S_OK on success, a FAILED hresult containing the win32 error from querying the token otherwise.
*/
template <typename T, wistd::enable_if_t<!details::MapTokenStructToInfoClass<T>::FixedSize>* = nullptr>
inline HRESULT get_token_information_nothrow(wistd::unique_ptr<T>& tokenInfo, HANDLE tokenHandle = nullptr)
{
tokenInfo.reset();
tokenHandle = GetCurrentThreadEffectiveTokenWithOverride(tokenHandle);
DWORD tokenInfoSize = 0;
const auto infoClass = details::MapTokenStructToInfoClass<T>::infoClass;
RETURN_LAST_ERROR_IF(!((!GetTokenInformation(tokenHandle, infoClass, nullptr, 0, &tokenInfoSize)) &&
(::GetLastError() == ERROR_INSUFFICIENT_BUFFER)));
wistd::unique_ptr<char> tokenInfoClose(
static_cast<char*>(operator new(tokenInfoSize, std::nothrow)));
RETURN_IF_NULL_ALLOC(tokenInfoClose.get());
RETURN_IF_WIN32_BOOL_FALSE(GetTokenInformation(tokenHandle, infoClass, tokenInfoClose.get(), tokenInfoSize, &tokenInfoSize));
tokenInfo.reset(reinterpret_cast<T *>(tokenInfoClose.release()));
return S_OK;
}
template <typename T, wistd::enable_if_t<details::MapTokenStructToInfoClass<T>::FixedSize>* = nullptr>
inline HRESULT get_token_information_nothrow(_Out_ T* tokenInfo, HANDLE tokenHandle = nullptr)
{
*tokenInfo = {};
tokenHandle = GetCurrentThreadEffectiveTokenWithOverride(tokenHandle);
DWORD tokenInfoSize = sizeof(T);
const auto infoClass = details::MapTokenStructToInfoClass<T>::infoClass;
RETURN_IF_WIN32_BOOL_FALSE(GetTokenInformation(tokenHandle, infoClass, tokenInfo, tokenInfoSize, &tokenInfoSize));
return S_OK;
}
namespace details
{
template<typename T, typename policy, wistd::enable_if_t<!details::MapTokenStructToInfoClass<T>::FixedSize>* = nullptr>
wistd::unique_ptr<T> GetTokenInfoWrap(HANDLE token = nullptr)
{
wistd::unique_ptr<T> temp;
policy::HResult(get_token_information_nothrow(temp, token));
return temp;
}
template<typename T, typename policy, wistd::enable_if_t<details::MapTokenStructToInfoClass<T>::FixedSize>* = nullptr>
T GetTokenInfoWrap(HANDLE token = nullptr)
{
T temp{};
policy::HResult(get_token_information_nothrow(&temp, token));
return temp;
}
}
//! A variant of get_token_information<T> that fails-fast on errors retrieving the token
template <typename T>
inline auto get_token_information_failfast(HANDLE token = nullptr)
{
return details::GetTokenInfoWrap<T, err_failfast_policy>(token);
}
//! Overload of GetTokenInformationNoThrow that retrieves a token linked from the provided token
inline HRESULT get_token_information_nothrow(unique_token_linked_token& tokenInfo, HANDLE tokenHandle = nullptr)
{
static_assert(sizeof(tokenInfo) == sizeof(TOKEN_LINKED_TOKEN), "confusing size mismatch");
tokenHandle = GetCurrentThreadEffectiveTokenWithOverride(tokenHandle);
DWORD tokenInfoSize = 0;
RETURN_IF_WIN32_BOOL_FALSE(::GetTokenInformation(tokenHandle, TokenLinkedToken,
tokenInfo.reset_and_addressof(), sizeof(tokenInfo), &tokenInfoSize));
return S_OK;
}
/** Retrieves the linked-token information for a token.
Fails-fast if the link information cannot be retrieved.
~~~~
auto link = get_linked_token_information_failfast(GetCurrentThreadToken());
auto tokenUser = get_token_information<TOKEN_USER>(link.LinkedToken);
~~~~
@param token Specifies the token to query. Pass nullptr to use the current effective thread token
@return unique_token_linked_token containing a handle to the linked token
*/
inline unique_token_linked_token get_linked_token_information_failfast(HANDLE token = nullptr)
{
unique_token_linked_token tokenInfo;
FAIL_FAST_IF_FAILED(get_token_information_nothrow(tokenInfo, token));
return tokenInfo;
}
#ifdef WIL_ENABLE_EXCEPTIONS
/** Fetches information about a token.
See get_token_information_nothrow for full details.
~~~~
auto user = wil::get_token_information<TOKEN_USER>(GetCurrentProcessToken());
ConsumeSid(user->User.Sid);
~~~~
Pass 'nullptr' (or omit the parameter) as tokenHandle to retrieve information about the effective token.
~~~~
auto privs = wil::get_token_information<TOKEN_PRIVILEGES>(privileges);
for (auto& priv : wil::make_range(privs->Privileges, privs->Privilieges + privs->PrivilegeCount))
{
if (priv.Attributes & SE_PRIVILEGE_ENABLED)
{
// ...
}
}
~~~~
@return A pointer to a structure containing the results of GetTokenInformation for the requested type. The type of
<T> selects which TOKEN_INFORMATION_CLASS will be used.
@param token Specifies which token will be queried. When nullptr or not set, the thread's effective current token is used.
*/
template <typename T>
inline auto get_token_information(HANDLE token = nullptr)
{
return details::GetTokenInfoWrap<T, err_exception_policy>(token);
}
/** Retrieves the linked-token information for a token.
Throws an exception if the link information cannot be retrieved.
~~~~
auto link = get_linked_token_information(GetCurrentThreadToken());
auto tokenUser = get_token_information<TOKEN_USER>(link.LinkedToken);
~~~~
@param token Specifies the token to query. Pass nullptr to use the current effective thread token
@return unique_token_linked_token containing a handle to the linked token
*/
inline unique_token_linked_token get_linked_token_information(HANDLE token = nullptr)
{
unique_token_linked_token tokenInfo;
THROW_IF_FAILED(get_token_information_nothrow(tokenInfo, token));
return tokenInfo;
}
#endif
#endif // _WIN32_WINNT >= _WIN32_WINNT_WIN8
/// @cond
namespace details
{
inline void RevertImpersonateToken(_Pre_opt_valid_ _Frees_ptr_opt_ HANDLE oldToken)
{
FAIL_FAST_IMMEDIATE_IF(!::SetThreadToken(nullptr, oldToken));
if (oldToken)
{
::CloseHandle(oldToken);
}
}
}
/// @endcond
using unique_token_reverter = wil::unique_any<
HANDLE,
decltype(&details::RevertImpersonateToken),
details::RevertImpersonateToken,
details::pointer_access_none,
HANDLE,
INT_PTR,
-1,
HANDLE>;
/** Temporarily impersonates a token on this thread.
This method sets a new token on a thread, restoring the current token when the returned object
is destroyed. Useful for impersonating other tokens or running as 'self,' especially in services.
~~~~
HRESULT OpenFileAsSessionuser(PCWSTR filePath, DWORD session, _Out_ HANDLE* opened)
{
wil::unique_handle userToken;
RETURN_IF_WIN32_BOOL_FALSE(QueryUserToken(session, &userToken));
wil::unique_token_reverter reverter;
RETURN_IF_FAILED(wil::impersonate_token_nothrow(userToken.get(), reverter));
wil::unique_hfile userFile(::CreateFile(filePath, ...));
RETURN_LAST_ERROR_IF(!userFile && (::GetLastError() != ERROR_FILE_NOT_FOUND));
*opened = userFile.release();
return S_OK;
}
~~~~
@param token A token to impersonate, or 'nullptr' to run as the process identity.
*/
inline HRESULT impersonate_token_nothrow(HANDLE token, unique_token_reverter& reverter)
{
wil::unique_handle currentToken;
// Get the token for the current thread. If there wasn't one, the reset will clear it as well
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &currentToken))
{
RETURN_LAST_ERROR_IF(::GetLastError() != ERROR_NO_TOKEN);
}
// Update the current token
RETURN_IF_WIN32_BOOL_FALSE(::SetThreadToken(nullptr, token));
reverter.reset(currentToken.release()); // Ownership passed
return S_OK;
}
/** Temporarily clears any impersonation on this thread.
This method resets the current thread's token to nullptr, indicating that it is not impersonating
any user. Useful for elevating to whatever identity a service or higher-privilege process might
be capable of running under.
~~~~
HRESULT DeleteFileRetryAsSelf(PCWSTR filePath)
{
if (!::DeleteFile(filePath))
{
RETURN_LAST_ERROR_IF(::GetLastError() != ERROR_ACCESS_DENIED);
wil::unique_token_reverter reverter;
RETURN_IF_FAILED(wil::run_as_self_nothrow(reverter));
RETURN_IF_FAILED(TakeOwnershipOfFile(filePath));
RETURN_IF_FAILED(GrantDeleteAccess(filePath));
RETURN_IF_WIN32_BOOL_FALSE(::DeleteFile(filePath));
}
return S_OK;
}
~~~~
*/
inline HRESULT run_as_self_nothrow(unique_token_reverter& reverter)
{
return impersonate_token_nothrow(nullptr, reverter);
}
inline unique_token_reverter impersonate_token_failfast(HANDLE token)
{
unique_token_reverter oldToken;
FAIL_FAST_IF_FAILED(impersonate_token_nothrow(token, oldToken));
return oldToken;
}
inline unique_token_reverter run_as_self_failfast()
{
return impersonate_token_failfast(nullptr);
}
#ifdef WIL_ENABLE_EXCEPTIONS
/** Temporarily impersonates a token on this thread.
This method sets a new token on a thread, restoring the current token when the returned object
is destroyed. Useful for impersonating other tokens or running as 'self,' especially in services.
~~~~
wil::unique_hfile OpenFileAsSessionuser(_In_z_ const wchar_t* filePath, DWORD session)
{
wil::unique_handle userToken;
THROW_IF_WIN32_BOOL_FALSE(QueryUserToken(session, &userToken));
auto priorToken = wil::impersonate_token(userToken.get());
wil::unique_hfile userFile(::CreateFile(filePath, ...));
THROW_LAST_ERROR_IF(::GetLastError() != ERROR_FILE_NOT_FOUND);
return userFile;
}
~~~~
@param token A token to impersonate, or 'nullptr' to run as the process identity.
*/
inline unique_token_reverter impersonate_token(HANDLE token = nullptr)
{
unique_token_reverter oldToken;
THROW_IF_FAILED(impersonate_token_nothrow(token, oldToken));
return oldToken;
}
/** Temporarily clears any impersonation on this thread.
This method resets the current thread's token to nullptr, indicating that it is not impersonating
any user. Useful for elevating to whatever identity a service or higher-privilege process might
be capable of running under.
~~~~
void DeleteFileRetryAsSelf(_In_z_ const wchar_t* filePath)
{
if (!::DeleteFile(filePath) && (::GetLastError() == ERROR_ACCESS_DENIED))
{
auto priorToken = wil::run_as_self();
TakeOwnershipOfFile(filePath);
GrantDeleteAccess(filePath);
::DeleteFile(filePath);
}
}
~~~~
*/
inline unique_token_reverter run_as_self()
{
return impersonate_token(nullptr);
}
#endif // WIL_ENABLE_EXCEPTIONS
namespace details
{
template<size_t AuthorityCount> struct static_sid_t
{
BYTE Revision;
BYTE SubAuthorityCount;
SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
DWORD SubAuthority[AuthorityCount];
PSID get()
{
return reinterpret_cast<PSID>(this);
}
template<size_t other> static_sid_t& operator=(const static_sid_t<other>& source)
{
static_assert(other <= AuthorityCount, "Cannot assign from a larger static sid to a smaller one");
if (&this->Revision != &source.Revision)
{
memcpy(this, &source, sizeof(source));
}
return *this;
}
};
}
/** Returns a structure containing a Revision 1 SID initialized with the authorities provided
Replaces AllocateAndInitializeSid by constructing a structure laid out like a PSID, but
returned like a value. The resulting object is suitable for use with any method taking PSID,
passed by "&the_sid" or via "the_sid.get()"
~~~~
// Change the owner of the key to administrators
auto systemSid = wil::make_static_sid(SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS);
RETURN_IF_WIN32_ERROR(SetNamedSecurityInfo(keyPath, SE_REGISTRY_KEY, OWNER_SECURITY_INFORMATION, &systemSid, nullptr, nullptr, nullptr));
~~~~
*/
template<typename... Ts> constexpr auto make_static_sid(const SID_IDENTIFIER_AUTHORITY& authority, Ts&&... subAuthorities)
{
using sid_t = details::static_sid_t<sizeof...(subAuthorities)>;
static_assert(sizeof...(subAuthorities) <= SID_MAX_SUB_AUTHORITIES, "too many sub authorities");
static_assert(offsetof(sid_t, Revision) == offsetof(_SID, Revision), "layout mismatch");
static_assert(offsetof(sid_t, SubAuthorityCount) == offsetof(_SID, SubAuthorityCount), "layout mismatch");
static_assert(offsetof(sid_t, IdentifierAuthority) == offsetof(_SID, IdentifierAuthority), "layout mismatch");
static_assert(offsetof(sid_t, SubAuthority) == offsetof(_SID, SubAuthority), "layout mismatch");
return sid_t { SID_REVISION, sizeof...(subAuthorities), authority, { static_cast<DWORD>(subAuthorities)... } };
}
//! Variant of static_sid that defaults to the NT authority
template<typename... Ts> constexpr auto make_static_nt_sid(Ts&& ... subAuthorities)
{
return make_static_sid(SECURITY_NT_AUTHORITY, wistd::forward<Ts>(subAuthorities)...);
}
/** Determines whether a specified security identifier (SID) is enabled in an access token.
This function determines whether a security identifier, described by a given set of subauthorities, is enabled
in the given access token. Note that only up to eight subauthorities can be passed to this function.
~~~~
bool IsGuest()
{
return wil::test_token_membership(nullptr, SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS));
}
~~~~
@param result This will be set to true if and only if a security identifier described by the given set of subauthorities is enabled in the given access token.
@param token A handle to an access token. The handle must have TOKEN_QUERY access to the token, and must be an impersonation token. If token is nullptr, test_token_membership
uses the impersonation token of the calling thread. If the thread is not impersonating, the function duplicates the thread's primary token to create an impersonation token.
@param sidAuthority A reference to a SID_IDENTIFIER_AUTHORITY structure. This structure provides the top-level identifier authority value to set in the SID.
@param subAuthorities Up to 15 subauthority values to place in the SID (this is a systemwide limit)
@return S_OK on success, a FAILED hresult containing the win32 error from creating the SID or querying the token otherwise.
*/
template<typename... Ts> HRESULT test_token_membership_nothrow(_Out_ bool* result, _In_opt_ HANDLE token,
const SID_IDENTIFIER_AUTHORITY& sidAuthority, Ts&&... subAuthorities)
{
*result = false;
auto tempSid = make_static_sid(sidAuthority, wistd::forward<Ts>(subAuthorities)...);
BOOL isMember;
RETURN_IF_WIN32_BOOL_FALSE(CheckTokenMembership(token, &tempSid, &isMember));
*result = (isMember != FALSE);
return S_OK;
}
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
/** Determine whether a token represents an app container
This method uses the passed in token and emits a boolean indicating that
whether TokenIsAppContainer is true.
~~~~
HRESULT OnlyIfAppContainer()
{
bool isAppContainer;
RETURN_IF_FAILED(wil::get_token_is_app_container_nothrow(nullptr, isAppContainer));
RETURN_HR_IF(E_ACCESSDENIED, !isAppContainer);
RETURN_HR(...);
}
~~~~
@param token A token to get info about, or 'nullptr' to run as the current thread.
*/
inline HRESULT get_token_is_app_container_nothrow(_In_opt_ HANDLE token, bool& value)
{
DWORD isAppContainer = 0;
DWORD returnLength = 0;
RETURN_IF_WIN32_BOOL_FALSE(::GetTokenInformation(
token ? token : GetCurrentThreadEffectiveToken(),
TokenIsAppContainer,
&isAppContainer,
sizeof(isAppContainer),
&returnLength));
value = (isAppContainer != 0);
return S_OK;
}
//! A variant of get_token_is_app_container_nothrow that fails-fast on errors retrieving the token information
inline bool get_token_is_app_container_failfast(HANDLE token = nullptr)
{
bool value = false;
FAIL_FAST_IF_FAILED(get_token_is_app_container_nothrow(token, value));
return value;
}
#ifdef WIL_ENABLE_EXCEPTIONS
//! A variant of get_token_is_app_container_nothrow that throws on errors retrieving the token information
inline bool get_token_is_app_container(HANDLE token = nullptr)
{
bool value = false;
THROW_IF_FAILED(get_token_is_app_container_nothrow(token, value));
return value;
}
#endif // WIL_ENABLE_EXCEPTIONS
#endif // _WIN32_WINNT >= _WIN32_WINNT_WIN8
template<typename... Ts> bool test_token_membership_failfast(_In_opt_ HANDLE token,
const SID_IDENTIFIER_AUTHORITY& sidAuthority, Ts&&... subAuthorities)
{
bool result;
FAIL_FAST_IF_FAILED(test_token_membership_nothrow(&result, token, sidAuthority, wistd::forward<Ts>(subAuthorities)...));
return result;
}
#ifdef WIL_ENABLE_EXCEPTIONS
template<typename... Ts> bool test_token_membership(_In_opt_ HANDLE token, const SID_IDENTIFIER_AUTHORITY& sidAuthority,
Ts&&... subAuthorities)
{
bool result;
THROW_IF_FAILED(test_token_membership_nothrow(&result, token, sidAuthority, wistd::forward<Ts>(subAuthorities)...));
return result;
}
#endif
} //namespace wil
#endif // __WIL_TOKEN_HELPERS_INCLUDED

@ -0,0 +1,612 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
//*********************************************************
#ifndef __WIL_WIN32_HELPERS_INCLUDED
#define __WIL_WIN32_HELPERS_INCLUDED
#include <minwindef.h> // FILETIME, HINSTANCE
#include <sysinfoapi.h> // GetSystemTimeAsFileTime
#include <libloaderapi.h> // GetProcAddress
#include <Psapi.h> // GetModuleFileNameExW (macro), K32GetModuleFileNameExW
#include <PathCch.h>
#include <objbase.h>
#include "result.h"
#include "resource.h"
#include "wistd_functional.h"
#include "wistd_type_traits.h"
namespace wil
{
//! Strictly a function of the file system but this is the value for all known file system, NTFS, FAT.
//! CDFs has a limit of 254.
size_t const max_path_segment_length = 255;
//! Character length not including the null, MAX_PATH (260) includes the null.
size_t const max_path_length = 259;
//! 32743 Character length not including the null. This is a system defined limit.
//! The 24 is for the expansion of the roots from "C:" to "\Device\HarddiskVolume4"
//! It will be 25 when there are more than 9 disks.
size_t const max_extended_path_length = 0x7FFF - 24;
//! For {guid} string form. Includes space for the null terminator.
size_t const guid_string_buffer_length = 39;
//! For {guid} string form. Not including the null terminator.
size_t const guid_string_length = 38;
#pragma region FILETIME helpers
// FILETIME duration values. FILETIME is in 100 nanosecond units.
namespace filetime_duration
{
long long const one_millisecond = 10000LL;
long long const one_second = 10000000LL;
long long const one_minute = 10000000LL * 60; // 600000000 or 600000000LL
long long const one_hour = 10000000LL * 60 * 60; // 36000000000 or 36000000000LL
long long const one_day = 10000000LL * 60 * 60 * 24; // 864000000000 or 864000000000LL
};
namespace filetime
{
constexpr unsigned long long to_int64(const FILETIME &ft)
{
// Cannot reinterpret_cast FILETIME* to unsigned long long*
// due to alignment differences.
return (static_cast<unsigned long long>(ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
}
inline FILETIME from_int64(unsigned long long i64)
{
static_assert(sizeof(i64) == sizeof(FILETIME), "sizes don't match");
static_assert(__alignof(unsigned long long) >= __alignof(FILETIME), "alignment not compatible with type pun");
return *reinterpret_cast<FILETIME *>(&i64);
}
inline FILETIME add(_In_ FILETIME const &ft, long long delta100ns)
{
return from_int64(to_int64(ft) + delta100ns);
}
constexpr bool is_empty(const FILETIME &ft)
{
return (ft.dwHighDateTime == 0) && (ft.dwLowDateTime == 0);
}
inline FILETIME get_system_time()
{
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
return ft;
}
/// Convert time as units of 100 nanoseconds to milliseconds. Fractional milliseconds are truncated.
constexpr unsigned long long convert_100ns_to_msec(unsigned long long time100ns)
{
return time100ns / filetime_duration::one_millisecond;
}
/// Convert time as milliseconds to units of 100 nanoseconds.
constexpr unsigned long long convert_msec_to_100ns(unsigned long long timeMsec)
{
return timeMsec * filetime_duration::one_millisecond;
}
#if defined(_APISETREALTIME_)
/// Returns the current unbiased interrupt-time count, in units of 100 nanoseconds. The unbiased interrupt-time count does not include time the system spends in sleep or hibernation.
///
/// This API avoids prematurely shortcircuiting timing loops due to system sleep/hibernation.
///
/// This is equivalent to GetTickCount64() except it returns units of 100 nanoseconds instead of milliseconds, and it doesn't include time the system spends in sleep or hibernation.
/// For example
///
/// start = GetTickCount64();
/// hibernate();
/// ...wake from hibernation 30 minutes later...;
/// elapsed = GetTickCount64() - start;
/// // elapsed = 30min
///
/// Do the same using unbiased interrupt-time and elapsed is 0 (or nearly so).
///
/// @note This is identical to QueryUnbiasedInterruptTime() but returns the value as a return value (rather than an out parameter).
/// @see https://msdn.microsoft.com/en-us/library/windows/desktop/ee662307(v=vs.85).aspx
inline unsigned long long QueryUnbiasedInterruptTimeAs100ns()
{
ULONGLONG now{};
QueryUnbiasedInterruptTime(&now);
return now;
}
/// Returns the current unbiased interrupt-time count, in units of milliseconds. The unbiased interrupt-time count does not include time the system spends in sleep or hibernation.
/// @see QueryUnbiasedInterruptTimeAs100ns
inline unsigned long long QueryUnbiasedInterruptTimeAsMSec()
{
return convert_100ns_to_msec(QueryUnbiasedInterruptTimeAs100ns());
}
#endif // _APISETREALTIME_
}
#pragma endregion
// Use to adapt Win32 APIs that take a fixed size buffer into forms that return
// an allocated buffer. Supports many types of string representation.
// See comments below on the expected behavior of the callback.
// Adjust stackBufferLength based on typical result sizes to optimize use and
// to test the boundary cases.
template <typename string_type, size_t stackBufferLength = 256>
HRESULT AdaptFixedSizeToAllocatedResult(string_type& result, wistd::function<HRESULT(PWSTR, size_t, size_t*)> callback)
{
details::string_maker<string_type> maker;
wchar_t value[stackBufferLength];
value[0] = L'\0';
size_t valueLengthNeededWithNull{}; // callback returns the number of characters needed including the null terminator.
RETURN_IF_FAILED_EXPECTED(callback(value, ARRAYSIZE(value), &valueLengthNeededWithNull));
WI_ASSERT(valueLengthNeededWithNull > 0);
if (valueLengthNeededWithNull <= ARRAYSIZE(value))
{
// Success case as described above, make() adds the space for the null.
RETURN_IF_FAILED(maker.make(value, valueLengthNeededWithNull - 1));
}
else
{
// Did not fit in the stack allocated buffer, need to do 2 phase construction.
// May need to loop more than once if external conditions cause the value to change.
size_t bufferLength;
do
{
bufferLength = valueLengthNeededWithNull;
// bufferLength includes the null so subtract that as make() will add space for it.
RETURN_IF_FAILED(maker.make(nullptr, bufferLength - 1));
RETURN_IF_FAILED_EXPECTED(callback(maker.buffer(), bufferLength, &valueLengthNeededWithNull));
WI_ASSERT(valueLengthNeededWithNull > 0);
// If the value shrunk, then adjust the string to trim off the excess buffer.
if (valueLengthNeededWithNull < bufferLength)
{
RETURN_IF_FAILED(maker.trim_at_existing_null(valueLengthNeededWithNull - 1));
}
}
while (valueLengthNeededWithNull > bufferLength);
}
result = maker.release();
return S_OK;
}
/** Expands the '%' quoted environment variables in 'input' using ExpandEnvironmentStringsW(); */
template <typename string_type, size_t stackBufferLength = 256>
HRESULT ExpandEnvironmentStringsW(_In_ PCWSTR input, string_type& result) WI_NOEXCEPT
{
return wil::AdaptFixedSizeToAllocatedResult<string_type, stackBufferLength>(result,
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNul) -> HRESULT
{
*valueLengthNeededWithNul = ::ExpandEnvironmentStringsW(input, value, static_cast<DWORD>(valueLength));
RETURN_LAST_ERROR_IF(*valueLengthNeededWithNul == 0);
return S_OK;
});
}
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES)
/** Searches for a specified file in a specified path using ExpandEnvironmentStringsW(); */
template <typename string_type, size_t stackBufferLength = 256>
HRESULT SearchPathW(_In_opt_ PCWSTR path, _In_ PCWSTR fileName, _In_opt_ PCWSTR extension, string_type& result) WI_NOEXCEPT
{
return wil::AdaptFixedSizeToAllocatedResult<string_type, stackBufferLength>(result,
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNul) -> HRESULT
{
*valueLengthNeededWithNul = ::SearchPathW(path, fileName, extension, static_cast<DWORD>(valueLength), value, nullptr);
if (*valueLengthNeededWithNul == 0)
{
// ERROR_FILE_NOT_FOUND is an expected return value for SearchPathW
const HRESULT searchResult = HRESULT_FROM_WIN32(::GetLastError());
RETURN_HR_IF_EXPECTED(searchResult, searchResult == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
RETURN_IF_FAILED(searchResult);
}
// AdaptFixedSizeToAllocatedResult expects that the length will always include the NUL.
// If the result is copied to the buffer, SearchPathW returns the length of copied string, WITHOUT the NUL.
// If the buffer is too small to hold the result, SearchPathW returns the length of the required buffer WITH the nul.
if (*valueLengthNeededWithNul < valueLength)
{
(*valueLengthNeededWithNul)++; // It fit, account for the null.
}
return S_OK;
});
}
// This function does not work beyond the default stack buffer size (255).
// Needs to to retry in a loop similar to wil::GetModuleFileNameExW
// These updates and unit tests are tracked by https://github.com/Microsoft/wil/issues/3
template <typename string_type, size_t stackBufferLength = 256>
HRESULT QueryFullProcessImageNameW(HANDLE processHandle, _In_ DWORD flags, string_type& result) WI_NOEXCEPT
{
return wil::AdaptFixedSizeToAllocatedResult<string_type, stackBufferLength>(result,
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNul) -> HRESULT
{
DWORD lengthToUse = static_cast<DWORD>(valueLength);
BOOL const success = ::QueryFullProcessImageNameW(processHandle, flags, value, &lengthToUse);
RETURN_LAST_ERROR_IF((success == FALSE) && (::GetLastError() != ERROR_INSUFFICIENT_BUFFER));
// On both success or insufficient buffer case, add +1 for the null-terminating character
*valueLengthNeededWithNul = lengthToUse + 1;
return S_OK;
});
}
/** Expands environment strings and checks path existence with SearchPathW */
template <typename string_type, size_t stackBufferLength = 256>
HRESULT ExpandEnvAndSearchPath(_In_ PCWSTR input, string_type& result) WI_NOEXCEPT
{
wil::unique_cotaskmem_string expandedName;
RETURN_IF_FAILED((wil::ExpandEnvironmentStringsW<string_type, stackBufferLength>(input, expandedName)));
// ERROR_FILE_NOT_FOUND is an expected return value for SearchPathW
const HRESULT searchResult = (wil::SearchPathW<string_type, stackBufferLength>(nullptr, expandedName.get(), nullptr, result));
RETURN_HR_IF_EXPECTED(searchResult, searchResult == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
RETURN_IF_FAILED(searchResult);
return S_OK;
}
#endif
/** Looks up the environment variable 'key' and fails if it is not found. */
template <typename string_type>
inline HRESULT GetEnvironmentVariableW(_In_ PCWSTR key, string_type& result) WI_NOEXCEPT
{
return wil::AdaptFixedSizeToAllocatedResult(result,
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNul) -> HRESULT
{
// If the function succeeds, the return value is the number of characters stored in the buffer
// pointed to by lpBuffer, not including the terminating null character.
//
// If lpBuffer is not large enough to hold the data, the return value is the buffer size, in
// characters, required to hold the string and its terminating null character and the contents of
// lpBuffer are undefined.
//
// If the function fails, the return value is zero. If the specified environment variable was not
// found in the environment block, GetLastError returns ERROR_ENVVAR_NOT_FOUND.
::SetLastError(ERROR_SUCCESS);
*valueLengthNeededWithNul = ::GetEnvironmentVariableW(key, value, static_cast<DWORD>(valueLength));
RETURN_LAST_ERROR_IF_EXPECTED((*valueLengthNeededWithNul == 0) && (::GetLastError() != ERROR_SUCCESS));
if (*valueLengthNeededWithNul < valueLength)
{
(*valueLengthNeededWithNul)++; // It fit, account for the null.
}
return S_OK;
});
}
/** Looks up the environment variable 'key' and returns null if it is not found. */
template <typename string_type>
HRESULT TryGetEnvironmentVariableW(_In_ PCWSTR key, string_type& result) WI_NOEXCEPT
{
const auto hr = wil::GetEnvironmentVariableW<string_type>(key, result);
RETURN_HR_IF(hr, FAILED(hr) && (hr != HRESULT_FROM_WIN32(ERROR_ENVVAR_NOT_FOUND)));
return S_OK;
}
/** Retrieves the fully qualified path for the file containing the specified module loaded
by a given process. Note GetModuleFileNameExW is a macro.*/
template <typename string_type, size_t initialBufferLength = 128>
HRESULT GetModuleFileNameExW(_In_opt_ HANDLE process, _In_opt_ HMODULE module, string_type& path)
{
// initialBufferLength is a template parameter to allow for testing. It creates some waste for
// shorter paths, but avoids iteration through the loop in common cases where paths are less
// than 128 characters.
// wil::max_extended_path_length + 1 (for the null char)
// + 1 (to be certain GetModuleFileNameExW didn't truncate)
size_t const ensureNoTrucation = (process != nullptr) ? 1 : 0;
size_t const maxExtendedPathLengthWithNull = wil::max_extended_path_length + 1 + ensureNoTrucation;
details::string_maker<string_type> maker;
for (size_t lengthWithNull = initialBufferLength;
lengthWithNull <= maxExtendedPathLengthWithNull;
lengthWithNull = (wistd::min)(lengthWithNull * 2, maxExtendedPathLengthWithNull))
{
// make() adds space for the trailing null
RETURN_IF_FAILED(maker.make(nullptr, lengthWithNull - 1));
DWORD copiedCount;
bool copyFailed;
bool copySucceededWithNoTruncation;
if (process != nullptr)
{
// GetModuleFileNameExW truncates and provides no error or other indication it has done so.
// The only way to be sure it didn't truncate is if it didn't need the whole buffer.
copiedCount = ::GetModuleFileNameExW(process, module, maker.buffer(), static_cast<DWORD>(lengthWithNull));
copyFailed = (0 == copiedCount);
copySucceededWithNoTruncation = !copyFailed && (copiedCount < lengthWithNull - 1);
}
else
{
// In cases of insufficient buffer, GetModuleFileNameW will return a value equal to lengthWithNull
// and set the last error to ERROR_INSUFFICIENT_BUFFER.
copiedCount = ::GetModuleFileNameW(module, maker.buffer(), static_cast<DWORD>(lengthWithNull));
copyFailed = (0 == copiedCount);
copySucceededWithNoTruncation = !copyFailed && (copiedCount < lengthWithNull);
}
if (copyFailed)
{
RETURN_LAST_ERROR();
}
else if (copySucceededWithNoTruncation)
{
path = maker.release();
return S_OK;
}
WI_ASSERT((process != nullptr) || (::GetLastError() == ERROR_INSUFFICIENT_BUFFER));
if (lengthWithNull == maxExtendedPathLengthWithNull)
{
// If we've reached this point, there's no point in trying a larger buffer size.
break;
}
}
// Any path should fit into the maximum max_extended_path_length. If we reached here, something went
// terribly wrong.
FAIL_FAST();
}
/** Retrieves the fully qualified path for the file that contains the specified module.
The module must have been loaded by the current process. The path returned will use the
same format that was specified when the module was loaded. Therefore, the path can be a
long or short file name, and can have the prefix '\\?\'. */
template <typename string_type, size_t initialBufferLength = 128>
HRESULT GetModuleFileNameW(HMODULE module, string_type& path)
{
return wil::GetModuleFileNameExW<string_type, initialBufferLength>(nullptr, module, path);
}
template <typename string_type, size_t stackBufferLength = 256>
HRESULT GetSystemDirectoryW(string_type& result) WI_NOEXCEPT
{
return wil::AdaptFixedSizeToAllocatedResult<string_type, stackBufferLength>(result,
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNul) -> HRESULT
{
*valueLengthNeededWithNul = ::GetSystemDirectoryW(value, static_cast<DWORD>(valueLength));
RETURN_LAST_ERROR_IF(*valueLengthNeededWithNul == 0);
if (*valueLengthNeededWithNul < valueLength)
{
(*valueLengthNeededWithNul)++; // it fit, account for the null
}
return S_OK;
});
}
#ifdef WIL_ENABLE_EXCEPTIONS
/** Expands the '%' quoted environment variables in 'input' using ExpandEnvironmentStringsW(); */
template <typename string_type = wil::unique_cotaskmem_string, size_t stackBufferLength = 256>
string_type ExpandEnvironmentStringsW(_In_ PCWSTR input)
{
string_type result;
THROW_IF_FAILED((wil::ExpandEnvironmentStringsW<string_type, stackBufferLength>(input, result)));
return result;
}
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES)
/** Searches for a specified file in a specified path using SearchPathW*/
template <typename string_type = wil::unique_cotaskmem_string, size_t stackBufferLength = 256>
string_type TrySearchPathW(_In_opt_ PCWSTR path, _In_ PCWSTR fileName, PCWSTR _In_opt_ extension)
{
string_type result;
HRESULT searchHR = wil::SearchPathW<string_type, stackBufferLength>(path, fileName, extension, result);
THROW_HR_IF(searchHR, FAILED(searchHR) && (searchHR != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)));
return result;
}
#endif
/** Looks up the environment variable 'key' and fails if it is not found. */
template <typename string_type = wil::unique_cotaskmem_string>
string_type GetEnvironmentVariableW(_In_ PCWSTR key)
{
string_type result;
THROW_IF_FAILED(wil::GetEnvironmentVariableW<string_type>(key, result));
return result;
}
/** Looks up the environment variable 'key' and returns null if it is not found. */
template <typename string_type = wil::unique_cotaskmem_string>
string_type TryGetEnvironmentVariableW(_In_ PCWSTR key)
{
string_type result;
THROW_IF_FAILED(wil::TryGetEnvironmentVariableW<string_type>(key, result));
return result;
}
template <typename string_type = wil::unique_cotaskmem_string>
string_type GetModuleFileNameW(HMODULE module)
{
string_type result;
THROW_IF_FAILED(wil::GetModuleFileNameW(module, result));
return result;
}
template <typename string_type = wil::unique_cotaskmem_string>
string_type GetModuleFileNameExW(HANDLE process, HMODULE module)
{
string_type result;
THROW_IF_FAILED(wil::GetModuleFileNameExW(process, module, result));
return result;
}
#endif
/** Retrieve the HINSTANCE for the current DLL or EXE using this symbol that
the linker provides for every module. This avoids the need for a global HINSTANCE variable
and provides access to this value for static libraries. */
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
inline HINSTANCE GetModuleInstanceHandle() { return reinterpret_cast<HINSTANCE>(&__ImageBase); }
/// @cond
namespace details
{
class init_once_completer
{
INIT_ONCE& m_once;
unsigned long m_flags = INIT_ONCE_INIT_FAILED;
public:
init_once_completer(_In_ INIT_ONCE& once) : m_once(once)
{
}
#pragma warning(push)
#pragma warning(disable:4702) // https://github.com/Microsoft/wil/issues/2
void success()
{
m_flags = 0;
}
#pragma warning(pop)
~init_once_completer()
{
::InitOnceComplete(&m_once, m_flags, nullptr);
}
};
}
/// @endcond
/** Performs one-time initialization
Simplifies using the Win32 INIT_ONCE structure to perform one-time initialization. The provided `func` is invoked
at most once.
~~~~
INIT_ONCE g_init{};
ComPtr<IFoo> g_foo;
HRESULT MyMethod()
{
bool winner = false;
RETURN_IF_FAILED(wil::init_once_nothrow(g_init, []
{
ComPtr<IFoo> foo;
RETURN_IF_FAILED(::CoCreateInstance(..., IID_PPV_ARGS(&foo));
RETURN_IF_FAILED(foo->Startup());
g_foo = foo;
}, &winner);
if (winner)
{
RETURN_IF_FAILED(g_foo->Another());
}
return S_OK;
}
~~~~
See MSDN for more information on `InitOnceExecuteOnce`.
@param initOnce The INIT_ONCE structure to use as context for initialization.
@param func A function that will be invoked to perform initialization. If this fails, the init call
fails and the once-init is not marked as initialized. A later caller could attempt to
initialize it a second time.
@param callerCompleted Set to 'true' if this was the call that caused initialization, false otherwise.
*/
template<typename T> HRESULT init_once_nothrow(_Inout_ INIT_ONCE& initOnce, T func, _Out_opt_ bool* callerCompleted = nullptr) WI_NOEXCEPT
{
BOOL pending = FALSE;
wil::assign_to_opt_param(callerCompleted, false);
__WIL_PRIVATE_RETURN_IF_WIN32_BOOL_FALSE(InitOnceBeginInitialize(&initOnce, 0, &pending, nullptr));
if (pending)
{
details::init_once_completer completion(initOnce);
__WIL_PRIVATE_RETURN_IF_FAILED(func());
completion.success();
wil::assign_to_opt_param(callerCompleted, true);
}
return S_OK;
}
//! Similar to init_once_nothrow, but fails-fast if the initialization step failed. The 'callerComplete' value is
//! returned to the caller instead of being an out-parameter.
template<typename T> bool init_once_failfast(_Inout_ INIT_ONCE& initOnce, T&& func) WI_NOEXCEPT
{
bool callerCompleted;
FAIL_FAST_IF_FAILED(init_once_nothrow(initOnce, wistd::forward<T>(func), &callerCompleted));
return callerCompleted;
};
//! Returns 'true' if this `init_once` structure has finished initialization, false otherwise.
inline bool init_once_initialized(_Inout_ INIT_ONCE& initOnce) WI_NOEXCEPT
{
BOOL pending = FALSE;
return ::InitOnceBeginInitialize(&initOnce, INIT_ONCE_CHECK_ONLY, &pending, nullptr) && !pending;
}
#ifdef WIL_ENABLE_EXCEPTIONS
/** Performs one-time initialization
Simplifies using the Win32 INIT_ONCE structure to perform one-time initialization. The provided `func` is invoked
at most once.
~~~~
INIT_ONCE g_init{};
ComPtr<IFoo> g_foo;
void MyMethod()
{
bool winner = wil::init_once(g_init, []
{
ComPtr<IFoo> foo;
THROW_IF_FAILED(::CoCreateInstance(..., IID_PPV_ARGS(&foo));
THROW_IF_FAILED(foo->Startup());
g_foo = foo;
});
if (winner)
{
THROW_IF_FAILED(g_foo->Another());
}
}
~~~~
See MSDN for more information on `InitOnceExecuteOnce`.
@param initOnce The INIT_ONCE structure to use as context for initialization.
@param func A function that will be invoked to perform initialization. If this fails, the init call
fails and the once-init is not marked as initialized. A later caller could attempt to
initialize it a second time.
@returns 'true' if this was the call that caused initialization, false otherwise.
*/
template<typename T> bool init_once(_Inout_ INIT_ONCE& initOnce, T func)
{
BOOL pending = FALSE;
THROW_IF_WIN32_BOOL_FALSE(::InitOnceBeginInitialize(&initOnce, 0, &pending, nullptr));
if (pending)
{
details::init_once_completer completion(initOnce);
func();
completion.success();
return true;
}
else
{
return false;
}
}
#endif // WIL_ENABLE_EXCEPTIONS
}
// Macro for calling GetProcAddress(), with type safety for C++ clients
// using the type information from the specified function.
// The return value is automatically cast to match the function prototype of the input function.
//
// Sample usage:
//
// auto sendMail = GetProcAddressByFunctionDeclaration(hinstMAPI, MAPISendMailW);
// if (sendMail)
// {
// sendMail(0, 0, pmm, MAPI_USE_DEFAULT, 0);
// }
// Declaration
#define GetProcAddressByFunctionDeclaration(hinst, fn) reinterpret_cast<decltype(::fn)*>(GetProcAddress(hinst, #fn))
#endif // __WIL_WIN32_HELPERS_INCLUDED

File diff suppressed because it is too large Load Diff

@ -0,0 +1,548 @@
// -*- C++ -*-
//===--------------------------- __config ---------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// STL common functionality
//
// Some aspects of STL are core language concepts that should be used from all C++ code, regardless
// of whether exceptions are enabled in the component. Common library code that expects to be used
// from exception-free components want these concepts, but including STL headers directly introduces
// friction as it requires components not using STL to declare their STL version. Doing so creates
// ambiguity around whether STL use is safe in a particular component and implicitly brings in
// a long list of headers (including <new>) which can create further ambiguity around throwing new
// support (some routines pulled in may expect it). Secondarily, pulling in these headers also has
// the potential to create naming conflicts or other implied dependencies.
//
// To promote the use of these core language concepts outside of STL-based binaries, this file is
// selectively pulling those concepts *directly* from corresponding STL headers. The corresponding
// "std::" namespace STL functions and types should be preferred over these in code that is bound to
// STL. The implementation and naming of all functions are taken directly from STL, instead using
// "wistd" (Windows Implementation std) as the namespace.
//
// Routines in this namespace should always be considered a reflection of the *current* STL implementation
// of those routines. Updates from STL should be taken, but no "bugs" should be fixed here.
//
// New, exception-based code should not use this namespace, but instead should prefer the std:: implementation.
// Only code that is not exception-based and libraries that expect to be utilized across both exception
// and non-exception based code should utilize this functionality.
// This header mimics libc++'s '__config' header to the extent necessary to get the wistd::* definitions compiling. Note
// that this has a few key differences since libc++'s MSVC compatability is currently not functional and a bit behind
#ifndef _WISTD_CONFIG_H_
#define _WISTD_CONFIG_H_
// DO NOT add *any* additional includes to this file -- there should be no dependencies from its usage
#include <cstddef> // For size_t and other necessary types
/// @cond
#if defined(_MSC_VER) && !defined(__clang__)
# if !defined(__WI_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# define __WI_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
# endif
#endif
#ifndef __WI_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
#pragma GCC system_header
#endif
#ifdef __GNUC__
# define __WI_GNUC_VER (__GNUC__ * 100 + __GNUC_MINOR__)
// The __WI_GNUC_VER_NEW macro better represents the new GCC versioning scheme
// introduced in GCC 5.0.
# define __WI_GNUC_VER_NEW (__WI_GNUC_VER * 10 + __GNUC_PATCHLEVEL__)
#else
# define __WI_GNUC_VER 0
# define __WI_GNUC_VER_NEW 0
#endif
// _MSVC_LANG is the more accurate way to get the C++ version in MSVC
#if defined(_MSVC_LANG) && (_MSVC_LANG > __cplusplus)
#define __WI_CPLUSPLUS _MSVC_LANG
#else
#define __WI_CPLUSPLUS __cplusplus
#endif
#ifndef __WI_LIBCPP_STD_VER
# if __WI_CPLUSPLUS <= 201103L
# define __WI_LIBCPP_STD_VER 11
# elif __WI_CPLUSPLUS <= 201402L
# define __WI_LIBCPP_STD_VER 14
# elif __WI_CPLUSPLUS <= 201703L
# define __WI_LIBCPP_STD_VER 17
# else
# define __WI_LIBCPP_STD_VER 18 // current year, or date of c++2a ratification
# endif
#endif // __WI_LIBCPP_STD_VER
#if __WI_CPLUSPLUS < 201103L
#define __WI_LIBCPP_CXX03_LANG
#endif
#if defined(__ELF__)
# define __WI_LIBCPP_OBJECT_FORMAT_ELF 1
#elif defined(__MACH__)
# define __WI_LIBCPP_OBJECT_FORMAT_MACHO 1
#elif defined(_WIN32)
# define __WI_LIBCPP_OBJECT_FORMAT_COFF 1
#elif defined(__wasm__)
# define __WI_LIBCPP_OBJECT_FORMAT_WASM 1
#else
# error Unknown object file format
#endif
#if defined(__clang__)
# define __WI_LIBCPP_COMPILER_CLANG
#elif defined(__GNUC__)
# define __WI_LIBCPP_COMPILER_GCC
#elif defined(_MSC_VER)
# define __WI_LIBCPP_COMPILER_MSVC
#elif defined(__IBMCPP__)
# define __WI_LIBCPP_COMPILER_IBM
#endif
// NOTE: MSVC, which is what we primarily target, is severly underrepresented in libc++ and checks such as
// __has_feature(...) are always false for MSVC, even when the feature being tested _is_ present in MSVC. Therefore, we
// instead modify all checks to be __WI_HAS_FEATURE_IS_UNION, etc., which provides the correct value for MSVC and falls
// back to the __has_feature(...), etc. value otherwise. We intentionally leave '__has_feature', etc. undefined for MSVC
// so that we don't accidentally use the incorrect behavior
#ifndef __WI_LIBCPP_COMPILER_MSVC
#ifndef __has_feature
#define __has_feature(__x) 0
#endif
// '__is_identifier' returns '0' if '__x' is a reserved identifier provided by
// the compiler and '1' otherwise.
#ifndef __is_identifier
#define __is_identifier(__x) 1
#endif
#ifndef __has_cpp_attribute
#define __has_cpp_attribute(__x) 0
#endif
#ifndef __has_attribute
#define __has_attribute(__x) 0
#endif
#ifndef __has_builtin
#define __has_builtin(__x) 0
#endif
#if __has_feature(cxx_alignas)
# define __WI_ALIGNAS_TYPE(x) alignas(x)
# define __WI_ALIGNAS(x) alignas(x)
#else
# define __WI_ALIGNAS_TYPE(x) __attribute__((__aligned__(__alignof(x))))
# define __WI_ALIGNAS(x) __attribute__((__aligned__(x)))
#endif
#if __has_feature(cxx_explicit_conversions) || defined(__IBMCPP__) || \
(!defined(__WI_LIBCPP_CXX03_LANG) && defined(__GNUC__)) // All supported GCC versions
# define __WI_LIBCPP_EXPLICIT explicit
#else
# define __WI_LIBCPP_EXPLICIT
#endif
#if __has_feature(cxx_attributes)
# define __WI_LIBCPP_NORETURN [[noreturn]]
#else
# define __WI_LIBCPP_NORETURN __attribute__ ((noreturn))
#endif
#define __WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS
#define __WI_LIBCPP_SUPPRESS_NOEXCEPT_ANALYSIS
// The __WI_LIBCPP_NODISCARD_ATTRIBUTE should only be used to define other
// NODISCARD macros to the correct attribute.
#if __has_cpp_attribute(nodiscard)
# define __WI_LIBCPP_NODISCARD_ATTRIBUTE [[nodiscard]]
#elif defined(__WI_LIBCPP_COMPILER_CLANG) && !defined(__WI_LIBCPP_CXX03_LANG)
# define __WI_LIBCPP_NODISCARD_ATTRIBUTE [[clang::warn_unused_result]]
#else
// We can't use GCC's [[gnu::warn_unused_result]] and
// __attribute__((warn_unused_result)), because GCC does not silence them via
// (void) cast.
# define __WI_LIBCPP_NODISCARD_ATTRIBUTE
#endif
#define __WI_HAS_FEATURE_IS_UNION __has_feature(is_union)
#define __WI_HAS_FEATURE_IS_CLASS __has_feature(is_class)
#define __WI_HAS_FEATURE_IS_ENUM __has_feature(is_enum)
#define __WI_HAS_FEATURE_IS_CONVERTIBLE_TO __has_feature(is_convertible_to)
#define __WI_HAS_FEATURE_IS_EMPTY __has_feature(is_empty)
#define __WI_HAS_FEATURE_IS_POLYMORPHIC __has_feature(is_polymorphic)
#define __WI_HAS_FEATURE_HAS_VIRTUAL_DESTRUCTOR __has_feature(has_virtual_destructor)
#define __WI_HAS_FEATURE_REFERENCE_QUALIFIED_FUNCTIONS __has_feature(cxx_reference_qualified_functions)
#define __WI_HAS_FEATURE_IS_CONSTRUCTIBLE __has_feature(is_constructible)
#define __WI_HAS_FEATURE_IS_TRIVIALLY_CONSTRUCTIBLE __has_feature(is_trivially_constructible)
#define __WI_HAS_FEATURE_IS_TRIVIALLY_ASSIGNABLE __has_feature(is_trivially_assignable)
#define __WI_HAS_FEATURE_HAS_TRIVIAL_DESTRUCTOR __has_feature(has_trivial_destructor)
#define __WI_HAS_FEATURE_NOEXCEPT __has_feature(cxx_noexcept)
#define __WI_HAS_FEATURE_IS_POD __has_feature(is_pod)
#define __WI_HAS_FEATURE_IS_STANDARD_LAYOUT __has_feature(is_standard_layout)
#define __WI_HAS_FEATURE_IS_TRIVIALLY_COPYABLE __has_feature(is_trivially_copyable)
#define __WI_HAS_FEATURE_IS_TRIVIAL __has_feature(is_trivial)
#define __WI_HAS_FEATURE_HAS_TRIVIAL_CONSTRUCTOR __has_feature(has_trivial_constructor) || (__WI_GNUC_VER >= 403)
#define __WI_HAS_FEATURE_HAS_NOTHROW_CONSTRUCTOR __has_feature(has_nothrow_constructor) || (__WI_GNUC_VER >= 403)
#define __WI_HAS_FEATURE_HAS_NOTHROW_COPY __has_feature(has_nothrow_copy) || (__WI_GNUC_VER >= 403)
#define __WI_HAS_FEATURE_HAS_NOTHROW_ASSIGN __has_feature(has_nothrow_assign) || (__WI_GNUC_VER >= 403)
#if !(__has_feature(cxx_noexcept))
#define __WI_LIBCPP_HAS_NO_NOEXCEPT
#endif
#if !__is_identifier(__has_unique_object_representations) || __WI_GNUC_VER >= 700
#define __WI_LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS
#endif
#if !(__has_feature(cxx_variadic_templates))
#define __WI_LIBCPP_HAS_NO_VARIADICS
#endif
#if __has_feature(is_literal) || __WI_GNUC_VER >= 407
#define __WI_LIBCPP_IS_LITERAL(T) __is_literal(T)
#endif
#if __has_feature(underlying_type) || __WI_GNUC_VER >= 407
#define __WI_LIBCPP_UNDERLYING_TYPE(T) __underlying_type(T)
#endif
#if __has_feature(is_final) || __WI_GNUC_VER >= 407
#define __WI_LIBCPP_HAS_IS_FINAL
#endif
#if __has_feature(is_base_of) || defined(__GNUC__) && __WI_GNUC_VER >= 403
#define __WI_LIBCPP_HAS_IS_BASE_OF
#endif
#if __is_identifier(__is_aggregate) && (__WI_GNUC_VER_NEW < 7001)
#define __WI_LIBCPP_HAS_NO_IS_AGGREGATE
#endif
#if !(__has_feature(cxx_rtti)) && !defined(__WI_LIBCPP_NO_RTTI)
#define __WI_LIBCPP_NO_RTTI
#endif
#if !(__has_feature(cxx_variable_templates))
#define __WI_LIBCPP_HAS_NO_VARIABLE_TEMPLATES
#endif
#if !(__has_feature(cxx_relaxed_constexpr))
#define __WI_LIBCPP_HAS_NO_CXX14_CONSTEXPR
#endif
#if !__has_builtin(__builtin_addressof) && _GNUC_VER < 700
#define __WI_LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
#endif
#if __has_attribute(__no_sanitize__) && !defined(__WI_LIBCPP_COMPILER_GCC)
# define __WI_LIBCPP_NO_CFI __attribute__((__no_sanitize__("cfi")))
#else
# define __WI_LIBCPP_NO_CFI
#endif
#define __WI_LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__))
#if __has_attribute(internal_linkage)
# define __WI_LIBCPP_INTERNAL_LINKAGE __attribute__ ((internal_linkage))
#else
# define __WI_LIBCPP_INTERNAL_LINKAGE __WI_LIBCPP_ALWAYS_INLINE
#endif
#else
// NOTE: Much of the following assumes a decently recent version of MSVC. Past versions can be supported, but will need
// to be updated to contain the proper _MSC_VER check
#define __WI_ALIGNAS_TYPE(x) alignas(x)
#define __WI_ALIGNAS(x) alignas(x)
#define __alignof__ __alignof
#define __WI_LIBCPP_EXPLICIT explicit
#define __WI_LIBCPP_NORETURN [[noreturn]]
#define __WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS __pragma(warning(suppress:26495))
#define __WI_LIBCPP_SUPPRESS_NOEXCEPT_ANALYSIS __pragma(warning(suppress:26439))
#if __WI_LIBCPP_STD_VER > 14
#define __WI_LIBCPP_NODISCARD_ATTRIBUTE [[nodiscard]]
#else
#define __WI_LIBCPP_NODISCARD_ATTRIBUTE _Check_return_
#endif
#define __WI_HAS_FEATURE_IS_UNION 1
#define __WI_HAS_FEATURE_IS_CLASS 1
#define __WI_HAS_FEATURE_IS_ENUM 1
#define __WI_HAS_FEATURE_IS_CONVERTIBLE_TO 1
#define __WI_HAS_FEATURE_IS_EMPTY 1
#define __WI_HAS_FEATURE_IS_POLYMORPHIC 1
#define __WI_HAS_FEATURE_HAS_VIRTUAL_DESTRUCTOR 1
#define __WI_LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS 1
#define __WI_HAS_FEATURE_REFERENCE_QUALIFIED_FUNCTIONS 1
#define __WI_HAS_FEATURE_IS_CONSTRUCTIBLE 1
#define __WI_HAS_FEATURE_IS_TRIVIALLY_CONSTRUCTIBLE 1
#define __WI_HAS_FEATURE_IS_TRIVIALLY_ASSIGNABLE 1
#define __WI_HAS_FEATURE_HAS_TRIVIAL_DESTRUCTOR 1
#define __WI_HAS_FEATURE_NOEXCEPT 1
#define __WI_HAS_FEATURE_IS_POD 1
#define __WI_HAS_FEATURE_IS_STANDARD_LAYOUT 1
#define __WI_HAS_FEATURE_IS_TRIVIALLY_COPYABLE 1
#define __WI_HAS_FEATURE_IS_TRIVIAL 1
#define __WI_HAS_FEATURE_HAS_TRIVIAL_CONSTRUCTOR 1
#define __WI_HAS_FEATURE_HAS_NOTHROW_CONSTRUCTOR 1
#define __WI_HAS_FEATURE_HAS_NOTHROW_COPY 1
#define __WI_HAS_FEATURE_HAS_NOTHROW_ASSIGN 1
#define __WI_HAS_FEATURE_IS_DESTRUCTIBLE 1
#if !defined(_CPPRTTI) && !defined(__WI_LIBCPP_NO_RTTI)
#define __WI_LIBCPP_NO_RTTI
#endif
#define __WI_LIBCPP_IS_LITERAL(T) __is_literal_type(T)
#define __WI_LIBCPP_UNDERLYING_TYPE(T) __underlying_type(T)
#define __WI_LIBCPP_HAS_IS_FINAL
#define __WI_LIBCPP_HAS_IS_BASE_OF
#if __WI_LIBCPP_STD_VER < 14
#define __WI_LIBCPP_HAS_NO_VARIABLE_TEMPLATES
#endif
#define __WI_LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
#define __WI_LIBCPP_NO_CFI
#define __WI_LIBCPP_ALWAYS_INLINE __forceinline
#define __WI_LIBCPP_INTERNAL_LINKAGE
#endif
#ifndef _WIN32
#ifdef __LITTLE_ENDIAN__
# if __LITTLE_ENDIAN__
# define __WI_LIBCPP_LITTLE_ENDIAN
# endif // __LITTLE_ENDIAN__
#endif // __LITTLE_ENDIAN__
#ifdef __BIG_ENDIAN__
# if __BIG_ENDIAN__
# define __WI_LIBCPP_BIG_ENDIAN
# endif // __BIG_ENDIAN__
#endif // __BIG_ENDIAN__
#ifdef __BYTE_ORDER__
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define __WI_LIBCPP_LITTLE_ENDIAN
# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define __WI_LIBCPP_BIG_ENDIAN
# endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#endif // __BYTE_ORDER__
#if !defined(__WI_LIBCPP_LITTLE_ENDIAN) && !defined(__WI_LIBCPP_BIG_ENDIAN)
# include <endian.h>
# if __BYTE_ORDER == __LITTLE_ENDIAN
# define __WI_LIBCPP_LITTLE_ENDIAN
# elif __BYTE_ORDER == __BIG_ENDIAN
# define __WI_LIBCPP_BIG_ENDIAN
# else // __BYTE_ORDER == __BIG_ENDIAN
# error unable to determine endian
# endif
#endif // !defined(__WI_LIBCPP_LITTLE_ENDIAN) && !defined(__WI_LIBCPP_BIG_ENDIAN)
#else // _WIN32
#define __WI_LIBCPP_LITTLE_ENDIAN
#endif // _WIN32
#ifdef __WI_LIBCPP_HAS_NO_CONSTEXPR
# define __WI_LIBCPP_CONSTEXPR
#else
# define __WI_LIBCPP_CONSTEXPR constexpr
#endif
#if __WI_LIBCPP_STD_VER > 11 && !defined(__WI_LIBCPP_HAS_NO_CXX14_CONSTEXPR)
# define __WI_LIBCPP_CONSTEXPR_AFTER_CXX11 constexpr
#else
# define __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
#endif
#if __WI_LIBCPP_STD_VER > 14 && !defined(__WI_LIBCPP_HAS_NO_CXX14_CONSTEXPR)
# define __WI_LIBCPP_CONSTEXPR_AFTER_CXX14 constexpr
#else
# define __WI_LIBCPP_CONSTEXPR_AFTER_CXX14
#endif
#if __WI_LIBCPP_STD_VER > 17 && !defined(__WI_LIBCPP_HAS_NO_CXX14_CONSTEXPR)
# define __WI_LIBCPP_CONSTEXPR_AFTER_CXX17 constexpr
#else
# define __WI_LIBCPP_CONSTEXPR_AFTER_CXX17
#endif
#if !defined(__WI_LIBCPP_DISABLE_NODISCARD_AFTER_CXX17) && \
(__WI_LIBCPP_STD_VER > 17 || defined(__WI_LIBCPP_ENABLE_NODISCARD))
# define __WI_LIBCPP_NODISCARD_AFTER_CXX17 __WI_LIBCPP_NODISCARD_ATTRIBUTE
#else
# define __WI_LIBCPP_NODISCARD_AFTER_CXX17
#endif
#if __WI_LIBCPP_STD_VER > 14 && defined(__cpp_inline_variables) && (__cpp_inline_variables >= 201606L)
# define __WI_LIBCPP_INLINE_VAR inline
#else
# define __WI_LIBCPP_INLINE_VAR
#endif
#ifdef __WI_LIBCPP_CXX03_LANG
#define __WI_LIBCPP_HAS_NO_UNICODE_CHARS
#define __WI_LIBCPP_HAS_NO_RVALUE_REFERENCES
#endif
#ifndef __SIZEOF_INT128__
#define __WI_LIBCPP_HAS_NO_INT128
#endif
#if !__WI_HAS_FEATURE_NOEXCEPT && !defined(__WI_LIBCPP_HAS_NO_NOEXCEPT)
#define __WI_LIBCPP_HAS_NO_NOEXCEPT
#endif
#ifndef __WI_LIBCPP_HAS_NO_NOEXCEPT
# define WI_NOEXCEPT noexcept
# define __WI_NOEXCEPT_(x) noexcept(x)
#else
# define WI_NOEXCEPT throw()
# define __WI_NOEXCEPT_(x)
#endif
#if defined(__WI_LIBCPP_OBJECT_FORMAT_COFF)
#define __WI_LIBCPP_HIDDEN
#define __WI_LIBCPP_TEMPLATE_VIS
#endif // defined(__WI_LIBCPP_OBJECT_FORMAT_COFF)
#ifndef __WI_LIBCPP_HIDDEN
# if !defined(__WI_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
# define __WI_LIBCPP_HIDDEN __attribute__ ((__visibility__("hidden")))
# else
# define __WI_LIBCPP_HIDDEN
# endif
#endif
#ifndef __WI_LIBCPP_TEMPLATE_VIS
# if !defined(__WI_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) && !defined(__WI_LIBCPP_COMPILER_MSVC)
# if __has_attribute(__type_visibility__)
# define __WI_LIBCPP_TEMPLATE_VIS __attribute__ ((__type_visibility__("default")))
# else
# define __WI_LIBCPP_TEMPLATE_VIS __attribute__ ((__visibility__("default")))
# endif
# else
# define __WI_LIBCPP_TEMPLATE_VIS
# endif
#endif
#define __WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_HIDDEN __WI_LIBCPP_INTERNAL_LINKAGE
namespace wistd // ("Windows Implementation" std)
{
typedef decltype(__nullptr) nullptr_t;
template <class _T1, class _T2 = _T1>
struct __less
{
__WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;}
__WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
bool operator()(const _T1& __x, const _T2& __y) const {return __x < __y;}
__WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
bool operator()(const _T2& __x, const _T1& __y) const {return __x < __y;}
__WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
bool operator()(const _T2& __x, const _T2& __y) const {return __x < __y;}
};
template <class _T1>
struct __less<_T1, _T1>
{
__WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;}
};
template <class _T1>
struct __less<const _T1, _T1>
{
__WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;}
};
template <class _T1>
struct __less<_T1, const _T1>
{
__WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;}
};
// These are added to wistd to enable use of min/max without having to use the windows.h min/max
// macros that some clients might not have access to. Note: the STL versions of these have debug
// checking for the less than operator and support for iterators that these implementations lack.
// Use the STL versions when you require use of those features.
// min
template <class _Tp, class _Compare>
inline __WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
const _Tp&
(min)(const _Tp& __a, const _Tp& __b, _Compare __comp)
{
return __comp(__b, __a) ? __b : __a;
}
template <class _Tp>
inline __WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
const _Tp&
(min)(const _Tp& __a, const _Tp& __b)
{
return (min)(__a, __b, __less<_Tp>());
}
// max
template <class _Tp, class _Compare>
inline __WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
const _Tp&
(max)(const _Tp& __a, const _Tp& __b, _Compare __comp)
{
return __comp(__a, __b) ? __b : __a;
}
template <class _Tp>
inline __WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_CONSTEXPR_AFTER_CXX11
const _Tp&
(max)(const _Tp& __a, const _Tp& __b)
{
return (max)(__a, __b, __less<_Tp>());
}
template <class _Arg, class _Result>
struct __WI_LIBCPP_TEMPLATE_VIS unary_function
{
typedef _Arg argument_type;
typedef _Result result_type;
};
template <class _Arg1, class _Arg2, class _Result>
struct __WI_LIBCPP_TEMPLATE_VIS binary_function
{
typedef _Arg1 first_argument_type;
typedef _Arg2 second_argument_type;
typedef _Result result_type;
};
}
/// @endcond
#endif _WISTD_CONFIG_H_

@ -0,0 +1,544 @@
// -*- C++ -*-
//===------------------------ functional ----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// STL common functionality
//
// Some aspects of STL are core language concepts that should be used from all C++ code, regardless
// of whether exceptions are enabled in the component. Common library code that expects to be used
// from exception-free components want these concepts, but including STL headers directly introduces
// friction as it requires components not using STL to declare their STL version. Doing so creates
// ambiguity around whether STL use is safe in a particular component and implicitly brings in
// a long list of headers (including <new>) which can create further ambiguity around throwing new
// support (some routines pulled in may expect it). Secondarily, pulling in these headers also has
// the potential to create naming conflicts or other implied dependencies.
//
// To promote the use of these core language concepts outside of STL-based binaries, this file is
// selectively pulling those concepts *directly* from corresponding STL headers. The corresponding
// "std::" namespace STL functions and types should be preferred over these in code that is bound to
// STL. The implementation and naming of all functions are taken directly from STL, instead using
// "wistd" (Windows Implementation std) as the namespace.
//
// Routines in this namespace should always be considered a reflection of the *current* STL implementation
// of those routines. Updates from STL should be taken, but no "bugs" should be fixed here.
//
// New, exception-based code should not use this namespace, but instead should prefer the std:: implementation.
// Only code that is not exception-based and libraries that expect to be utilized across both exception
// and non-exception based code should utilize this functionality.
#ifndef _WISTD_FUNCTIONAL_H_
#define _WISTD_FUNCTIONAL_H_
// DO NOT add *any* additional includes to this file -- there should be no dependencies from its usage
#include "wistd_memory.h"
#include <intrin.h> // For __fastfail
#include <new.h> // For placement new
#if !defined(__WI_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif
#pragma warning(push)
#pragma warning(disable: 4324)
#pragma warning(disable: 4800)
/// @cond
namespace wistd // ("Windows Implementation" std)
{
// wistd::function
//
// All of the code below is in direct support of wistd::function. This class is identical to std::function
// with the following exceptions:
//
// 1) It never allocates and is safe to use from exception-free code (custom allocators are not supported)
// 2) It's slightly bigger on the stack (64 bytes, rather than 24 for 32bit)
// 3) There is an explicit static-assert if a lambda becomes too large to hold in the internal buffer (rather than an allocation)
template <class _Ret>
struct __invoke_void_return_wrapper
{
#ifndef __WI_LIBCPP_CXX03_LANG
template <class ..._Args>
static _Ret __call(_Args&&... __args) {
return __invoke(wistd::forward<_Args>(__args)...);
}
#else
template <class _Fn>
static _Ret __call(_Fn __f) {
return __invoke(__f);
}
template <class _Fn, class _A0>
static _Ret __call(_Fn __f, _A0& __a0) {
return __invoke(__f, __a0);
}
template <class _Fn, class _A0, class _A1>
static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1) {
return __invoke(__f, __a0, __a1);
}
template <class _Fn, class _A0, class _A1, class _A2>
static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2){
return __invoke(__f, __a0, __a1, __a2);
}
#endif
};
template <>
struct __invoke_void_return_wrapper<void>
{
#ifndef __WI_LIBCPP_CXX03_LANG
template <class ..._Args>
static void __call(_Args&&... __args) {
(void)__invoke(wistd::forward<_Args>(__args)...);
}
#else
template <class _Fn>
static void __call(_Fn __f) {
__invoke(__f);
}
template <class _Fn, class _A0>
static void __call(_Fn __f, _A0& __a0) {
__invoke(__f, __a0);
}
template <class _Fn, class _A0, class _A1>
static void __call(_Fn __f, _A0& __a0, _A1& __a1) {
__invoke(__f, __a0, __a1);
}
template <class _Fn, class _A0, class _A1, class _A2>
static void __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2) {
__invoke(__f, __a0, __a1, __a2);
}
#endif
};
////////////////////////////////////////////////////////////////////////////////
// FUNCTION
//==============================================================================
// bad_function_call
__WI_LIBCPP_NORETURN inline __WI_LIBCPP_INLINE_VISIBILITY
void __throw_bad_function_call()
{
__fastfail(7); // FAST_FAIL_FATAL_APP_EXIT
}
template<class _Fp> class __WI_LIBCPP_TEMPLATE_VIS function; // undefined
namespace __function
{
template<class _Rp>
struct __maybe_derive_from_unary_function
{
};
template<class _Rp, class _A1>
struct __maybe_derive_from_unary_function<_Rp(_A1)>
: public unary_function<_A1, _Rp>
{
};
template<class _Rp>
struct __maybe_derive_from_binary_function
{
};
template<class _Rp, class _A1, class _A2>
struct __maybe_derive_from_binary_function<_Rp(_A1, _A2)>
: public binary_function<_A1, _A2, _Rp>
{
};
template <class _Fp>
__WI_LIBCPP_INLINE_VISIBILITY
bool __not_null(_Fp const&) { return true; }
template <class _Fp>
__WI_LIBCPP_INLINE_VISIBILITY
bool __not_null(_Fp* __ptr) { return __ptr; }
template <class _Ret, class _Class>
__WI_LIBCPP_INLINE_VISIBILITY
bool __not_null(_Ret _Class::*__ptr) { return __ptr; }
template <class _Fp>
__WI_LIBCPP_INLINE_VISIBILITY
bool __not_null(function<_Fp> const& __f) { return !!__f; }
} // namespace __function
#ifndef __WI_LIBCPP_CXX03_LANG
namespace __function {
template<class _Fp> class __base;
template<class _Rp, class ..._ArgTypes>
class __base<_Rp(_ArgTypes...)>
{
__base(const __base&);
__base& operator=(const __base&);
public:
__WI_LIBCPP_INLINE_VISIBILITY __base() {}
__WI_LIBCPP_INLINE_VISIBILITY virtual ~__base() {}
virtual void __clone(__base*) const = 0;
virtual void __move(__base*) = 0;
virtual void destroy() WI_NOEXCEPT = 0;
virtual _Rp operator()(_ArgTypes&& ...) = 0;
};
template<class _FD, class _FB> class __func;
template<class _Fp, class _Rp, class ..._ArgTypes>
class __func<_Fp, _Rp(_ArgTypes...)>
: public __base<_Rp(_ArgTypes...)>
{
_Fp __f_;
public:
__WI_LIBCPP_INLINE_VISIBILITY
explicit __func(_Fp&& __f)
: __f_(wistd::move(__f)) {}
__WI_LIBCPP_INLINE_VISIBILITY
explicit __func(const _Fp& __f)
: __f_(__f) {}
virtual void __clone(__base<_Rp(_ArgTypes...)>*) const;
virtual void __move(__base<_Rp(_ArgTypes...)>*);
virtual void destroy() WI_NOEXCEPT;
virtual _Rp operator()(_ArgTypes&& ... __arg);
};
template<class _Fp, class _Rp, class ..._ArgTypes>
void
__func<_Fp, _Rp(_ArgTypes...)>::__clone(__base<_Rp(_ArgTypes...)>* __p) const
{
::new (__p) __func(__f_);
}
template<class _Fp, class _Rp, class ..._ArgTypes>
void
__func<_Fp, _Rp(_ArgTypes...)>::__move(__base<_Rp(_ArgTypes...)>* __p)
{
::new (__p) __func(wistd::move(__f_));
}
template<class _Fp, class _Rp, class ..._ArgTypes>
void
__func<_Fp, _Rp(_ArgTypes...)>::destroy() WI_NOEXCEPT
{
__f_.~_Fp();
}
template<class _Fp, class _Rp, class ..._ArgTypes>
_Rp
__func<_Fp, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg)
{
typedef __invoke_void_return_wrapper<_Rp> _Invoker;
return _Invoker::__call(__f_, wistd::forward<_ArgTypes>(__arg)...);
}
} // __function
template<class _Rp, class ..._ArgTypes>
class __WI_LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)>
: public __function::__maybe_derive_from_unary_function<_Rp(_ArgTypes...)>,
public __function::__maybe_derive_from_binary_function<_Rp(_ArgTypes...)>
{
// 'wistd::function' is most similar to 'inplace_function' in that it _only_ permits holding function objects
// that can fit within its internal buffer. Therefore, we expand this size to accommodate space for at least 12
// pointers (__base vtable takes an additional one).
static constexpr size_t __buffer_size = 13 * sizeof(void*);
typedef __function::__base<_Rp(_ArgTypes...)> __base;
__WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS
typename aligned_storage<__buffer_size>::type __buf_;
__base* __f_;
__WI_LIBCPP_NO_CFI static __base *__as_base(void *p) {
return reinterpret_cast<__base*>(p);
}
template <class _Fp, bool>
struct __callable_imp
{
static const bool value = is_same<void, _Rp>::value ||
is_convertible<typename __invoke_of<_Fp&, _ArgTypes...>::type,
_Rp>::value;
};
template <class _Fp>
struct __callable_imp<_Fp, false>
{
static const bool value = false;
};
template <class _Fp>
struct __callable
{
static const bool value = __callable_imp<_Fp, __lazy_and<
integral_constant<bool, !is_same<__uncvref_t<_Fp>, function>::value>,
__invokable<_Fp&, _ArgTypes...>
>::value>::value;
};
template <class _Fp>
using _EnableIfCallable = typename enable_if<__callable<_Fp>::value>::type;
public:
typedef _Rp result_type;
// construct/copy/destroy:
__WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS
function() WI_NOEXCEPT : __f_(0) {}
__WI_LIBCPP_INLINE_VISIBILITY
function(nullptr_t) WI_NOEXCEPT : __f_(0) {}
function(const function&);
function(function&&);
template<class _Fp, class = _EnableIfCallable<_Fp>>
function(_Fp);
function& operator=(const function&);
function& operator=(function&&);
function& operator=(nullptr_t) WI_NOEXCEPT;
template<class _Fp, class = _EnableIfCallable<_Fp>>
function& operator=(_Fp&&);
~function();
// function modifiers:
void swap(function&);
// function capacity:
__WI_LIBCPP_INLINE_VISIBILITY
__WI_LIBCPP_EXPLICIT operator bool() const WI_NOEXCEPT {return __f_;}
// deleted overloads close possible hole in the type system
template<class _R2, class... _ArgTypes2>
bool operator==(const function<_R2(_ArgTypes2...)>&) const = delete;
template<class _R2, class... _ArgTypes2>
bool operator!=(const function<_R2(_ArgTypes2...)>&) const = delete;
public:
// function invocation:
_Rp operator()(_ArgTypes...) const;
// NOTE: type_info is very compiler specific, and on top of that, we're operating in a namespace other than
// 'std' so all functions requiring RTTI have been removed
};
template<class _Rp, class ..._ArgTypes>
__WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS
function<_Rp(_ArgTypes...)>::function(const function& __f)
{
if (__f.__f_ == 0)
__f_ = 0;
else
{
__f_ = __as_base(&__buf_);
__f.__f_->__clone(__f_);
}
}
template<class _Rp, class ..._ArgTypes>
__WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS __WI_LIBCPP_SUPPRESS_NOEXCEPT_ANALYSIS
function<_Rp(_ArgTypes...)>::function(function&& __f)
{
if (__f.__f_ == 0)
__f_ = 0;
else
{
__f_ = __as_base(&__buf_);
__f.__f_->__move(__f_);
__f.__f_->destroy();
__f.__f_ = 0;
}
}
template<class _Rp, class ..._ArgTypes>
template <class _Fp, class>
__WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS
function<_Rp(_ArgTypes...)>::function(_Fp __f)
: __f_(0)
{
if (__function::__not_null(__f))
{
typedef __function::__func<_Fp, _Rp(_ArgTypes...)> _FF;
static_assert(sizeof(_FF) <= sizeof(__buf_),
"The sizeof(wistd::function) has grown too large for the reserved buffer (12 pointers). Refactor to reduce size of the capture.");
__f_ = ::new((void*)&__buf_) _FF(wistd::move(__f));
}
}
template<class _Rp, class ..._ArgTypes>
function<_Rp(_ArgTypes...)>&
function<_Rp(_ArgTypes...)>::operator=(const function& __f)
{
*this = nullptr;
if (__f.__f_)
{
__f_ = __as_base(&__buf_);
__f.__f_->__clone(__f_);
}
return *this;
}
template<class _Rp, class ..._ArgTypes>
function<_Rp(_ArgTypes...)>&
function<_Rp(_ArgTypes...)>::operator=(function&& __f)
{
*this = nullptr;
if (__f.__f_)
{
__f_ = __as_base(&__buf_);
__f.__f_->__move(__f_);
__f.__f_->destroy();
__f.__f_ = 0;
}
return *this;
}
template<class _Rp, class ..._ArgTypes>
function<_Rp(_ArgTypes...)>&
function<_Rp(_ArgTypes...)>::operator=(nullptr_t) WI_NOEXCEPT
{
__base* __t = __f_;
__f_ = 0;
if (__t)
__t->destroy();
return *this;
}
template<class _Rp, class ..._ArgTypes>
template <class _Fp, class>
function<_Rp(_ArgTypes...)>&
function<_Rp(_ArgTypes...)>::operator=(_Fp&& __f)
{
*this = nullptr;
if (__function::__not_null(__f))
{
typedef __function::__func<typename decay<_Fp>::type, _Rp(_ArgTypes...)> _FF;
static_assert(sizeof(_FF) <= sizeof(__buf_),
"The sizeof(wistd::function) has grown too large for the reserved buffer (12 pointers). Refactor to reduce size of the capture.");
__f_ = ::new((void*)&__buf_) _FF(wistd::move(__f));
}
return *this;
}
template<class _Rp, class ..._ArgTypes>
function<_Rp(_ArgTypes...)>::~function()
{
if (__f_)
__f_->destroy();
}
template<class _Rp, class ..._ArgTypes>
void
function<_Rp(_ArgTypes...)>::swap(function& __f)
{
if (wistd::addressof(__f) == this)
return;
if (__f_ && __f.__f_)
{
typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
__base* __t = __as_base(&__tempbuf);
__f_->__move(__t);
__f_->destroy();
__f_ = 0;
__f.__f_->__move(__as_base(&__buf_));
__f.__f_->destroy();
__f.__f_ = 0;
__f_ = __as_base(&__buf_);
__t->__move(__as_base(&__f.__buf_));
__t->destroy();
__f.__f_ = __as_base(&__f.__buf_);
}
else if (__f_)
{
__f_->__move(__as_base(&__f.__buf_));
__f_->destroy();
__f_ = 0;
__f.__f_ = __as_base(&__f.__buf_);
}
else if (__f.__f_)
{
__f.__f_->__move(__as_base(&__buf_));
__f.__f_->destroy();
__f.__f_ = 0;
__f_ = __as_base(&__buf_);
}
}
template<class _Rp, class ..._ArgTypes>
_Rp
function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const
{
if (__f_ == 0)
__throw_bad_function_call();
return (*__f_)(wistd::forward<_ArgTypes>(__arg)...);
}
template <class _Rp, class... _ArgTypes>
inline __WI_LIBCPP_INLINE_VISIBILITY
bool
operator==(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) WI_NOEXCEPT {return !__f;}
template <class _Rp, class... _ArgTypes>
inline __WI_LIBCPP_INLINE_VISIBILITY
bool
operator==(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) WI_NOEXCEPT {return !__f;}
template <class _Rp, class... _ArgTypes>
inline __WI_LIBCPP_INLINE_VISIBILITY
bool
operator!=(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) WI_NOEXCEPT {return (bool)__f;}
template <class _Rp, class... _ArgTypes>
inline __WI_LIBCPP_INLINE_VISIBILITY
bool
operator!=(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) WI_NOEXCEPT {return (bool)__f;}
// Provide both 'swap_wil' and 'swap' since we now have two ADL scenarios that we need to work
template <class _Rp, class... _ArgTypes>
inline __WI_LIBCPP_INLINE_VISIBILITY
void
swap(function<_Rp(_ArgTypes...)>& __x, function<_Rp(_ArgTypes...)>& __y)
{return __x.swap(__y);}
template <class _Rp, class... _ArgTypes>
inline __WI_LIBCPP_INLINE_VISIBILITY
void
swap_wil(function<_Rp(_ArgTypes...)>& __x, function<_Rp(_ArgTypes...)>& __y)
{return __x.swap(__y);}
// std::invoke
template <class _Fn, class ..._Args>
typename __invoke_of<_Fn, _Args...>::type
invoke(_Fn&& __f, _Args&&... __args)
__WI_NOEXCEPT_((__nothrow_invokable<_Fn, _Args...>::value))
{
return wistd::__invoke(wistd::forward<_Fn>(__f), wistd::forward<_Args>(__args)...);
}
#else // __WI_LIBCPP_CXX03_LANG
#error wistd::function and wistd::invoke not implemented for pre-C++11
#endif
}
/// @endcond
#pragma warning(pop)
#endif // _WISTD_FUNCTIONAL_H_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,84 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
//*********************************************************
#ifndef __WIL_WRL_INCLUDED
#define __WIL_WRL_INCLUDED
#include <wrl.h>
#include "result.h"
#include "common.h" // wistd type_traits helpers
namespace wil
{
#ifdef WIL_ENABLE_EXCEPTIONS
#pragma region Object construction helpers that throw exceptions
/** Used to construct a RuntimeClass based object that uses 2 phase construction.
Construct a RuntimeClass based object that uses 2 phase construction (by implementing
RuntimeClassInitialize() and returning error codes for failures.
~~~~
// SomeClass uses 2 phase initialization by implementing RuntimeClassInitialize()
auto someClass = MakeAndInitializeOrThrow<SomeClass>(L"input", true);
~~~~ */
template <typename T, typename... TArgs>
Microsoft::WRL::ComPtr<T> MakeAndInitializeOrThrow(TArgs&&... args)
{
Microsoft::WRL::ComPtr<T> obj;
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<T>(&obj, Microsoft::WRL::Details::Forward<TArgs>(args)...));
return obj;
}
/** Used to construct an RuntimeClass based object that uses exceptions in its constructor (and does
not require 2 phase construction).
~~~~
// SomeClass uses exceptions for error handling in its constructor.
auto someClass = MakeOrThrow<SomeClass>(L"input", true);
~~~~ */
template <typename T, typename... TArgs>
Microsoft::WRL::ComPtr<T> MakeOrThrow(TArgs&&... args)
{
// This is how you can detect the presence of RuntimeClassInitialize() and find dangerous use.
// Unfortunately this produces false positives as all RuntimeClass derived classes have
// a RuntimeClassInitialize() method from their base class.
// static_assert(!std::is_member_function_pointer<decltype(&T::RuntimeClassInitialize)>::value,
// "class has a RuntimeClassInitialize member, use MakeAndInitializeOrThrow instead");
auto obj = Microsoft::WRL::Make<T>(Microsoft::WRL::Details::Forward<TArgs>(args)...);
THROW_IF_NULL_ALLOC(obj.Get());
return obj;
}
#pragma endregion
#endif // WIL_ENABLE_EXCEPTIONS
/** By default WRL Callback objects are not agile, use this to make an agile one. Replace use of Callback<> with MakeAgileCallback<>.
Will return null on failure, translate that into E_OUTOFMEMORY using XXX_IF_NULL_ALLOC()
from wil\result.h to test the result. */
template<typename TDelegateInterface, typename ...Args>
::Microsoft::WRL::ComPtr<TDelegateInterface> MakeAgileCallbackNoThrow(Args&&... args) WI_NOEXCEPT
{
using namespace Microsoft::WRL;
return Callback<Implements<RuntimeClassFlags<ClassicCom>, TDelegateInterface, FtmBase>>(wistd::forward<Args>(args)...);
}
#ifdef WIL_ENABLE_EXCEPTIONS
template<typename TDelegateInterface, typename ...Args>
::Microsoft::WRL::ComPtr<TDelegateInterface> MakeAgileCallback(Args&&... args)
{
auto result = MakeAgileCallbackNoThrow<TDelegateInterface, Args...>(wistd::forward<Args>(args)...);
THROW_IF_NULL_ALLOC(result);
return result;
}
#endif // WIL_ENABLE_EXCEPTIONS
} // namespace wil
#endif // __WIL_WRL_INCLUDED