470,602 Members | 1,546 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,602 developers. It's quick & easy.

Marshal.AllocHGlobal failure after calling GetTokenInformation

I have been banging my head against the wall for a while now, and can't
seem to id the problem. I've been through a ton of posts and the code
doesn't seem any different. Can anybody see it?

When I call to GetTokenInformation I receive a buffer size (see
//HERE... comment in code), but when I let the code continue, asp.net
just sits there returning nothing, apparently on the
Marshal.AllocHGlobal call.

Here's the library function:

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~
using System;
using System.Collections.Specialized;
using System.DirectoryServices;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text.RegularExpressions;
namespace foobar.Library
{
public class AdFunctions
{
enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId,
TokenGroupsAndPrivileges,
TokenSessionReference,
TokenSandBoxInert,
TokenAuditPolicy,
TokenOrigin
}

public struct TOKEN_USER
{
public SID_AND_ATTRIBUTES User; // a single SID_AND_ATTRIBUTES
struct
}

public struct TOKEN_GROUPS
{
public int GroupCount; // DWORD number of groups
public SID_AND_ATTRIBUTES[] Groups; // array of SID_AND_ATTRIBUTES
structs
}

public struct SID_AND_ATTRIBUTES
{
public IntPtr Sid; // pointer to a sid
public int Attributes; // DWORD attributes
}
//[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
//static extern bool ConvertSidToStringSid( IntPtr pSID,
[In,Out,MarshalAs(UnmanagedType.LPTStr)] ref string pStringSid);

// Using IntPtr for pSID insted of Byte[]
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern bool ConvertSidToStringSid(IntPtr pSID, out IntPtr
pSid);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern bool ConvertStringSidToSid( string sStringSid, out
IntPtr pSID );

[DllImport("advapi32.dll", SetLastError=true)]
static extern bool GetTokenInformation(
IntPtr TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
IntPtr TokenInformation,
int TokenInformationLength,
out int ReturnLength);

[DllImport("kernel32.dll")]
static extern IntPtr LocalFree(IntPtr hMem);

public int GetGroupSidsFromToken(IntPtr pToken, ref string[] aSids)
{
int iTokenInfoLength = 0;
bool bResult = true;

// first call gets length of TokenInformation
bResult = GetTokenInformation( pToken,
TOKEN_INFORMATION_CLASS.TokenGroups, IntPtr.Zero, 0, out
iTokenInfoLength );

//HERE if I uncomment this, the call returns an integer rapidly
//return iTokenInfoLength;

// if we got a return, continue
if ( iTokenInfoLength > 0 )
{
// allocate a memory buffer for the TokenInformation
IntPtr pTokenInfo = Marshal.AllocHGlobal( iTokenInfoLength );

// get the TokenInformation
bResult = GetTokenInformation( pToken,
TOKEN_INFORMATION_CLASS.TokenGroups , pTokenInfo, iTokenInfoLength, out
iTokenInfoLength ) ;
if ( bResult == false ) { return 2; }

// convert the TokenInformation to a TOKEN_GROUPS struct
TOKEN_GROUPS TokenGroups = ( TOKEN_GROUPS )Marshal.PtrToStructure(
pTokenInfo , typeof( TOKEN_GROUPS ) ) ;

// loop through the groups
for ( int i=0; i < TokenGroups.GroupCount; i++ )
{
IntPtr pSid = IntPtr.Zero;

// get the string representation of the sid
bResult = ConvertSidToStringSid( TokenGroups.Groups[i].Sid, out
pSid );
if ( bResult == false ) { return 3; }

// put it into a c# string and free the memory
string sSid = Marshal.PtrToStringAuto( pSid );
LocalFree(pSid);

// add it to the array reference
aSids[i] = sSid;
}
}
else
{
// GetTokenInformation returned a 0 length
return 1;
}

// all set
return 0;
}


}
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~

Here's the code behind file that calls it:

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Security.Principal;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

using foobar.Library;

