1377 lines
29 KiB
C++
1377 lines
29 KiB
C++
|
/*
|
||
|
File sdowrap.cpp
|
||
|
|
||
|
Implements a wrapper for the sdo server class based on
|
||
|
weijiang's rasuser.dll code.
|
||
|
|
||
|
Paul Mayfield, 6/8/98
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <windows.h>
|
||
|
#include <objbase.h>
|
||
|
|
||
|
#include "sdoias.h"
|
||
|
#include "sdolib.h"
|
||
|
#include "sdowrap.h"
|
||
|
#include "hashtab.h"
|
||
|
|
||
|
//
|
||
|
// Structure defines data returned as a profile
|
||
|
//
|
||
|
typedef struct _SDO_PROFILE
|
||
|
{
|
||
|
ISdo * pSdo; // sdo of profile
|
||
|
ISdoCollection * pCollection; // attributes
|
||
|
ISdoDictionaryOld * pDictionary; // associated dictionary
|
||
|
ISdoServiceControl * pServiceControl; // associated ias service
|
||
|
HANDLE hMap; // attribute map
|
||
|
} SDO_PROFILE;
|
||
|
|
||
|
//
|
||
|
// Structure maps sdo object to an id
|
||
|
//
|
||
|
typedef struct _SDO_TO_ID {
|
||
|
ISdo * pSdo;
|
||
|
ULONG ulId;
|
||
|
} SDO_TO_ID;
|
||
|
|
||
|
//
|
||
|
// Size of hash tables we'll use
|
||
|
//
|
||
|
#define SDO_HASH_SIZE 13
|
||
|
|
||
|
//
|
||
|
// External function prototypes
|
||
|
//
|
||
|
extern "C"
|
||
|
{
|
||
|
DWORD SdoTraceEx (DWORD dwErr, LPSTR pszTrace, ...);
|
||
|
|
||
|
PVOID SdoAlloc (
|
||
|
IN DWORD dwSize,
|
||
|
IN BOOL bZero);
|
||
|
|
||
|
VOID SdoFree (
|
||
|
IN PVOID pvData);
|
||
|
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
SdoCollectionGetNext(
|
||
|
IEnumVARIANT* pEnum,
|
||
|
ISdo** ppSdo);
|
||
|
|
||
|
ULONG SdoHashId (
|
||
|
IN HANDLE hId);
|
||
|
|
||
|
int SdoCompIds (
|
||
|
IN HANDLE hId,
|
||
|
IN HANDLE hSdoNode);
|
||
|
|
||
|
VOID SdoCleanupElement (
|
||
|
IN HANDLE hSdoNode);
|
||
|
|
||
|
DWORD
|
||
|
SdoCreateIdMap(
|
||
|
IN ISdoCollection * pCollection,
|
||
|
OUT PHANDLE phMap);
|
||
|
|
||
|
HRESULT
|
||
|
SdoProfileSetAttribute(
|
||
|
IN SDO_PROFILE* pProf,
|
||
|
IN VARIANT* pVar,
|
||
|
IN ULONG ulId);
|
||
|
|
||
|
//
|
||
|
// Strings
|
||
|
//
|
||
|
static const WCHAR pszIasService[] = L"IAS";
|
||
|
static const WCHAR pszRemoteAccessService[] = L"RemoteAccess";
|
||
|
|
||
|
//
|
||
|
// Macros
|
||
|
//
|
||
|
#define SDO_RELEASE(_x) {if (_x) ((_x)->Release());}
|
||
|
|
||
|
//
|
||
|
// Define a class to act as a wrapper for sdo
|
||
|
// server functionality.
|
||
|
//
|
||
|
class SdoMachine {
|
||
|
|
||
|
public:
|
||
|
// Construction/destruction
|
||
|
//
|
||
|
SdoMachine();
|
||
|
SdoMachine(BOOL bLocal);
|
||
|
~SdoMachine();
|
||
|
|
||
|
// Server connection
|
||
|
//
|
||
|
HRESULT Attach(
|
||
|
BSTR pszMachine);
|
||
|
|
||
|
// Get the machine sdo
|
||
|
//
|
||
|
ISdoMachine * GetMachine();
|
||
|
|
||
|
// Get the dictionary sdo
|
||
|
//
|
||
|
ISdoDictionaryOld * GetDictionary();
|
||
|
|
||
|
// Returns the ias service object
|
||
|
IUnknown * GetIasService();
|
||
|
IUnknown * GetRemoteAccessService();
|
||
|
|
||
|
// Obtain user objects
|
||
|
HRESULT GetUserSdo(
|
||
|
BSTR bstrUserName,
|
||
|
ISdo** ppUserSdo);
|
||
|
|
||
|
// Obtain profiles
|
||
|
HRESULT GetDefaultProfile(
|
||
|
ISdo ** ppProfileSdo);
|
||
|
|
||
|
protected:
|
||
|
|
||
|
// Returns the datastore that should be
|
||
|
// used for this machine
|
||
|
IASDATASTORE GetDataStore();
|
||
|
|
||
|
// Protected data
|
||
|
ISdoMachine * m_pMachine;
|
||
|
BOOL m_bDataStoreInitailzed;
|
||
|
BOOL m_bLocal;
|
||
|
IASDATASTORE m_IasDataStore;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Construct a server
|
||
|
//
|
||
|
SdoMachine::SdoMachine() {
|
||
|
m_pMachine = NULL;
|
||
|
m_bDataStoreInitailzed = FALSE;
|
||
|
m_bLocal = TRUE;
|
||
|
m_IasDataStore = DATA_STORE_LOCAL;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Construct a server
|
||
|
//
|
||
|
SdoMachine::SdoMachine(BOOL bLocal) {
|
||
|
m_pMachine = NULL;
|
||
|
m_bDataStoreInitailzed = FALSE;
|
||
|
m_bLocal = bLocal;
|
||
|
m_IasDataStore = (bLocal) ? DATA_STORE_LOCAL : DATA_STORE_DIRECTORY;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Cleanup a server
|
||
|
//
|
||
|
SdoMachine::~SdoMachine() {
|
||
|
if (m_pMachine)
|
||
|
m_pMachine->Release();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Attach to an SdoServer
|
||
|
//
|
||
|
HRESULT SdoMachine::Attach(
|
||
|
IN BSTR pszMachine)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
VARIANT var;
|
||
|
|
||
|
VariantInit(&var);
|
||
|
|
||
|
do {
|
||
|
// CoCreate the instance
|
||
|
hr = CoCreateInstance(
|
||
|
CLSID_SdoMachine,
|
||
|
NULL,
|
||
|
CLSCTX_INPROC_SERVER,
|
||
|
IID_ISdoMachine,
|
||
|
(void**)&m_pMachine);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
SdoTraceEx(0, "CoCreateInstance SdoMachine failed %x\n", hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Connect
|
||
|
hr = m_pMachine->Attach(pszMachine);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
SdoTraceEx(0, "SdoMachine::Attach failed %x\n", hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
// Cleanup
|
||
|
{
|
||
|
VariantClear(&var);
|
||
|
if ((FAILED(hr)) && (m_pMachine != NULL))
|
||
|
{
|
||
|
m_pMachine->Release();
|
||
|
m_pMachine = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Returns the machine sdo for this machine
|
||
|
//
|
||
|
ISdoMachine* SdoMachine::GetMachine() {
|
||
|
return m_pMachine;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Returns dictionary associated with this machine
|
||
|
//
|
||
|
ISdoDictionaryOld * SdoMachine::GetDictionary()
|
||
|
{
|
||
|
ISdoDictionaryOld * pRet = NULL;
|
||
|
IUnknown * pUnk = NULL;
|
||
|
HRESULT hr;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
hr = m_pMachine->GetDictionarySDO(&pUnk);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
SetLastError(hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
hr = pUnk->QueryInterface(IID_ISdoDictionaryOld, (VOID**)&pRet);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
SetLastError(hr);
|
||
|
break;
|
||
|
}
|
||
|
pRet->AddRef();
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
// Cleanup
|
||
|
{
|
||
|
SDO_RELEASE(pUnk);
|
||
|
SDO_RELEASE(pRet);
|
||
|
}
|
||
|
|
||
|
return pRet;
|
||
|
}
|
||
|
|
||
|
IUnknown * SdoMachine::GetIasService()
|
||
|
{
|
||
|
IUnknown * pRet = NULL;
|
||
|
HRESULT hr = S_OK;
|
||
|
BSTR bstrService = SysAllocString(pszIasService);
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if (bstrService == NULL)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
hr = m_pMachine->GetServiceSDO(
|
||
|
GetDataStore(),
|
||
|
bstrService,
|
||
|
&pRet);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
SetLastError(hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
// Cleanup
|
||
|
{
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
SDO_RELEASE(pRet);
|
||
|
}
|
||
|
|
||
|
if (bstrService)
|
||
|
{
|
||
|
SysFreeString(bstrService);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pRet;
|
||
|
}
|
||
|
|
||
|
IUnknown * SdoMachine::GetRemoteAccessService()
|
||
|
{
|
||
|
IUnknown * pRet = NULL;
|
||
|
HRESULT hr = S_OK;
|
||
|
BSTR bstrService = SysAllocString(pszRemoteAccessService);
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if (bstrService == NULL)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
hr = m_pMachine->GetServiceSDO(
|
||
|
GetDataStore(),
|
||
|
bstrService,
|
||
|
&pRet);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
SetLastError(hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
// Cleanup
|
||
|
{
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
SDO_RELEASE(pRet);
|
||
|
}
|
||
|
|
||
|
if (bstrService)
|
||
|
{
|
||
|
SysFreeString(bstrService);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Get a reference to the given user from the
|
||
|
// sdo server
|
||
|
//
|
||
|
HRESULT SdoMachine::GetUserSdo(
|
||
|
IN BSTR bstrUserName,
|
||
|
OUT ISdo** ppUserSdo)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
IUnknown* pUnkn = NULL;
|
||
|
|
||
|
// Validate parameters
|
||
|
if(!ppUserSdo)
|
||
|
{
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
if (! m_pMachine)
|
||
|
{
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
do {
|
||
|
// Get the user from the machine
|
||
|
hr = m_pMachine->GetUserSDO(GetDataStore(), bstrUserName, &pUnkn);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
SdoTraceEx (0,"GetUserSdo failed %x\n", hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Get the required interface
|
||
|
hr = pUnkn->QueryInterface(IID_ISdo, (void**)ppUserSdo);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
SdoTraceEx (0,"User has no SDO interface %x\n", hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
// Cleanup
|
||
|
{
|
||
|
if (pUnkn)
|
||
|
pUnkn->Release();
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Obtains default profile from the sdo
|
||
|
//
|
||
|
HRESULT
|
||
|
SdoMachine::GetDefaultProfile(
|
||
|
ISdo ** ppProfileSdo)
|
||
|
{
|
||
|
IDispatch* pDisp = NULL;
|
||
|
IEnumVARIANT* pEnum = NULL;
|
||
|
ISdo * pSdo = NULL;
|
||
|
IUnknown * pUnkn = NULL;
|
||
|
IUnknown *pUnknEnum = NULL;
|
||
|
ISdoCollection * pCollection = NULL;
|
||
|
PWCHAR bstrService = NULL;
|
||
|
VARIANT var;
|
||
|
HRESULT hr = S_OK;
|
||
|
INT iCmp;
|
||
|
|
||
|
// Make sure we're ready to go
|
||
|
if(! ppProfileSdo)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
if (! m_pMachine)
|
||
|
return E_FAIL;
|
||
|
|
||
|
VariantInit(&var);
|
||
|
|
||
|
do {
|
||
|
// Initialize the service name
|
||
|
bstrService = SysAllocString(pszIasService);
|
||
|
if (bstrService == NULL)
|
||
|
{
|
||
|
SdoTraceEx (0, "GetProfile: unable to alloc service name\n");
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Get the service SDO
|
||
|
pUnkn = GetRemoteAccessService();
|
||
|
if (pUnkn == NULL)
|
||
|
{
|
||
|
hr = GetLastError();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Get an SDO reference to the service object
|
||
|
hr = pUnkn->QueryInterface(IID_ISdo, (VOID**)&pSdo);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
SdoTraceEx (0,"GetProfile: no service sdo %x\n", hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Get the profiles collection for the service
|
||
|
hr = pSdo->GetProperty(
|
||
|
PROPERTY_IAS_PROFILES_COLLECTION,
|
||
|
&var);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
SdoTraceEx (0,"GetProfile: no profiles collection %x\n", hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// We're done with the service sdo
|
||
|
pSdo->Release();
|
||
|
pSdo = NULL;
|
||
|
|
||
|
// Get the collection interface to the profiles collection
|
||
|
hr = (V_DISPATCH(&var))->QueryInterface(
|
||
|
IID_ISdoCollection,
|
||
|
(VOID**)&pCollection);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
SdoTraceEx (0,"GetProfile: collec interface %x\n", hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Get an enumerator for the profiles collection
|
||
|
hr = pCollection->get__NewEnum(&pUnknEnum);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
SdoTraceEx (0,"GetProfile: no collec enumerator %x\n", hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Get the variant enumerator interface of the profiles collection
|
||
|
hr = pUnknEnum->QueryInterface(
|
||
|
IID_IEnumVARIANT,
|
||
|
(VOID**)&pEnum);
|
||
|
|
||
|
// Get the first profile
|
||
|
pEnum->Reset();
|
||
|
hr = SdoCollectionGetNext(pEnum, &pSdo);
|
||
|
if (hr != S_OK)
|
||
|
{
|
||
|
SdoTraceEx (0,"GetProfile: no profile %x\n", hr);
|
||
|
hr = DISP_E_MEMBERNOTFOUND;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Make sure there is only one profile
|
||
|
//
|
||
|
{
|
||
|
ISdo* pSdo2 = NULL;
|
||
|
HRESULT hr2 = S_OK;
|
||
|
|
||
|
hr2 = SdoCollectionGetNext(pEnum, &pSdo2);
|
||
|
SDO_RELEASE(pSdo2);
|
||
|
if (hr2 == S_OK)
|
||
|
{
|
||
|
SdoTraceEx(0, "GetProfile: multiple found, returning error\n");
|
||
|
hr = DISP_E_MEMBERNOTFOUND;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Done
|
||
|
*ppProfileSdo = pSdo;
|
||
|
pSdo = NULL;
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
// Cleanup
|
||
|
{
|
||
|
SDO_RELEASE (pDisp);
|
||
|
SDO_RELEASE (pSdo);
|
||
|
SDO_RELEASE (pEnum);
|
||
|
SDO_RELEASE (pUnkn);
|
||
|
SDO_RELEASE (pUnknEnum);
|
||
|
SDO_RELEASE (pCollection);
|
||
|
VariantClear(&var);
|
||
|
if (bstrService)
|
||
|
SysFreeString(bstrService);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the data store for this machine
|
||
|
//
|
||
|
IASDATASTORE SdoMachine::GetDataStore() {
|
||
|
VARIANT_BOOL vbDirectory = VARIANT_FALSE;
|
||
|
HRESULT hr;
|
||
|
|
||
|
if (! m_bDataStoreInitailzed)
|
||
|
{
|
||
|
do {
|
||
|
// Determine whether a local verses directory user should
|
||
|
// be loaded.
|
||
|
hr = m_pMachine->IsDirectoryAvailable(&vbDirectory);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
SdoTraceEx (0,"IsDirectoryAvailable failed %x\n", hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// If the user wants a local user, it's always ok to
|
||
|
// attempt to get it.
|
||
|
if (m_bLocal)
|
||
|
{
|
||
|
m_IasDataStore = DATA_STORE_LOCAL;
|
||
|
}
|
||
|
|
||
|
// Otherwise, a directory user is being requested
|
||
|
else
|
||
|
{
|
||
|
// Directory is available, go to the ds
|
||
|
if (vbDirectory == VARIANT_TRUE)
|
||
|
{
|
||
|
m_IasDataStore = DATA_STORE_DIRECTORY;
|
||
|
}
|
||
|
|
||
|
// Directory's not available, exit with error
|
||
|
else if (vbDirectory == VARIANT_FALSE)
|
||
|
{
|
||
|
m_IasDataStore = DATA_STORE_LOCAL;
|
||
|
SdoTraceEx(0, "GetUserSdo: DS user but no DS %x\n", hr);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
} while (FALSE);
|
||
|
|
||
|
// Remember that we've already calculated the data store
|
||
|
m_bDataStoreInitailzed = TRUE;
|
||
|
}
|
||
|
|
||
|
return m_IasDataStore;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Opens an sdo server and connects to it.
|
||
|
//
|
||
|
HRESULT WINAPI
|
||
|
SdoWrapOpenServer(
|
||
|
IN BSTR pszMachine,
|
||
|
IN BOOL bLocal,
|
||
|
OUT HANDLE* phSdoSrv)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
if(! phSdoSrv)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
*phSdoSrv = NULL;
|
||
|
|
||
|
// Build the machine wrapper for the given
|
||
|
// machine
|
||
|
SdoMachine* pSdoSrv = new SdoMachine(bLocal);
|
||
|
if(! pSdoSrv)
|
||
|
return E_OUTOFMEMORY;
|
||
|
|
||
|
// Attach the wrapper to the desired macine
|
||
|
hr = pSdoSrv->Attach(
|
||
|
pszMachine);
|
||
|
|
||
|
if(S_OK == hr)
|
||
|
*phSdoSrv = (HANDLE)pSdoSrv;
|
||
|
else
|
||
|
delete pSdoSrv;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Closes out an open sdo server object
|
||
|
//
|
||
|
HRESULT WINAPI
|
||
|
SdoWrapCloseServer(
|
||
|
IN HANDLE hSdoSrv)
|
||
|
{
|
||
|
SdoMachine* pSdoSrv;
|
||
|
|
||
|
pSdoSrv = (SdoMachine*)hSdoSrv;
|
||
|
|
||
|
if (pSdoSrv)
|
||
|
delete pSdoSrv;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get a reference to a user in the sdo object
|
||
|
//
|
||
|
// returns S_OK, or error message from SDO
|
||
|
//
|
||
|
HRESULT WINAPI
|
||
|
SdoWrapOpenUser(
|
||
|
IN HANDLE hSdoSrv,
|
||
|
IN BSTR pszUser,
|
||
|
OUT HANDLE* phSdoObj)
|
||
|
{
|
||
|
SdoMachine* pSdoSrv = (SdoMachine*)hSdoSrv;
|
||
|
HRESULT hr = S_OK;
|
||
|
ISdo* pSdo = NULL;
|
||
|
|
||
|
if(!hSdoSrv || !phSdoObj)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
// Get the user object
|
||
|
hr = pSdoSrv->GetUserSdo(pszUser, &pSdo);
|
||
|
if(! FAILED(hr))
|
||
|
{
|
||
|
*phSdoObj = (HANDLE)pSdo;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Retrieves the default profile object
|
||
|
//
|
||
|
HRESULT WINAPI
|
||
|
SdoWrapOpenDefaultProfile (
|
||
|
IN HANDLE hSdoSrv,
|
||
|
OUT PHANDLE phProfile)
|
||
|
{
|
||
|
SdoMachine* pMachine = (SdoMachine*)hSdoSrv;
|
||
|
HRESULT hr = S_OK;
|
||
|
ISdo* pSdo = NULL;
|
||
|
ISdoCollection * pCollection = NULL;
|
||
|
ISdoDictionaryOld * pDictionary = NULL;
|
||
|
IUnknown * pUnkn = NULL;
|
||
|
ISdoServiceControl * pServiceControl = NULL;
|
||
|
HANDLE hMap = NULL;
|
||
|
SDO_PROFILE * pProf = NULL;
|
||
|
VARIANT var;
|
||
|
|
||
|
// Validate parameters
|
||
|
if ((pMachine == NULL) || (phProfile == NULL))
|
||
|
{
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
VariantInit(&var);
|
||
|
|
||
|
do
|
||
|
{
|
||
|
// Initialize a structure to hold the profile
|
||
|
pProf = (SDO_PROFILE*) SdoAlloc(sizeof(SDO_PROFILE), TRUE);
|
||
|
if (pProf == NULL)
|
||
|
{
|
||
|
hr = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Get the sdo reference to the default profile
|
||
|
// from the server
|
||
|
hr = pMachine->GetDefaultProfile(&pSdo);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
if (pSdo == NULL)
|
||
|
{
|
||
|
hr = E_FAIL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Get the collection of attributes
|
||
|
hr = pSdo->GetProperty(
|
||
|
PROPERTY_PROFILE_ATTRIBUTES_COLLECTION,
|
||
|
&var);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Get a reference to the IsdoCollection
|
||
|
hr = V_DISPATCH(&var)->QueryInterface(
|
||
|
IID_ISdoCollection,
|
||
|
(VOID**)&pCollection);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Load the attributes for the profile
|
||
|
hr = SdoCreateIdMap(pCollection, &hMap);
|
||
|
if (hr != NO_ERROR)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Get the dictionary for the profile
|
||
|
pDictionary = pMachine->GetDictionary();
|
||
|
if (pDictionary == NULL)
|
||
|
{
|
||
|
hr = GetLastError();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Get the service for the profile
|
||
|
pUnkn = pMachine->GetRemoteAccessService();
|
||
|
if (pUnkn == NULL)
|
||
|
{
|
||
|
hr = GetLastError();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// If this call fails, pServiceControl
|
||
|
// will be silently NULL which is what
|
||
|
// we want (it's not required).
|
||
|
pUnkn->QueryInterface(
|
||
|
IID_ISdoServiceControl,
|
||
|
(VOID**)&pServiceControl);
|
||
|
|
||
|
// Initialize the sdo control block.
|
||
|
pProf->pSdo = pSdo;
|
||
|
pProf->pCollection = pCollection;
|
||
|
pProf->pDictionary = pDictionary;
|
||
|
pProf->pServiceControl = pServiceControl;
|
||
|
pProf->hMap = hMap;
|
||
|
*phProfile = (HANDLE)pProf;
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
// Cleanup
|
||
|
{
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
HashTabCleanup(hMap);
|
||
|
SDO_RELEASE(pSdo);
|
||
|
SDO_RELEASE(pCollection);
|
||
|
SDO_RELEASE(pDictionary);
|
||
|
SDO_RELEASE(pServiceControl);
|
||
|
SdoFree(pProf);
|
||
|
}
|
||
|
SDO_RELEASE(pUnkn);
|
||
|
VariantClear(&var);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Closes an open sdo object
|
||
|
//
|
||
|
HRESULT WINAPI
|
||
|
SdoWrapClose(
|
||
|
IN HANDLE hSdoObj)
|
||
|
{
|
||
|
ISdo* pSdo = (ISdo*)hSdoObj;
|
||
|
|
||
|
if (pSdo)
|
||
|
pSdo->Release();
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Closes an open sdo profile
|
||
|
//
|
||
|
HRESULT WINAPI
|
||
|
SdoWrapCloseProfile(
|
||
|
IN HANDLE hProfile)
|
||
|
{
|
||
|
SDO_PROFILE* pProf = (SDO_PROFILE*)hProfile;
|
||
|
|
||
|
if (pProf)
|
||
|
{
|
||
|
// Cleanup the hashtab of values
|
||
|
if (pProf->hMap)
|
||
|
{
|
||
|
HashTabCleanup(pProf->hMap);
|
||
|
}
|
||
|
|
||
|
SDO_RELEASE(pProf->pSdo);
|
||
|
SDO_RELEASE(pProf->pCollection);
|
||
|
SDO_RELEASE(pProf->pDictionary);
|
||
|
SDO_RELEASE(pProf->pServiceControl);
|
||
|
|
||
|
SdoFree(pProf);
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Commits an sdo object
|
||
|
//
|
||
|
// bCommitChanges -- TRUE, all changes are saved,
|
||
|
// FALSE restore to previous commit
|
||
|
// returns S_OK or error message from SDO
|
||
|
//
|
||
|
HRESULT WINAPI
|
||
|
SdoWrapCommit(
|
||
|
IN HANDLE hSdoObj,
|
||
|
IN BOOL bCommitChanges)
|
||
|
{
|
||
|
ISdo* pSdo = (ISdo*)hSdoObj;
|
||
|
|
||
|
if (! bCommitChanges)
|
||
|
return pSdo->Restore();
|
||
|
|
||
|
return pSdo->Apply();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get's an sdo attribute
|
||
|
//
|
||
|
// when attribute is absent,
|
||
|
// V_VT(pVar) = VT_ERROR;
|
||
|
// V_ERROR(pVar) = DISP_E_PARAMNOTFOUND;
|
||
|
//
|
||
|
// returns S_OK or error message from SDO
|
||
|
//
|
||
|
HRESULT WINAPI
|
||
|
SdoWrapGetAttr(
|
||
|
IN HANDLE hSdoObj,
|
||
|
IN ULONG ulPropId,
|
||
|
OUT VARIANT* pVar)
|
||
|
{
|
||
|
ISdo* pSdo = (ISdo*)hSdoObj;
|
||
|
|
||
|
return pSdo->GetProperty(ulPropId, pVar);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Puts an sdo attribute
|
||
|
//
|
||
|
// returns S_OK or error message from SDO
|
||
|
//
|
||
|
HRESULT WINAPI
|
||
|
SdoWrapPutAttr(
|
||
|
IN HANDLE hSdoObj,
|
||
|
IN ULONG ulPropId,
|
||
|
OUT VARIANT* pVar)
|
||
|
{
|
||
|
ISdo* pSdo = (ISdo*)hSdoObj;
|
||
|
|
||
|
return pSdo->PutProperty(ulPropId, pVar);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Remove an attribute
|
||
|
//
|
||
|
// returns S_OK or error message from SDO
|
||
|
//
|
||
|
HRESULT WINAPI
|
||
|
SdoWrapRemoveAttr(
|
||
|
IN HANDLE hSdoObj,
|
||
|
IN ULONG ulPropId)
|
||
|
{
|
||
|
ISdo* pSdo = (ISdo*)hSdoObj;
|
||
|
VARIANT var;
|
||
|
|
||
|
VariantInit(&var);
|
||
|
V_VT(&var) = VT_EMPTY;
|
||
|
|
||
|
return pSdo->PutProperty(ulPropId, &var);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Reads in the set of profile values that we're interested
|
||
|
// in.
|
||
|
//
|
||
|
HRESULT
|
||
|
SdoWrapGetProfileValues(
|
||
|
IN HANDLE hProfile,
|
||
|
OUT VARIANT* pvarEp,
|
||
|
OUT VARIANT* pvarEt,
|
||
|
OUT VARIANT* pvarAt)
|
||
|
{
|
||
|
SDO_TO_ID * pNode = NULL;
|
||
|
SDO_PROFILE * pProf = (SDO_PROFILE*)hProfile;
|
||
|
|
||
|
// Validate
|
||
|
if (pProf == NULL)
|
||
|
{
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
// Initialize
|
||
|
V_VT(pvarEp) = VT_EMPTY;
|
||
|
V_VT(pvarEt) = VT_EMPTY;
|
||
|
V_VT(pvarAt) = VT_EMPTY;
|
||
|
|
||
|
// Read in the enc policy
|
||
|
pNode = NULL;
|
||
|
HashTabFind(
|
||
|
pProf->hMap,
|
||
|
(HANDLE)RAS_ATTRIBUTE_ENCRYPTION_POLICY,
|
||
|
(HANDLE*)&pNode);
|
||
|
if (pNode)
|
||
|
{
|
||
|
pNode->pSdo->GetProperty(PROPERTY_ATTRIBUTE_VALUE, pvarEp);
|
||
|
}
|
||
|
|
||
|
// Read in the enc type
|
||
|
pNode = NULL;
|
||
|
HashTabFind(
|
||
|
pProf->hMap,
|
||
|
(HANDLE)RAS_ATTRIBUTE_ENCRYPTION_TYPE,
|
||
|
(HANDLE*)&pNode);
|
||
|
if (pNode)
|
||
|
{
|
||
|
pNode->pSdo->GetProperty(PROPERTY_ATTRIBUTE_VALUE, pvarEt);
|
||
|
}
|
||
|
|
||
|
// Read in the auth type
|
||
|
pNode = NULL;
|
||
|
HashTabFind(
|
||
|
pProf->hMap,
|
||
|
(HANDLE)IAS_ATTRIBUTE_NP_AUTHENTICATION_TYPE,
|
||
|
(HANDLE*)&pNode);
|
||
|
if (pNode)
|
||
|
{
|
||
|
pNode->pSdo->GetProperty(PROPERTY_ATTRIBUTE_VALUE, pvarAt);
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Writes out the set of profile values that we're interested
|
||
|
// in.
|
||
|
//
|
||
|
HRESULT
|
||
|
SdoWrapSetProfileValues(
|
||
|
IN HANDLE hProfile,
|
||
|
IN VARIANT* pvarEp OPTIONAL,
|
||
|
IN VARIANT* pvarEt OPTIONAL,
|
||
|
IN VARIANT* pvarAt OPTIONAL)
|
||
|
{
|
||
|
SDO_PROFILE * pProf = (SDO_PROFILE*)hProfile;
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
// Validate
|
||
|
if (pProf == NULL)
|
||
|
{
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
do
|
||
|
{
|
||
|
// Write out the values
|
||
|
if (pvarEp)
|
||
|
{
|
||
|
hr = SdoProfileSetAttribute(
|
||
|
pProf,
|
||
|
pvarEp,
|
||
|
RAS_ATTRIBUTE_ENCRYPTION_POLICY);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pvarEt)
|
||
|
{
|
||
|
hr = SdoProfileSetAttribute(
|
||
|
pProf,
|
||
|
pvarEt,
|
||
|
RAS_ATTRIBUTE_ENCRYPTION_TYPE);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pvarAt)
|
||
|
{
|
||
|
hr = SdoProfileSetAttribute(
|
||
|
pProf,
|
||
|
pvarAt,
|
||
|
IAS_ATTRIBUTE_NP_AUTHENTICATION_TYPE);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Commit the values
|
||
|
hr = pProf->pSdo->Apply();
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Tell the service to restart so it reads in the
|
||
|
// new profile values we've set.
|
||
|
if (pProf->pServiceControl)
|
||
|
{
|
||
|
hr = pProf->pServiceControl->ResetService();
|
||
|
SdoTraceEx(0, "ResetService returned: %x!\n", hr);
|
||
|
hr = S_OK;
|
||
|
//if (FAILED (hr))
|
||
|
//{
|
||
|
// break;
|
||
|
//}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SdoTraceEx(0, "NO SERVICE CONTROL INTERFACE!\n");
|
||
|
}
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
// Cleanup
|
||
|
{
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Retrieves the next item from a collection
|
||
|
//
|
||
|
HRESULT
|
||
|
SdoCollectionGetNext(
|
||
|
IEnumVARIANT* pEnum,
|
||
|
ISdo** ppSdo)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
DWORD dwRetrieved = 1;
|
||
|
VARIANT var;
|
||
|
|
||
|
// Get the next value
|
||
|
VariantInit(&var);
|
||
|
hr = pEnum->Next(1, &var, &dwRetrieved);
|
||
|
if ( S_OK == hr ) {
|
||
|
hr = V_DISPATCH(&var)->QueryInterface(
|
||
|
IID_ISdo,
|
||
|
(void**)ppSdo);
|
||
|
}
|
||
|
VariantClear(&var);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Hash table functions that take advantage of
|
||
|
// SDO_TO_ID structures
|
||
|
//
|
||
|
ULONG SdoHashId (HANDLE hId) {
|
||
|
ULONG ulId = PtrToUlong(hId);
|
||
|
|
||
|
return (ulId % SDO_HASH_SIZE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Compare two ids
|
||
|
//
|
||
|
int SdoCompIds (HANDLE hId, HANDLE hSdoNode) {
|
||
|
ULONG ulId = PtrToUlong(hId);
|
||
|
SDO_TO_ID * pSdoNode = (SDO_TO_ID*)hSdoNode;
|
||
|
|
||
|
if (ulId == pSdoNode->ulId)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
else if (ulId > pSdoNode->ulId)
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Cleanup data in the hash table
|
||
|
//
|
||
|
VOID SdoCleanupElement (HANDLE hSdoNode) {
|
||
|
SDO_TO_ID * pSdoNode = (SDO_TO_ID*)hSdoNode;
|
||
|
|
||
|
if (pSdoNode) {
|
||
|
SDO_RELEASE(pSdoNode->pSdo);
|
||
|
delete pSdoNode;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Creates an attribute to id map given a collection
|
||
|
//
|
||
|
DWORD
|
||
|
SdoCreateIdMap(
|
||
|
IN ISdoCollection * pCollection,
|
||
|
OUT PHANDLE phMap)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
SDO_TO_ID * pMapNode = NULL;
|
||
|
VARIANT var, *pVar = NULL;
|
||
|
ULONG ulCount;
|
||
|
IUnknown * pUnk = NULL;
|
||
|
IEnumVARIANT * pEnum = NULL;
|
||
|
DWORD i;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
// Get the count to see if there are any attributes
|
||
|
hr = pCollection->get_Count((long*)&ulCount);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
if (ulCount == 0)
|
||
|
{
|
||
|
hr = S_OK;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Create the map
|
||
|
hr = HashTabCreate(
|
||
|
SDO_HASH_SIZE,
|
||
|
SdoHashId,
|
||
|
SdoCompIds,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
SdoCleanupElement,
|
||
|
phMap);
|
||
|
if (hr != NO_ERROR)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Get an attribute enumerator
|
||
|
hr = pCollection->get__NewEnum(&pUnk);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Get the enum variant interface for the enumerator
|
||
|
hr = pUnk->QueryInterface(IID_IEnumVARIANT, (void**)&pEnum);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Create a buffer large enough to hold the result
|
||
|
// of the enumeration.
|
||
|
pVar = new VARIANT[ulCount];
|
||
|
if(!pVar)
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
// Initialize the buffer
|
||
|
for(i = 0; i < ulCount; i++)
|
||
|
{
|
||
|
VariantInit(pVar + i);
|
||
|
}
|
||
|
|
||
|
// Enumerate
|
||
|
hr = pEnum->Reset();
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
hr = pEnum->Next(ulCount, pVar, &ulCount);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// Fill in the map
|
||
|
for(i = 0; i < ulCount; i++)
|
||
|
{
|
||
|
VariantInit(&var);
|
||
|
|
||
|
// Initialize the node in the map
|
||
|
pMapNode = new SDO_TO_ID;
|
||
|
if (! pMapNode)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Get the current attribute
|
||
|
hr = V_DISPATCH(pVar + i)->QueryInterface(
|
||
|
IID_ISdo,
|
||
|
(void**)&(pMapNode->pSdo));
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
delete pMapNode;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Get it's id
|
||
|
hr = pMapNode->pSdo->GetProperty(
|
||
|
PROPERTY_ATTRIBUTE_ID,
|
||
|
&var);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
delete pMapNode;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Map it
|
||
|
pMapNode->ulId = V_I4(&var);
|
||
|
HashTabInsert (
|
||
|
*phMap,
|
||
|
(HANDLE)UlongToPtr(pMapNode->ulId),
|
||
|
(HANDLE)pMapNode);
|
||
|
|
||
|
VariantClear(&var);
|
||
|
}
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
// Cleanup
|
||
|
{
|
||
|
if (pVar)
|
||
|
{
|
||
|
for(i = 0; i < ulCount; i++)
|
||
|
{
|
||
|
VariantClear(pVar + i);
|
||
|
}
|
||
|
|
||
|
delete[] pVar;
|
||
|
}
|
||
|
|
||
|
SDO_RELEASE(pUnk);
|
||
|
SDO_RELEASE(pEnum);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Sets a value in an attribute collection, adding it
|
||
|
// to the collection as needed.
|
||
|
//
|
||
|
HRESULT
|
||
|
SdoProfileSetAttribute(
|
||
|
IN SDO_PROFILE* pProf,
|
||
|
IN VARIANT* pVar,
|
||
|
IN ULONG ulPropId)
|
||
|
{
|
||
|
SDO_TO_ID * pNode = NULL;
|
||
|
ISdo * pSdo = NULL;
|
||
|
IDispatch * pDispatch = NULL;
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
// Search for the given attribute in the
|
||
|
// table.
|
||
|
pNode = NULL;
|
||
|
HashTabFind(
|
||
|
pProf->hMap,
|
||
|
(HANDLE)UlongToPtr(ulPropId),
|
||
|
(HANDLE*)&pNode);
|
||
|
|
||
|
// If attribute is found, then we have the sdo interface
|
||
|
// we need
|
||
|
if (pNode)
|
||
|
{
|
||
|
pSdo = pNode->pSdo;
|
||
|
}
|
||
|
|
||
|
// Otherwise, we need to add the value to the collection
|
||
|
else
|
||
|
{
|
||
|
// Create the attribute using the dictionary
|
||
|
hr = pProf->pDictionary->CreateAttribute(
|
||
|
(ATTRIBUTEID)ulPropId,
|
||
|
&pDispatch);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Add to the collection
|
||
|
hr = pProf->pCollection->Add(NULL, &pDispatch);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Get the sdo interface
|
||
|
hr = pDispatch->QueryInterface(IID_ISdo, (VOID**)&pSdo);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Update the hash table
|
||
|
pNode = new SDO_TO_ID;
|
||
|
if (!pNode)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Add ref so we can track the sdo in the hash table
|
||
|
pSdo->AddRef();
|
||
|
pNode->ulId = ulPropId;
|
||
|
pNode->pSdo = pSdo;
|
||
|
HashTabInsert (pProf->hMap, (HANDLE)UlongToPtr(ulPropId), (HANDLE)pNode);
|
||
|
}
|
||
|
|
||
|
// Set the attribute
|
||
|
pSdo->PutProperty(PROPERTY_ATTRIBUTE_VALUE, pVar);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
// Cleanup
|
||
|
{
|
||
|
SDO_RELEASE(pDispatch);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|