windows-nt/Source/XPSP1/NT/base/fs/hsm/hsmconn/hsmconn.cpp
2020-09-26 16:20:57 +08:00

1069 lines
28 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1996 Microsoft Corporation
© 1998 Seagate Software, Inc. All rights reserved.
Module Name:
HsmConn.cpp
Abstract:
This is the main implementation of the HsmConn dll. This dll provides
functions for accessing Directory Services and for connecting to
our services.
Author:
Rohde Wakefield [rohde] 21-Oct-1996
Revision History:
--*/
#include "stdafx.h"
#include <dsgetdc.h>
#include <lmcons.h>
#include <lmapibuf.h>
// Required by SECURITY.H
#define SECURITY_WIN32
#include <security.h>
// HsmConnPoint objects are used only here
#include "hsmservr.h"
//
// Tracing information
//
#define WSB_TRACE_IS WSB_TRACE_BIT_HSMCONN
//
// _Module instantiation for ATL
//
CComModule _Module;
/////////////////////////////////////////////////////////////////////////////
#define REG_PATH OLESTR("SOFTWARE\\Microsoft\\RemoteStorage")
#define REG_USE_DS OLESTR("UseDirectoryServices")
// Local data
static OLECHAR CNEqual[] = L"CN=";
static OLECHAR ComputersNodeName[] = L"Computers";
static OLECHAR DCsNodeName[] = L"Domain Controllers";
static OLECHAR ContainerType[] = L"Container";
static OLECHAR DisplaySpecifierName[] = L"displaySpecifier";
static OLECHAR GuidAttrName[] = L"remoteStorageGUID";
static OLECHAR RsDisplaySpecifierName[] = L"remoteStorageServicePoint-Display";
static OLECHAR RsNodeName[] = L"RemoteStorage";
static OLECHAR RsNodeType[] = L"remoteStorageServicePoint";
static OLECHAR ServiceBindAttrName[] = L"serviceBindingInformation";
static OLECHAR ServiceBindValue[] = L"Rsadmin.msc /ds ";
static ADS_ATTR_INFO aaInfo[2]; // For use in IDirectoryObject
static ADSVALUE adsValue[2]; // For use in IDirectoryObject
static OLECHAR DomainName[MAX_COMPUTERNAME_LENGTH];
static BOOL DSIsWritable = FALSE; // Default to "NO"
static BOOL UseDirectoryServices = FALSE; // Default to "NO"
#if defined(HSMCONN_DEBUG)
// We use this and OutputDebugString when we can't use our normal
// tracing.
OLECHAR dbg_string[200];
#endif
extern "C"
{
// Local functions
static void GetDSState(void);
static HRESULT HsmConnectToServer(HSMCONN_TYPE type,
const OLECHAR * Server, REFIID riid, void ** ppv);
static const OLECHAR *HsmConnTypeAsString(HSMCONN_TYPE type);
static GUID HsmConnTypeToGuid(IN HSMCONN_TYPE type);
static HRESULT HsmGetComputerNode(const OLECHAR * compName,
IADsContainer **pContainer);
static HRESULT HsmGetDsChild(IADsContainer * pContainer, const OLECHAR * Name,
REFIID riid, void **ppv);
BOOL WINAPI
DllMain (
IN HINSTANCE hInst,
IN ULONG ulReason,
LPVOID /*lpReserved*/
)
/*++
Routine Description:
This routine is called whenever a new process and thread attaches
to this DLL. Its purpose is to initialize the _Module object,
necessary for ATL.
Arguments:
hInst - HINSTANCE of this dll.
ulReason - Context of the attaching/detaching
Return Value:
non-zero - success
0 - prevent action
--*/
{
switch ( ulReason ) {
case DLL_PROCESS_ATTACH:
//
// Initialize the ATL module, and prevent
// any of the additional threads from sending
// notifications through
//
_Module.Init ( 0, hInst );
DisableThreadLibraryCalls ( hInst );
GetDSState();
break;
case DLL_PROCESS_DETACH:
//
// Tell ATL module to terminate
//
_Module.Term ( );
break;
}
return ( TRUE );
}
static HRESULT
HsmConnectToServer (
IN HSMCONN_TYPE type,
IN const OLECHAR * Server,
IN REFIID riid,
OUT void ** ppv
)
/*++
Routine Description:
Given a generic server (connected via HsmConnPoint class)
connect to it and return back the requested interface 'riid'.
Arguments:
type - Type of server to connect
Server - Name of machine on which server is running.
riid - The interface type to return.
ppv - Returned interface pointer of the Server.
Return Value:
S_OK - Connection made, Success.
E_NOINTERFACE - Requested interface not supported by Server.
E_POINTER - ppv is not a valid pointer.
E_OUTOFMEMORY - Low memory condition prevented connection.
HSM_E_NOT_READY - Engine is not running or not initialized yet
FSA_E_NOT_READY - Fsa is not running or not initialized yet
--*/
{
WsbTraceIn ( L"HsmConnectToServer",
L"type = '%ls' , Server = '%ls', riid = '%ls', ppv = 0x%p",
HsmConnTypeAsString ( type ), Server, WsbStringCopy ( WsbGuidAsString ( riid ) ), ppv );
HRESULT hr = S_OK;
try {
//
// Ensure parameters are valid
//
WsbAssert ( 0 != Server, E_POINTER );
WsbAssert ( 0 != ppv, E_POINTER );
//
// We will specify the provided HSM as the machine to contact,
// so Construct a COSERVERINFO with Server.
//
REFCLSID rclsid = CLSID_HsmConnPoint;
COSERVERINFO csi;
memset ( &csi, 0, sizeof ( csi ) );
csi.pwszName = (OLECHAR *) Server; // must cast to remove constness
//
// Build a MULTI_QI structure to obtain desired interface (necessary for
// CoCreateInstanceEx). In our case, we need only one interface.
//
MULTI_QI mqi[1];
memset ( mqi, 0, sizeof ( mqi ) );
mqi[0].pIID = &IID_IHsmConnPoint;
//
// The HsmConnPoint object ic created in the scope of the main HSM service and
// provides access for HSM server objects
//
WsbAffirmHr( CoCreateInstanceEx ( rclsid, 0, CLSCTX_SERVER, &csi, 1, mqi ) );
//
// Put returned interfaces in smart pointers so we
// don't leak a reference in case off throw
//
CComPtr<IHsmConnPoint> pConn;
if( SUCCEEDED( mqi[0].hr ) ) {
pConn = (IHsmConnPoint *)(mqi[0].pItf);
(mqi[0].pItf)->Release( );
hr = mqi[0].hr;
#if 0 // This is now done at the COM process-wide security layer
/* NOTE: In case that a per-connection security will be require,
the method CheckAccess should be implemented in CHsmConnPoint */
//
// Check the security first
//
WsbAffirmHr( mqi[1].hr );
WsbAffirmHr( pServer->CheckAccess( WSB_ACCESS_TYPE_ADMINISTRATOR ) );
#endif
// get the server object itself
switch (type) {
case HSMCONN_TYPE_HSM: {
WsbAffirmHr( pConn->GetEngineServer((IHsmServer **)ppv) );
break;
}
case HSMCONN_TYPE_FSA:
case HSMCONN_TYPE_RESOURCE: {
WsbAffirmHr( pConn->GetFsaServer((IFsaServer **)ppv) );
break;
}
default: {
WsbThrow ( E_INVALIDARG );
break;
}
}
} else {
// Make sure interface pointer is safe (NULL) when failing
*ppv = 0;
}
} WsbCatchAndDo ( hr,
// Make sure interface pointer is safe (NULL) when failing
*ppv = 0;
) // WsbCatchAndDo
WsbTraceOut ( L"HsmConnectToServer",
L"HRESULT = %ls, *ppv = %ls",
WsbHrAsString ( hr ), WsbPtrToPtrAsString ( ppv ) );
return ( hr );
}
HRESULT
HsmGetComputerNameFromADsPath(
IN const OLECHAR * szADsPath,
OUT OLECHAR ** pszComputerName
)
/*++
Routine Description:
Extract the computer name from the ADs path of the RemoteStorage node.
The assumption here is that the full ADs path will contain this substring:
"CN=RemoteStorage,CN=computername,CN=Computers"
where computername is what we want to return.
Arguments:
szADsPath - The ADs path.
pszComputerName - The returned computer name.
Return Value:
S_OK - Computer name returned OK.
--*/
{
HRESULT hr = S_FALSE;
WCHAR* pContainerNode;
WCHAR* pRSNode;
WsbTraceIn(OLESTR("HsmGetComputerNameFromADsPath"),
OLESTR("AdsPath = <%ls>"), szADsPath);
// Find the RemoteStorage node name and the computers node name
// in the ADs path. If the machine is a DC, then we have to
// check for a "Domain Controllers" level instead.
*pszComputerName = NULL;
pRSNode = wcsstr(szADsPath, RsNodeName);
pContainerNode = wcsstr(szADsPath, ComputersNodeName);
if(!pContainerNode) {
pContainerNode = wcsstr(szADsPath, DCsNodeName);
}
if (pRSNode && pContainerNode && pRSNode < pContainerNode) {
WCHAR* pWc;
// Find the "CN=" before the computer name
pWc = wcsstr(pRSNode, CNEqual);
if (pWc && pWc < pContainerNode) {
WCHAR* pComma;
// Skip the "CN="
pWc += wcslen(CNEqual);
// Find the "," after the computer name
pComma = wcschr(pWc, OLECHAR(','));
// Extract the computer name
if (pWc < pContainerNode && pComma && pComma < pContainerNode) {
int len;
len = (int)(pComma - pWc);
// Remove '$' from end of name???
if (0 < len && OLECHAR('$') == pWc[len - 1]) {
len--;
}
*pszComputerName = static_cast<OLECHAR *>(WsbAlloc(
(len + 1) * sizeof(WCHAR)));
if (*pszComputerName) {
wcsncpy(*pszComputerName, pWc, len);
(*pszComputerName)[len] = 0;
hr = S_OK;
}
}
}
}
WsbTraceOut (OLESTR("HsmGetComputerNameFromADsPath"),
OLESTR("HRESULT = %ls, Computername = <%ls>"),
WsbHrAsString(hr), (*pszComputerName ? *pszComputerName : OLESTR("")));
return(hr);
}
static HRESULT HsmGetComputerNode(
const OLECHAR * Name,
IADsContainer **ppContainer
)
/*++
Routine Description:
Return the computer node for the given computer name in the current Domain
Arguments:
Name - Computer name.
ppContainer - Returned interface pointer of the node.
Return Value:
S_OK - Success.
--*/
{
HRESULT hr = S_OK;
WsbTraceIn ( L"HsmGetComputerNode", L"Name = <%ls>", Name);
try {
WsbAssert(UseDirectoryServices, E_NOTIMPL);
WCHAR ComputerDn[MAX_PATH];
CWsbStringPtr temp;
ULONG ulen;
// Construct the SamCompatible (whatever that means) name
temp = DomainName;
temp.Append("\\");
temp.Append(Name);
temp.Append("$");
WsbTrace(L"HsmGetComputerNode: Domain\\computer = <%ls>\n",
static_cast<OLECHAR*>(temp));
// Translate that name to a fully qualified one
ulen = MAX_PATH;
ComputerDn[0] = WCHAR('\0');
if (TranslateName(temp, NameSamCompatible,
NameFullyQualifiedDN, ComputerDn, &ulen)) {
WsbTrace(L"HsmGetComputerNode: ComputerDn = <%ls>\n", ComputerDn);
// Get the computer node
temp = "LDAP://";
temp.Append(ComputerDn);
WsbTrace(L"HsmGetComputerNode: calling ADsGetObject with <%ls>\n",
static_cast<OLECHAR*>(temp));
WsbAffirmHr(ADsGetObject(temp, IID_IADsContainer,
(void**)ppContainer));
} else {
DWORD err = GetLastError();
WsbTrace(L"HsmGetComputerNode: TranslateName failed; ComputerDn = <%ls>, err = %ld\n",
ComputerDn, err);
if (err) {
WsbThrow(HRESULT_FROM_WIN32(err));
} else {
WsbThrow(E_UNEXPECTED);
}
}
WsbTrace(OLESTR("HsmGetComputerNode: got computer node\n"));
} WsbCatch( hr )
WsbTraceOut ( L"HsmGetComputerNode", L"HRESULT = %ls, *ppContainer = '%ls'",
WsbHrAsString ( hr ), WsbPtrToPtrAsString ( (void**)ppContainer ) );
return ( hr );
}
static HRESULT
HsmGetDsChild (
IN IADsContainer * pContainer,
IN const OLECHAR * Name,
IN REFIID riid,
OUT void ** ppv
)
/*++
Routine Description:
This routine returns back the requested child node.
Arguments:
pContainer - The parent container.
Name - The childs name (i.e. value of Name attribute or CN=Name)
riid - Desired interface to return.
ppv - Returned interface.
Return Value:
S_OK - Connection made, Success.
E_POINTER - Invalid pointer passed in as parameter.
E_* - Error
--*/
{
WsbTraceIn ( L"HsmGetDsChild",
L"pContainer = '0x%p', Name = '%ls', riid = '%ls', ppv = '0x%p'",
pContainer, Name, WsbGuidAsString ( riid ), ppv );
HRESULT hr = S_OK;
try {
CWsbStringPtr lName;
CComPtr<IDispatch> pDispatch;
// Validate params
WsbAssert ( 0 != pContainer, E_POINTER );
WsbAssert ( 0 != Name, E_POINTER );
WsbAssert ( 0 != ppv, E_POINTER );
WsbAssert(UseDirectoryServices, E_NOTIMPL);
// Check to see if the child exists
lName = Name;
hr = pContainer->GetObject(NULL, lName, &pDispatch);
if (FAILED(hr)) {
hr = S_OK;
lName.Prepend(CNEqual);
WsbAffirmHr(pContainer->GetObject(NULL, lName, &pDispatch));
}
// Convert to the correct interface
WsbAffirmHr(pDispatch->QueryInterface(riid, ppv));
} WsbCatch( hr )
WsbTraceOut ( L"HsmGetDsChild", L"HRESULT = %ls, *ppv = '%ls'",
WsbHrAsString ( hr ), WsbPtrToPtrAsString ( ppv ) );
return ( hr );
}
static const OLECHAR *
HsmConnTypeAsString (
IN HSMCONN_TYPE type
)
/*++
Routine Description:
Gives back a static string representing the connection type.
Note return type is strictly ANSI. This is intentional to make
macro work possible.
Arguments:
type - the type to return a string for.
Return Value:
NULL - invalid type passed in.
Otherwise, a valid char *.
--*/
{
#define STRINGIZE(_str) (OLESTR( #_str ))
#define RETURN_STRINGIZED_CASE(_case) \
case _case: \
return ( STRINGIZE( _case ) );
//
// Do the Switch
//
switch ( type ) {
RETURN_STRINGIZED_CASE( HSMCONN_TYPE_HSM );
RETURN_STRINGIZED_CASE( HSMCONN_TYPE_FSA );
RETURN_STRINGIZED_CASE( HSMCONN_TYPE_FILTER );
RETURN_STRINGIZED_CASE( HSMCONN_TYPE_RESOURCE );
default:
return ( OLESTR("Invalid Value") );
}
}
static GUID
HsmConnTypeToGuid(IN HSMCONN_TYPE type)
{
GUID serverGuid = GUID_NULL;
switch ( type ) {
case HSMCONN_TYPE_HSM:
serverGuid = CLSID_HsmServer;
break;
case HSMCONN_TYPE_FSA:
case HSMCONN_TYPE_RESOURCE:
serverGuid = CLSID_CFsaServerNTFS;
break;
}
return(serverGuid);
}
HRESULT
HsmConnectFromName (
IN HSMCONN_TYPE type,
IN const OLECHAR * Name,
IN REFIID riid,
OUT void ** ppv
)
/*++
Routine Description:
When given an name, connect and return the object representing the
Server, providing the specified interface.
Arguments:
type - The type of service / object we are connecting too.
Name - UNICODE string describing the Server to connect to.
riid - The interface type to return.
ppv - Returned interface pointer of the Server.
Return Value:
S_OK - Connection made, Success.
E_NOINTERFACE - Requested interface not supported by Server.
E_POINTER - ppv or Name is not a valid pointer.
E_OUTOFMEMORY - Low memory condition prevented connection.
E_INVALIDARG - The given name does not corespond to a known Server.
--*/
{
WsbTraceIn ( L"HsmConnectFromName",
L"type = '%ls', Name = '%ls', riid = '%ls', ppv = 0x%p",
HsmConnTypeAsString ( type ), Name, WsbGuidAsString ( riid ), ppv );
WsbTrace(OLESTR("HsmConnectFromName: UseDirectoryServices = %ls\n"),
WsbBoolAsString(UseDirectoryServices));
HRESULT hr = S_OK;
try {
BOOLEAN done = FALSE;
//
// Ensure parameters are valid
//
WsbAssert ( 0 != Name, E_POINTER );
WsbAssert ( 0 != ppv, E_POINTER );
if (!done) { // Try without Directory Services
CWsbStringPtr ComputerName = Name;
int i;
// Get the computer/server name
i = wcscspn(Name, OLESTR("\\"));
ComputerName[i] = 0;
if (HSMCONN_TYPE_RESOURCE == type) {
CWsbStringPtr Path;
OLECHAR * rscName;
CComPtr<IFsaResource> pFsaResource;
CComPtr<IFsaServer> pFsaServer;
WsbAffirmHr(HsmConnectToServer(type, ComputerName,
IID_IFsaServer, (void**)&pFsaServer));
// Determine if we have a logical name or a sticky name format.
// The logical name is a format like ("server\NTFS\d") and a sticky name
// format is like ("server\NTFS\Volume{GUID}\").
// Find the start of the last section and determine if there is only a single
// character after it or not.
rscName = wcsstr ( Name, L"NTFS\\" );
WsbAssert ( 0 != rscName, E_INVALIDARG );
// Now point just past the "NTFS\" part of the string. So we are pointing at
// either a single character, indicating the drive, or the "Volume{GUID}\".
rscName += 5;
Path = rscName;
if (wcslen (rscName) == 1) {
// Logical name ("server\NTFS\d") so convert to path and find resource
WsbAffirmHr(Path.Append(":\\"));
WsbAffirmHr(pFsaServer->FindResourceByPath(Path, &pFsaResource));
}
else {
// Sticky name ("server\NTFS\Volume{GUID}\") so find resource for it.
WsbAffirmHr(pFsaServer->FindResourceByStickyName(Path, &pFsaResource));
}
WsbAffirmHr(pFsaResource->QueryInterface(riid, ppv));
} else {
WsbAffirmHr(HsmConnectToServer(type, ComputerName, riid, ppv));
}
}
} WsbCatch ( hr )
WsbTraceOut ( L"HsmConnectFromName",
L"HRESULT = %ls, *ppv = %ls",
WsbHrAsString ( hr ), WsbPtrToPtrAsString ( ppv ) );
return ( hr );
}
HRESULT
HsmConnectFromId (
IN HSMCONN_TYPE type,
IN REFGUID rguid,
IN REFIID riid,
OUT void ** ppv
)
/*++
Routine Description:
Connects to the specified service or object. See HSMCONN_TYPE for
the types of services and objects.
Arguments:
type - The type of service / object we are connecting too.
rguid - The unique ID of the service / object to connect too.
riid - The interface type to return.
ppv - Returned interface pointer of the HSM Server.
Return Value:
S_OK - Connection made, Success.
E_NOINTERFACE - Requested interface not supported by HSM Server.
E_POINTER - ppv or Hsm is not a valid pointer.
E_OUTOFMEMORY - Low memory condition prevented connection.
E_INVALIDARG - The given ID and type do not correspond to a known
service or object.
--*/
{
WsbTraceIn ( L"HsmConnectFromId",
L"type = '%ls', rguid = '%ls', riid = '%ls', ppv = 0x%p",
HsmConnTypeAsString ( type ), WsbStringCopy ( WsbGuidAsString ( rguid ) ),
WsbStringCopy ( WsbGuidAsString ( riid ) ), ppv );
WsbTrace(OLESTR("HsmConnectFromId: UseDirectoryServices = %ls\n"),
WsbBoolAsString(UseDirectoryServices));
HRESULT hr = S_OK;
try {
BOOLEAN DSUsed = FALSE;
CWsbVariant guidVariant;
CComPtr < IADs > pObject;
CWsbStringPtr serverName;
CWsbVariant serverVariant;
//
// Ensure parameters are valid
//
WsbAssert ( 0 != ppv, E_POINTER );
switch ( type ) {
case HSMCONN_TYPE_HSM:
case HSMCONN_TYPE_FSA:
case HSMCONN_TYPE_FILTER:
if (DSUsed) {
} else {
WsbAffirmHr( WsbGetComputerName( serverName ) );
}
//
// Connect to the server
//
WsbAffirmHr ( HsmConnectToServer ( type, serverName, riid, ppv ) );
break;
case HSMCONN_TYPE_RESOURCE:
{
CComPtr< IFsaServer > pFsaServer;
GUID serverGuid;
serverGuid = HsmConnTypeToGuid(type);
WsbAffirmHr ( HsmConnectFromId ( HSMCONN_TYPE_FSA, serverGuid, IID_IFsaServer, (void**)&pFsaServer ) );
CComPtr< IFsaResource > pFsaResource;
WsbAffirmHr ( pFsaServer->FindResourceById ( rguid, &pFsaResource ) );
WsbAffirmHr ( pFsaResource->QueryInterface ( riid, ppv ) );
}
break;
default:
WsbThrow ( E_INVALIDARG );
}
} WsbCatch ( hr )
WsbTraceOut ( L"HsmConnectFromId",
L"HRESULT = %ls, *ppv = %ls",
WsbHrAsString ( hr ), WsbPtrToPtrAsString ( ppv ) );
return ( hr );
}
HRESULT
HsmPublish (
IN HSMCONN_TYPE type,
IN const OLECHAR * Name,
IN REFGUID rguidObjectId,
IN const OLECHAR * Server,
IN REFGUID rguid
)
/*++
Routine Description:
Publish (i.e. store) information about the service/object in
Directory Services.
Arguments:
type - The type of service/object.
Name - Name (possibly preceded by a subpath) of the Service/Object.
rguidObjectId - The ID that the object is known by.
Server - The server (computer name) on which the service actually exists.
For resources, this will be NULL since it is implicit in the
FSA specified by rguid.
rguid - For resources, the ID of the FSA. For services, the CLSID of
the service's class factory ie. CLSID_HsmServer.
Return Value:
S_OK - Connection made, Success.
E_POINTER - Name or Server is not a valid pointer.
E_OUTOFMEMORY - Low memory condition prevented connection.
--*/
{
HRESULT hr = S_OK;
WsbTraceIn ( L"HsmPublish",
L"type = '%ls', Name = '%ls', rguidObjectId = '%ls', Server = '%ls', rguid = '%ls'",
HsmConnTypeAsString ( type ), Name,
WsbStringCopy ( WsbGuidAsString ( rguidObjectId ) ), Server,
WsbStringCopy ( WsbGuidAsString ( rguid ) ) );
WsbTrace(OLESTR("HsmPublish: UseDirectoryServices = %ls\n"),
WsbBoolAsString(UseDirectoryServices));
try {
//
// Ensure parameters are valid
//
WsbAssert ( 0 != Name, E_POINTER );
WsbAssert ( ( HSMCONN_TYPE_RESOURCE == type ) || ( 0 != Server ), E_POINTER );
// Perhaps we should output a log event if the DS is not writable
// We now only publish the Engine service. Perhaps in the future we
// will publish additional information
if (HSMCONN_TYPE_HSM == type && UseDirectoryServices && DSIsWritable) {
CWsbStringPtr pathToName;
try {
DWORD aSet;
CWsbStringPtr guidString(rguidObjectId);
HRESULT hrGetNode;
CComPtr<IADsContainer> pComputer;
CComPtr<IDispatch> pDispatch;
CComPtr<IDirectoryObject> pDirObj;
CComPtr<IADs> pNode;
// Save the node name for the event log message
pathToName = Name;
pathToName.Append("\\");
pathToName.Append(RsNodeName);
// Get the computer node
WsbAffirmHr(HsmGetComputerNode(Name, &pComputer));
// See if we're already published
hrGetNode = HsmGetDsChild(pComputer, RsNodeName,
IID_IADs, (void**)&pNode);
// If not, add our node
if (HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT) == hrGetNode) {
CWsbBstrPtr relPath(RsNodeName);
relPath.Prepend(CNEqual);
WsbAffirmHr(pComputer->Create(RsNodeType, relPath, &pDispatch));
WsbAffirmHr(pDispatch->QueryInterface(IID_IADs,
(void**)&pNode));
// Force info out of cache
WsbAffirmHr(pNode->SetInfo());
} else {
WsbAffirmHr(hrGetNode);
}
// Set the GUID & ServiceBinding values
adsValue[0].dwType = ADSTYPE_CASE_IGNORE_STRING;
adsValue[0].CaseIgnoreString = (WCHAR*)guidString;
aaInfo[0].pszAttrName = GuidAttrName;
aaInfo[0].dwControlCode = ADS_ATTR_UPDATE;
aaInfo[0].dwADsType = ADSTYPE_CASE_IGNORE_STRING;
aaInfo[0].pADsValues = &adsValue[0];
aaInfo[0].dwNumValues = 1;
adsValue[1].dwType = ADSTYPE_CASE_IGNORE_STRING;
adsValue[1].CaseIgnoreString = ServiceBindValue;
aaInfo[1].pszAttrName = ServiceBindAttrName;
aaInfo[1].dwControlCode = ADS_ATTR_UPDATE;
aaInfo[1].dwADsType = ADSTYPE_CASE_IGNORE_STRING;
aaInfo[1].pADsValues = &adsValue[1];
aaInfo[1].dwNumValues = 1;
WsbAffirmHr(pNode->QueryInterface(IID_IDirectoryObject,
(void**)&pDirObj));
WsbAffirmHr(pDirObj->SetObjectAttributes(aaInfo, 2, &aSet));
WsbTrace(L"HsmPublish: after SetObjectAttributes, aSet = %ld\n",
aSet);
WsbLogEvent(WSB_MESSAGE_PUBLISH_IN_DS, 0, NULL,
static_cast<OLECHAR*>(pathToName), NULL);
} WsbCatchAndDo(hr,
WsbLogEvent(WSB_MESSAGE_PUBLISH_FAILED, 0, NULL,
static_cast<OLECHAR*>(pathToName), NULL);
hr = S_OK; // Don't stop service just for this
)
}
} WsbCatch ( hr )
WsbTraceOut ( L"HsmPublish", L"HRESULT = %ls", WsbHrAsString ( hr ) );
return ( hr );
}
// GetDSState - determine if we're using Directory Services or not
static void GetDSState(void)
{
BOOL CheckForDS = TRUE;
DOMAIN_CONTROLLER_INFO * dc_info;
DWORD size;
OLECHAR vstr[32];
DWORD status;
UseDirectoryServices = FALSE;
// Should we attempt to use directory services in this module?
// (Setting the registry value to "0" allows us to avoid Directory
// Services completely
if (S_OK == WsbGetRegistryValueString(NULL, REG_PATH, REG_USE_DS,
vstr, 32, &size)) {
OLECHAR *stop;
ULONG value;
value = wcstoul(vstr, &stop, 10 );
if (0 == value) {
CheckForDS = FALSE;
}
}
// Get the account domain name
WsbGetAccountDomainName(DomainName, MAX_COMPUTERNAME_LENGTH );
#if defined(HSMCONN_DEBUG)
swprintf(dbg_string, L"Account domain name = <%ls>\n", DomainName);
OutputDebugString(dbg_string);
#endif
// Check if Directory Services is available
if (CheckForDS) {
status = DsGetDcName(NULL, NULL, NULL, NULL,
DS_DIRECTORY_SERVICE_REQUIRED | DS_IS_FLAT_NAME |
DS_RETURN_FLAT_NAME, &dc_info);
#if defined(HSMCONN_DEBUG)
swprintf(dbg_string, L"DsGetDcName status = %d\n", status);
OutputDebugString(dbg_string);
#endif
if (NO_ERROR == status) {
#if defined(HSMCONN_DEBUG)
swprintf(dbg_string, L"dc_info->DomainName = <%ls>\n", dc_info->DomainName);
OutputDebugString(dbg_string);
#endif
if (dc_info->Flags & DS_DS_FLAG) {
wcscpy(DomainName, dc_info->DomainName);
UseDirectoryServices = TRUE;
if (dc_info->Flags & DS_WRITABLE_FLAG) {
DSIsWritable = TRUE;
}
}
NetApiBufferFree(dc_info);
}
}
#if defined(HSMCONN_DEBUG)
swprintf(dbg_string, L"dHsmConn - GetDSState: UseDirectoryServices = %ls\n",
WsbBoolAsString(UseDirectoryServices));
OutputDebugString(dbg_string);
#endif
}
} // extern "C"