我正在C#中实现自定义凭据提供程序。我以一个C ++项目为例。这段C ++代码为Windows提供了一个映像。我看到phbmp的方式是指向图像位图的指针。代码要么更新指针,使其指向新的位图(从Resource中读取),要么将位图加载到phbmp指向的地址。我不确定指针本身是否已更改。

// Get the image to show in the user tile
HRESULT CSampleCredential::GetBitmapValue(DWORD dwFieldID, _Outptr_result_nullonfailure_ HBITMAP *phbmp)
{
    HRESULT hr;
    *phbmp = nullptr;

    if ((SFI_TILEIMAGE == dwFieldID))
    {
        HBITMAP hbmp = LoadBitmap(HINST_THISDLL, MAKEINTRESOURCE(IDB_TILE_IMAGE));
        if (hbmp != nullptr)
        {
            hr = S_OK;
            *phbmp = hbmp;
        }
        else
        {
            hr = HRESULT_FROM_WIN32(GetLastError());
        }
    }
    else
    {
        hr = E_INVALIDARG;
    }

    return hr;
}


以下是我正在实现的C#等效项:

public int GetBitmapValue(uint dwFieldID, IntPtr phbmp)
{
    if (dwFieldID == 2)
    {
        Bitmap image = Resource1.TileImage;

        ImageConverter imageConverter = new ImageConverter();
        byte[] bytes = (byte[])imageConverter.ConvertTo(image, typeof(byte[]));

        Marshal.Copy(bytes, 0, phbmp, bytes.Length);

        return HResultValues.S_OK;
    }

    return HResultValues.E_INVALIDARG;
}


我正在尝试做的是:


从资源加载图像(此方法有效,长度正确)
将位图转换为字节数组
将这些字节复制到phbmp指向的地址


由于内存分配,我认为这会崩溃。

该方法中的参数由接口定义(在Microsoft提供的CredentialProvider.Interop.dll中-我认为)。因此,我非常确定这是正确的,而且phbmp并非超出参数。

因为它不是参数,所以我不能更改phbmp使其指向我的位图,对吗?我已经将phbmp分配给Bitmap.GetHbitmap(),并且不会崩溃,但也无法正常工作。我假设对phbmp的更改仅在此方法中是本地的。

我可以理解不可能将内存分配给预定义的地址。这是另一回事:分配内存并获得指向它的指针。但是,此更改再次是本地的。这是如何运作的?

最佳答案

尽管有些人同意IntPtr应该是一个超参数(请参见https://syfuhs.net/2017/10/15/creating-custom-windows-credential-providers-in-net/中的注释),但答案实际上是:

var bmp = new Bitmap(imageStream);
Marshal.WriteIntPtr(phbmp, bmp.GetHbitmap());

08-25 17:59