I was recently using BITS (Background Intelligent Transfer Service) to create a component for uploading and downloading files asynchronously from a windows sharepoint services document library. One of the requirement was transfer can only be done by authenticated users. BITS version 1.5 and above supports this via the IBackgroundCopyJob2::SetCredentials method. However, this method uses an union in its parameter and C# does not have union. After playing with interop attributes for a while I've worked out the necessary attributes to make this work with a C# only wrapper without going to managed C++.
After looking at the definition for BG_AUTH_CREDENTIALS in the .h file from the SDK, it turns out that the union (BG_AUTH_CREDENTIALS_UNION) only contains one type which is BG_BASIC_CREDENTIALS. I was able to make the call to SetCredentials work by using the FieldOffset attribute in the struct definitions.
Here is an extract of the important struct definitions.
internal enum BG_AUTH_SCHEME
{
// Fields
BG_AUTH_SCHEME_BASIC = 1,
BG_AUTH_SCHEME_DIGEST = 2,
BG_AUTH_SCHEME_NTLM = 3,
BG_AUTH_SCHEME_NEGOTIATE = 4,
BG_AUTH_SCHEME_PASSPORT = 5
}
internal enum BG_AUTH_TARGET
{
// Fields
BG_AUTH_TARGET_SERVER = 1,
BG_AUTH_TARGET_PROXY = 2,
}
[StructLayout(LayoutKind.Explicit, Size=16, Pack=4)]
internal struct BG_AUTH_CREDENTIALS
{
[FieldOffset(0)]
public BG_AUTH_TARGET Target;
[FieldOffset(4)]
public BG_AUTH_SCHEME Scheme;
[FieldOffset(8)]
public BG_AUTH_CREDENTIALS_UNION Credentials;
}
[StructLayout(LayoutKind.Explicit, Size=8, Pack=4)]
internal struct BG_AUTH_CREDENTIALS_UNION
{
[FieldOffset(0)]
public BG_BASIC_CREDENTIALS Basic;
}
[StructLayout(LayoutKind.Explicit, Size=8, Pack=4)]
internal struct BG_BASIC_CREDENTIALS
{
[FieldOffset(0)]
[MarshalAs(UnmanagedType.LPWStr)]
public string UserName;
[FieldOffset(4)]
[MarshalAs(UnmanagedType.LPWStr)]
public string Password;
}
I've posted the interop library at
http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=99f2f473-26de-41cd-bf39-8f7e75fda5aa