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.

647 lines
14 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. rndrend.cpp
  5. Abstract:
  6. This module contains implementation of CRendezvous control.
  7. --*/
  8. #include "stdafx.h"
  9. #include "rndrend.h"
  10. #include "rndcoll.h"
  11. #include "rndreg.h"
  12. #include "rndnt.h"
  13. #include "rndils.h"
  14. #include "rndndnc.h"
  15. #include "rndldap.h"
  16. #include <atlwin.cpp>
  17. CRegistry g_RregistryInfo;
  18. CRendezvous::~CRendezvous()
  19. {
  20. if (m_fWinsockReady)
  21. {
  22. WSACleanup();
  23. }
  24. if ( m_pFTM )
  25. {
  26. m_pFTM->Release();
  27. }
  28. }
  29. HRESULT CRendezvous::FinalConstruct(void)
  30. {
  31. LOG((MSP_TRACE, "CRendezvous::FinalConstruct - enter"));
  32. HRESULT hr = CoCreateFreeThreadedMarshaler( GetControllingUnknown(),
  33. & m_pFTM );
  34. if ( FAILED(hr) )
  35. {
  36. LOG((MSP_INFO, "CRendezvous::FinalConstruct - "
  37. "create FTM returned 0x%08x; exit", hr));
  38. return hr;
  39. }
  40. LOG((MSP_TRACE, "CRendezvous::FinalConstruct - exit S_OK"));
  41. return S_OK;
  42. }
  43. /////////////////////////////////////////////////////////////////////////////
  44. // Private functions
  45. /////////////////////////////////////////////////////////////////////////////
  46. HRESULT CRendezvous::InitWinsock()
  47. {
  48. Lock();
  49. if (!m_fWinsockReady)
  50. {
  51. WSADATA wsaData;
  52. int err;
  53. // initialize winsock
  54. if (err = WSAStartup(RENDWINSOCKVERSION, &wsaData))
  55. {
  56. Unlock();
  57. return HRESULT_FROM_ERROR_CODE(err);
  58. }
  59. m_fWinsockReady = TRUE;
  60. }
  61. Unlock();
  62. return S_OK;
  63. }
  64. HRESULT CRendezvous::CreateNTDirectory(
  65. OUT ITDirectory **ppDirectory
  66. )
  67. /*++
  68. Routine Description:
  69. Create a object that uses NTDS to support the ITDirectory.
  70. Arguments:
  71. ppDirectory - the object being created.
  72. Return Value:
  73. HRESULT.
  74. --*/
  75. {
  76. HRESULT hr;
  77. // create the NTDS directory, if NTDS exists.
  78. CComObject<CNTDirectory> * pNTDirectory;
  79. hr = CComObject<CNTDirectory>::CreateInstance(&pNTDirectory);
  80. if (NULL == pNTDirectory)
  81. {
  82. LOG((MSP_ERROR, "can't create NT Directory Object."));
  83. return hr;
  84. }
  85. hr = pNTDirectory->_InternalQueryInterface(
  86. IID_ITDirectory,
  87. (void **)ppDirectory
  88. );
  89. if (FAILED(hr))
  90. {
  91. LOG((MSP_ERROR, "CreateNTDirectory:QueryInterface failed: %x", hr));
  92. delete pNTDirectory;
  93. return hr;
  94. }
  95. return S_OK;
  96. }
  97. HRESULT CRendezvous::CreateILSDirectory(
  98. IN const WCHAR * const wstrName,
  99. IN const WORD wPort,
  100. OUT ITDirectory ** ppDirectory
  101. )
  102. /*++
  103. Routine Description:
  104. Create a object that uses ILS to support the ITDirectory.
  105. Arguments:
  106. wstrName - The ILS server name.
  107. wPort - The port that the server is listening on.
  108. ppDirectory - the object being created.
  109. Return Value:
  110. HRESULT.
  111. --*/
  112. {
  113. HRESULT hr;
  114. // create the com object.
  115. CComObject<CILSDirectory> * pILSDirectory;
  116. hr = CComObject<CILSDirectory>::CreateInstance(&pILSDirectory);
  117. if (NULL == pILSDirectory)
  118. {
  119. LOG((MSP_ERROR, "can't create ILS Directory Object."));
  120. return hr;
  121. }
  122. // init the object with the server name and port.
  123. hr = pILSDirectory->Init(wstrName, wPort);
  124. if (FAILED(hr))
  125. {
  126. LOG((MSP_ERROR, "CreateILSDirectory:Init failed: %x", hr));
  127. delete pILSDirectory;
  128. return hr;
  129. }
  130. // get the ITDirectory interface.
  131. hr = pILSDirectory->_InternalQueryInterface(
  132. IID_ITDirectory,
  133. (void **)ppDirectory
  134. );
  135. if (FAILED(hr))
  136. {
  137. LOG((MSP_ERROR, "CreateILSDirectory:QueryInterface failed: %x", hr));
  138. delete pILSDirectory;
  139. return hr;
  140. }
  141. return S_OK;
  142. }
  143. HRESULT CRendezvous::CreateNDNCDirectory(
  144. IN const WCHAR * const wstrName,
  145. IN const WORD wPort,
  146. OUT ITDirectory ** ppDirectory
  147. )
  148. /*++
  149. Routine Description:
  150. Create a object that uses an NDNC to support the ITDirectory.
  151. Arguments:
  152. wstrName - The NDNC server name.
  153. wPort - The port that the server is listening on.
  154. ppDirectory - the object being created.
  155. Return Value:
  156. HRESULT.
  157. --*/
  158. {
  159. LOG((MSP_TRACE, "CRendezvous::CreateNDNCDirectory - enter"));
  160. HRESULT hr;
  161. //
  162. // create the com object.
  163. //
  164. CComObject<CNDNCDirectory> * pNDNCDirectory;
  165. hr = CComObject<CNDNCDirectory>::CreateInstance(&pNDNCDirectory);
  166. if ( NULL == pNDNCDirectory )
  167. {
  168. LOG((MSP_ERROR, "CreateNDNCDirectory - "
  169. "can't create NDNC Directory Object - exit 0x%08x", hr));
  170. return hr;
  171. }
  172. //
  173. // get the ITDirectory interface.
  174. //
  175. hr = pNDNCDirectory->_InternalQueryInterface(
  176. IID_ITDirectory,
  177. (void **)ppDirectory
  178. );
  179. if ( FAILED( hr ) )
  180. {
  181. LOG((MSP_ERROR, "CreateNDNCDirectory - "
  182. "QueryInterface failed - exit 0x%08x", hr));
  183. delete pNDNCDirectory;
  184. return hr;
  185. }
  186. //
  187. // init the object with the server name and port.
  188. // For NDNCs, this also looks around on the server and tries to
  189. // see where on the server the NDNC is supposed to live. If there
  190. // is no TAPI NDNC in the domain, this will fail. Therefore, when
  191. // enumerating default directories, the local DC won't show up as
  192. // an NDNC if there is no NDNC accessible from the local DC.
  193. //
  194. hr = pNDNCDirectory->Init(wstrName, wPort);
  195. if ( FAILED( hr ) )
  196. {
  197. LOG((MSP_ERROR, "CreateNDNCDirectory - "
  198. "Init failed - exit 0x%08x", hr));
  199. (*ppDirectory)->Release();
  200. *ppDirectory = NULL;
  201. return hr;
  202. }
  203. LOG((MSP_TRACE, "CRendezvous::CreateNDNCDirectory - exit S_OK"));
  204. return S_OK;
  205. }
  206. HRESULT CRendezvous::CreateDirectories(
  207. SimpleVector <ITDirectory *> &VDirectory
  208. )
  209. /*++
  210. Routine Description:
  211. Find out all the direcories that are available.
  212. Arguments:
  213. pppDirectory - the array of directories being created.
  214. dwCount - The number of directories.
  215. Return Value:
  216. HRESULT.
  217. --*/
  218. {
  219. HRESULT hr;
  220. LOG((MSP_TRACE, "CreateDirectories: "));
  221. ITDirectory * pDirectory;
  222. //
  223. // First, create the NTDS non-dynamic directory object.
  224. //
  225. if (SUCCEEDED(hr = CreateNTDirectory(&pDirectory)))
  226. {
  227. if (!VDirectory.add(pDirectory))
  228. {
  229. pDirectory->Release();
  230. return E_OUTOFMEMORY;
  231. }
  232. }
  233. else
  234. {
  235. LOG((MSP_WARN, "Cannot create NT directory: 0x%08x", hr));
  236. }
  237. //
  238. // Second, create the NDNC directory object.
  239. //
  240. WCHAR * pDomainControllerName;
  241. //
  242. // The first argument (=0) means we find out all
  243. // objects
  244. //
  245. hr = GetDomainControllerName(0, &pDomainControllerName);
  246. if ( SUCCEEDED(hr) )
  247. {
  248. hr = CreateNDNCDirectory(
  249. pDomainControllerName,
  250. LDAP_PORT,
  251. &pDirectory
  252. );
  253. delete pDomainControllerName;
  254. if ( SUCCEEDED( hr ) )
  255. {
  256. if (!VDirectory.add(pDirectory))
  257. {
  258. pDirectory->Release();
  259. return E_OUTOFMEMORY;
  260. }
  261. }
  262. else
  263. {
  264. LOG((MSP_WARN, "Cannot create NDNC directory: 0x%08x", hr));
  265. }
  266. }
  267. else
  268. {
  269. LOG((MSP_WARN, "Cannot get DC name: 0x%08x", hr));
  270. }
  271. //
  272. // Third, find out if there are any ILS servers published in the NTDS.
  273. //
  274. HANDLE hLookup;
  275. int ret = ::LookupILSServiceBegin(&hLookup);
  276. if (ret != NOERROR)
  277. {
  278. LOG((MSP_WARN, "Lookup ILSservice failed: 0x%08x", ret));
  279. }
  280. else
  281. {
  282. const DWORD MAX_HOST_NAME_LEN = 511;
  283. WCHAR HostName[MAX_HOST_NAME_LEN + 1];
  284. DWORD dwLen = MAX_HOST_NAME_LEN;
  285. WORD wPort;
  286. while (::LookupILSServiceNext(
  287. hLookup,
  288. HostName,
  289. &dwLen,
  290. &wPort
  291. ) == NOERROR)
  292. {
  293. LOG((MSP_INFO, "ILS server in NTDS: %S, Port:%d",
  294. HostName, wPort));
  295. hr = CreateILSDirectory(HostName, wPort, &pDirectory);
  296. if (SUCCEEDED(hr))
  297. {
  298. if (!VDirectory.add(pDirectory))
  299. {
  300. pDirectory->Release();
  301. return E_OUTOFMEMORY;
  302. }
  303. }
  304. else
  305. {
  306. LOG((MSP_WARN, "Cannot create ILS directory: 0x%08x", hr));
  307. }
  308. dwLen = MAX_HOST_NAME_LEN;
  309. }
  310. ::LookupILSServiceEnd(hLookup);
  311. }
  312. return S_OK;
  313. }
  314. HRESULT CRendezvous::CreateDirectoryEnumerator(
  315. IN ITDirectory ** begin,
  316. IN ITDirectory ** end,
  317. OUT IEnumDirectory ** ppIEnum
  318. )
  319. /*++
  320. Routine Description:
  321. Create a enumerator of directories.
  322. Arguments:
  323. begin - The start iterator.
  324. end - The end iterator.
  325. ppIEnum - The enumerator being created.
  326. Return Value:
  327. HRESULT.
  328. --*/
  329. {
  330. typedef _CopyInterface<ITDirectory> CCopy;
  331. typedef CSafeComEnum<IEnumDirectory, &IID_IEnumDirectory,
  332. ITDirectory *, CCopy> CEnumerator;
  333. HRESULT hr;
  334. CComObject<CEnumerator> *pEnum = NULL;
  335. hr = CComObject<CEnumerator>::CreateInstance(&pEnum);
  336. if (pEnum == NULL)
  337. {
  338. LOG((MSP_ERROR, "Could not create enumerator object, %x", hr));
  339. return hr;
  340. }
  341. hr = pEnum->Init(begin, end, NULL, AtlFlagCopy);
  342. if (FAILED(hr))
  343. {
  344. LOG((MSP_ERROR, "init enumerator object failed, %x", hr));
  345. delete pEnum;
  346. return hr;
  347. }
  348. // query for the IID_IEnumDirectory i/f
  349. hr = pEnum->_InternalQueryInterface(IID_IEnumDirectory, (void**)ppIEnum);
  350. if (FAILED(hr))
  351. {
  352. LOG((MSP_ERROR, "query enum interface failed, %x", hr));
  353. delete pEnum;
  354. return hr;
  355. }
  356. return hr;
  357. }
  358. /////////////////////////////////////////////////////////////////////////////
  359. // ITRendezvous
  360. /////////////////////////////////////////////////////////////////////////////
  361. STDMETHODIMP CRendezvous::get_DefaultDirectories(
  362. OUT VARIANT * pVariant
  363. )
  364. {
  365. if (BadWritePtr(pVariant))
  366. {
  367. LOG((MSP_ERROR, "bad variant pointer in get_DefaultDirectories"));
  368. return E_POINTER;
  369. }
  370. BAIL_IF_FAIL(InitWinsock(), "Init winsock");
  371. // create the default directories.
  372. SimpleVector <ITDirectory *> VDirectory;
  373. CreateDirectories(VDirectory);
  374. // create the collection.
  375. HRESULT hr = ::CreateInterfaceCollection(VDirectory.size(),
  376. &VDirectory[0],
  377. &VDirectory[VDirectory.size()],
  378. pVariant);
  379. // the collection has its ref count, so release local ones.
  380. for (DWORD i = 0; i < VDirectory.size(); i ++)
  381. {
  382. VDirectory[i]->Release();
  383. }
  384. return hr;
  385. }
  386. STDMETHODIMP CRendezvous::EnumerateDefaultDirectories(
  387. OUT IEnumDirectory ** ppEnumDirectory
  388. )
  389. {
  390. if (BadWritePtr(ppEnumDirectory))
  391. {
  392. LOG((MSP_ERROR, "bad pointer in EnumerateDefaultDirectories"));
  393. return E_POINTER;
  394. }
  395. BAIL_IF_FAIL(InitWinsock(), "Init winsock");
  396. // create the default directories.
  397. SimpleVector <ITDirectory *> VDirectory;
  398. CreateDirectories(VDirectory);
  399. // create the enumerator
  400. HRESULT hr = CreateDirectoryEnumerator(
  401. &VDirectory[0],
  402. &VDirectory[VDirectory.size()],
  403. ppEnumDirectory
  404. );
  405. for (DWORD i = 0; i < VDirectory.size(); i ++)
  406. {
  407. VDirectory[i]->Release();
  408. }
  409. return hr;
  410. }
  411. STDMETHODIMP CRendezvous::CreateDirectory(
  412. IN DIRECTORY_TYPE DirectoryType,
  413. IN BSTR pName,
  414. OUT ITDirectory ** ppDir
  415. )
  416. {
  417. if (BadWritePtr(ppDir))
  418. {
  419. LOG((MSP_ERROR, "bad pointer in CreateDirectory"));
  420. return E_POINTER;
  421. }
  422. //
  423. // We should validate the pName
  424. // If is NULL we should return E_INVALIDARG
  425. //
  426. if( IsBadStringPtr( pName, (UINT)-1))
  427. {
  428. LOG((MSP_ERROR, "bad Name pointer in CreateDirectory"));
  429. return E_INVALIDARG;
  430. }
  431. BAIL_IF_FAIL(InitWinsock(), "Init winsock");
  432. HRESULT hr;
  433. switch (DirectoryType)
  434. {
  435. case DT_NTDS:
  436. hr = CreateNTDirectory(ppDir);
  437. break;
  438. case DT_ILS:
  439. //
  440. // Try NDNC first, as ILS is legacy. The CreateNDNCDirectory actually
  441. // goes on the wire and checks if it looks like an NDNC server; the
  442. // CreateILSDirectory does no such thing. This maintains the ability
  443. // to use custom ports with ILS, and it also preserves the semantics
  444. // of not getting a failure returned for a bad server name until you
  445. // call ITDirectory::Connect.
  446. //
  447. hr = CreateNDNCDirectory(pName, LDAP_PORT, ppDir);
  448. if ( FAILED(hr) )
  449. {
  450. hr = CreateILSDirectory(pName, ILS_PORT, ppDir);
  451. }
  452. break;
  453. default:
  454. LOG((MSP_ERROR, "unknown directory type, %x", DirectoryType));
  455. hr = E_INVALIDARG;
  456. }
  457. return hr;
  458. }
  459. STDMETHODIMP CRendezvous::CreateDirectoryObject(
  460. IN DIRECTORY_OBJECT_TYPE DirectoryObjectType,
  461. IN BSTR pName,
  462. OUT ITDirectoryObject ** ppDirectoryObject
  463. )
  464. {
  465. if (BadWritePtr(ppDirectoryObject))
  466. {
  467. LOG((MSP_ERROR, "bad pointer in CreateDirectoryObject"));
  468. return E_POINTER;
  469. }
  470. BAIL_IF_FAIL(InitWinsock(), "Init winsock");
  471. HRESULT hr;
  472. switch (DirectoryObjectType)
  473. {
  474. case OT_CONFERENCE:
  475. hr = ::CreateEmptyConference(pName, ppDirectoryObject);
  476. break;
  477. case OT_USER:
  478. hr = ::CreateEmptyUser(pName, ppDirectoryObject);
  479. break;
  480. default:
  481. LOG((MSP_ERROR, "unknown directory type, %x", DirectoryObjectType));
  482. hr = E_INVALIDARG;
  483. }
  484. return hr; // ZoltanS fix 6-1-98
  485. }
  486. // eof