windows-nt/Source/XPSP1/NT/admin/dsweb/dsctl/dsctlobj.cpp

517 lines
13 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
// DsctlObj.cpp : Implementation of CdsctlApp and DLL registration.
#include "stdafx.h"
#include <wininet.h>
#include "dsctl.h"
#include "DsctlObj.h"
#include <activeds.h>
TCHAR DebugOut[MAX_PATH];
/////////////////////////////////////////////////////////////////////////////
//
STDMETHODIMP CDsctlObject::InterfaceSupportsErrorInfo(REFIID riid)
{
if (riid == IID_IDsctl)
return S_OK;
return S_FALSE;
}
//+----------------------------------------------------------------------------
//
// Method: CDsctlObject::DSGetObject
//
// Synopsis: Returns a DS object.
//
//-----------------------------------------------------------------------------
STDMETHODIMP
CDsctlObject::DSGetObject(VARIANT ADsPath, VARIANT * pRetVar)
{
HRESULT hr;
VariantInit(pRetVar);
// DebugBreak();
if (ADsPath.vt != VT_BSTR)
{
#ifdef DBG
OutputDebugString(TEXT("DSctl::DsGetObject not passed a string!\n"));
#endif
pRetVar->vt = VT_ERROR;
pRetVar->scode = E_INVALIDARG;
return E_INVALIDARG;
}
m_Path = SysAllocString(ADsPath.bstrVal);
if (m_Path == NULL)
{
#ifdef DBG
OutputDebugString(TEXT("DSctl::DsGetObject allocation failed!\n"));
#endif
pRetVar->vt = VT_ERROR;
pRetVar->scode = E_OUTOFMEMORY;
return E_OUTOFMEMORY;
}
#ifdef DBG
wsprintf(DebugOut, TEXT("DSctl::DsGetObject: Path to object is: %ws\n"),
m_Path);
OutputDebugString(DebugOut);
#endif
hr = ADsGetObject(m_Path, IID_IDispatch, (void **)&pRetVar->pdispVal);
if (FAILED(hr))
{
#ifdef DBG
wsprintf(DebugOut,
TEXT("DSctl::DsGetObject: ADsGetObject returned: %lx\n"), hr);
OutputDebugString(DebugOut);
#endif
pRetVar->vt = VT_ERROR;
pRetVar->scode = E_FAIL;
return E_FAIL;
}
#ifdef DBG
wsprintf(DebugOut,
TEXT("DSctl::DsGetObject - Returning Object: 0x%x\n\n"),
pRetVar->pdispVal);
OutputDebugString(DebugOut);
#endif
pRetVar->vt = VT_DISPATCH;
return S_OK;
}
//+----------------------------------------------------------------------------
//
// Method: CDsctlObject::DSGetEnum
//
// Synopsis: Returns a container enumerator
//
//-----------------------------------------------------------------------------
STDMETHODIMP
CDsctlObject::DSGetEnum(VARIANT ADsPath, VARIANT* retval)
{
HRESULT hr;
VARIANT vaResult;
IADsContainer *pCont;
VariantInit(&vaResult);
if (ADsPath.vt == VT_BSTR) {
m_Path = SysAllocString(ADsPath.bstrVal);
} else {
vaResult.vt = VT_ERROR;
vaResult.scode = E_FAIL;
#ifdef DBG
OutputDebugString(TEXT("DSctl: DSGetEnum not passed a string path\n"));
#endif
*retval = vaResult;
return S_OK;
}
// DebugBreak();
#ifdef DBG
OutputDebugString(TEXT("DSctl: GetEnum entered...\n"));
wsprintf (DebugOut, TEXT("DSctl: ptr to object is: %lx\n"), &ADsPath);
OutputDebugString(DebugOut);
wsprintf (DebugOut, TEXT("DSctl: Path to object is: %ws\n"), ADsPath.bstrVal);
OutputDebugString(DebugOut);
#endif
hr = ADsGetObject(m_Path, IID_IADsContainer,(void **)&pCont);
if (SUCCEEDED(hr)) {
hr = ADsBuildEnumerator(pCont,(IEnumVARIANT**)&vaResult.punkVal);
if (SUCCEEDED(hr))
vaResult.vt = VT_UNKNOWN;
else {
vaResult.vt = VT_ERROR;
vaResult.scode = E_FAIL;
#ifdef DBG
wsprintf(DebugOut,
TEXT("DSctl: OleDSBuildEnumerator returned: %lx\n"), hr);
OutputDebugString(DebugOut);
#endif
}
} else {
vaResult.vt = VT_ERROR;
vaResult.scode = E_FAIL;
#ifdef DBG
wsprintf (DebugOut, TEXT("DSctl: OleDSGetObject returned: %lx\n"), hr);
OutputDebugString(DebugOut);
#endif
}
*retval = vaResult;
return S_OK;
}
//+----------------------------------------------------------------------------
//
// Method: CDsctlObject::DSGetMemberEnum
//
// Synopsis: Returns a members (group) object enumerator
//
//-----------------------------------------------------------------------------
STDMETHODIMP
CDsctlObject::DSGetMemberEnum(VARIANT ObjectPtr, VARIANT* retval)
{
#ifdef DBG
OutputDebugString(TEXT("DSctl: GetMemberEnum entered...\n"));
#endif
VARIANT vaResult;
VariantInit(&vaResult);
IUnknown * pDisp;
//
// Get the DS object pointer.
//
if (ObjectPtr.vt == VT_DISPATCH || ObjectPtr.vt == VT_UNKNOWN)
{
pDisp = ObjectPtr.pdispVal;
}
else
{
if (ObjectPtr.vt == (VT_BYREF | VT_VARIANT))
{
if ((ObjectPtr.pvarVal)->vt == VT_DISPATCH ||
(ObjectPtr.pvarVal)->vt == VT_UNKNOWN)
{
pDisp = (ObjectPtr.pvarVal)->pdispVal;
}
else
{
vaResult.vt = VT_ERROR;
vaResult.scode = E_FAIL;
*retval = vaResult;
return S_OK;
}
}
}
IADsMembers * pDsMembers;
HRESULT hr = pDisp->QueryInterface(IID_IADsMembers, (void **)&pDsMembers);
if (FAILED(hr))
{
vaResult.vt = VT_ERROR;
vaResult.scode = E_FAIL;
*retval = vaResult;
return S_OK;
}
hr = pDsMembers->get__NewEnum((IUnknown **)&vaResult.punkVal);
if (SUCCEEDED(hr)) {
vaResult.vt = VT_UNKNOWN;
} else {
vaResult.vt = VT_ERROR;
vaResult.scode = E_FAIL;
#ifdef DBG
wsprintf(DebugOut,
TEXT("DSctl: OleDSBuildEnumerator returned: %lx\n"), hr);
OutputDebugString(DebugOut);
#endif
}
pDsMembers->Release();
*retval = vaResult;
return S_OK;
}
//+----------------------------------------------------------------------------
//
// Method: CDsctlObject::DSEnumNext
//
// Synopsis: Iterates through the enumeration sequence
//
//-----------------------------------------------------------------------------
STDMETHODIMP
CDsctlObject::DSEnumNext(VARIANT Enum, VARIANT* retval)
{
HRESULT hr;
VARIANT vaResult;
ULONG iCount;
VariantInit(&vaResult);
if (Enum.punkVal == NULL) {
vaResult.vt = VT_ERROR;
vaResult.scode = E_FAIL;
} else {
//DebugBreak();
hr = ADsEnumerateNext((IEnumVARIANT*)Enum.punkVal,1,&vaResult,&iCount);
if (!SUCCEEDED(hr)) {
ADsFreeEnumerator((IEnumVARIANT*)Enum.punkVal);
vaResult.vt = VT_ERROR;
vaResult.scode = E_FAIL;
}
}
*retval = vaResult;
return S_OK;
}
//+----------------------------------------------------------------------------
//
// Method: CDsctlObject::DSIsContainer
//
// Synopsis: Checks if the object is a container.
//
//-----------------------------------------------------------------------------
STDMETHODIMP
CDsctlObject::DSIsContainer(VARIANT ObjectPtr, VARIANT* retval)
{
VARIANT vaResult;
#ifdef DBG
OutputDebugString(TEXT("Entering CDsctlObject::DSIsContainer.\n"));
#endif
VariantInit(&vaResult);
vaResult.vt = VT_BOOL;
vaResult.boolVal = VARIANT_FALSE;
IUnknown * pDisp;
//
// Get the DS object pointer.
//
if (ObjectPtr.vt == VT_DISPATCH || ObjectPtr.vt == VT_UNKNOWN)
{
pDisp = ObjectPtr.pdispVal;
}
else
{
if (ObjectPtr.vt == (VT_BYREF | VT_VARIANT))
{
if ((ObjectPtr.pvarVal)->vt == VT_DISPATCH ||
(ObjectPtr.pvarVal)->vt == VT_UNKNOWN)
{
pDisp = (ObjectPtr.pvarVal)->pdispVal;
}
else
{
//
// If we don't know what sort of argument we received, then
// just return FALSE.
//
#ifdef DBG
OutputDebugString(TEXT("DSIsContainer - can't make sense of argument!\n"));
#endif
*retval = vaResult;
return S_OK;
}
}
}
IADs * pDsObject;
HRESULT hr = pDisp->QueryInterface(IID_IADs, (void **)&pDsObject);
if (SUCCEEDED(hr))
{
//pDisp->Release();
}
else
{
#ifdef DBG
OutputDebugString(TEXT("DSIsContainer - QI for IID_IADs failed!\n"));
#endif
*retval = vaResult;
return S_OK;
}
BSTR bstrSchema;
IADsClass * pDsClass;
VARIANT_BOOL bIsContainer;
//
// Objects are containers if their schema says they are containers...
//
if (SUCCEEDED(pDsObject->get_Schema( &bstrSchema )))
{
if (SUCCEEDED(ADsGetObject(bstrSchema, IID_IADsClass, (LPVOID *)&pDsClass)))
{
if (SUCCEEDED(pDsClass->get_Container(&bIsContainer)))
{
vaResult.boolVal = bIsContainer;
#ifdef DBG
wsprintf(DebugOut, TEXT("DSIsContainer returned: %lx\n"),
bIsContainer);
OutputDebugString(DebugOut);
#endif
}
pDsClass->Release();
}
SysFreeString(bstrSchema);
}
else
{
// If the get_Schema fails, we can assume it's a container (says yihsins)
vaResult.boolVal = VARIANT_TRUE;
#ifdef DBG
OutputDebugString(TEXT("DSIsContainer returning TRUE because get_Schema failed.\n"));
#endif
}
pDsObject->Release();
*retval = vaResult;
#ifdef DBG
OutputDebugString(TEXT("Exiting CDsctlObject::DSIsContainer\n"));
#endif
return S_OK;
}
//+----------------------------------------------------------------------------
//
// Method: CDsctlObject::DSGetLastError
//
// Synopsis: Checks ADs extended error.
//
//-----------------------------------------------------------------------------
STDMETHODIMP
CDsctlObject::DSGetLastError(VARIANT* retval)
{
VARIANT vaResult;
#ifdef DBG
OutputDebugString(TEXT("Entering CDsctlObject::DSGetLastError.\n"));
#endif
VariantInit(&vaResult);
vaResult.vt = VT_EMPTY;
vaResult.vt = VT_BSTR;
*retval = vaResult;
//
// There doesn't seem to be a way to detect if the returned string is
// truncated. Hopefully, this size will be large enough (the function
// header, in oleds\router\oledserr.cxx, says that 256 bytes is the
// recommended minimum for the error buffer and that the returned string
// will always be null terminated).
//
# define ERRBUFSIZE 512
DWORD dwErr;
WCHAR wszErrBuf[ERRBUFSIZE];
HRESULT hr = ADsGetLastError(&dwErr,
wszErrBuf,
ERRBUFSIZE,
NULL,
0);
if (FAILED(hr))
{
#ifdef DBG
wsprintf(DebugOut, TEXT("DSctl: ADsGetLastError returned: %lx\n"), hr);
OutputDebugString(DebugOut);
#endif
return hr;
}
wsprintf(DebugOut, TEXT("DSctl::ADsGetLastError: error = 0x%lx, errstr = %S\n"),
dwErr, wszErrBuf);
OutputDebugString(DebugOut);
BSTR bstr = SysAllocString(wszErrBuf);
if (bstr == NULL)
{
return E_OUTOFMEMORY;
}
vaResult.vt = VT_BSTR;
vaResult.bstrVal = bstr;
*retval = vaResult;
return S_OK;
}
//+----------------------------------------------------------------------------
//
// Method: CDsctlObject::DecodeURL
//
// Synopsis: Returns the decoded URL.
//
//-----------------------------------------------------------------------------
STDMETHODIMP
CDsctlObject::DecodeURL(VARIANT EncodedURL, VARIANT * pRetVar)
{
#ifdef DBG
wsprintf(DebugOut, TEXT("\nDSctl::DecodeURL: in param address: %x\n"),
&EncodedURL);
OutputDebugString(DebugOut);
#endif
//DebugBreak();
VariantInit(pRetVar);
if (EncodedURL.vt != VT_BSTR)
{
#ifdef DBG
OutputDebugString(TEXT("DSctl::DecodeURL not passed a string\n"));
#endif
pRetVar->vt = VT_ERROR;
pRetVar->scode = E_INVALIDARG;
return E_INVALIDARG;
}
#ifdef DBG
wsprintf(DebugOut, TEXT("DSctl::DecodeURL: input is %ws\n"),
EncodedURL.bstrVal);
OutputDebugString(DebugOut);
#endif
//
// DeURLize path
//
TCHAR szDecodedURL[INTERNET_MAX_URL_LENGTH];
DWORD dwLen = INTERNET_MAX_URL_LENGTH;
if (!InternetCanonicalizeUrl(EncodedURL.bstrVal, szDecodedURL, &dwLen,
ICU_DECODE | ICU_NO_ENCODE))
{
pRetVar->vt = VT_ERROR;
pRetVar->scode = E_FAIL;
#ifdef DBG
wsprintf(DebugOut,
TEXT("DSctl: InternetCanonicalizeUrl returned: %lx!\n"),
GetLastError());
OutputDebugString(DebugOut);
#endif
return E_FAIL;
}
if (_tcsstr(szDecodedURL, TEXT("ldap")) != NULL)
{
//
// Convert the protocol sequence to upper case.
//
_tcsncpy(szDecodedURL, TEXT("LDAP"), 4);
}
pRetVar->vt = VT_BSTR;
pRetVar->bstrVal = SysAllocString(szDecodedURL);
if (pRetVar->bstrVal == NULL)
{
#ifdef DBG
OutputDebugString(TEXT("DSctl::DecodeURL: allocation failed!\n"));
#endif
pRetVar->vt = VT_ERROR;
pRetVar->scode = E_OUTOFMEMORY;
return E_OUTOFMEMORY;
}
#ifdef DBG
wsprintf(DebugOut, TEXT("DSctl::DecodeURL: decoded URL is: %ws\n\n"),
pRetVar->bstrVal);
OutputDebugString(DebugOut);
#endif
return S_OK;
}