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); } }
private void OpenKey(KeyIdentity existingBase, KeyIdentity identity, KeySecurity samDesired, out IntPtr phkResult) { phkResult = IntPtr.Zero; phkResult = keyStorage_.Add( factory_.OpenKeyPreliminarily(existingBase, identity, samDesired)); }
// 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)); }
public static void ExtractWow64Options(Win32Api.KeySecurity value, out KeySecurity keySecurity, out Win32Api.RegWow64Options wow64Options) { wow64Options = (Win32Api.RegWow64Options)((int)value & (int)(Win32Api.RegWow64Options.KEY_WOW64_32KEY | Win32Api.RegWow64Options.KEY_WOW64_64KEY)); keySecurity = new KeySecurity(value & (Win32Api.KeySecurity) ~wow64Options); }
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); }
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 void ApplyNotOnlyReadOperation(string subKeyName, KeySecurity samDesired, KeyImplOperation operation, Win32Api.RegWow64Options wowOptions = Win32Api.RegWow64Options.None) { if (!TryApplyOperation(KeyDisposition.DIFF_HIVE, subKeyName, samDesired, operation, wowOptions)) { throw new FileNotFoundException(); } }
public bool IsSubSetOf(KeySecurity another) { // During refactoring in the next line // (value_ & ~another.value_) != 0 was replaced with (value_ & ~another.value_) == 0 // this may be wrong (althoug looks like it was a bug and now it should be fixed) // so please keep an eye on this change return((value_ & ~another.value_) == 0 || value_ == Win32Api.KeySecurity.MAXIMUM_ALLOWED || another.value_ == Win32Api.KeySecurity.MAXIMUM_ALLOWED); }
internal IKeyImpl Open(KeyDisposition disposition, KeyIdentity identity, KeySecurity samDesired) { IKeyImpl result; if (!TryOpen(null, disposition, identity, samDesired, out result)) { throw new FileNotFoundException(); } return(result); }
private static void CheckReadOnlyHivesAccess(KeyDisposition disposition, KeySecurity samDesired) { if (disposition != KeyDisposition.DIFF_HIVE) { Debug.Assert(samDesired.IsOnlyForRead()); if (!samDesired.IsOnlyForRead()) { throw new AccessDeniedException(); } } }
// 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); }
internal void OpenUserClassesRoot( IntPtr hToken, UInt32 dwOptions, KeySecurity samDesired, out IntPtr phkResult) { IntPtr baseKey; Win32Exception.CheckResult( Win32Api.RegOpenUserClassesRoot(hToken, dwOptions, samDesired.Value, out baseKey)); OpenWindowsBaseKey(baseKey, samDesired, out phkResult); }
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 void OpenCurrentUser( KeySecurity samDesired, out IntPtr phkResult) { // CurrentUser identity depends on the user to which opening // thread is impersonated right now, so we need to do the syscall // exactly at the moment and then use the returned value IntPtr baseKey; Win32Exception.CheckResult( Win32Api.RegOpenCurrentUser(samDesired.Value, out baseKey)); OpenWindowsBaseKey(baseKey, samDesired, out phkResult); }
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); }
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 void ApplyReadOperation(string subKeyName, KeySecurity samDesired, KeyImplOperation operation) { Debug.Assert(samDesired.IsOnlyForRead()); if (!samDesired.IsOnlyForRead()) { throw new AccessDeniedException(); } foreach (KeyDisposition disposition in HIVES_ORDER) { if (TryApplyOperation(disposition, subKeyName, samDesired, operation)) { return; } } throw new FileNotFoundException(); }
// 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 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); }
internal void CreateKey(IntPtr hKey, string lpSubKey, int Reserved, string lpClass, Win32Api.RegOption dwOptions, Win32Api.KeySecurity samDesired, IntPtr lpSecurityAttributes, out IntPtr phkResult, IntPtr lpdwDisposition) { phkResult = IntPtr.Zero; // Reserved is ignored as this is a reserved parameter try { OpenKey(hKey, lpSubKey, 0, samDesired, out phkResult); if (lpdwDisposition != IntPtr.Zero) { Marshal.WriteInt32(lpdwDisposition, (int)Win32Api.RegKeyDisposition.REG_OPENED_EXISTING_KEY); } return; } catch (FileNotFoundException) {} KeySecurity keySecurity; Win32Api.RegWow64Options wowOptions; KeySecurity.ExtractWow64Options(samDesired, out keySecurity, out wowOptions); VirtualKey key = factory_.CreateKey( new KeyIdentity(GetKey(hKey).Identity, wowOptions, lpSubKey), lpClass, dwOptions, lpSecurityAttributes); if (lpdwDisposition != IntPtr.Zero) { Marshal.WriteInt32(lpdwDisposition, (int)Win32Api.RegKeyDisposition.REG_CREATED_NEW_KEY); } phkResult = keyStorage_.Add(key); }
private void OpenWindowsBaseKey(IntPtr windowsBaseKey, KeySecurity samDesired, out IntPtr phkResult) { // There are two options: // 1. Opening for reading -> we create and return windows key, which is // closed by user call to RegCloseKey // 2. Opening for writing -> we call RegOpenCurrentUser so that // if a subkey is opened for reading, it is under the right branch // and we open OffReg key and return it. try { OpenKey(null, new KeyIdentity(windowsBaseKey), samDesired, out phkResult); } catch (Exception) { // If something went wrong, we keep responsibility for closing the key Win32Api.RegCloseKey(windowsBaseKey); throw; } }
public static bool TryOpen(KeyIdentity identity, KeySecurity samDesired, out WindowsKey openedImpl) { if (identity.GetRegPath() == null) { // This works fine because baseKey is always one of the predefined // registry keys, so its handle does not need to be duplicated // or closed openedImpl = new WindowsKey(identity.BaseKey, samDesired); return(true); } IntPtr handle; int result = Win32Api.RegOpenKeyEx(identity.BaseKey, identity.GetRegPath(), 0, samDesired.Value | (Win32Api.KeySecurity)identity.GetWow64Mode(), out handle); openedImpl = null; if (!Win32Exception.CheckIfFoundAndNoError(result)) { return(false); } openedImpl = new WindowsKey(handle, samDesired); return(true); }
// returns false in case of FileNotFound error, otherwise throws exception internal bool TryApplyOperation(KeyDisposition disposition, string subKeyName, KeySecurity samDesired, KeyImplOperation operation, Win32Api.RegWow64Options wowOptions = Win32Api.RegWow64Options.None) { // None is passed from Get/Set/Enum operations which does not allow user to pass wow options // in such case we take it from the current identity if (wowOptions == Win32Api.RegWow64Options.None) { wowOptions = identity_.GetWow64Mode(); } KeyImplHolder subKey; if (!TryGetSubKey(disposition, subKeyName, samDesired, wowOptions, out subKey)) { return(false); } using (subKey) { // TODO: almost always the operation needs subKey name, at least for logging // so it is constructed second time there. // Better to pass it from here. try { if (!operation(subKey.GetKeyImpl())) { return(false); } } catch (FileNotFoundException) { // TODO: make all operations return false in case of FileNotFoundException // so that this catch can be removed. return(false); } } return(true); }
/* * public KeyImplHolder OpenHolder(KeyDisposition disposition, * KeyIdentity identity, KeySecurity samDesired) * { * KeyImplHolder result; * if (!TryOpenHolder(disposition, identity, samDesired, out result)) * throw new FileNotFoundException(); * return result; * } */ public bool TryOpenHolder(KeyIdentity existingBase, KeyDisposition disposition, KeyIdentity identity, KeySecurity samDesired, out KeyImplHolder openedHolder) { openedHolder = null; // ATTENTION: it is not clear if this function works fine if // lpSubKey == null is given for a predefined key, may be it will fail // trying to close the predefined key or something. Check later. // This way we redirect system registry locations into windows registry // and make it fail for write operations if (!CheckSystemKeyAccess(disposition, identity, samDesired)) { return(false); } CheckReadOnlyHivesAccess(disposition, samDesired); IKeyImpl registryKey; if (disposition != KeyDisposition.DIFF_HIVE) { if (!TryOpen(existingBase, disposition, identity, samDesired, out registryKey)) { return(false); } } else { if (!TryOpenOrCreateDiffKey(existingBase, identity, samDesired, out registryKey)) { return(false); } } openedHolder = new KeyImplHolder(registryKey); return(true); }
private WindowsKey(IntPtr handle, KeySecurity samDesired) { handle_ = handle; accessMode_ = samDesired; }
// Opens virtual key not for regular operation, but just // when RegOpen*/RegCreate* is called, so access checking is not so strict // as for operation // TODO: don't check security access mode on open, // make just a reg function call check it internal VirtualKey OpenKeyPreliminarily(KeyIdentity existingBase, KeyIdentity identity, KeySecurity samDesired) { foreach (KeyDisposition disposition in VirtualKey.HIVES_ORDER) { try { VirtualKey key; if (TryOpenKey(existingBase, disposition, identity, samDesired, out key)) { return(key); } // Key not found if (!samDesired.IsOnlyForRead()) { // Key not present in reghive and write access requested // we can't give it in hives other than DIFF_HIVE throw new FileNotFoundException(); } } catch (AccessDeniedException) { if (!identity.IsSystemKey() || disposition == KeyDisposition.WINDOWS_REG) { // Access denied in reghive (may happen if key is system key) // but if not a system key throw; } } if (identity.IsSystemKey() && !samDesired.IsOnlyForRead()) { // Relaxing access (some apps request write access and do not use it // we want to make them work samDesired.RelaxToReadAccess(); } } throw new FileNotFoundException(); }