// private MorphicResult <GetValueAndTypeAsObjectResult, RegistryValueError> GetValueAndTypeAsObject(string?name) { var handleAsUIntPtr = (UIntPtr)(_handle.DangerousGetHandle().ToInt64()); // pass 1: set dataSize to zero (so that RegQueryValueEx returns the size of the value uint dataSize = 0; ExtendedPInvoke.RegistryValueType valueType; var queryValueErrorCode = ExtendedPInvoke.RegQueryValueEx(handleAsUIntPtr, name, IntPtr.Zero, out valueType, IntPtr.Zero, ref dataSize); switch (queryValueErrorCode) { case PInvoke.Win32ErrorCode.ERROR_SUCCESS: break; case PInvoke.Win32ErrorCode.ERROR_FILE_NOT_FOUND: return(MorphicResult.ErrorResult(RegistryValueError.ValueDoesNotExist)); default: // NOTE: in the future, we may want to consider returning a specific result (i.e. "could not open for write access" etc.) return(MorphicResult.ErrorResult(RegistryValueError.Win32Error((int)queryValueErrorCode))); } // pass 2: capture the actual data var getValueResult = RegistryKey.GetValueForHandleAsUInt32(handleAsUIntPtr, name, dataSize); if (getValueResult.IsError) { return(MorphicResult.ErrorResult(getValueResult.Error !)); } var data = getValueResult.Value; return(MorphicResult.OkResult(new GetValueAndTypeAsObjectResult(data, valueType))); }
private static MorphicResult <MorphicUnit, MorphicUnit> SetValueForHandle <T>(UIntPtr handle, string?name, T value) { IntPtr ptrToData; uint dataSize; ExtendedPInvoke.RegistryValueType valueType; if (typeof(T) == typeof(uint)) { var dataSizeAsInt = Marshal.SizeOf <uint>(); ptrToData = Marshal.AllocHGlobal(dataSizeAsInt); var valueAsUInt = (uint)(object)value !; Marshal.StructureToPtr <uint>(valueAsUInt, ptrToData, false); // dataSize = (uint)dataSizeAsInt; valueType = ExtendedPInvoke.RegistryValueType.REG_DWORD; } else if (typeof(T) == typeof(System.String)) { var valueAsString = (value as System.String) !; ptrToData = Marshal.StringToHGlobalUni(valueAsString); // dataSize = (uint)((valueAsString.Length + 1 /* +1 for the null terminator */) * 2); valueType = ExtendedPInvoke.RegistryValueType.REG_SZ; } else { // unknown type return(MorphicResult.ErrorResult()); } // try { var setValueErrorCode = ExtendedPInvoke.RegSetValueEx(handle, name, 0, valueType, ptrToData, dataSize); switch (setValueErrorCode) { case PInvoke.Win32ErrorCode.ERROR_SUCCESS: break; default: // NOTE: in the future, we may want to consider returning a specific result (i.e. "could not open for write access" etc.) return(MorphicResult.ErrorResult()); } // setting the value was a success return(MorphicResult.OkResult()); } finally { Marshal.FreeHGlobal(ptrToData); } }
private static MorphicResult <uint, RegistryValueError> GetValueForHandleAsUInt32(UIntPtr handle, string?name, uint dataSize) { var ptrToData = Marshal.AllocHGlobal((int)dataSize); try { var mutableDataSize = dataSize; ExtendedPInvoke.RegistryValueType valueType; var queryValueErrorCode = ExtendedPInvoke.RegQueryValueEx(handle, name, IntPtr.Zero, out valueType, ptrToData, ref mutableDataSize); switch (queryValueErrorCode) { case PInvoke.Win32ErrorCode.ERROR_SUCCESS: break; default: // NOTE: in the future, we may want to consider returning a specific result (i.e. "could not open for write access" etc.) return(MorphicResult.ErrorResult(RegistryValueError.Win32Error((int)queryValueErrorCode))); } // validate value type and data size if (valueType != ExtendedPInvoke.RegistryValueType.REG_DWORD) { return(MorphicResult.ErrorResult(RegistryValueError.TypeMismatch)); } // if (mutableDataSize != dataSize) { return(MorphicResult.ErrorResult(RegistryValueError.TypeMismatch)); } // capture and return result var data = Marshal.PtrToStructure <uint>(ptrToData); return(MorphicResult.OkResult(data)); } finally { Marshal.FreeHGlobal(ptrToData); } }