|
|
//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996
//
// File: globals.cxx
//
// Contents:
//
// History:
//----------------------------------------------------------------------------
#include "ldap.hxx"
#pragma hdrstop
TCHAR *szProviderName = TEXT("LDAP"); TCHAR *szLDAPNamespaceName = TEXT("LDAP"); TCHAR *szGCNamespaceName = TEXT("GC");
//
// List of interface properties for Generic Objects
//
INTF_PROP_DATA IntfPropsGeneric[] = { // 9999 implies BSTR value got using pIADs ptr.
{ TEXT("__Class"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__GUID"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__Path"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__Parent"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__Schema"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__URL"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, // end of list from IADs::get_ methods.
{ TEXT("__Genus"), OPERATION_CODE_READABLE, UMI_TYPE_I4, FALSE, {UMI_GENUS_INSTANCE}}, { TEXT("__Name"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__KEY"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__RELURL"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__RELPATH"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__FULLRELURL"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__PADS_SCHEMA_CONTAINER_PATH"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__SECURITY_DESCRIPTOR"), OPERATION_CODE_READWRITE, 9999, FALSE, {NULL}}, { NULL, 0, 0, FALSE, {0}} // end of data marker
};
//
// Same as generic save that genus is set to schema value.
//
INTF_PROP_DATA IntfPropsSchema[] = { // 9999 implies BSTR value got using pIADs ptr.
{ TEXT("__Class"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__Path"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__Parent"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__URL"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, // end of list from IADs::get_ methods.
{ TEXT("__Genus"), OPERATION_CODE_READABLE, UMI_TYPE_I4, FALSE, {UMI_GENUS_CLASS}}, { TEXT("__Name"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__RELURL"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__RELPATH"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__FULLRELURL"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { TEXT("__SUPERCLASS"), OPERATION_CODE_READABLE, 9999, FALSE, {NULL}}, { NULL, 0, 0, FALSE, {0}} // end of data marker
};
//
// Interface property data for connection objects.
//
INTF_PROP_DATA IntfPropsConnection[] = { { TEXT("Class"), OPERATION_CODE_READABLE, UMI_TYPE_LPWSTR, FALSE, {NULL} }, { TEXT("__UserId"), OPERATION_CODE_READWRITE, UMI_TYPE_LPWSTR, FALSE, {NULL}}, { TEXT("__Password"), OPERATION_CODE_WRITEABLE, UMI_TYPE_LPWSTR, FALSE, {NULL}}, { TEXT("__SECURE_AUTHENTICATION"), OPERATION_CODE_READWRITE, UMI_TYPE_BOOL, FALSE, {TRUE}}, { TEXT("__NO_AUTHENTICATION"), OPERATION_CODE_READWRITE, UMI_TYPE_BOOL, FALSE, {FALSE}}, { TEXT("__PADS_READONLY_SERVER"), OPERATION_CODE_READWRITE, UMI_TYPE_BOOL, FALSE, {FALSE}}, { TEXT("__PADS_PROMPT_CREDENTIALS"), OPERATION_CODE_READWRITE, UMI_TYPE_BOOL, FALSE, {FALSE}}, { TEXT("__PADS_SERVER_BIND"), OPERATION_CODE_READWRITE, UMI_TYPE_BOOL, FALSE, {FALSE}}, { TEXT("__PADS_FAST_BIND"), OPERATION_CODE_READWRITE, UMI_TYPE_BOOL, FALSE, {FALSE}}, { TEXT("__PADS_USE_SIGNING"), OPERATION_CODE_READWRITE, UMI_TYPE_BOOL, FALSE, {FALSE}}, { TEXT("__PADS_USE_SEALING"), OPERATION_CODE_READWRITE, UMI_TYPE_BOOL, FALSE, {FALSE}}, // { TEXT("SecurityFlags"), OPERATION_CODE_READWRITE,
// UMI_TYPE_I4, FALSE, {1}},
{ NULL, 0, 0, FALSE, {0}} // end of data marker
};
//
// Interface property data for cursor objects.
//
INTF_PROP_DATA IntfPropsCursor[] = { { TEXT("__Filter"), OPERATION_CODE_READWRITE, UMI_TYPE_LPWSTR, TRUE, {NULL}}, { NULL, 0, 0, FALSE, {0}} // end of data marker
};
//
// Interface properties for query object.
//
INTF_PROP_DATA IntfPropsQuery[]= { { TEXT("__SEARCH_SCOPE"), OPERATION_CODE_READWRITE, UMI_TYPE_I4, FALSE, {LDAP_SCOPE_SUBTREE} }, { TEXT("__PADS_SEARCHPREF_ASYNCHRONOUS"), OPERATION_CODE_READWRITE, UMI_TYPE_BOOL, FALSE, {FALSE}}, { TEXT("__PADS_SEARCHPREF_DEREF_ALIASES"), OPERATION_CODE_READWRITE, UMI_TYPE_BOOL, FALSE, {FALSE}}, { TEXT("__PADS_SEARCHPREF_SIZE_LIMIT"), OPERATION_CODE_READWRITE, UMI_TYPE_I4, FALSE, {0}}, { TEXT("__PADS_SEARCHPREF_TIME_LIMIT"), OPERATION_CODE_READWRITE, UMI_TYPE_I4, FALSE, {0}}, { TEXT("__PADS_SEARCHPREF_ATTRIBTYPES_ONLY"), OPERATION_CODE_READWRITE, UMI_TYPE_BOOL, FALSE, {FALSE}}, { TEXT("__PADS_SEARCHPREF_TIMEOUT"), OPERATION_CODE_READWRITE, UMI_TYPE_I4, FALSE, {0}}, { TEXT("__PADS_SEARCHPREF_PAGESIZE"), OPERATION_CODE_READWRITE, UMI_TYPE_I4, FALSE, {0}}, { TEXT("__PADS_SEARCHPREF_PAGED_TIME_LIMIT"), OPERATION_CODE_READWRITE, UMI_TYPE_I4, FALSE, {0}}, { TEXT("__PADS_SEARCHPREF_CHASE_REFERRALS"), OPERATION_CODE_READWRITE, UMI_TYPE_I4, FALSE, {ADS_CHASE_REFERRALS_EXTERNAL}}, //
// BugBug do we keep this similar to IDirectorySearch or do we not cache.
//
{ TEXT("__PADS_SEARCHPREF_CACHE_RESULTS"), OPERATION_CODE_READWRITE, UMI_TYPE_BOOL, FALSE, {TRUE}}, { TEXT("__PADS_SEARCHPREF_TOMBSTONE"), OPERATION_CODE_READWRITE, UMI_TYPE_BOOL, FALSE, {FALSE}}, { TEXT("__PADS_SEARCHPREF_FILTER"), OPERATION_CODE_READWRITE, UMI_TYPE_LPWSTR, FALSE, {0}}, { TEXT("__PADS_SEARCHPREF_ATTRIBUTES"), OPERATION_CODE_READWRITE, UMI_TYPE_LPWSTR, TRUE, {0}}, { NULL, 0, 0, FALSE, {0}} // end of data marker
};
BOOL g_fDllsLoaded = FALSE; HANDLE g_hDllNtdsapi = NULL; HANDLE g_hDllSecur32 = NULL; CRITICAL_SECTION g_csLoadLibsCritSect;
//
// Loads all the dynamic libs we need.
//
void BindToDlls() { DWORD dwErr = 0;
if (g_fDllsLoaded) { return; }
ENTER_LOADLIBS_CRITSECT(); if (g_fDllsLoaded) { LEAVE_LOADLIBS_CRITSECT(); return; }
if (!(g_hDllNtdsapi = LoadLibrary(L"NTDSAPI.DLL"))) { dwErr = GetLastError(); }
if (g_hDllSecur32 = LoadLibrary(L"SECUR32.DLL")) { if (dwErr) { //
// Set the last error for whatever it is worth.
// This does not really matter cause any dll we
// cannot load, we will not get functions on that
// dll. If secur32 load failed, then that call
// would have set a relevant last error.
//
SetLastError(dwErr); } }
g_fDllsLoaded = TRUE; LEAVE_LOADLIBS_CRITSECT();
return; }
//
// Loads the appropriate ntdsapi fn.
//
PVOID LoadNtDsApiFunction(CHAR *function) { if (!g_fDllsLoaded) { BindToDlls(); }
if (g_hDllNtdsapi) { return((PVOID*) GetProcAddress((HMODULE) g_hDllNtdsapi, function)); }
return NULL; }
//
// Loads the appropriate secur32 fn.
//
PVOID LoadSecur32Function(CHAR *function) { if (!g_fDllsLoaded) { BindToDlls(); }
if (g_hDllSecur32) { return((PVOID*) GetProcAddress((HMODULE) g_hDllSecur32, function)); }
return NULL; }
//
// DsUnquoteRdnValueWrapper
//
DWORD DsUnquoteRdnValueWrapper( IN DWORD cQuotedRdnValueLength, IN LPCWSTR psQuotedRdnValue, IN OUT DWORD *pcUnquotedRdnValueLength, OUT LPWSTR psUnquotedRdnValue ) { static PF_DsUnquoteRdnValueW pfDsUnquoteRdnVal = NULL; static BOOL f_LoadAttempted = FALSE;
//
// Load the fn and set the variables accordingly.
//
if (!f_LoadAttempted && pfDsUnquoteRdnVal == NULL) { pfDsUnquoteRdnVal = (PF_DsUnquoteRdnValueW) LoadNtDsApiFunction(DSUNQUOTERDN_API); f_LoadAttempted = TRUE; }
if (pfDsUnquoteRdnVal != NULL) { return ((*pfDsUnquoteRdnVal)( cQuotedRdnValueLength, psQuotedRdnValue, pcUnquotedRdnValueLength, psUnquotedRdnValue ) ); } else { return (ERROR_GEN_FAILURE); }
}
//
// DsMakePasswordCredentialsWrapper
//
DWORD DsMakePasswordCredentialsWrapper( LPCWSTR User, LPCWSTR Domain, LPCWSTR Password, RPC_AUTH_IDENTITY_HANDLE *pAuthIdentity ) { static PF_DsMakePasswordCredentialsW pfMakePwdCreds = NULL; static BOOL f_LoadAttempted = FALSE;
//
// Load the fn and set the variables accordingly.
//
if (!f_LoadAttempted && pfMakePwdCreds == NULL) { pfMakePwdCreds = (PF_DsMakePasswordCredentialsW) LoadNtDsApiFunction(DSMAKEPASSWD_CRED_API); f_LoadAttempted = TRUE; }
if (pfMakePwdCreds != NULL) { return ((*pfMakePwdCreds)( User, Domain, Password, pAuthIdentity ) ); } else { return (ERROR_GEN_FAILURE); } }
//
// DsFreePasswordCredentialsWrapper
//
DWORD DsFreePasswordCredentialsWrapper( RPC_AUTH_IDENTITY_HANDLE AuthIdentity ) { static PF_DsFreePasswordCredentials pfFreeCreds = NULL; static BOOL f_LoadAttempted = FALSE;
//
// Load the fn and set the variables accordingly.
//
if (!f_LoadAttempted && pfFreeCreds == NULL) { pfFreeCreds = (PF_DsFreePasswordCredentials) LoadNtDsApiFunction(DSFREEPASSWD_CRED_API); f_LoadAttempted = TRUE; }
if (pfFreeCreds != NULL) { return ((*pfFreeCreds)( AuthIdentity ) ); } else { return (ERROR_GEN_FAILURE); } }
//
// DsBindWrapper.
//
DWORD DsBindWrapper( LPCWSTR DomainControllerName, LPCWSTR DnsDomainName, HANDLE *phDS ) { static PF_DsBindW pfDsBind = NULL; static BOOL f_LoadAttempted = FALSE;
//
// Load the fn and set the variables accordingly.
//
if (!f_LoadAttempted && pfDsBind == NULL) { pfDsBind = (PF_DsBindW) LoadNtDsApiFunction(DSBIND_API); f_LoadAttempted = TRUE; }
if (pfDsBind != NULL) { return ((*pfDsBind)( DomainControllerName, DnsDomainName, phDS ) ); } else { return (ERROR_GEN_FAILURE); } }
//
// DsUnBindWrapper.
//
DWORD DsUnBindWrapper( HANDLE *phDS ) { static PF_DsUnbindW pfDsUnbind = NULL; static BOOL f_LoadAttempted = FALSE;
//
// Load the fn and set the variables accordingly.
//
if (!f_LoadAttempted && pfDsUnbind == NULL) { pfDsUnbind = (PF_DsUnbindW) LoadNtDsApiFunction(DSUNBIND_API); f_LoadAttempted = TRUE; }
if (pfDsUnbind != NULL) { return ((*pfDsUnbind)( phDS ) ); } else { return (ERROR_GEN_FAILURE); } }
//
// DsCrackNamesWrapper.
//
DWORD DsCrackNamesWrapper( HANDLE hDS, DS_NAME_FLAGS flags, DS_NAME_FORMAT formatOffered, DS_NAME_FORMAT formatDesired, DWORD cNames, const LPCWSTR *rpNames, PDS_NAME_RESULTW *ppResult ) { static PF_DsCrackNamesW pfDsCrackNames = NULL; static BOOL f_LoadAttempted = FALSE;
//
// Load the fn and set the variables accordingly.
//
if (!f_LoadAttempted && pfDsCrackNames == NULL) { pfDsCrackNames = (PF_DsCrackNamesW) LoadNtDsApiFunction(DSCRACK_NAMES_API); f_LoadAttempted = TRUE; }
if (pfDsCrackNames != NULL) { return ((*pfDsCrackNames)( hDS, flags, formatOffered, formatDesired, cNames, rpNames, ppResult ) ); } else { return (ERROR_GEN_FAILURE); } }
//
// DsBindWithCredWrapper.
//
DWORD DsBindWithCredWrapper( LPCWSTR DomainControllerName, LPCWSTR DnsDomainName, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, HANDLE *phDS ) { static PF_DsBindWithCredW pfDsBindWithCred = NULL; static BOOL f_LoadAttempted = FALSE;
//
// Load the fn and set the variables accordingly.
//
if (!f_LoadAttempted && pfDsBindWithCred == NULL) { pfDsBindWithCred = (PF_DsBindWithCredW) LoadNtDsApiFunction(DSBINDWITHCRED_API); f_LoadAttempted = TRUE; }
if (pfDsBindWithCred != NULL) { return ((*pfDsBindWithCred)( DomainControllerName, DnsDomainName, AuthIdentity, phDS ) ); } else { return (ERROR_GEN_FAILURE); } }
//
// DsFreeNameResultWrapper.
//
DWORD DsFreeNameResultWrapper( DS_NAME_RESULTW *pResult ) { static PF_DsFreeNameResultW pfDsFreeNameResult = NULL; static BOOL f_LoadAttempted = FALSE;
//
// Load the fn and set the variables accordingly.
//
if (!f_LoadAttempted && pfDsFreeNameResult == NULL) { pfDsFreeNameResult = (PF_DsFreeNameResultW) LoadNtDsApiFunction(DSFREENAME_RESULT_API); f_LoadAttempted = TRUE; }
if (pfDsFreeNameResult != NULL) { return ((*pfDsFreeNameResult)( pResult ) ); } else { return (ERROR_GEN_FAILURE); } }
//
// QueryContextAttributesWrapper.
//
DWORD QueryContextAttributesWrapper( PCtxtHandle phContext, unsigned long ulAttribute, void SEC_FAR * pBuffer ) { static PF_QueryContextAttributes pfQueryCtxtAttr = NULL; static BOOL f_LoadAttempted = FALSE;
//
// Load the fn and set the variables accordingly.
//
if (!f_LoadAttempted && pfQueryCtxtAttr == NULL) { pfQueryCtxtAttr = (PF_QueryContextAttributes) LoadSecur32Function(QUERYCONTEXT_ATTR_API); f_LoadAttempted = TRUE; }
if (pfQueryCtxtAttr != NULL) { return ((*pfQueryCtxtAttr)( phContext, ulAttribute, pBuffer ) ); } else { return (ERROR_GEN_FAILURE); } }
//+---------------------------------------------------------------------------
// Function: UrlToClassAndDn - global scope, helper function.
//
// Synopsis: This function takes strings of the following formats and
// returns the class name and dn part in the appropriate return
// values :
// 1) Fully qualified = user.cn=MyTestUser,
// 2) Full Name (umi) = .cn=MyTestUser,
// 3) ADSI style RDN = cn=MyTestUser.
//
// Arguments: pUrl - IUmiURL pointer.
// ppszDN - Contains returned DN (callee must free
// using FreeADsStr.
// ppszClass - Contains returned class name string. It
// is the callees responsiblity to free using
// FreeADsStrResult.
//
// Returns: HRESULT - S_OK or any failure ecode.
//
// Modifies: *ppszDN && *ppszClass.
//
//----------------------------------------------------------------------------
HRESULT UrlToClassAndDn( IN IUmiURL *pUrl, OUT LPWSTR *ppszClass, OUT LPWSTR *ppszDN ) { HRESULT hr; WCHAR pszTxt[1024]; ULONG ulLen = 1023; WCHAR *pszUrlTxt = pszTxt; LPCWSTR pszUrlTxtCopy = NULL; LPWSTR pszDN = NULL, pszClass = NULL; DWORD dwClassCount = 0;
*ppszDN = *ppszClass = NULL;
ADsAssert(pUrl); //
// Something on the url object telling us what is wrong will help.
//
//
// We need to get hold of the string from the url.
//
hr = pUrl->Get(0, &ulLen, pszUrlTxt); // replace the correct error code below WBEM_E_BUFFER_TOO_SMALL
if (hr == 0x8004103c) { //
// not enough space in our buffer, lets try again.
//
pszUrlTxt = (WCHAR*) AllocADsMem(ulLen * sizeof(WCHAR)); if (!pszUrlTxt) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
hr = pUrl->Get(0, &ulLen, pszUrlTxt); }
BAIL_ON_FAILURE(hr);
pszUrlTxtCopy = pszUrlTxt; //
// Look for the . if there is one that is.
//
while (*pszUrlTxtCopy && (*pszUrlTxtCopy != L'.') && (*pszUrlTxtCopy != L'=') ) { dwClassCount++; pszUrlTxtCopy++; }
if (!*pszUrlTxtCopy) { //
// There was no = in the url has to be a bad RDN.
//
BAIL_ON_FAILURE(hr = E_INVALIDARG); }
//
// Urls without a . or not valid.
//
if (*pszUrlTxtCopy != L'.') { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
if (*pszUrlTxtCopy == L'=') { //
// We do not have any class name
//
pszDN = AllocADsStr(pszUrlTxt);
if (!pszDN) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } } else { //
// If the count is zero then we have .cn=something
//
if (dwClassCount == 0) { pszDN = AllocADsStr(++pszUrlTxtCopy);
if (!pszDN) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } } else { //
// A valid class name is present.
//
pszClass = (LPWSTR) AllocADsMem(sizeof(WCHAR) * (dwClassCount+1)); if (!pszClass) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
wcsncpy(pszClass, pszUrlTxt, dwClassCount);
//
// Advance beyond the . in the url and copy the rdn.
//
pszUrlTxtCopy++;
if (!*pszUrlTxtCopy) { //
// Only class name, no RDN.
//
BAIL_ON_FAILURE(hr = E_INVALIDARG); }
pszDN = AllocADsStr(pszUrlTxtCopy);
if (!pszDN) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } } // end of else that is dwClassCount != 0
} // end of else corresponding to class name or . present
//
// Alloc class name into new str so we can free using FreeADsStr.
//
if (pszClass) { *ppszClass = AllocADsStr(pszClass);
if (!*ppszClass) { BAIL_ON_FAILURE(hr); } FreeADsMem(pszClass); }
*ppszDN = pszDN;
error:
if (pszUrlTxt && (pszUrlTxt != pszTxt)) { FreeADsMem(pszUrlTxt); }
//
// Free the DN and Class only if applicable.
//
if (FAILED(hr)) { if (pszDN) { FreeADsStr(pszDN); }
if (pszClass) { FreeADsMem(pszClass); } }
RRETURN(hr); }
HRESULT GetRDn( IUmiURL *pURL, DWORD dwComponent, LPWSTR pszRDn, DWORD dwRDnLen ) { HRESULT hr = S_OK; IUmiURLKeyList * pKeyList = NULL; DWORD dwLen = dwRDnLen; DWORD dwKeyNameLen = 64; WCHAR szKeyName[64]; LPWSTR pszTmpStr = NULL; BOOL fSchema = FALSE;
pszTmpStr = (WCHAR*)AllocADsMem(dwRDnLen); if (!pszTmpStr) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
//
// Get the component we need, num is passed in.
//
hr = pURL->GetComponent( dwComponent, &dwLen, pszRDn, &pKeyList ); BAIL_ON_FAILURE(hr);
if (!pKeyList) { BAIL_ON_FAILURE(hr = UMI_E_NOT_FOUND); }
//
// Make sure that the key count is only one, anything
//else cannot be an LDAP path component.
//
hr = pKeyList->GetCount(&dwLen); BAIL_ON_FAILURE(hr);
if (dwLen != 1) { //
// Need to see if we have the pszRDN set, if so that is the
// RDN itself - for example Schema or RootDSE.
//
if (pszRDn) { goto error; } BAIL_ON_FAILURE(hr = UMI_E_NOT_FOUND); }
dwLen = dwRDnLen; //
// Get the RDN from the key !.
//
hr = pKeyList->GetKey( 0, 0, &dwKeyNameLen, szKeyName, &dwLen, pszTmpStr ); BAIL_ON_FAILURE(hr);
//
// We need to special case class.Name=User. This means
// we are looking for a class called user not an instance
// of class with RDN Name=User.
//
fSchema = !_wcsicmp(pszRDn, L"Class") || !_wcsicmp(pszRDn, L"Schema") || !_wcsicmp(pszRDn, L"Property") || !_wcsicmp(pszRDn, L"Syntax");
if (fSchema && szKeyName && !_wcsicmp(szKeyName, L"Name") ) { //
// We have class.Name=User.
//
wsprintf(pszRDn, L"%s", pszTmpStr); } else { //
// We have right values and this is the normal code path.
//
wsprintf(pszRDn, L"%s=",szKeyName); wcscat(pszRDn, pszTmpStr); }
error:
if (pKeyList) { pKeyList->Release(); }
if (pszTmpStr) { FreeADsMem(pszTmpStr); }
RRETURN(hr); }
HRESULT GetDNFromURL( IUmiURL *pURL, LPWSTR *pszDnStr, DWORD dwTotalLen ) { HRESULT hr = S_OK; DWORD dwNumComponents = 0, dwCtr = 0; LPWSTR pszLocalDn = NULL; LPWSTR pszRDn = NULL;
*pszDnStr = NULL; hr = pURL->GetComponentCount(&dwNumComponents); BAIL_ON_FAILURE(hr);
if (dwNumComponents == 0) { //
// DnStr is NULL in this case.
//
RRETURN(hr); }
//
// This is for the retval.
//
pszLocalDn = (LPWSTR) AllocADsMem(dwTotalLen * sizeof(WCHAR)); if (!pszLocalDn) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
//
// This is for the rdn's, this buffer should be more than enough
//
pszRDn = (LPWSTR) AllocADsMem(dwTotalLen * sizeof(WCHAR)); if (!pszRDn) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
//
// We need to get each of the individuals dn's and keep adding
// them to the dn we return.
//
for (dwCtr = 0; dwCtr < dwNumComponents; dwCtr++) { *pszRDn = NULL; hr = GetRDn(pURL, (dwNumComponents-1) - dwCtr, pszRDn, dwTotalLen); BAIL_ON_FAILURE(hr); if (*pszRDn) { wcscat(pszLocalDn, pszRDn); if (dwCtr != (dwNumComponents - 1)) { wcscat(pszLocalDn, L","); } } else { BAIL_ON_FAILURE(hr = E_FAIL); } }
//
// We must have the correct DN !
//
*pszDnStr = pszLocalDn;
error:
if (FAILED(hr)) { if (pszLocalDn) { FreeADsMem(pszLocalDn); } }
if (pszRDn) { FreeADsMem(pszRDn); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: UrlToLDAPPath - global scope, helper function.
//
// Synopsis: This routine converts the URL to the
//
// Arguments: pURL - URL to be converted to path. Note
// that this can be native or Umi.
// pszLDAPPath - Path is allocated into this var.
// ppszDn -
// ppszClass - Contains returned class name string. It
// is the callees responsiblity to free using
// FreeADsStrResult.
//
// Returns: HRESULT - S_OK or any failure ecode.
//
// Modifies: *ppszDN && *ppszClass.
//
//----------------------------------------------------------------------------
HRESULT UrlToLDAPPath( IN IUmiURL *pURL, OUT LPWSTR *ppszLDAPPath, OPTIONAL OUT LPWSTR *ppszDn, OPTIONAL OUT LPWSTR *ppszServer ) { HRESULT hr = S_OK; DWORD dwURLType = 0; DWORD dwLen = 1023; DWORD dwTxtLen = 1023; WCHAR pszTxt[1024]; LPWSTR pszDn = NULL; LPWSTR pszLdapPath = NULL; BOOL fAddSlash = FALSE; ULONGLONG ululPathType = UMIPATH_INFO_INSTANCE_PATH;
//
// We need the type of the url, if it is an ldap native path.
// For now though this support is not available. We assume that
// this is a umi path for now.
//
//
// Get the total length needed for the path.
//
hr = pURL->Get(0, &dwLen, pszTxt); // replace the correct error code below WBEM_E_BUFFER_TOO_SMALL
if ((FAILED(hr) && (hr != 0x8004103c)) || (dwLen == 0)) { //
// Failure was either length was zero or error was someting
// other than buffer too small.
//
BAIL_ON_FAILURE(hr); }
dwLen++; // for the terminating \0.
pszLdapPath = (LPWSTR) AllocADsMem(dwLen * sizeof(WCHAR)); if (!pszLdapPath) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
hr = pURL->GetPathInfo(0, &ululPathType); BAIL_ON_FAILURE(hr);
if (ululPathType == UMIPATH_INFO_NATIVE_STRING) { //
// Just get the path in pszLdapPath and return.
//
hr = pURL->Get(0, &dwLen, pszLdapPath); BAIL_ON_FAILURE(hr); } else { //
// Make sure that the namespace is either LDAP or GC.
// We bail on failure cause we cannot possibly have a locator
// that is more than our buffer size !
//
hr = pURL->GetRootNamespace(&dwTxtLen, pszTxt); BAIL_ON_FAILURE(hr); if (!_wcsicmp(L"LDAP", pszTxt)) { wsprintf(pszLdapPath, L"%s", L"LDAP:"); } else if (!_wcsicmp(L"GC", pszTxt)) { wsprintf(pszLdapPath, L"%s", L"GC:"); } else { BAIL_ON_FAILURE(hr = UMI_E_NOT_FOUND); } //
// We now need to add the server and the // if applicable.
//
dwTxtLen = 1023; hr = pURL->GetLocator(&dwTxtLen, pszTxt); if (hr == 0x8004103c) { //
// Unexpected cause locator is too big !.
//
hr = E_FAIL; } BAIL_ON_FAILURE(hr); if (!wcscmp(pszTxt, L".")) { //
// This would mean we are going serverless.
//
wcscat(pszLdapPath, L"/"); } else if (!*pszTxt) { //
// Means that we have the LDAP namespace or no server.
//
fAddSlash = TRUE; } else { //
// Add the // and the servername given.
//
wcscat(pszLdapPath, L"//"); wcscat(pszLdapPath, pszTxt); } //
// Now we need to get the DN and tag it along.
//
hr = GetDNFromURL(pURL, &pszDn, dwLen); BAIL_ON_FAILURE(hr); if (pszDn && *pszDn) { if (fAddSlash) { //
// Serverless path.
//
wcscat(pszLdapPath, L"/"); } //
// Tag on the DN now, it will do the right thing for
// both server and serverless paths.
//
wcscat(pszLdapPath,L"/"); wcscat(pszLdapPath,pszDn); } } // this was not a native path.
*ppszLDAPPath = pszLdapPath;
error:
if (FAILED(hr)) { if (pszLdapPath) { FreeADsMem(pszLdapPath); } }
if (pszDn) { FreeADsMem(pszDn); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: ADsPathToUmiUrl - global scope, helper function.
//
// Synopsis: This routine converts the ADsPath to UMI URL txt.
//
// Arguments: ADsPath - Input string.
// ppszUrlTxt - Output converted url txt.
//
// Returns: HRESULT - S_OK or any failure ecode.
//
// Modifies: *ppszUrlTxt - to point to the correct
//
//----------------------------------------------------------------------------
HRESULT ADsPathToUmiURL( IN LPWSTR ADsPath, OUT LPWSTR *ppszUrlTxt ) { HRESULT hr = S_OK; OBJECTINFO ObjectInfo; POBJECTINFO pObjectInfo = &ObjectInfo; DWORD dwNumComponents = 0, dwCtr; LPWSTR pszUrl = NULL; BOOL fReverseOrder = TRUE;
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
ADsAssert(ADsPath && ppszUrlTxt); *ppszUrlTxt = NULL;
//
// We build our ObjectInfo struct and then build the url
// from the objectInfo struct.
//
pObjectInfo->ObjectType = TOKEN_LDAPOBJECT; hr = ADsObject(ADsPath, pObjectInfo); BAIL_ON_FAILURE(hr);
dwNumComponents = pObjectInfo->NumComponents; //
// We can make a guess as to the size we need for the string.
//
pszUrl = (WCHAR *) AllocADsMem( ( sizeof(WCHAR) * wcslen(ADsPath) ) // for the actual name
+ (sizeof(WCHAR) * dwNumComponents) // for all the .'s we need as in .DC=test
+ (sizeof(WCHAR) * 15) ); //
// sizeof(WCHAR) * 15 has been added so that we can handle
// the umi:// (6) which is extra + if we have a GC path, then
// we would need to add LDAP/ (5) just in case a small buffer
// of 4 giving the 15
//
if (!pszUrl) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
//
// Get the umi:// in the output, then add the server if applicable,
// then the LDAP/GC or LDAP alone as applicable.
//
wsprintf(pszUrl, L"%s", L"umi://");
if (pObjectInfo->dwServerPresent) { if (pObjectInfo->TreeName) { wcscat(pszUrl, pObjectInfo->TreeName); } }
wcscat(pszUrl, L"/"); // need if there is a server or not.
wcscat(pszUrl, L"LDAP"); // needed if LDAP or GC.
if (!_wcsicmp(pObjectInfo->ProviderName, szGCNamespaceName)) { wcscat(pszUrl, L"/GC"); }
//
// This is to check if we were given an LDAP windows style path,
// with reverse order rather than LDAP dn style path.
//
if (pObjectInfo->dwPathType == ADS_PATHTYPE_ROOTFIRST) { //
// Already reversed so just use the order directly.
//
for (dwCtr = 0; dwCtr < dwNumComponents; dwCtr++) { //
// When you have a path like LDAP://RootDSE, then the szComponent
// alone is set and not the value in these cases we need to
// build the path in a different manner.
//
if (pObjectInfo->ComponentArray[dwCtr].szValue) {
wcscat(pszUrl, L"/."); wcscat( pszUrl, pObjectInfo->ComponentArray[dwCtr].szComponent ); wcscat(pszUrl, L"="); wcscat(pszUrl, pObjectInfo->ComponentArray[dwCtr].szValue); } else { //
// We just have a component as in RootDSE or Schema so.
//
wcscat(pszUrl, L"/"); wcscat( pszUrl, pObjectInfo->ComponentArray[dwCtr].szComponent ); } } } else { //
// Need to do this reverse order.
//
for (dwCtr = dwNumComponents; dwCtr > 0; dwCtr--) { //
// When you have a path like LDAP://RootDSE, then the szComponent
// alone is set and not the value in these cases we need to
// build the path in a different manner.
//
if (pObjectInfo->ComponentArray[dwCtr-1].szValue) {
wcscat(pszUrl, L"/."); wcscat( pszUrl, pObjectInfo->ComponentArray[dwCtr-1].szComponent ); wcscat(pszUrl, L"="); wcscat(pszUrl, pObjectInfo->ComponentArray[dwCtr-1].szValue); } else { //
// We just have a component as in RootDSE or Schema so.
//
wcscat(pszUrl, L"/"); wcscat( pszUrl, pObjectInfo->ComponentArray[dwCtr-1].szComponent ); }
} }
*ppszUrlTxt = pszUrl;
error:
if (FAILED(hr)) { if (pszUrl) { FreeADsMem(pszUrl); } }
if (pObjectInfo) { FreeObjectInfo(pObjectInfo); }
RRETURN(hr); }
BOOL IsPreDefinedErrorCode(HRESULT hr) { switch (hr) { case E_UNEXPECTED : case E_NOTIMPL : case E_OUTOFMEMORY : case E_INVALIDARG : case E_NOINTERFACE : case E_HANDLE : case E_ABORT : case E_FAIL : case E_ACCESSDENIED : case E_PENDING : case E_POINTER : case UMI_E_CONNECTION_FAILURE : case UMI_E_TIMED_OUT : case UMI_E_TYPE_MISMATCH : case UMI_E_NOT_FOUND : case UMI_E_INVALID_FLAGS : case UMI_E_UNSUPPORTED_FLAGS : case UMI_E_SYNCHRONIZATION_REQUIRED : case UMI_E_UNSUPPORTED_OPERATION : case UMI_E_TRANSACTION_FAILURE : RRETURN(TRUE); break;
default: RRETURN(FALSE); break; } }
//+---------------------------------------------------------------------------
// Function: MapHrToUmiError - global scope, helper function.
//
// Synopsis: This routine converts the given hr to an equivalent umi err.
//
// Arguments: hr - hr to convert to umi error.
//
// Returns: HRESULT - umi error code corresponing to hr passed in.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
HRESULT MapHrToUmiError(HRESULT hr) { HRESULT retHr = hr;
if (IsPreDefinedErrorCode(hr)) { RRETURN(hr); }
switch (hr) {
case E_ADS_INVALID_DOMAIN_OBJECT: case E_ADS_INVALID_USER_OBJECT: case E_ADS_INVALID_COMPUTER_OBJECT: case E_ADS_UNKNOWN_OBJECT: retHr = UMI_E_NOT_FOUND; break;
case E_ADS_PROPERTY_NOT_FOUND: retHr = UMI_E_NOT_FOUND; break;
case E_ADS_BAD_PARAMETER: retHr = E_INVALIDARG; break;
case E_ADS_CANT_CONVERT_DATATYPE: retHr = UMI_E_TYPE_MISMATCH; break;
case E_ADS_BAD_PATHNAME: retHr = E_INVALIDARG; break;
case HRESULT_FROM_WIN32(ERROR_DS_NO_ATTRIBUTE_OR_VALUE) : // LDAP_NO_SUCH_ATTRIBUTE
retHr = UMI_E_NOT_FOUND; break; case HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT) : // LDAP_NO_SUCH_OBJECT
retHr = UMI_E_NOT_FOUND; break;
default: retHr = E_FAIL; break; } // end of case
RRETURN(retHr); }
|