从32位编译版本的应用程序调用本机代码时,为什么会出现AccessViolationException,而不是从64位版本调用

时间:2014-11-19 22:07:06

标签: c# clr pinvoke

我从C#托管代码中调用一些C ++本机代码。当这个DLL从64位或AnyCPU编译的应用程序加载时,一切都很完美。当从32位应用程序加载它时,我在调用InitializeSecurityContextW方法时得到AccessViolationException。本机方法的定义如下:

[DllImport(SECUR32DLL, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
private static extern StatusEnum InitializeSecurityContextW(
    [In] ref HandleStruct handle1,
    [In] IntPtr handle2,
    [In] String str,
    [In] uint flags1,
    [In] uint reserved1,
    [In] uint flags2,
    [In] IntPtr bufferDesc,
    [In] uint reserved2,
    [In, Out] ref HandleStruct handleOut,
    [In, Out] BufferDescriptor bufferDescOut,
    [Out] out uint flagsOut,
    [Out] out long expiryOut);

使用以下Structs和enums:

public struct HandleStruct
{
    private IntPtr Low;
    private IntPtr High;

    public bool IsZero
    {
        return Low == IntPtr.Zero && High == IntPtr.Zero;
    }
}

private enum StatusEnum {
     // Values here.
}

[StructLayout(LayoutKind.Sequential, Pack=1)]
private struct BufferDescriptor
{
    public uint Version;
    public uint Count;
    public IntPtr BufferArray;
}

[StructLayout(LayoutKind.Sequential, Pack=1)]
private struct Buffer
{
    public uint Size;
    public uint Type;
    public IntPtr Data;
}

(简化的)调用代码是:

Buffer[] bufferOut = new Buffer[1];
bufferOut[0].Size = 0;
bufferOut[0].Type = 2; // Token type
bufferOut[0].Data = IntPtr.Zero; // I'm asking the server to allocate this memory (unmanaged).

GCHandle bufferOutPtr = GCHandle.Alloc(bufferOut, GCHandleType.Pinned);

BufferDescriptor bufferDescOut = new BufferDescriptor();
bufferDescOut.Count = 1;
bufferDescOut.Version = 0; // Version number
bufferDescOut.BufferArray = bufferOutPtr.AddrOfPinnedObject();

uint flags1 = // Some flags here including asking the server to allocate memory;
uint flags2 = 0; //data representation

uint flagsOut;
long expiry;

StatusEnum status = InitializeSecurityContextW(
    ref handle1, // From calling method
    IntPtr.Zero, // Null for this call
    str, // From calling method
    flags1,
    0,
    flags2,
    IntPtr.Zero, // Null for this call
    0,
    ref handleOut, // From calling method, currently handleOut.IsZero == true
    bufferDescOut,
    out flagsOut,
    out expiry);

// Clean up code, never reached.

为什么会发生这种情况,为什么只能在32位?

1 个答案:

答案 0 :(得分:0)

我需要固定输出缓冲区描述符并传递地址而不是整个结构。