How to call a method which expects a pointer? #250
-
I want to call the method DhcpEnumSubnets() from the Dhcpsapi.dll.
The variable enumInfo should have the desired values after a succesfull call. CS0214 Pointers and fixed size buffers may only be used in an unsafe context After marking the class Win32Example with the unsafe keyword:
The error changes to: CS1919 Unsafe type 'DHCP_IP_ARRAY*' cannot be used in object creation I discovered the keyword stackalloc, and changed initialization of enumInfo to:
Now I receive an alert stating that all threads were allowed to run to prevent an unsafe abort when evaluating the method. The method call looks now like this:
Is this the right way to call this method? If this is the right way, how to I marshal the DHCP_IP_ARRAY* to an uint array, Thank you AArnott for your help. For further reference, this worked for me: public static unsafe List<string> DhcpEnumSubnetAddresses(string serverAddress)
{
uint resumeHandle = 0;
uint preferredMaximum = 65536;
DHCP_IP_ARRAY* enumInfo = null;
List<string> subnets = new();
var result = PInvoke.DhcpEnumSubnets(serverAddress,
ref resumeHandle,
preferredMaximum,
ref enumInfo,
out uint elementsRead,
out uint elementsTotal);
try
{
if (result.IsEqual(DhcpErrorCode.ERROR_NO_MORE_ITEMS))
return subnets;
if (result.IsSuccess())
{
DHCP_IP_ARRAY subnetElements = *enumInfo;
for (uint j = 0; j < subnetElements.NumElements; j++)
{
uint subnetAddressNative = subnetElements.Elements[j];
var subnetAddress = DhcpHelper.NativeIpAddressToString(subnetAddressNative);
subnets.Add(subnetAddress);
}
}
}
finally
{
PInvoke.DhcpRpcFreeMemory(enumInfo);
}
return subnets;
} Notice the
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 6 replies
-
Thanks for reaching out. This is a sub-par experience and I filed microsoft/win32metadata#452 to get this fixed in the metadata. The only real problem is the In the meantime, this syntax should work. You don't want to use using System;
using Microsoft.Windows.Sdk;
unsafe
{
uint resumeHandle = 0;
uint preferredMaximum = 65536;
DHCP_IP_ARRAY* enumInfo = null;
while (PInvoke.DhcpEnumSubnets("192.168.1.1",
ref resumeHandle,
preferredMaximum,
ref enumInfo,
out uint elementsRead,
out uint elementsTotal) == Constants.ERROR_SUCCESS)
{
try
{
for (uint i = 0; i < elementsRead; i++)
{
DHCP_IP_ARRAY info = enumInfo[i];
for (uint j = 0; j < info.NumElements; j++)
{
uint ipv4 = info.Elements[j];
}
}
}
finally
{
for (uint i = 0; i < elementsRead; i++)
{
PInvoke.DhcpRpcFreeMemory(enumInfo[i].Elements);
}
PInvoke.DhcpRpcFreeMemory(enumInfo);
}
}
} And don't forget to release the memory when you're done with it.
Ya, that's probably why they did this in the metadata. |
Beta Was this translation helpful? Give feedback.
Thanks for reaching out. This is a sub-par experience and I filed microsoft/win32metadata#452 to get this fixed in the metadata. The only real problem is the
EnumInfo
parameter should beout
instead ofref
. So just set it tonull
.In the meantime, this syntax should work. You don't want to use
Marshal.PtrToStructure
probably because you need the original pointer to release the memory, and honestly the syntax doesn't get any easier anyway.