简体   繁体   中英

DllImport ERROR_MORE_DATA UNMANAGED Call C++ in C# PBYTE

DWORD OREnumValue(
  __in         ORHKEY Handle,
  __in         DWORD dwIndex,
  __out        PWSTR lpValueName,
  __inout      PDWORD lpcValueName,
  __out_opt    PDWORD lpType,
  __out_opt    PBYTE lpData,
  __inout_opt  PDWORD lpcbData
);

My Code:

public static extern uint OREnumValue(IntPtr Handle, uint dwIndex, [MarshalAsAttribute(UnmanagedType.LPWStr)] out StringBuilder lpValueName, ref int lpcValueName, out uint lpType, out IntPtr lpData, ref int lpcbData);

    IntPtr Handle=mykey;
    uint dwIndex=0;

    StringBuilder lpValueName = new StringBuilder(16383);
    int lpcValueName=lpValueName.Capacity;  

    uint lpType=0;
    IntPtr lpData;
    int lpcbData = int.MaxValue;

    uint ret3= OREnumValue(Handle, dwIndex, out lpValueName, ref lpcValueName, out lpType, out lpData, ref lpcbData);

This gives an error:

ret3=ERROR_MORE_DATA 259

I think problem is either in

  1. lpData - what should I use for PBYTE? Or
  2. lpcbData - what capacity should I use?

From MSDN

If the buffer specified by lpData is not large enough to hold the data, the function returns ERROR_MORE_DATA and stores the required buffer size in the variable pointed to by lpcbData. In this case, the contents of lpData are undefined.

You should NEVER explicitly define the length of the string builders, this value should be got using the method RegQueryInfoKey which will give you the length in bytes of the longest value name, subkey name and value data, which you can then use to initialise the string builders and byte arrays recieving the actual names and data. This means that you have the smallest possible amount of memory used whilst still being large enough to contain the result. I am pretty sure your problem is in the length you defined for lpValueName.

Also you should use UIntPtr rather than IntPtr and the lpData field should be a byte array if you want the data.

according to the following sources you should use IntPtr for PBYTE:

(these are not for your api explicitly but are using PBYTE as well. If you compare c++ values from msdn with the listed links)

you will most likely need to define

    var myIntPtr = Marshal.AllocCoTaskMem(sizeOfMyIntPtr);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM