// existingBase is passed for performance optimization // TODO: encapsulate existingBase in a class and extract methods // with it a first argument there private bool TryOpenImpl(KeyIdentity existingBase, KeyDisposition disposition, KeyIdentity identity, KeySecurity samDesired, out IKeyImpl openedImpl) { openedImpl = null; if (disposition != KeyDisposition.DIFF_HIVE) { if (diffHive_.IsMarkedAsDeleted(existingBase, identity)) { return(false); } } IKeyImplOpenFactory factory = null; switch (disposition) { case KeyDisposition.WINDOWS_REG: factory = windowsKeyFactory_; break; case KeyDisposition.BASE_HIVE: factory = baseHive_; break; case KeyDisposition.DIFF_HIVE: factory = diffHive_; break; } if (factory == null) { // In case if specified hive is not used (currently used // only for null baseHive_) return(false); } return(factory.TryOpen(identity, samDesired, out openedImpl)); }
private bool TryOpenOrCreateDiffKey(KeyIdentity existingBase, KeyIdentity identity, KeySecurity samDesired, out IKeyImpl openedImpl) { if (TryOpen(existingBase, KeyDisposition.DIFF_HIVE, identity, samDesired, out openedImpl)) { return(true); } // If some modification operation is requested and offreg key // does not exist, but it is in one of readonly hives - creating it if (samDesired.IsOnlyForRead() || !KeyExistsInROHives(identity)) { return(false); } try { openedImpl = Create(identity, null, (int)Win32Api.RegOption.REG_OPTION_NON_VOLATILE, IntPtr.Zero, IntPtr.Zero); return(true); } catch (FileNotFoundException) { return(false); } }
// Create key and if needed all parent keys private OffregLib.OffregKey CreateKeys(OffregLib.OffregHive hiveImpl, string path, string lpClass, Win32Api.RegOption dwOptions, IntPtr lpSecurityDescriptor, IntPtr lpdwDisposition) { OffregLib.OffregKey result = null; try { OffRegHive.ConvertException(() => result = hiveImpl.Root.OpenSubKey(path)); return(result); } catch (FileNotFoundException) { } // We either take the first subkey of the path, or the last string parentPath, subkey; if (KeyIdentity.PartitionPath(path, out parentPath, out subkey)) { OffregLib.OffregKey parentKey = CreateKeys(hiveImpl, parentPath, lpClass, dwOptions, lpSecurityDescriptor, lpdwDisposition); OffRegHive.ConvertException(() => parentKey.Close()); } // TODO: do something with lpClass, lpSecurityDescriptor, for now they are ignored OffRegHive.ConvertException(() => result = hiveImpl.Root.CreateSubKey( path, (OffregLib.RegOption)dwOptions)); if (lpdwDisposition != IntPtr.Zero) { Marshal.WriteInt32(lpdwDisposition, (int)Win32Api.RegKeyDisposition.REG_CREATED_NEW_KEY); } // TODO: if there is an existing key in windows registry, but we create one // in offreg hive, which disposition do we need to return? return(result); }
internal IKeyImpl Create(KeyIdentity identity, string lpClass, Win32Api.RegOption dwOptions, IntPtr lpSecurityDescriptor, IntPtr lpdwDisposition) { return(new OffRegKey(this, hive_, identity, lpClass, dwOptions, lpSecurityDescriptor, lpdwDisposition)); }
internal IKeyImpl Create(KeyIdentity identity, string lpClass, Win32Api.RegOption dwOptions, IntPtr lpSecurityDescriptor, IntPtr lpdwDisposition) { return(diffHive_.Create(identity, lpClass, dwOptions, lpSecurityDescriptor, lpdwDisposition)); }
private void OpenKey(KeyIdentity existingBase, KeyIdentity identity, KeySecurity samDesired, out IntPtr phkResult) { phkResult = IntPtr.Zero; phkResult = keyStorage_.Add( factory_.OpenKeyPreliminarily(existingBase, identity, samDesired)); }
public bool TryOpen(KeyIdentity identity, KeySecurity samDesired, out IKeyImpl openedImpl) { OffRegKey offregKey; bool result = OffRegKey.TryOpen(this, hive_, identity, out offregKey); openedImpl = offregKey; return(result); }
internal VirtualKey CreatePredefinedKey(IntPtr hKey) { KeyIdentity identity = new KeyIdentity(hKey); return(new VirtualKey(factory_, identity, factory_.Open( KeyDisposition.WINDOWS_REG, identity, new KeySecurity(Win32Api.KeySecurity.KEY_READ)), alterer_)); }
private string CallStrAlterers(KeyIdentity key, string valueName, string value) { foreach (StrAlterer alterer in strAlterers_) { value = alterer(key, valueName, value); } return(value); }
public bool TryOpen(KeyIdentity identity, KeySecurity samDesired, out IKeyImpl openedImpl) { WindowsKey windowsKey; bool result = WindowsKey.TryOpen(identity, samDesired, out windowsKey); openedImpl = windowsKey; return(result); }
internal OffRegKey(OffRegHive hive, OffregLib.OffregHive hiveImpl, KeyIdentity identity, string lpClass, Win32Api.RegOption dwOptions, IntPtr lpSecurityDescriptor, IntPtr lpdwDisposition) { hive_ = hive; identity_ = identity; key_ = CreateKeys(hiveImpl, GetMainOffRegPath(identity), lpClass, dwOptions, lpSecurityDescriptor, lpdwDisposition); }
internal VirtualKey(VirtualKeyFactory opener, KeyIdentity identity, IKeyImpl baseKeyImpl, DataAlterer alterer) { opener_ = opener; identity_ = identity; baseImpl_ = baseKeyImpl; alterer_ = alterer; ReinitializeCache(); }
internal static string GetMainOffRegPath(KeyIdentity identity) { if (!predefinedPaths_.ContainsKey((Int64)identity.BaseKey)) { // Not thrown in usual cases, may be thrown very rarely if identity.BaseKey // points to some specific place (may be) throw new FileNotFoundException(); } return(KeyIdentity.CombinePaths(predefinedPaths_[(Int64)identity.BaseKey][0], identity.GetRegPath())); }
internal IKeyImpl Open(KeyDisposition disposition, KeyIdentity identity, KeySecurity samDesired) { IKeyImpl result; if (!TryOpen(null, disposition, identity, samDesired, out result)) { throw new FileNotFoundException(); } return(result); }
// returns false if the key does not exist in the given disposition, // on other errors throws exception. private bool TryOpen(KeyIdentity existingBase, KeyDisposition disposition, KeyIdentity identity, KeySecurity samDesired, out IKeyImpl openedImpl) { if (!TryOpenImpl(existingBase, disposition, identity, samDesired, out openedImpl)) { return(false); } baseKeyManager_.BaseKeyCopied(identity.BaseKey); openedImpl = new KeyImplDecoratorHookingClose(openedImpl, () => baseKeyManager_.BaseKeyClosed(identity.BaseKey)); return(true); }
private bool TryOpenKey(KeyIdentity existingBase, KeyDisposition disposition, KeyIdentity identity, KeySecurity samDesired, out VirtualKey key) { KeyImplHolder holder; key = null; if (!TryOpenHolder(existingBase, disposition, identity, samDesired, out holder)) { return(false); } key = new VirtualKey(this, identity, holder.ReleaseKeyImpl(), alterer_); return(true); }
internal string GetKeySystemPath(IntPtr hKey) { VirtualKey key = GetKeyOrPickUp(hKey); if (key == null) { if (hKey == IntPtr.Zero) { return("<null>"); } return(KeyIdentity.UknownHKeyStr(hKey)); } return(key.Identity.GetSystemPath()); }
public bool Handle(WindowsKey key) { if (!KeyIdentity.IsPredefined(key.Handle)) { return Win32Exception.CheckIfFoundAndNoError( Win32Api.NtQueryKey(key.Handle, KeyInformationClass_, KeyInformation_, Length_, out ResultLength_)); } // Predefined key handle values are valid only on the advapi32.dll level // on the ntdll.dll level we have to replace them with appropriate ntdll.dll handles IntPtr hNtKey = IntPtr.Zero; string objectName = KeyIdentity.GetSystemBasePath(key.Handle); Win32Api.UNICODE_STRING usObjectName = new Win32Api.UNICODE_STRING(); usObjectName.Length = unchecked((ushort)(sizeof(char) * objectName.Length)); usObjectName.MaximumLength = usObjectName.Length; using (HGlobalPtr pObjectNameBuffer = new HGlobalPtr(Marshal.StringToHGlobalUni(objectName))) { usObjectName.Buffer = pObjectNameBuffer.Ptr; using (HGlobalPtr pObjectName = new HGlobalPtr(Marshal.SizeOf(typeof(Win32Api.UNICODE_STRING)))) { Marshal.StructureToPtr(usObjectName, pObjectName.Ptr, false); Win32Api.OBJECT_ATTRIBUTES oa = new Win32Api.OBJECT_ATTRIBUTES(); oa.Length = unchecked((uint)Marshal.SizeOf(typeof(Win32Api.OBJECT_ATTRIBUTES))); oa.RootDirectory = IntPtr.Zero; oa.ObjectName = pObjectName.Ptr; oa.Attributes = (uint)Win32Api.ObjectAttributes.OBJ_CASE_INSENSITIVE; oa.SecurityDescriptor = IntPtr.Zero; oa.SecurityQualityOfService = IntPtr.Zero; using (HGlobalPtr pOA = new HGlobalPtr(Marshal.SizeOf(typeof(Win32Api.OBJECT_ATTRIBUTES)))) { Marshal.StructureToPtr(oa, pOA.Ptr, false); if (!Win32Exception.CheckIfFoundAndNoError( Win32Api.NtOpenKey(out hNtKey, (uint)Win32Api.KeySecurity.KEY_QUERY_VALUE, pOA.Ptr))) { return false; } try { return Win32Exception.CheckIfFoundAndNoError( Win32Api.NtQueryKey(hNtKey, KeyInformationClass_, KeyInformation_, Length_, out ResultLength_)); } finally { Win32Api.NtClose(hNtKey); } } } } }
// If the keyImpl is added, returns NotOwningKeyImplHolder, // otherwise returns original KeyImplHolder public KeyImplHolder Add(KeyIdentity identity, KeyDisposition disposition, KeyImplHolder keyHolder) { lock (this) { CacheKey cacheKey = new CacheKey { Identity = identity, Disposition = disposition }; if (cachedKeyImpls_.ContainsKey(cacheKey)) { return(keyHolder); } cachedKeyImpls_.Add(cacheKey, keyHolder); return(new NotOwningKeyImplHolder(keyHolder.GetKeyImpl())); } }
internal void OpenKey(IntPtr hKey, string lpSubKey, int ulOptions, Win32Api.KeySecurity samDesired, out IntPtr phkResult) { // ulOptions are ignored as this is a reserved parameter phkResult = IntPtr.Zero; KeySecurity keySecurity; Win32Api.RegWow64Options wowOptions; KeySecurity.ExtractWow64Options(samDesired, out keySecurity, out wowOptions); KeyIdentity baseIdentity = GetKey(hKey).Identity; OpenKey(baseIdentity, new KeyIdentity(baseIdentity, wowOptions, lpSubKey), keySecurity, out phkResult); }
internal void BaseKeyCopied(IntPtr baseKey) { if (KeyIdentity.IsPredefined(baseKey)) { return; } Int64 key = baseKey.ToInt64(); lock (this) { if (!baseKeyRefCount_.ContainsKey(key)) { baseKeyRefCount_[key] = 0; } baseKeyRefCount_[key]++; } }
internal void BaseKeyClosed(IntPtr baseKey) { if (KeyIdentity.IsPredefined(baseKey)) { return; } Int64 key = baseKey.ToInt64(); lock (this) { baseKeyRefCount_[key]--; if (baseKeyRefCount_[key] == 0) { baseKeyRefCount_.Remove(key); Win32Exception.CheckResult(Win32Api.RegCloseKey(baseKey)); } } }
private static bool CheckSystemKeyAccess(KeyDisposition disposition, KeyIdentity identity, KeySecurity samDesired) { // This way we redirect system registry locations into windows registry // and make it fail for write operations if (disposition != KeyDisposition.WINDOWS_REG && identity.IsSystemKey()) { if (samDesired.IsOnlyForRead()) { // So that it retries to read from system registry return(false); } // So that user gets appropriate error code throw new AccessDeniedException(); } return(true); }
internal static List <string> GetOffRegPaths(KeyIdentity identity) { if (!predefinedPaths_.ContainsKey((Int64)identity.BaseKey)) { return(new List <string>()); } List <string> result = new List <string>(); List <string> basePaths = predefinedPaths_[(Int64)identity.BaseKey]; string regPath = identity.GetRegPath(); foreach (string basePath in basePaths) { // offreg hive does not distinguish between 32bit and 64 bit branches for now // so we use path w/o Wow6432Node result.Add(KeyIdentity.CombinePaths(basePath, regPath)); } return(result); }
internal void MarkKeyAsDeleted(KeyIdentity identity) { try { string[] subkeys = identity.SplitPath(); int existingLevels, nonRemovableLevels; CalcNonRemovableLevels(null, identity, out existingLevels, out nonRemovableLevels); if (subkeys.Length <= nonRemovableLevels) { // We can't mark root keys as deleted return; } using (HGlobalPtr pData = new HGlobalPtr(Marshal.SizeOf(typeof(int)))) { Marshal.WriteInt32(pData.Ptr, 1); // Conciously suppressing errors OffRegKey key = null; try { key = new OffRegKey(this, hive_, KeyIdentity.Build(identity.BaseKey, subkeys, subkeys.Length - 1), null, Win32Api.RegOption.REG_OPTION_NON_VOLATILE, IntPtr.Zero, IntPtr.Zero); key.SetValue(DELETED_PREFIX + subkeys[subkeys.Length - 1], Win32Api.RegValueType.REG_DWORD, pData.Ptr, Marshal.SizeOf(typeof(int))); } catch (Win32Exception) { // Suppressing errors because there might be access issues // or may be other stuff if (key != null) { key.Close(); } } } } catch (FileNotFoundException) { // We don't know anything about the key, so we can't mark it as deleted return; } }
private bool TryGetSubKey(KeyDisposition disposition, string lpSubKey, KeySecurity samDesired, Win32Api.RegWow64Options wowOptions, out KeyImplHolder subKeyHolder) { KeyIdentity subKeyIdentity = new KeyIdentity(identity_, wowOptions, lpSubKey); IKeyImpl keyImpl = cachedKeyImpls_.TryGet(subKeyIdentity, disposition, samDesired); if (keyImpl != null) { subKeyHolder = new NotOwningKeyImplHolder(keyImpl); return(true); } KeyImplHolder newOne; if (!opener_.TryOpenHolder(identity_, disposition, subKeyIdentity, samDesired, out newOne)) { subKeyHolder = null; return(false); } subKeyHolder = cachedKeyImpls_.Add(subKeyIdentity, disposition, newOne); return(true); }
// Returns keyImpl owned by cache, thus KeyHolder is not used public IKeyImpl TryGet(KeyIdentity identity, KeyDisposition disposition, KeySecurity samDesired) { lock (this) { CacheKey cacheKey = new CacheKey { Identity = identity, Disposition = disposition }; if (!cachedKeyImpls_.ContainsKey(cacheKey)) { return(null); } KeyImplHolder cached = cachedKeyImpls_[cacheKey]; if (!samDesired.IsSubSetOf(cached.GetKeyImpl().GetAccessMode())) { return(null); } return(cached.GetKeyImpl()); } }
private static bool GetNativeHKeyName(IntPtr hKey, out KeyIdentity identity) { identity = null; uint cbData; int result = Win32Api.NtQueryKey(hKey, Win32Api.KeyInformationClass.KeyNameInformation, IntPtr.Zero, 0, out cbData); if (result != (int)Win32Api.Status.STATUS_BUFFER_TOO_SMALL) { DebugLogger.WriteLine("Error querying key name {0}", result); return(false); } using (HGlobalPtr pData = new HGlobalPtr(cbData)) { result = Win32Api.NtQueryKey(hKey, Win32Api.KeyInformationClass.KeyNameInformation, pData.Ptr, cbData, out cbData); if (result != 0) { DebugLogger.WriteLine("Error querying key name {0}", result); return(false); } cbData = (uint)Marshal.ReadInt32(pData.Ptr); string name = Marshal.PtrToStringUni( (IntPtr)(pData.Ptr.ToInt64() + Marshal.SizeOf(typeof(uint))), (int)cbData / sizeof(char)); foreach (KeyValuePair <string, IntPtr> m in HKeySysNameMappings) { if (name.StartsWith(m.Key, StringComparison.CurrentCultureIgnoreCase)) { identity = new KeyIdentity(m.Value, RemovePrefix(name, m.Key.Length)); return(true); } } DebugLogger.WriteLine("Can't interpret key name {0}", name); } return(false); }
private VirtualKey GetKeyOrPickUp(IntPtr hKey) { if (hKey == IntPtr.Zero) { return(null); } VirtualKey key = keyStorage_.Get(hKey); if (key != null) { return(key); } // The key might be open by a native Reg* function before // OpenSandbox was embedded try { KeyIdentity identity = new KeyIdentity(hKey); key = new VirtualKey(factory_, identity, factory_.Open( KeyDisposition.WINDOWS_REG, identity, new KeySecurity(Win32Api.KeySecurity.KEY_READ)), alterer_); // ATTENTION: resource leak is happening here and may lead to AV: // returned VirtualKey has a cache of open keys which never gets closed // and the base keyImpl does not get closed too. // Closing is called in finalizers after registry is shutdown, which is UB. // We put the key to the storage for the case if it will be accessed // further and to avoid resource leaks keyStorage_.Add(hKey, key); DebugLogger.WriteLine("Picked up key 0x{0} {1}", hKey.ToString("X"), identity); return(key); } catch (InvalidHandleException) { return(null); } catch (FileNotFoundException) { return(null); } }
internal bool IsMarkedAsDeleted(KeyIdentity existingBase, KeyIdentity identity) { if (identity.IsSystemKey()) { return(false); } try { return(DoesntExistOrMarkedAsDeleted(existingBase, identity, IMAD_pData_.Ptr, IMAD_pcbData_.Ptr) == DoesntExistOrMarkedAsDeletedState.MarkedAsDeleted); } catch (FileNotFoundException) { // We don't know anything about the key, so it was not marked as deleted return(false); } catch (Win32Exception ex) { DebugLogger.WriteLine("IsDeleted exception " + ex.ToString()); throw; } }