public void QueryInfo( /*out StringBuilder*/ IntPtr lpClass, /*ref */ IntPtr lpcClass, IntPtr lpReserved, /*out */ IntPtr lpcSubKeys, /*out */ IntPtr lpcbMaxSubKeyLen, /*out */ IntPtr lpcbMaxClassLen, /*out */ IntPtr lpcValues, /*out */ IntPtr lpcbMaxValueNameLen, /*out */ IntPtr lpcbMaxValueLen, /*out */ IntPtr lpcbSecurityDescriptor, IntPtr lpftLastWriteTime) { // TODO: Actually a much more complex implementation of QeryInfoKeyA, // traversing through all values and handling strings in a special way // is required for exact MaxValueLen value calculation taking // into account unicode->ansi conversion. // For now we return a bigger value, still enough to allocate buffers // (length of unicode values is always larger than length of ansi ones). using (Uni2AnsiConverter classConverter = new Uni2AnsiConverter(new Data(lpClass, lpcClass, Data.CountIn.Chars), DoUni2AnsiConversion)) { OffRegHive.ConvertException(() => key_.QueryInfoUnmanaged( classConverter.UnicodeStr, lpcClass, lpcSubKeys, lpcbMaxSubKeyLen, lpcbMaxClassLen, lpcValues, lpcbMaxValueNameLen, lpcbMaxValueLen, lpcbSecurityDescriptor, lpftLastWriteTime)); classConverter.Convert(); } }
public void EnumKey( uint dwIndex, IntPtr lpName, /*ref UInt32*/ IntPtr lpcchName, IntPtr lpReserved, IntPtr lpClass, /*ref UInt32*/ IntPtr lpcchClass, /*ref Win32Api.FILETIME*/ IntPtr lpftLastWriteTime) { using (Uni2AnsiConverter nameConverter = new Uni2AnsiConverter(new Data(lpName, lpcchName, Data.CountIn.Chars), DoUni2AnsiConversion), classConverter = new Uni2AnsiConverter(new Data(lpClass, lpcchClass, Data.CountIn.Chars), DoUni2AnsiConversion)) { OffRegHive.ConvertException(() => key_.EnumKeyUnmanaged(dwIndex, nameConverter.UnicodeStr, lpcchName, classConverter.UnicodeStr, lpcchClass, lpftLastWriteTime)); nameConverter.Convert(); classConverter.Convert(); } }
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; } } }