internal static UnsafeNativeMethods.DomainControllerInfo GetDcName(string computerName, string domainName, string siteName, int flags) { IntPtr domainControllerInfoPtr = IntPtr.Zero; try { int err = UnsafeNativeMethods.DsGetDcName(computerName, domainName, IntPtr.Zero, siteName, flags, out domainControllerInfoPtr); if (err != 0) { GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetDcName: DsGetDcName failed, err=" + err); throw new PrincipalOperationException( String.Format( CultureInfo.CurrentCulture, StringResources.UnableToRetrieveDomainInfo, err)); } UnsafeNativeMethods.DomainControllerInfo domainControllerInfo = (UnsafeNativeMethods.DomainControllerInfo)Marshal.PtrToStructure(domainControllerInfoPtr, typeof(UnsafeNativeMethods.DomainControllerInfo)); return(domainControllerInfo); } finally { if (domainControllerInfoPtr != IntPtr.Zero) { UnsafeNativeMethods.NetApiBufferFree(domainControllerInfoPtr); } } }
internal static UnsafeNativeMethods.DomainControllerInfo GetDcName(string computerName, string domainName, string siteName, int flags) { UnsafeNativeMethods.DomainControllerInfo domainControllerInfo; IntPtr zero = IntPtr.Zero; try { int num = UnsafeNativeMethods.DsGetDcName(computerName, domainName, IntPtr.Zero, siteName, flags, out zero); if (num == 0) { UnsafeNativeMethods.DomainControllerInfo structure = (UnsafeNativeMethods.DomainControllerInfo)Marshal.PtrToStructure(zero, typeof(UnsafeNativeMethods.DomainControllerInfo)); domainControllerInfo = structure; } else { object[] objArray = new object[1]; objArray[0] = num; throw new PrincipalOperationException(string.Format(CultureInfo.CurrentCulture, StringResources.UnableToRetrieveDomainInfo, objArray)); } } finally { if (zero != IntPtr.Zero) { UnsafeNativeMethods.NetApiBufferFree(zero); } } return(domainControllerInfo); }
public PrincipalContext GetContext(string name, NetCred credentials, ContextOptions contextOptions) { string contextName = name; string userName = null; bool explicitCreds = false; if (credentials != null && credentials.UserName != null) { if (credentials.Domain != null) { userName = credentials.Domain + "\\" + credentials.UserName; } else { userName = credentials.UserName; } explicitCreds = true; } else { userName = Utils.GetNT4UserName(); } GlobalDebug.WriteLineIf( GlobalDebug.Info, "SDSCache", "GetContext: looking for context for server {0}, user {1}, explicitCreds={2}, options={3}", name, userName, explicitCreds.ToString(), contextOptions.ToString()); if (!_isSAM) { // Determine the domain DNS name // DS_RETURN_DNS_NAME | DS_DIRECTORY_SERVICE_REQUIRED | DS_BACKGROUND_ONLY int flags = unchecked ((int)(0x40000000 | 0x00000010 | 0x00000100)); UnsafeNativeMethods.DomainControllerInfo info = Utils.GetDcName(null, contextName, null, flags); contextName = info.DomainName; } GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: final contextName is " + contextName); ManualResetEvent contextReadyEvent = null; while (true) { Hashtable credTable = null; PrincipalContext ctx = null; // Wait for the PrincipalContext to be ready if (contextReadyEvent != null) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: waiting"); contextReadyEvent.WaitOne(); } contextReadyEvent = null; lock (_tableLock) { CredHolder credHolder = (CredHolder)_table[contextName]; if (credHolder != null) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: found a credHolder for " + contextName); credTable = (explicitCreds ? credHolder.explicitCreds : credHolder.defaultCreds); Debug.Assert(credTable != null); object o = credTable[userName]; if (o is Placeholder) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: credHolder for " + contextName + " has a Placeholder"); // A PrincipalContext is currently being constructed by another thread. // Wait for it. contextReadyEvent = ((Placeholder)o).contextReadyEvent; continue; } WeakReference refToContext = o as WeakReference; if (refToContext != null) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: refToContext is non-null"); ctx = (PrincipalContext)refToContext.Target; // null if GC'ed // If the PrincipalContext hasn't been GCed or disposed, use it. // Otherwise, we'll need to create a new one if (ctx != null && ctx.Disposed == false) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: using found refToContext"); return(ctx); } else { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: refToContext is GCed/disposed, removing"); credTable.Remove(userName); } } } // Either credHolder/credTable are null (no contexts exist for the contextName), or credHolder/credTable // are non-null (contexts exist, but none for the userName). Either way, we need to create a PrincipalContext. if (credHolder == null) { GlobalDebug.WriteLineIf( GlobalDebug.Info, "SDSCache", "GetContext: null credHolder for " + contextName + ", explicitCreds=" + explicitCreds.ToString()); // No contexts exist for the contextName. Create a CredHolder for the contextName so we have a place // to store the PrincipalContext we'll be creating. credHolder = new CredHolder(); _table[contextName] = credHolder; credTable = (explicitCreds ? credHolder.explicitCreds : credHolder.defaultCreds); } // Put a placeholder on the contextName/userName slot, so that other threads that come along after // we release the tableLock know we're in the process of creating the needed PrincipalContext and will wait for us credTable[userName] = new Placeholder(); } // Now we just need to create a PrincipalContext for the contextName and credentials GlobalDebug.WriteLineIf( GlobalDebug.Info, "SDSCache", "GetContext: creating context, contextName=" + contextName + ", options=" + contextOptions.ToString()); ctx = new PrincipalContext( (_isSAM ? ContextType.Machine : ContextType.Domain), contextName, null, contextOptions, credentials?.UserName, credentials?.Password ); lock (_tableLock) { Placeholder placeHolder = (Placeholder)credTable[userName]; // Replace the placeholder with the newly-created PrincipalContext credTable[userName] = new WeakReference(ctx); // Signal waiting threads to continue. We do this after inserting the PrincipalContext // into the table, so that the PrincipalContext is ready as soon as the other threads wake up. // (Actually, the order probably doesn't matter, since even if we did it in the // opposite order and the other thread woke up before we inserted the PrincipalContext, it would // just block as soon as it tries to acquire the tableLock that we're currently holding.) bool f = placeHolder.contextReadyEvent.Set(); Debug.Assert(f); } return(ctx); } }
public PrincipalContext GetContext(string name, NetCred credentials, ContextOptions contextOptions) { string nT4UserName; PrincipalContext target; PrincipalContext principalContext; ContextType contextType; string userName; string password; Hashtable hashtables; Hashtable hashtables1; string domainName = name; bool flag = false; if (credentials == null || credentials.UserName == null) { nT4UserName = Utils.GetNT4UserName(); } else { if (credentials.Domain == null) { nT4UserName = credentials.UserName; } else { nT4UserName = string.Concat(credentials.Domain, "\\", credentials.UserName); } flag = true; } if (!this.isSAM) { int num = 0x40000110; UnsafeNativeMethods.DomainControllerInfo dcName = Utils.GetDcName(null, domainName, null, num); domainName = dcName.DomainName; } ManualResetEvent manualResetEvent = null; while (true) { Hashtable hashtables2 = null; if (manualResetEvent != null) { manualResetEvent.WaitOne(); } manualResetEvent = null; lock (this.tableLock) { SDSCache.CredHolder item = (SDSCache.CredHolder) this.table[domainName]; if (item != null) { if (flag) { hashtables1 = item.explicitCreds; } else { hashtables1 = item.defaultCreds; } hashtables2 = hashtables1; object obj = hashtables2[nT4UserName]; if (obj as SDSCache.Placeholder == null) { WeakReference weakReference = obj as WeakReference; if (weakReference != null) { target = (PrincipalContext)weakReference.Target; if (target == null || target.Disposed) { hashtables2.Remove(nT4UserName); } else { principalContext = target; break; } } } else { manualResetEvent = ((SDSCache.Placeholder)obj).contextReadyEvent; continue; } } if (item == null) { item = new SDSCache.CredHolder(); this.table[domainName] = item; if (flag) { hashtables = item.explicitCreds; } else { hashtables = item.defaultCreds; } hashtables2 = hashtables; } hashtables2[nT4UserName] = new SDSCache.Placeholder(); if (this.isSAM) { contextType = ContextType.Machine; } else { contextType = ContextType.Domain; } string str = domainName; object obj1 = null; ContextOptions contextOption = contextOptions; if (credentials != null) { userName = credentials.UserName; } else { userName = null; } if (credentials != null) { password = credentials.Password; } else { password = null; } target = new PrincipalContext(contextType, str, obj1, contextOption, userName, password); lock (this.tableLock) { SDSCache.Placeholder placeholder = (SDSCache.Placeholder)hashtables2[nT4UserName]; hashtables2[nT4UserName] = new WeakReference(target); placeholder.contextReadyEvent.Set(); } return(target); } } return(principalContext); }