This code causes the following exception, sometimes:
"Attempted to read or write protected memory. This is often an indication that other memory is corrupt"
private static TOKEN_GROUPS GetTokenGroups(IntPtr tokenHandle)
{
var groups = new TOKEN_GROUPS();
uint tokenInfoLength = 0;
uint returnLength;
var res = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenGroups, IntPtr.Zero,
tokenInfoLength, out returnLength);
if (!res && returnLength > 0)
{
tokenInfoLength = returnLength;
var tokenInfo = Marshal.AllocHGlobal((int) tokenInfoLength);
res = GetTokenInformation(tokenHandle,
TOKEN_INFORMATION_CLASS.TokenGroups,
tokenInfo,
tokenInfoLength,
out returnLength);
if(res)
{
groups = (TOKEN_GROUPS)Marshal.PtrToStructure(tokenInfo, typeof (TOKEN_GROUPS));
}
Marshal.FreeHGlobal(tokenInfo);
CloseHandle(tokenHandle);
}
else
{
var error = new Win32Exception(Marshal.GetLastWin32Error());
_log.WarnFormat("Failed evaluate the call to get process token information. {0}", error.Message);
}
return groups;
}
The line that fails is groups = (TOKEN_GROUPS)Marshal.PtrToStructure(tokenInfo, typeof (TOKEN_GROUPS));
I would say the exception happens in 1 and every 20 calls to this method. Once it begins happening every call afterwards will throw the exception. Restarting the process causes the error to go away.
IntPtr tokenHandle
is the result of:
var processId = GetCurrentProcess();
_log.InfoFormat("Process ID [{0}]", processId.ToString());
if (processId != IntPtr.Zero)
{
IntPtr tokenHandle;
if (OpenProcessToken(processId, TOKEN_READ, out tokenHandle))
{
groups = GetTokenGroups(tokenHandle);
}
EDIT Hopefully this isn't information overload but here's the pinvoke declarations:
struct TOKEN_GROUPS
{
public uint GroupCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4000)]
public SID_AND_ATTRIBUTES[] Groups;
}
[StructLayout(LayoutKind.Sequential)]
struct SID_AND_ATTRIBUTES
{
public IntPtr SID;
public uint Attributes;
}
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool GetTokenInformation(
IntPtr TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
IntPtr TokenInformation,
uint TokenInformationLength,
out uint ReturnLength);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool OpenProcessToken(IntPtr ProcessHandle,
UInt32 DesiredAccess, out IntPtr TokenHandle);
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentProcess();
enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId,
TokenGroupsAndPrivileges,
TokenSessionReference,
TokenSandBoxInert,
TokenAuditPolicy,
TokenOrigin
}