0
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.

Hannele
  • 9,301
  • 6
  • 48
  • 68
John
  • 864
  • 1
  • 11
  • 26

2 Answers2

1

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.

Steven Wood
  • 2,675
  • 3
  • 26
  • 51
  • This looks like a good answer - a small code sample demonstrating the proper usage would also help! – Hannele Jul 26 '13 at 15:53
  • Actually, this right here -> https://learn.microsoft.com/en-us/dotnet/framework/interop/default-marshaling-for-strings#fixed-length-string-buffers talks about setting the Capacity for Fixed-Length String Buffers. – AaronR Jul 25 '21 at 17:40
0

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);
Icad
  • 101
  • 1
  • 6