2

RegSetValueEx has the following P/Invoke signature:

[DllImport("advapi32.dll", SetLastError = true)]
static extern uint RegSetValueEx(
 UIntPtr hKey,
 [MarshalAs(UnmanagedType.LPStr)]
 string lpValueName,
 int Reserved,
 RegistryValueKind dwType,
 IntPtr lpData,
 int cbData);

The IntPtr lpData parameter can be a pain to work with. To pass a string value, I need to call one of the Marshall.StringToHGlobal functions and then release it when I'm done. My code can be simpler if I change the type of the lpData parameter to [MarshalAs(UnmanagedType.LPStr)]String lpData. This seems to work and I can imagine that behind the scenes the marshalling code is doing exactly what I would do to get an IntPtr. I haven't been able to find any definitive statements if this is legal or not. Can anyone provide one?

[Yes, I know there is managed code to interface with the registry. In my particular case I can't use it, and even if I could I would still be interested in the answer in general]

bmm6o
  • 6,187
  • 3
  • 28
  • 55

1 Answers1

5

Yes, this is a perfectly normal and acceptable technique in pinvoke. Just about any winapi function argument of type BYTE*, PVOID, LPARAM lends itself to a customized [DllImport] declaration. A string, array or struct is the usual equivalent C# parameter type. Particularly useful when you declare SendMessage().

Not where it ends, you can also readily take advantage of the C# language allowing method overloads. In other words, you can write any number of RegSetValueEx() declarations with different types for the lpData argument. They all map to the same native function so nothing else you have to do. A practical example is here.

You just have to make sure that the value you pass after marshalling has the expected byte values. Beware that mistakes tend to be hard to debug, you might still want to marshal manually if the call doesn't pan out. One quirk is certainly notable for this question, you always want to use CharSet = CharSet.Unicode in the declaration, calling the ANSI version (RegSetValueExA) is not useful. Now you can also add ExactSpelling = true.

Community
  • 1
  • 1
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Do you have any links to e.g. MSDN that call this out as explicitly supported behavior? Or are we relying on details of the current implementation? – bmm6o Mar 27 '17 at 20:58
  • No, this is not explicitly documented afaik. It is used in .NET Framework source code, originally published through the SSCLI project, that's how I personally became aware of it. – Hans Passant Mar 27 '17 at 21:15