private void Bind(bool throwIfFail) { //Cannot rebind after the object has been disposed, since finalization has been suppressed. if (this.disposed) { throw new ObjectDisposedException(GetType().Name); } if (Path != null && Path.Length != 0) { //SECREVIEW: Need to demand permission event if adsObject is not null // this entry might be the result of a search, need to verify // if the user has permission to browse the object first. if (!browseGranted) { DirectoryServicesPermission permission = new DirectoryServicesPermission(DirectoryServicesPermissionAccess.Browse, Path); permission.Demand(); browseGranted = true; } } if (adsObject == null) { string pathToUse = Path; if (pathToUse == null || pathToUse.Length == 0) { // get the default naming context. This should be the default root for the search. DirectoryEntry rootDSE = new DirectoryEntry("LDAP://RootDSE"); //SECREVIEW: Looking at the root of the DS will demand browse permissions // on "*" or "LDAP://RootDSE". string defaultNamingContext = (string)rootDSE.Properties["defaultNamingContext"][0]; rootDSE.Dispose(); pathToUse = "LDAP://" + defaultNamingContext; if (!browseGranted) { DirectoryServicesPermission permission = new DirectoryServicesPermission(DirectoryServicesPermissionAccess.Browse, pathToUse); permission.Demand(); browseGranted = true; } } // Ensure we've got a thread model set, else CoInitialize() won't have been called. if (Thread.CurrentThread.ApartmentState == ApartmentState.Unknown) { Thread.CurrentThread.ApartmentState = ApartmentState.MTA; } Guid g = new Guid("00000000-0000-0000-c000-000000000046"); // IID_IUnknown object value = null; int hr = UnsafeNativeMethods.ADsOpenObject(pathToUse, Username, Password, (int)authenticationType, ref g, out value); if (hr != 0) { if (throwIfFail) { throw CreateFormattedComException(hr); } } else { adsObject = (UnsafeNativeMethods.IAds)value; } } }