APICall GetTokenInformation returns 错误值
APICall GetTokenInformation returns error value
我使用以下 C# 代码:
enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId,
TokenGroupsAndPrivileges,
TokenSessionReference,
TokenSandBoxInert,
TokenAuditPolicy,
TokenOrigin
}
[StructLayout(LayoutKind.Sequential)]
public struct SID_AND_ATTRIBUTES
{
public IntPtr Sid;
public UInt32 Attributes;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_GROUPS
{
public UInt32 GroupCount;
// Followed by this:
[MarshalAs(UnmanagedType.ByValArray)]
public SID_AND_ATTRIBUTES[] Groups;
}
internal class TokenInformationTools : ITokenInformationTools
{
[DllImport("advapi32", SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
static extern int OpenProcessToken(System.IntPtr processHandle, int desiredAccess, ref IntPtr tokenHandle);
const int OpenProcessTokenFail = 0;
[DllImport("advapi32.dll", SetLastError = true)]
static extern int GetTokenInformation(IntPtr tokenHandle, TOKEN_INFORMATION_CLASS tokenInformationClass, IntPtr tokenInformation, int tokenInformationLength, out int returnLength);
const int GetTokenInformationFail = 0;
[DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool ConvertSidToStringSid(IntPtr securityIdentifier, out string securityIdentifierName);
[DllImport("kernel32.dll")]
static extern uint GetLastError();
public bool CheckForTokenGroup(string tokenGroupName)
{
var processHandle = Process.GetCurrentProcess().Handle;
IntPtr tokenHandler = IntPtr.Zero;
const int TOKEN_READ = 0x20008;
if (OpenProcessToken(processHandle, TOKEN_READ, ref tokenHandler) != OpenProcessTokenFail)
{
int length = 0;
var getTokenInformationReturnValue = GetTokenInformation(tokenHandler, TOKEN_INFORMATION_CLASS.TokenGroups, IntPtr.Zero, 0, out length);
if (getTokenInformationReturnValue != GetTokenInformationFail)
{
var tokenInfo = Marshal.AllocHGlobal(length);
if (GetTokenInformation(tokenHandler, TOKEN_INFORMATION_CLASS.TokenGroups, tokenInfo, length, out length) != GetTokenInformationFail)
{
int groupCount = Marshal.ReadInt32(tokenInfo);
const int sizeDword = 4;
var pSaa = tokenInfo + sizeDword;
for (int i = 0; i < groupCount; i++)
{
var groupInfo = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure((IntPtr)pSaa, typeof(SID_AND_ATTRIBUTES));
string sidAsString = string.Empty;
ConvertSidToStringSid(groupInfo.Sid, out sidAsString);
if (sidAsString == tokenGroupName)
{
Marshal.FreeHGlobal(tokenInfo);
return true;
}
pSaa += Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
}
}
else
{
var error = GetLastError();
}
Marshal.FreeHGlobal(tokenInfo);
}
else
{
var error = GetLastError();
}
}
return false;
}
}
问题是,getTokenInformationReturnValue 在第一次调用时为 0。因此,如此处所述:https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-gettokeninformation 这是错误情况:
If the function succeeds, the return value is nonzero.
GetLastError returns 0 表示“操作成功完成。”根据此:https://docs.microsoft.com/de-de/windows/desktop/Debug/system-error-codes--0-499-
但该功能似乎仍然有效。如果我忽略 getTokenInformationReturnValue(以及以下对 GetTokenInformation 的调用的 return 值),一切似乎都按预期工作。
此代码是以下 VBA 代码的副本,其中 GetTokenInformationFail 的 return 值不为 0。
Enum TokenInformation
TokenUser = 1
TokenGroups = 2
End Enum
Private Const TOKEN_READ As Long = &H20008
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pTo As Any, uFrom As Any, ByVal lSize As Long)
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Const GetCurrentProcessFail As Long = 0
Private Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Const OpenProcessTokenFail As Long = 0
Private Declare Function GetTokenInformation Lib "advapi32.dll" (ByVal TokenHandle As Long, ByVal TokenInformationClass As Long, TokenInformation As Any, ByVal TokenInformationLength As Long, ReturnLength As Long) As Long
Private Const GetTokenInformationFail As Long = 0
Private Declare Function ConvertSidToStringSid Lib "advapi32.dll" Alias "ConvertSidToStringSidA" (ByVal lpSid As Long, lpString As Long) As Long
Private Declare Function LocalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString As Long) As Long
Private Type SID_AND_ATTRIBUTES
Sid As Long
Attributes As Long
End Type
Private Type VB_TOKEN_GROUPS
GroupCount As Long
Groups() As SID_AND_ATTRIBUTES
End Type
Private Const SizeDword As Long = 4
Public Function fn_checkForTokenGroup(ByVal par_UserGroupSid As String) As Boolean
Dim dPseudoProcessHandle As Long
Dim dTokenHandler As Long
Dim dNeeded As Long
Dim dReadBuffer() As Byte
Dim dStringBuffer As String
Dim dStringPointer As Long
Dim dGroupData As VB_TOKEN_GROUPS
On Error GoTo fn_checkForTokenGroup_error
fn_checkForTokenGroup = False
dPseudoProcessHandle = GetCurrentProcess()
If dPseudoProcessHandle <> GetCurrentProcessFail Then
If OpenProcessToken(dPseudoProcessHandle, TOKEN_READ, dTokenHandler) <> OpenProcessTokenFail Then
Call GetTokenInformation(dTokenHandler, TokenInformation.TokenGroups, ByVal 0, 0, dNeeded)
ReDim dReadBuffer(0 To dNeeded)
If GetTokenInformation(dTokenHandler, TokenInformation.TokenGroups, dReadBuffer(0), UBound(dReadBuffer), dNeeded) <> GetTokenInformationFail Then
Call CopyMemory(dGroupData.GroupCount, dReadBuffer(0), SizeDword)
ReDim dGroupData.Groups(0 To dGroupData.GroupCount - 1)
Call CopyMemory(dGroupData.Groups(0), dReadBuffer(SizeDword), dGroupData.GroupCount * Len(dGroupData.Groups(0)))
Dim i As Long
For i = 0 To dGroupData.GroupCount - 1
If ConvertSidToStringSid(dGroupData.Groups(i).Sid, dStringPointer) Then
dStringBuffer = Space(lstrlen(dStringPointer))
Call CopyMemory(ByVal dStringBuffer, ByVal dStringPointer, Len(dStringBuffer))
Call LocalFree(dStringPointer)
If (dStringBuffer = par_UserGroupSid) Then
fn_checkForTokenGroup = True
GoTo fn_checkForTokenGroup_endeSchleife:
End If
End If
Next
fn_checkForTokenGroup_endeSchleife:
End If
Call CloseHandle(dTokenHandler)
End If
Call CloseHandle(dPseudoProcessHandle)
End If
fn_checkForTokenGroup_exit:
Exit Function
fn_checkForTokenGroup_error:
Call msg_error_norm(ModuleName, "CheckForTokenGroup")
GoTo fn_checkForTokenGroup_exit:
End Function
那么我的 C# 代码有什么问题?我的声明有问题吗?
您不能使用 GetLastError
但是
int nLastWin32Error = Marshal.GetLastWin32Error();
当return值为0时测试这个错误==ERROR_INSUFFICIENT_BUFFER (122),
那么你可以调用 Marshal.AllocHGlobal
我使用以下 C# 代码:
enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId,
TokenGroupsAndPrivileges,
TokenSessionReference,
TokenSandBoxInert,
TokenAuditPolicy,
TokenOrigin
}
[StructLayout(LayoutKind.Sequential)]
public struct SID_AND_ATTRIBUTES
{
public IntPtr Sid;
public UInt32 Attributes;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_GROUPS
{
public UInt32 GroupCount;
// Followed by this:
[MarshalAs(UnmanagedType.ByValArray)]
public SID_AND_ATTRIBUTES[] Groups;
}
internal class TokenInformationTools : ITokenInformationTools
{
[DllImport("advapi32", SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
static extern int OpenProcessToken(System.IntPtr processHandle, int desiredAccess, ref IntPtr tokenHandle);
const int OpenProcessTokenFail = 0;
[DllImport("advapi32.dll", SetLastError = true)]
static extern int GetTokenInformation(IntPtr tokenHandle, TOKEN_INFORMATION_CLASS tokenInformationClass, IntPtr tokenInformation, int tokenInformationLength, out int returnLength);
const int GetTokenInformationFail = 0;
[DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool ConvertSidToStringSid(IntPtr securityIdentifier, out string securityIdentifierName);
[DllImport("kernel32.dll")]
static extern uint GetLastError();
public bool CheckForTokenGroup(string tokenGroupName)
{
var processHandle = Process.GetCurrentProcess().Handle;
IntPtr tokenHandler = IntPtr.Zero;
const int TOKEN_READ = 0x20008;
if (OpenProcessToken(processHandle, TOKEN_READ, ref tokenHandler) != OpenProcessTokenFail)
{
int length = 0;
var getTokenInformationReturnValue = GetTokenInformation(tokenHandler, TOKEN_INFORMATION_CLASS.TokenGroups, IntPtr.Zero, 0, out length);
if (getTokenInformationReturnValue != GetTokenInformationFail)
{
var tokenInfo = Marshal.AllocHGlobal(length);
if (GetTokenInformation(tokenHandler, TOKEN_INFORMATION_CLASS.TokenGroups, tokenInfo, length, out length) != GetTokenInformationFail)
{
int groupCount = Marshal.ReadInt32(tokenInfo);
const int sizeDword = 4;
var pSaa = tokenInfo + sizeDword;
for (int i = 0; i < groupCount; i++)
{
var groupInfo = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure((IntPtr)pSaa, typeof(SID_AND_ATTRIBUTES));
string sidAsString = string.Empty;
ConvertSidToStringSid(groupInfo.Sid, out sidAsString);
if (sidAsString == tokenGroupName)
{
Marshal.FreeHGlobal(tokenInfo);
return true;
}
pSaa += Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
}
}
else
{
var error = GetLastError();
}
Marshal.FreeHGlobal(tokenInfo);
}
else
{
var error = GetLastError();
}
}
return false;
}
}
问题是,getTokenInformationReturnValue 在第一次调用时为 0。因此,如此处所述:https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-gettokeninformation 这是错误情况:
If the function succeeds, the return value is nonzero.
GetLastError returns 0 表示“操作成功完成。”根据此:https://docs.microsoft.com/de-de/windows/desktop/Debug/system-error-codes--0-499-
但该功能似乎仍然有效。如果我忽略 getTokenInformationReturnValue(以及以下对 GetTokenInformation 的调用的 return 值),一切似乎都按预期工作。
此代码是以下 VBA 代码的副本,其中 GetTokenInformationFail 的 return 值不为 0。
Enum TokenInformation
TokenUser = 1
TokenGroups = 2
End Enum
Private Const TOKEN_READ As Long = &H20008
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pTo As Any, uFrom As Any, ByVal lSize As Long)
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Const GetCurrentProcessFail As Long = 0
Private Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Const OpenProcessTokenFail As Long = 0
Private Declare Function GetTokenInformation Lib "advapi32.dll" (ByVal TokenHandle As Long, ByVal TokenInformationClass As Long, TokenInformation As Any, ByVal TokenInformationLength As Long, ReturnLength As Long) As Long
Private Const GetTokenInformationFail As Long = 0
Private Declare Function ConvertSidToStringSid Lib "advapi32.dll" Alias "ConvertSidToStringSidA" (ByVal lpSid As Long, lpString As Long) As Long
Private Declare Function LocalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString As Long) As Long
Private Type SID_AND_ATTRIBUTES
Sid As Long
Attributes As Long
End Type
Private Type VB_TOKEN_GROUPS
GroupCount As Long
Groups() As SID_AND_ATTRIBUTES
End Type
Private Const SizeDword As Long = 4
Public Function fn_checkForTokenGroup(ByVal par_UserGroupSid As String) As Boolean
Dim dPseudoProcessHandle As Long
Dim dTokenHandler As Long
Dim dNeeded As Long
Dim dReadBuffer() As Byte
Dim dStringBuffer As String
Dim dStringPointer As Long
Dim dGroupData As VB_TOKEN_GROUPS
On Error GoTo fn_checkForTokenGroup_error
fn_checkForTokenGroup = False
dPseudoProcessHandle = GetCurrentProcess()
If dPseudoProcessHandle <> GetCurrentProcessFail Then
If OpenProcessToken(dPseudoProcessHandle, TOKEN_READ, dTokenHandler) <> OpenProcessTokenFail Then
Call GetTokenInformation(dTokenHandler, TokenInformation.TokenGroups, ByVal 0, 0, dNeeded)
ReDim dReadBuffer(0 To dNeeded)
If GetTokenInformation(dTokenHandler, TokenInformation.TokenGroups, dReadBuffer(0), UBound(dReadBuffer), dNeeded) <> GetTokenInformationFail Then
Call CopyMemory(dGroupData.GroupCount, dReadBuffer(0), SizeDword)
ReDim dGroupData.Groups(0 To dGroupData.GroupCount - 1)
Call CopyMemory(dGroupData.Groups(0), dReadBuffer(SizeDword), dGroupData.GroupCount * Len(dGroupData.Groups(0)))
Dim i As Long
For i = 0 To dGroupData.GroupCount - 1
If ConvertSidToStringSid(dGroupData.Groups(i).Sid, dStringPointer) Then
dStringBuffer = Space(lstrlen(dStringPointer))
Call CopyMemory(ByVal dStringBuffer, ByVal dStringPointer, Len(dStringBuffer))
Call LocalFree(dStringPointer)
If (dStringBuffer = par_UserGroupSid) Then
fn_checkForTokenGroup = True
GoTo fn_checkForTokenGroup_endeSchleife:
End If
End If
Next
fn_checkForTokenGroup_endeSchleife:
End If
Call CloseHandle(dTokenHandler)
End If
Call CloseHandle(dPseudoProcessHandle)
End If
fn_checkForTokenGroup_exit:
Exit Function
fn_checkForTokenGroup_error:
Call msg_error_norm(ModuleName, "CheckForTokenGroup")
GoTo fn_checkForTokenGroup_exit:
End Function
那么我的 C# 代码有什么问题?我的声明有问题吗?
您不能使用 GetLastError 但是
int nLastWin32Error = Marshal.GetLastWin32Error();
当return值为0时测试这个错误==ERROR_INSUFFICIENT_BUFFER (122), 那么你可以调用 Marshal.AllocHGlobal