Source code of Windows XP (NT5)
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.

1068 lines
28 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. 1998 Seagate Software, Inc. All rights reserved.
  4. Module Name:
  5. HsmConn.cpp
  6. Abstract:
  7. This is the main implementation of the HsmConn dll. This dll provides
  8. functions for accessing Directory Services and for connecting to
  9. our services.
  10. Author:
  11. Rohde Wakefield [rohde] 21-Oct-1996
  12. Revision History:
  13. --*/
  14. #include "stdafx.h"
  15. #include <dsgetdc.h>
  16. #include <lmcons.h>
  17. #include <lmapibuf.h>
  18. // Required by SECURITY.H
  19. #define SECURITY_WIN32
  20. #include <security.h>
  21. // HsmConnPoint objects are used only here
  22. #include "hsmservr.h"
  23. //
  24. // Tracing information
  25. //
  26. #define WSB_TRACE_IS WSB_TRACE_BIT_HSMCONN
  27. //
  28. // _Module instantiation for ATL
  29. //
  30. CComModule _Module;
  31. /////////////////////////////////////////////////////////////////////////////
  32. #define REG_PATH OLESTR("SOFTWARE\\Microsoft\\RemoteStorage")
  33. #define REG_USE_DS OLESTR("UseDirectoryServices")
  34. // Local data
  35. static OLECHAR CNEqual[] = L"CN=";
  36. static OLECHAR ComputersNodeName[] = L"Computers";
  37. static OLECHAR DCsNodeName[] = L"Domain Controllers";
  38. static OLECHAR ContainerType[] = L"Container";
  39. static OLECHAR DisplaySpecifierName[] = L"displaySpecifier";
  40. static OLECHAR GuidAttrName[] = L"remoteStorageGUID";
  41. static OLECHAR RsDisplaySpecifierName[] = L"remoteStorageServicePoint-Display";
  42. static OLECHAR RsNodeName[] = L"RemoteStorage";
  43. static OLECHAR RsNodeType[] = L"remoteStorageServicePoint";
  44. static OLECHAR ServiceBindAttrName[] = L"serviceBindingInformation";
  45. static OLECHAR ServiceBindValue[] = L"Rsadmin.msc /ds ";
  46. static ADS_ATTR_INFO aaInfo[2]; // For use in IDirectoryObject
  47. static ADSVALUE adsValue[2]; // For use in IDirectoryObject
  48. static OLECHAR DomainName[MAX_COMPUTERNAME_LENGTH];
  49. static BOOL DSIsWritable = FALSE; // Default to "NO"
  50. static BOOL UseDirectoryServices = FALSE; // Default to "NO"
  51. #if defined(HSMCONN_DEBUG)
  52. // We use this and OutputDebugString when we can't use our normal
  53. // tracing.
  54. OLECHAR dbg_string[200];
  55. #endif
  56. extern "C"
  57. {
  58. // Local functions
  59. static void GetDSState(void);
  60. static HRESULT HsmConnectToServer(HSMCONN_TYPE type,
  61. const OLECHAR * Server, REFIID riid, void ** ppv);
  62. static const OLECHAR *HsmConnTypeAsString(HSMCONN_TYPE type);
  63. static GUID HsmConnTypeToGuid(IN HSMCONN_TYPE type);
  64. static HRESULT HsmGetComputerNode(const OLECHAR * compName,
  65. IADsContainer **pContainer);
  66. static HRESULT HsmGetDsChild(IADsContainer * pContainer, const OLECHAR * Name,
  67. REFIID riid, void **ppv);
  68. BOOL WINAPI
  69. DllMain (
  70. IN HINSTANCE hInst,
  71. IN ULONG ulReason,
  72. LPVOID /*lpReserved*/
  73. )
  74. /*++
  75. Routine Description:
  76. This routine is called whenever a new process and thread attaches
  77. to this DLL. Its purpose is to initialize the _Module object,
  78. necessary for ATL.
  79. Arguments:
  80. hInst - HINSTANCE of this dll.
  81. ulReason - Context of the attaching/detaching
  82. Return Value:
  83. non-zero - success
  84. 0 - prevent action
  85. --*/
  86. {
  87. switch ( ulReason ) {
  88. case DLL_PROCESS_ATTACH:
  89. //
  90. // Initialize the ATL module, and prevent
  91. // any of the additional threads from sending
  92. // notifications through
  93. //
  94. _Module.Init ( 0, hInst );
  95. DisableThreadLibraryCalls ( hInst );
  96. GetDSState();
  97. break;
  98. case DLL_PROCESS_DETACH:
  99. //
  100. // Tell ATL module to terminate
  101. //
  102. _Module.Term ( );
  103. break;
  104. }
  105. return ( TRUE );
  106. }
  107. static HRESULT
  108. HsmConnectToServer (
  109. IN HSMCONN_TYPE type,
  110. IN const OLECHAR * Server,
  111. IN REFIID riid,
  112. OUT void ** ppv
  113. )
  114. /*++
  115. Routine Description:
  116. Given a generic server (connected via HsmConnPoint class)
  117. connect to it and return back the requested interface 'riid'.
  118. Arguments:
  119. type - Type of server to connect
  120. Server - Name of machine on which server is running.
  121. riid - The interface type to return.
  122. ppv - Returned interface pointer of the Server.
  123. Return Value:
  124. S_OK - Connection made, Success.
  125. E_NOINTERFACE - Requested interface not supported by Server.
  126. E_POINTER - ppv is not a valid pointer.
  127. E_OUTOFMEMORY - Low memory condition prevented connection.
  128. HSM_E_NOT_READY - Engine is not running or not initialized yet
  129. FSA_E_NOT_READY - Fsa is not running or not initialized yet
  130. --*/
  131. {
  132. WsbTraceIn ( L"HsmConnectToServer",
  133. L"type = '%ls' , Server = '%ls', riid = '%ls', ppv = 0x%p",
  134. HsmConnTypeAsString ( type ), Server, WsbStringCopy ( WsbGuidAsString ( riid ) ), ppv );
  135. HRESULT hr = S_OK;
  136. try {
  137. //
  138. // Ensure parameters are valid
  139. //
  140. WsbAssert ( 0 != Server, E_POINTER );
  141. WsbAssert ( 0 != ppv, E_POINTER );
  142. //
  143. // We will specify the provided HSM as the machine to contact,
  144. // so Construct a COSERVERINFO with Server.
  145. //
  146. REFCLSID rclsid = CLSID_HsmConnPoint;
  147. COSERVERINFO csi;
  148. memset ( &csi, 0, sizeof ( csi ) );
  149. csi.pwszName = (OLECHAR *) Server; // must cast to remove constness
  150. //
  151. // Build a MULTI_QI structure to obtain desired interface (necessary for
  152. // CoCreateInstanceEx). In our case, we need only one interface.
  153. //
  154. MULTI_QI mqi[1];
  155. memset ( mqi, 0, sizeof ( mqi ) );
  156. mqi[0].pIID = &IID_IHsmConnPoint;
  157. //
  158. // The HsmConnPoint object ic created in the scope of the main HSM service and
  159. // provides access for HSM server objects
  160. //
  161. WsbAffirmHr( CoCreateInstanceEx ( rclsid, 0, CLSCTX_SERVER, &csi, 1, mqi ) );
  162. //
  163. // Put returned interfaces in smart pointers so we
  164. // don't leak a reference in case off throw
  165. //
  166. CComPtr<IHsmConnPoint> pConn;
  167. if( SUCCEEDED( mqi[0].hr ) ) {
  168. pConn = (IHsmConnPoint *)(mqi[0].pItf);
  169. (mqi[0].pItf)->Release( );
  170. hr = mqi[0].hr;
  171. #if 0 // This is now done at the COM process-wide security layer
  172. /* NOTE: In case that a per-connection security will be require,
  173. the method CheckAccess should be implemented in CHsmConnPoint */
  174. //
  175. // Check the security first
  176. //
  177. WsbAffirmHr( mqi[1].hr );
  178. WsbAffirmHr( pServer->CheckAccess( WSB_ACCESS_TYPE_ADMINISTRATOR ) );
  179. #endif
  180. // get the server object itself
  181. switch (type) {
  182. case HSMCONN_TYPE_HSM: {
  183. WsbAffirmHr( pConn->GetEngineServer((IHsmServer **)ppv) );
  184. break;
  185. }
  186. case HSMCONN_TYPE_FSA:
  187. case HSMCONN_TYPE_RESOURCE: {
  188. WsbAffirmHr( pConn->GetFsaServer((IFsaServer **)ppv) );
  189. break;
  190. }
  191. default: {
  192. WsbThrow ( E_INVALIDARG );
  193. break;
  194. }
  195. }
  196. } else {
  197. // Make sure interface pointer is safe (NULL) when failing
  198. *ppv = 0;
  199. }
  200. } WsbCatchAndDo ( hr,
  201. // Make sure interface pointer is safe (NULL) when failing
  202. *ppv = 0;
  203. ) // WsbCatchAndDo
  204. WsbTraceOut ( L"HsmConnectToServer",
  205. L"HRESULT = %ls, *ppv = %ls",
  206. WsbHrAsString ( hr ), WsbPtrToPtrAsString ( ppv ) );
  207. return ( hr );
  208. }
  209. HRESULT
  210. HsmGetComputerNameFromADsPath(
  211. IN const OLECHAR * szADsPath,
  212. OUT OLECHAR ** pszComputerName
  213. )
  214. /*++
  215. Routine Description:
  216. Extract the computer name from the ADs path of the RemoteStorage node.
  217. The assumption here is that the full ADs path will contain this substring:
  218. "CN=RemoteStorage,CN=computername,CN=Computers"
  219. where computername is what we want to return.
  220. Arguments:
  221. szADsPath - The ADs path.
  222. pszComputerName - The returned computer name.
  223. Return Value:
  224. S_OK - Computer name returned OK.
  225. --*/
  226. {
  227. HRESULT hr = S_FALSE;
  228. WCHAR* pContainerNode;
  229. WCHAR* pRSNode;
  230. WsbTraceIn(OLESTR("HsmGetComputerNameFromADsPath"),
  231. OLESTR("AdsPath = <%ls>"), szADsPath);
  232. // Find the RemoteStorage node name and the computers node name
  233. // in the ADs path. If the machine is a DC, then we have to
  234. // check for a "Domain Controllers" level instead.
  235. *pszComputerName = NULL;
  236. pRSNode = wcsstr(szADsPath, RsNodeName);
  237. pContainerNode = wcsstr(szADsPath, ComputersNodeName);
  238. if(!pContainerNode) {
  239. pContainerNode = wcsstr(szADsPath, DCsNodeName);
  240. }
  241. if (pRSNode && pContainerNode && pRSNode < pContainerNode) {
  242. WCHAR* pWc;
  243. // Find the "CN=" before the computer name
  244. pWc = wcsstr(pRSNode, CNEqual);
  245. if (pWc && pWc < pContainerNode) {
  246. WCHAR* pComma;
  247. // Skip the "CN="
  248. pWc += wcslen(CNEqual);
  249. // Find the "," after the computer name
  250. pComma = wcschr(pWc, OLECHAR(','));
  251. // Extract the computer name
  252. if (pWc < pContainerNode && pComma && pComma < pContainerNode) {
  253. int len;
  254. len = (int)(pComma - pWc);
  255. // Remove '$' from end of name???
  256. if (0 < len && OLECHAR('$') == pWc[len - 1]) {
  257. len--;
  258. }
  259. *pszComputerName = static_cast<OLECHAR *>(WsbAlloc(
  260. (len + 1) * sizeof(WCHAR)));
  261. if (*pszComputerName) {
  262. wcsncpy(*pszComputerName, pWc, len);
  263. (*pszComputerName)[len] = 0;
  264. hr = S_OK;
  265. }
  266. }
  267. }
  268. }
  269. WsbTraceOut (OLESTR("HsmGetComputerNameFromADsPath"),
  270. OLESTR("HRESULT = %ls, Computername = <%ls>"),
  271. WsbHrAsString(hr), (*pszComputerName ? *pszComputerName : OLESTR("")));
  272. return(hr);
  273. }
  274. static HRESULT HsmGetComputerNode(
  275. const OLECHAR * Name,
  276. IADsContainer **ppContainer
  277. )
  278. /*++
  279. Routine Description:
  280. Return the computer node for the given computer name in the current Domain
  281. Arguments:
  282. Name - Computer name.
  283. ppContainer - Returned interface pointer of the node.
  284. Return Value:
  285. S_OK - Success.
  286. --*/
  287. {
  288. HRESULT hr = S_OK;
  289. WsbTraceIn ( L"HsmGetComputerNode", L"Name = <%ls>", Name);
  290. try {
  291. WsbAssert(UseDirectoryServices, E_NOTIMPL);
  292. WCHAR ComputerDn[MAX_PATH];
  293. CWsbStringPtr temp;
  294. ULONG ulen;
  295. // Construct the SamCompatible (whatever that means) name
  296. temp = DomainName;
  297. temp.Append("\\");
  298. temp.Append(Name);
  299. temp.Append("$");
  300. WsbTrace(L"HsmGetComputerNode: Domain\\computer = <%ls>\n",
  301. static_cast<OLECHAR*>(temp));
  302. // Translate that name to a fully qualified one
  303. ulen = MAX_PATH;
  304. ComputerDn[0] = WCHAR('\0');
  305. if (TranslateName(temp, NameSamCompatible,
  306. NameFullyQualifiedDN, ComputerDn, &ulen)) {
  307. WsbTrace(L"HsmGetComputerNode: ComputerDn = <%ls>\n", ComputerDn);
  308. // Get the computer node
  309. temp = "LDAP://";
  310. temp.Append(ComputerDn);
  311. WsbTrace(L"HsmGetComputerNode: calling ADsGetObject with <%ls>\n",
  312. static_cast<OLECHAR*>(temp));
  313. WsbAffirmHr(ADsGetObject(temp, IID_IADsContainer,
  314. (void**)ppContainer));
  315. } else {
  316. DWORD err = GetLastError();
  317. WsbTrace(L"HsmGetComputerNode: TranslateName failed; ComputerDn = <%ls>, err = %ld\n",
  318. ComputerDn, err);
  319. if (err) {
  320. WsbThrow(HRESULT_FROM_WIN32(err));
  321. } else {
  322. WsbThrow(E_UNEXPECTED);
  323. }
  324. }
  325. WsbTrace(OLESTR("HsmGetComputerNode: got computer node\n"));
  326. } WsbCatch( hr )
  327. WsbTraceOut ( L"HsmGetComputerNode", L"HRESULT = %ls, *ppContainer = '%ls'",
  328. WsbHrAsString ( hr ), WsbPtrToPtrAsString ( (void**)ppContainer ) );
  329. return ( hr );
  330. }
  331. static HRESULT
  332. HsmGetDsChild (
  333. IN IADsContainer * pContainer,
  334. IN const OLECHAR * Name,
  335. IN REFIID riid,
  336. OUT void ** ppv
  337. )
  338. /*++
  339. Routine Description:
  340. This routine returns back the requested child node.
  341. Arguments:
  342. pContainer - The parent container.
  343. Name - The childs name (i.e. value of Name attribute or CN=Name)
  344. riid - Desired interface to return.
  345. ppv - Returned interface.
  346. Return Value:
  347. S_OK - Connection made, Success.
  348. E_POINTER - Invalid pointer passed in as parameter.
  349. E_* - Error
  350. --*/
  351. {
  352. WsbTraceIn ( L"HsmGetDsChild",
  353. L"pContainer = '0x%p', Name = '%ls', riid = '%ls', ppv = '0x%p'",
  354. pContainer, Name, WsbGuidAsString ( riid ), ppv );
  355. HRESULT hr = S_OK;
  356. try {
  357. CWsbStringPtr lName;
  358. CComPtr<IDispatch> pDispatch;
  359. // Validate params
  360. WsbAssert ( 0 != pContainer, E_POINTER );
  361. WsbAssert ( 0 != Name, E_POINTER );
  362. WsbAssert ( 0 != ppv, E_POINTER );
  363. WsbAssert(UseDirectoryServices, E_NOTIMPL);
  364. // Check to see if the child exists
  365. lName = Name;
  366. hr = pContainer->GetObject(NULL, lName, &pDispatch);
  367. if (FAILED(hr)) {
  368. hr = S_OK;
  369. lName.Prepend(CNEqual);
  370. WsbAffirmHr(pContainer->GetObject(NULL, lName, &pDispatch));
  371. }
  372. // Convert to the correct interface
  373. WsbAffirmHr(pDispatch->QueryInterface(riid, ppv));
  374. } WsbCatch( hr )
  375. WsbTraceOut ( L"HsmGetDsChild", L"HRESULT = %ls, *ppv = '%ls'",
  376. WsbHrAsString ( hr ), WsbPtrToPtrAsString ( ppv ) );
  377. return ( hr );
  378. }
  379. static const OLECHAR *
  380. HsmConnTypeAsString (
  381. IN HSMCONN_TYPE type
  382. )
  383. /*++
  384. Routine Description:
  385. Gives back a static string representing the connection type.
  386. Note return type is strictly ANSI. This is intentional to make
  387. macro work possible.
  388. Arguments:
  389. type - the type to return a string for.
  390. Return Value:
  391. NULL - invalid type passed in.
  392. Otherwise, a valid char *.
  393. --*/
  394. {
  395. #define STRINGIZE(_str) (OLESTR( #_str ))
  396. #define RETURN_STRINGIZED_CASE(_case) \
  397. case _case: \
  398. return ( STRINGIZE( _case ) );
  399. //
  400. // Do the Switch
  401. //
  402. switch ( type ) {
  403. RETURN_STRINGIZED_CASE( HSMCONN_TYPE_HSM );
  404. RETURN_STRINGIZED_CASE( HSMCONN_TYPE_FSA );
  405. RETURN_STRINGIZED_CASE( HSMCONN_TYPE_FILTER );
  406. RETURN_STRINGIZED_CASE( HSMCONN_TYPE_RESOURCE );
  407. default:
  408. return ( OLESTR("Invalid Value") );
  409. }
  410. }
  411. static GUID
  412. HsmConnTypeToGuid(IN HSMCONN_TYPE type)
  413. {
  414. GUID serverGuid = GUID_NULL;
  415. switch ( type ) {
  416. case HSMCONN_TYPE_HSM:
  417. serverGuid = CLSID_HsmServer;
  418. break;
  419. case HSMCONN_TYPE_FSA:
  420. case HSMCONN_TYPE_RESOURCE:
  421. serverGuid = CLSID_CFsaServerNTFS;
  422. break;
  423. }
  424. return(serverGuid);
  425. }
  426. HRESULT
  427. HsmConnectFromName (
  428. IN HSMCONN_TYPE type,
  429. IN const OLECHAR * Name,
  430. IN REFIID riid,
  431. OUT void ** ppv
  432. )
  433. /*++
  434. Routine Description:
  435. When given an name, connect and return the object representing the
  436. Server, providing the specified interface.
  437. Arguments:
  438. type - The type of service / object we are connecting too.
  439. Name - UNICODE string describing the Server to connect to.
  440. riid - The interface type to return.
  441. ppv - Returned interface pointer of the Server.
  442. Return Value:
  443. S_OK - Connection made, Success.
  444. E_NOINTERFACE - Requested interface not supported by Server.
  445. E_POINTER - ppv or Name is not a valid pointer.
  446. E_OUTOFMEMORY - Low memory condition prevented connection.
  447. E_INVALIDARG - The given name does not corespond to a known Server.
  448. --*/
  449. {
  450. WsbTraceIn ( L"HsmConnectFromName",
  451. L"type = '%ls', Name = '%ls', riid = '%ls', ppv = 0x%p",
  452. HsmConnTypeAsString ( type ), Name, WsbGuidAsString ( riid ), ppv );
  453. WsbTrace(OLESTR("HsmConnectFromName: UseDirectoryServices = %ls\n"),
  454. WsbBoolAsString(UseDirectoryServices));
  455. HRESULT hr = S_OK;
  456. try {
  457. BOOLEAN done = FALSE;
  458. //
  459. // Ensure parameters are valid
  460. //
  461. WsbAssert ( 0 != Name, E_POINTER );
  462. WsbAssert ( 0 != ppv, E_POINTER );
  463. if (!done) { // Try without Directory Services
  464. CWsbStringPtr ComputerName = Name;
  465. int i;
  466. // Get the computer/server name
  467. i = wcscspn(Name, OLESTR("\\"));
  468. ComputerName[i] = 0;
  469. if (HSMCONN_TYPE_RESOURCE == type) {
  470. CWsbStringPtr Path;
  471. OLECHAR * rscName;
  472. CComPtr<IFsaResource> pFsaResource;
  473. CComPtr<IFsaServer> pFsaServer;
  474. WsbAffirmHr(HsmConnectToServer(type, ComputerName,
  475. IID_IFsaServer, (void**)&pFsaServer));
  476. // Determine if we have a logical name or a sticky name format.
  477. // The logical name is a format like ("server\NTFS\d") and a sticky name
  478. // format is like ("server\NTFS\Volume{GUID}\").
  479. // Find the start of the last section and determine if there is only a single
  480. // character after it or not.
  481. rscName = wcsstr ( Name, L"NTFS\\" );
  482. WsbAssert ( 0 != rscName, E_INVALIDARG );
  483. // Now point just past the "NTFS\" part of the string. So we are pointing at
  484. // either a single character, indicating the drive, or the "Volume{GUID}\".
  485. rscName += 5;
  486. Path = rscName;
  487. if (wcslen (rscName) == 1) {
  488. // Logical name ("server\NTFS\d") so convert to path and find resource
  489. WsbAffirmHr(Path.Append(":\\"));
  490. WsbAffirmHr(pFsaServer->FindResourceByPath(Path, &pFsaResource));
  491. }
  492. else {
  493. // Sticky name ("server\NTFS\Volume{GUID}\") so find resource for it.
  494. WsbAffirmHr(pFsaServer->FindResourceByStickyName(Path, &pFsaResource));
  495. }
  496. WsbAffirmHr(pFsaResource->QueryInterface(riid, ppv));
  497. } else {
  498. WsbAffirmHr(HsmConnectToServer(type, ComputerName, riid, ppv));
  499. }
  500. }
  501. } WsbCatch ( hr )
  502. WsbTraceOut ( L"HsmConnectFromName",
  503. L"HRESULT = %ls, *ppv = %ls",
  504. WsbHrAsString ( hr ), WsbPtrToPtrAsString ( ppv ) );
  505. return ( hr );
  506. }
  507. HRESULT
  508. HsmConnectFromId (
  509. IN HSMCONN_TYPE type,
  510. IN REFGUID rguid,
  511. IN REFIID riid,
  512. OUT void ** ppv
  513. )
  514. /*++
  515. Routine Description:
  516. Connects to the specified service or object. See HSMCONN_TYPE for
  517. the types of services and objects.
  518. Arguments:
  519. type - The type of service / object we are connecting too.
  520. rguid - The unique ID of the service / object to connect too.
  521. riid - The interface type to return.
  522. ppv - Returned interface pointer of the HSM Server.
  523. Return Value:
  524. S_OK - Connection made, Success.
  525. E_NOINTERFACE - Requested interface not supported by HSM Server.
  526. E_POINTER - ppv or Hsm is not a valid pointer.
  527. E_OUTOFMEMORY - Low memory condition prevented connection.
  528. E_INVALIDARG - The given ID and type do not correspond to a known
  529. service or object.
  530. --*/
  531. {
  532. WsbTraceIn ( L"HsmConnectFromId",
  533. L"type = '%ls', rguid = '%ls', riid = '%ls', ppv = 0x%p",
  534. HsmConnTypeAsString ( type ), WsbStringCopy ( WsbGuidAsString ( rguid ) ),
  535. WsbStringCopy ( WsbGuidAsString ( riid ) ), ppv );
  536. WsbTrace(OLESTR("HsmConnectFromId: UseDirectoryServices = %ls\n"),
  537. WsbBoolAsString(UseDirectoryServices));
  538. HRESULT hr = S_OK;
  539. try {
  540. BOOLEAN DSUsed = FALSE;
  541. CWsbVariant guidVariant;
  542. CComPtr < IADs > pObject;
  543. CWsbStringPtr serverName;
  544. CWsbVariant serverVariant;
  545. //
  546. // Ensure parameters are valid
  547. //
  548. WsbAssert ( 0 != ppv, E_POINTER );
  549. switch ( type ) {
  550. case HSMCONN_TYPE_HSM:
  551. case HSMCONN_TYPE_FSA:
  552. case HSMCONN_TYPE_FILTER:
  553. if (DSUsed) {
  554. } else {
  555. WsbAffirmHr( WsbGetComputerName( serverName ) );
  556. }
  557. //
  558. // Connect to the server
  559. //
  560. WsbAffirmHr ( HsmConnectToServer ( type, serverName, riid, ppv ) );
  561. break;
  562. case HSMCONN_TYPE_RESOURCE:
  563. {
  564. CComPtr< IFsaServer > pFsaServer;
  565. GUID serverGuid;
  566. serverGuid = HsmConnTypeToGuid(type);
  567. WsbAffirmHr ( HsmConnectFromId ( HSMCONN_TYPE_FSA, serverGuid, IID_IFsaServer, (void**)&pFsaServer ) );
  568. CComPtr< IFsaResource > pFsaResource;
  569. WsbAffirmHr ( pFsaServer->FindResourceById ( rguid, &pFsaResource ) );
  570. WsbAffirmHr ( pFsaResource->QueryInterface ( riid, ppv ) );
  571. }
  572. break;
  573. default:
  574. WsbThrow ( E_INVALIDARG );
  575. }
  576. } WsbCatch ( hr )
  577. WsbTraceOut ( L"HsmConnectFromId",
  578. L"HRESULT = %ls, *ppv = %ls",
  579. WsbHrAsString ( hr ), WsbPtrToPtrAsString ( ppv ) );
  580. return ( hr );
  581. }
  582. HRESULT
  583. HsmPublish (
  584. IN HSMCONN_TYPE type,
  585. IN const OLECHAR * Name,
  586. IN REFGUID rguidObjectId,
  587. IN const OLECHAR * Server,
  588. IN REFGUID rguid
  589. )
  590. /*++
  591. Routine Description:
  592. Publish (i.e. store) information about the service/object in
  593. Directory Services.
  594. Arguments:
  595. type - The type of service/object.
  596. Name - Name (possibly preceded by a subpath) of the Service/Object.
  597. rguidObjectId - The ID that the object is known by.
  598. Server - The server (computer name) on which the service actually exists.
  599. For resources, this will be NULL since it is implicit in the
  600. FSA specified by rguid.
  601. rguid - For resources, the ID of the FSA. For services, the CLSID of
  602. the service's class factory ie. CLSID_HsmServer.
  603. Return Value:
  604. S_OK - Connection made, Success.
  605. E_POINTER - Name or Server is not a valid pointer.
  606. E_OUTOFMEMORY - Low memory condition prevented connection.
  607. --*/
  608. {
  609. HRESULT hr = S_OK;
  610. WsbTraceIn ( L"HsmPublish",
  611. L"type = '%ls', Name = '%ls', rguidObjectId = '%ls', Server = '%ls', rguid = '%ls'",
  612. HsmConnTypeAsString ( type ), Name,
  613. WsbStringCopy ( WsbGuidAsString ( rguidObjectId ) ), Server,
  614. WsbStringCopy ( WsbGuidAsString ( rguid ) ) );
  615. WsbTrace(OLESTR("HsmPublish: UseDirectoryServices = %ls\n"),
  616. WsbBoolAsString(UseDirectoryServices));
  617. try {
  618. //
  619. // Ensure parameters are valid
  620. //
  621. WsbAssert ( 0 != Name, E_POINTER );
  622. WsbAssert ( ( HSMCONN_TYPE_RESOURCE == type ) || ( 0 != Server ), E_POINTER );
  623. // Perhaps we should output a log event if the DS is not writable
  624. // We now only publish the Engine service. Perhaps in the future we
  625. // will publish additional information
  626. if (HSMCONN_TYPE_HSM == type && UseDirectoryServices && DSIsWritable) {
  627. CWsbStringPtr pathToName;
  628. try {
  629. DWORD aSet;
  630. CWsbStringPtr guidString(rguidObjectId);
  631. HRESULT hrGetNode;
  632. CComPtr<IADsContainer> pComputer;
  633. CComPtr<IDispatch> pDispatch;
  634. CComPtr<IDirectoryObject> pDirObj;
  635. CComPtr<IADs> pNode;
  636. // Save the node name for the event log message
  637. pathToName = Name;
  638. pathToName.Append("\\");
  639. pathToName.Append(RsNodeName);
  640. // Get the computer node
  641. WsbAffirmHr(HsmGetComputerNode(Name, &pComputer));
  642. // See if we're already published
  643. hrGetNode = HsmGetDsChild(pComputer, RsNodeName,
  644. IID_IADs, (void**)&pNode);
  645. // If not, add our node
  646. if (HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT) == hrGetNode) {
  647. CWsbBstrPtr relPath(RsNodeName);
  648. relPath.Prepend(CNEqual);
  649. WsbAffirmHr(pComputer->Create(RsNodeType, relPath, &pDispatch));
  650. WsbAffirmHr(pDispatch->QueryInterface(IID_IADs,
  651. (void**)&pNode));
  652. // Force info out of cache
  653. WsbAffirmHr(pNode->SetInfo());
  654. } else {
  655. WsbAffirmHr(hrGetNode);
  656. }
  657. // Set the GUID & ServiceBinding values
  658. adsValue[0].dwType = ADSTYPE_CASE_IGNORE_STRING;
  659. adsValue[0].CaseIgnoreString = (WCHAR*)guidString;
  660. aaInfo[0].pszAttrName = GuidAttrName;
  661. aaInfo[0].dwControlCode = ADS_ATTR_UPDATE;
  662. aaInfo[0].dwADsType = ADSTYPE_CASE_IGNORE_STRING;
  663. aaInfo[0].pADsValues = &adsValue[0];
  664. aaInfo[0].dwNumValues = 1;
  665. adsValue[1].dwType = ADSTYPE_CASE_IGNORE_STRING;
  666. adsValue[1].CaseIgnoreString = ServiceBindValue;
  667. aaInfo[1].pszAttrName = ServiceBindAttrName;
  668. aaInfo[1].dwControlCode = ADS_ATTR_UPDATE;
  669. aaInfo[1].dwADsType = ADSTYPE_CASE_IGNORE_STRING;
  670. aaInfo[1].pADsValues = &adsValue[1];
  671. aaInfo[1].dwNumValues = 1;
  672. WsbAffirmHr(pNode->QueryInterface(IID_IDirectoryObject,
  673. (void**)&pDirObj));
  674. WsbAffirmHr(pDirObj->SetObjectAttributes(aaInfo, 2, &aSet));
  675. WsbTrace(L"HsmPublish: after SetObjectAttributes, aSet = %ld\n",
  676. aSet);
  677. WsbLogEvent(WSB_MESSAGE_PUBLISH_IN_DS, 0, NULL,
  678. static_cast<OLECHAR*>(pathToName), NULL);
  679. } WsbCatchAndDo(hr,
  680. WsbLogEvent(WSB_MESSAGE_PUBLISH_FAILED, 0, NULL,
  681. static_cast<OLECHAR*>(pathToName), NULL);
  682. hr = S_OK; // Don't stop service just for this
  683. )
  684. }
  685. } WsbCatch ( hr )
  686. WsbTraceOut ( L"HsmPublish", L"HRESULT = %ls", WsbHrAsString ( hr ) );
  687. return ( hr );
  688. }
  689. // GetDSState - determine if we're using Directory Services or not
  690. static void GetDSState(void)
  691. {
  692. BOOL CheckForDS = TRUE;
  693. DOMAIN_CONTROLLER_INFO * dc_info;
  694. DWORD size;
  695. OLECHAR vstr[32];
  696. DWORD status;
  697. UseDirectoryServices = FALSE;
  698. // Should we attempt to use directory services in this module?
  699. // (Setting the registry value to "0" allows us to avoid Directory
  700. // Services completely
  701. if (S_OK == WsbGetRegistryValueString(NULL, REG_PATH, REG_USE_DS,
  702. vstr, 32, &size)) {
  703. OLECHAR *stop;
  704. ULONG value;
  705. value = wcstoul(vstr, &stop, 10 );
  706. if (0 == value) {
  707. CheckForDS = FALSE;
  708. }
  709. }
  710. // Get the account domain name
  711. WsbGetAccountDomainName(DomainName, MAX_COMPUTERNAME_LENGTH );
  712. #if defined(HSMCONN_DEBUG)
  713. swprintf(dbg_string, L"Account domain name = <%ls>\n", DomainName);
  714. OutputDebugString(dbg_string);
  715. #endif
  716. // Check if Directory Services is available
  717. if (CheckForDS) {
  718. status = DsGetDcName(NULL, NULL, NULL, NULL,
  719. DS_DIRECTORY_SERVICE_REQUIRED | DS_IS_FLAT_NAME |
  720. DS_RETURN_FLAT_NAME, &dc_info);
  721. #if defined(HSMCONN_DEBUG)
  722. swprintf(dbg_string, L"DsGetDcName status = %d\n", status);
  723. OutputDebugString(dbg_string);
  724. #endif
  725. if (NO_ERROR == status) {
  726. #if defined(HSMCONN_DEBUG)
  727. swprintf(dbg_string, L"dc_info->DomainName = <%ls>\n", dc_info->DomainName);
  728. OutputDebugString(dbg_string);
  729. #endif
  730. if (dc_info->Flags & DS_DS_FLAG) {
  731. wcscpy(DomainName, dc_info->DomainName);
  732. UseDirectoryServices = TRUE;
  733. if (dc_info->Flags & DS_WRITABLE_FLAG) {
  734. DSIsWritable = TRUE;
  735. }
  736. }
  737. NetApiBufferFree(dc_info);
  738. }
  739. }
  740. #if defined(HSMCONN_DEBUG)
  741. swprintf(dbg_string, L"dHsmConn - GetDSState: UseDirectoryServices = %ls\n",
  742. WsbBoolAsString(UseDirectoryServices));
  743. OutputDebugString(dbg_string);
  744. #endif
  745. }
  746. } // extern "C"