mirror of
https://github.com/MichaelGrafnetter/DSInternals
synced 2024-12-25 07:32:26 +00:00
Fixed #23
This commit is contained in:
parent
e21c85812f
commit
1c8d6dbde8
@ -1,3 +1,7 @@
|
||||
Version 2.18
|
||||
- [Module] The Get-ADReplAccount cmdlet now correctly reports the access denied error.
|
||||
- [Framework] Replication errors are now reported using more suitable exception types.
|
||||
|
||||
Version 2.17.1
|
||||
- [Module] Fixed a bug in progress reporting of the Get-ADReplAccount cmdlet.
|
||||
|
||||
|
@ -4,6 +4,9 @@
|
||||
|
||||
[Serializable]
|
||||
public abstract class DirectoryException : Exception
|
||||
{
|
||||
public DirectoryException(Exception innerException = null) : base(null, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ namespace DSInternals.Common.Exceptions
|
||||
private set;
|
||||
}
|
||||
|
||||
public DirectoryObjectException(object objectIdentifier)
|
||||
public DirectoryObjectException(object objectIdentifier, Exception innerException = null) : base(innerException)
|
||||
{
|
||||
this.ObjectIdentifier = objectIdentifier;
|
||||
}
|
||||
|
@ -7,8 +7,8 @@
|
||||
[Serializable]
|
||||
public sealed class DirectoryObjectNotFoundException : DirectoryObjectException
|
||||
{
|
||||
public DirectoryObjectNotFoundException(object objectIdentifier)
|
||||
: base(objectIdentifier)
|
||||
public DirectoryObjectNotFoundException(object objectIdentifier = null, Exception innerExcetion = null)
|
||||
: base(objectIdentifier, innerExcetion)
|
||||
{
|
||||
}
|
||||
|
||||
@ -16,7 +16,9 @@
|
||||
{
|
||||
get
|
||||
{
|
||||
return String.Format(Resources.ObjectNotFoundMessageFormat,this.ObjectIdentifier);
|
||||
return this.ObjectIdentifier != null ?
|
||||
String.Format(Resources.ObjectWithIdentityNotFoundMessageFormat, this.ObjectIdentifier) :
|
||||
Resources.ObjectNotFoundMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,11 +11,12 @@
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public SchemaAttributeNotFoundException(string attributeName)
|
||||
public SchemaAttributeNotFoundException(string attributeName) : base(null)
|
||||
{
|
||||
this.AttributeIdentifier = attributeName;
|
||||
}
|
||||
public SchemaAttributeNotFoundException(int attributeId)
|
||||
: base(null)
|
||||
{
|
||||
this.AttributeIdentifier = attributeId;
|
||||
}
|
||||
|
@ -620,7 +620,7 @@
|
||||
/// <summary>
|
||||
/// The volume label you entered exceeds the label character limit of the target file system.
|
||||
/// </summary>
|
||||
LABEL_TOO_Int32 = 154,
|
||||
LABEL_TOO_LONG = 154,
|
||||
|
||||
/// <summary>
|
||||
/// Cannot create another thread.
|
||||
@ -811,7 +811,7 @@
|
||||
/// <summary>
|
||||
/// The global filename characters, * or ?, are entered incorrectly or too many global filename characters are specified.
|
||||
/// </summary>
|
||||
META_EXPANSION_TOO_Int32 = 208,
|
||||
META_EXPANSION_TOO_LONG = 208,
|
||||
|
||||
/// <summary>
|
||||
/// The signal being posted is not correct.
|
||||
@ -1735,7 +1735,7 @@
|
||||
/// <summary>
|
||||
/// The format of the specified password is invalid.
|
||||
/// </summary>
|
||||
INVALID_PASSUInt16NAME = 1216,
|
||||
INVALID_PASSWORDNAME = 1216,
|
||||
|
||||
/// <summary>
|
||||
/// The format of the specified message name is invalid.
|
||||
@ -2083,7 +2083,7 @@
|
||||
/// <summary>
|
||||
/// The password is too complex to be converted to a LAN Manager password. The LAN Manager password returned is a NULL string.
|
||||
/// </summary>
|
||||
NULL_LM_PASSUInt16 = 1304,
|
||||
NULL_LM_PASSWORD = 1304,
|
||||
|
||||
/// <summary>
|
||||
/// The revision level is unknown.
|
||||
@ -2213,7 +2213,7 @@
|
||||
/// <summary>
|
||||
/// Logon failure: the specified account password has expired.
|
||||
/// </summary>
|
||||
PASSUInt16_EXPIRED = 1330,
|
||||
PASSWORD_EXPIRED = 1330,
|
||||
|
||||
/// <summary>
|
||||
/// Logon failure: account currently disabled.
|
||||
@ -2468,7 +2468,7 @@
|
||||
/// <summary>
|
||||
/// The length of a secret exceeds the maximum length allowed.
|
||||
/// </summary>
|
||||
SECRET_TOO_Int32 = 1382,
|
||||
SECRET_TOO_LONG = 1382,
|
||||
|
||||
/// <summary>
|
||||
/// The local security authority database contains an internal inconsistency.
|
||||
@ -3315,7 +3315,7 @@
|
||||
/// <summary>
|
||||
/// The string is too long.
|
||||
/// </summary>
|
||||
RPC_S_STRING_TOO_Int32 = 1743,
|
||||
RPC_S_STRING_TOO_LONG = 1743,
|
||||
|
||||
/// <summary>
|
||||
/// The RPC protocol sequence was not found.
|
||||
@ -3470,7 +3470,7 @@
|
||||
/// <summary>
|
||||
/// The file containing the character translation table has fewer than 512 bytes.
|
||||
/// </summary>
|
||||
RPC_X_SS_CHAR_TRANS_Int16_FILE = 1774,
|
||||
RPC_X_SS_CHAR_TRANS_LONG_FILE = 1774,
|
||||
|
||||
/// <summary>
|
||||
/// A null context handle was passed from the client to the host during a remote procedure call.
|
||||
@ -3805,7 +3805,7 @@
|
||||
/// <summary>
|
||||
/// The user's password must be changed before logging on the first time.
|
||||
/// </summary>
|
||||
PASSUInt16_MUST_CHANGE = 1907,
|
||||
PASSWORD_MUST_CHANGE = 1907,
|
||||
|
||||
/// <summary>
|
||||
/// Could not find the domain controller for this domain.
|
||||
@ -4050,12 +4050,12 @@
|
||||
/// <summary>
|
||||
/// The network connection was made successfully, but the user had to be prompted for a password other than the one originally specified.
|
||||
/// </summary>
|
||||
CONNECTED_OTHER_PASSUInt16 = 2108,
|
||||
CONNECTED_OTHER_PASSWORD = 2108,
|
||||
|
||||
/// <summary>
|
||||
/// The network connection was made successfully using default credentials.
|
||||
/// </summary>
|
||||
CONNECTED_OTHER_PASSUInt16_DEFAULT = 2109,
|
||||
CONNECTED_OTHER_PASSWORD_DEFAULT = 2109,
|
||||
|
||||
/// <summary>
|
||||
/// The specified username is invalid.
|
||||
@ -5984,12 +5984,12 @@
|
||||
/// <summary>
|
||||
/// The name is too long.
|
||||
/// </summary>
|
||||
DS_NAME_TOO_Int32 = 8348,
|
||||
DS_NAME_TOO_LONG = 8348,
|
||||
|
||||
/// <summary>
|
||||
/// The name value is too long.
|
||||
/// </summary>
|
||||
DS_NAME_VALUE_TOO_Int32 = 8349,
|
||||
DS_NAME_VALUE_TOO_LONG = 8349,
|
||||
|
||||
/// <summary>
|
||||
/// The directory service encountered an error parsing a name.
|
||||
@ -6009,7 +6009,7 @@
|
||||
/// <summary>
|
||||
/// The security descriptor is too short.
|
||||
/// </summary>
|
||||
DS_SEC_DESC_TOO_Int16 = 8353,
|
||||
DS_SEC_DESC_TOO_LONG = 8353,
|
||||
|
||||
/// <summary>
|
||||
/// The security descriptor is invalid.
|
||||
@ -6890,7 +6890,7 @@
|
||||
/// <summary>
|
||||
/// Security Account Manager needs to get the boot password.
|
||||
/// </summary>
|
||||
DS_SAM_NEED_BOOTKEY_PASSUInt16 = 8529,
|
||||
DS_SAM_NEED_BOOTKEY_PASSWORD = 8529,
|
||||
|
||||
/// <summary>
|
||||
/// Security Account Manager needs to get the boot key from floppy disk.
|
||||
@ -8006,7 +8006,7 @@
|
||||
/// <summary>
|
||||
/// Name component or name was too long.
|
||||
/// </summary>
|
||||
WSAENAMETOOInt32 = 10063,
|
||||
WSAENAMETOOLONG = 10063,
|
||||
|
||||
/// <summary>
|
||||
/// A socket operation failed because the destination host was down.
|
||||
@ -8657,7 +8657,7 @@
|
||||
/// <summary>
|
||||
/// Assembly Protection Error : The public key for an assembly was too short to be allowed.
|
||||
/// </summary>
|
||||
SXS_PROTECTION_PUBLIC_KEY_TOO_Int16 = 14075,
|
||||
SXS_PROTECTION_PUBLIC_KEY_TOO_LONG = 14075,
|
||||
|
||||
/// <summary>
|
||||
/// Assembly Protection Error : The catalog for an assembly is not valid, or does not match the assembly's manifest.
|
||||
|
@ -1,7 +1,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
// Runtime Version:4.0.30319.34209
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
@ -124,11 +124,11 @@ namespace DSInternals.Common.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Object with identity '{0}' has not been found..
|
||||
/// Looks up a localized string similar to Could not find the requested object..
|
||||
/// </summary>
|
||||
public static string ObjectNotFoundMessageFormat {
|
||||
public static string ObjectNotFoundMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("ObjectNotFoundMessageFormat", resourceCulture);
|
||||
return ResourceManager.GetString("ObjectNotFoundMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,6 +141,15 @@ namespace DSInternals.Common.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Object with identity '{0}' has not been found..
|
||||
/// </summary>
|
||||
public static string ObjectWithIdentityNotFoundMessageFormat {
|
||||
get {
|
||||
return ResourceManager.GetString("ObjectWithIdentityNotFoundMessageFormat", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} (Object identity: '{1}').
|
||||
/// </summary>
|
||||
|
@ -138,12 +138,15 @@
|
||||
<data name="ObjectNotAccountMessage" xml:space="preserve">
|
||||
<value>Object is not an account.</value>
|
||||
</data>
|
||||
<data name="ObjectNotFoundMessageFormat" xml:space="preserve">
|
||||
<value>Object with identity '{0}' has not been found.</value>
|
||||
<data name="ObjectNotFoundMessage" xml:space="preserve">
|
||||
<value>Could not find the requested object.</value>
|
||||
</data>
|
||||
<data name="ObjectNotSecurityPrincipalMessage" xml:space="preserve">
|
||||
<value>Object is not a security principal.</value>
|
||||
</data>
|
||||
<data name="ObjectWithIdentityNotFoundMessageFormat" xml:space="preserve">
|
||||
<value>Object with identity '{0}' has not been found.</value>
|
||||
</data>
|
||||
<data name="OperationExceptionMessageFormat" xml:space="preserve">
|
||||
<value>{0} (Object identity: '{1}')</value>
|
||||
</data>
|
||||
|
@ -1,4 +1,5 @@
|
||||
using DSInternals.Common.Cryptography;
|
||||
using DSInternals.Common.Exceptions;
|
||||
using DSInternals.Common.Interop;
|
||||
using DSInternals.Common.Properties;
|
||||
using System;
|
||||
@ -36,6 +37,8 @@ namespace DSInternals.Common
|
||||
break;
|
||||
case Win32ErrorCode.ACCESS_DENIED:
|
||||
case Win32ErrorCode.DS_DRA_ACCESS_DENIED:
|
||||
case Win32ErrorCode.WRONG_PASSWORD:
|
||||
case Win32ErrorCode.PASSWORD_EXPIRED:
|
||||
exceptionToThrow = new UnauthorizedAccessException(genericException.Message, genericException);
|
||||
break;
|
||||
case Win32ErrorCode.NOT_ENOUGH_MEMORY:
|
||||
@ -50,6 +53,11 @@ namespace DSInternals.Common
|
||||
case Win32ErrorCode.RPC_S_CALL_FAILED:
|
||||
exceptionToThrow = new ActiveDirectoryServerDownException(genericException.Message, genericException);
|
||||
break;
|
||||
case Win32ErrorCode.DS_OBJ_NOT_FOUND:
|
||||
// This error code means either a non-existing DN or Access Denied.
|
||||
case Win32ErrorCode.DS_DRA_BAD_DN:
|
||||
exceptionToThrow = new DirectoryObjectNotFoundException(null, genericException);
|
||||
break;
|
||||
// TODO: Add translation for ActiveDirectoryOperationException and for other exception types.
|
||||
default:
|
||||
// We were not able to translate the Win32Exception to a more specific type.
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "RpcTypeConverter.h"
|
||||
|
||||
using namespace DSInternals::Common;
|
||||
using namespace DSInternals::Common::Exceptions;
|
||||
using namespace DSInternals::Common::Interop;
|
||||
using namespace DSInternals::Replication::Model;
|
||||
|
||||
@ -227,6 +228,8 @@ namespace DSInternals
|
||||
}
|
||||
|
||||
ReplicaObject^ DrsConnection::ReplicateSingleObject(String^ distinguishedName, array<ATTRTYP>^ partialAttributeSet)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto request = CreateReplicateSingleRequest(distinguishedName, partialAttributeSet);
|
||||
auto reply = GetNCChanges(move(request));
|
||||
@ -234,6 +237,22 @@ namespace DSInternals
|
||||
// TODO: Assert objects.Count == 1; It is guaranteed that it is > 0
|
||||
return objects[0];
|
||||
}
|
||||
catch (DirectoryObjectNotFoundException^)
|
||||
{
|
||||
// ReplicateSingleObject also exits with this error when access is denied, so we need to differentiate between these situations.
|
||||
bool objectExists = this->TestObjectExistence(distinguishedName);
|
||||
if (objectExists)
|
||||
{
|
||||
// Force the validator to throw the DRA access denied exception.
|
||||
Validator::AssertSuccess(Win32ErrorCode::DS_DRA_ACCESS_DENIED);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rethrow the original exception, as the object really does not exists.
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReplicaObject^ DrsConnection::ReplicateSingleObject(Guid objectGuid)
|
||||
{
|
||||
@ -241,6 +260,8 @@ namespace DSInternals
|
||||
}
|
||||
|
||||
ReplicaObject^ DrsConnection::ReplicateSingleObject(Guid objectGuid, array<ATTRTYP>^ partialAttributeSet)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto request = CreateReplicateSingleRequest(objectGuid, partialAttributeSet);
|
||||
auto reply = GetNCChanges(move(request));
|
||||
@ -248,6 +269,22 @@ namespace DSInternals
|
||||
// TODO: Assert objects.Count == 1; It is guaranteed that it is > 0
|
||||
return objects[0];
|
||||
}
|
||||
catch (DirectoryObjectNotFoundException^)
|
||||
{
|
||||
// ReplicateSingleObject also exits with this error when access is denied, so we need to differentiate between these situations.
|
||||
bool objectExists = this->TestObjectExistence(objectGuid);
|
||||
if (objectExists)
|
||||
{
|
||||
// Force the validator to throw the DRA access denied exception.
|
||||
Validator::AssertSuccess(Win32ErrorCode::DS_DRA_ACCESS_DENIED);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rethrow the original exception, as the object really does not exists.
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
midl_ptr<DRS_MSG_GETCHGREPLY_V6> DrsConnection::GetNCChanges(midl_ptr<DRS_MSG_GETCHGREQ_V8> &&request)
|
||||
{
|
||||
@ -262,15 +299,11 @@ namespace DSInternals
|
||||
DWORD outVersion = 0;
|
||||
auto reply = make_midl_ptr<DRS_MSG_GETCHGREPLY_V6>();
|
||||
// Send message:
|
||||
ULONG result = IDL_DRSGetNCChanges_NoSEH(handle, inVersion, (DRS_MSG_GETCHGREQ*)request.get(), &outVersion, (DRS_MSG_GETCHGREPLY*)reply.get());
|
||||
Validator::AssertSuccess((Win32ErrorCode)result);
|
||||
// TODO: Check the returned version
|
||||
auto result = (Win32ErrorCode) IDL_DRSGetNCChanges_NoSEH(handle, inVersion, (DRS_MSG_GETCHGREQ*)request.get(), &outVersion, (DRS_MSG_GETCHGREPLY*)reply.get());
|
||||
|
||||
// Validate result
|
||||
if (reply->cNumObjects == 0)
|
||||
{
|
||||
// TODO: DirectoryObjectNotFound ex.
|
||||
throw gcnew Exception("Directory object not found.");
|
||||
}
|
||||
// TODO: Check the returned version
|
||||
Validator::AssertSuccess(result);
|
||||
// TODO: Test extended error code:
|
||||
DWORD extendedError = reply->dwDRSError;
|
||||
return reply;
|
||||
@ -291,75 +324,105 @@ namespace DSInternals
|
||||
DRS_HANDLE handle = this->handle.ToPointer();
|
||||
auto result = IDL_DRSCrackNames_NoSEH(handle, inVersion, (DRS_MSG_CRACKREQ*)request.get(), &outVersion, (DRS_MSG_CRACKREPLY*)reply.get());
|
||||
Validator::AssertSuccess((Win32ErrorCode)result);
|
||||
|
||||
if (reply->pResult->cItems != request->cNames)
|
||||
{
|
||||
// TODO: Exception type
|
||||
throw gcnew Exception("Obj not found");
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
|
||||
String^ DrsConnection::ResolveDistinguishedName(NTAccount^ accountName)
|
||||
{
|
||||
auto stringAccountName = accountName->Value;
|
||||
auto dn = this->ResolveName(stringAccountName, DS_NAME_FORMAT::DS_NT4_ACCOUNT_NAME, DS_NAME_FORMAT::DS_FQDN_1779_NAME);
|
||||
auto dn = this->TryResolveName(stringAccountName, DS_NAME_FORMAT::DS_NT4_ACCOUNT_NAME, DS_NAME_FORMAT::DS_FQDN_1779_NAME);
|
||||
if (dn == nullptr)
|
||||
{
|
||||
throw gcnew DirectoryObjectNotFoundException(stringAccountName, nullptr);
|
||||
}
|
||||
return dn;
|
||||
}
|
||||
|
||||
String^ DrsConnection::ResolveDistinguishedName(SecurityIdentifier^ objectSid)
|
||||
{
|
||||
auto stringSid = objectSid->ToString();
|
||||
auto dn = this->ResolveName(stringSid, DS_NAME_FORMAT::DS_SID_OR_SID_HISTORY_NAME, DS_NAME_FORMAT::DS_FQDN_1779_NAME);
|
||||
auto dn = this->TryResolveName(stringSid, DS_NAME_FORMAT::DS_SID_OR_SID_HISTORY_NAME, DS_NAME_FORMAT::DS_FQDN_1779_NAME);
|
||||
if (dn == nullptr)
|
||||
{
|
||||
throw gcnew DirectoryObjectNotFoundException(stringSid, nullptr);
|
||||
}
|
||||
return dn;
|
||||
}
|
||||
|
||||
Guid DrsConnection::ResolveGuid(NTAccount^ accountName)
|
||||
{
|
||||
auto stringAccountName = accountName->Value;
|
||||
auto stringGuid = this->ResolveName(stringAccountName, DS_NAME_FORMAT::DS_NT4_ACCOUNT_NAME, DS_NAME_FORMAT::DS_UNIQUE_ID_NAME);
|
||||
auto stringGuid = this->TryResolveName(stringAccountName, DS_NAME_FORMAT::DS_NT4_ACCOUNT_NAME, DS_NAME_FORMAT::DS_UNIQUE_ID_NAME);
|
||||
if (stringGuid == nullptr)
|
||||
{
|
||||
throw gcnew DirectoryObjectNotFoundException(stringAccountName, nullptr);
|
||||
}
|
||||
return Guid::Parse(stringGuid);
|
||||
}
|
||||
|
||||
Guid DrsConnection::ResolveGuid(SecurityIdentifier^ objectSid)
|
||||
{
|
||||
auto stringSid = objectSid->ToString();
|
||||
auto stringGuid = this->ResolveName(stringSid, DS_NAME_FORMAT::DS_SID_OR_SID_HISTORY_NAME, DS_NAME_FORMAT::DS_UNIQUE_ID_NAME);
|
||||
auto stringGuid = this->TryResolveName(stringSid, DS_NAME_FORMAT::DS_SID_OR_SID_HISTORY_NAME, DS_NAME_FORMAT::DS_UNIQUE_ID_NAME);
|
||||
if (stringGuid == nullptr)
|
||||
{
|
||||
throw gcnew DirectoryObjectNotFoundException(stringSid, nullptr);
|
||||
}
|
||||
return Guid::Parse(stringGuid);
|
||||
}
|
||||
|
||||
Guid DrsConnection::ResolveGuid(String^ userPrincipalName)
|
||||
{
|
||||
auto stringGuid = this->ResolveName(userPrincipalName, DS_NAME_FORMAT::DS_USER_PRINCIPAL_NAME, DS_NAME_FORMAT::DS_UNIQUE_ID_NAME);
|
||||
auto stringGuid = this->TryResolveName(userPrincipalName, DS_NAME_FORMAT::DS_USER_PRINCIPAL_NAME, DS_NAME_FORMAT::DS_UNIQUE_ID_NAME);
|
||||
if (stringGuid == nullptr)
|
||||
{
|
||||
throw gcnew DirectoryObjectNotFoundException(userPrincipalName, nullptr);
|
||||
}
|
||||
return Guid::Parse(stringGuid);
|
||||
}
|
||||
|
||||
String^ DrsConnection::ResolveName(String^ name, DS_NAME_FORMAT formatOffered, DS_NAME_FORMAT formatDesired)
|
||||
String^ DrsConnection::TryResolveName(String^ name, DS_NAME_FORMAT formatOffered, DS_NAME_FORMAT formatDesired)
|
||||
{
|
||||
// We only want to resolve 1 name at a time:
|
||||
const size_t numItems = 1;
|
||||
|
||||
// Prepare the request
|
||||
auto request = make_midl_ptr<DRS_MSG_CRACKREQ_V1>(numItems);
|
||||
request->formatOffered = formatOffered;
|
||||
request->formatDesired = formatDesired;
|
||||
request->rpNames[0] = RpcTypeConverter::ToNativeString(name).release();
|
||||
auto result = this->ResolveName(move(request));
|
||||
// TODO: Merge with ResolveName(midl_ptr<DRS_MSG_CRACKREQ_V1> &&request)?
|
||||
return result;
|
||||
}
|
||||
|
||||
String^ DrsConnection::ResolveName(midl_ptr<DRS_MSG_CRACKREQ_V1> &&request)
|
||||
{
|
||||
// Perform RPC call
|
||||
auto reply = this->CrackNames(move(request));
|
||||
|
||||
// Process the response
|
||||
auto item = reply->pResult->rItems[0];
|
||||
// TODO: const 0
|
||||
if (item.status != 0)
|
||||
if (item.status == DS_NAME_ERROR::DS_NAME_NO_ERROR)
|
||||
{
|
||||
// TODO: Exception type
|
||||
throw gcnew Exception("Object not found");
|
||||
}
|
||||
auto name = marshal_as<String^>(item.pName);
|
||||
return name;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No name translation has been found for some reason.
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool DrsConnection::TestObjectExistence(String^ distinguishedName)
|
||||
{
|
||||
auto resolvedName = this->TryResolveName(distinguishedName, DS_NAME_FORMAT::DS_FQDN_1779_NAME, DS_NAME_FORMAT::DS_UNIQUE_ID_NAME);
|
||||
// Return true if and only if the object exists
|
||||
return resolvedName != nullptr;
|
||||
}
|
||||
|
||||
bool DrsConnection::TestObjectExistence(Guid objectGuid)
|
||||
{
|
||||
auto stringGuid = objectGuid.ToString("B");
|
||||
auto resolvedName = this->TryResolveName(stringGuid, DS_NAME_FORMAT::DS_UNIQUE_ID_NAME, DS_NAME_FORMAT::DS_FQDN_1779_NAME);
|
||||
// Return true if and only if the object exists
|
||||
return resolvedName != nullptr;
|
||||
}
|
||||
|
||||
bool DrsConnection::ReleaseHandle()
|
||||
{
|
||||
|
@ -54,6 +54,8 @@ namespace DSInternals
|
||||
Guid ResolveGuid(NTAccount^ accountName);
|
||||
Guid ResolveGuid(SecurityIdentifier^ objectSid);
|
||||
Guid ResolveGuid(String^ userPrincipalName);
|
||||
bool TestObjectExistence(String^ distinguishedName);
|
||||
bool TestObjectExistence(Guid objectGuid);
|
||||
protected:
|
||||
virtual bool ReleaseHandle() override;
|
||||
private:
|
||||
@ -61,8 +63,7 @@ namespace DSInternals
|
||||
void Bind(IntPtr rpcHandle);
|
||||
midl_ptr<DRS_MSG_GETCHGREPLY_V6> GetNCChanges(midl_ptr<DRS_MSG_GETCHGREQ_V8> &&request);
|
||||
midl_ptr<DRS_MSG_CRACKREPLY_V1> CrackNames(midl_ptr<DRS_MSG_CRACKREQ_V1> &&request);
|
||||
String^ ResolveName(String^ name, DS_NAME_FORMAT formatOffered, DS_NAME_FORMAT formatDesired);
|
||||
String^ ResolveName(midl_ptr<DRS_MSG_CRACKREQ_V1> &&request);
|
||||
String^ TryResolveName(String^ name, DS_NAME_FORMAT formatOffered, DS_NAME_FORMAT formatDesired);
|
||||
midl_ptr<DRS_EXTENSIONS_INT> CreateClientInfo();
|
||||
midl_ptr<DRS_MSG_GETCHGREQ_V8> CreateReplicateAllRequest(ReplicationCookie^ cookie, array<ATTRTYP>^ partialAttributeSet, ULONG maxBytes, ULONG maxObjects);
|
||||
midl_ptr<DRS_MSG_GETCHGREQ_V8> CreateReplicateSingleRequest(String^ distinguishedName, array<ATTRTYP>^ partialAttributeSet);
|
||||
|
Loading…
Reference in New Issue
Block a user