Skip to content

Commit c4e286e

Browse files
author
James Forshaw
committed
Added some more non-throwing apis.
1 parent 5052b9f commit c4e286e

2 files changed

Lines changed: 170 additions & 22 deletions

File tree

NtApiDotNet/NtThread.cs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,12 @@ private static NtResult<NtThread> Open(NtThreadInformation thread_info, ThreadAc
4242

4343
private ThreadBasicInformation QueryBasicInformation()
4444
{
45-
return Query<ThreadBasicInformation>(ThreadInformationClass.ThreadBasicInformation);
45+
return QueryBasicInformation(true).Result;
46+
}
47+
48+
private NtResult<ThreadBasicInformation> QueryBasicInformation(bool throw_on_error)
49+
{
50+
return Query(ThreadInformationClass.ThreadBasicInformation, new ThreadBasicInformation(), throw_on_error);
4651
}
4752

4853
private NtResult<IContext> GetX86Context(ContextFlags flags, bool throw_on_error)
@@ -823,6 +828,30 @@ public ThreadAlpcServerInformation GetAlpcServerInformation()
823828
return GetAlpcServerInformation(true).Result;
824829
}
825830

831+
/// <summary>
832+
/// Get the process ID associated with the thread.
833+
/// </summary>
834+
/// <param name="throw_on_error">True to throw on error.</param>
835+
/// <returns>The process ID.</returns>
836+
public NtResult<int> GetProcessId(bool throw_on_error)
837+
{
838+
if (_pid.HasValue)
839+
return _pid.Value.CreateResult();
840+
return QueryBasicInformation(throw_on_error).Map(i => i.ClientId.UniqueProcess.ToInt32());
841+
}
842+
843+
/// <summary>
844+
/// Get the thread ID.
845+
/// </summary>
846+
/// <param name="throw_on_error">True to throw on error.</param>
847+
/// <returns>The thread ID.</returns>
848+
public NtResult<int> GeThreadId(bool throw_on_error)
849+
{
850+
if (_tid.HasValue)
851+
return _tid.Value.CreateResult();
852+
return QueryBasicInformation(throw_on_error).Map(i => i.ClientId.UniqueProcess.ToInt32());
853+
}
854+
826855
/// <summary>
827856
/// Method to query information for this object type.
828857
/// </summary>

NtApiDotNet/NtToken.cs

Lines changed: 140 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -172,13 +172,24 @@ public NtToken DuplicateToken(TokenType type, SecurityImpersonationLevel level,
172172
}
173173

174174
/// <summary>
175-
/// Duplicate the token as a primary token
175+
/// Duplicate the token as the same token type.
176176
/// </summary>
177-
/// <returns>The new token</returns>
177+
/// <returns>The new token.</returns>
178178
/// <exception cref="NtException">Thrown on error</exception>
179179
public NtToken DuplicateToken()
180180
{
181-
return DuplicateToken(TokenType.Primary, SecurityImpersonationLevel.Anonymous, TokenAccessRights.MaximumAllowed);
181+
return DuplicateToken(true).Result;
182+
}
183+
184+
/// <summary>
185+
/// Duplicate the token as the same token type.
186+
/// </summary>
187+
/// <param name="throw_on_error">True to throw on error.</param>
188+
/// <returns>The new token.</returns>
189+
/// <exception cref="NtException">Thrown on error</exception>
190+
public NtResult<NtToken> DuplicateToken(bool throw_on_error)
191+
{
192+
return DuplicateToken(TokenType, ImpersonationLevel, TokenAccessRights.MaximumAllowed, throw_on_error);
182193
}
183194

184195
/// <summary>
@@ -887,6 +898,21 @@ public UserGroup[] QueryGroups(QueryGroupType group_type)
887898
return QueryGroups(group_type, true).Result;
888899
}
889900