namespace Users
{
/// <summary>
/// Summary description for WebForm1.
/// </summary>
public class Default : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Label lblStatusLine;

private void Page_Load(object sender, System.EventArgs e)
{
Trace.Write("debug", "Page_Load: entered function");
Trace.Write("debug", "Page_Load: user id is " +
System.Web.HttpContext.Current.User.Identity.Name. ToString() );
Trace.Write("debug", "Page_Load: process id is " +
WindowsIdentity.GetCurrent().Name.ToString() );

string[] aSids = new string[200];
Trace.Write("debug", "Page_Load: created array" );

AdFunctions oAdFunctions = new AdFunctions();
Trace.Write("debug", "Page_Load: created AdFunctions object" );

int iReturn =
oAdFunctions.GetGroupSidsFromToken(WindowsIdentity .GetCurrent().Token,
ref aSids);
Trace.Write("debug", "Page_Load: AdFunctions.GetGroupSidsFromToken
returned " + iReturn.ToString() );

if ( iReturn == 0 )
{
// TODO color the output
lblStatusLine.Text = "ok...";
}
else
{
lblStatusLine.Text = Application["ProductName"] + " could not
retrive your logon groups. Please contact your administrator
(GetGroupSidsFromToken:" + iReturn.ToString() + ").";
}
}

#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion
}
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~

and finally the aspx page:

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~

<%@ Page language="c#" Codebehind="Default.aspx.cs"
AutoEventWireup="false" Inherits="Users.Default" Trace="True"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm1</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<asp:Label id="lblStatusLine" style="Z-INDEX: 101; LEFT: 160px;
POSITION: absolute; TOP: 760px"
runat="server" Width="872px"></asp:Label>
</form>
</body>
</HTML>

Nov 17 '05 #1
1 3882
I managed to fix this, the fixed code is below:

thanks to Mattias from the post "How to call Win32 Native API
GetTokenInformation() using C#?"

public class Misc
{

public Array redim(Array arrToResize, int length)
{
// from http://www.code101.com/Code101/Displ...le.aspx?cid=54
Type t= arrToResize.GetType().GetElementType();
Array newArray=Array.CreateInstance(t,length);
Array.Copy(arrToResize,0,newArray,0,Math.Min(arrTo Resize.Length,length));
return newArray;
}
}

public class AdFunctions
{
enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId,
TokenGroupsAndPrivileges,
TokenSessionReference,
TokenSandBoxInert,
TokenAuditPolicy,
TokenOrigin
}

public struct TOKEN_USER
{
public SID_AND_ATTRIBUTES User; // a single SID_AND_ATTRIBUTES
struct
}

[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_GROUPS
{
public int GroupCount; // DWORD number of groups
public SID_AND_ATTRIBUTES[] Groups; // array of SID_AND_ATTRIBUTES
structs
}

[StructLayout(LayoutKind.Sequential)]
public struct SID_AND_ATTRIBUTES
{
public IntPtr Sid; // pointer to a sid
public int Attributes; // DWORD attributes
}
//[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
//static extern bool ConvertSidToStringSid( IntPtr pSID,
[In,Out,MarshalAs(UnmanagedType.LPTStr)] ref string pStringSid);

// Using IntPtr for pSID insted of Byte[]
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern bool ConvertSidToStringSid(IntPtr pSID, out IntPtr
pSid);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern bool ConvertStringSidToSid( string sStringSid, out
IntPtr pSID );

[DllImport("advapi32.dll", SetLastError=true)]
static extern bool GetTokenInformation(
IntPtr TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
IntPtr TokenInformation,
int TokenInformationLength,
out int ReturnLength);

[DllImport("kernel32.dll")]
static extern IntPtr LocalFree(IntPtr hMem);

public int GetGroupSidsFromToken(IntPtr pToken, ref string[] aSids)
{
int iTokenInfoLength = 0;
bool bResult = true;

// first call gets length of TokenInformation
bResult = GetTokenInformation( pToken,
TOKEN_INFORMATION_CLASS.TokenGroups, IntPtr.Zero, 0, out
iTokenInfoLength );
// if I uncomment this, the call returns an integer rapidly
//return iTokenInfoLength;

// if we got a return, continue
if ( iTokenInfoLength > 0 )
{
// allocate a memory buffer for the TokenInformation
IntPtr pTokenInfo = Marshal.AllocHGlobal( iTokenInfoLength );

// get the TokenInformation
bResult = GetTokenInformation( pToken,
TOKEN_INFORMATION_CLASS.TokenGroups , pTokenInfo, iTokenInfoLength, out
iTokenInfoLength ) ;
if ( bResult == false ) { return 2; }

// why would this be here and not after Marshal.PtrToStructure?
like TokenGroups.GroupCount?
int groupCount = Marshal.ReadInt32( pTokenInfo );

// convert the TokenInformation to a TOKEN_GROUPS struct
// BREAKING HERE
//TOKEN_GROUPS TokenGroups = ( TOKEN_GROUPS
)Marshal.PtrToStructure( pTokenInfo , typeof( TOKEN_GROUPS ) ) ;

// get a pointer to the first group
int pSidAndAttibutes = (int)pTokenInfo + 4;

// loop through the groups
for ( int i=0; i < groupCount; i++ )
{
// marshall the struct out of the pointer
SID_AND_ATTRIBUTES SidAndAttibutes =
(SID_AND_ATTRIBUTES)Marshal.PtrToStructure( (IntPtr)pSidAndAttibutes ,
typeof(SID_AND_ATTRIBUTES) ) ;

// initialize a pointer and get the sid converted
IntPtr pSid = IntPtr.Zero;
bResult = ConvertSidToStringSid( SidAndAttibutes.Sid, out pSid );
if ( bResult == false ) { return 3; }

// place it into a c# string and free up the memory
string sSid = Marshal.PtrToStringAuto( pSid );
LocalFree(pSid);

// add it to the array reference
aSids[i] = sSid;

// move to the next pointer
pSidAndAttibutes += Marshal.SizeOf( typeof(SID_AND_ATTRIBUTES) );
}
// redim the array
Misc oMisc = new Misc();
aSids = (string[])oMisc.redim(aSids, groupCount);
}
else
{
// GetTokenInformation returned a 0 length
return 1;
}

// all set
return 0;
}

Nov 17 '05 #2

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

2 posts views Thread by Stefan | last post: by
2 posts views Thread by scottt | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.