internal static KeyInfo QueryInfo(this IKey key) { using (HGlobalPtr lpcClass = new HGlobalPtr(Marshal.SizeOf(typeof(int)))) { Marshal.WriteInt32(lpcClass.Ptr, 0); try { key.QueryInfo(IntPtr.Zero, lpcClass.Ptr, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); } catch (Win32Exception ex) { if (ex.ErrorCode != (int)Win32Api.Error.ERROR_MORE_DATA) { throw; } } int cClass = Marshal.ReadInt32(lpcClass.Ptr) + 1; Marshal.WriteInt32(lpcClass.Ptr, cClass); using (HGlobalPtr lpClass = new HGlobalPtr(cClass * sizeof(char)), lpReserved = new HGlobalPtr(IntPtr.Zero), lpcSubKeys = new HGlobalPtr(sizeof(int)), lpcMaxSubKeyLen = new HGlobalPtr(sizeof(int)), lpcMaxClassLen = new HGlobalPtr(sizeof(int)), lpcValues = new HGlobalPtr(sizeof(int)), lpcMaxValueNameLen = new HGlobalPtr(sizeof(int)), lpcMaxValueLen = new HGlobalPtr(sizeof(int)), lpcSecurityDescriptor = new HGlobalPtr(sizeof(int)), lpftLastWriteTime = new HGlobalPtr(2 * sizeof(int))) { key.QueryInfo( lpClass.Ptr, lpcClass.Ptr, lpReserved.Ptr, lpcSubKeys.Ptr, lpcMaxSubKeyLen.Ptr, lpcMaxClassLen.Ptr, lpcValues.Ptr, lpcMaxValueNameLen.Ptr, lpcMaxValueLen.Ptr, lpcSecurityDescriptor.Ptr, lpftLastWriteTime.Ptr); int classLength = Marshal.ReadInt32(lpcClass.Ptr); Win32Api.FILETIME lastWriteTime = (Win32Api.FILETIME)Marshal.PtrToStructure(lpftLastWriteTime.Ptr, typeof(Win32Api.FILETIME)); KeyInfo info; info.Class = DataTransformer.PtrToString(lpClass.Ptr, classLength); info.SubKeysNumber = unchecked ((uint)Marshal.ReadInt32(lpcSubKeys.Ptr)); info.MaxSubKeyLength = unchecked ((uint)Marshal.ReadInt32(lpcMaxSubKeyLen.Ptr)); info.MaxClassLength = unchecked ((uint)Marshal.ReadInt32(lpcMaxClassLen.Ptr)); info.ValuesNumber = unchecked ((uint)Marshal.ReadInt32(lpcValues.Ptr)); info.MaxValueNameLength = unchecked ((uint)Marshal.ReadInt32(lpcMaxValueNameLen.Ptr)); info.MaxValueLength = unchecked ((uint)Marshal.ReadInt32(lpcMaxValueLen.Ptr)); info.SecurityDescriptorLength = unchecked ((uint)Marshal.ReadInt32(lpcSecurityDescriptor.Ptr)); info.LastWriteTime = lastWriteTime; return(info); } } }
public void EnumValue( uint dwIndex, IntPtr lpValueName, /*ref UInt32*/ IntPtr lpcchValueName, IntPtr lpReserved, /*ref Win32Api.RegValueType*/ IntPtr lpType, IntPtr lpData, /*ref UInt32*/ IntPtr lpcbData) { if (!DoUni2AnsiConversion) { OffRegHive.ConvertException(() => key_.EnumValueUnmanaged(dwIndex, lpValueName, lpcchValueName, lpType, lpData, lpcbData)); return; } int cchValueName = 0; if (lpcchValueName != IntPtr.Zero) { cchValueName = Marshal.ReadInt32(lpcchValueName); } using (Uni2AnsiConverter nameConverter = new Uni2AnsiConverter(new Data(lpValueName, lpcchValueName, Data.CountIn.Chars))) { try { Data dst = new Data(lpData, lpcbData, Data.CountIn.Bytes); // Sandboxie-generated reghives might contain REG_SZ values stored in ansi format // we need to detect them and avoid conversion for them if (!DataTransformer.TryAlterData(lpType, dst, (newpdwType, newDst) => { // EnumValue takes buffer size WITH null character // but returns WITHOUT, so we need to reset input // param to allow multiple calls to the operation if (lpcchValueName != IntPtr.Zero) { Marshal.WriteInt32(lpcchValueName, cchValueName); } return(OffRegHive.CatchException(() => key_.EnumValueUnmanaged( dwIndex, nameConverter.UnicodeStr, lpcchValueName, newpdwType, newDst.Ptr, newDst.PCount))); }, (result, type) => (result == Win32Api.Error.ERROR_SUCCESS || result == Win32Api.Error.ERROR_MORE_DATA) && DataTransformer.IsStringType(type), (type, pSrcData, cbSrcData) => dst.FillWithString(new BytesString(pSrcData, cbSrcData), StringFormat.Ansi, Data.NullCharHandling.NotAddingIfNotPresent))) { throw new FileNotFoundException(); } nameConverter.Convert(); } catch (Win32Exception ex) { if (ex.ErrorCode == (int)Win32Api.Error.ERROR_MORE_DATA) { // Assumming that in case of ERROR_MORE_DATA lpcchValueName is // filled with correct value nameConverter.Convert(); } throw; } } }