901+
/// <summary>
902+
/// Get the user from the token.
903+
/// </summary>
904+
/// <param name="throw_on_error">True to throw on error.</param>
905+
/// <returns>The user group information.</returns>
906+
public NtResult<UserGroup> GetUser(bool throw_on_error)
907+
{
908+
using (var user = QueryBuffer(TokenInformationClass.TokenUser, new TokenUser(), throw_on_error))
909+
{
910+
if (!user.IsSuccess)
911+
return user.Cast<UserGroup>();
912+
return user.Result.Result.User.ToUserGroup().CreateResult();
913+
}
914+
}
915+
890916
/// <summary>
891917
/// Method to query information for this object type.
892918
/// </summary>
@@ -1854,15 +1880,27 @@ public static NtToken OpenProcessToken(NtProcess process, bool duplicate)
18541880
/// <exception cref="NtException">Thrown if cannot open token</exception>
18551881
public static NtToken OpenProcessToken(NtProcess process, bool duplicate, TokenAccessRights desired_access)
18561882
{
1857-
var ret = OpenProcessToken(process, desired_access, true).Result;
1858-
if (duplicate)
1883+
return OpenProcessToken(process, duplicate, desired_access, true).Result;
1884+
}
1885+
1886+
/// <summary>
1887+
/// Open the process token of another process
1888+
/// </summary>
1889+
/// <param name="process">The process to open the token for</param>
1890+
/// <param name="duplicate">True to duplicate the token before returning</param>
1891+
/// <param name="desired_access">The desired access for the token</param>
1892+
/// <param name="throw_on_error">True to throw on error.</param>
1893+
/// <returns>The opened token</returns>
1894+
/// <exception cref="NtException">Thrown if cannot open token</exception>
1895+
public static NtResult<NtToken> OpenProcessToken(NtProcess process, bool duplicate, TokenAccessRights desired_access, bool throw_on_error)
1896+
{
1897+
var ret = OpenProcessToken(process, desired_access, throw_on_error);
1898+
if (!ret.IsSuccess || !duplicate)
1899+
return ret;
1900+
using (ret)
18591901
{
1860-
using (ret)
1861-
{
1862-
return ret.DuplicateToken();
1863-
}
1902+
return ret.Result.DuplicateToken(throw_on_error);
18641903
}
1865-
return ret;
18661904
}
18671905

18681906
/// <summary>
@@ -1937,6 +1975,25 @@ public static NtToken OpenProcessToken(int pid, bool duplicate, TokenAccessRight
19371975
}
19381976
}
19391977

1978+
/// <summary>
1979+
/// Open the process token of another process
1980+
/// </summary>
1981+
/// <param name="pid">The id of the process to open the token for</param>
1982+
/// <param name="duplicate">True to duplicate the token before returning</param>
1983+
/// <param name="desired_access">The desired access for the token</param>
1984+
/// <param name="throw_on_error">True to throw on error.</param>
1985+
/// <returns>The opened token</returns>
1986+
/// <exception cref="NtException">Thrown if cannot open token</exception>
1987+
public static NtResult<NtToken> OpenProcessToken(int pid, bool duplicate, TokenAccessRights desired_access, bool throw_on_error)
1988+
{
1989+
using (var process = NtProcess.Open(pid, ProcessAccessRights.QueryLimitedInformation, throw_on_error))
1990+
{
1991+
if (!process.IsSuccess)
1992+
return process.Cast<NtToken>();
1993+
return OpenProcessToken(process.Result, duplicate, desired_access, throw_on_error);
1994+
}
1995+
}
1996+
19401997
/// <summary>
19411998
/// Open the process token of another process
19421999
/// </summary>
@@ -1968,24 +2025,37 @@ public static NtResult<NtToken> OpenThreadToken(NtThread thread, bool open_as_se
19682025
/// </summary>
19692026
/// <param name="thread">The thread to open the token for</param>
19702027
/// <param name="open_as_self">Open the token as the current identify rather than the impersonated one</param>
1971-
/// <param name="duplicate">True to duplicate the token before returning</param>
2028+
/// <param name="duplicate">True to duplicate the token before returning.</param>
19722029
/// <param name="desired_access">The desired access for the token</param>
2030+
/// <param name="throw_on_error">True to throw on error.</param>
19732031
/// <returns>The opened token, if no token return null</returns>
19742032
/// <exception cref="NtException">Thrown if cannot open token</exception>
1975-
public static NtToken OpenThreadToken(NtThread thread, bool open_as_self, bool duplicate, TokenAccessRights desired_access)
2033+
public static NtResult<NtToken> OpenThreadToken(NtThread thread, bool open_as_self,
2034+
bool duplicate, TokenAccessRights desired_access, bool throw_on_error)
19762035
{
19772036
var result = OpenThreadToken(thread, open_as_self, desired_access, false);
19782037
if (result.Status == NtStatus.STATUS_NO_TOKEN)
1979-
return null;
1980-
NtToken ret = result.GetResultOrThrow();
1981-
if (duplicate)
2038+
return new NtResult<NtToken>();
2039+
if (!duplicate)
2040+
return result;
2041+
using (result)
19822042
{
1983-
using (ret)
1984-
{
1985-
return ret.DuplicateToken();
1986-
}
2043+
return result.Result.DuplicateToken(throw_on_error);
19872044
}
1988-
return ret;
2045+
}
2046+
2047+
/// <summary>
2048+
/// Open the thread token
2049+
/// </summary>
2050+
/// <param name="thread">The thread to open the token for</param>
2051+
/// <param name="open_as_self">Open the token as the current identify rather than the impersonated one</param>
2052+
/// <param name="duplicate">True to duplicate the token before returning</param>
2053+
/// <param name="desired_access">The desired access for the token</param>
2054+
/// <returns>The opened token, if no token return null</returns>
2055+
/// <exception cref="NtException">Thrown if cannot open token</exception>
2056+
public static NtToken OpenThreadToken(NtThread thread, bool open_as_self, bool duplicate, TokenAccessRights desired_access)
2057+
{
2058+
return OpenThreadToken(thread, open_as_self, duplicate, desired_access, true).Result;
19892059
}
19902060

19912061
/// <summary>
@@ -2050,6 +2120,27 @@ public static NtToken OpenThreadToken()
20502120
return OpenThreadToken(false);
20512121
}
20522122

