How to convert IntPtr to UIntPtr?

I tried to do it like this:

UIntPtr x = (UIntPtr)intPtr; 

... but the compiler is not very happy with it and returned a compilation error.

I need to do the conversion because the P / Invoke signature for RegOpenKeyEx requires UIntPtr:

  [DllImport("advapi32.dll", CharSet = CharSet.Auto)] public static extern int RegOpenKeyEx( UIntPtr hKey, string subKey, int ulOptions, int samDesired, out UIntPtr hkResult); 

To get the handle, I use SafeHandle.DangerousHandle (), which returns IntPtr:

  /// <summary> /// Get a pointer to a registry key. /// </summary> /// <param name="registryKey">Registry key to obtain the pointer of.</param> /// <returns>Pointer to the given registry key.</returns> IntPtr _getRegistryKeyHandle(RegistryKey registryKey) { //Get the type of the RegistryKey Type registryKeyType = typeof(RegistryKey); //Get the FieldInfo of the 'hkey' member of RegistryKey System.Reflection.FieldInfo fieldInfo = registryKeyType.GetField("hkey", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); //Get the handle held by hkey SafeHandle handle = (SafeHandle)fieldInfo.GetValue(registryKey); //Get the unsafe handle IntPtr dangerousHandle = handle.DangerousGetHandle(); return dangerousHandle; } 
+4
source share
4 answers

After looking at msdn, I noticed that both the UIntPtr and IntPtr parameters have a void* pointer conversion.

 IntPtr a = ....; UIntPtr b = (UIntPtr)a.ToPointer(); 

At this point, you need insecure code. The only way to avoid this is to use the unchecked keyword and convert using types without pointers (also used here ).

The reason for the lack of conversion between the two pointers may be that UIntPtr as IntPtr does not have a fixed size, because they are platform specific ( see ).

+2
source

I found BitConverter most reliable since it also works when using VB.NET, which does not allow overflows from unsigned signed values:

 new UIntPtr(BitConverter.ToUInt64(BitConverter.GetBytes(handleIntPtr.ToInt64), 0)) 
0
source

Why don't you just unchecked((IntPtr)(int)uintPtr) on 32-bit pointers or unchecked((IntPtr)(long)uintPtr) on 64-bit pointers? Works well (and faster than other solutions).

0
source

IntPtr can contain as many values ​​as UIntPtr . Both have the same number of bits.

Overflow is the concept of arithmetic. Arithemtic is never performed on handles. This concept does not apply here.

In general, BCL IntPtr is the standard type for descriptors. Use IntPtr everywhere.

The site says:

Changed IntPtr to UIntPtr: when called from IntPtr for descriptors, you will go overflow. UIntPtr is the right choice if you want this to work correctly on 32- and 64-bit platforms.

Probably his code converted the types in an overflowing form. It's just superstitious faith in him. He changed a few things. One of the soles made him work. Now he thinks it was an IntPtr change, but that was something else.

In addition, this choice has nothing to beat in the process bit.

0
source

Source: https://habr.com/ru/post/1384855/


All Articles