Mattias,

Thank you very much! I was able to sort out these and other marshaling issues (a ton 
of credit to be given to your post).

To everyone on this list: Sorry for the RTFM posting. I locked myself in a room and 
read the entire marshaling documentation stack last night. I feel much more 
enlightened now.

Does anyone know of a managed Kerberos library (other than sun.security.krb5.*)? ;-) 
;-)

John

> -----Original Message-----
> From: Mattias Sjögren [mailto:[EMAIL PROTECTED]] 
> Sent: Friday, 26 April 2002 7:10 PM
> To: [EMAIL PROTECTED]
> Subject: Re: [DOTNET] Marshalling Issue
> 
> 
> John,
> 
> > > In
> > > particular, I'm having trouble trying to figure out how 
> to marshal 
> > > the following struct:
> > >
> > >       public struct KERB_QUERY_TKT_CACHE_RESPONSE
> > >       {
> > >               public KERB_PROTOCOL_MESSAGE_TYPE MessageType;
> > >               public ulong CountOfTickets;
> > >               public KERB_TICKET_CACHE_INFO[] Tickets;
> > >       }
> > >
> > > The marshaller bombs each and every time, stating that 
> the Tickets 
> > > array couldn't be marshalled as a struct.
> 
> The marhalling layer can't handle variable length arrays in a 
> struct. The 
> best workaround is usually to remove the  array member, and 
> then manually 
> calculate the offset of the array and read it.
> 
> 
> >        public struct LARGE_INTEGER
> >         {
> >                 public uint LowPart;
> >                 public int HighPart;
> >                 public struct u
> >                 {
> >                         public uint LowPart;
> >                         public int HighPart;
> >                 }
> >                 public long QuadPart;
> >         }
> 
> This isn't right. LARGE_INTEGER is a union that you either 
> can treat as a 
> single 64 bit integer, or two 32 bit parts. Since .NET has a 
> native 64 bit 
> integer, it's easier to remove this type entirely, and 
> replace it with a 
> long everywhere.
> 
> 
> >         [StructLayout(LayoutKind.Sequential)]
> >         public struct KERB_QUERY_TKT_CACHE_RESPONSE
> >         {
> >                 public KERB_PROTOCOL_MESSAGE_TYPE MessageType;
> >                 public uint CountOfTickets;
> >                 public KERB_TICKET_CACHE_INFO[] Tickets;
> >         }
> 
> I suggest you change it to
> 
>         public struct KERB_QUERY_TKT_CACHE_RESPONSE
>          {
>                  public KERB_PROTOCOL_MESSAGE_TYPE MessageType;
>                  public uint CountOfTickets;
>                  // public KERB_TICKET_CACHE_INFO[] Tickets;
>          }
> 
> 
> >         public class AccessTktCacheExample
> >         {
> >                [DllImport("secur32.dll")]
> >                 static extern void LsaConnectUntrusted(out IntPtr 
> > LsaHandle);
> 
> According to the docs, this function returns an NTSTATUS 
> value you might 
> want to check for success, not void.
> 
> 
> 
> >                [DllImport("secur32.dll")]
> >                 static extern int LsaCallAuthenticationPackage(
> >                         IntPtr LsaHandle,
> >                         ulong AuthenticationPackage,
> >                         ref KERB_QUERY_TKT_CACHE_REQUEST[]
> > ProtocolSubmitBuffer,
> >                         ref int SubmitBufferLength,
> >                         ref KERB_QUERY_TKT_CACHE_RESPONSE[] 
> > ProtocolReturnBuffer,
> >                         ref ulong ReturnBufferLength,
> >                         ref int ProtocolStatus);
> 
> AuthenticationPackage and ReturnBufferLength should have the 
> type (u)int, 
> not ulong. ProtocolSubmitBuffer shouldn't be an array, just ref 
> KERB_QUERY_TKT_CACHE_REQUEST should work. ProtocolReturnBuffer should 
> recieve a pointer to memory allocated by the function, you 
> shouldn't supply 
> your own buffer. Therefore, the type should be out IntPtr. 
> Don't forget to 
> free the buffer with LsaFreeReturnBuffer.
> 
> You can use Marshal.PtrToStructure to retrieve a 
> KERB_QUERY_TKT_CACHE_RESPONSE structure from the returned 
> pointer. You then 
> add an 8 byte offset 
> (Marshal.Sizeof(typeof(KERB_QUERY_TKT_CACHE_RESPONSE))) to 
> the pointer and 
> start reading KERB_TICKET_CACHE_INFO array, item by item. This can be 
> easier to do in an unsafe code block, where you can just 
> increment a "real" 
> pointer (not IntPtr).
> 
> 
> Mattias
> 
> ===
> Mattias Sjögren
> [EMAIL PROTECTED]

You can read messages from the DOTNET archive, unsubscribe from DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

Reply via email to