2123+
/// <summary>
2124+
/// Open the effective token, thread if available or process
2125+
/// </summary>
2126+
/// <param name="thread">The thread to open the token for</param>
2127+
/// <param name="duplicate">True to duplicate the token before returning</param>
2128+
/// <param name="throw_on_error">True to throw on error.</param>
2129+
/// <returns>The opened token</returns>
2130+
/// <exception cref="NtException">Thrown if cannot open token</exception>
2131+
public static NtResult<NtToken> OpenEffectiveToken(NtThread thread, bool duplicate, bool throw_on_error)
2132+
{
2133+
var token = OpenThreadToken(thread, true, duplicate, TokenAccessRights.MaximumAllowed, throw_on_error);
2134+
if (!token.IsSuccess || token.Result != null)
2135+
return token;
2136+
2137+
var pid = thread.GetProcessId(throw_on_error);
2138+
if (!pid.IsSuccess)
2139+
return pid.Cast<NtToken>();
2140+
2141+
return OpenProcessToken(pid.Result, duplicate, TokenAccessRights.MaximumAllowed, throw_on_error);
2142+
}
2143+
20532144
/// <summary>
20542145
/// Open the effective token, thread if available or process
20552146
/// </summary>
@@ -2078,7 +2169,18 @@ public static NtToken OpenEffectiveToken(NtThread thread, bool duplicate)
20782169
/// <exception cref="NtException">Thrown if cannot open token</exception>
20792170
public static NtToken OpenEffectiveToken()
20802171
{
2081-
return OpenEffectiveToken(NtThread.Current, false);
2172+
return OpenEffectiveToken(true).Result;
2173+
}
2174+
2175+
/// <summary>
2176+
/// Open the current effective token, thread if available or process
2177+
/// </summary>
2178+
/// <param name="throw_on_error">True to throw on error.</param>
2179+
/// <returns>The opened token</returns>
2180+
/// <exception cref="NtException">Thrown if cannot open token</exception>
2181+
public static NtResult<NtToken> OpenEffectiveToken(bool throw_on_error)
2182+
{
2183+
return OpenEffectiveToken(NtThread.Current, false, throw_on_error);
20822184
}
20832185

20842186
/// <summary>
@@ -2227,6 +2329,23 @@ public static ThreadImpersonationContext Impersonate(int pid, SecurityImpersonat
22272329
}
22282330
}
22292331

2332+
/// <summary>
2333+
/// Get the current user.
2334+
/// </summary>
2335+
/// <param name="throw_on_error">True to throw on error.</param>
2336+
/// <returns>The current user.</returns>
2337+
public static NtResult<UserGroup> GetCurrentUser(bool throw_on_error)
2338+
{
2339+
using (var token = OpenEffectiveToken(throw_on_error))
2340+
{
2341+
if (!token.IsSuccess)
2342+
{
2343+
return token.Cast<UserGroup>();
2344+
}
2345+
return token.Result.GetUser(throw_on_error);
2346+
}
2347+
}
2348+
22302349
#endregion
22312350

22322351
#region Static Properties

0 commit comments

Comments
 (0)