You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1370 lines
31 KiB
1370 lines
31 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1997.
|
|
//
|
|
// File: pathmgmt.cxx
|
|
//
|
|
// Contents:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 25-April-97 KrishnaG Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "ldapc.hxx"
|
|
#pragma hdrstop
|
|
|
|
|
|
#define STRING_LENGTH(p) ( p ? wcslen(p) : 0)
|
|
|
|
HRESULT
|
|
BuildADsParentPathFromObjectInfo2(
|
|
POBJECTINFO pObjectInfo,
|
|
LPWSTR *ppszParent,
|
|
LPWSTR *ppszCommonName
|
|
)
|
|
{
|
|
DWORD i = 0;
|
|
DWORD dwNumComponents = 0;
|
|
HRESULT hr = S_OK;
|
|
LPWSTR pszComponent = NULL, pszValue = NULL;
|
|
|
|
|
|
hr = ComputeAllocateParentCommonNameSize(pObjectInfo, ppszParent, ppszCommonName);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
hr = BuildADsParentPathFromObjectInfo(
|
|
pObjectInfo,
|
|
*ppszParent,
|
|
*ppszCommonName
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
|
|
RRETURN(hr);
|
|
|
|
|
|
error:
|
|
if (*ppszParent) {
|
|
|
|
FreeADsMem(*ppszParent);
|
|
}
|
|
|
|
if (*ppszCommonName) {
|
|
|
|
FreeADsMem(*ppszCommonName);
|
|
}
|
|
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
BuildADsParentPath(
|
|
LPWSTR szBuffer,
|
|
LPWSTR *ppszParent,
|
|
LPWSTR *ppszCommonName
|
|
)
|
|
{
|
|
OBJECTINFO ObjectInfo;
|
|
POBJECTINFO pObjectInfo = &ObjectInfo;
|
|
HRESULT hr = S_OK;
|
|
LPWSTR pszCommonName = NULL;
|
|
LPWSTR pszParent = NULL;
|
|
|
|
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
|
|
hr = ADsObject(szBuffer, pObjectInfo);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
// The length of pszParent or pszCommon is definitely less than the
|
|
// length of the total buffer.
|
|
|
|
pszParent = (LPWSTR) AllocADsMem( (_tcslen(szBuffer) + 1) * sizeof(TCHAR));
|
|
|
|
if ( pszParent == NULL )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
pszCommonName = (LPWSTR) AllocADsMem( (_tcslen(szBuffer) + 1) * sizeof(TCHAR));
|
|
|
|
if ( pszCommonName == NULL )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
hr = BuildADsParentPathFromObjectInfo(
|
|
pObjectInfo,
|
|
pszParent,
|
|
pszCommonName
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
*ppszParent = pszParent;
|
|
*ppszCommonName = pszCommonName;
|
|
|
|
FreeObjectInfo( &ObjectInfo );
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
|
|
if (pszCommonName) {
|
|
FreeADsMem(pszCommonName);
|
|
}
|
|
|
|
if (pszParent) {
|
|
FreeADsMem(pszParent);
|
|
}
|
|
|
|
FreeObjectInfo( &ObjectInfo );
|
|
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
BuildADsParentPathFromObjectInfo(
|
|
POBJECTINFO pObjectInfo,
|
|
LPWSTR pszParent,
|
|
LPWSTR pszCommonName
|
|
)
|
|
{
|
|
DWORD i = 0;
|
|
DWORD dwNumComponents = 0;
|
|
HRESULT hr = S_OK;
|
|
LPWSTR pszComponent = NULL, pszValue = NULL;
|
|
|
|
dwNumComponents = pObjectInfo->NumComponents;
|
|
|
|
if (!dwNumComponents && !pObjectInfo->DisplayTreeName) {
|
|
|
|
//
|
|
// There are no CNs in this pathname and
|
|
// no tree name specified. This is the
|
|
// namespace object - its parent is the
|
|
// @ADs! object
|
|
//
|
|
|
|
wsprintf(pszParent,L"ADs:");
|
|
wsprintf(pszCommonName, L"%s:", pObjectInfo->NamespaceName);
|
|
|
|
hr = S_OK;
|
|
|
|
} else if (!dwNumComponents && pObjectInfo->DisplayTreeName) {
|
|
//
|
|
// There are no CNs in this pathname and a tree
|
|
// name has been specified. This is the root
|
|
// object - its parent is the @NDS! object
|
|
|
|
|
|
wsprintf(pszParent, L"%s:", pObjectInfo->NamespaceName);
|
|
|
|
//
|
|
// And the common name is the TreeName (and port)
|
|
//
|
|
|
|
if ( IS_EXPLICIT_PORT(pObjectInfo->PortNumber) ) {
|
|
|
|
wsprintf(pszCommonName,L"%s:%d", pObjectInfo->TreeName, pObjectInfo->PortNumber);
|
|
}
|
|
else {
|
|
|
|
wsprintf(pszCommonName,L"%s", pObjectInfo->TreeName);
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
}else {
|
|
//
|
|
// There are one or more CNs, a tree name has been
|
|
// specified. In the worst case the parent is the
|
|
// root object. In the best case a long CN.
|
|
//
|
|
|
|
switch (pObjectInfo->dwServerPresent) {
|
|
|
|
case TRUE:
|
|
|
|
if ( IS_EXPLICIT_PORT(pObjectInfo->PortNumber) ) {
|
|
|
|
wsprintf(
|
|
pszParent, L"%s://%s:%d",
|
|
pObjectInfo->NamespaceName,
|
|
pObjectInfo->DisplayTreeName,
|
|
pObjectInfo->PortNumber
|
|
);
|
|
}
|
|
else {
|
|
|
|
wsprintf(
|
|
pszParent, L"%s://%s",
|
|
pObjectInfo->NamespaceName,
|
|
pObjectInfo->DisplayTreeName
|
|
);
|
|
}
|
|
break;
|
|
|
|
|
|
case FALSE:
|
|
wsprintf(
|
|
pszParent, L"%s:",
|
|
pObjectInfo->NamespaceName
|
|
);
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
switch (pObjectInfo->dwPathType) {
|
|
|
|
case PATHTYPE_X500:
|
|
default: // where we cannot make a determination whether its X500 or Windows style
|
|
|
|
if (dwNumComponents > 1) {
|
|
|
|
if (pObjectInfo->dwServerPresent) {
|
|
wcscat(pszParent, L"/");
|
|
}else {
|
|
wcscat(pszParent,L"//");
|
|
}
|
|
|
|
for (i = 1; i < dwNumComponents; i++) {
|
|
|
|
AppendComponent(pszParent, &(pObjectInfo->DisplayComponentArray[i]));
|
|
|
|
if (i < (dwNumComponents - 1)) {
|
|
wcscat(pszParent, L",");
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// And the common name is the last component
|
|
//
|
|
|
|
pszComponent = pObjectInfo->DisplayComponentArray[0].szComponent;
|
|
pszValue = pObjectInfo->DisplayComponentArray[0].szValue;
|
|
|
|
|
|
if (pszComponent && pszValue) {
|
|
|
|
wsprintf(pszCommonName, L"%s=%s",pszComponent, pszValue);
|
|
|
|
}else if (pszComponent){
|
|
|
|
wsprintf(pszCommonName, L"%s", pszComponent);
|
|
|
|
}else {
|
|
//
|
|
// Error - we should never hit this case!!
|
|
//
|
|
|
|
}
|
|
hr = S_OK;
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PATHTYPE_WINDOWS:
|
|
|
|
switch (pObjectInfo->dwServerPresent) {
|
|
case FALSE:
|
|
|
|
if (dwNumComponents > 1) {
|
|
|
|
wcscat(pszParent,L"//");
|
|
|
|
for (i = 0; i < dwNumComponents - 1; i++) {
|
|
if (i ) {
|
|
wcscat(pszParent, L"/");
|
|
}
|
|
|
|
AppendComponent(pszParent, &(pObjectInfo->DisplayComponentArray[i]));
|
|
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
case TRUE:
|
|
for (i = 0; i < dwNumComponents - 1; i++) {
|
|
|
|
|
|
wcscat(pszParent, L"/");
|
|
|
|
AppendComponent(pszParent, &(pObjectInfo->DisplayComponentArray[i]));
|
|
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// And the common name is the last component
|
|
//
|
|
|
|
pszComponent = pObjectInfo->DisplayComponentArray[dwNumComponents - 1].szComponent;
|
|
pszValue = pObjectInfo->DisplayComponentArray[dwNumComponents - 1].szValue;
|
|
|
|
|
|
if (pszComponent && pszValue) {
|
|
|
|
wsprintf(pszCommonName, L"%s=%s",pszComponent, pszValue);
|
|
|
|
}else if (pszComponent){
|
|
|
|
wsprintf(pszCommonName, L"%s", pszComponent);
|
|
|
|
}else {
|
|
//
|
|
// Error - we should never hit this case!!
|
|
//
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
HRESULT
|
|
AppendComponent(
|
|
LPWSTR pszADsPathName,
|
|
PCOMPONENT pComponent
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPWSTR pszComponent = NULL, pszValue = NULL;
|
|
|
|
pszComponent = pComponent->szComponent;
|
|
pszValue = pComponent->szValue;
|
|
|
|
|
|
if (pszComponent && pszValue) {
|
|
|
|
wcscat(
|
|
pszADsPathName,
|
|
pComponent->szComponent
|
|
);
|
|
wcscat(pszADsPathName,L"=");
|
|
wcscat(
|
|
pszADsPathName,
|
|
pComponent->szValue
|
|
);
|
|
}else if (pszComponent){
|
|
|
|
wcscat(
|
|
pszADsPathName,
|
|
pComponent->szComponent
|
|
);
|
|
|
|
}else {
|
|
//
|
|
// Error - we should never hit this case!!
|
|
//
|
|
|
|
}
|
|
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
ComputeAllocateParentCommonNameSize(
|
|
POBJECTINFO pObjectInfo,
|
|
LPWSTR * ppszParent,
|
|
LPWSTR * ppszCommonName
|
|
)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
LPWSTR pszParent = NULL;
|
|
LPWSTR pszCommonName = NULL;
|
|
DWORD dwPathSz = 0;
|
|
WCHAR szPort[32];
|
|
DWORD i = 0;
|
|
|
|
|
|
//
|
|
// the ADsPath of the Parent is atleast as long as the standard
|
|
// pathname
|
|
//
|
|
|
|
//
|
|
// the CommonName is atleast as long as the parent name
|
|
//
|
|
|
|
dwPathSz += STRING_LENGTH(pObjectInfo->NamespaceName);
|
|
dwPathSz += STRING_LENGTH(pObjectInfo->ProviderName);
|
|
dwPathSz += 2;
|
|
dwPathSz += STRING_LENGTH(pObjectInfo->DisplayTreeName);
|
|
|
|
//
|
|
// If an explicit port has been specified
|
|
//
|
|
|
|
if ( IS_EXPLICIT_PORT(pObjectInfo->PortNumber) ) {
|
|
wsprintf(szPort, L":%d", pObjectInfo->PortNumber);
|
|
dwPathSz += wcslen(szPort);
|
|
}
|
|
|
|
dwPathSz += 1;
|
|
|
|
for (i = 0; i < pObjectInfo->NumComponents; i++) {
|
|
|
|
dwPathSz += STRING_LENGTH(pObjectInfo->DisplayComponentArray[i].szComponent);
|
|
dwPathSz += 1;
|
|
dwPathSz += STRING_LENGTH(pObjectInfo->DisplayComponentArray[i].szValue);
|
|
dwPathSz += 1;
|
|
}
|
|
|
|
dwPathSz += 1;
|
|
|
|
pszCommonName = (LPWSTR)AllocADsMem((dwPathSz)*sizeof(WCHAR));
|
|
if (!pszCommonName) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
|
|
pszParent = (LPWSTR)AllocADsMem((dwPathSz)*sizeof(WCHAR));
|
|
if (!pszParent) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
*ppszCommonName = pszCommonName;
|
|
|
|
*ppszParent = pszParent;
|
|
|
|
RRETURN(hr);
|
|
|
|
|
|
error:
|
|
|
|
if (pszCommonName ) {
|
|
FreeADsMem(pszCommonName);
|
|
}
|
|
|
|
if (pszParent) {
|
|
FreeADsMem(pszParent);
|
|
}
|
|
|
|
|
|
RRETURN(hr);
|
|
|
|
|
|
}
|
|
|
|
HRESULT
|
|
BuildADsPathFromParent(
|
|
LPWSTR Parent,
|
|
LPWSTR Name,
|
|
LPWSTR *ppszADsPath
|
|
)
|
|
{
|
|
OBJECTINFO ObjectInfo;
|
|
POBJECTINFO pParentObjectInfo = &ObjectInfo;
|
|
HRESULT hr = S_OK;
|
|
LPWSTR pszCommonName = NULL;
|
|
LPWSTR pszADsPath = NULL;
|
|
|
|
memset(pParentObjectInfo, 0, sizeof(OBJECTINFO));
|
|
hr = ADsObject(Parent, pParentObjectInfo);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
// The length of the pszADsPath is the total path + name + 1;
|
|
|
|
//
|
|
// The length of pszParent or pszCommon is definitely less than the
|
|
// length of the total buffer.
|
|
//
|
|
// The Name part may be expanded to include escaping characters. In
|
|
// the worst case, the number of characters will double. Extra 2+1 is for
|
|
// the "//" and a NULL
|
|
//
|
|
|
|
pszADsPath = (LPWSTR) AllocADsMem( (_tcslen(Parent) + (_tcslen(Name)*2) + 2 + 1) * sizeof(TCHAR));
|
|
|
|
if (!pszADsPath) {
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
hr = BuildADsPathFromParentObjectInfo(
|
|
pParentObjectInfo,
|
|
Name,
|
|
pszADsPath
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
*ppszADsPath = pszADsPath;
|
|
|
|
|
|
cleanup:
|
|
|
|
if (pParentObjectInfo) {
|
|
|
|
FreeObjectInfo( pParentObjectInfo );
|
|
}
|
|
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
|
|
if (pszADsPath) {
|
|
FreeADsMem(pszADsPath);
|
|
}
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
BuildADsPathFromParentObjectInfo(
|
|
POBJECTINFO pParentObjectInfo,
|
|
LPWSTR pszName,
|
|
LPWSTR pszADsPath
|
|
)
|
|
{
|
|
DWORD i = 0;
|
|
DWORD dwNumComponents = 0;
|
|
HRESULT hr = S_OK;
|
|
LPWSTR pszDisplayName = NULL;
|
|
|
|
//
|
|
// Get the display name for the name; The display name will have the proper
|
|
// escaping for characters that have special meaning in an ADsPath like
|
|
// '/' etc.
|
|
//
|
|
hr = GetDisplayName(
|
|
pszName,
|
|
&pszDisplayName
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
dwNumComponents = pParentObjectInfo->NumComponents;
|
|
|
|
if (!dwNumComponents && !pParentObjectInfo->DisplayTreeName) {
|
|
|
|
//
|
|
// Should never happen --- ADs is the root of the tree,
|
|
// and has no parent
|
|
//
|
|
ADsAssert(_wcsicmp(pszDisplayName, L"ADs:") != 0);
|
|
|
|
if (!_wcsicmp(pParentObjectInfo->NamespaceName, L"ADs")) {
|
|
|
|
//
|
|
// In this one particular case we take in LDAP: as the Name
|
|
// or GC: as the name
|
|
//
|
|
|
|
//
|
|
// Do not add another : - so bogus!! Krishna
|
|
//
|
|
|
|
|
|
|
|
wsprintf(pszADsPath, L"%s", pszDisplayName);
|
|
}else {
|
|
|
|
//
|
|
// There are no CNs in this pathname and
|
|
// no tree name specified. This is the
|
|
// namespace object
|
|
|
|
//
|
|
// Its pszName is a TreeName and we will concatenate
|
|
// the treename with a slash slash
|
|
//
|
|
|
|
wsprintf(pszADsPath,
|
|
L"%s://%s",
|
|
pParentObjectInfo->NamespaceName,
|
|
pszDisplayName
|
|
);
|
|
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
} else if (!dwNumComponents && pParentObjectInfo->DisplayTreeName) {
|
|
//
|
|
// There are no CNs in this pathname and a tree
|
|
// name has been specified.
|
|
//
|
|
|
|
if (IS_EXPLICIT_PORT(pParentObjectInfo->PortNumber) ) {
|
|
|
|
wsprintf(
|
|
pszADsPath,
|
|
L"%s://%s:%d/%s",
|
|
pParentObjectInfo->NamespaceName,
|
|
pParentObjectInfo->DisplayTreeName,
|
|
pParentObjectInfo->PortNumber,
|
|
pszDisplayName
|
|
);
|
|
}
|
|
else {
|
|
|
|
wsprintf(
|
|
pszADsPath,
|
|
L"%s://%s/%s",
|
|
pParentObjectInfo->NamespaceName,
|
|
pParentObjectInfo->DisplayTreeName,
|
|
pszDisplayName
|
|
);
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
}else {
|
|
//
|
|
// There are one or more CNs, a tree name has been
|
|
// specified. In the worst case the parent is the
|
|
// root object. In the best case a long CN.
|
|
//
|
|
switch (pParentObjectInfo->dwServerPresent) {
|
|
case TRUE:
|
|
|
|
if ( IS_EXPLICIT_PORT(pParentObjectInfo->PortNumber) ) {
|
|
|
|
wsprintf(
|
|
pszADsPath, L"%s://%s:%d",
|
|
pParentObjectInfo->NamespaceName,
|
|
pParentObjectInfo->DisplayTreeName,
|
|
pParentObjectInfo->PortNumber
|
|
);
|
|
}
|
|
else {
|
|
|
|
wsprintf(
|
|
pszADsPath, L"%s://%s",
|
|
pParentObjectInfo->NamespaceName,
|
|
pParentObjectInfo->DisplayTreeName
|
|
);
|
|
}
|
|
break;
|
|
|
|
case FALSE:
|
|
wsprintf(
|
|
pszADsPath, L"%s://",
|
|
pParentObjectInfo->NamespaceName
|
|
);
|
|
}
|
|
switch (pParentObjectInfo->dwPathType) {
|
|
case PATHTYPE_WINDOWS:
|
|
|
|
switch (pParentObjectInfo->dwServerPresent) {
|
|
case TRUE:
|
|
for (i = 0; i < dwNumComponents; i++) {
|
|
|
|
wcscat(pszADsPath, L"/");
|
|
|
|
AppendComponent(pszADsPath, &(pParentObjectInfo->DisplayComponentArray[i]));
|
|
|
|
}
|
|
wcscat(pszADsPath, L"/");
|
|
wcscat(pszADsPath, pszDisplayName);
|
|
|
|
hr = S_OK;
|
|
break;
|
|
|
|
case FALSE:
|
|
for (i = 0; i < dwNumComponents; i++) {
|
|
|
|
if (i ) {
|
|
wcscat(pszADsPath, L"/");
|
|
}
|
|
|
|
AppendComponent(pszADsPath, &(pParentObjectInfo->DisplayComponentArray[i]));
|
|
|
|
}
|
|
wcscat(pszADsPath, L"/");
|
|
wcscat(pszADsPath, pszDisplayName);
|
|
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PATHTYPE_X500:
|
|
default:
|
|
|
|
switch (pParentObjectInfo->dwServerPresent) {
|
|
case TRUE:
|
|
wcscat(pszADsPath, L"/");
|
|
break;
|
|
|
|
case FALSE:
|
|
break;
|
|
}
|
|
|
|
wcscat(pszADsPath, pszDisplayName);
|
|
wcscat(pszADsPath, L",");
|
|
|
|
for (i = 0; i < dwNumComponents; i++) {
|
|
|
|
AppendComponent(pszADsPath, &(pParentObjectInfo->DisplayComponentArray[i]));
|
|
|
|
if (i < (dwNumComponents - 1)) {
|
|
wcscat(pszADsPath, L",");
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
error:
|
|
|
|
if (pszDisplayName) {
|
|
FreeADsMem(pszDisplayName);
|
|
}
|
|
|
|
RRETURN(hr);
|
|
|
|
}
|
|
|
|
HRESULT
|
|
BuildLDAPPathFromADsPath(
|
|
LPWSTR szADsPathName,
|
|
LPWSTR *pszLDAPPathName
|
|
)
|
|
{
|
|
OBJECTINFO ObjectInfo;
|
|
POBJECTINFO pObjectInfo = &ObjectInfo;
|
|
DWORD i = 0;
|
|
DWORD dwNumComponents = 0;
|
|
HRESULT hr = S_OK;
|
|
LPWSTR szLDAPPathName = NULL;
|
|
|
|
*pszLDAPPathName = NULL;
|
|
|
|
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
|
|
hr = ADsObject(szADsPathName, pObjectInfo);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
dwNumComponents = pObjectInfo->NumComponents;
|
|
|
|
//
|
|
// Assumption LDAPPath is always less than the ADsPath
|
|
//
|
|
|
|
szLDAPPathName = AllocADsStr(szADsPathName);
|
|
if (!szLDAPPathName) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
if (!pObjectInfo->TreeName) {
|
|
|
|
//
|
|
// At the very minimum, we need a treename
|
|
//
|
|
|
|
hr = E_FAIL;
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
}else if (pObjectInfo->TreeName && !dwNumComponents){
|
|
|
|
_tcscpy(szLDAPPathName, TEXT("\\\\"));
|
|
_tcscat(szLDAPPathName, pObjectInfo->TreeName);
|
|
|
|
}else if (pObjectInfo->TreeName && dwNumComponents){
|
|
|
|
_tcscpy(szLDAPPathName, TEXT("\\\\"));
|
|
_tcscat(szLDAPPathName, pObjectInfo->TreeName);
|
|
_tcscat(szLDAPPathName, TEXT("\\"));
|
|
|
|
switch (pObjectInfo->dwPathType) {
|
|
|
|
case PATHTYPE_X500:
|
|
default:
|
|
for (i = 0; i < dwNumComponents; i++) {
|
|
|
|
AppendComponent(
|
|
szLDAPPathName,
|
|
&(pObjectInfo->ComponentArray[i])
|
|
);
|
|
|
|
if (i < (dwNumComponents - 1)){
|
|
_tcscat(szLDAPPathName, TEXT(","));
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case PATHTYPE_WINDOWS:
|
|
for (i = dwNumComponents; i > 0; i--) {
|
|
|
|
AppendComponent(
|
|
szLDAPPathName,
|
|
&(pObjectInfo->ComponentArray[i-1])
|
|
);
|
|
|
|
if ((i - 1) > 0){
|
|
_tcscat(szLDAPPathName, TEXT(","));
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*pszLDAPPathName = szLDAPPathName;
|
|
|
|
error:
|
|
|
|
FreeObjectInfo( &ObjectInfo );
|
|
|
|
RRETURN(hr);
|
|
|
|
}
|
|
|
|
HRESULT
|
|
BuildADsPathFromLDAPPath(
|
|
LPWSTR szADsPathContext,
|
|
LPWSTR szTargetLdapDN,
|
|
LPWSTR * ppszADsPathName
|
|
)
|
|
{
|
|
LPWSTR pszADsPathName = NULL;
|
|
PKEYDATA pKeyData = NULL;
|
|
DWORD dwCount = 0, dwLen = 0;
|
|
DWORD i = 0;
|
|
int cHostNameLen;
|
|
HRESULT hr;
|
|
LPWSTR pszHostName = NULL, pszTemp = NULL;
|
|
LPWSTR pszLDAPServer = NULL;
|
|
LPWSTR pszLDAPDn = NULL;
|
|
WCHAR szPort[32];
|
|
DWORD dwPortNumber = 0;
|
|
|
|
OBJECTINFO ObjectInfo, ObjectInfo2;
|
|
POBJECTINFO pObjectInfo = &ObjectInfo;
|
|
POBJECTINFO pObjectInfo2 = &ObjectInfo2;
|
|
|
|
LPWSTR pszDisplayDN = NULL;
|
|
|
|
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
|
|
memset(pObjectInfo2, 0, sizeof(OBJECTINFO));
|
|
|
|
if (!szADsPathContext || !szTargetLdapDN) {
|
|
RRETURN(E_FAIL);
|
|
}
|
|
|
|
hr = GetDisplayName(
|
|
szTargetLdapDN,
|
|
&pszDisplayDN
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
if (!pszDisplayDN) {
|
|
BAIL_ON_FAILURE(hr = E_FAIL);
|
|
}
|
|
|
|
*ppszADsPathName = NULL;
|
|
|
|
hr = ADsObject(szADsPathContext, pObjectInfo);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = BuildLDAPPathFromADsPath2(
|
|
szADsPathContext,
|
|
&pszLDAPServer,
|
|
&pszLDAPDn,
|
|
&dwPortNumber
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
dwLen = STRING_LENGTH(pObjectInfo->NamespaceName) +
|
|
STRING_LENGTH(pszLDAPServer) +
|
|
STRING_LENGTH(pszDisplayDN) +
|
|
STRING_LENGTH(L"://") +
|
|
STRING_LENGTH(L"/") +
|
|
1;
|
|
|
|
if (IS_EXPLICIT_PORT(dwPortNumber) ) {
|
|
wsprintf(szPort, L":%d", dwPortNumber);
|
|
dwLen += wcslen(szPort);
|
|
}
|
|
|
|
pszADsPathName = (LPWSTR) AllocADsMem( dwLen * sizeof(WCHAR) );
|
|
if(!pszADsPathName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto error;
|
|
}
|
|
|
|
pszTemp = (LPWSTR) AllocADsMem( dwLen * sizeof(WCHAR) );
|
|
|
|
if(!pszTemp) {
|
|
if(pszADsPathName)
|
|
{
|
|
FreeADsMem(pszADsPathName);
|
|
}
|
|
hr = E_OUTOFMEMORY;
|
|
goto error;
|
|
}
|
|
|
|
switch (pObjectInfo->dwPathType) {
|
|
|
|
case PATHTYPE_WINDOWS:
|
|
|
|
//
|
|
// Simplistic way to do this is to create the X500 based name and then
|
|
// reparse it to generate the Windows style name
|
|
//
|
|
|
|
switch (pObjectInfo->dwServerPresent) {
|
|
case TRUE:
|
|
|
|
wsprintf(pszADsPathName,L"%s://", pObjectInfo->NamespaceName);
|
|
wcscat(pszADsPathName, pszLDAPServer);
|
|
if (IS_EXPLICIT_PORT(pObjectInfo->PortNumber) ) {
|
|
wsprintf(szPort, L":%d", pObjectInfo->PortNumber);
|
|
wcscat(pszADsPathName, szPort);
|
|
}
|
|
wcscat(pszADsPathName, L"/");
|
|
wcscpy(pszTemp, pszADsPathName);
|
|
|
|
wcscat(pszADsPathName, pszDisplayDN);
|
|
break;
|
|
|
|
case FALSE:
|
|
wsprintf(pszADsPathName,L"%s://", pObjectInfo->NamespaceName);
|
|
wcscpy(pszTemp, pszADsPathName);
|
|
|
|
wcscat(pszADsPathName, pszDisplayDN);
|
|
break;
|
|
}
|
|
|
|
hr = ADsObject(pszADsPathName, pObjectInfo2);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
wcscpy (pszADsPathName, pszTemp);
|
|
for (i = pObjectInfo2->NumComponents; i > 0; i--) {
|
|
|
|
AppendComponent(
|
|
pszADsPathName,
|
|
&(pObjectInfo2->DisplayComponentArray[i-1])
|
|
);
|
|
|
|
if ((i - 1) > 0){
|
|
_tcscat(pszADsPathName, TEXT("/"));
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case PATHTYPE_X500:
|
|
default:
|
|
|
|
switch (pObjectInfo->dwServerPresent) {
|
|
case TRUE:
|
|
wsprintf(pszADsPathName,L"%s://", pObjectInfo->NamespaceName);
|
|
wcscat(pszADsPathName, pszLDAPServer);
|
|
|
|
if (IS_EXPLICIT_PORT(pObjectInfo->PortNumber) ) {
|
|
wsprintf(szPort, L":%d", pObjectInfo->PortNumber);
|
|
wcscat(pszADsPathName, szPort);
|
|
}
|
|
|
|
wcscat(pszADsPathName, L"/");
|
|
wcscat(pszADsPathName, pszDisplayDN);
|
|
break;
|
|
|
|
case FALSE:
|
|
wsprintf(pszADsPathName,L"%s://", pObjectInfo->NamespaceName);
|
|
wcscat(pszADsPathName, pszDisplayDN);
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*ppszADsPathName = pszADsPathName;
|
|
|
|
error:
|
|
|
|
if (pObjectInfo) {
|
|
FreeObjectInfo(pObjectInfo);
|
|
}
|
|
|
|
if (pObjectInfo2) {
|
|
FreeObjectInfo(pObjectInfo2);
|
|
}
|
|
|
|
if (pszTemp) {
|
|
FreeADsMem(pszTemp);
|
|
}
|
|
|
|
if (pszLDAPServer) {
|
|
FreeADsStr(pszLDAPServer);
|
|
}
|
|
|
|
if (pszLDAPDn) {
|
|
FreeADsStr(pszLDAPDn);
|
|
}
|
|
|
|
if (pszDisplayDN) {
|
|
FreeADsMem(pszDisplayDN);
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
PKEYDATA
|
|
CreateTokenList(
|
|
LPWSTR pKeyData,
|
|
WCHAR ch
|
|
)
|
|
{
|
|
DWORD cTokens;
|
|
DWORD cb;
|
|
PKEYDATA pResult;
|
|
LPWSTR pDest;
|
|
LPWSTR psz = pKeyData;
|
|
LPWSTR *ppToken;
|
|
WCHAR szTokenList[MAX_PATH];
|
|
|
|
|
|
if (!psz || !*psz)
|
|
return NULL;
|
|
|
|
_stprintf(szTokenList, TEXT("%c"), ch);
|
|
|
|
cTokens=1;
|
|
|
|
// Scan through the string looking for commas,
|
|
// ensuring that each is followed by a non-NULL character:
|
|
|
|
while ((psz = wcschr(psz, ch)) && psz[1]) {
|
|
|
|
cTokens++;
|
|
psz++;
|
|
}
|
|
|
|
cb = sizeof(KEYDATA) + (cTokens-1) * sizeof(LPWSTR) +
|
|
wcslen(pKeyData)*sizeof(WCHAR) + sizeof(WCHAR);
|
|
|
|
if (!(pResult = (PKEYDATA)AllocADsMem(cb)))
|
|
return NULL;
|
|
|
|
// Initialise pDest to point beyond the token pointers:
|
|
|
|
pDest = (LPWSTR)((LPBYTE)pResult + sizeof(KEYDATA) +
|
|
(cTokens-1) * sizeof(LPWSTR));
|
|
|
|
// Then copy the key data buffer there:
|
|
|
|
wcscpy(pDest, pKeyData);
|
|
|
|
ppToken = pResult->pTokens;
|
|
|
|
|
|
// Remember, wcstok has the side effect of replacing the delimiter
|
|
// by NULL, which is precisely what we want:
|
|
|
|
psz = wcstok (pDest, szTokenList);
|
|
|
|
while (psz) {
|
|
|
|
*ppToken++ = psz;
|
|
psz = wcstok (NULL, szTokenList);
|
|
}
|
|
|
|
pResult->cTokens = cTokens;
|
|
|
|
return( pResult );
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
BuildLDAPPathFromADsPath2(
|
|
LPWSTR szADsPathName,
|
|
LPWSTR *pszLDAPServer,
|
|
LPWSTR *pszLDAPDn,
|
|
DWORD * pdwPort
|
|
)
|
|
{
|
|
OBJECTINFO ObjectInfo;
|
|
POBJECTINFO pObjectInfo = &ObjectInfo;
|
|
DWORD i = 0;
|
|
DWORD dwNumComponents = 0;
|
|
HRESULT hr = S_OK;
|
|
LPWSTR szLDAPServer = NULL;
|
|
LPWSTR szLDAPDn = NULL;
|
|
DWORD dwPortNumber = 0;
|
|
|
|
*pszLDAPServer = NULL;
|
|
*pszLDAPDn = NULL;
|
|
*pdwPort = 0;
|
|
|
|
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
|
|
hr = ADsObject(szADsPathName, pObjectInfo);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
dwPortNumber = pObjectInfo->PortNumber;
|
|
|
|
|
|
dwNumComponents = pObjectInfo->NumComponents;
|
|
|
|
//
|
|
// Assumption LDAPPath is always less than the ADsPath
|
|
//
|
|
|
|
if (!pObjectInfo->TreeName && !dwNumComponents) {
|
|
|
|
//
|
|
// At the very minimum, we need a treename
|
|
//
|
|
|
|
hr = E_FAIL;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
if (pObjectInfo->TreeName){
|
|
|
|
szLDAPServer = (LPWSTR)AllocADsMem((wcslen(szADsPathName) +1)*sizeof(WCHAR));
|
|
if (!szLDAPServer) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
_tcscat(szLDAPServer, pObjectInfo->TreeName);
|
|
|
|
}
|
|
|
|
if (dwNumComponents){
|
|
|
|
szLDAPDn = (LPWSTR)AllocADsMem((wcslen(szADsPathName) +1)*sizeof(WCHAR));
|
|
|
|
if (!szLDAPDn) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
switch (pObjectInfo->dwPathType) {
|
|
|
|
case PATHTYPE_X500:
|
|
default:
|
|
for (i = 0; i < dwNumComponents; i++) {
|
|
|
|
AppendComponent(
|
|
szLDAPDn,
|
|
&(pObjectInfo->ComponentArray[i])
|
|
);
|
|
|
|
if (i < (dwNumComponents - 1)){
|
|
_tcscat(szLDAPDn, TEXT(","));
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case PATHTYPE_WINDOWS:
|
|
for (i = dwNumComponents; i > 0; i--) {
|
|
|
|
AppendComponent(
|
|
szLDAPDn,
|
|
&(pObjectInfo->ComponentArray[i-1])
|
|
);
|
|
|
|
if ((i - 1) > 0){
|
|
_tcscat(szLDAPDn, TEXT(","));
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (szLDAPServer && *szLDAPServer) {
|
|
*pszLDAPServer = szLDAPServer;
|
|
}
|
|
|
|
if (szLDAPDn && *szLDAPDn) {
|
|
*pszLDAPDn = szLDAPDn;
|
|
}
|
|
|
|
*pdwPort = dwPortNumber;
|
|
|
|
error:
|
|
|
|
if (szLDAPServer && (*szLDAPServer == NULL)) {
|
|
FreeADsMem(szLDAPServer);
|
|
}
|
|
|
|
if (szLDAPDn && (*szLDAPDn == NULL)) {
|
|
FreeADsMem(szLDAPDn);
|
|
}
|
|
|
|
FreeObjectInfo( &ObjectInfo );
|
|
|
|
RRETURN(hr);
|
|
|
|
}
|
|
|
|
|
|
HRESULT
|
|
BuildADsPathFromLDAPPath2(
|
|
DWORD dwServerPresent,
|
|
LPWSTR szADsNamespace,
|
|
LPWSTR szLDAPServer,
|
|
DWORD dwPort,
|
|
LPWSTR szLDAPDn,
|
|
LPWSTR * ppszADsPathName
|
|
)
|
|
{
|
|
LPWSTR pszADsPathName = NULL;
|
|
HRESULT hr = S_OK;
|
|
DWORD dwLen;
|
|
WCHAR szPort[32];
|
|
LPWSTR pszDisplayDN = NULL;
|
|
|
|
hr = GetDisplayName(
|
|
szLDAPDn,
|
|
&pszDisplayDN
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
dwLen = STRING_LENGTH(szADsNamespace) +
|
|
STRING_LENGTH(szLDAPServer) +
|
|
STRING_LENGTH(pszDisplayDN) +
|
|
STRING_LENGTH(L"//") +
|
|
STRING_LENGTH(L"/") +
|
|
1;
|
|
|
|
if (IS_EXPLICIT_PORT(dwPort) ) {
|
|
wsprintf(szPort, L":%d", dwPort);
|
|
dwLen += STRING_LENGTH(szPort);
|
|
}
|
|
|
|
|
|
pszADsPathName = (LPWSTR) AllocADsMem( dwLen * sizeof(WCHAR) );
|
|
|
|
if(!pszADsPathName) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto error;
|
|
}
|
|
|
|
wsprintf(pszADsPathName,L"%s//", szADsNamespace);
|
|
|
|
if (dwServerPresent) {
|
|
|
|
if (szLDAPServer && *szLDAPServer) {
|
|
|
|
wcscat(pszADsPathName, szLDAPServer);
|
|
|
|
if (IS_EXPLICIT_PORT(dwPort) ) {
|
|
|
|
wsprintf(szPort, L":%d", dwPort);
|
|
wcscat(pszADsPathName, szPort);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pszDisplayDN && *pszDisplayDN) {
|
|
|
|
wcscat(pszADsPathName, L"/");
|
|
wcscat(pszADsPathName, pszDisplayDN);
|
|
|
|
}
|
|
|
|
}else {
|
|
|
|
if (pszDisplayDN && *pszDisplayDN) {
|
|
wcscat(pszADsPathName, pszDisplayDN);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
*ppszADsPathName = pszADsPathName;
|
|
|
|
error:
|
|
if (pszDisplayDN) {
|
|
FreeADsMem(pszDisplayDN);
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
GetNamespaceFromADsPath(
|
|
LPWSTR szADsPath,
|
|
LPWSTR pszNamespace
|
|
)
|
|
{
|
|
LPWSTR pszTemp;
|
|
|
|
// Get the namespace name
|
|
|
|
pszTemp = _tcschr( szADsPath, TEXT(':'));
|
|
if (!pszTemp) {
|
|
RRETURN(E_FAIL);
|
|
}
|
|
_tcsncpy (pszNamespace, szADsPath, (int)(pszTemp - szADsPath));
|
|
pszNamespace[pszTemp - szADsPath] = L'\0';
|
|
|
|
RRETURN(S_OK);
|
|
|
|
}
|
|
|
|
//
|
|
// Change the separator of a DN from '\' to '/' so that it can be used in
|
|
// an ADsPath
|
|
|
|
HRESULT
|
|
ChangeSeparator(
|
|
LPWSTR pszDN
|
|
)
|
|
{
|
|
|
|
LPWSTR ptr;
|
|
|
|
if (pszDN) {
|
|
|
|
while (ptr = wcschr(pszDN, '\\')) {
|
|
*ptr = '/';
|
|
}
|
|
|
|
}
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
|