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.

1435 lines
34 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. rndcnf.cpp
  5. Abstract:
  6. This module contains implementation of CConference object.
  7. --*/
  8. #include "stdafx.h"
  9. #include <winsock2.h>
  10. #include "rndcnf.h"
  11. // These are the attribute names according to the schema in NTDS.
  12. const WCHAR *const MeetingAttributeNames[] =
  13. {
  14. L"meetingAdvertisingScope",
  15. L"meetingBlob",
  16. L"meetingDescription",
  17. L"meetingIsEncrypted",
  18. L"meetingName",
  19. L"meetingOriginator",
  20. L"meetingProtocol",
  21. L"meetingStartTime",
  22. L"meetingStopTime",
  23. L"meetingType",
  24. L"meetingURL"
  25. };
  26. #define INC_ACCESS_ACL_SIZE(_SIZE_, _SID_) \
  27. _SIZE_ += (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(_SID_));
  28. #define BAIL_ON_BOOLFAIL(_FN_) \
  29. if ( !_FN_ ) \
  30. { \
  31. hr = HRESULT_FROM_WIN32(GetLastError()); \
  32. goto failed; \
  33. }
  34. #define ACCESS_READ 0x10
  35. #define ACCESS_WRITE 0x20
  36. #define ACCESS_MODIFY (ACCESS_WRITE | WRITE_DAC)
  37. #define ACCESS_DELETE DELETE
  38. #define ACCESS_ALL (ACCESS_READ | ACCESS_MODIFY | ACCESS_DELETE)
  39. HRESULT
  40. ConvertStringToSid(
  41. IN PWSTR string,
  42. OUT PSID *sid,
  43. OUT PDWORD pdwSidSize,
  44. OUT PWSTR *end
  45. );
  46. HRESULT
  47. ConvertACLToVariant(
  48. PACL pACL,
  49. LPVARIANT pvarACL
  50. );
  51. /////////////////////////////////////////////////////////////////////////////
  52. // non-interface class methods
  53. /////////////////////////////////////////////////////////////////////////////
  54. HRESULT
  55. CConference::FinalConstruct()
  56. /*++
  57. Routine Description:
  58. Create the SDPBlob object that is aggregated with the conference object.
  59. Also query my own Notification interface which will be given to the
  60. SDPBlob object. To avoid circlar ref count, this interface is realeased
  61. as soon as it is queried.
  62. Arguments:
  63. Return Value:
  64. HRESULT.
  65. --*/
  66. {
  67. // Create the conference Blob
  68. CComPtr <IUnknown> pIUnkConfBlob;
  69. HRESULT hr = CoCreateInstance(
  70. CLSID_SdpConferenceBlob,
  71. NULL,
  72. CLSCTX_INPROC_SERVER,
  73. IID_IUnknown,
  74. (void **)&pIUnkConfBlob
  75. );
  76. BAIL_IF_FAIL(hr, "Create SdpConferenceBlob");
  77. // Get the ITConfBlobPrivate interface from the Blob object.
  78. CComPtr <ITConfBlobPrivate> pITConfBlobPrivate;
  79. hr = pIUnkConfBlob->QueryInterface(
  80. IID_ITConfBlobPrivate,
  81. (void **)&pITConfBlobPrivate
  82. );
  83. BAIL_IF_FAIL(hr, "Query ITConfBlobPrivate interface");
  84. // query the conf blob instance for the conf blob i/f
  85. CComPtr <ITConferenceBlob> pITConfBlob;
  86. hr = pIUnkConfBlob->QueryInterface(
  87. IID_ITConferenceBlob,
  88. (void **)&pITConfBlob
  89. );
  90. BAIL_IF_FAIL(hr, "Query ITConferenceBlob");
  91. // keep the interface pointers.
  92. m_pIUnkConfBlob = pIUnkConfBlob;
  93. m_pIUnkConfBlob->AddRef();
  94. m_pITConfBlob = pITConfBlob;
  95. m_pITConfBlob->AddRef();
  96. m_pITConfBlobPrivate = pITConfBlobPrivate;
  97. m_pITConfBlobPrivate->AddRef();
  98. return S_OK;
  99. }
  100. HRESULT CConference::Init(BSTR bName)
  101. /*++
  102. Routine Description:
  103. Init this conference with only a name. This is called when an empty
  104. conference is created. A default SDP blob will be created. The format
  105. is in the registry. See sdpblb code.
  106. Arguments:
  107. bName - The name of the conference.
  108. Return Value:
  109. HRESULT.
  110. --*/
  111. {
  112. HRESULT hr;
  113. hr = SetDefaultValue(
  114. g_ConfInstInfoArray,
  115. g_ContInstInfoArraySize
  116. );
  117. BAIL_IF_FAIL(hr, "set default attribute value");
  118. hr = SetSingleValue(MA_MEETINGNAME, bName);
  119. BAIL_IF_FAIL(hr, "can't set meeting name");
  120. hr = m_pITConfBlob->Init(bName, BCS_UTF8, NULL);
  121. BAIL_IF_FAIL(hr, "Init the conference Blob");
  122. hr = SetDefaultSD();
  123. BAIL_IF_FAIL(hr, "Init the security descriptor");
  124. return hr;
  125. }
  126. HRESULT CConference::Init(BSTR bName, BSTR bProtocol, BSTR bBlob)
  127. /*++
  128. Routine Description:
  129. Init this conference with only the conference name and also a conference
  130. blob whose protocol should be IP conference. The blob is parsed by the
  131. SDP Blob object and the information in the blob will be notified back
  132. to this conference object through the notification interface.
  133. Arguments:
  134. bName - The name of the conference.
  135. bProtocol - The protocol used by the blob. should be SDP now.
  136. bBlob - The opaque data blob that describes this conference.
  137. Return Value:
  138. HRESULT.
  139. --*/
  140. {
  141. HRESULT hr;
  142. hr = SetSingleValue(MA_MEETINGNAME, bName);
  143. BAIL_IF_FAIL(hr, "can't set meeting name");
  144. // Check to make sure protocol is IP Conference
  145. if ( wcscmp(bProtocol, L"IP Conference" ))
  146. {
  147. LOG((MSP_ERROR, "Protocol must be IP Conference"));
  148. return E_INVALIDARG;
  149. }
  150. hr = SetSingleValue(MA_PROTOCOL, bProtocol);
  151. BAIL_IF_FAIL(hr, "can't set meeting protocol");
  152. hr = SetSingleValue(MA_CONFERENCE_BLOB, bBlob);
  153. BAIL_IF_FAIL(hr, "can't set meeting blob");
  154. hr = m_pITConfBlob->Init(NULL, BCS_UTF8, bBlob);
  155. BAIL_IF_FAIL(hr, "Init the conference Blob object");
  156. return hr;
  157. }
  158. void
  159. CConference::FinalRelease()
  160. /*++
  161. Routine Description:
  162. Clean up the SDP blob contained in this object.
  163. clean up the security object for this object.
  164. clean up all the attributes.
  165. Arguments:
  166. Return Value:
  167. --*/
  168. {
  169. CLock Lock(m_lock);
  170. // do base class first
  171. CDirectoryObject::FinalRelease();
  172. if ( NULL != m_pIUnkConfBlob )
  173. {
  174. m_pIUnkConfBlob->Release();
  175. m_pIUnkConfBlob = NULL;
  176. }
  177. if ( NULL != m_pITConfBlobPrivate )
  178. {
  179. m_pITConfBlobPrivate->Release();
  180. m_pITConfBlobPrivate = NULL;
  181. }
  182. if ( NULL != m_pITConfBlob )
  183. {
  184. m_pITConfBlob->Release();
  185. m_pITConfBlob = NULL;
  186. }
  187. // MuHan + ZoltanS fix 3-19-98 -- these are member smart pointers,
  188. // should not be deleted!!!
  189. // for (DWORD i = 0; i < NUM_MEETING_ATTRIBUTES; i ++)
  190. // {
  191. // delete m_Attributes[i];
  192. // }
  193. // the interface pointer to this instance's ITNotification i/f is NOT
  194. // released because it was already released in FinalConstruct but the
  195. // pointer was held to be passed onto the aggregated conf blob instance
  196. }
  197. HRESULT
  198. CConference::UpdateConferenceBlob(
  199. IN IUnknown *pIUnkConfBlob
  200. )
  201. /*++
  202. Routine Description:
  203. update the blob attribute if the blob object has been changed.
  204. Arguments:
  205. pIUnkConfBlob - pointer to the SDPBlob object.
  206. Return Value:
  207. HRESULT.
  208. --*/
  209. {
  210. // check if the sdp blob has been modified since the component was created
  211. VARIANT_BOOL BlobIsModified;
  212. BAIL_IF_FAIL(m_pITConfBlobPrivate->get_IsModified(&BlobIsModified),
  213. "UpdateConferenceBlob.get_IsModified");
  214. // if not, return
  215. if ( BlobIsModified == VARIANT_FALSE )
  216. {
  217. return S_OK;
  218. }
  219. // get the blob and
  220. CBstr SdpBlobBstr;
  221. BAIL_IF_FAIL(m_pITConfBlob->get_ConferenceBlob(&SdpBlobBstr),
  222. "UpdateConferenceBlob.get_ConfrenceBlob");
  223. // set the conference blob attribute for the conference
  224. BAIL_IF_FAIL(SetSingleValue(MA_CONFERENCE_BLOB, SdpBlobBstr),
  225. "UpdateConferenceBlob.Setblob");
  226. return S_OK;
  227. }
  228. HRESULT
  229. CConference::SetDefaultValue(
  230. IN REG_INFO RegInfo[],
  231. IN DWORD dwItems
  232. )
  233. /*++
  234. Routine Description:
  235. Set attributes to the default value got from the registry.
  236. Arguments:
  237. RegInfo - {attribute, value} array.
  238. dwItems - The number of items in the array.
  239. Return Value:
  240. HRESULT.
  241. --*/
  242. {
  243. for (DWORD i=0; i < dwItems ; i++)
  244. {
  245. HRESULT hr;
  246. hr = SetSingleValue(RegInfo[i].Attribute, RegInfo[i].wstrValue);
  247. BAIL_IF_FAIL(hr, "set value");
  248. }
  249. return S_OK;
  250. }
  251. /*++
  252. Routine Description:
  253. Set the right security descriptor for the conference.
  254. Arguments:
  255. Return Value:
  256. HRESULT.
  257. --*/
  258. HRESULT
  259. CConference::SetDefaultSD()
  260. {
  261. LOG((MSP_INFO, "CConference::SetDefaultSD - entered"));
  262. //
  263. // The security descriptor
  264. //
  265. IADsSecurityDescriptor* pSecDesc = NULL;
  266. HRESULT hr = S_OK;
  267. bool bOwner = false, bWorld = false;
  268. PACL pACL = NULL;
  269. PSID pSidWorld = NULL;
  270. DWORD dwAclSize = sizeof(ACL), dwTemp;
  271. BSTR bstrTemp = NULL;
  272. LPWSTR pszTemp = NULL;
  273. HANDLE hToken;
  274. UCHAR *pInfoBuffer = NULL;
  275. DWORD cbInfoBuffer = 512;
  276. //
  277. // Try to get the thread or process token
  278. //
  279. if( !OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken) )
  280. {
  281. //
  282. // If there was a sever error we exit
  283. //
  284. if( GetLastError() != ERROR_NO_TOKEN )
  285. {
  286. LOG((MSP_ERROR, "CConference::SetDefaultSD - exit E_FAIL "
  287. "OpenThreadToken failed!"));
  288. return E_FAIL;
  289. }
  290. //
  291. // Attempt to open the process token, since no thread token exists
  292. //
  293. if( !OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) )
  294. {
  295. LOG((MSP_ERROR, "CConference::SetDefaultSD - exit E_FAIL "
  296. "OpenProcessToken failed"));
  297. return E_FAIL;
  298. }
  299. }
  300. //
  301. // Loop until we have a large enough structure
  302. //
  303. while ( (pInfoBuffer = new UCHAR[cbInfoBuffer]) != NULL )
  304. {
  305. if ( !GetTokenInformation(hToken, TokenUser, pInfoBuffer, cbInfoBuffer, &cbInfoBuffer) )
  306. {
  307. delete pInfoBuffer;
  308. pInfoBuffer = NULL;
  309. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
  310. return E_FAIL;
  311. }
  312. else
  313. {
  314. break;
  315. }
  316. }
  317. CloseHandle(hToken);
  318. //
  319. // Did we get the owner ACL?
  320. //
  321. if ( pInfoBuffer )
  322. {
  323. INC_ACCESS_ACL_SIZE( dwAclSize, ((PTOKEN_USER) pInfoBuffer)->User.Sid );
  324. bOwner = true;
  325. }
  326. //
  327. // Make SID for "Everyone"
  328. //
  329. SysReAllocString( &bstrTemp, L"S-1-1-0" );
  330. hr = ConvertStringToSid( bstrTemp, &pSidWorld, &dwTemp, &pszTemp );
  331. if ( SUCCEEDED(hr) )
  332. {
  333. INC_ACCESS_ACL_SIZE( dwAclSize, pSidWorld );
  334. bWorld = true;
  335. }
  336. //
  337. // Create a security descriptor
  338. //
  339. hr = CoCreateInstance(
  340. CLSID_SecurityDescriptor,
  341. NULL,
  342. CLSCTX_INPROC_SERVER,
  343. IID_IADsSecurityDescriptor,
  344. (void **)&pSecDesc
  345. );
  346. if( FAILED(hr) )
  347. {
  348. LOG((MSP_ERROR, "CConference::SetDefaultSD - exit 0x%08x "
  349. "Create security descriptor failed!", hr));
  350. goto failed;
  351. }
  352. //
  353. // Create the ACL containing the Owner and World ACEs
  354. //
  355. pACL = (PACL) new BYTE[dwAclSize];
  356. if ( pACL )
  357. {
  358. BAIL_ON_BOOLFAIL( InitializeAcl(pACL, dwAclSize, ACL_REVISION) );
  359. // Add World Rights
  360. if ( bWorld )
  361. {
  362. if ( bOwner )
  363. {
  364. BAIL_ON_BOOLFAIL( AddAccessAllowedAce(pACL, ACL_REVISION, ACCESS_READ, pSidWorld) );
  365. }
  366. else
  367. {
  368. BAIL_ON_BOOLFAIL( AddAccessAllowedAce(pACL, ACL_REVISION, ACCESS_ALL , pSidWorld) );
  369. }
  370. }
  371. // Add Creator rights
  372. if ( bOwner )
  373. BAIL_ON_BOOLFAIL( AddAccessAllowedAce(pACL, ACL_REVISION, ACCESS_ALL, ((PTOKEN_USER) pInfoBuffer)->User.Sid) );
  374. // Set the DACL onto our security descriptor
  375. VARIANT varDACL;
  376. VariantInit( &varDACL );
  377. if ( SUCCEEDED(hr = ConvertACLToVariant((PACL) pACL, &varDACL)) )
  378. {
  379. if ( SUCCEEDED(hr = pSecDesc->put_DaclDefaulted(FALSE)) )
  380. {
  381. hr = pSecDesc->put_DiscretionaryAcl( V_DISPATCH(&varDACL) );
  382. if( SUCCEEDED(hr) )
  383. {
  384. hr = put_SecurityDescriptor((IDispatch*)pSecDesc);
  385. if( SUCCEEDED(hr) )
  386. {
  387. hr = this->put_SecurityDescriptorIsModified(TRUE);
  388. }
  389. }
  390. }
  391. }
  392. VariantClear( &varDACL );
  393. }
  394. else
  395. {
  396. hr = E_OUTOFMEMORY;
  397. }
  398. // Clean up
  399. failed:
  400. SysFreeString( bstrTemp );
  401. if ( pACL ) delete pACL;
  402. if ( pSidWorld ) delete pSidWorld;
  403. if ( pInfoBuffer ) delete pInfoBuffer;
  404. if( pSecDesc ) pSecDesc->Release();
  405. LOG((MSP_INFO, "CConference::SetDefaultSD - exit 0x%08x", hr));
  406. return hr;
  407. }
  408. HRESULT
  409. CConference::GetSingleValueBstr(
  410. IN OBJECT_ATTRIBUTE Attribute,
  411. OUT BSTR * AttributeValue
  412. )
  413. /*++
  414. Routine Description:
  415. Get the value of an attribute and create a BSTR to return.
  416. Arguments:
  417. Attribute - the attribute id as defined in rend.idl
  418. AttributeValue - a pointer to a BSTR that points to the returned value.
  419. Return Value:
  420. HRESULT.
  421. --*/
  422. {
  423. LOG((MSP_INFO, "CConference::GetSingleValueBstr - entered"));
  424. BAIL_IF_BAD_WRITE_PTR(AttributeValue, E_POINTER);
  425. // Check to see if the attribute is valid.
  426. if (!ValidMeetingAttribute(Attribute))
  427. {
  428. LOG((MSP_ERROR, "Invalid Attribute, %d", Attribute));
  429. return E_FAIL;
  430. }
  431. CLock Lock(m_lock);
  432. // check to see if I have this attribute.
  433. if(!m_Attributes[MeetingAttrIndex(Attribute)])
  434. {
  435. LOG((MSP_ERROR, "Attribute %S is not found",
  436. MeetingAttributeName(Attribute)));
  437. return E_FAIL;
  438. }
  439. // allocate a BSTR to return.
  440. *AttributeValue =
  441. SysAllocString(m_Attributes[MeetingAttrIndex(Attribute)]);
  442. if (*AttributeValue == NULL)
  443. {
  444. return E_OUTOFMEMORY;
  445. }
  446. LOG((MSP_INFO, "CConference::get %S : %S",
  447. MeetingAttributeName(Attribute), *AttributeValue));
  448. return S_OK;
  449. }
  450. HRESULT
  451. CConference::GetSingleValueWstr(
  452. IN OBJECT_ATTRIBUTE Attribute,
  453. IN DWORD dwSize,
  454. OUT WCHAR * AttributeValue
  455. )
  456. /*++
  457. Routine Description:
  458. Get the value of an attribute. copy the value to the buffer provided.
  459. Arguments:
  460. Attribute - the attribute id as defined in rend.idl
  461. AttributeValue - a pointer to a buffer where the value will be copied to.
  462. Return Value:
  463. HRESULT.
  464. --*/
  465. {
  466. LOG((MSP_INFO, "CConference::GetSingleValueWstr - entered"));
  467. _ASSERTE(NULL != AttributeValue);
  468. _ASSERTE(ValidMeetingAttribute(Attribute));
  469. CLock Lock(m_lock);
  470. if(!m_Attributes[MeetingAttrIndex(Attribute)])
  471. {
  472. LOG((MSP_ERROR, "Attribute %S is not found",
  473. MeetingAttributeName(Attribute)));
  474. return E_FAIL;
  475. }
  476. // copy the attribute value
  477. lstrcpynW(
  478. AttributeValue,
  479. m_Attributes[MeetingAttrIndex(Attribute)],
  480. dwSize
  481. );
  482. LOG((MSP_INFO, "CConference::get %S : %S",
  483. MeetingAttributeName(Attribute), AttributeValue));
  484. return S_OK;
  485. }
  486. HRESULT
  487. CConference::SetSingleValue(
  488. IN OBJECT_ATTRIBUTE Attribute,
  489. IN WCHAR * AttributeValue
  490. )
  491. /*++
  492. Routine Description:
  493. Set the attribute value to a new string.
  494. Arguments:
  495. Attribute - the attribute id as defined in rend.idl
  496. AttributeValue - the new value. If it is null, the value is deleted.
  497. Return Value:
  498. HRESULT.
  499. --*/
  500. {
  501. LOG((MSP_INFO, "CConference::SetSingleValue - entered"));
  502. if (!ValidMeetingAttribute(Attribute))
  503. {
  504. LOG((MSP_ERROR, "Invalid Attribute, %d", Attribute));
  505. return E_FAIL;
  506. }
  507. if (AttributeValue != NULL)
  508. {
  509. BAIL_IF_BAD_READ_PTR(AttributeValue, E_POINTER);
  510. }
  511. CLock Lock(m_lock);
  512. // if AttributeValue is NULL, the attribute is deleted.
  513. if (!m_Attributes[MeetingAttrIndex(Attribute)].set(AttributeValue))
  514. {
  515. LOG((MSP_ERROR, "Can not add attribute %S",
  516. MeetingAttributeName(Attribute)));
  517. return E_OUTOFMEMORY;
  518. }
  519. LOG((MSP_INFO, "CConference::%S is set to %S",
  520. MeetingAttributeName(Attribute), AttributeValue));
  521. return S_OK;
  522. }
  523. /////////////////////////////////////////////////////////////////////////////
  524. // ITConference interface
  525. /////////////////////////////////////////////////////////////////////////////
  526. STDMETHODIMP CConference::get_Name(BSTR * ppVal)
  527. {
  528. return m_pITConfBlobPrivate->GetName(ppVal);
  529. }
  530. STDMETHODIMP CConference::put_Name(BSTR pVal)
  531. {
  532. return m_pITConfBlobPrivate->SetName(pVal);
  533. }
  534. STDMETHODIMP CConference::get_Protocol(BSTR * ppVal)
  535. {
  536. return GetSingleValueBstr(MA_PROTOCOL, ppVal);
  537. }
  538. /*
  539. *
  540. * I've removed the following method from the interface because I don't plan
  541. * to ever implement it.
  542. *
  543. STDMETHODIMP CConference::put_Protocol(BSTR newVal)
  544. {
  545. // currently not allowed to change this
  546. // only IP Conference is supported
  547. return E_NOTIMPL;
  548. }
  549. *
  550. * The following are implemented but don't work. Again these are useless
  551. * methods! Removed from the interface.
  552. *
  553. STDMETHODIMP CConference::get_ConferenceType(BSTR * ppVal)
  554. {
  555. return GetSingleValueBstr(MA_TYPE, ppVal);
  556. }
  557. STDMETHODIMP CConference::put_ConferenceType(BSTR newVal)
  558. {
  559. return SetSingleValue(MA_TYPE, newVal);
  560. }
  561. */
  562. STDMETHODIMP CConference::get_Originator(BSTR * ppVal)
  563. {
  564. return m_pITConfBlobPrivate->GetOriginator(ppVal);
  565. }
  566. STDMETHODIMP CConference::put_Originator(BSTR newVal)
  567. {
  568. return m_pITConfBlobPrivate->SetOriginator(newVal);
  569. }
  570. STDMETHODIMP CConference::get_AdvertisingScope(
  571. RND_ADVERTISING_SCOPE *pAdvertisingScope
  572. )
  573. {
  574. return m_pITConfBlobPrivate->GetAdvertisingScope(pAdvertisingScope);
  575. }
  576. STDMETHODIMP CConference::put_AdvertisingScope(
  577. RND_ADVERTISING_SCOPE AdvertisingScope
  578. )
  579. {
  580. return m_pITConfBlobPrivate->SetAdvertisingScope(AdvertisingScope);
  581. }
  582. STDMETHODIMP CConference::get_Url(BSTR * ppVal)
  583. {
  584. return m_pITConfBlobPrivate->GetUrl(ppVal);
  585. }
  586. STDMETHODIMP CConference::put_Url(BSTR newVal)
  587. {
  588. return m_pITConfBlobPrivate->SetUrl(newVal);
  589. }
  590. STDMETHODIMP CConference::get_Description(BSTR * ppVal)
  591. {
  592. return m_pITConfBlobPrivate->GetDescription(ppVal);
  593. }
  594. STDMETHODIMP CConference::put_Description(BSTR newVal)
  595. {
  596. return m_pITConfBlobPrivate->SetDescription(newVal);
  597. }
  598. STDMETHODIMP CConference::get_IsEncrypted(VARIANT_BOOL *pfEncrypted)
  599. {
  600. if ( IsBadWritePtr(pfEncrypted, sizeof(VARIANT_BOOL)) )
  601. {
  602. LOG((MSP_ERROR, "CConference::get_IsEncrypted : bad pointer passed in"));
  603. return E_POINTER;
  604. }
  605. // We don't support encrypted streaming at all.
  606. *pfEncrypted = VARIANT_FALSE;
  607. return S_OK;
  608. // ILS server (NT 5 beta 1) has IsEncrypted as a dword, this will be modified
  609. // to a string afterwards at that time the code below should replace
  610. // the current implementation
  611. // return GetSingleValueBstr(MA_IS_ENCRYPTED, pVal);
  612. }
  613. STDMETHODIMP CConference::put_IsEncrypted(VARIANT_BOOL fEncrypted)
  614. {
  615. // We don't allow changes to this. See get_IsEncrypted.
  616. return E_NOTIMPL;
  617. // ILS server (NT 5 beta 1) has IsEncrypted as a dword, this will be modified
  618. // to a string afterwards at that time the code below should replace the
  619. // current implementation no need to notify the conference blob of the change
  620. // return SetSingleValue(MA_IS_ENCRYPTED, newVal);
  621. }
  622. inline
  623. DWORD_PTR TimetToNtpTime(IN time_t TimetVal)
  624. {
  625. return TimetVal + NTP_OFFSET;
  626. }
  627. inline
  628. time_t NtpTimeToTimet(IN DWORD_PTR NtpTime)
  629. {
  630. return NtpTime - NTP_OFFSET;
  631. }
  632. inline HRESULT
  633. SystemTimeToNtpTime(
  634. IN SYSTEMTIME &Time,
  635. OUT DWORD &NtpDword
  636. )
  637. {
  638. _ASSERTE(FIRST_POSSIBLE_YEAR <= Time.wYear);
  639. // fill in a tm struct with the values
  640. tm NtpTmStruct;
  641. NtpTmStruct.tm_isdst = -1; // no info available about daylight savings time
  642. NtpTmStruct.tm_year = (int)Time.wYear - 1900;
  643. NtpTmStruct.tm_mon = (int)Time.wMonth - 1; // months since january
  644. NtpTmStruct.tm_mday = (int)Time.wDay;
  645. NtpTmStruct.tm_wday = (int)Time.wDayOfWeek;
  646. NtpTmStruct.tm_hour = (int)Time.wHour;
  647. NtpTmStruct.tm_min = (int)Time.wMinute;
  648. NtpTmStruct.tm_sec = (int)Time.wSecond;
  649. // try to convert into a time_t value
  650. time_t TimetVal = mktime(&NtpTmStruct);
  651. if ( -1 == TimetVal )
  652. {
  653. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  654. }
  655. // convert the time_t value into an NTP value
  656. NtpDword = (DWORD) TimetToNtpTime(TimetVal);
  657. return S_OK;
  658. }
  659. inline
  660. HRESULT
  661. NtpTimeToSystemTime(
  662. IN DWORD dwNtpTime,
  663. OUT SYSTEMTIME &Time
  664. )
  665. {
  666. // if the gen time is WSTR_GEN_TIME_ZERO then,
  667. // all the out parameters should be set to 0
  668. if (dwNtpTime == 0)
  669. {
  670. memset(&Time, 0, sizeof(SYSTEMTIME));
  671. return S_OK;
  672. }
  673. time_t Timet = NtpTimeToTimet(dwNtpTime);
  674. // get the local tm struct for this time value
  675. tm* pTimet = localtime(&Timet);
  676. if( IsBadReadPtr(pTimet, sizeof(tm) ))
  677. {
  678. return E_FAIL;
  679. }
  680. tm LocalTm = *pTimet;
  681. //
  682. // win64: added casts below
  683. //
  684. // set the ref parameters to the tm struct values
  685. Time.wYear = (WORD) ( LocalTm.tm_year + 1900 ); // years since 1900
  686. Time.wMonth = (WORD) ( LocalTm.tm_mon + 1 ); // months SINCE january (0,11)
  687. Time.wDay = (WORD) LocalTm.tm_mday;
  688. Time.wDayOfWeek = (WORD) LocalTm.tm_wday;
  689. Time.wHour = (WORD) LocalTm.tm_hour;
  690. Time.wMinute = (WORD) LocalTm.tm_min;
  691. Time.wSecond = (WORD) LocalTm.tm_sec;
  692. Time.wMilliseconds = (WORD) 0;
  693. return S_OK;
  694. }
  695. STDMETHODIMP CConference::get_StartTime(DATE *pDate)
  696. {
  697. LOG((MSP_INFO, "CConference::get_StartTime - enter"));
  698. BAIL_IF_BAD_WRITE_PTR(pDate, E_POINTER);
  699. DWORD dwStartTime;
  700. HRESULT hr = m_pITConfBlobPrivate->GetStartTime(&dwStartTime);
  701. BAIL_IF_FAIL(hr, "GetStartTime from blob");
  702. // special case for permanent / unbounded conferences
  703. // return the variant time zero. In the put_ methods this
  704. // is also considered a special value. We will never
  705. // actually use zero as a valid time because it is so
  706. // far in the past.
  707. if ( dwStartTime == 0 )
  708. {
  709. *pDate = 0; // special "unbounded" value
  710. LOG((MSP_INFO, "CConference::get_StartTime - unbounded/permanent "
  711. "- exit S_OK"));
  712. return S_OK;
  713. }
  714. // break the generalized time entry into the year,
  715. // month, day, hour and minute (local values)
  716. SYSTEMTIME Time;
  717. hr = NtpTimeToSystemTime(dwStartTime, Time);
  718. if( FAILED(hr) )
  719. {
  720. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  721. }
  722. DOUBLE vtime;
  723. if (SystemTimeToVariantTime(&Time, &vtime) == FALSE)
  724. {
  725. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  726. }
  727. *pDate = vtime;
  728. LOG((MSP_INFO, "CConference::get_StartTime - exit S_OK"));
  729. return S_OK;
  730. }
  731. STDMETHODIMP CConference::put_StartTime(DATE Date)
  732. {
  733. SYSTEMTIME Time;
  734. if (VariantTimeToSystemTime(Date, &Time) == FALSE)
  735. {
  736. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  737. }
  738. DWORD dwNtpStartTime;
  739. if (Date == 0)
  740. {
  741. // unbounded start time
  742. dwNtpStartTime = 0;
  743. }
  744. else if ( FIRST_POSSIBLE_YEAR > Time.wYear )
  745. {
  746. // cannot handle years less than FIRST_POSSIBLE_YEAR
  747. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  748. }
  749. else
  750. {
  751. BAIL_IF_FAIL(
  752. SystemTimeToNtpTime(Time, dwNtpStartTime),
  753. "getNtpDword"
  754. );
  755. }
  756. // notify the conference blob of the change
  757. HRESULT hr = m_pITConfBlobPrivate->SetStartTime(dwNtpStartTime);
  758. BAIL_IF_FAIL(hr, "SetStartTime from to blob");
  759. return S_OK;
  760. }
  761. STDMETHODIMP CConference::get_StopTime(DATE *pDate)
  762. {
  763. LOG((MSP_INFO, "CConference::get_StopTime - enter"));
  764. BAIL_IF_BAD_WRITE_PTR(pDate, E_POINTER);
  765. DWORD dwStopTime;
  766. HRESULT hr = m_pITConfBlobPrivate->GetStopTime(&dwStopTime);
  767. BAIL_IF_FAIL(hr, "GetStopTime from blob");
  768. // special case for permanent / unbounded conferences
  769. // return the variant time zero. In the put_ methods this
  770. // is also considered a special value. We will never
  771. // actually use zero as a valid time because it is so
  772. // far in the past.
  773. if ( dwStopTime == 0 )
  774. {
  775. *pDate = 0; // special "unbounded" value
  776. LOG((MSP_INFO, "CConference::get_StopTime - unbounded/permanent "
  777. "- exit S_OK"));
  778. return S_OK;
  779. }
  780. // break the generalized time entry into the year,
  781. // month, day, hour and minute (local values)
  782. SYSTEMTIME Time;
  783. hr =NtpTimeToSystemTime(dwStopTime, Time);
  784. if( FAILED(hr) )
  785. {
  786. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  787. }
  788. DOUBLE vtime;
  789. if (SystemTimeToVariantTime(&Time, &vtime) == FALSE)
  790. {
  791. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  792. }
  793. *pDate = vtime;
  794. LOG((MSP_INFO, "CConference::get_StopTime - exit S_OK"));
  795. return S_OK;
  796. }
  797. STDMETHODIMP CConference::put_StopTime(DATE Date)
  798. {
  799. SYSTEMTIME Time;
  800. if (VariantTimeToSystemTime(Date, &Time) == FALSE)
  801. {
  802. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  803. }
  804. DWORD dwNtpStopTime;
  805. if (Date == 0)
  806. {
  807. // unbounded start time
  808. dwNtpStopTime = 0;
  809. }
  810. else if ( FIRST_POSSIBLE_YEAR > Time.wYear )
  811. {
  812. // cannot handle years less than FIRST_POSSIBLE_YEAR
  813. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  814. }
  815. else
  816. {
  817. BAIL_IF_FAIL(
  818. SystemTimeToNtpTime(Time, dwNtpStopTime),
  819. "getNtpDword"
  820. );
  821. // determine current time
  822. time_t CurrentTime = time(NULL);
  823. if (dwNtpStopTime <= TimetToNtpTime(CurrentTime))
  824. {
  825. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  826. }
  827. }
  828. // notify the conference blob of the change
  829. HRESULT hr = m_pITConfBlobPrivate->SetStopTime(dwNtpStopTime);
  830. BAIL_IF_FAIL(hr, "SetStopTime from to blob");
  831. return S_OK;
  832. }
  833. /////////////////////////////////////////////////////////////////////////////
  834. // ITDirectoryObject
  835. /////////////////////////////////////////////////////////////////////////////
  836. STDMETHODIMP CConference::get_DialableAddrs(
  837. IN long dwAddressTypes, //defined in tapi.h
  838. OUT VARIANT * pVariant
  839. )
  840. {
  841. BAIL_IF_BAD_WRITE_PTR(pVariant, E_POINTER);
  842. BSTR *Addresses = new BSTR[1]; // only one for now.
  843. BAIL_IF_NULL(Addresses, E_OUTOFMEMORY);
  844. HRESULT hr;
  845. switch (dwAddressTypes) // ZoltanS fix
  846. {
  847. case LINEADDRESSTYPE_SDP:
  848. hr = UpdateConferenceBlob(m_pIUnkConfBlob);
  849. if ( FAILED(hr) )
  850. {
  851. LOG((MSP_ERROR, "CConference::get_DialableAddrs - "
  852. "failed to update blob attribute from the blob object"));
  853. }
  854. else
  855. {
  856. hr = GetSingleValueBstr(MA_CONFERENCE_BLOB, &Addresses[0]);
  857. }
  858. break;
  859. default:
  860. hr = E_FAIL; // just return 0 addresses
  861. break;
  862. }
  863. DWORD dwCount = (FAILED(hr)) ? 0 : 1;
  864. hr = ::CreateBstrCollection(dwCount, // count
  865. &Addresses[0], // begin pointer
  866. &Addresses[dwCount], // end pointer
  867. pVariant, // return value
  868. AtlFlagTakeOwnership); // flags
  869. // the collection will destroy the Addresses array eventually.
  870. // no need to free anything here. Even if we tell it to hand
  871. // out zero objects, it will delete the array on construction.
  872. // (ZoltanS verified.)
  873. return hr;
  874. }
  875. STDMETHODIMP CConference::EnumerateDialableAddrs(
  876. IN DWORD dwAddressTypes, //defined in tapi.h
  877. OUT IEnumDialableAddrs ** ppEnumDialableAddrs
  878. )
  879. {
  880. BAIL_IF_BAD_WRITE_PTR(ppEnumDialableAddrs, E_POINTER);
  881. BSTR *Addresses = new BSTR[1]; // only one for now.
  882. BAIL_IF_NULL(Addresses, E_OUTOFMEMORY);
  883. HRESULT hr;
  884. switch (dwAddressTypes) // ZoltanS fix
  885. {
  886. case LINEADDRESSTYPE_SDP:
  887. hr = UpdateConferenceBlob(m_pIUnkConfBlob);
  888. if ( FAILED(hr) )
  889. {
  890. LOG((MSP_ERROR, "CConference::EnumerateDialableAddrs - "
  891. "failed to update blob attribute from the blob object"));
  892. }
  893. else
  894. {
  895. hr = GetSingleValueBstr(MA_CONFERENCE_BLOB, &Addresses[0]);
  896. }
  897. break;
  898. default:
  899. hr = E_FAIL; // just return 0 addresses
  900. break;
  901. }
  902. DWORD dwCount = (FAILED(hr)) ? 0 : 1;
  903. hr = ::CreateDialableAddressEnumerator(
  904. &Addresses[0],
  905. &Addresses[dwCount],
  906. ppEnumDialableAddrs
  907. );
  908. // the enumerator will destroy the Addresses array eventually,
  909. // so no need to free anything here. Even if we tell it to hand
  910. // out zero objects, it will delete the array on destruction.
  911. // (ZoltanS verified.)
  912. return hr;
  913. }
  914. STDMETHODIMP CConference::GetAttribute(
  915. IN OBJECT_ATTRIBUTE Attribute,
  916. OUT BSTR * ppAttributeValue
  917. )
  918. {
  919. if (Attribute == MA_CONFERENCE_BLOB)
  920. {
  921. BAIL_IF_FAIL(
  922. UpdateConferenceBlob(m_pIUnkConfBlob),
  923. "update blob attribute from the blob object"
  924. );
  925. }
  926. return GetSingleValueBstr(Attribute, ppAttributeValue);
  927. }
  928. STDMETHODIMP CConference::SetAttribute(
  929. IN OBJECT_ATTRIBUTE Attribute,
  930. IN BSTR pAttributeValue
  931. )
  932. {
  933. // this function is never called in the current implementation.
  934. // However, it might be useful in the future.
  935. return SetSingleValue(Attribute, pAttributeValue);
  936. }
  937. STDMETHODIMP CConference::GetTTL(
  938. OUT DWORD * pdwTTL
  939. )
  940. {
  941. LOG((MSP_INFO, "CConference::GetTTL - enter"));
  942. //
  943. // Check arguments.
  944. //
  945. BAIL_IF_BAD_WRITE_PTR(pdwTTL, E_POINTER);
  946. //
  947. // Get the stop time from the conference blob.
  948. //
  949. DWORD dwStopTime;
  950. HRESULT hr = m_pITConfBlobPrivate->GetStopTime(&dwStopTime);
  951. BAIL_IF_FAIL(hr, "GetStopTime from blob");
  952. //
  953. // If the blob has zero as the stop time, then this conference does not
  954. // have an explicit end time. The RFC calls this an "unbounded" session
  955. // (or a "permanent" session if the start time is also zero. In this
  956. // case we use some very large value (MAX_TTL) as the TTL.
  957. //
  958. if ( dwStopTime == 0 )
  959. {
  960. *pdwTTL = MAX_TTL;
  961. LOG((MSP_INFO, "CConference::GetTTL - unbounded or permanent "
  962. "conference - exit S_OK"));
  963. return S_OK;
  964. }
  965. //
  966. // Determine the current NTP time.
  967. //
  968. time_t CurrentTime = time(NULL);
  969. DWORD dwCurrentTime = (DWORD) TimetToNtpTime(CurrentTime);
  970. //
  971. // Error if the current time is later than the conference stop time.
  972. //
  973. if ( dwStopTime <= dwCurrentTime )
  974. {
  975. LOG((MSP_ERROR, "CConference::GetTTL - bounded conference - "
  976. "current time is later than start time - "
  977. "exit RND_INVALID_TIME"));
  978. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  979. }
  980. //
  981. // Return how much time from now until the conference expires.
  982. //
  983. *pdwTTL = dwStopTime - (DWORD) TimetToNtpTime(CurrentTime);
  984. LOG((MSP_INFO, "CConference::GetTTL - bounded conference - "
  985. "exit S_OK"));
  986. return S_OK;
  987. }
  988. typedef IDispatchImpl<ITDirectoryObjectConferenceVtbl<CConference>, &IID_ITDirectoryObjectConference, &LIBID_RENDLib> CTDirObjConference;
  989. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  990. //
  991. // CConference::GetIDsOfNames
  992. //
  993. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  994. STDMETHODIMP CConference::GetIDsOfNames(REFIID riid,
  995. LPOLESTR* rgszNames,
  996. UINT cNames,
  997. LCID lcid,
  998. DISPID* rgdispid
  999. )
  1000. {
  1001. LOG((MSP_TRACE, "CConference::GetIDsOfNames[%p] - enter. Name [%S]",this, *rgszNames));
  1002. HRESULT hr = DISP_E_UNKNOWNNAME;
  1003. //
  1004. // See if the requsted method belongs to the default interface
  1005. //
  1006. hr = CTDirObjConference::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  1007. if (SUCCEEDED(hr))
  1008. {
  1009. LOG((MSP_TRACE, "CConference:GetIDsOfNames - found %S on CTDirObjConference", *rgszNames));
  1010. rgdispid[0] |= IDISPDIROBJCONFERENCE;
  1011. return hr;
  1012. }
  1013. //
  1014. // If not, then try the CDirectoryObject base class
  1015. //
  1016. hr = CDirectoryObject::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  1017. if (SUCCEEDED(hr))
  1018. {
  1019. LOG((MSP_TRACE, "CConference::GetIDsOfNames - found %S on CDirectoryObject", *rgszNames));
  1020. rgdispid[0] |= IDISPDIROBJECT;
  1021. return hr;
  1022. }
  1023. LOG((MSP_ERROR, "CConference::GetIDsOfNames[%p] - finish. didn't find %S on our iterfaces",*rgszNames));
  1024. return hr;
  1025. }
  1026. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1027. //
  1028. // CConference::Invoke
  1029. //
  1030. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1031. STDMETHODIMP CConference::Invoke(DISPID dispidMember,
  1032. REFIID riid,
  1033. LCID lcid,
  1034. WORD wFlags,
  1035. DISPPARAMS* pdispparams,
  1036. VARIANT* pvarResult,
  1037. EXCEPINFO* pexcepinfo,
  1038. UINT* puArgErr
  1039. )
  1040. {
  1041. LOG((MSP_TRACE, "CConference::Invoke[%p] - enter. dispidMember %lx",this, dispidMember));
  1042. HRESULT hr = DISP_E_MEMBERNOTFOUND;
  1043. DWORD dwInterface = (dispidMember & INTERFACEMASK);
  1044. //
  1045. // Call invoke for the required interface
  1046. //
  1047. switch (dwInterface)
  1048. {
  1049. case IDISPDIROBJCONFERENCE:
  1050. {
  1051. hr = CTDirObjConference::Invoke(dispidMember,
  1052. riid,
  1053. lcid,
  1054. wFlags,
  1055. pdispparams,
  1056. pvarResult,
  1057. pexcepinfo,
  1058. puArgErr
  1059. );
  1060. LOG((MSP_TRACE, "CConference::Invoke - ITDirectoryObjectConference"));
  1061. break;
  1062. }
  1063. case IDISPDIROBJECT:
  1064. {
  1065. hr = CDirectoryObject::Invoke(dispidMember,
  1066. riid,
  1067. lcid,
  1068. wFlags,
  1069. pdispparams,
  1070. pvarResult,
  1071. pexcepinfo,
  1072. puArgErr
  1073. );
  1074. LOG((MSP_TRACE, "CConference::Invoke - ITDirectoryObject"));
  1075. break;
  1076. }
  1077. } // end switch (dwInterface)
  1078. LOG((MSP_TRACE, "CConference::Invoke[%p] - finish. hr = %lx", hr));
  1079. return hr;
  1080. }
  1081. // eof