├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── README.md
├── apiset.c
├── apiset.h
├── apiset.sln
├── apiset.vcxproj
├── apiset.vcxproj.filters
├── main.c
├── nls.c
├── ntapi.h
├── ntpsapi.h
├── ntrtl.h
├── ntstatus.h
├── pebteb.h
├── resolve.c
├── string.c
└── unicode.c
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 | [Ll]ogs/
33 |
34 | # Visual Studio 2015/2017 cache/options directory
35 | .vs/
36 | # Uncomment if you have tasks that create the project's static files in wwwroot
37 | #wwwroot/
38 |
39 | # Visual Studio 2017 auto generated files
40 | Generated\ Files/
41 |
42 | # MSTest test Results
43 | [Tt]est[Rr]esult*/
44 | [Bb]uild[Ll]og.*
45 |
46 | # NUnit
47 | *.VisualState.xml
48 | TestResult.xml
49 | nunit-*.xml
50 |
51 | # Build Results of an ATL Project
52 | [Dd]ebugPS/
53 | [Rr]eleasePS/
54 | dlldata.c
55 |
56 | # Benchmark Results
57 | BenchmarkDotNet.Artifacts/
58 |
59 | # .NET Core
60 | project.lock.json
61 | project.fragment.lock.json
62 | artifacts/
63 |
64 | # StyleCop
65 | StyleCopReport.xml
66 |
67 | # Files built by Visual Studio
68 | *_i.c
69 | *_p.c
70 | *_h.h
71 | *.ilk
72 | *.meta
73 | *.obj
74 | *.iobj
75 | *.pch
76 | *.pdb
77 | *.ipdb
78 | *.pgc
79 | *.pgd
80 | *.rsp
81 | *.sbr
82 | *.tlb
83 | *.tli
84 | *.tlh
85 | *.tmp
86 | *.tmp_proj
87 | *_wpftmp.csproj
88 | *.log
89 | *.vspscc
90 | *.vssscc
91 | .builds
92 | *.pidb
93 | *.svclog
94 | *.scc
95 |
96 | # Chutzpah Test files
97 | _Chutzpah*
98 |
99 | # Visual C++ cache files
100 | ipch/
101 | *.aps
102 | *.ncb
103 | *.opendb
104 | *.opensdf
105 | *.sdf
106 | *.cachefile
107 | *.VC.db
108 | *.VC.VC.opendb
109 |
110 | # Visual Studio profiler
111 | *.psess
112 | *.vsp
113 | *.vspx
114 | *.sap
115 |
116 | # Visual Studio Trace Files
117 | *.e2e
118 |
119 | # TFS 2012 Local Workspace
120 | $tf/
121 |
122 | # Guidance Automation Toolkit
123 | *.gpState
124 |
125 | # ReSharper is a .NET coding add-in
126 | _ReSharper*/
127 | *.[Rr]e[Ss]harper
128 | *.DotSettings.user
129 |
130 | # TeamCity is a build add-in
131 | _TeamCity*
132 |
133 | # DotCover is a Code Coverage Tool
134 | *.dotCover
135 |
136 | # AxoCover is a Code Coverage Tool
137 | .axoCover/*
138 | !.axoCover/settings.json
139 |
140 | # Visual Studio code coverage results
141 | *.coverage
142 | *.coveragexml
143 |
144 | # NCrunch
145 | _NCrunch_*
146 | .*crunch*.local.xml
147 | nCrunchTemp_*
148 |
149 | # MightyMoose
150 | *.mm.*
151 | AutoTest.Net/
152 |
153 | # Web workbench (sass)
154 | .sass-cache/
155 |
156 | # Installshield output folder
157 | [Ee]xpress/
158 |
159 | # DocProject is a documentation generator add-in
160 | DocProject/buildhelp/
161 | DocProject/Help/*.HxT
162 | DocProject/Help/*.HxC
163 | DocProject/Help/*.hhc
164 | DocProject/Help/*.hhk
165 | DocProject/Help/*.hhp
166 | DocProject/Help/Html2
167 | DocProject/Help/html
168 |
169 | # Click-Once directory
170 | publish/
171 |
172 | # Publish Web Output
173 | *.[Pp]ublish.xml
174 | *.azurePubxml
175 | # Note: Comment the next line if you want to checkin your web deploy settings,
176 | # but database connection strings (with potential passwords) will be unencrypted
177 | *.pubxml
178 | *.publishproj
179 |
180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
181 | # checkin your Azure Web App publish settings, but sensitive information contained
182 | # in these scripts will be unencrypted
183 | PublishScripts/
184 |
185 | # NuGet Packages
186 | *.nupkg
187 | # NuGet Symbol Packages
188 | *.snupkg
189 | # The packages folder can be ignored because of Package Restore
190 | **/[Pp]ackages/*
191 | # except build/, which is used as an MSBuild target.
192 | !**/[Pp]ackages/build/
193 | # Uncomment if necessary however generally it will be regenerated when needed
194 | #!**/[Pp]ackages/repositories.config
195 | # NuGet v3's project.json files produces more ignorable files
196 | *.nuget.props
197 | *.nuget.targets
198 |
199 | # Microsoft Azure Build Output
200 | csx/
201 | *.build.csdef
202 |
203 | # Microsoft Azure Emulator
204 | ecf/
205 | rcf/
206 |
207 | # Windows Store app package directories and files
208 | AppPackages/
209 | BundleArtifacts/
210 | Package.StoreAssociation.xml
211 | _pkginfo.txt
212 | *.appx
213 | *.appxbundle
214 | *.appxupload
215 |
216 | # Visual Studio cache files
217 | # files ending in .cache can be ignored
218 | *.[Cc]ache
219 | # but keep track of directories ending in .cache
220 | !?*.[Cc]ache/
221 |
222 | # Others
223 | ClientBin/
224 | ~$*
225 | *~
226 | *.dbmdl
227 | *.dbproj.schemaview
228 | *.jfm
229 | *.pfx
230 | *.publishsettings
231 | orleans.codegen.cs
232 |
233 | # Including strong name files can present a security risk
234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
235 | #*.snk
236 |
237 | # Since there are multiple workflows, uncomment next line to ignore bower_components
238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
239 | #bower_components/
240 |
241 | # RIA/Silverlight projects
242 | Generated_Code/
243 |
244 | # Backup & report files from converting an old project file
245 | # to a newer Visual Studio version. Backup files are not needed,
246 | # because we have git ;-)
247 | _UpgradeReport_Files/
248 | Backup*/
249 | UpgradeLog*.XML
250 | UpgradeLog*.htm
251 | ServiceFabricBackup/
252 | *.rptproj.bak
253 |
254 | # SQL Server files
255 | *.mdf
256 | *.ldf
257 | *.ndf
258 |
259 | # Business Intelligence projects
260 | *.rdl.data
261 | *.bim.layout
262 | *.bim_*.settings
263 | *.rptproj.rsuser
264 | *- [Bb]ackup.rdl
265 | *- [Bb]ackup ([0-9]).rdl
266 | *- [Bb]ackup ([0-9][0-9]).rdl
267 |
268 | # Microsoft Fakes
269 | FakesAssemblies/
270 |
271 | # GhostDoc plugin setting file
272 | *.GhostDoc.xml
273 |
274 | # Node.js Tools for Visual Studio
275 | .ntvs_analysis.dat
276 | node_modules/
277 |
278 | # Visual Studio 6 build log
279 | *.plg
280 |
281 | # Visual Studio 6 workspace options file
282 | *.opt
283 |
284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
285 | *.vbw
286 |
287 | # Visual Studio LightSwitch build output
288 | **/*.HTMLClient/GeneratedArtifacts
289 | **/*.DesktopClient/GeneratedArtifacts
290 | **/*.DesktopClient/ModelManifest.xml
291 | **/*.Server/GeneratedArtifacts
292 | **/*.Server/ModelManifest.xml
293 | _Pvt_Extensions
294 |
295 | # Paket dependency manager
296 | .paket/paket.exe
297 | paket-files/
298 |
299 | # FAKE - F# Make
300 | .fake/
301 |
302 | # CodeRush personal settings
303 | .cr/personal
304 |
305 | # Python Tools for Visual Studio (PTVS)
306 | __pycache__/
307 | *.pyc
308 |
309 | # Cake - Uncomment if you are using it
310 | # tools/**
311 | # !tools/packages.config
312 |
313 | # Tabs Studio
314 | *.tss
315 |
316 | # Telerik's JustMock configuration file
317 | *.jmconfig
318 |
319 | # BizTalk build output
320 | *.btp.cs
321 | *.btm.cs
322 | *.odx.cs
323 | *.xsd.cs
324 |
325 | # OpenCover UI analysis results
326 | OpenCover/
327 |
328 | # Azure Stream Analytics local run output
329 | ASALocalRun/
330 |
331 | # MSBuild Binary and Structured Log
332 | *.binlog
333 |
334 | # NVidia Nsight GPU debugger configuration file
335 | *.nvuser
336 |
337 | # MFractors (Xamarin productivity tool) working folder
338 | .mfractor/
339 |
340 | # Local History for Visual Studio
341 | .localhistory/
342 |
343 | # BeatPulse healthcheck temp database
344 | healthchecksdb
345 |
346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
347 | MigrationBackup/
348 |
349 | # Ionide (cross platform F# VS Code tools) working folder
350 | .ionide/
351 |
352 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.21)
2 |
3 | #
4 | # Define the ApiSet project
5 | #
6 | project(apiset C)
7 |
8 | if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
9 | # Force GCC and Clang to compile with proper unicode support for Windows.
10 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -municode -fshort-wchar")
11 | message(STATUS "Using GCC compiler: ${CMAKE_C_COMPILER}")
12 | elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
13 | # Compile as static runtime binary.
14 | message(STATUS "Using MSVC compiler: ${CMAKE_C_COMPILER}")
15 | # https://gitlab.kitware.com/cmake/community/wikis/FAQ#dynamic-replace
16 | foreach(flag_var CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
17 | if(${flag_var} MATCHES "/MD")
18 | string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
19 | endif(${flag_var} MATCHES "/MD")
20 | if(${flag_var} MATCHES "/MDd")
21 | string(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}")
22 | endif(${flag_var} MATCHES "/MDd")
23 | endforeach(flag_var)
24 | endif()
25 |
26 | set(APISET_SOURCES
27 | string.c
28 | nls.c
29 | apiset.c
30 | resolve.c
31 | main.c
32 | )
33 | if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
34 | set(APISET_SOURCES ${APISET_SOURCES} unicode.c)
35 | endif()
36 |
37 | add_executable(apiset ${APISET_SOURCES})
38 | target_link_libraries(apiset ntdll)
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017-2019 Aidan Khoury
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ApiSet
2 |
3 | API Set resolver written in C. This implementation supports API Set versions V2 to V6.
4 |
5 | The intended purpose of this tool is to resolve Windows API Set stub libraries for assisting in reverse engineering forwarded Windows API exports.
6 |
7 | I wrote this to quickly resolve API Set libraries on different Windows OSes (Windows 7 - Windows 10 1909).
8 |
9 | Usage:
10 | `apiset.exe ext-some-api-set-library-l1-1-0.dll`
11 |
12 | Thanks to [lucasg](https://github.com/lucasg) for a great starting point for this little project.
13 |
--------------------------------------------------------------------------------
/apiset.c:
--------------------------------------------------------------------------------
1 | /**
2 | * API Set Lookup
3 | * Copyright (c) 2018-2019 Aidan Khoury. All rights reserved.
4 | *
5 | * @file apiset.c
6 | * @authors Aidan Khoury (ajkhoury)
7 | * @date 11/22/2018
8 | */
9 |
10 | #include "apiset.h"
11 | #include "ntrtl.h"
12 |
13 | //
14 | // ApiSet DLL prefixes.
15 | //
16 |
17 | #define API_SET_PREFIX_API_ (ULONGLONG)0x002D004900500041 /* L"api-" */
18 | #define API_SET_PREFIX_EXT_ (ULONGLONG)0x002D005400580045 /* L"ext-" */
19 | #define API_SET_DLL_EXTENSTION (ULONGLONG)0x004C004C0044002E /* L".DLL" */
20 |
21 | //
22 | // Useful macros for ApiSet api.
23 | //
24 |
25 | #define API_SET_CHAR_TO_LOWER(c) \
26 | (((WCHAR)((c) - L'A') <= (L'a' - L'A' - 1)) ? ((c) + 0x20) : (c))
27 |
28 |
29 | //
30 | // API set schema version 6.
31 | //
32 |
33 | #define GET_API_SET_NAMESPACE_ENTRY_V6(ApiSetNamespace, Index) \
34 | ((PAPI_SET_NAMESPACE_ENTRY_V6)((ULONG_PTR)(ApiSetNamespace) + \
35 | ((PAPI_SET_NAMESPACE_V6)(ApiSetNamespace))->EntryOffset + \
36 | ((Index) * sizeof(API_SET_NAMESPACE_ENTRY_V6))))
37 |
38 | #define GET_API_SET_NAMESPACE_VALUE_ENTRY_V6(ApiSetNamespace, Entry, Index) \
39 | ((PAPI_SET_VALUE_ENTRY_V6)((ULONG_PTR)(ApiSetNamespace) + \
40 | ((PAPI_SET_NAMESPACE_ENTRY_V6)(Entry))->ValueOffset + \
41 | ((Index) * sizeof(API_SET_VALUE_ENTRY_V6))))
42 |
43 | #define GET_API_SET_NAMESPACE_ENTRY_NAME_V6(ApiSetNamespace, Entry) \
44 | ((PWCHAR)((ULONG_PTR)(ApiSetNamespace) + ((PAPI_SET_NAMESPACE_ENTRY_V6)(Entry))->NameOffset))
45 |
46 | #define GET_API_SET_NAMESPACE_ENTRY_VALUE_V6(ApiSetNamespace, Entry) \
47 | ((PWCHAR)((ULONG_PTR)(ApiSetNamespace) + ((PAPI_SET_NAMESPACE_ENTRY_V6)(Entry))->ValueOffset))
48 |
49 | #define GET_API_SET_VALUE_ENTRY_NAME_V6(ApiSetNamespace, Entry) \
50 | ((PWCHAR)((ULONG_PTR)(ApiSetNamespace) + ((PAPI_SET_VALUE_ENTRY_V6)(Entry))->NameOffset))
51 |
52 | #define GET_API_SET_VALUE_ENTRY_VALUE_V6(ApiSetNamespace, Entry) \
53 | ((PWCHAR)((ULONG_PTR)(ApiSetNamespace) + ((PAPI_SET_VALUE_ENTRY_V6)(Entry))->ValueOffset))
54 |
55 | #define GET_API_SET_HASH_ENTRY_V6(ApiSetNamespace, Middle) \
56 | ((PAPI_SET_HASH_ENTRY_V6)((ULONG_PTR)(ApiSetNamespace) + \
57 | ((PAPI_SET_NAMESPACE_V6)(ApiSetNamespace))->HashOffset + \
58 | ((Middle) * sizeof(API_SET_HASH_ENTRY_V6))))
59 |
60 | static
61 | PAPI_SET_NAMESPACE_ENTRY_V6
62 | ApiSetpSearchForApiSetV6(
63 | _In_ PAPI_SET_NAMESPACE_V6 ApiSetNamespace,
64 | _In_ PWCHAR ApiSetNameToResolve,
65 | _In_ USHORT ApiSetNameToResolveLength
66 | )
67 | {
68 | WCHAR *pwc;
69 | USHORT Count;
70 | ULONG HashKey;
71 | LONG Low;
72 | LONG Middle;
73 | LONG High;
74 | PAPI_SET_HASH_ENTRY_V6 HashEntry;
75 | PAPI_SET_NAMESPACE_ENTRY_V6 FoundEntry;
76 |
77 | if (!ApiSetNameToResolveLength) {
78 | return NULL;
79 | }
80 |
81 | //
82 | // Calculate hash key for this ApiSet name.
83 | //
84 | HashKey = 0;
85 | pwc = ApiSetNameToResolve;
86 | Count = ApiSetNameToResolveLength;
87 | do {
88 | HashKey = HashKey * ApiSetNamespace->HashFactor + (USHORT)API_SET_CHAR_TO_LOWER(*pwc);
89 | ++pwc;
90 | --Count;
91 | } while (Count);
92 |
93 | //
94 | // Lookup the matching hash in the ApiSet namespace using a binary search.
95 | //
96 | FoundEntry = NULL;
97 | Low = 0;
98 | Middle = 0;
99 | High = (LONG)ApiSetNamespace->Count - 1;
100 |
101 | while (High >= Low) {
102 | Middle = (Low + High) >> 1;
103 |
104 | HashEntry = GET_API_SET_HASH_ENTRY_V6(ApiSetNamespace, Middle);
105 |
106 | if (HashKey < HashEntry->Hash) {
107 | High = Middle - 1;
108 | } else if (HashKey > HashEntry->Hash) {
109 | Low = Middle + 1;
110 | } else {
111 | //
112 | // Get the namespace entry from the hash entry index.
113 | //
114 | FoundEntry = GET_API_SET_NAMESPACE_ENTRY_V6(ApiSetNamespace, HashEntry->Index);
115 | break;
116 | }
117 | }
118 |
119 | //
120 | // If the high index is less than the low index, then a matching hash entry was not found.
121 | // Otherwise, get the found namespace entry.
122 | //
123 | if (High < Low) {
124 | return NULL;
125 | }
126 |
127 | //
128 | // Final check on apiset library name in order to make sure we didn't collide with
129 | // another hash bucket.
130 | //
131 | if (RtlCompareUnicodeStrings(ApiSetNameToResolve,
132 | ApiSetNameToResolveLength,
133 | GET_API_SET_NAMESPACE_ENTRY_NAME_V6(ApiSetNamespace, FoundEntry),
134 | FoundEntry->HashedLength / sizeof(WCHAR),
135 | TRUE) == 0) {
136 | return FoundEntry;
137 | }
138 |
139 | return NULL;
140 | }
141 |
142 | static
143 | PAPI_SET_VALUE_ENTRY_V6
144 | ApiSetpSearchForApiSetHostV6(
145 | _In_ PAPI_SET_NAMESPACE_ENTRY_V6 Entry,
146 | _In_ WCHAR *ApiSetNameToResolve,
147 | _In_ USHORT ApiSetNameToResolveLength,
148 | _In_ PAPI_SET_NAMESPACE_V6 ApiSetNamespace
149 | )
150 | {
151 | LONG Low;
152 | LONG Middle;
153 | LONG High;
154 | LONG Result;
155 | PAPI_SET_VALUE_ENTRY_V6 FoundEntry;
156 | PAPI_SET_VALUE_ENTRY_V6 ApiSetHostEntry;
157 |
158 | //
159 | // If there is no alias, don't bother checking each one.
160 | //
161 | FoundEntry = GET_API_SET_NAMESPACE_VALUE_ENTRY_V6(ApiSetNamespace, Entry, 0);
162 |
163 | High = (LONG)(Entry->ValueCount - 1);
164 | if (!High) {
165 | return FoundEntry;
166 | }
167 |
168 | Low = 1; // skip the first entry.
169 |
170 | while (Low <= High) {
171 | Middle = (Low + High) >> 1;
172 |
173 | ApiSetHostEntry = GET_API_SET_NAMESPACE_VALUE_ENTRY_V6(ApiSetNamespace, Entry, Middle);
174 |
175 | //
176 | // Compare API names.
177 | //
178 | Result = RtlCompareUnicodeStrings(ApiSetNameToResolve,
179 | ApiSetNameToResolveLength,
180 | GET_API_SET_VALUE_ENTRY_NAME_V6(ApiSetNamespace, ApiSetHostEntry),
181 | ApiSetHostEntry->NameLength / sizeof(WCHAR),
182 | TRUE);
183 | if (Result < 0) {
184 | High = Middle - 1;
185 | } else if (Result > 0) {
186 | Low = Middle + 1;
187 | } else {
188 | FoundEntry = GET_API_SET_NAMESPACE_VALUE_ENTRY_V6(ApiSetNamespace, Entry, Middle);
189 | break;
190 | }
191 | }
192 |
193 | return FoundEntry;
194 | }
195 |
196 | NTSTATUS
197 | APISETAPI
198 | ApiSetResolveToHostV6(
199 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace,
200 | _In_ PCUNICODE_STRING ApiSetNameToResolve,
201 | _In_opt_ PCUNICODE_STRING ParentName,
202 | _Out_ PBOOLEAN Resolved,
203 | _Out_ PUNICODE_STRING Output
204 | )
205 | {
206 | NTSTATUS Status;
207 | BOOLEAN IsResolved;
208 | WCHAR *ApiSetNameBuffer;
209 | WCHAR *pwc;
210 | ULONG ApiSetNameBufferLength;
211 | USHORT ApiSetNameNoExtLength;
212 | PAPI_SET_NAMESPACE_ENTRY_V6 ResolvedNamespaceEntry;
213 | PAPI_SET_VALUE_ENTRY_V6 HostLibraryEntry;
214 | ULONGLONG ApiSetNameBufferPrefix;
215 |
216 | IsResolved = FALSE;
217 | RtlInitEmptyUnicodeString(Output, NULL, 0);
218 |
219 | //
220 | // Make sure the API Set name is a valid length.
221 | //
222 | if (ApiSetNameToResolve->Length < sizeof(API_SET_PREFIX_API_)) {
223 | goto Exit;
224 | }
225 |
226 | ApiSetNameBuffer = ApiSetNameToResolve->Buffer;
227 |
228 | //
229 | // Check library name starts with "api-" or "ext-"
230 | //
231 | ApiSetNameBufferPrefix = *(ULONGLONG*)ApiSetNameBuffer;
232 | ApiSetNameBufferPrefix &= ~(ULONGLONG)0x0000002000200020; // Trick to convert the chars to uppercase.
233 | if ((ApiSetNameBufferPrefix != API_SET_PREFIX_API_) &&
234 | (ApiSetNameBufferPrefix != API_SET_PREFIX_EXT_)) {
235 | goto Exit;
236 | }
237 |
238 | //
239 | // Compute word count of apiset library name without the dll suffix and anything
240 | // beyond the last hyphen. Example:
241 | // api-ms-win-core-apiquery-l1-1-0.dll -> wordlen(api-ms-win-core-apiquery-l1-1)
242 | //
243 | ApiSetNameBufferLength = (ULONG)ApiSetNameToResolve->Length;
244 | pwc = (WCHAR*)((ULONG_PTR)ApiSetNameBuffer + ApiSetNameBufferLength);
245 | do {
246 | if (ApiSetNameBufferLength <= 1)
247 | break;
248 | ApiSetNameBufferLength -= sizeof(WCHAR);
249 | --pwc;
250 | } while (*pwc != L'-');
251 |
252 | ApiSetNameNoExtLength = (USHORT)(ApiSetNameBufferLength / sizeof(WCHAR));
253 | if (!ApiSetNameNoExtLength) {
254 | goto Exit;
255 | }
256 |
257 | //
258 | // Hash table lookup.
259 | //
260 | ResolvedNamespaceEntry = ApiSetpSearchForApiSetV6((PAPI_SET_NAMESPACE_V6)ApiSetNamespace,
261 | ApiSetNameBuffer,
262 | ApiSetNameNoExtLength
263 | );
264 | if (!ResolvedNamespaceEntry) {
265 | goto Exit;
266 | }
267 |
268 | //
269 | // Look for aliases in hosts libraries if necessary.
270 | //
271 | if (ResolvedNamespaceEntry->ValueCount > 1 && ParentName) {
272 |
273 | HostLibraryEntry = ApiSetpSearchForApiSetHostV6(ResolvedNamespaceEntry,
274 | ParentName->Buffer,
275 | ParentName->Length / sizeof(WCHAR),
276 | (PAPI_SET_NAMESPACE_V6)ApiSetNamespace
277 | );
278 |
279 | } else if (ResolvedNamespaceEntry->ValueCount > 0) {
280 |
281 | HostLibraryEntry = GET_API_SET_NAMESPACE_VALUE_ENTRY_V6(ApiSetNamespace,
282 | ResolvedNamespaceEntry,
283 | 0);
284 | } else {
285 | goto Exit;
286 | }
287 |
288 | //
289 | // Output resolved host library.
290 | //
291 | Output->Length = (USHORT)HostLibraryEntry->ValueLength;
292 | Output->MaximumLength = Output->Length;
293 | Output->Buffer = GET_API_SET_VALUE_ENTRY_VALUE_V6(ApiSetNamespace, HostLibraryEntry);
294 |
295 | IsResolved = TRUE;
296 |
297 | Exit:
298 | Status = STATUS_SUCCESS;
299 | *Resolved = IsResolved;
300 |
301 | return Status;
302 | }
303 |
304 |
305 |
306 | //
307 | // API set schema version 4.
308 | //
309 |
310 | #define GET_API_SET_NAMESPACE_ENTRY_V4(ApiSetNamespace, Index) \
311 | ((PAPI_SET_NAMESPACE_ENTRY_V4)(((PAPI_SET_NAMESPACE_ARRAY_V4)(ApiSetNamespace))->Array + \
312 | Index))
313 |
314 | #define GET_API_SET_NAMESPACE_ENTRY_NAME_V4(ApiSetNamespace, NamespaceEntry) \
315 | ((PWCHAR)((ULONG_PTR)(ApiSetNamespace) + \
316 | ((PAPI_SET_NAMESPACE_ENTRY_V4)(NamespaceEntry))->NameOffset))
317 |
318 | #define GET_API_SET_NAMESPACE_ENTRY_DATA_V4(ApiSetNamespace, NamespaceEntry) \
319 | ((PAPI_SET_VALUE_ARRAY_V4)((ULONG_PTR)(ApiSetNamespace) + \
320 | ((PAPI_SET_NAMESPACE_ENTRY_V4)(NamespaceEntry))->DataOffset))
321 |
322 | #define GET_API_SET_VALUE_ENTRY_V4(ApiSetNamespace, ResolvedValueArray, Index) \
323 | ((PAPI_SET_VALUE_ENTRY_V4)(((PAPI_SET_VALUE_ARRAY_V4)(ResolvedValueArray))->Array + \
324 | Index))
325 |
326 | #define GET_API_SET_VALUE_ENTRY_NAME_V4(ApiSetNamespace, ApiSetValueEntry) \
327 | ((WCHAR*)((ULONG_PTR)(ApiSetNamespace) + \
328 | ((PAPI_SET_VALUE_ENTRY_V4)(ApiSetValueEntry))->NameOffset))
329 |
330 | #define GET_API_SET_VALUE_ENTRY_VALUE_V4(ApiSetNamespace, ApiSetValueEntry) \
331 | ((WCHAR*)((ULONG_PTR)(ApiSetNamespace) + \
332 | ((PAPI_SET_VALUE_ENTRY_V4)(ApiSetValueEntry))->ValueOffset))
333 |
334 | static
335 | PAPI_SET_NAMESPACE_ENTRY_V4
336 | ApiSetpSearchForApiSetV4(
337 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace,
338 | _In_ PWCHAR ApiSetNameToResolve,
339 | _In_ USHORT ApiSetNameToResolveLength
340 | )
341 | {
342 | LONG Low;
343 | LONG Middle;
344 | LONG High;
345 | LONG Result;
346 | PAPI_SET_NAMESPACE_ARRAY_V4 ApiSetNamespaceArray;
347 | PAPI_SET_NAMESPACE_ENTRY_V4 ApiSetNamespaceEntry;
348 |
349 | ApiSetNamespaceArray = (PAPI_SET_NAMESPACE_ARRAY_V4)ApiSetNamespace;
350 |
351 | Low = 0;
352 | High = (LONG)(ApiSetNamespaceArray->Count - 1);
353 |
354 | while (High >= Low) {
355 | Middle = (High + Low) >> 1;
356 |
357 | ApiSetNamespaceEntry = GET_API_SET_NAMESPACE_ENTRY_V4(ApiSetNamespace, Middle);
358 |
359 | Result = RtlCompareUnicodeStrings(ApiSetNameToResolve,
360 | ApiSetNameToResolveLength,
361 | GET_API_SET_NAMESPACE_ENTRY_NAME_V4(ApiSetNamespace, ApiSetNamespaceEntry),
362 | ApiSetNamespaceEntry->NameLength,
363 | TRUE
364 | );
365 | if (Result < 0) {
366 | High = Middle - 1;
367 | } else if (Result > 0) {
368 | Low = Middle + 1;
369 | } else {
370 | return ApiSetNamespaceEntry;
371 | }
372 | }
373 |
374 | return NULL;
375 | }
376 |
377 | static
378 | PAPI_SET_VALUE_ENTRY_V4
379 | ApiSetpSearchForApiSetHostV4(
380 | _In_ PAPI_SET_VALUE_ARRAY_V4 ApiSetValueArray,
381 | _In_ WCHAR *ApiSetNameToResolve,
382 | _In_ USHORT ApiSetNameToResolveLength,
383 | _In_ PAPI_SET_NAMESPACE_ARRAY_V4 ApiSetNamespace
384 | )
385 | {
386 | LONG Low;
387 | LONG Middle;
388 | LONG High;
389 | LONG Result;
390 | PAPI_SET_VALUE_ENTRY_V4 ApiSetHostEntry;
391 |
392 | Low = 1; // skip first entry.
393 | High = (LONG)(ApiSetValueArray->Count - 1);
394 |
395 | while (High >= Low) {
396 | Middle = (High + Low) >> 1;
397 |
398 | ApiSetHostEntry = GET_API_SET_VALUE_ENTRY_V4(ApiSetNamespace, ApiSetValueArray, Middle);
399 |
400 | Result = RtlCompareUnicodeStrings(ApiSetNameToResolve,
401 | ApiSetNameToResolveLength,
402 | GET_API_SET_VALUE_ENTRY_NAME_V4(ApiSetNamespace, ApiSetHostEntry),
403 | ApiSetHostEntry->NameLength,
404 | TRUE
405 | );
406 | if (Result < 0) {
407 | High = Middle - 1;
408 | } else if (Result > 0) {
409 | Low = Middle + 1;
410 | } else {
411 | return ApiSetHostEntry;
412 | }
413 | }
414 |
415 | return NULL;
416 | }
417 |
418 | NTSTATUS
419 | APISETAPI
420 | ApiSetResolveToHostV4(
421 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace,
422 | _In_ PCUNICODE_STRING ApiSetNameToResolve,
423 | _In_opt_ PCUNICODE_STRING ParentName,
424 | _Out_ PBOOLEAN Resolved,
425 | _Out_ PUNICODE_STRING Output
426 | )
427 | {
428 | NTSTATUS Status;
429 | BOOLEAN IsResolved;
430 | ULONGLONG ApiSetNameBufferPrefix;
431 | PAPI_SET_NAMESPACE_ENTRY_V4 ResolvedNamespaceEntry;
432 | PAPI_SET_VALUE_ARRAY_V4 ResolvedValueArray;
433 | PAPI_SET_VALUE_ENTRY_V4 HostLibraryEntry;
434 | UNICODE_STRING ApiSetNameNoExtString;
435 |
436 | IsResolved = FALSE;
437 | RtlInitEmptyUnicodeString(Output, NULL, 0);
438 |
439 | //
440 | // Make sure the API Set name is a valid length.
441 | //
442 | if (ApiSetNameToResolve->Length < sizeof(API_SET_PREFIX_API_)) {
443 | goto Exit;
444 | }
445 |
446 | //
447 | // Check library name starts with "api-" or "ext-"
448 | //
449 | ApiSetNameBufferPrefix = *(ULONGLONG*)ApiSetNameToResolve->Buffer;
450 | ApiSetNameBufferPrefix &= ~(ULONGLONG)0x0000002000200020; // Trick to convert the chars to uppercase.
451 | if (ApiSetNameBufferPrefix != API_SET_PREFIX_API_ &&
452 | ApiSetNameBufferPrefix != API_SET_PREFIX_EXT_) {
453 | goto Exit;
454 | }
455 |
456 | //
457 | // Skip the prefix.
458 | //
459 | ApiSetNameNoExtString.Length = ApiSetNameToResolve->Length - sizeof(API_SET_PREFIX_API_);
460 | ApiSetNameNoExtString.MaximumLength = ApiSetNameNoExtString.Length;
461 | ApiSetNameNoExtString.Buffer = (WCHAR*)((ULONG_PTR)ApiSetNameToResolve->Buffer +
462 | sizeof(API_SET_PREFIX_API_));
463 |
464 | //
465 | // Cut off the '.DLL' extension.
466 | //
467 | if (ApiSetNameNoExtString.Length >= sizeof(API_SET_DLL_EXTENSTION) &&
468 | ApiSetNameNoExtString.Buffer[(ApiSetNameNoExtString.Length -
469 | sizeof(API_SET_DLL_EXTENSTION)) / sizeof(WCHAR)] == L'.') {
470 | ApiSetNameNoExtString.Length -= sizeof(API_SET_DLL_EXTENSTION);
471 | }
472 |
473 | ResolvedNamespaceEntry = ApiSetpSearchForApiSetV4(ApiSetNamespace,
474 | ApiSetNameNoExtString.Buffer,
475 | ApiSetNameNoExtString.Length / sizeof(WCHAR)
476 | );
477 | if (!ResolvedNamespaceEntry) {
478 | goto Exit;
479 | }
480 |
481 | //
482 | // Get the namspace value array.
483 | //
484 | ResolvedValueArray = GET_API_SET_NAMESPACE_ENTRY_DATA_V4(ApiSetNamespace,
485 | ResolvedNamespaceEntry);
486 |
487 | //
488 | // Look for aliases in hosts libraries if necessary.
489 | //
490 | if (ResolvedValueArray->Count > 1 && ParentName) {
491 |
492 | HostLibraryEntry = ApiSetpSearchForApiSetHostV4(ResolvedValueArray,
493 | ParentName->Buffer,
494 | ParentName->Length / sizeof(WCHAR),
495 | (PAPI_SET_NAMESPACE_ARRAY_V4)ApiSetNamespace
496 | );
497 |
498 | } else if (ResolvedValueArray->Count > 0) {
499 |
500 | HostLibraryEntry = GET_API_SET_VALUE_ENTRY_V4(ApiSetNamespace, ResolvedValueArray, 0);
501 |
502 | } else {
503 | goto Exit;
504 | }
505 |
506 | Output->Length = (USHORT)HostLibraryEntry->ValueLength;
507 | Output->MaximumLength = Output->Length;
508 | Output->Buffer = GET_API_SET_VALUE_ENTRY_VALUE_V4(ApiSetNamespace, HostLibraryEntry);
509 |
510 | IsResolved = TRUE;
511 |
512 | Exit:
513 | Status = STATUS_SUCCESS;
514 | *Resolved = IsResolved;
515 |
516 | return Status;
517 | }
518 |
519 |
520 |
521 | //
522 | // API Set Schema Version 3
523 | //
524 |
525 | #define GET_API_SET_NAMESPACE_ENTRY_V3(ApiSetNamespace, Index) \
526 | ((PAPI_SET_NAMESPACE_ENTRY_V3)(((PAPI_SET_NAMESPACE_ARRAY_V3)(ApiSetNamespace))->Array + \
527 | Index))
528 |
529 | #define GET_API_SET_NAMESPACE_ENTRY_NAME_V3(ApiSetNamespace, NamespaceEntry) \
530 | ((PWCHAR)((ULONG_PTR)(ApiSetNamespace) + \
531 | ((PAPI_SET_NAMESPACE_ENTRY_V3)(NamespaceEntry))->NameOffset))
532 |
533 | #define GET_API_SET_NAMESPACE_ENTRY_DATA_V3(ApiSetNamespace, NamespaceEntry) \
534 | ((PAPI_SET_VALUE_ARRAY_V3)((ULONG_PTR)(ApiSetNamespace) + \
535 | ((PAPI_SET_NAMESPACE_ENTRY_V3)(NamespaceEntry))->DataOffset))
536 |
537 | #define GET_API_SET_VALUE_ENTRY_V3(ApiSetNamespace, ResolvedValueArray, Index) \
538 | ((PAPI_SET_VALUE_ENTRY_V3)(((PAPI_SET_VALUE_ARRAY_V3)(ResolvedValueArray))->Array + \
539 | Index))
540 |
541 | #define GET_API_SET_VALUE_ENTRY_NAME_V3(ApiSetNamespace, ApiSetValueEntry) \
542 | ((WCHAR*)((ULONG_PTR)(ApiSetNamespace) + \
543 | ((PAPI_SET_VALUE_ENTRY_V3)(ApiSetValueEntry))->NameOffset))
544 |
545 | #define GET_API_SET_VALUE_ENTRY_VALUE_V3(ApiSetNamespace, ApiSetValueEntry) \
546 | ((WCHAR*)((ULONG_PTR)(ApiSetNamespace) + \
547 | ((PAPI_SET_VALUE_ENTRY_V3)(ApiSetValueEntry))->ValueOffset))
548 |
549 | static
550 | PAPI_SET_VALUE_ENTRY_V3
551 | ApiSetpSearchForApiSetHostV3(
552 | _In_ PAPI_SET_VALUE_ARRAY_V3 ApiSetValueArray,
553 | _In_ WCHAR *ApiSetNameToResolve,
554 | _In_ USHORT ApiSetNameToResolveLength,
555 | _In_ PAPI_SET_NAMESPACE_ARRAY_V3 ApiSetNamespace
556 | )
557 | {
558 | LONG Low;
559 | LONG Middle;
560 | LONG High;
561 | LONG Result;
562 | PAPI_SET_VALUE_ENTRY_V3 ApiSetValueEntry;
563 |
564 | Low = 1; // skip first entry.
565 | High = ApiSetValueArray->Count - 1;
566 |
567 | while (High >= Low) {
568 | Middle = (High + Low) >> 1;
569 |
570 | ApiSetValueEntry = GET_API_SET_VALUE_ENTRY_V3(ApiSetNamespace, ApiSetValueArray, Middle);
571 |
572 | Result = RtlCompareUnicodeStrings(ApiSetNameToResolve,
573 | ApiSetNameToResolveLength,
574 | GET_API_SET_VALUE_ENTRY_NAME_V3(ApiSetNamespace,
575 | ApiSetValueEntry),
576 | ApiSetValueEntry->NameLength,
577 | TRUE);
578 | if (Result < 0) {
579 | High = Middle - 1;
580 | } else if (Result > 0) {
581 | Low = Middle + 1;
582 | } else {
583 | return ApiSetValueEntry;
584 | }
585 | }
586 |
587 | return NULL;
588 | }
589 |
590 | NTSTATUS
591 | APISETAPI
592 | ApiSetResolveToHostV3(
593 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace,
594 | _In_ PCUNICODE_STRING ApiSetNameToResolve,
595 | _In_opt_ PCUNICODE_STRING ParentName,
596 | _Out_ PBOOLEAN Resolved,
597 | _Out_ PUNICODE_STRING Output
598 | )
599 | {
600 | NTSTATUS Status;
601 | BOOLEAN IsResolved;
602 | ULONGLONG ApiSetNameBufferPrefix;
603 | LONG Low;
604 | LONG Middle;
605 | LONG High;
606 | LONG Result;
607 | PAPI_SET_NAMESPACE_ARRAY_V3 ApiSetNamespaceArray;
608 | PAPI_SET_NAMESPACE_ENTRY_V3 ResolvedNamespaceEntry;
609 | PAPI_SET_VALUE_ARRAY_V3 ResolvedValueArray;
610 | PAPI_SET_VALUE_ENTRY_V3 HostLibraryEntry;
611 | UNICODE_STRING ApiSetNameNoExtString;
612 |
613 | IsResolved = FALSE;
614 | RtlInitEmptyUnicodeString(Output, NULL, 0);
615 |
616 | //
617 | // Make sure the API Set name is a valid length.
618 | //
619 | if (ApiSetNameToResolve->Length < sizeof(API_SET_PREFIX_API_)) {
620 | goto Exit;
621 | }
622 |
623 | //
624 | // Check library name starts with "api-" or "ext-"
625 | //
626 | ApiSetNameBufferPrefix = *(ULONGLONG*)ApiSetNameToResolve->Buffer;
627 | ApiSetNameBufferPrefix &= ~(ULONGLONG)0x0000002000200020; // Trick to convert the chars to lowercase.
628 | if (ApiSetNameBufferPrefix != API_SET_PREFIX_API_ &&
629 | ApiSetNameBufferPrefix != API_SET_PREFIX_EXT_) {
630 | goto Exit;
631 | }
632 |
633 | //
634 | // Skip the prefix.
635 | //
636 | ApiSetNameNoExtString.Length = ApiSetNameToResolve->Length - sizeof(API_SET_PREFIX_API_);
637 | ApiSetNameNoExtString.MaximumLength = ApiSetNameNoExtString.Length;
638 | ApiSetNameNoExtString.Buffer = (WCHAR*)((ULONG_PTR)ApiSetNameToResolve->Buffer +
639 | sizeof(API_SET_PREFIX_API_));
640 |
641 | //
642 | // Cut off the '.DLL' extension.
643 | //
644 | if (ApiSetNameNoExtString.Length >= sizeof(API_SET_DLL_EXTENSTION) &&
645 | ApiSetNameNoExtString.Buffer[(ApiSetNameNoExtString.Length -
646 | sizeof(API_SET_DLL_EXTENSTION)) / sizeof(WCHAR)] == L'.') {
647 | ApiSetNameNoExtString.Length -= sizeof(API_SET_DLL_EXTENSTION);
648 | }
649 |
650 | ApiSetNamespaceArray = (PAPI_SET_NAMESPACE_ARRAY_V3)ApiSetNamespace;
651 | ResolvedNamespaceEntry = NULL;
652 |
653 | Low = 0;
654 | High = (LONG)(ApiSetNamespaceArray->Count - 1);
655 |
656 | while (High >= Low) {
657 | Middle = (Low + High) >> 1;
658 |
659 | ResolvedNamespaceEntry = GET_API_SET_NAMESPACE_ENTRY_V3(ApiSetNamespace, Middle);
660 |
661 | Result = RtlCompareUnicodeStrings(ApiSetNameNoExtString.Buffer,
662 | ApiSetNameNoExtString.Length / sizeof(WCHAR),
663 | GET_API_SET_NAMESPACE_ENTRY_NAME_V3(ApiSetNamespace,
664 | ResolvedNamespaceEntry),
665 | ResolvedNamespaceEntry->NameLength / sizeof(WCHAR),
666 | TRUE
667 | );
668 | if (Result < 0) {
669 | High = Middle - 1;
670 | } else if (Result > 0) {
671 | Low = Middle + 1;
672 | } else {
673 | break;
674 | }
675 | }
676 |
677 | //
678 | // If the high index is less than the low index, then a matching namespace
679 | // entry was not found.
680 | //
681 | if (High < Low) {
682 | goto Exit;
683 | }
684 |
685 | //
686 | // Get the namspace value array.
687 | //
688 | ResolvedValueArray = GET_API_SET_NAMESPACE_ENTRY_DATA_V3(ApiSetNamespace, ResolvedNamespaceEntry);
689 |
690 | //
691 | // Look for aliases in hosts libraries if necessary.
692 | //
693 | if (ResolvedValueArray->Count > 1 && ParentName) {
694 |
695 | HostLibraryEntry = ApiSetpSearchForApiSetHostV3(ResolvedValueArray,
696 | ParentName->Buffer,
697 | ParentName->Length / sizeof(WCHAR),
698 | (PAPI_SET_NAMESPACE_ARRAY_V3)ApiSetNamespace
699 | );
700 | } else {
701 | HostLibraryEntry = NULL;
702 | }
703 |
704 | //
705 | // Default to the first value entry.
706 | //
707 | if (!HostLibraryEntry) {
708 | HostLibraryEntry = GET_API_SET_VALUE_ENTRY_V3(ApiSetNamespace, ResolvedValueArray, 0);
709 | }
710 |
711 | //
712 | // Output resolved host library.
713 | //
714 | Output->Length = (USHORT)HostLibraryEntry->ValueLength;
715 | Output->MaximumLength = Output->Length;
716 | Output->Buffer = GET_API_SET_VALUE_ENTRY_VALUE_V3(ApiSetNamespace, HostLibraryEntry);
717 |
718 | IsResolved = TRUE;
719 |
720 | Exit:
721 | Status = STATUS_SUCCESS;
722 | *Resolved = IsResolved;
723 |
724 | return Status;
725 | }
726 |
727 |
728 |
729 | //
730 | // API Set Schema Version 2
731 | //
732 |
733 | #define GET_API_SET_NAMESPACE_ENTRY_V2(ApiSetNamespace, Index) \
734 | ((PAPI_SET_NAMESPACE_ENTRY_V2)((ULONG_PTR)(ApiSetNamespace) + \
735 | ((PAPI_SET_NAMESPACE_ARRAY_V2)(ApiSetNamespace))->Array + \
736 | Index))
737 |
738 | static
739 | PAPI_SET_VALUE_ENTRY_V2
740 | ApiSetpSearchForApiSetHostV2(
741 | _In_ PAPI_SET_VALUE_ARRAY_V2 ApiSetValueArray,
742 | _In_ PCUNICODE_STRING ApiToResolve,
743 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace
744 | )
745 | {
746 | LONG Low;
747 | LONG Middle;
748 | LONG High;
749 | LONG Result;
750 | UNICODE_STRING ApiSetHostString;
751 | PAPI_SET_VALUE_ENTRY_V2 ApiSetValueEntry;
752 |
753 | Low = 1; // skip first entry.
754 | High = ApiSetValueArray->Count - 1;
755 |
756 | while (High >= Low) {
757 | Middle = (High + Low) >> 1;
758 |
759 | ApiSetValueEntry = &ApiSetValueArray->Array[Middle];
760 | ApiSetHostString.Length = (USHORT)ApiSetValueEntry->NameLength;
761 | ApiSetHostString.MaximumLength = ApiSetHostString.Length;
762 | ApiSetHostString.Buffer = (WCHAR*)((ULONG_PTR)ApiSetNamespace + ApiSetValueEntry->NameOffset);
763 |
764 | Result = RtlCompareUnicodeString(ApiToResolve, &ApiSetHostString, TRUE);
765 |
766 | if (Result < 0) {
767 | High = Middle - 1;
768 | } else if (Result > 0) {
769 | Low = Middle + 1;
770 | } else {
771 | return ApiSetValueEntry;
772 | }
773 | }
774 |
775 | return NULL;
776 | }
777 |
778 | NTSTATUS
779 | APISETAPI
780 | ApiSetResolveToHostV2(
781 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace,
782 | _In_ PCUNICODE_STRING ApiSetNameToResolve,
783 | _In_opt_ PCUNICODE_STRING ParentName,
784 | _Out_ PBOOLEAN Resolved,
785 | _Out_ PUNICODE_STRING Output
786 | )
787 | {
788 | NTSTATUS Status;
789 | BOOLEAN IsResolved;
790 | ULONGLONG ApiSetNameBufferPrefix;
791 | LONG Low;
792 | LONG Middle;
793 | LONG High;
794 | LONG Result;
795 | PAPI_SET_NAMESPACE_ARRAY_V2 ApiSetNamespaceArray;
796 | PAPI_SET_NAMESPACE_ENTRY_V2 ApiSetNamespaceEntry;
797 | PAPI_SET_VALUE_ARRAY_V2 ApiSetValueArray;
798 | PAPI_SET_VALUE_ENTRY_V2 HostLibraryEntry;
799 | UNICODE_STRING ApiSetNamespaceString;
800 | UNICODE_STRING ApiSetNameNoExtString;
801 |
802 | IsResolved = FALSE;
803 | RtlInitEmptyUnicodeString(Output, NULL, 0);
804 |
805 | //
806 | // Make sure the API Set name is a valid length.
807 | //
808 | if (ApiSetNameToResolve->Length < sizeof(API_SET_PREFIX_API_)) {
809 | goto Exit;
810 | }
811 |
812 | //
813 | // Check library name starts with "api-"
814 | //
815 | ApiSetNameBufferPrefix = *(ULONGLONG*)ApiSetNameToResolve->Buffer;
816 | ApiSetNameBufferPrefix &= ~(ULONGLONG)0x0000002000200020; // Trick to convert the chars to lowercase.
817 | if (ApiSetNameBufferPrefix != API_SET_PREFIX_API_) {
818 | goto Exit;
819 | }
820 |
821 | //
822 | // Skip the prefix.
823 | //
824 | ApiSetNameNoExtString.Length = ApiSetNameToResolve->Length - sizeof(API_SET_PREFIX_API_);
825 | ApiSetNameNoExtString.MaximumLength = ApiSetNameNoExtString.Length;
826 | ApiSetNameNoExtString.Buffer = (WCHAR*)((ULONG_PTR)ApiSetNameToResolve->Buffer +
827 | sizeof(API_SET_PREFIX_API_));
828 |
829 | //
830 | // Cut off the '.DLL' extension.
831 | //
832 | if (ApiSetNameNoExtString.Length >= sizeof(API_SET_DLL_EXTENSTION) &&
833 | ApiSetNameNoExtString.Buffer[(ApiSetNameNoExtString.Length -
834 | sizeof(API_SET_DLL_EXTENSTION)) / sizeof(WCHAR)] == L'.') {
835 | ApiSetNameNoExtString.Length -= sizeof(API_SET_DLL_EXTENSTION);
836 | }
837 |
838 | ApiSetNamespaceArray = (PAPI_SET_NAMESPACE_ARRAY_V2)ApiSetNamespace;
839 | ApiSetNamespaceEntry = NULL;
840 |
841 | Low = 0;
842 | High = (LONG)(ApiSetNamespaceArray->Count - 1);
843 |
844 | while (High >= Low) {
845 | Middle = (Low + High) >> 1;
846 |
847 | ApiSetNamespaceEntry = GET_API_SET_NAMESPACE_ENTRY_V2(ApiSetNamespace, Middle);
848 | ApiSetNamespaceString.Length = (USHORT)ApiSetNamespaceEntry->NameLength;
849 | ApiSetNamespaceString.MaximumLength = ApiSetNamespaceString.Length;
850 | ApiSetNamespaceString.Buffer = (WCHAR*)((ULONG_PTR)ApiSetNamespace +
851 | ApiSetNamespaceEntry->NameOffset);
852 |
853 | Result = RtlCompareUnicodeString(&ApiSetNameNoExtString, &ApiSetNamespaceString, TRUE);
854 |
855 | if (Result < 0) {
856 | High = Middle - 1;
857 | } else if (Result > 0) {
858 | Low = Middle + 1;
859 | } else {
860 | break;
861 | }
862 | }
863 |
864 | //
865 | // If the high index is less than the low index, then a matching namespace
866 | // entry was not found.
867 | //
868 | if (High < Low) {
869 | goto Exit;
870 | }
871 |
872 | //
873 | // Get the namspace value array.
874 | //
875 | ApiSetValueArray = (PAPI_SET_VALUE_ARRAY_V2)((ULONG_PTR)ApiSetNamespace +
876 | ApiSetNamespaceEntry->DataOffset);
877 |
878 | //
879 | // Look for aliases in hosts libraries if necessary.
880 | //
881 | if (ApiSetValueArray->Count > 1 && ParentName) {
882 |
883 | HostLibraryEntry = ApiSetpSearchForApiSetHostV2(ApiSetValueArray,
884 | ParentName,
885 | ApiSetNamespace
886 | );
887 | } else {
888 | HostLibraryEntry = NULL;
889 | }
890 |
891 | //
892 | // Default to the first value entry.
893 | //
894 | if (!HostLibraryEntry) {
895 | HostLibraryEntry = ApiSetValueArray->Array;
896 | }
897 |
898 | //
899 | // Output resolved host library.
900 | //
901 | Output->Length = (USHORT)HostLibraryEntry->ValueLength;
902 | Output->MaximumLength = Output->Length;
903 | Output->Buffer = (WCHAR*)((ULONG_PTR)ApiSetNamespace + HostLibraryEntry->ValueOffset);
904 |
905 | IsResolved = TRUE;
906 |
907 | Exit:
908 | Status = STATUS_SUCCESS;
909 | *Resolved = IsResolved;
910 |
911 | return Status;
912 | }
913 |
--------------------------------------------------------------------------------
/apiset.h:
--------------------------------------------------------------------------------
1 | /**
2 | * API Set Lookup
3 | * Copyright (c) 2018-2019 Aidan Khoury. All rights reserved.
4 | *
5 | * @file apiset.h
6 | * @author Aidan Khoury (ajkhoury)
7 | * @date 11/22/2018
8 | */
9 |
10 | #ifndef _API_SET_H_
11 | #define _API_SET_H_
12 | #if defined(_MSC_VER)
13 | #pragma once
14 | #endif
15 |
16 | #include "ntapi.h"
17 |
18 | // API Set calling convention
19 | #define APISETAPI NTAPI
20 |
21 |
22 | //
23 | // API schema definitions.
24 | //
25 |
26 | #define API_SET_SCHEMA_VERSION_V2 0x00000002
27 | #define API_SET_SCHEMA_VERSION_V3 0x00000003 // No offline support.
28 | #define API_SET_SCHEMA_VERSION_V4 0x00000004
29 | #define API_SET_SCHEMA_VERSION_V6 0x00000006
30 |
31 |
32 | //
33 | // API Set data structures
34 | //
35 |
36 | typedef struct _API_SET_NAMESPACE {
37 | ULONG Version;
38 | } API_SET_NAMESPACE, *PAPI_SET_NAMESPACE;
39 |
40 |
41 | //
42 | // API set schema version 6.
43 | //
44 |
45 | typedef struct _API_SET_NAMESPACE_V6 {
46 | ULONG Version;
47 | ULONG Size;
48 | ULONG Flags;
49 | ULONG Count;
50 | ULONG EntryOffset; // API_SET_NAMESPACE_ENTRY_V6
51 | ULONG HashOffset; // API_SET_NAMESPACE_HASH_ENTRY_V6
52 | ULONG HashFactor;
53 | } API_SET_NAMESPACE_V6, *PAPI_SET_NAMESPACE_V6;
54 |
55 | typedef struct _API_SET_NAMESPACE_ENTRY_V6 {
56 | ULONG Flags;
57 | ULONG NameOffset;
58 | ULONG NameLength;
59 | ULONG HashedLength;
60 | ULONG ValueOffset;
61 | ULONG ValueCount;
62 | } API_SET_NAMESPACE_ENTRY_V6, *PAPI_SET_NAMESPACE_ENTRY_V6;
63 |
64 | typedef struct _API_SET_HASH_ENTRY_V6 {
65 | ULONG Hash;
66 | ULONG Index;
67 | } API_SET_HASH_ENTRY_V6, *PAPI_SET_HASH_ENTRY_V6;
68 |
69 | typedef struct _API_SET_VALUE_ENTRY_V6 {
70 | ULONG Flags;
71 | ULONG NameOffset;
72 | ULONG NameLength;
73 | ULONG ValueOffset;
74 | ULONG ValueLength;
75 | } API_SET_VALUE_ENTRY_V6, *PAPI_SET_VALUE_ENTRY_V6;
76 |
77 | typedef const API_SET_VALUE_ENTRY_V6 *PCAPI_SET_VALUE_ENTRY_V6;
78 | typedef const API_SET_HASH_ENTRY_V6 *PCAPI_SET_HASH_ENTRY_V6;
79 | typedef const API_SET_NAMESPACE_ENTRY_V6 *PCAPI_SET_NAMESPACE_ENTRY_V6;
80 | typedef const API_SET_NAMESPACE_V6 *PCAPI_SET_NAMESPACE_V6;
81 |
82 |
83 | //
84 | // API set schema version 4.
85 | //
86 |
87 | typedef struct _API_SET_VALUE_ENTRY_V4 {
88 | ULONG Flags; // 0x00
89 | ULONG NameOffset; // 0x04
90 | ULONG NameLength; // 0x08
91 | ULONG ValueOffset; // 0x0C
92 | ULONG ValueLength; // 0x10
93 | } API_SET_VALUE_ENTRY_V4, *PAPI_SET_VALUE_ENTRY_V4;
94 |
95 | typedef struct _API_SET_VALUE_ARRAY_V4 {
96 | ULONG Flags; // 0x00
97 | ULONG Count; // 0x04
98 | API_SET_VALUE_ENTRY_V4 Array[ANYSIZE_ARRAY];
99 | } API_SET_VALUE_ARRAY_V4, *PAPI_SET_VALUE_ARRAY_V4;
100 |
101 | typedef struct _API_SET_NAMESPACE_ENTRY_V4 {
102 | ULONG Flags;
103 | ULONG NameOffset;
104 | ULONG NameLength;
105 | ULONG AliasOffset;
106 | ULONG AliasLength;
107 | ULONG DataOffset; // API_SET_VALUE_ARRAY_V4
108 | } API_SET_NAMESPACE_ENTRY_V4, *PAPI_SET_NAMESPACE_ENTRY_V4;
109 |
110 | typedef struct _API_SET_NAMESPACE_ARRAY_V4 {
111 | ULONG Version; // 0x00
112 | ULONG Size; // 0x04
113 | ULONG Flags; // 0x08
114 | ULONG Count; // 0x0C
115 | API_SET_NAMESPACE_ENTRY_V4 Array[ANYSIZE_ARRAY];
116 | } API_SET_NAMESPACE_ARRAY_V4, *PAPI_SET_NAMESPACE_ARRAY_V4;
117 |
118 | typedef const API_SET_VALUE_ENTRY_V4 *PCAPI_SET_VALUE_ENTRY_V4;
119 | typedef const API_SET_VALUE_ARRAY_V4 *PCAPI_SET_VALUE_ARRAY_V4;
120 | typedef const API_SET_NAMESPACE_ENTRY_V4 *PCAPI_SET_NAMESPACE_ENTRY_V4;
121 | typedef const API_SET_NAMESPACE_ARRAY_V4 *PCAPI_SET_NAMESPACE_ARRAY_V4;
122 |
123 | #define API_SET_SCHEMA_FLAGS_SEALED 0x00000001
124 | #define API_SET_SCHEMA_FLAGS_HOST_EXTENSION 0x00000002
125 |
126 | #define API_SET_SCHEMA_ENTRY_FLAGS_SEALED 0x00000001
127 | #define API_SET_SCHEMA_ENTRY_FLAGS_EXTENSION 0x00000002
128 |
129 | //
130 | // API set schema version 3.
131 | //
132 |
133 | typedef struct _API_SET_VALUE_ENTRY_V3 {
134 | ULONG NameOffset;
135 | ULONG NameLength;
136 | ULONG ValueOffset;
137 | ULONG ValueLength;
138 | } API_SET_VALUE_ENTRY_V3, *PAPI_SET_VALUE_ENTRY_V3;
139 |
140 | typedef struct _API_SET_VALUE_ARRAY_V3 {
141 | ULONG Count;
142 | API_SET_VALUE_ENTRY_V3 Array[ANYSIZE_ARRAY];
143 | } API_SET_VALUE_ARRAY_V3, *PAPI_SET_VALUE_ARRAY_V3;
144 |
145 | typedef struct _API_SET_NAMESPACE_ENTRY_V3 {
146 | ULONG NameOffset;
147 | ULONG NameLength;
148 | ULONG DataOffset; // API_SET_VALUE_ARRAY_V3
149 | } API_SET_NAMESPACE_ENTRY_V3, *PAPI_SET_NAMESPACE_ENTRY_V3;
150 |
151 | typedef struct _API_SET_NAMESPACE_ARRAY_V3 {
152 | ULONG Version;
153 | ULONG Count;
154 | API_SET_NAMESPACE_ENTRY_V3 Array[ANYSIZE_ARRAY];
155 | } API_SET_NAMESPACE_ARRAY_V3, *PAPI_SET_NAMESPACE_ARRAY_V3;
156 |
157 | typedef const API_SET_VALUE_ENTRY_V3 *PCAPI_SET_VALUE_ENTRY_V3;
158 | typedef const API_SET_VALUE_ARRAY_V3 *PCAPI_SET_VALUE_ARRAY_V3;
159 | typedef const API_SET_NAMESPACE_ENTRY_V3 *PCAPI_SET_NAMESPACE_ENTRY_V3;
160 | typedef const API_SET_NAMESPACE_ARRAY_V3 *PCAPI_SET_NAMESPACE_ARRAY_V3;
161 |
162 | //
163 | // Support for downlevel API set schema version 2.
164 | //
165 |
166 | typedef struct _API_SET_VALUE_ENTRY_V2 {
167 | ULONG NameOffset;
168 | ULONG NameLength;
169 | ULONG ValueOffset;
170 | ULONG ValueLength;
171 | } API_SET_VALUE_ENTRY_V2, *PAPI_SET_VALUE_ENTRY_V2;
172 |
173 | typedef struct _API_SET_VALUE_ARRAY_V2 {
174 | ULONG Count;
175 | API_SET_VALUE_ENTRY_V2 Array[ANYSIZE_ARRAY];
176 | } API_SET_VALUE_ARRAY_V2, *PAPI_SET_VALUE_ARRAY_V2;
177 |
178 | typedef struct _API_SET_NAMESPACE_ENTRY_V2 {
179 | ULONG NameOffset;
180 | ULONG NameLength;
181 | ULONG DataOffset; // API_SET_VALUE_ARRAY_V2
182 | } API_SET_NAMESPACE_ENTRY_V2, *PAPI_SET_NAMESPACE_ENTRY_V2;
183 |
184 | typedef struct _API_SET_NAMESPACE_ARRAY_V2 {
185 | ULONG Version;
186 | ULONG Count;
187 | API_SET_NAMESPACE_ENTRY_V2 Array[ANYSIZE_ARRAY];
188 | } API_SET_NAMESPACE_ARRAY_V2, *PAPI_SET_NAMESPACE_ARRAY_V2;
189 |
190 | typedef const API_SET_VALUE_ENTRY_V2 *PCAPI_SET_VALUE_ENTRY_V2;
191 | typedef const API_SET_VALUE_ARRAY_V2 *PCAPI_SET_VALUE_ARRAY_V2;
192 | typedef const API_SET_NAMESPACE_ENTRY_V2 *PCAPI_SET_NAMESPACE_ENTRY_V2;
193 | typedef const API_SET_NAMESPACE_ARRAY_V2 *PCAPI_SET_NAMESPACE_ARRAY_V2;
194 |
195 |
196 | //
197 | // API Set Routines
198 | //
199 |
200 | NTSTATUS
201 | APISETAPI
202 | ApiSetResolveToHostV6(
203 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace,
204 | _In_ PCUNICODE_STRING ApiSetNameToResolve,
205 | _In_opt_ PCUNICODE_STRING ParentName,
206 | _Out_ PBOOLEAN Resolved,
207 | _Out_ PUNICODE_STRING Output
208 | );
209 |
210 | NTSTATUS
211 | APISETAPI
212 | ApiSetResolveToHostV4(
213 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace,
214 | _In_ PCUNICODE_STRING ApiSetNameToResolve,
215 | _In_opt_ PCUNICODE_STRING ParentName,
216 | _Out_ PBOOLEAN Resolved,
217 | _Out_ PUNICODE_STRING Output
218 | );
219 |
220 | NTSTATUS
221 | APISETAPI
222 | ApiSetResolveToHostV3(
223 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace,
224 | _In_ PCUNICODE_STRING ApiSetNameToResolve,
225 | _In_opt_ PCUNICODE_STRING ParentName,
226 | _Out_ PBOOLEAN Resolved,
227 | _Out_ PUNICODE_STRING Output
228 | );
229 |
230 | NTSTATUS
231 | APISETAPI
232 | ApiSetResolveToHostV2(
233 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace,
234 | _In_ PCUNICODE_STRING ApiSetNameToResolve,
235 | _In_opt_ PCUNICODE_STRING ParentName,
236 | _Out_ PBOOLEAN Resolved,
237 | _Out_ PUNICODE_STRING Output
238 | );
239 |
240 | BOOLEAN
241 | APISETAPI
242 | ApiSetResolve(
243 | _In_z_ PWCHAR ApiSetName,
244 | _In_opt_z_ PWCHAR BaseDllName,
245 | _Out_ PUNICODE_STRING ResolvedHostLibrary
246 | );
247 |
248 | #endif // _ODIN_API_SET_H_
--------------------------------------------------------------------------------
/apiset.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29418.71
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apiset", "apiset.vcxproj", "{EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}.Debug|x64.ActiveCfg = Debug|x64
17 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}.Debug|x64.Build.0 = Debug|x64
18 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}.Debug|x86.ActiveCfg = Debug|Win32
19 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}.Debug|x86.Build.0 = Debug|Win32
20 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}.Release|x64.ActiveCfg = Release|x64
21 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}.Release|x64.Build.0 = Release|x64
22 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}.Release|x86.ActiveCfg = Release|Win32
23 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {9DB7E6ED-C673-46CA-B623-50B1DDAE4204}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/apiset.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}
24 | apiset
25 | 10.0
26 |
27 |
28 |
29 | Application
30 | true
31 | v142
32 | MultiByte
33 |
34 |
35 | Application
36 | false
37 | v142
38 | true
39 | MultiByte
40 |
41 |
42 | Application
43 | true
44 | v142
45 | MultiByte
46 |
47 |
48 | Application
49 | false
50 | v142
51 | true
52 | MultiByte
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | apiset
74 |
75 |
76 |
77 | Level3
78 | Disabled
79 | true
80 | true
81 |
82 |
83 | Console
84 | ntdll.lib;%(AdditionalDependencies)
85 |
86 |
87 |
88 |
89 | Level3
90 | Disabled
91 | true
92 | true
93 | CompileAsC
94 |
95 |
96 | Console
97 | ntdll.lib;%(AdditionalDependencies)
98 |
99 |
100 |
101 |
102 | Level3
103 | MaxSpeed
104 | true
105 | true
106 | true
107 | true
108 |
109 |
110 | Console
111 | true
112 | true
113 |
114 |
115 |
116 |
117 | Level3
118 | MaxSpeed
119 | true
120 | true
121 | true
122 | true
123 | MultiThreaded
124 |
125 |
126 | Console
127 | true
128 | true
129 | ntdll.lib;%(AdditionalDependencies)
130 | false
131 |
132 |
133 | copy "$(OutDir)$(TargetName)$(TargetExt)" "F:\tools\bin\$(TargetName)$(TargetExt)"
134 |
135 |
136 | Copying to tools directory...
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
--------------------------------------------------------------------------------
/apiset.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 | Source Files
23 |
24 |
25 | Source Files
26 |
27 |
28 | Source Files
29 |
30 |
31 | Source Files
32 |
33 |
34 |
35 |
36 | Header Files
37 |
38 |
39 | Header Files
40 |
41 |
42 | Header Files
43 |
44 |
45 | Header Files
46 |
47 |
48 | Header Files
49 |
50 |
51 | Header Files
52 |
53 |
54 |
--------------------------------------------------------------------------------
/main.c:
--------------------------------------------------------------------------------
1 | /**
2 | * API Set Lookup
3 | * Copyright (c) 2018-2019 Aidan Khoury. All rights reserved.
4 | *
5 | * @file apiset.c
6 | * @authors Aidan Khoury (ajkhoury)
7 | * lucasg
8 | * @date 11/22/2018
9 | */
10 |
11 | #include "apiset.h"
12 |
13 | #include
14 |
15 | void help()
16 | {
17 | wprintf(L"ApiSet : resolve api set host library\n");
18 | wprintf(L"Usage:\n apiset ext-some-api-set-library-l1-1-0.dll [base_dll_name]\n");
19 | }
20 |
21 | int wmain(int argc, wchar_t* argv[])
22 | {
23 | PWCHAR ApiSetName;
24 | PWCHAR BaseDllName;
25 | UNICODE_STRING HostApi;
26 | WCHAR HostLibraryName[MAX_PATH];
27 |
28 | if (argc < 2) {
29 | help();
30 | return -1;
31 | }
32 |
33 | if (wcscmp(argv[1], L"-h") == 0 ||
34 | wcscmp(argv[1], L"/?") == 0 ||
35 | wcscmp(argv[1], L"-help") == 0 ||
36 | wcscmp(argv[1], L"--help") == 0) {
37 | help();
38 | return 0;
39 | }
40 |
41 | //
42 | // Process arguments.
43 | //
44 | ApiSetName = argv[1];
45 |
46 | if (argc > 2) {
47 | BaseDllName = argv[2];
48 | } else {
49 | BaseDllName = NULL;
50 | }
51 |
52 | //
53 | // Attempt to resolve API Set library.
54 | //
55 | if (!ApiSetResolve(ApiSetName, BaseDllName, &HostApi)) {
56 | wprintf(L"[x] Could not resolve Api set library : %s\n", ApiSetName);
57 | return -1;
58 | }
59 |
60 | //
61 | // Output the resolved host library.
62 | //
63 | if (wcsncpy_s(HostLibraryName, RTL_NUMBER_OF(HostLibraryName), HostApi.Buffer, HostApi.Length)) {
64 | wprintf(L"[x] Could not copy resolved host library name\n");
65 | return -1;
66 | }
67 | HostLibraryName[HostApi.Length / sizeof(WCHAR)] = '\0';
68 |
69 | wprintf(L"[!] Api set library resolved : %s -> %s\n", ApiSetName, HostLibraryName);
70 |
71 | return 0;
72 | }
73 |
--------------------------------------------------------------------------------
/nls.c:
--------------------------------------------------------------------------------
1 | #include "ntrtl.h"
2 |
3 | /**
4 | * Compares two counted Unicode strings. The return value indicates if the
5 | * strings are equal or String1 is less than String2 or String1 is greater
6 | * than String2.
7 | *
8 | * The CaseInSensitive parameter specifies if case is to be ignored when
9 | * doing the comparison.
10 | *
11 | * @param[in] String1 Pointer to the first string.
12 | * @param[in] Length1 Length of the first string.
13 | * @param[in] String2 Pointer to the second string.
14 | * @param[in] Length2 Length of the second string.
15 | * @param[in] CaseInSensitive If TRUE, case should be ignored when doing
16 | * the comparison.
17 | *
18 | * @return Signed value that gives the results of the comparison:
19 | * Zero - String1 equals String2
20 | * < Zero - String1 less than String2
21 | * > Zero - String1 greater than String2
22 | */
23 | LONG
24 | NTAPI
25 | RtlCompareUnicodeStrings(
26 | IN CONST WCHAR* String1,
27 | IN SIZE_T Length1,
28 | IN CONST WCHAR* String2,
29 | IN SIZE_T Length2,
30 | IN BOOLEAN CaseInSensitive
31 | )
32 | {
33 | CONST WCHAR* s1, * s2, * Limit;
34 | LONG n1, n2;
35 | UINT32 c1, c2;
36 |
37 | if (Length1 > LONG_MAX || Length2 > LONG_MAX) {
38 | return STATUS_INVALID_BUFFER_SIZE;
39 | }
40 |
41 | s1 = String1;
42 | s2 = String2;
43 | n1 = (LONG)Length1;
44 | n2 = (LONG)Length2;
45 |
46 | Limit = (WCHAR*)((CHAR*)s1 + (n1 <= n2 ? n1 : n2));
47 | if (CaseInSensitive) {
48 | while (s1 < Limit) {
49 | c1 = *s1;
50 | c2 = *s2;
51 | if (c1 != c2) {
52 |
53 | //
54 | // Note that this needs to reference the translation table!
55 | //
56 | c1 = RTL_UPCASE(c1);
57 | c2 = RTL_UPCASE(c2);
58 | if (c1 != c2) {
59 | return (INT32)(c1)-(INT32)(c2);
60 | }
61 | }
62 | s1 += 1;
63 | s2 += 1;
64 | }
65 |
66 | } else {
67 |
68 | while (s1 < Limit) {
69 | c1 = *s1;
70 | c2 = *s2;
71 | if (c1 != c2) {
72 | return (LONG)(c1)-(LONG)(c2);
73 | }
74 | s1 += 1;
75 | s2 += 1;
76 | }
77 | }
78 |
79 | return n1 - n2;
80 | }
--------------------------------------------------------------------------------
/ntapi.h:
--------------------------------------------------------------------------------
1 | #ifndef _NTAPI_
2 | #define _NTAPI_
3 |
4 | #include
5 | #include
6 |
7 | #include "ntstatus.h"
8 |
9 | //
10 | // Counted String
11 | //
12 |
13 | typedef USHORT RTL_STRING_LENGTH_TYPE;
14 |
15 | typedef struct _STRING {
16 | USHORT Length;
17 | USHORT MaximumLength;
18 | #ifdef MIDL_PASS
19 | [size_is(MaximumLength), length_is(Length)]
20 | #endif // MIDL_PASS
21 | _Field_size_bytes_part_opt_(MaximumLength, Length) PCHAR Buffer;
22 | } STRING;
23 | typedef STRING* PSTRING;
24 | typedef STRING ANSI_STRING;
25 | typedef PSTRING PANSI_STRING;
26 |
27 | // end_sdfwdm
28 | // end_wudfwdm
29 |
30 | typedef STRING OEM_STRING;
31 | typedef PSTRING POEM_STRING;
32 | typedef CONST STRING* PCOEM_STRING;
33 |
34 | //
35 | // CONSTCounted String
36 | //
37 |
38 | typedef struct _CSTRING {
39 | USHORT Length;
40 | USHORT MaximumLength;
41 | CONST char* Buffer;
42 | } CSTRING;
43 | typedef CSTRING* PCSTRING;
44 | #ifndef ANSI_NULL
45 | #define ANSI_NULL ((CHAR)0)
46 | #endif
47 |
48 | // begin_wudfwdm
49 | // begin_sdfwdm
50 |
51 | typedef STRING CANSI_STRING;
52 | typedef PSTRING PCANSI_STRING;
53 |
54 | //
55 | // Unicode strings are counted 16-bit character strings. If they are
56 | // NULL terminated, Length does not include trailing NULL.
57 | //
58 |
59 | typedef struct _UNICODE_STRING {
60 | USHORT Length;
61 | USHORT MaximumLength;
62 | #ifdef MIDL_PASS
63 | [size_is(MaximumLength / 2), length_is((Length) / 2)] USHORT* Buffer;
64 | #else // MIDL_PASS
65 | _Field_size_bytes_part_opt_(MaximumLength, Length) PWCH Buffer;
66 | #endif // MIDL_PASS
67 | } UNICODE_STRING;
68 | typedef UNICODE_STRING* PUNICODE_STRING;
69 | typedef const UNICODE_STRING* PCUNICODE_STRING;
70 |
71 | #ifndef UNICODE_NULL
72 | #define UNICODE_NULL ((WCHAR)0)
73 | #endif
74 |
75 | #if _WIN32_WINNT >= 0x0500
76 |
77 | #ifndef UNICODE_STRING_MAX_BYTES
78 | #define UNICODE_STRING_MAX_BYTES ((USHORT) 65534) // winnt
79 | #endif
80 | #ifndef UNICODE_STRING_MAX_CHARS
81 | #define UNICODE_STRING_MAX_CHARS (32767) // winnt
82 | #endif
83 |
84 | #define DECLARE_CONST_UNICODE_STRING(_var, _string) \
85 | const WCHAR _var ## _buffer[] = _string; \
86 | __pragma(warning(push)) \
87 | __pragma(warning(disable:4221)) __pragma(warning(disable:4204)) \
88 | const UNICODE_STRING _var = { sizeof(_string) - sizeof(WCHAR), sizeof(_string), (PWCH) _var ## _buffer } \
89 | __pragma(warning(pop))
90 |
91 | #define DECLARE_GLOBAL_CONST_UNICODE_STRING(_var, _str) \
92 | extern const __declspec(selectany) UNICODE_STRING _var = RTL_CONSTANT_STRING(_str)
93 |
94 | #define DECLARE_UNICODE_STRING_SIZE(_var, _size) \
95 | WCHAR _var ## _buffer[_size]; \
96 | __pragma(warning(push)) \
97 | __pragma(warning(disable:4221)) __pragma(warning(disable:4204)) \
98 | UNICODE_STRING _var = { 0, (_size) * sizeof(WCHAR) , _var ## _buffer } \
99 | __pragma(warning(pop))
100 |
101 | #endif // _WIN32_WINNT >= 0x0500
102 |
103 | //
104 | // This is the maximum MaximumLength for a UNICODE_STRING.
105 | //
106 | #ifndef MAX_USTRING
107 | #define MAX_USTRING ( sizeof(WCHAR) * (MAXUSHORT/sizeof(WCHAR)) )
108 | #endif
109 |
110 |
111 | //
112 | // Balanced tree node (AVL or RB) structure definition.
113 | //
114 | #if defined(_MSC_VER)
115 | #pragma warning(push)
116 | #pragma warning(disable:4214)
117 | #endif
118 | typedef struct _RTL_BALANCED_NODE {
119 | union {
120 | struct _RTL_BALANCED_NODE* Children[2];
121 | struct {
122 | struct _RTL_BALANCED_NODE* Left;
123 | struct _RTL_BALANCED_NODE* Right;
124 | } DUMMYSTRUCTNAME;
125 | } DUMMYUNIONNAME;
126 |
127 | #define RTL_BALANCED_NODE_RESERVED_PARENT_MASK 3
128 |
129 | union {
130 | UCHAR Red : 1;
131 | UCHAR Balance : 2;
132 | ULONG_PTR ParentValue;
133 | } DUMMYUNIONNAME2;
134 | } RTL_BALANCED_NODE, * PRTL_BALANCED_NODE;
135 | #if defined(_MSC_VER)
136 | #pragma warning(pop)
137 | #endif
138 |
139 | #define RTL_BALANCED_NODE_GET_PARENT_POINTER(Node) \
140 | ((PRTL_BALANCED_NODE)((Node)->ParentValue & \
141 | ~RTL_BALANCED_NODE_RESERVED_PARENT_MASK))
142 |
143 |
144 | typedef struct _STRING32 {
145 | USHORT Length;
146 | USHORT MaximumLength;
147 | ULONG Buffer;
148 | } STRING32;
149 | typedef STRING32* PSTRING32;
150 |
151 | typedef STRING32 UNICODE_STRING32;
152 | typedef UNICODE_STRING32* PUNICODE_STRING32;
153 |
154 | typedef STRING32 ANSI_STRING32;
155 | typedef ANSI_STRING32* PANSI_STRING32;
156 |
157 |
158 | typedef struct _STRING64 {
159 | USHORT Length;
160 | USHORT MaximumLength;
161 | ULONGLONG Buffer;
162 | } STRING64;
163 | typedef STRING64* PSTRING64;
164 |
165 | typedef STRING64 UNICODE_STRING64;
166 | typedef UNICODE_STRING64* PUNICODE_STRING64;
167 |
168 | typedef STRING64 ANSI_STRING64;
169 | typedef ANSI_STRING64* PANSI_STRING64;
170 |
171 | //
172 | // Valid values for the Attributes field
173 | //
174 |
175 | #ifndef OBJ_INHERIT
176 | #define OBJ_INHERIT 0x00000002L
177 | #endif
178 | #ifndef OBJ_PERMANENT
179 | #define OBJ_PERMANENT 0x00000010L
180 | #endif
181 | #ifndef OBJ_EXCLUSIVE
182 | #define OBJ_EXCLUSIVE 0x00000020L
183 | #endif
184 | #ifndef OBJ_CASE_INSENSITIVE
185 | #define OBJ_CASE_INSENSITIVE 0x00000040L
186 | #endif
187 | #ifndef OBJ_OPENIF
188 | #define OBJ_OPENIF 0x00000080L
189 | #endif
190 | #ifndef OBJ_OPENLINK
191 | #define OBJ_OPENLINK 0x00000100L
192 | #endif
193 | #ifndef OBJ_KERNEL_HANDLE
194 | #define OBJ_KERNEL_HANDLE 0x00000200L
195 | #endif
196 | #ifndef OBJ_FORCE_ACCESS_CHECK
197 | #define OBJ_FORCE_ACCESS_CHECK 0x00000400L
198 | #endif
199 | #ifndef OBJ_IGNORE_IMPERSONATED_DEVICEMAP
200 | #define OBJ_IGNORE_IMPERSONATED_DEVICEMAP 0x00000800L
201 | #endif
202 | #ifndef OBJ_DONT_REPARSE
203 | #define OBJ_DONT_REPARSE 0x00001000L
204 | #endif
205 | #ifndef OBJ_VALID_ATTRIBUTES
206 | #define OBJ_VALID_ATTRIBUTES 0x00001FF2L
207 | #endif
208 |
209 | //
210 | // Object Attributes structure
211 | //
212 |
213 | typedef struct _OBJECT_ATTRIBUTES64 {
214 | ULONG Length;
215 | ULONG64 RootDirectory;
216 | ULONG64 ObjectName;
217 | ULONG Attributes;
218 | ULONG64 SecurityDescriptor;
219 | ULONG64 SecurityQualityOfService;
220 | } OBJECT_ATTRIBUTES64;
221 | typedef OBJECT_ATTRIBUTES64* POBJECT_ATTRIBUTES64;
222 | typedef CONST OBJECT_ATTRIBUTES64* PCOBJECT_ATTRIBUTES64;
223 |
224 | typedef struct _OBJECT_ATTRIBUTES32 {
225 | ULONG Length;
226 | ULONG RootDirectory;
227 | ULONG ObjectName;
228 | ULONG Attributes;
229 | ULONG SecurityDescriptor;
230 | ULONG SecurityQualityOfService;
231 | } OBJECT_ATTRIBUTES32;
232 | typedef OBJECT_ATTRIBUTES32* POBJECT_ATTRIBUTES32;
233 | typedef CONST OBJECT_ATTRIBUTES32* PCOBJECT_ATTRIBUTES32;
234 |
235 |
236 | typedef struct _OBJECT_ATTRIBUTES {
237 | ULONG Length;
238 | HANDLE RootDirectory;
239 | PUNICODE_STRING ObjectName;
240 | ULONG Attributes;
241 | PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR
242 | PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE
243 | } OBJECT_ATTRIBUTES;
244 | typedef OBJECT_ATTRIBUTES* POBJECT_ATTRIBUTES;
245 | typedef CONST OBJECT_ATTRIBUTES* PCOBJECT_ATTRIBUTES;
246 |
247 | //++
248 | //
249 | // VOID
250 | // InitializeObjectAttributes(
251 | // _Out_ POBJECT_ATTRIBUTES p,
252 | // _In_ PUNICODE_STRING n,
253 | // _In_ ULONG a,
254 | // _In_ HANDLE r,
255 | // _In_ PSECURITY_DESCRIPTOR s
256 | // )
257 | //
258 | //--
259 |
260 | #define InitializeObjectAttributes( p, n, a, r, s ) { \
261 | (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
262 | (p)->RootDirectory = r; \
263 | (p)->Attributes = a; \
264 | (p)->ObjectName = n; \
265 | (p)->SecurityDescriptor = s; \
266 | (p)->SecurityQualityOfService = NULL; \
267 | }
268 |
269 |
270 | // RTL_ to avoid collisions in the global namespace.
271 | // I don't believe there are possible/likely constant RootDirectory
272 | // or SecurityDescriptor values other than NULL, so they are hardcoded.
273 | // As well, the string will generally be const, so we cast that away.
274 | #define RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a) \
275 | { sizeof(OBJECT_ATTRIBUTES), NULL, RTL_CONST_CAST(PUNICODE_STRING)(n), a, NULL, NULL }
276 |
277 | // This synonym is more appropriate for initializing what isn't actually const.
278 | #define RTL_INIT_OBJECT_ATTRIBUTES(n, a) RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a)
279 |
280 |
281 | #include
282 |
283 | #ifndef __OBJECTID_DEFINED
284 | #define __OBJECTID_DEFINED
285 |
286 | typedef struct _OBJECTID { // size is 20
287 | GUID Lineage;
288 | ULONG Uniquifier;
289 | } OBJECTID;
290 | #endif // !_OBJECTID_DEFINED
291 |
292 | #ifndef MINCHAR
293 | #define MINCHAR 0x80
294 | #endif
295 | #ifndef MAXCHAR
296 | #define MAXCHAR 0x7f
297 | #endif
298 | #ifndef MINSHORT
299 | #define MINSHORT 0x8000
300 | #endif
301 | #ifndef MAXSHORT
302 | #define MAXSHORT 0x7fff
303 | #endif
304 | #ifndef MINLONG
305 | #define MINLONG 0x80000000
306 | #endif
307 | #ifndef MAXLONG
308 | #define MAXLONG 0x7fffffff
309 | #endif
310 | #ifndef MAXUCHAR
311 | #define MAXUCHAR 0xff
312 | #endif
313 | #ifndef MAXUSHORT
314 | #define MAXUSHORT 0xffff
315 | #endif
316 | #ifndef MAXULONG
317 | #define MAXULONG 0xffffffff
318 | #endif
319 |
320 | //
321 | // Determine if an argument is present by testing the value of the pointer
322 | // to the argument value.
323 | //
324 |
325 | #ifndef ARGUMENT_PRESENT
326 | #define ARGUMENT_PRESENT(ArgumentPointer) (\
327 | (CHAR *)((ULONG_PTR)(ArgumentPointer)) != (CHAR *)(NULL) )
328 | #endif
329 |
330 |
331 | #define LOW_PRIORITY 0 // Lowest thread priority level
332 | #define LOW_REALTIME_PRIORITY 16 // Lowest realtime priority level
333 | #define HIGH_PRIORITY 31 // Highest thread priority level
334 | #define MAXIMUM_PRIORITY 32 // Number of thread priority levels
335 |
336 | #define MAXIMUM_WAIT_OBJECTS 64 // Maximum number of wait objects
337 |
338 | #define MAXIMUM_SUSPEND_COUNT MAXCHAR // Maximum times thread can be suspended
339 |
340 | //
341 | // Event type
342 | //
343 |
344 | typedef enum _EVENT_TYPE {
345 | NotificationEvent,
346 | SynchronizationEvent
347 | } EVENT_TYPE;
348 |
349 | //
350 | // Timer type
351 | //
352 |
353 | typedef enum _TIMER_TYPE {
354 | NotificationTimer,
355 | SynchronizationTimer
356 | } TIMER_TYPE;
357 |
358 | //
359 | // Wait type
360 | //
361 |
362 | typedef enum _WAIT_TYPE {
363 | WaitAll,
364 | WaitAny,
365 | WaitNotification,
366 | WaitDequeue
367 | } WAIT_TYPE;
368 |
369 | //
370 | // Processor modes.
371 | //
372 |
373 | typedef enum _MODE {
374 | KernelMode,
375 | UserMode,
376 | MaximumMode
377 | } MODE;
378 |
379 | typedef INT8 KPROCESSOR_MODE;
380 |
381 | //
382 | // Define system time structure.
383 | //
384 |
385 | typedef struct _KSYSTEM_TIME {
386 | ULONG LowPart;
387 | LONG High1Time;
388 | LONG High2Time;
389 | } KSYSTEM_TIME, * PKSYSTEM_TIME;
390 |
391 |
392 | //
393 | // Thread priority
394 | //
395 |
396 | typedef LONG KPRIORITY;
397 |
398 | //
399 | // Spin Lock
400 | //
401 |
402 | typedef ULONG_PTR KSPIN_LOCK;
403 | typedef KSPIN_LOCK* PKSPIN_LOCK;
404 |
405 | //
406 | // Update Sequence Number
407 | //
408 |
409 | typedef LONGLONG USN;
410 |
411 |
412 | //
413 | // Client ID
414 | //
415 |
416 | typedef struct _CLIENT_ID {
417 | HANDLE UniqueProcess;
418 | HANDLE UniqueThread;
419 | } CLIENT_ID;
420 | typedef CLIENT_ID* PCLIENT_ID;
421 |
422 |
423 | #ifndef _PHYSICAL_ADDRESS_T
424 | #define _PHYSICAL_ADDRESS_T
425 |
426 | //
427 | // Physical address.
428 | //
429 |
430 | typedef LARGE_INTEGER PHYSICAL_ADDRESS, * PPHYSICAL_ADDRESS;
431 |
432 | #endif // _PHYSICAL_ADDRESS_T
433 |
434 |
435 | //
436 | // Profile source types
437 | //
438 |
439 | typedef enum _KPROFILE_SOURCE {
440 | ProfileTime,
441 | ProfileAlignmentFixup,
442 | ProfileTotalIssues,
443 | ProfilePipelineDry,
444 | ProfileLoadInstructions,
445 | ProfilePipelineFrozen,
446 | ProfileBranchInstructions,
447 | ProfileTotalNonissues,
448 | ProfileDcacheMisses,
449 | ProfileIcacheMisses,
450 | ProfileCacheMisses,
451 | ProfileBranchMispredictions,
452 | ProfileStoreInstructions,
453 | ProfileFpInstructions,
454 | ProfileIntegerInstructions,
455 | Profile2Issue,
456 | Profile3Issue,
457 | Profile4Issue,
458 | ProfileSpecialInstructions,
459 | ProfileTotalCycles,
460 | ProfileIcacheIssues,
461 | ProfileDcacheAccesses,
462 | ProfileMemoryBarrierCycles,
463 | ProfileLoadLinkedIssues,
464 | ProfileMaximum
465 | } KPROFILE_SOURCE;
466 |
467 | #include "ntpsapi.h"
468 |
469 | #endif // _NTAPI_
470 |
--------------------------------------------------------------------------------
/ntpsapi.h:
--------------------------------------------------------------------------------
1 | #ifndef _NTPSAPI_
2 | #define _NTPSAPI_
3 | #if _MSC_VER > 1000
4 | #pragma once
5 | #endif
6 |
7 | #if defined(_MSC_VER)
8 | #pragma warning(push)
9 | #pragma warning(disable : 4201) // nonstandard extension used: nameless struct/union
10 | #pragma warning(disable : 4214) // nonstandard extension used: bit field types other than int
11 | #endif // _MSC_VER
12 |
13 | #ifdef __cplusplus
14 | extern "C" {
15 | #endif
16 |
17 | //
18 | // Process Environment Block and Thread Environment Block
19 | //
20 |
21 | //
22 | // Handle tag bits for Peb Stdio File Handles
23 | //
24 |
25 | #define PEB_STDIO_HANDLE_NATIVE 0
26 | #define PEB_STDIO_HANDLE_SUBSYS 1
27 | #define PEB_STDIO_HANDLE_PM 2
28 | #define PEB_STDIO_HANDLE_RESERVED 3
29 |
30 | #define GDI_HANDLE_BUFFER_SIZE32 34
31 | #define GDI_HANDLE_BUFFER_SIZE64 60
32 |
33 | #if !(defined(_M_AMD64) || defined(__x86_64__))
34 | #define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE32
35 | #else
36 | #define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE64
37 | #endif
38 |
39 | typedef ULONG GDI_HANDLE_BUFFER32[GDI_HANDLE_BUFFER_SIZE32];
40 | typedef ULONG GDI_HANDLE_BUFFER64[GDI_HANDLE_BUFFER_SIZE64];
41 | typedef ULONG GDI_HANDLE_BUFFER [GDI_HANDLE_BUFFER_SIZE ];
42 |
43 | #define FOREGROUND_BASE_PRIORITY 9
44 | #define NORMAL_BASE_PRIORITY 8
45 |
46 | typedef struct _PEB_FREE_BLOCK {
47 | struct _PEB_FREE_BLOCK *Next;
48 | ULONG Size;
49 | } PEB_FREE_BLOCK, *PPEB_FREE_BLOCK;
50 |
51 |
52 | #if !defined(CLIENT_ID64_DEFINED)
53 |
54 | typedef struct _CLIENT_ID64 {
55 | ULONG64 UniqueProcess;
56 | ULONG64 UniqueThread;
57 | } CLIENT_ID64;
58 | typedef CLIENT_ID64 *PCLIENT_ID64;
59 |
60 | typedef struct _CLIENT_ID32 {
61 | ULONG UniqueProcess;
62 | ULONG UniqueThread;
63 | } CLIENT_ID32;
64 | typedef CLIENT_ID32 *PCLIENT_ID32;
65 |
66 | #define CLIENT_ID64_DEFINED
67 | #endif
68 |
69 | #ifndef FLS_MAXIMUM_AVAILABLE
70 | #define FLS_MAXIMUM_AVAILABLE 128
71 | #endif
72 | #ifndef TLS_MINIMUM_AVAILABLE
73 | #define TLS_MINIMUM_AVAILABLE 64
74 | #endif
75 | #ifndef TLS_EXPANSION_SLOTS
76 | #define TLS_EXPANSION_SLOTS 1024
77 | #endif
78 |
79 | typedef
80 | VOID
81 | (*PPS_POST_PROCESS_INIT_ROUTINE) (
82 | VOID
83 | );
84 |
85 |
86 | //
87 | // Thread Environment Block (and portable part of Thread Information Block)
88 | //
89 |
90 | //
91 | // NT_TIB - Thread Information Block - Portable part.
92 | //
93 | // This is the subsystem portable part of the Thread Information Block.
94 | // It appears as the first part of the TEB for all threads which have
95 | // a user mode component.
96 | //
97 | // This structure MUST MATCH OS/2 V2.0!
98 | //
99 | // There is another, non-portable part of the TIB which is used
100 | // for by subsystems, i.e. Os2Tib for OS/2 threads. SubSystemTib
101 | // points there.
102 | //
103 | //
104 |
105 | #if !defined(_NTDDK_) && !defined(_WINNT_)
106 |
107 | typedef struct _NT_TIB {
108 | struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;
109 | PVOID StackBase;
110 | PVOID StackLimit;
111 | PVOID SubSystemTib;
112 | union {
113 | PVOID FiberData;
114 | ULONG Version;
115 | };
116 | PVOID ArbitraryUserPointer;
117 | struct _NT_TIB *Self;
118 | } NT_TIB;
119 | typedef NT_TIB *PNT_TIB;
120 |
121 | //
122 | // 32 and 64 bit specific version for wow64 and the debugger
123 | //
124 | typedef struct _NT_TIB32 {
125 | ULONG ExceptionList;
126 | ULONG StackBase;
127 | ULONG StackLimit;
128 | ULONG SubSystemTib;
129 | union {
130 | ULONG FiberData;
131 | ULONG Version;
132 | };
133 | ULONG ArbitraryUserPointer;
134 | ULONG Self;
135 | } NT_TIB32, *PNT_TIB32;
136 |
137 | typedef struct _NT_TIB64 {
138 | ULONG64 ExceptionList;
139 | ULONG64 StackBase;
140 | ULONG64 StackLimit;
141 | ULONG64 SubSystemTib;
142 | union {
143 | ULONG64 FiberData;
144 | ULONG Version;
145 | };
146 | ULONG64 ArbitraryUserPointer;
147 | ULONG64 Self;
148 | } NT_TIB64, *PNT_TIB64;
149 |
150 | #endif // !_NTDDK_ && !_WINNT_
151 |
152 |
153 | //
154 | // Gdi command batching
155 | //
156 |
157 | #define GDI_BATCH_BUFFER_SIZE 310
158 |
159 | typedef struct _GDI_TEB_BATCH {
160 | ULONG Offset;
161 | ULONG_PTR HDC;
162 | ULONG Buffer[GDI_BATCH_BUFFER_SIZE];
163 | } GDI_TEB_BATCH,*PGDI_TEB_BATCH;
164 |
165 | typedef struct _GDI_TEB_BATCH64 {
166 | ULONG Offset;
167 | ULONG64 HDC;
168 | ULONG Buffer[GDI_BATCH_BUFFER_SIZE];
169 | } GDI_TEB_BATCH64, *PGDI_TEB_BATCH64;
170 |
171 | typedef struct _GDI_TEB_BATCH32 {
172 | ULONG Offset;
173 | ULONG HDC;
174 | ULONG Buffer[GDI_BATCH_BUFFER_SIZE];
175 | } GDI_TEB_BATCH32, *PGDI_TEB_BATCH32;
176 |
177 | //
178 | // Wx86 thread state information
179 | //
180 |
181 | typedef struct _Wx86ThreadState {
182 | ULONG *CallBx86Eip;
183 | PVOID DeallocationCpu;
184 | BOOLEAN UseKnownWx86Dll;
185 | CHAR OleStubInvoked;
186 | } WX86THREAD, *PWX86THREAD;
187 |
188 | //
189 | // WoW64 Process
190 | //
191 |
192 | typedef struct _WOW64_PROCESS {
193 | PVOID Wow64;
194 | } WOW64_PROCESS, *PWOW64_PROCESS;
195 |
196 | //
197 | // TEB - The thread environment block
198 | //
199 |
200 | #define STATIC_UNICODE_BUFFER_LENGTH 261
201 | #define WIN32_CLIENT_INFO_LENGTH 62
202 |
203 | #define WIN32_CLIENT_INFO_SPIN_COUNT 1
204 |
205 | typedef PVOID* PPVOID;
206 |
207 | #include "pebteb.h"
208 |
209 | #define TYPE32(x) ULONG
210 | #define TYPE64(x) ULONG64
211 |
212 | #define PEBTEB_BITS 32
213 |
214 | #include "pebteb.h"
215 |
216 | #undef PEBTEB_BITS
217 |
218 | #define PEBTEB_BITS 64
219 |
220 | #include "pebteb.h"
221 |
222 | #undef PEBTEB_BITS
223 |
224 |
225 | typedef struct _INITIAL_TEB {
226 | struct {
227 | PVOID OldStackBase;
228 | PVOID OldStackLimit;
229 | } OldInitialTeb;
230 | PVOID StackBase;
231 | PVOID StackLimit;
232 | PVOID StackAllocationBase;
233 | } INITIAL_TEB, *PINITIAL_TEB;
234 |
235 |
236 | #define PROCESS_PRIORITY_CLASS_UNKNOWN 0
237 | #define PROCESS_PRIORITY_CLASS_IDLE 1
238 | #define PROCESS_PRIORITY_CLASS_NORMAL 2
239 | #define PROCESS_PRIORITY_CLASS_HIGH 3
240 | #define PROCESS_PRIORITY_CLASS_REALTIME 4
241 | #define PROCESS_PRIORITY_CLASS_BELOW_NORMAL 5
242 | #define PROCESS_PRIORITY_CLASS_ABOVE_NORMAL 6
243 |
244 | typedef struct _PROCESS_PRIORITY_CLASS {
245 | BOOLEAN Foreground;
246 | UINT8 PriorityClass;
247 | } PROCESS_PRIORITY_CLASS, * PPROCESS_PRIORITY_CLASS;
248 |
249 | typedef struct _PROCESS_FOREGROUND_BACKGROUND {
250 | BOOLEAN Foreground;
251 | } PROCESS_FOREGROUND_BACKGROUND, * PPROCESS_FOREGROUND_BACKGROUND;
252 |
253 | //
254 | // Define process debug flags
255 | //
256 | #define PROCESS_DEBUG_INHERIT 0x00000001
257 |
258 | #if !defined(_NTDDK_)
259 |
260 | //
261 | // Process Information Classes
262 | //
263 |
264 | typedef enum _PROCESSINFOCLASS {
265 | ProcessBasicInformation, // q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION
266 | ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX
267 | ProcessIoCounters, // q: IO_COUNTERS
268 | ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX, VM_COUNTERS_EX2
269 | ProcessTimes, // q: KERNEL_USER_TIMES
270 | ProcessBasePriority, // s: KPRIORITY
271 | ProcessRaisePriority, // s: ULONG
272 | ProcessDebugPort, // q: HANDLE
273 | ProcessExceptionPort, // s: PROCESS_EXCEPTION_PORT
274 | ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN
275 | ProcessLdtInformation, // qs: PROCESS_LDT_INFORMATION // 10
276 | ProcessLdtSize, // s: PROCESS_LDT_SIZE
277 | ProcessDefaultHardErrorMode, // qs: ULONG
278 | ProcessIoPortHandlers, // (kernel-mode only)
279 | ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS
280 | ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void
281 | ProcessUserModeIOPL,
282 | ProcessEnableAlignmentFaultFixup, // s: BOOLEAN
283 | ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS
284 | ProcessWx86Information,
285 | ProcessHandleCount, // q: ULONG, PROCESS_HANDLE_INFORMATION // 20
286 | ProcessAffinityMask, // s: KAFFINITY
287 | ProcessPriorityBoost, // qs: ULONG
288 | ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX
289 | ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION
290 | ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND
291 | ProcessWow64Information, // q: ULONG_PTR
292 | ProcessImageFileName, // q: UNICODE_STRING
293 | ProcessLUIDDeviceMapsEnabled, // q: ULONG
294 | ProcessBreakOnTermination, // qs: ULONG
295 | ProcessDebugObjectHandle, // q: HANDLE // 30
296 | ProcessDebugFlags, // qs: ULONG
297 | ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables
298 | ProcessIoPriority, // qs: IO_PRIORITY_HINT
299 | ProcessExecuteFlags, // qs: ULONG
300 | ProcessResourceManagement, // ProcessTlsInformation // PROCESS_TLS_INFORMATION
301 | ProcessCookie, // q: ULONG
302 | ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION
303 | ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION // since VISTA
304 | ProcessPagePriority, // q: PAGE_PRIORITY_INFORMATION
305 | ProcessInstrumentationCallback, // qs: PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION // 40
306 | ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX
307 | ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[]
308 | ProcessImageFileNameWin32, // q: UNICODE_STRING
309 | ProcessImageFileMapping, // q: HANDLE (input)
310 | ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE
311 | ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE
312 | ProcessGroupInformation, // q: USHORT[]
313 | ProcessTokenVirtualizationEnabled, // s: ULONG
314 | ProcessConsoleHostProcess, // q: ULONG_PTR // ProcessOwnerInformation
315 | ProcessWindowInformation, // q: PROCESS_WINDOW_INFORMATION // 50
316 | ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8
317 | ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION
318 | ProcessDynamicFunctionTableInformation,
319 | ProcessHandleCheckingMode,
320 | ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION
321 | ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION
322 | ProcessWorkingSetControl, // s: PROCESS_WORKING_SET_CONTROL
323 | ProcessHandleTable, // since WINBLUE
324 | ProcessCheckStackExtentsMode,
325 | ProcessCommandLineInformation, // q: UNICODE_STRING // 60
326 | ProcessProtectionInformation, // q: PS_PROTECTION
327 | ProcessMemoryExhaustion, // PROCESS_MEMORY_EXHAUSTION_INFO // since THRESHOLD
328 | ProcessFaultInformation, // PROCESS_FAULT_INFORMATION
329 | ProcessTelemetryIdInformation, // PROCESS_TELEMETRY_ID_INFORMATION
330 | ProcessCommitReleaseInformation, // PROCESS_COMMIT_RELEASE_INFORMATION
331 | ProcessDefaultCpuSetsInformation,
332 | ProcessAllowedCpuSetsInformation,
333 | ProcessSubsystemProcess,
334 | ProcessJobMemoryInformation, // PROCESS_JOB_MEMORY_INFO
335 | ProcessInPrivate, // since THRESHOLD2 // 70
336 | ProcessRaiseUMExceptionOnInvalidHandleClose,
337 | ProcessIumChallengeResponse,
338 | ProcessChildProcessInformation, // PROCESS_CHILD_PROCESS_INFORMATION
339 | ProcessHighGraphicsPriorityInformation,
340 | ProcessSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2
341 | ProcessEnergyValues, // PROCESS_ENERGY_VALUES, PROCESS_EXTENDED_ENERGY_VALUES
342 | ProcessActivityThrottleState, // PROCESS_ACTIVITY_THROTTLE_STATE
343 | ProcessActivityThrottlePolicy, // PROCESS_ACTIVITY_THROTTLE_POLICY
344 | ProcessWin32kSyscallFilterInformation,
345 | ProcessDisableSystemAllowedCpuSets,
346 | ProcessWakeInformation, // PROCESS_WAKE_INFORMATION
347 | ProcessEnergyTrackingState, // PROCESS_ENERGY_TRACKING_STATE
348 | ProcessManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3
349 | ProcessCaptureTrustletLiveDump,
350 | ProcessTelemetryCoverage,
351 | ProcessEnclaveInformation,
352 | ProcessEnableReadWriteVmLogging, // PROCESS_READWRITEVM_LOGGING_INFORMATION
353 | ProcessUptimeInformation, // PROCESS_UPTIME_INFORMATION
354 | ProcessImageSection,
355 | ProcessDebugAuthInformation, // since REDSTONE4
356 | ProcessSystemResourceManagement, // PROCESS_SYSTEM_RESOURCE_MANAGEMENT
357 | ProcessSequenceNumber, // q: ULONGLONG
358 | MaxProcessInfoClass // MaxProcessInfoClass should always be the last enum
359 | } PROCESSINFOCLASS;
360 |
361 | //
362 | // Thread Information Classes
363 | //
364 |
365 | typedef enum _THREADINFOCLASS {
366 | ThreadBasicInformation, // q: THREAD_BASIC_INFORMATION
367 | ThreadTimes, // q: KERNEL_USER_TIMES
368 | ThreadPriority, // s: KPRIORITY
369 | ThreadBasePriority, // s: LONG
370 | ThreadAffinityMask, // s: KAFFINITY
371 | ThreadImpersonationToken, // s: HANDLE
372 | ThreadDescriptorTableEntry, // q: DESCRIPTOR_TABLE_ENTRY (or WOW64_DESCRIPTOR_TABLE_ENTRY)
373 | ThreadEnableAlignmentFaultFixup, // s: BOOLEAN
374 | ThreadEventPair,
375 | ThreadQuerySetWin32StartAddress, // q: PVOID
376 | ThreadZeroTlsCell, // 10
377 | ThreadPerformanceCount, // q: LARGE_INTEGER
378 | ThreadAmILastThread, // q: ULONG
379 | ThreadIdealProcessor, // s: ULONG
380 | ThreadPriorityBoost, // qs: ULONG
381 | ThreadSetTlsArrayAddress,
382 | ThreadIsIoPending, // q: ULONG
383 | ThreadHideFromDebugger, // s: void
384 | ThreadBreakOnTermination, // qs: ULONG
385 | ThreadSwitchLegacyState,
386 | ThreadIsTerminated, // q: ULONG // 20
387 | ThreadLastSystemCall, // q: THREAD_LAST_SYSCALL_INFORMATION
388 | ThreadIoPriority, // qs: IO_PRIORITY_HINT
389 | ThreadCycleTime, // q: THREAD_CYCLE_TIME_INFORMATION
390 | ThreadPagePriority, // q: ULONG
391 | ThreadActualBasePriority,
392 | ThreadTebInformation, // q: THREAD_TEB_INFORMATION (requires THREAD_GET_CONTEXT + THREAD_SET_CONTEXT)
393 | ThreadCSwitchMon,
394 | ThreadCSwitchPmu,
395 | ThreadWow64Context, // q: WOW64_CONTEXT
396 | ThreadGroupInformation, // q: GROUP_AFFINITY // 30
397 | ThreadUmsInformation, // q: THREAD_UMS_INFORMATION
398 | ThreadCounterProfiling,
399 | ThreadIdealProcessorEx, // q: PROCESSOR_NUMBER
400 | ThreadCpuAccountingInformation, // since WIN8
401 | ThreadSuspendCount, // since WINBLUE
402 | ThreadHeterogeneousCpuPolicy, // q: KHETERO_CPU_POLICY // since THRESHOLD
403 | ThreadContainerId, // q: GUID
404 | ThreadNameInformation, // qs: THREAD_NAME_INFORMATION
405 | ThreadSelectedCpuSets,
406 | ThreadSystemThreadInformation, // q: SYSTEM_THREAD_INFORMATION // 40
407 | ThreadActualGroupAffinity, // since THRESHOLD2
408 | ThreadDynamicCodePolicyInfo,
409 | ThreadExplicitCaseSensitivity,
410 | ThreadWorkOnBehalfTicket,
411 | ThreadSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2
412 | ThreadDbgkWerReportActive,
413 | ThreadAttachContainer,
414 | ThreadManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3
415 | ThreadPowerThrottlingState, // THREAD_POWER_THROTTLING_STATE
416 | MaxThreadInfoClass
417 | } THREADINFOCLASS;
418 |
419 | // Use with both ProcessPagePriority and ThreadPagePriority
420 | typedef struct _PAGE_PRIORITY_INFORMATION {
421 | ULONG PagePriority;
422 | } PAGE_PRIORITY_INFORMATION, * PPAGE_PRIORITY_INFORMATION;
423 |
424 | #endif // !_NTDDK_
425 |
426 | #define PROCESS_PRIORITY_SEPARATION_MASK 0x00000003
427 | #define PROCESS_PRIORITY_SEPARATION_MAX 0x00000002
428 | #define PROCESS_QUANTUM_VARIABLE_MASK 0x0000000c
429 | #define PROCESS_QUANTUM_VARIABLE_DEF 0x00000000
430 | #define PROCESS_QUANTUM_VARIABLE_VALUE 0x00000004
431 | #define PROCESS_QUANTUM_FIXED_VALUE 0x00000008
432 | #define PROCESS_QUANTUM_LONG_MASK 0x00000030
433 | #define PROCESS_QUANTUM_LONG_DEF 0x00000000
434 | #define PROCESS_QUANTUM_LONG_VALUE 0x00000010
435 | #define PROCESS_QUANTUM_SHORT_VALUE 0x00000020
436 |
437 |
438 | #define PROCESS_HARDERROR_ALIGNMENT_BIT 0x0004 // from winbase.h, but not tagged
439 | #if defined(_M_AMD64) || defined(__x86_64__)
440 | #define PROCESS_HARDERROR_DEFAULT (1 | PROCESS_HARDERROR_ALIGNMENT_BIT)
441 | #else
442 | #define PROCESS_HARDERROR_DEFAULT 1
443 | #endif
444 |
445 | //
446 | // thread base priority ranges
447 | //
448 | #define THREAD_BASE_PRIORITY_LOWRT 15 // value that gets a thread to LowRealtime-1
449 | #define THREAD_BASE_PRIORITY_MAX 2 // maximum thread base priority boost
450 | #define THREAD_BASE_PRIORITY_MIN (-2) // minimum thread base priority boost
451 | #define THREAD_BASE_PRIORITY_IDLE (-15) // value that gets a thread to idle
452 |
453 |
454 | //
455 | // Process Information Structures
456 | //
457 |
458 |
459 | #if !defined(_NTDDK_)
460 |
461 | //
462 | // PageFaultHistory Information
463 | // NtQueryInformationProcess using ProcessWorkingSetWatch
464 | //
465 | typedef struct _PROCESS_WS_WATCH_INFORMATION {
466 | PVOID FaultingPc;
467 | PVOID FaultingVa;
468 | } PROCESS_WS_WATCH_INFORMATION, * PPROCESS_WS_WATCH_INFORMATION;
469 |
470 | //
471 | // Basic Process Information
472 | // NtQueryInformationProcess using ProcessBasicInfo
473 | //
474 | typedef struct _PROCESS_BASIC_INFORMATION {
475 | NTSTATUS ExitStatus;
476 | PPEB PebBaseAddress;
477 | ULONG_PTR AffinityMask;
478 | KPRIORITY BasePriority;
479 | HANDLE UniqueProcessId;
480 | HANDLE InheritedFromUniqueProcessId;
481 | } PROCESS_BASIC_INFORMATION, * PPROCESS_BASIC_INFORMATION;
482 |
483 | typedef struct _PROCESS_BASIC_INFORMATION64 {
484 | NTSTATUS ExitStatus;
485 | ULONG Pad1;
486 | ULONG64 PebBaseAddress;
487 | ULONG64 AffinityMask;
488 | KPRIORITY BasePriority;
489 | ULONG Pad2;
490 | ULONG64 UniqueProcessId;
491 | ULONG64 InheritedFromUniqueProcessId;
492 | } PROCESS_BASIC_INFORMATION64;
493 | typedef PROCESS_BASIC_INFORMATION64* PPROCESS_BASIC_INFORMATION64;
494 |
495 | typedef struct _PROCESS_EXTENDED_BASIC_INFORMATION {
496 | SIZE_T Size; // set to sizeof structure on input
497 | PROCESS_BASIC_INFORMATION BasicInfo;
498 | union {
499 | ULONG Flags;
500 | struct {
501 | ULONG IsProtectedProcess : 1;
502 | ULONG IsWow64Process : 1;
503 | ULONG IsProcessDeleting : 1;
504 | ULONG IsCrossSessionCreate : 1;
505 | ULONG IsFrozen : 1;
506 | ULONG IsBackground : 1;
507 | ULONG IsStronglyNamed : 1;
508 | ULONG IsSecureProcess : 1;
509 | ULONG IsSubsystemProcess : 1;
510 | ULONG SpareBits : 23;
511 | };
512 | };
513 | } PROCESS_EXTENDED_BASIC_INFORMATION, * PPROCESS_EXTENDED_BASIC_INFORMATION;
514 |
515 | //
516 | // Process Device Map information
517 | // NtQueryInformationProcess using ProcessDeviceMap
518 | // NtSetInformationProcess using ProcessDeviceMap
519 | //
520 |
521 | typedef struct _PROCESS_DEVICEMAP_INFORMATION {
522 | union {
523 | struct {
524 | HANDLE DirectoryHandle;
525 | } Set;
526 | struct {
527 | ULONG DriveMap;
528 | UINT8 DriveType[32];
529 | } Query;
530 | } DUMMYUNIONNAME;
531 | } PROCESS_DEVICEMAP_INFORMATION, * PPROCESS_DEVICEMAP_INFORMATION;
532 |
533 | typedef struct _PROCESS_DEVICEMAP_INFORMATION_EX {
534 | union {
535 | struct {
536 | HANDLE DirectoryHandle;
537 | } Set;
538 | struct {
539 | ULONG DriveMap;
540 | UINT8 DriveType[32];
541 | } Query;
542 | } DUMMYUNIONNAME;
543 | ULONG Flags; // specifies that the query type
544 | } PROCESS_DEVICEMAP_INFORMATION_EX, * PPROCESS_DEVICEMAP_INFORMATION_EX;
545 |
546 | //
547 | // PROCESS_DEVICEMAP_INFORMATION_EX flags
548 | //
549 | #define PROCESS_LUID_DOSDEVICES_ONLY 0x00000001
550 |
551 | //
552 | // Multi-User Session specific Process Information
553 | // NtQueryInformationProcess using ProcessSessionInformation
554 | //
555 |
556 | typedef struct _PROCESS_SESSION_INFORMATION {
557 | ULONG SessionId;
558 | } PROCESS_SESSION_INFORMATION, * PPROCESS_SESSION_INFORMATION;
559 |
560 | typedef struct _PROCESS_HANDLE_TRACING_ENABLE {
561 | ULONG Flags;
562 | } PROCESS_HANDLE_TRACING_ENABLE, * PPROCESS_HANDLE_TRACING_ENABLE;
563 |
564 | typedef struct _PROCESS_HANDLE_TRACING_ENABLE_EX {
565 | ULONG Flags;
566 | ULONG TotalSlots;
567 | } PROCESS_HANDLE_TRACING_ENABLE_EX, * PPROCESS_HANDLE_TRACING_ENABLE_EX;
568 |
569 | #define PROCESS_HANDLE_EXCEPTIONS_ENABLED 0x00000001
570 |
571 | #define PROCESS_HANDLE_RAISE_UM_EXCEPTION_ON_INVALID_HANDLE_CLOSE_DISABLED 0x00000000
572 | #define PROCESS_HANDLE_RAISE_UM_EXCEPTION_ON_INVALID_HANDLE_CLOSE_ENABLED 0x00000001
573 |
574 | #define PROCESS_HANDLE_TRACING_MAX_STACKS 16
575 |
576 | typedef struct _PROCESS_HANDLE_TRACING_ENTRY {
577 | HANDLE Handle;
578 | struct _CLIENT_ID ClientId;
579 | ULONG Type;
580 | PVOID Stacks[PROCESS_HANDLE_TRACING_MAX_STACKS];
581 | } PROCESS_HANDLE_TRACING_ENTRY, * PPROCESS_HANDLE_TRACING_ENTRY;
582 |
583 | typedef struct _PROCESS_HANDLE_TRACING_QUERY {
584 | HANDLE Handle;
585 | ULONG TotalTraces;
586 | PROCESS_HANDLE_TRACING_ENTRY HandleTrace[1];
587 | } PROCESS_HANDLE_TRACING_QUERY, * PPROCESS_HANDLE_TRACING_QUERY;
588 |
589 | #if !defined(_WINNT_)
590 |
591 | //
592 | // Process Quotas
593 | // NtQueryInformationProcess using ProcessQuotaLimits
594 | // NtQueryInformationProcess using ProcessPooledQuotaLimits
595 | // NtSetInformationProcess using ProcessQuotaLimits
596 | //
597 |
598 | typedef struct _QUOTA_LIMITS {
599 | SIZE_T PagedPoolLimit;
600 | SIZE_T NonPagedPoolLimit;
601 | SIZE_T MinimumWorkingSetSize;
602 | SIZE_T MaximumWorkingSetSize;
603 | SIZE_T PagefileLimit;
604 | LARGE_INTEGER TimeLimit;
605 | } QUOTA_LIMITS, * PQUOTA_LIMITS;
606 |
607 |
608 | #define QUOTA_LIMITS_HARDWS_MIN_ENABLE 0x00000001
609 | #define QUOTA_LIMITS_HARDWS_MIN_DISABLE 0x00000002
610 | #define QUOTA_LIMITS_HARDWS_MAX_ENABLE 0x00000004
611 | #define QUOTA_LIMITS_HARDWS_MAX_DISABLE 0x00000008
612 | #define QUOTA_LIMITS_USE_DEFAULT_LIMITS 0x00000010
613 |
614 | typedef union _RATE_QUOTA_LIMIT {
615 | ULONG RateData;
616 | struct {
617 | ULONG RatePercent : 7;
618 | ULONG Reserved0 : 25;
619 | } DUMMYSTRUCTNAME;
620 | } RATE_QUOTA_LIMIT, * PRATE_QUOTA_LIMIT;
621 |
622 | typedef struct _QUOTA_LIMITS_EX {
623 | SIZE_T PagedPoolLimit;
624 | SIZE_T NonPagedPoolLimit;
625 | SIZE_T MinimumWorkingSetSize;
626 | SIZE_T MaximumWorkingSetSize;
627 | SIZE_T PagefileLimit; // Limit expressed in pages
628 | LARGE_INTEGER TimeLimit;
629 | SIZE_T WorkingSetLimit; // Limit expressed in pages
630 | SIZE_T Reserved2;
631 | SIZE_T Reserved3;
632 | SIZE_T Reserved4;
633 | ULONG Flags;
634 | RATE_QUOTA_LIMIT CpuRateLimit;
635 | } QUOTA_LIMITS_EX, * PQUOTA_LIMITS_EX;
636 |
637 | //
638 | // Process I/O Counters
639 | // NtQueryInformationProcess using ProcessIoCounters
640 | //
641 |
642 | typedef struct _IO_COUNTERS {
643 | ULONG64 ReadOperationCount;
644 | ULONG64 WriteOperationCount;
645 | ULONG64 OtherOperationCount;
646 | ULONG64 ReadTransferCount;
647 | ULONG64 WriteTransferCount;
648 | ULONG64 OtherTransferCount;
649 | } IO_COUNTERS;
650 | typedef IO_COUNTERS* PIO_COUNTERS;
651 |
652 | #endif // !_WINNT_
653 |
654 | //
655 | // Process Virtual Memory Counters
656 | // NtQueryInformationProcess using ProcessVmCounters
657 | //
658 |
659 | typedef struct _VM_COUNTERS {
660 | SIZE_T PeakVirtualSize;
661 | SIZE_T VirtualSize;
662 | ULONG PageFaultCount;
663 | SIZE_T PeakWorkingSetSize;
664 | SIZE_T WorkingSetSize;
665 | SIZE_T QuotaPeakPagedPoolUsage;
666 | SIZE_T QuotaPagedPoolUsage;
667 | SIZE_T QuotaPeakNonPagedPoolUsage;
668 | SIZE_T QuotaNonPagedPoolUsage;
669 | SIZE_T PagefileUsage;
670 | SIZE_T PeakPagefileUsage;
671 | } VM_COUNTERS, * PVM_COUNTERS;
672 |
673 | typedef struct _VM_COUNTERS_EX {
674 | SIZE_T PeakVirtualSize;
675 | SIZE_T VirtualSize;
676 | ULONG PageFaultCount;
677 | SIZE_T PeakWorkingSetSize;
678 | SIZE_T WorkingSetSize;
679 | SIZE_T QuotaPeakPagedPoolUsage;
680 | SIZE_T QuotaPagedPoolUsage;
681 | SIZE_T QuotaPeakNonPagedPoolUsage;
682 | SIZE_T QuotaNonPagedPoolUsage;
683 | SIZE_T PagefileUsage;
684 | SIZE_T PeakPagefileUsage;
685 | SIZE_T PrivateUsage;
686 | } VM_COUNTERS_EX, * PVM_COUNTERS_EX;
687 |
688 | typedef struct _VM_COUNTERS_EX2 {
689 | VM_COUNTERS_EX CountersEx;
690 | SIZE_T PrivateWorkingSetSize;
691 | SIZE_T SharedCommitUsage;
692 | } VM_COUNTERS_EX2, * PVM_COUNTERS_EX2;
693 |
694 |
695 | #if !defined(_WINNT_)
696 |
697 | #define MAX_HW_COUNTERS 16
698 | #define THREAD_PROFILING_FLAG_DISPATCH 0x00000001
699 |
700 | typedef enum _HARDWARE_COUNTER_TYPE {
701 | PMCCounter,
702 | MaxHardwareCounterType
703 | } HARDWARE_COUNTER_TYPE, * PHARDWARE_COUNTER_TYPE;
704 |
705 | #endif // !_WINNT_
706 |
707 | typedef struct _HARDWARE_COUNTER {
708 | HARDWARE_COUNTER_TYPE Type;
709 | ULONG Reserved;
710 | ULONG Index;
711 | } HARDWARE_COUNTER, * PHARDWARE_COUNTER;
712 |
713 |
714 | #if !defined(_WINNT_)
715 |
716 | //
717 | // Process mitigation policy information
718 | // NtSetInformationProcess using ProcessMitigationPolicy
719 | //
720 |
721 | typedef enum _PROCESS_MITIGATION_POLICY {
722 | ProcessDEPPolicy,
723 | ProcessASLRPolicy,
724 | ProcessDynamicCodePolicy,
725 | ProcessStrictHandleCheckPolicy,
726 | ProcessSystemCallDisablePolicy,
727 | ProcessMitigationOptionsMask,
728 | ProcessExtensionPointDisablePolicy,
729 | ProcessControlFlowGuardPolicy,
730 | ProcessSignaturePolicy,
731 | ProcessFontDisablePolicy,
732 | ProcessImageLoadPolicy,
733 | ProcessSystemCallFilterPolicy,
734 | ProcessPayloadRestrictionPolicy,
735 | ProcessChildProcessPolicy,
736 | MaxProcessMitigationPolicy
737 | } PROCESS_MITIGATION_POLICY, * PPROCESS_MITIGATION_POLICY;
738 |
739 | //
740 | // N.B. High entropy mode is read only and can only be set at creation time
741 | // and not via the ProcessMitigationPolicy APIs.
742 | //
743 | typedef struct _PROCESS_MITIGATION_ASLR_POLICY {
744 | union {
745 | ULONG Flags;
746 | struct {
747 | ULONG EnableBottomUpRandomization : 1;
748 | ULONG EnableForceRelocateImages : 1;
749 | ULONG EnableHighEntropy : 1;
750 | ULONG DisallowStrippedImages : 1;
751 | ULONG ReservedFlags : 28;
752 | } DUMMYSTRUCTNAME;
753 | } DUMMYUNIONNAME;
754 | } PROCESS_MITIGATION_ASLR_POLICY, * PPROCESS_MITIGATION_ASLR_POLICY;
755 |
756 | typedef struct _PROCESS_MITIGATION_DEP_POLICY {
757 | union {
758 | ULONG Flags;
759 | struct {
760 | ULONG Enable : 1;
761 | ULONG DisableAtlThunkEmulation : 1;
762 | ULONG ReservedFlags : 30;
763 | } DUMMYSTRUCTNAME;
764 | } DUMMYUNIONNAME;
765 | BOOLEAN Permanent;
766 | } PROCESS_MITIGATION_DEP_POLICY, * PPROCESS_MITIGATION_DEP_POLICY;
767 |
768 | typedef struct _PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY {
769 | union {
770 | ULONG Flags;
771 | struct {
772 | ULONG RaiseExceptionOnInvalidHandleReference : 1;
773 | ULONG HandleExceptionsPermanentlyEnabled : 1;
774 | ULONG ReservedFlags : 30;
775 | } DUMMYSTRUCTNAME;
776 | } DUMMYUNIONNAME;
777 | } PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY, * PPROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY;
778 |
779 | typedef struct _PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY {
780 | union {
781 | ULONG Flags;
782 | struct {
783 | ULONG DisallowWin32kSystemCalls : 1;
784 | ULONG AuditDisallowWin32kSystemCalls : 1;
785 | ULONG ReservedFlags : 30;
786 | } DUMMYSTRUCTNAME;
787 | } DUMMYUNIONNAME;
788 | } PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY, * PPROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY;
789 |
790 | typedef struct _PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY {
791 | union {
792 | ULONG Flags;
793 | struct {
794 | ULONG DisableExtensionPoints : 1;
795 | ULONG ReservedFlags : 31;
796 | } DUMMYSTRUCTNAME;
797 | } DUMMYUNIONNAME;
798 | } PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY, * PPROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY;
799 |
800 | typedef struct _PROCESS_MITIGATION_DYNAMIC_CODE_POLICY {
801 | union {
802 | ULONG Flags;
803 | struct {
804 | ULONG ProhibitDynamicCode : 1;
805 | ULONG AllowThreadOptOut : 1;
806 | ULONG AllowRemoteDowngrade : 1;
807 | ULONG AuditProhibitDynamicCode : 1;
808 | ULONG ReservedFlags : 28;
809 | } DUMMYSTRUCTNAME;
810 | } DUMMYUNIONNAME;
811 | } PROCESS_MITIGATION_DYNAMIC_CODE_POLICY, * PPROCESS_MITIGATION_DYNAMIC_CODE_POLICY;
812 | typedef struct _PROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY {
813 | union {
814 | ULONG Flags;
815 | struct {
816 | ULONG EnableControlFlowGuard : 1;
817 | ULONG EnableExportSuppression : 1;
818 | ULONG StrictMode : 1;
819 | ULONG ReservedFlags : 29;
820 | } DUMMYSTRUCTNAME;
821 | } DUMMYUNIONNAME;
822 | } PROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY, * PPROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY;
823 |
824 | typedef struct _PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY {
825 | union {
826 | ULONG Flags;
827 | struct {
828 | ULONG MicrosoftSignedOnly : 1;
829 | ULONG StoreSignedOnly : 1;
830 | ULONG MitigationOptIn : 1;
831 | ULONG AuditMicrosoftSignedOnly : 1;
832 | ULONG AuditStoreSignedOnly : 1;
833 | ULONG ReservedFlags : 27;
834 | } DUMMYSTRUCTNAME;
835 | } DUMMYUNIONNAME;
836 | } PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY, * PPROCESS_MITIGATION_BINARY_SIGNATURE_POLICY;
837 |
838 | typedef struct _PROCESS_MITIGATION_FONT_DISABLE_POLICY {
839 | union {
840 | ULONG Flags;
841 | struct {
842 | ULONG DisableNonSystemFonts : 1;
843 | ULONG AuditNonSystemFontLoading : 1;
844 | ULONG ReservedFlags : 30;
845 | } DUMMYSTRUCTNAME;
846 | } DUMMYUNIONNAME;
847 | } PROCESS_MITIGATION_FONT_DISABLE_POLICY, * PPROCESS_MITIGATION_FONT_DISABLE_POLICY;
848 |
849 | typedef struct _PROCESS_MITIGATION_IMAGE_LOAD_POLICY {
850 | union {
851 | ULONG Flags;
852 | struct {
853 | ULONG NoRemoteImages : 1;
854 | ULONG NoLowMandatoryLabelImages : 1;
855 | ULONG PreferSystem32Images : 1;
856 | ULONG AuditNoRemoteImages : 1;
857 | ULONG AuditNoLowMandatoryLabelImages : 1;
858 | ULONG ReservedFlags : 27;
859 | } DUMMYSTRUCTNAME;
860 | } DUMMYUNIONNAME;
861 | } PROCESS_MITIGATION_IMAGE_LOAD_POLICY, * PPROCESS_MITIGATION_IMAGE_LOAD_POLICY;
862 |
863 | typedef struct _PROCESS_MITIGATION_SYSTEM_CALL_FILTER_POLICY {
864 | union {
865 | ULONG Flags;
866 | struct {
867 | ULONG FilterId : 4;
868 | ULONG ReservedFlags : 28;
869 | } DUMMYSTRUCTNAME;
870 | } DUMMYUNIONNAME;
871 | } PROCESS_MITIGATION_SYSTEM_CALL_FILTER_POLICY, * PPROCESS_MITIGATION_SYSTEM_CALL_FILTER_POLICY;
872 |
873 | typedef struct _PROCESS_MITIGATION_PAYLOAD_RESTRICTION_POLICY {
874 | union {
875 | ULONG Flags;
876 | struct {
877 | ULONG EnableExportAddressFilter : 1;
878 | ULONG AuditExportAddressFilter : 1;
879 |
880 | ULONG EnableExportAddressFilterPlus : 1;
881 | ULONG AuditExportAddressFilterPlus : 1;
882 |
883 | ULONG EnableImportAddressFilter : 1;
884 | ULONG AuditImportAddressFilter : 1;
885 |
886 | ULONG EnableRopStackPivot : 1;
887 | ULONG AuditRopStackPivot : 1;
888 |
889 | ULONG EnableRopCallerCheck : 1;
890 | ULONG AuditRopCallerCheck : 1;
891 |
892 | ULONG EnableRopSimExec : 1;
893 | ULONG AuditRopSimExec : 1;
894 |
895 | ULONG ReservedFlags : 20;
896 | } DUMMYSTRUCTNAME;
897 | } DUMMYUNIONNAME;
898 | } PROCESS_MITIGATION_PAYLOAD_RESTRICTION_POLICY, * PPROCESS_MITIGATION_PAYLOAD_RESTRICTION_POLICY;
899 |
900 | typedef struct _PROCESS_MITIGATION_CHILD_PROCESS_POLICY {
901 | union {
902 | ULONG Flags;
903 | struct {
904 | ULONG NoChildProcessCreation : 1;
905 | ULONG AuditNoChildProcessCreation : 1;
906 | ULONG AllowSecureProcessCreation : 1;
907 | ULONG ReservedFlags : 29;
908 | } DUMMYSTRUCTNAME;
909 | } DUMMYUNIONNAME;
910 | } PROCESS_MITIGATION_CHILD_PROCESS_POLICY, * PPROCESS_MITIGATION_CHILD_PROCESS_POLICY;
911 |
912 | typedef struct _PROCESS_MITIGATION_POLICY_INFORMATION {
913 | PROCESS_MITIGATION_POLICY Policy;
914 | union {
915 | PROCESS_MITIGATION_ASLR_POLICY ASLRPolicy;
916 | PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY StrictHandleCheckPolicy;
917 | PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY SystemCallDisablePolicy;
918 | PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY ExtensionPointDisablePolicy;
919 | PROCESS_MITIGATION_DYNAMIC_CODE_POLICY DynamicCodePolicy;
920 | PROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY ControlFlowGuardPolicy;
921 | PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY SignaturePolicy;
922 | PROCESS_MITIGATION_FONT_DISABLE_POLICY FontDisablePolicy;
923 | PROCESS_MITIGATION_IMAGE_LOAD_POLICY ImageLoadPolicy;
924 | PROCESS_MITIGATION_SYSTEM_CALL_FILTER_POLICY SystemCallFilterPolicy;
925 | PROCESS_MITIGATION_PAYLOAD_RESTRICTION_POLICY PayloadRestrictionPolicy;
926 | PROCESS_MITIGATION_CHILD_PROCESS_POLICY ChildProcessPolicy;
927 | };
928 | } PROCESS_MITIGATION_POLICY_INFORMATION, * PPROCESS_MITIGATION_POLICY_INFORMATION;
929 |
930 | #endif // !_WINNT_
931 |
932 |
933 | //
934 | // Process KeepAlive Count
935 | // NtQueryInformationProcess using ProcessKeepAliveCount
936 | //
937 |
938 | typedef struct _PROCESS_KEEPALIVE_COUNT_INFORMATION {
939 | ULONG WakeCount;
940 | ULONG NoWakeCount;
941 | } PROCESS_KEEPALIVE_COUNT_INFORMATION, * PPROCESS_KEEPALIVE_COUNT_INFORMATION;
942 |
943 | //
944 | // Process File Handle Revocation
945 | // NtSetInformationProcess using ProcessRevokeFileHandles
946 | //
947 |
948 | typedef struct _PROCESS_REVOKE_FILE_HANDLES_INFORMATION {
949 | UNICODE_STRING TargetDevicePath;
950 | } PROCESS_REVOKE_FILE_HANDLES_INFORMATION, * PPROCESS_REVOKE_FILE_HANDLES_INFORMATION;
951 |
952 | //
953 | // Process Read/WriteVm Logging
954 | // NtQueryInformationProcess using ProcessEnableReadWriteVmLogging
955 | //
956 |
957 | #define PROCESS_READWRITEVM_LOGGING_ENABLE_READVM 0x01
958 | #define PROCESS_READWRITEVM_LOGGING_ENABLE_READVM_V 1UL
959 | #define PROCESS_READWRITEVM_LOGGING_ENABLE_WRITEVM 0x02L
960 | #define PROCESS_READWRITEVM_LOGGING_ENABLE_WRITEVM_V 2UL
961 |
962 | typedef union _PROCESS_READWRITEVM_LOGGING_INFORMATION {
963 | UINT8 Flags;
964 | struct {
965 | UINT8 EnableReadVmLogging : 1;
966 | UINT8 EnableWriteVmLogging : 1;
967 | UINT8 Unused : 6;
968 | };
969 | } PROCESS_READWRITEVM_LOGGING_INFORMATION, * PPROCESS_READWRITEVM_LOGGING_INFORMATION;
970 |
971 | //
972 | // Process Pooled Quota Usage and Limits
973 | // NtQueryInformationProcess using ProcessPooledUsageAndLimits
974 | //
975 |
976 | typedef struct _POOLED_USAGE_AND_LIMITS {
977 | SIZE_T PeakPagedPoolUsage;
978 | SIZE_T PagedPoolUsage;
979 | SIZE_T PagedPoolLimit;
980 | SIZE_T PeakNonPagedPoolUsage;
981 | SIZE_T NonPagedPoolUsage;
982 | SIZE_T NonPagedPoolLimit;
983 | SIZE_T PeakPagefileUsage;
984 | SIZE_T PagefileUsage;
985 | SIZE_T PagefileLimit;
986 | } POOLED_USAGE_AND_LIMITS, * PPOOLED_USAGE_AND_LIMITS;
987 |
988 | //
989 | // Process Exception Port Information
990 | // NtSetInformationProcess using ProcessExceptionPort
991 | // PROCESS_SET_PORT access to the process is needed
992 | // to use this info level.
993 | //
994 |
995 | #define PROCESS_EXCEPTION_PORT_ALL_STATE_BITS 0x00000003UL
996 | #define PROCESS_EXCEPTION_PORT_ALL_STATE_FLAGS ((UINTN)((1UL << PROCESS_EXCEPTION_PORT_ALL_STATE_BITS) - 1))
997 |
998 | typedef struct _PROCESS_EXCEPTION_PORT {
999 | //
1000 | // Handle to the exception port. No particular access required.
1001 | //
1002 | IN HANDLE ExceptionPortHandle;
1003 | //
1004 | // Miscellaneous state flags to be cached along with the exception
1005 | // port in the kernel.
1006 | //
1007 | IN OUT ULONG StateFlags;
1008 | } PROCESS_EXCEPTION_PORT, * PPROCESS_EXCEPTION_PORT;
1009 |
1010 | //
1011 | // Process Security Context Information
1012 | // NtSetInformationProcess using ProcessAccessToken
1013 | // PROCESS_SET_ACCESS_TOKEN access to the process is needed
1014 | // to use this info level.
1015 | //
1016 |
1017 | typedef struct _PROCESS_ACCESS_TOKEN {
1018 |
1019 | //
1020 | // Handle to Primary token to assign to the process.
1021 | // TOKEN_ASSIGN_PRIMARY access to this token is needed.
1022 | //
1023 | HANDLE Token;
1024 |
1025 | //
1026 | // Handle to the initial thread of the process.
1027 | // A process's access token can only be changed if the process has
1028 | // no threads or one thread. If the process has no threads, this
1029 | // field must be set to NULL. Otherwise, it must contain a handle
1030 | // open to the process's only thread. THREAD_QUERY_INFORMATION access
1031 | // is needed via this handle.
1032 | //
1033 | HANDLE Thread;
1034 |
1035 | } PROCESS_ACCESS_TOKEN, * PPROCESS_ACCESS_TOKEN;
1036 |
1037 | //
1038 | // Process/Thread System and User Time
1039 | // NtQueryInformationProcess using ProcessTimes
1040 | // NtQueryInformationThread using ThreadTimes
1041 | //
1042 |
1043 | typedef struct _KERNEL_USER_TIMES {
1044 | LARGE_INTEGER CreateTime;
1045 | LARGE_INTEGER ExitTime;
1046 | LARGE_INTEGER KernelTime;
1047 | LARGE_INTEGER UserTime;
1048 | } KERNEL_USER_TIMES;
1049 | typedef KERNEL_USER_TIMES* PKERNEL_USER_TIMES;
1050 |
1051 | //
1052 | // Process/Thread subsystem information
1053 | // NtQueryInformationProcess using ProcessSubsystemInformation
1054 | // NtQueryInformationThread using ThreadSubsystemInformation
1055 | //
1056 |
1057 | typedef enum _SUBSYSTEM_INFORMATION_TYPE {
1058 | SubsystemInformationTypeWin32 = 0,
1059 | SubsystemInformationTypeWSL = 1,
1060 | MaxSubsystemInformationType
1061 | } SUBSYSTEM_INFORMATION_TYPE, * PSUBSYSTEM_INFORMATION_TYPE;
1062 |
1063 | //
1064 | // Ums Context
1065 | //
1066 |
1067 | typedef struct _RTL_UMS_CONTEXT {
1068 | SINGLE_LIST_ENTRY Link;
1069 | CONTEXT Context;
1070 | PVOID Teb;
1071 | PVOID UserContext;
1072 | volatile ULONG ScheduledThread;
1073 | volatile ULONG Suspended;
1074 | volatile ULONG VolatileContext;
1075 | volatile ULONG Terminated;
1076 | volatile ULONG DebugActive;
1077 | volatile ULONG RunningOnSelfThread;
1078 | volatile ULONG DenyRunningOnSelfThread;
1079 | volatile INT32 Flags;
1080 | volatile ULONG64 KernelUpdateLock;
1081 | volatile ULONG64 PrimaryClientID;
1082 | volatile ULONG64 ContextLock;
1083 | struct _RTL_UMS_CONTEXT* PrimaryUmsContext;
1084 | ULONG SwitchCount;
1085 | ULONG KernelYieldCount;
1086 | ULONG MixedYieldCount;
1087 | ULONG YieldCount;
1088 | } RTL_UMS_CONTEXT, * PRTL_UMS_CONTEXT;
1089 |
1090 | #endif // !_NTDDK_ && !_WINNT_
1091 |
1092 |
1093 | typedef
1094 | NTSTATUS
1095 | (NTAPI* PNT_QUERY_INFORMATION_PROCESS)(
1096 | IN HANDLE ProcessHandle,
1097 | IN PROCESSINFOCLASS ProcessInformationClass,
1098 | OUT PVOID ProcessInformation,
1099 | IN ULONG ProcessInformationLength,
1100 | OUT PULONG ReturnLength OPTIONAL
1101 | );
1102 | NTSYSCALLAPI
1103 | NTSTATUS
1104 | NTAPI
1105 | NtQueryInformationProcess(
1106 | IN HANDLE ProcessHandle,
1107 | IN PROCESSINFOCLASS ProcessInformationClass,
1108 | OUT PVOID ProcessInformation,
1109 | IN ULONG ProcessInformationLength,
1110 | OUT PULONG ReturnLength OPTIONAL
1111 | );
1112 |
1113 | NTSYSCALLAPI
1114 | NTSTATUS
1115 | NTAPI
1116 | ZwQueryInformationProcess(
1117 | IN HANDLE ProcessHandle,
1118 | IN PROCESSINFOCLASS ProcessInformationClass,
1119 | OUT PVOID ProcessInformation,
1120 | IN ULONG ProcessInformationLength,
1121 | OUT PULONG ReturnLength OPTIONAL
1122 | );
1123 |
1124 | typedef
1125 | NTSTATUS
1126 | (NTAPI* PNT_QUERY_INFORMATION_THREAD)(
1127 | IN HANDLE ThreadHandle,
1128 | IN THREADINFOCLASS ThreadInformationClass,
1129 | OUT PVOID ThreadInformation,
1130 | IN ULONG ThreadInformationLength,
1131 | OUT PULONG ReturnLength OPTIONAL
1132 | );
1133 | NTSYSCALLAPI
1134 | NTSTATUS
1135 | NTAPI
1136 | NtQueryInformationThread(
1137 | IN HANDLE ThreadHandle,
1138 | IN THREADINFOCLASS ThreadInformationClass,
1139 | OUT PVOID ThreadInformation,
1140 | IN ULONG ThreadInformationLength,
1141 | OUT PULONG ReturnLength OPTIONAL
1142 | );
1143 |
1144 | #ifdef __cplusplus
1145 | } // extern "C"
1146 | #endif
1147 |
1148 | #if defined(_MSC_VER)
1149 | #pragma warning(pop)
1150 | #endif // _MSC_VER
1151 |
1152 | #endif // _NTPSAPI_
1153 |
--------------------------------------------------------------------------------
/ntrtl.h:
--------------------------------------------------------------------------------
1 | #include "ntapi.h"
2 |
3 | // Hacky case manipulation macros.
4 |
5 | #define RTL_UPCASE(wch) ( \
6 | ((wch) < 'a' ? \
7 | (wch) \
8 | : \
9 | ((wch) <= 'z' ? \
10 | (wch) - ('a'-'A') \
11 | : \
12 | ((WCHAR)(wch)) \
13 | ) \
14 | ) \
15 | )
16 |
17 | #define RTL_DOWNCASE(wch) ( \
18 | ((wch) < 'A' ? \
19 | (wch) \
20 | : \
21 | ((wch) <= 'Z' ? \
22 | (wch) + ('a'-'A') \
23 | : \
24 | ((WCHAR)(wch)) \
25 | ) \
26 | ) \
27 | )
28 |
29 | //NTSYSAPI
30 | LONG
31 | NTAPI
32 | RtlCompareUnicodeStrings(
33 | IN CONST WCHAR* String1,
34 | IN SIZE_T Length1,
35 | IN CONST WCHAR* String2,
36 | IN SIZE_T Length2,
37 | IN BOOLEAN CaseInSensitive
38 | );
39 |
40 | #if !defined(_NTDDK_)
41 |
42 | FORCEINLINE
43 | LONG
44 | NTAPI
45 | RtlCompareUnicodeString(
46 | IN PCUNICODE_STRING String1,
47 | IN PCUNICODE_STRING String2,
48 | IN BOOLEAN CaseInSensitive
49 | )
50 | {
51 | return RtlCompareUnicodeStrings(String1->Buffer, String1->Length,
52 | String2->Buffer, String2->Length,
53 | CaseInSensitive);
54 | }
55 |
56 | _At_(DestinationString->Buffer, _Post_equal_to_(SourceString))
57 | _At_(DestinationString->Length, _Post_equal_to_(_String_length_(SourceString) * sizeof(WCHAR)))
58 | _At_(DestinationString->MaximumLength, _Post_equal_to_((_String_length_(SourceString)+1) * sizeof(WCHAR)))
59 | //NTSYSAPI
60 | VOID
61 | NTAPI
62 | RtlInitUnicodeString(
63 | _Out_ PUNICODE_STRING DestinationString,
64 | _In_opt_z_ PCWSTR SourceString
65 | );
66 |
67 | _At_(UnicodeString->Buffer, _Post_equal_to_(Buffer))
68 | _At_(UnicodeString->Length, _Post_equal_to_(0))
69 | _At_(UnicodeString->MaximumLength, _Post_equal_to_(BufferSize))
70 | FORCEINLINE
71 | VOID
72 | RtlInitEmptyUnicodeString(
73 | OUT PUNICODE_STRING UnicodeString,
74 | IN _Writable_bytes_(BufferSize) _When_(BufferSize != 0, _Notnull_)
75 | PWCHAR Buffer,
76 | IN UINT16 BufferSize
77 | )
78 | {
79 | memset(UnicodeString, 0, sizeof(*UnicodeString));
80 | UnicodeString->MaximumLength = BufferSize;
81 | UnicodeString->Buffer = Buffer;
82 | }
83 |
84 | _At_(AnsiString->Buffer, _Post_equal_to_(Buffer))
85 | _At_(AnsiString->Length, _Post_equal_to_(0))
86 | _At_(AnsiString->MaximumLength, _Post_equal_to_(BufferSize))
87 | FORCEINLINE
88 | VOID
89 | RtlInitEmptyAnsiString(
90 | OUT PANSI_STRING AnsiString,
91 | IN _Pre_readable_size_(BufferSize) CHAR* Buffer,
92 | IN UINT16 BufferSize
93 | )
94 | {
95 | AnsiString->Length = 0;
96 | AnsiString->MaximumLength = BufferSize;
97 | AnsiString->Buffer = Buffer;
98 | }
99 |
100 | #endif // !_NTDDK_
101 |
102 |
--------------------------------------------------------------------------------
/pebteb.h:
--------------------------------------------------------------------------------
1 | //
2 | // Declarations of PEB and TEB, and some types contained in them.
3 | //
4 | // Address the maintenance problem that resulted from PEB and TEB being
5 | // defined three times, once "native" in ntpsapi.w, and twice, 32bit and 64bit
6 | // in wow64t.w.
7 | //
8 |
9 | //
10 | // This file deliberately lacks #pragma once or #ifndef guards.
11 | // It is only included by ntpsapi.h and wow64t.h and ntapi.h, never directly.
12 | //
13 |
14 | //
15 | // This file is #included three times.
16 | //
17 | // 1) by ntpsapi.h, with no "unusual" macros defined, to declare
18 | // PEB and TEB, and some types contained in them
19 | // 2) by wow64t.h to declare PEB32 and TEB32, and some types contained in them
20 | // 3) by wow64t.h to declare PEB64 and TEB64, and some types contained in them
21 | //
22 | // wow64t.h #defines the macro PEBTEB_BITS to guide the declarations.
23 | //
24 |
25 | #define PEBTEB_PRIVATE_PASTE(x, y) x##y
26 | #define PEBTEB_PASTE(x, y) PEBTEB_PRIVATE_PASTE(x,y)
27 |
28 | #if defined(PEBTEB_BITS) /* This is defined by wow64t.h. */
29 |
30 | #if PEBTEB_BITS == 32
31 |
32 | #define PEBTEB_STRUCT(x) PEBTEB_PASTE(x, 32) /* FOO32 */
33 | #define PEBTEB_POINTER(x) TYPE32(x) /* ULONG, defined in wow64t.h */
34 |
35 | #elif PEBTEB_BITS == 64
36 |
37 | #define PEBTEB_STRUCT(x) PEBTEB_PASTE(x, 64) /* FOO64 */
38 | #define PEBTEB_POINTER(x) TYPE64(x) /* ULONG64, defined in wow64t.h */
39 |
40 | #else
41 |
42 | #error Unknown value for pebteb_bits (PEBTEB_BITS).
43 |
44 | #endif
45 |
46 | #else
47 |
48 | //
49 | // Declare and use regular native types.
50 | //
51 | #define PEBTEB_POINTER(x) x
52 | #define PEBTEB_STRUCT(x) x
53 |
54 | #endif
55 |
56 |
57 | typedef struct PEBTEB_STRUCT(_PEB_LDR_DATA) {
58 | ULONG Length;
59 | BOOLEAN Initialized;
60 | ULONG SsHandle;
61 | PEBTEB_STRUCT(LIST_ENTRY) InLoadOrderModuleList;
62 | PEBTEB_STRUCT(LIST_ENTRY) InMemoryOrderModuleList;
63 | PEBTEB_STRUCT(LIST_ENTRY) InInitializationOrderModuleList;
64 | ULONG EntryInProgress;
65 | BOOLEAN ShutdownInProgress;
66 | ULONG ShutdownThreadId;
67 | } PEBTEB_STRUCT(PEB_LDR_DATA), *PEBTEB_STRUCT(PPEB_LDR_DATA);
68 |
69 |
70 | /* for searching
71 | typedef struct _PEB
72 | typedef struct _PEB32
73 | typedef struct _PEB64
74 | */
75 | typedef struct PEBTEB_STRUCT(_PEB) {
76 | BOOLEAN InheritedAddressSpace; // These four fields cannot change unless the
77 | BOOLEAN ReadImageFileExecOptions; // ..
78 | BOOLEAN BeingDebugged; // ..
79 | union {
80 | BOOLEAN BitField; // ..
81 | struct {
82 | BOOLEAN ImageUsesLargePages : 1;
83 | BOOLEAN IsProtectedProcess : 1;
84 | BOOLEAN IsImageDynamicallyRelocated : 1;
85 | BOOLEAN SkipPatchingUser32Forwarders : 1;
86 | BOOLEAN IsPackagedProcess : 1;
87 | BOOLEAN IsAppContainer : 1;
88 | BOOLEAN IsProtectedProcessLight : 1;
89 | BOOLEAN IsLongPathAwareProcess : 1;
90 | };
91 | };
92 |
93 | PEBTEB_POINTER(HANDLE) Mutant; // INITIAL_PEB structure is also updated.
94 |
95 | PEBTEB_POINTER(PVOID) ImageBaseAddress;
96 | PEBTEB_POINTER(PPEB_LDR_DATA) Ldr;
97 | PEBTEB_POINTER(struct _RTL_USER_PROCESS_PARAMETERS*)ProcessParameters;
98 | PEBTEB_POINTER(PVOID) SubSystemData;
99 | PEBTEB_POINTER(PVOID) ProcessHeap;
100 | PEBTEB_POINTER(struct _RTL_CRITICAL_SECTION*)FastPebLock;
101 | PEBTEB_POINTER(PVOID) IFEOKey;
102 | PEBTEB_POINTER(PVOID) AtlThunkSListPtr; // Used only for AMD64 PSLIST_HEADER
103 | union {
104 | ULONG CrossProcessFlags;
105 | struct {
106 | ULONG ProcessInJob : 1;
107 | ULONG ProcessInitializing : 1;
108 | ULONG ProcessUsingVEH : 1;
109 | ULONG ProcessUsingVCH : 1;
110 | ULONG ProcessUsingFTH : 1;
111 | ULONG ProcessPreviouslyThrottled : 1;
112 | ULONG ProcessCurrentlyThrottled : 1;
113 | ULONG ReservedBits0 : 25;
114 | };
115 | };
116 | union {
117 | PEBTEB_POINTER(PVOID) KernelCallbackTable;
118 | PEBTEB_POINTER(PVOID) UserSharedInfoPtr;
119 | };
120 | ULONG SystemReserved[1];
121 | ULONG AtlThunkSListPtr32;
122 | PEBTEB_POINTER(PVOID) ApiSetMap; // PAPI_SET_NAMESPACE
123 | ULONG TlsExpansionCounter;
124 | PEBTEB_POINTER(PVOID) TlsBitmap;
125 | ULONG TlsBitmapBits[2]; // TLS_MINIMUM_AVAILABLE bits
126 | PEBTEB_POINTER(PVOID) ReadOnlySharedMemoryBase;
127 | PEBTEB_POINTER(PVOID) SharedData; // HotpatchInformation
128 | PEBTEB_POINTER(PPVOID) ReadOnlyStaticServerData;
129 | PEBTEB_POINTER(PVOID) AnsiCodePageData; // PCPTABLEINFO
130 | PEBTEB_POINTER(PVOID) OemCodePageData; // PCPTABLEINFO
131 | PEBTEB_POINTER(PVOID) UnicodeCaseTableData; // PNLSTABLEINFO
132 |
133 | //
134 | // Useful information for LdrpInitialize
135 | ULONG NumberOfProcessors;
136 | ULONG NtGlobalFlag;
137 |
138 | //
139 | // Passed up from MmCreatePeb from Session Manager registry key
140 | //
141 |
142 | LARGE_INTEGER CriticalSectionTimeout;
143 | PEBTEB_POINTER(SIZE_T) HeapSegmentReserve;
144 | PEBTEB_POINTER(SIZE_T) HeapSegmentCommit;
145 | PEBTEB_POINTER(SIZE_T) HeapDeCommitTotalFreeThreshold;
146 | PEBTEB_POINTER(SIZE_T) HeapDeCommitFreeBlockThreshold;
147 |
148 | //
149 | // Where heap manager keeps track of all heaps created for a process
150 | // Fields initialized by MmCreatePeb. ProcessHeaps is initialized
151 | // to point to the first free byte after the PEB and MaximumNumberOfHeaps
152 | // is computed from the page size used to hold the PEB, less the fixed
153 | // size of this data structure.
154 | //
155 |
156 | ULONG NumberOfHeaps;
157 | ULONG MaximumNumberOfHeaps;
158 | PEBTEB_POINTER(PPVOID) ProcessHeaps; // PHEAP*
159 |
160 | //
161 | //
162 | PEBTEB_POINTER(PVOID) GdiSharedHandleTable;
163 | PEBTEB_POINTER(PVOID) ProcessStarterHelper;
164 | ULONG GdiDCAttributeList;
165 | PEBTEB_POINTER(struct _RTL_CRITICAL_SECTION*)LoaderLock;
166 |
167 | //
168 | // Following fields filled in by MmCreatePeb from system values and/or
169 | // image header.
170 | //
171 |
172 | ULONG OSMajorVersion;
173 | ULONG OSMinorVersion;
174 | USHORT OSBuildNumber;
175 | USHORT OSCSDVersion;
176 | ULONG OSPlatformId;
177 | ULONG ImageSubsystem;
178 | ULONG ImageSubsystemMajorVersion;
179 | ULONG ImageSubsystemMinorVersion;
180 | PEBTEB_POINTER(UINT_PTR) ActiveProcessAffinityMask;
181 | PEBTEB_STRUCT(GDI_HANDLE_BUFFER) GdiHandleBuffer;
182 | PEBTEB_POINTER(PPS_POST_PROCESS_INIT_ROUTINE) PostProcessInitRoutine;
183 |
184 | PEBTEB_POINTER(PVOID) TlsExpansionBitmap;
185 | ULONG TlsExpansionBitmapBits[32]; // TLS_EXPANSION_SLOTS bits
186 |
187 | //
188 | // Id of the Hydra session in which this process is running
189 | //
190 | ULONG SessionId;
191 |
192 | //
193 | // Filled in by LdrpInstallAppcompatBackend
194 | //
195 | ULARGE_INTEGER AppCompatFlags;
196 |
197 | //
198 | // ntuser appcompat flags
199 | //
200 | ULARGE_INTEGER AppCompatFlagsUser;
201 |
202 | //
203 | // Filled in by LdrpInstallAppcompatBackend
204 | //
205 | PEBTEB_POINTER(PVOID) pShimData;
206 |
207 | //
208 | // Filled in by LdrQueryImageFileExecutionOptions
209 | //
210 | PEBTEB_POINTER(PVOID) AppCompatInfo; // APPCOMPAT_EXE_DATA
211 |
212 | //
213 | // Used by GetVersionExW as the szCSDVersion string
214 | //
215 | PEBTEB_STRUCT(UNICODE_STRING) CSDVersion;
216 |
217 | //
218 | // Fusion stuff
219 | //
220 | PEBTEB_POINTER(const struct _ACTIVATION_CONTEXT_DATA *)ActivationContextData; // ACTIVATION_CONTEXT_DATA
221 | PEBTEB_POINTER(struct _ASSEMBLY_STORAGE_MAP *)ProcessAssemblyStorageMap; // ASSEMBLY_STORAGE_MAP
222 | PEBTEB_POINTER(const struct _ACTIVATION_CONTEXT_DATA *)SystemDefaultActivationContextData; // ACTIVATION_CONTEXT_DATA
223 | PEBTEB_POINTER(struct _ASSEMBLY_STORAGE_MAP *)SystemAssemblyStorageMap; // ASSEMBLY_STORAGE_MAP
224 |
225 | //
226 | // Enforced minimum initial commit stack
227 | //
228 | PEBTEB_POINTER(SIZE_T) MinimumStackCommit;
229 |
230 | //
231 | // Fiber local storage.
232 | //
233 |
234 | PEBTEB_POINTER(PPVOID) FlsCallback;
235 | PEBTEB_STRUCT(LIST_ENTRY) FlsListHead;
236 | PEBTEB_POINTER(PVOID) FlsBitmap;
237 | ULONG FlsBitmapBits[FLS_MAXIMUM_AVAILABLE / (sizeof(ULONG) * 8)];
238 | ULONG FlsHighIndex;
239 |
240 | PEBTEB_POINTER(PVOID) WerRegistrationData;
241 | PEBTEB_POINTER(PVOID) WerShipAssertPtr;
242 | PEBTEB_POINTER(PVOID) pUnused; // pContextData
243 | PEBTEB_POINTER(PVOID) pImageHeaderHash;
244 |
245 | union {
246 | ULONG TracingFlags;
247 | struct {
248 | ULONG HeapTracingEnabled : 1;
249 | ULONG CritSecTracingEnabled : 1;
250 | ULONG LibLoaderTracingEnabled : 1;
251 | ULONG SpareTracingBits : 29;
252 | };
253 | };
254 |
255 | ULONG64 CsrServerReadOnlySharedMemoryBase;
256 |
257 | PEBTEB_POINTER(struct _RTL_CRITICAL_SECTION*)TppWorkerpListLock;
258 | PEBTEB_STRUCT(LIST_ENTRY) TppWorkerpList;
259 |
260 | PEBTEB_POINTER(PVOID) WaitOnAddressHashTable[128];
261 |
262 | // winver >= rs3
263 | PEBTEB_POINTER(PVOID) TelemetryCoverageHeader;
264 | ULONG CloudFileFlags;
265 |
266 | // winver >= rs4
267 | ULONG CloudFileDiagFlags;
268 |
269 | CHAR PlaceholderCompatibilityMode;
270 | CHAR PlaceholderCompatibilityModeReserved[7];
271 |
272 | } PEBTEB_STRUCT(PEB), *PEBTEB_STRUCT(PPEB);
273 |
274 |
275 | typedef struct PEBTEB_STRUCT(_RTL_ACTIVATION_CONTEXT_STACK_FRAME) {
276 | // PEBTEB_POINTER(SIZE_T) Size; // -0x10
277 | // ULONG Format; // -0x08
278 | PEBTEB_POINTER(struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME *)Previous; // 0x00
279 | PEBTEB_POINTER(struct _ACTIVATION_CONTEXT *)ActivationContext; // +0x08
280 | ULONG Flags; // +0x10
281 | } PEBTEB_STRUCT(RTL_ACTIVATION_CONTEXT_STACK_FRAME),
282 | *PEBTEB_STRUCT(PRTL_ACTIVATION_CONTEXT_STACK_FRAME);
283 |
284 | typedef struct PEBTEB_STRUCT(_RTL_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED) {
285 | // PEBTEB_POINTER(SIZE_T) Size; // -0x10
286 | // ULONG Format; // -0x08
287 | PEBTEB_POINTER(struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME *)Previous; // 0x00
288 | PEBTEB_POINTER(struct _ACTIVATION_CONTEXT *)ActivationContext; // +0x08
289 | ULONG Flags; // +0x10
290 | PEBTEB_POINTER(SIZE_T) Extra1; // +0x18
291 | PEBTEB_POINTER(SIZE_T) Extra2; // +0x20
292 | PEBTEB_POINTER(SIZE_T) Extra3; // +0x28
293 | PEBTEB_POINTER(SIZE_T) Extra4; // +0x30
294 | } PEBTEB_STRUCT(RTL_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED),
295 | *PEBTEB_STRUCT(PRTL_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED);
296 |
297 | typedef struct PEBTEB_STRUCT(_ACTIVATION_CONTEXT_STACK) {
298 | PEBTEB_POINTER(struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME *)ActiveFrame;
299 | PEBTEB_STRUCT(LIST_ENTRY) FrameListCache;
300 | ULONG Flags;
301 | ULONG NextCookieSequenceNumber;
302 | ULONG StackId;
303 | } PEBTEB_STRUCT(ACTIVATION_CONTEXT_STACK),
304 | *PEBTEB_STRUCT(PACTIVATION_CONTEXT_STACK);
305 |
306 | typedef const PEBTEB_STRUCT(ACTIVATION_CONTEXT_STACK) *PEBTEB_STRUCT(PCACTIVATION_CONTEXT_STACK);
307 |
308 | #define TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED (0x00000001)
309 |
310 | typedef struct PEBTEB_STRUCT(_TEB_ACTIVE_FRAME_CONTEXT) {
311 | ULONG Flags;
312 | PEBTEB_POINTER(CHAR*)FrameName;
313 | } PEBTEB_STRUCT(TEB_ACTIVE_FRAME_CONTEXT),
314 | *PEBTEB_STRUCT(PTEB_ACTIVE_FRAME_CONTEXT);
315 |
316 | typedef const PEBTEB_STRUCT(TEB_ACTIVE_FRAME_CONTEXT) *PEBTEB_STRUCT(PCTEB_ACTIVE_FRAME_CONTEXT);
317 |
318 | typedef struct PEBTEB_STRUCT(_TEB_ACTIVE_FRAME_CONTEXT_EX) {
319 | PEBTEB_STRUCT(TEB_ACTIVE_FRAME_CONTEXT) BasicContext;
320 | PEBTEB_POINTER(const CHAR*)SourceLocation; // e.g. "Z:\foo\bar\baz.c"
321 | } PEBTEB_STRUCT(TEB_ACTIVE_FRAME_CONTEXT_EX),
322 | *PEBTEB_STRUCT(PTEB_ACTIVE_FRAME_CONTEXT_EX);
323 |
324 | typedef const PEBTEB_STRUCT(TEB_ACTIVE_FRAME_CONTEXT_EX) *PEBTEB_STRUCT(
325 | PCTEB_ACTIVE_FRAME_CONTEXT_EX);
326 |
327 | #define TEB_ACTIVE_FRAME_FLAG_EXTENDED (0x00000001)
328 |
329 | typedef struct PEBTEB_STRUCT(_TEB_ACTIVE_FRAME) {
330 | ULONG Flags;
331 | PEBTEB_POINTER(struct _TEB_ACTIVE_FRAME*)Previous;
332 | PEBTEB_POINTER(PCTEB_ACTIVE_FRAME_CONTEXT) Context;
333 | } PEBTEB_STRUCT(TEB_ACTIVE_FRAME),
334 | *PEBTEB_STRUCT(PTEB_ACTIVE_FRAME);
335 |
336 | typedef const PEBTEB_STRUCT(TEB_ACTIVE_FRAME) *PEBTEB_STRUCT(PCTEB_ACTIVE_FRAME);
337 |
338 | typedef struct PEBTEB_STRUCT(_TEB_ACTIVE_FRAME_EX) {
339 | PEBTEB_STRUCT(TEB_ACTIVE_FRAME) BasicFrame;
340 | PEBTEB_POINTER(PVOID) ExtensionIdentifier; // use address of your DLL Main or something unique to
341 | // your mapping in the address space
342 | } PEBTEB_STRUCT(TEB_ACTIVE_FRAME_EX),
343 | *PEBTEB_STRUCT(PTEB_ACTIVE_FRAME_EX);
344 |
345 | typedef const PEBTEB_STRUCT(TEB_ACTIVE_FRAME_EX) *PEBTEB_STRUCT(PCTEB_ACTIVE_FRAME_EX);
346 |
347 |
348 | /* for searching
349 | typedef struct _TEB
350 | typedef struct _TEB32
351 | typedef struct _TEB64
352 | */
353 | typedef struct PEBTEB_STRUCT(_TEB) {
354 | PEBTEB_STRUCT(NT_TIB) NtTib;
355 | PEBTEB_POINTER(PVOID) EnvironmentPointer;
356 | PEBTEB_STRUCT(CLIENT_ID) ClientId;
357 | PEBTEB_POINTER(PVOID) ActiveRpcHandle;
358 | PEBTEB_POINTER(PVOID) ThreadLocalStoragePointer;
359 | PEBTEB_POINTER(PPEB) ProcessEnvironmentBlock;
360 | ULONG LastErrorValue;
361 | ULONG CountOfOwnedCriticalSections;
362 | PEBTEB_POINTER(PVOID) CsrClientThread;
363 | PEBTEB_POINTER(PVOID) Win32ThreadInfo; // PtiCurrent
364 | ULONG User32Reserved[26]; // user32.dll items
365 | ULONG UserReserved[5]; // Winsrv SwitchStack
366 | PEBTEB_POINTER(PVOID) WOW32Reserved; // used by WOW
367 | LCID CurrentLocale;
368 | ULONG FpSoftwareStatusRegister; // offset known by outsiders!
369 | PVOID ReservedForDebuggerInstrumentation[16];
370 | #if defined(_M_AMD64) || defined(__x86_64__)
371 | PEBTEB_POINTER(PVOID) SystemReserved1[30];
372 | #else
373 | PEBTEB_POINTER( PVOID ) SystemReserved1[26];
374 | #endif
375 |
376 | CHAR PlaceholderCompatibilityMode;
377 | CHAR PlaceholderReserved[11];
378 | ULONG ProxiedProcessId;
379 | PEBTEB_STRUCT(ACTIVATION_CONTEXT_STACK) ActivationStack;
380 |
381 | UINT8 WorkingOnBehalfTicket[8];
382 | NTSTATUS ExceptionCode; // for RaiseUserException
383 |
384 | PEBTEB_POINTER(PEBTEB_STRUCT(PACTIVATION_CONTEXT_STACK)) ActivationContextStackPointer; // Fusion activation stack
385 | PEBTEB_POINTER(ULONG_PTR) InstrumentationCallbackSp;
386 | PEBTEB_POINTER(ULONG_PTR) InstrumentationCallbackPreviousPc;
387 | PEBTEB_POINTER(ULONG_PTR) InstrumentationCallbackPreviousSp;
388 | #if defined(_M_AMD64) || defined(__x86_64__)
389 | ULONG TxFsContext;
390 | #endif
391 |
392 | BOOLEAN InstrumentationCallbackDisabled;
393 | #if !(defined(_M_AMD64) || defined(__x86_64__))
394 | UCHAR SpareBytes[23];
395 | ULONG TxFsContext;
396 | #endif
397 |
398 | PEBTEB_STRUCT(GDI_TEB_BATCH) GdiTebBatch; // Gdi batching
399 | PEBTEB_STRUCT(CLIENT_ID) RealClientId;
400 | PEBTEB_POINTER(HANDLE) GdiCachedProcessHandle;
401 | ULONG GdiClientPID;
402 | ULONG GdiClientTID;
403 | PEBTEB_POINTER(PVOID) GdiThreadLocalInfo;
404 | PEBTEB_POINTER(ULONG_PTR) Win32ClientInfo[62];
405 | PEBTEB_POINTER(PVOID) glDispatchTable[233]; // OpenGL
406 | PEBTEB_POINTER(ULONG_PTR) glReserved1[29]; // OpenGL
407 | PEBTEB_POINTER(PVOID) glReserved2; // OpenGL
408 | PEBTEB_POINTER(PVOID) glSectionInfo; // OpenGL
409 | PEBTEB_POINTER(PVOID) glSection; // OpenGL
410 | PEBTEB_POINTER(PVOID) glTable; // OpenGL
411 | PEBTEB_POINTER(PVOID) glCurrentRC; // OpenGL
412 | PEBTEB_POINTER(PVOID) glContext; // OpenGL
413 | NTSTATUS LastStatusValue;
414 | PEBTEB_STRUCT(UNICODE_STRING) StaticUnicodeString;
415 | WCHAR StaticUnicodeBuffer[STATIC_UNICODE_BUFFER_LENGTH];
416 | PEBTEB_POINTER(PVOID) DeallocationStack;
417 | PEBTEB_POINTER(PVOID) TlsSlots[TLS_MINIMUM_AVAILABLE];
418 | PEBTEB_STRUCT(LIST_ENTRY) TlsLinks;
419 | PEBTEB_POINTER(PVOID) Vdm;
420 | PEBTEB_POINTER(PVOID) ReservedForNtRpc;
421 | PEBTEB_POINTER(PVOID) DbgSsReserved[2];
422 | ULONG HardErrorMode;
423 | #if defined(_M_AMD64) || defined(__x86_64__)
424 | PEBTEB_POINTER(PVOID) Instrumentation[11];
425 | #else
426 | PEBTEB_POINTER( PVOID ) Instrumentation[9];
427 | #endif
428 | GUID ActivityId;
429 | PEBTEB_POINTER(PVOID) SubProcessTag;
430 | PEBTEB_POINTER(PVOID) PerflibData;
431 | PEBTEB_POINTER(PVOID) EtwTraceData;
432 | PEBTEB_POINTER(PVOID) WinSockData; // WinSock
433 | ULONG GdiBatchCount;
434 | union {
435 | PROCESSOR_NUMBER CurrentIdealProcessor;
436 | ULONG IdealProcessorValue;
437 | struct {
438 | UINT8 ReservedPad0;
439 | UINT8 ReservedPad1;
440 | UINT8 ReservedPad2;
441 | UINT8 IdealProcessor;
442 | };
443 | };
444 | ULONG GuaranteedStackBytes;
445 | PEBTEB_POINTER(PVOID) ReservedForPerf;
446 | PEBTEB_POINTER(PVOID) ReservedForOle;
447 | ULONG WaitingOnLoaderLock;
448 | PEBTEB_POINTER(PVOID) SavedPriorityState;
449 | PEBTEB_POINTER(ULONG_PTR) ReservedForCodeCoverage;
450 | PEBTEB_POINTER(PVOID) ThreadPoolData;
451 | PEBTEB_POINTER(PPVOID) TlsExpansionSlots;
452 | #if ((defined(_M_AMD64) || defined(__x86_64__)) && !defined(PEBTEB_BITS)) \
453 | || (((defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__))) \
454 | && defined(PEBTEB_BITS) && PEBTEB_BITS == 64)
455 | //
456 | // These are in native Win64 TEB, Win64 TEB64, and x86 TEB64.
457 | //
458 | PEBTEB_POINTER(PVOID) DeallocationBStore;
459 | PEBTEB_POINTER(PVOID) BStoreLimit;
460 | #endif
461 | ULONG MuiGeneration;
462 | ULONG IsImpersonating; // Thread impersonation status
463 | PEBTEB_POINTER(PVOID) NlsCache; // NLS thread cache
464 | PEBTEB_POINTER(PVOID) pShimData; // Per thread data used in the shim
465 | USHORT HeapVirtualAffinity;
466 | USHORT LowFragHeapDataSlot;
467 | PEBTEB_POINTER(HANDLE) CurrentTransactionHandle;// reserved for TxF transaction context
468 | PEBTEB_POINTER(PTEB_ACTIVE_FRAME) ActiveFrame;
469 | PEBTEB_POINTER(PVOID) FlsData;
470 | PEBTEB_POINTER(PVOID) PreferredLanguages;
471 | PEBTEB_POINTER(PVOID) UserPrefLanguages;
472 | PEBTEB_POINTER(PVOID) MergedPrefLanguages;
473 | ULONG MuiImpersonation; // mui impersonation status
474 | union {
475 | USHORT CrossTebFlags;
476 | USHORT SpareCrossTebBits : 16;
477 | };
478 | union {
479 | USHORT SameTebFlags;
480 | struct {
481 | USHORT SafeThunkCall : 1;
482 | USHORT InDebugPrint : 1;
483 | USHORT HasFiberData : 1;
484 | USHORT SkipThreadAttach : 1;
485 | USHORT WerInShipAssertCode : 1;
486 | USHORT RanProcessInit : 1;
487 | USHORT ClonedThread : 1;
488 | USHORT SuppressDebugMsg : 1;
489 | USHORT DisableUserStackWalk : 1;
490 | USHORT RtlExceptionAttached : 1;
491 | USHORT InitialThread : 1;
492 | USHORT SessionAware : 1;
493 | USHORT LoadOwner : 1;
494 | USHORT LoaderWorker : 1;
495 | USHORT SkipLoaderInit : 1;
496 | USHORT SpareSameTebBits : 1;
497 | };
498 | };
499 | PEBTEB_POINTER(PVOID) TxnScopeEnterCallback;
500 | PEBTEB_POINTER(PVOID) TxnScopeExitCallback;
501 | PEBTEB_POINTER(PVOID) TxnScopeContext;
502 | ULONG LockCount;
503 | INT32 WowTebOffset;
504 | PEBTEB_POINTER(PVOID) ResourceRetValue;
505 | PEBTEB_POINTER(PVOID) ReservedForWdf;
506 | ULONG64 ReservedForCrt;
507 | GUID EffectiveContainerId;
508 | } PEBTEB_STRUCT(TEB), *PEBTEB_STRUCT(PTEB);
509 |
510 | #undef PEBTEB_POINTER
511 | #undef PEBTEB_STRUCT
512 | #undef PEBTEB_PRIVATE_PASTE
513 | #undef PEBTEB_PASTE
514 |
--------------------------------------------------------------------------------
/resolve.c:
--------------------------------------------------------------------------------
1 | /**
2 | * API Set Lookup
3 | * Copyright (c) 2018-2019 Aidan Khoury. All rights reserved.
4 | *
5 | * @file resolve.c
6 | * @authors Aidan Khoury (ajkhoury)
7 | * @date 11/22/2018
8 | */
9 |
10 | #include "apiset.h"
11 |
12 | #include "ntrtl.h"
13 |
14 | static
15 | NTSTATUS
16 | ApiSetpResolve(
17 | _In_ HANDLE Process,
18 | _In_ PCUNICODE_STRING Name,
19 | _In_opt_ PCUNICODE_STRING BaseName,
20 | _Out_ PUNICODE_STRING ResolvedName
21 | )
22 | {
23 | NTSTATUS Status;
24 | PROCESS_BASIC_INFORMATION BasicInfo;
25 | ULONG ReturnLength;
26 | PPEB Peb;
27 | PVOID PebWow64;
28 | BOOLEAN Resolved;
29 | PAPI_SET_NAMESPACE ApiSetMap;
30 |
31 | //
32 | // Retrieve PEB address for given process.
33 | //
34 | Status = NtQueryInformationProcess(Process,
35 | ProcessBasicInformation,
36 | &BasicInfo,
37 | sizeof(BasicInfo),
38 | &ReturnLength);
39 | if (!NT_SUCCESS(Status)) {
40 | return Status;
41 | }
42 |
43 | Peb = (PPEB)BasicInfo.PebBaseAddress;
44 |
45 | Status = NtQueryInformationProcess(Process,
46 | ProcessWow64Information,
47 | &PebWow64,
48 | sizeof(PebWow64),
49 | &ReturnLength);
50 | if (!NT_SUCCESS(Status)) {
51 | return Status;
52 | }
53 |
54 | if (PebWow64 != NULL) {
55 | ApiSetMap = (PAPI_SET_NAMESPACE)(ULONG_PTR)((PPEB32)PebWow64)->ApiSetMap;
56 | } else {
57 | ApiSetMap = (PAPI_SET_NAMESPACE)Peb->ApiSetMap;
58 | }
59 |
60 | if (!ApiSetMap) {
61 | return STATUS_NOT_FOUND;
62 | }
63 |
64 | switch (ApiSetMap->Version) {
65 |
66 | //
67 | // API set schema version 2
68 | //
69 | case API_SET_SCHEMA_VERSION_V2:
70 | Status = ApiSetResolveToHostV2(ApiSetMap, Name, BaseName, &Resolved, ResolvedName);
71 | if (NT_SUCCESS(Status) && !Resolved) {
72 | Status = STATUS_NOT_FOUND;
73 | }
74 | break;
75 |
76 | //
77 | // API set schema version 3
78 | //
79 | case API_SET_SCHEMA_VERSION_V3:
80 | Status = ApiSetResolveToHostV3(ApiSetMap, Name, BaseName, &Resolved, ResolvedName);
81 | if (NT_SUCCESS(Status) && !Resolved) {
82 | Status = STATUS_NOT_FOUND;
83 | }
84 | break;
85 |
86 | //
87 | // API set schema version 4
88 | //
89 | case API_SET_SCHEMA_VERSION_V4:
90 | Status = ApiSetResolveToHostV4(ApiSetMap, Name, BaseName, &Resolved, ResolvedName);
91 | if (NT_SUCCESS(Status) && !Resolved) {
92 | Status = STATUS_NOT_FOUND;
93 | }
94 | break;
95 |
96 | //
97 | // API set schema version 6
98 | //
99 | case API_SET_SCHEMA_VERSION_V6:
100 | Status = ApiSetResolveToHostV6(ApiSetMap, Name, BaseName, &Resolved, ResolvedName);
101 | if (NT_SUCCESS(Status) && !Resolved) {
102 | Status = STATUS_NOT_FOUND;
103 | }
104 | break;
105 |
106 | default:
107 | Status = STATUS_NOT_SUPPORTED;
108 | break;
109 | }
110 |
111 | return Status;
112 | }
113 |
114 | BOOLEAN
115 | APISETAPI
116 | ApiSetResolve(
117 | _In_z_ PWCHAR ApiSetName,
118 | _In_opt_z_ PWCHAR BaseDllName,
119 | _Out_ PUNICODE_STRING ResolvedHostLibrary
120 | )
121 | {
122 | NTSTATUS Status;
123 | UNICODE_STRING ApiToResolve;
124 | UNICODE_STRING BaseName;
125 |
126 | RtlInitUnicodeString(&ApiToResolve, ApiSetName);
127 | if (BaseDllName != NULL) {
128 | RtlInitUnicodeString(&BaseName, BaseDllName);
129 | }
130 |
131 | Status = ApiSetpResolve(GetCurrentProcess(),
132 | &ApiToResolve,
133 | BaseDllName ? &BaseName : NULL,
134 | ResolvedHostLibrary
135 | );
136 |
137 | if (NT_SUCCESS(Status)) {
138 | return TRUE;
139 | }
140 |
141 | return FALSE;
142 | }
143 |
--------------------------------------------------------------------------------
/string.c:
--------------------------------------------------------------------------------
1 | #include "ntrtl.h"
2 |
3 | /**
4 | * The RtlInitUnicodeString function initializes an NT counted
5 | * unicode string. The DestinationString is initialized to point to
6 | * the SourceString and the Length and MaximumLength fields of
7 | * DestinationString are initialized to the length of the SourceString,
8 | * which is zero if SourceString is not specified.
9 | *
10 | * @param[out] DestinationString Pointer to the counted string to initialize.
11 | * @param[in] SourceString Optional pointer to a null terminated unicode
12 | * string that the counted string is to point to.
13 | */
14 | VOID
15 | NTAPI
16 | RtlInitUnicodeString(
17 | _Out_ PUNICODE_STRING DestinationString,
18 | _In_opt_z_ PCWSTR SourceString
19 | )
20 | {
21 | SIZE_T Length;
22 |
23 | DestinationString->MaximumLength = 0;
24 | DestinationString->Length = 0;
25 | DestinationString->Buffer = (PWCH)SourceString;
26 |
27 | if (ARGUMENT_PRESENT(SourceString)) {
28 | Length = wcslen(SourceString) * sizeof(WCHAR);
29 | if (Length >= MAX_USTRING) {
30 | Length = MAX_USTRING - sizeof(UNICODE_NULL);
31 | }
32 |
33 | DestinationString->Length = (USHORT)Length;
34 | DestinationString->MaximumLength = (USHORT)(Length + sizeof(UNICODE_NULL));
35 | }
36 |
37 | return;
38 | }
39 |
--------------------------------------------------------------------------------
/unicode.c:
--------------------------------------------------------------------------------
1 | // This document is released into the public domain. Absolutely no warranty is provided.
2 | // See http://www.coderforlife.com/projects/utilities.
3 | //
4 | // This is for the MinGW compiler which does not support wmain.
5 | // It is a wrapper for _tmain when _UNICODE is defined (wmain).
6 | //
7 | // !! Do not compile this file, but instead include it right before your _tmain function like:
8 | // #include "mingw-unicode.c"
9 | // int _tmain(int argc, _TCHAR *argv[]) {
10 | //
11 | // If you wish to have enpv in your main, then define the following before including this file:
12 | // #define MAIN_USE_ENVP
13 | //
14 | // This wrapper adds ~300 bytes to the program and negligible overhead
15 |
16 | #undef _tmain
17 | #ifdef _UNICODE
18 | #define _tmain wmain
19 | #else
20 | #define _tmain main
21 | #endif
22 |
23 | #if defined(__GNUC__) && defined(_UNICODE)
24 |
25 | #ifndef __MSVCRT__
26 | #error Unicode main function requires linking to MSVCRT
27 | #endif
28 |
29 | #include
30 | #include
31 |
32 | extern int _CRT_glob;
33 | extern
34 | #ifdef __cplusplus
35 | "C"
36 | #endif
37 | void __wgetmainargs(int*,wchar_t***,wchar_t***,int,int*);
38 |
39 | #ifdef MAIN_USE_ENVP
40 | int wmain(int argc, wchar_t *argv[], wchar_t *envp[]);
41 | #else
42 | int wmain(int argc, wchar_t *argv[]);
43 | #endif
44 |
45 | int main() {
46 | wchar_t **enpv, **argv;
47 | int argc, si = 0;
48 | __wgetmainargs(&argc, &argv, &enpv, _CRT_glob, &si); // this also creates the global variable __wargv
49 | #ifdef MAIN_USE_ENVP
50 | return wmain(argc, argv, enpv);
51 | #else
52 | return wmain(argc, argv);
53 | #endif
54 | }
55 |
56 | #endif //defined(__GNUC__) && defined(_UNICODE)
--------------------------------------------------------------------------------