Leaked source code of windows server 2003
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.

1429 lines
35 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. return S_OK;
  447. }
  448. HRESULT
  449. CConference::GetSingleValueWstr(
  450. IN OBJECT_ATTRIBUTE Attribute,
  451. IN DWORD dwSize,
  452. OUT WCHAR * AttributeValue
  453. )
  454. /*++
  455. Routine Description:
  456. Get the value of an attribute. copy the value to the buffer provided.
  457. Arguments:
  458. Attribute - the attribute id as defined in rend.idl
  459. AttributeValue - a pointer to a buffer where the value will be copied to.
  460. Return Value:
  461. HRESULT.
  462. --*/
  463. {
  464. LOG((MSP_INFO, "CConference::GetSingleValueWstr - entered"));
  465. _ASSERTE(NULL != AttributeValue);
  466. _ASSERTE(ValidMeetingAttribute(Attribute));
  467. CLock Lock(m_lock);
  468. if(!m_Attributes[MeetingAttrIndex(Attribute)])
  469. {
  470. LOG((MSP_ERROR, "Attribute %S is not found",
  471. MeetingAttributeName(Attribute)));
  472. return E_FAIL;
  473. }
  474. // copy the attribute value
  475. lstrcpynW(
  476. AttributeValue,
  477. m_Attributes[MeetingAttrIndex(Attribute)],
  478. dwSize
  479. );
  480. return S_OK;
  481. }
  482. HRESULT
  483. CConference::SetSingleValue(
  484. IN OBJECT_ATTRIBUTE Attribute,
  485. IN WCHAR * AttributeValue
  486. )
  487. /*++
  488. Routine Description:
  489. Set the attribute value to a new string.
  490. Arguments:
  491. Attribute - the attribute id as defined in rend.idl
  492. AttributeValue - the new value. If it is null, the value is deleted.
  493. Return Value:
  494. HRESULT.
  495. --*/
  496. {
  497. LOG((MSP_INFO, "CConference::SetSingleValue - entered"));
  498. if (!ValidMeetingAttribute(Attribute))
  499. {
  500. LOG((MSP_ERROR, "Invalid Attribute, %d", Attribute));
  501. return E_FAIL;
  502. }
  503. if (AttributeValue != NULL)
  504. {
  505. BAIL_IF_BAD_READ_PTR(AttributeValue, E_POINTER);
  506. }
  507. CLock Lock(m_lock);
  508. // if AttributeValue is NULL, the attribute is deleted.
  509. if (!m_Attributes[MeetingAttrIndex(Attribute)].set(AttributeValue))
  510. {
  511. LOG((MSP_ERROR, "Can not add attribute %S",
  512. MeetingAttributeName(Attribute)));
  513. return E_OUTOFMEMORY;
  514. }
  515. return S_OK;
  516. }
  517. /////////////////////////////////////////////////////////////////////////////
  518. // ITConference interface
  519. /////////////////////////////////////////////////////////////////////////////
  520. STDMETHODIMP CConference::get_Name(BSTR * ppVal)
  521. {
  522. return m_pITConfBlobPrivate->GetName(ppVal);
  523. }
  524. STDMETHODIMP CConference::put_Name(BSTR pVal)
  525. {
  526. return m_pITConfBlobPrivate->SetName(pVal);
  527. }
  528. STDMETHODIMP CConference::get_Protocol(BSTR * ppVal)
  529. {
  530. return GetSingleValueBstr(MA_PROTOCOL, ppVal);
  531. }
  532. /*
  533. *
  534. * I've removed the following method from the interface because I don't plan
  535. * to ever implement it.
  536. *
  537. STDMETHODIMP CConference::put_Protocol(BSTR newVal)
  538. {
  539. // currently not allowed to change this
  540. // only IP Conference is supported
  541. return E_NOTIMPL;
  542. }
  543. *
  544. * The following are implemented but don't work. Again these are useless
  545. * methods! Removed from the interface.
  546. *
  547. STDMETHODIMP CConference::get_ConferenceType(BSTR * ppVal)
  548. {
  549. return GetSingleValueBstr(MA_TYPE, ppVal);
  550. }
  551. STDMETHODIMP CConference::put_ConferenceType(BSTR newVal)
  552. {
  553. return SetSingleValue(MA_TYPE, newVal);
  554. }
  555. */
  556. STDMETHODIMP CConference::get_Originator(BSTR * ppVal)
  557. {
  558. return m_pITConfBlobPrivate->GetOriginator(ppVal);
  559. }
  560. STDMETHODIMP CConference::put_Originator(BSTR newVal)
  561. {
  562. return m_pITConfBlobPrivate->SetOriginator(newVal);
  563. }
  564. STDMETHODIMP CConference::get_AdvertisingScope(
  565. RND_ADVERTISING_SCOPE *pAdvertisingScope
  566. )
  567. {
  568. return m_pITConfBlobPrivate->GetAdvertisingScope(pAdvertisingScope);
  569. }
  570. STDMETHODIMP CConference::put_AdvertisingScope(
  571. RND_ADVERTISING_SCOPE AdvertisingScope
  572. )
  573. {
  574. return m_pITConfBlobPrivate->SetAdvertisingScope(AdvertisingScope);
  575. }
  576. STDMETHODIMP CConference::get_Url(BSTR * ppVal)
  577. {
  578. return m_pITConfBlobPrivate->GetUrl(ppVal);
  579. }
  580. STDMETHODIMP CConference::put_Url(BSTR newVal)
  581. {
  582. return m_pITConfBlobPrivate->SetUrl(newVal);
  583. }
  584. STDMETHODIMP CConference::get_Description(BSTR * ppVal)
  585. {
  586. return m_pITConfBlobPrivate->GetDescription(ppVal);
  587. }
  588. STDMETHODIMP CConference::put_Description(BSTR newVal)
  589. {
  590. return m_pITConfBlobPrivate->SetDescription(newVal);
  591. }
  592. STDMETHODIMP CConference::get_IsEncrypted(VARIANT_BOOL *pfEncrypted)
  593. {
  594. if ( IsBadWritePtr(pfEncrypted, sizeof(VARIANT_BOOL)) )
  595. {
  596. LOG((MSP_ERROR, "CConference::get_IsEncrypted : bad pointer passed in"));
  597. return E_POINTER;
  598. }
  599. // We don't support encrypted streaming at all.
  600. *pfEncrypted = VARIANT_FALSE;
  601. return S_OK;
  602. // ILS server (NT 5 beta 1) has IsEncrypted as a dword, this will be modified
  603. // to a string afterwards at that time the code below should replace
  604. // the current implementation
  605. // return GetSingleValueBstr(MA_IS_ENCRYPTED, pVal);
  606. }
  607. STDMETHODIMP CConference::put_IsEncrypted(VARIANT_BOOL fEncrypted)
  608. {
  609. // We don't allow changes to this. See get_IsEncrypted.
  610. return E_NOTIMPL;
  611. // ILS server (NT 5 beta 1) has IsEncrypted as a dword, this will be modified
  612. // to a string afterwards at that time the code below should replace the
  613. // current implementation no need to notify the conference blob of the change
  614. // return SetSingleValue(MA_IS_ENCRYPTED, newVal);
  615. }
  616. inline
  617. DWORD_PTR TimetToNtpTime(IN time_t TimetVal)
  618. {
  619. return TimetVal + NTP_OFFSET;
  620. }
  621. inline
  622. time_t NtpTimeToTimet(IN DWORD_PTR NtpTime)
  623. {
  624. return NtpTime - NTP_OFFSET;
  625. }
  626. inline HRESULT
  627. SystemTimeToNtpTime(
  628. IN SYSTEMTIME &Time,
  629. OUT DWORD &NtpDword
  630. )
  631. {
  632. _ASSERTE(FIRST_POSSIBLE_YEAR <= Time.wYear);
  633. // fill in a tm struct with the values
  634. tm NtpTmStruct;
  635. NtpTmStruct.tm_isdst = -1; // no info available about daylight savings time
  636. NtpTmStruct.tm_year = (int)Time.wYear - 1900;
  637. NtpTmStruct.tm_mon = (int)Time.wMonth - 1; // months since january
  638. NtpTmStruct.tm_mday = (int)Time.wDay;
  639. NtpTmStruct.tm_wday = (int)Time.wDayOfWeek;
  640. NtpTmStruct.tm_hour = (int)Time.wHour;
  641. NtpTmStruct.tm_min = (int)Time.wMinute;
  642. NtpTmStruct.tm_sec = (int)Time.wSecond;
  643. // try to convert into a time_t value
  644. time_t TimetVal = mktime(&NtpTmStruct);
  645. if ( -1 == TimetVal )
  646. {
  647. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  648. }
  649. // convert the time_t value into an NTP value
  650. NtpDword = (DWORD) TimetToNtpTime(TimetVal);
  651. return S_OK;
  652. }
  653. inline
  654. HRESULT
  655. NtpTimeToSystemTime(
  656. IN DWORD dwNtpTime,
  657. OUT SYSTEMTIME &Time
  658. )
  659. {
  660. // if the gen time is WSTR_GEN_TIME_ZERO then,
  661. // all the out parameters should be set to 0
  662. if (dwNtpTime == 0)
  663. {
  664. memset(&Time, 0, sizeof(SYSTEMTIME));
  665. return S_OK;
  666. }
  667. time_t Timet = NtpTimeToTimet(dwNtpTime);
  668. // get the local tm struct for this time value
  669. tm* pTimet = localtime(&Timet);
  670. if( IsBadReadPtr(pTimet, sizeof(tm) ))
  671. {
  672. return E_FAIL;
  673. }
  674. tm LocalTm = *pTimet;
  675. //
  676. // win64: added casts below
  677. //
  678. // set the ref parameters to the tm struct values
  679. Time.wYear = (WORD) ( LocalTm.tm_year + 1900 ); // years since 1900
  680. Time.wMonth = (WORD) ( LocalTm.tm_mon + 1 ); // months SINCE january (0,11)
  681. Time.wDay = (WORD) LocalTm.tm_mday;
  682. Time.wDayOfWeek = (WORD) LocalTm.tm_wday;
  683. Time.wHour = (WORD) LocalTm.tm_hour;
  684. Time.wMinute = (WORD) LocalTm.tm_min;
  685. Time.wSecond = (WORD) LocalTm.tm_sec;
  686. Time.wMilliseconds = (WORD) 0;
  687. return S_OK;
  688. }
  689. STDMETHODIMP CConference::get_StartTime(DATE *pDate)
  690. {
  691. LOG((MSP_INFO, "CConference::get_StartTime - enter"));
  692. BAIL_IF_BAD_WRITE_PTR(pDate, E_POINTER);
  693. DWORD dwStartTime;
  694. HRESULT hr = m_pITConfBlobPrivate->GetStartTime(&dwStartTime);
  695. BAIL_IF_FAIL(hr, "GetStartTime from blob");
  696. // special case for permanent / unbounded conferences
  697. // return the variant time zero. In the put_ methods this
  698. // is also considered a special value. We will never
  699. // actually use zero as a valid time because it is so
  700. // far in the past.
  701. if ( dwStartTime == 0 )
  702. {
  703. *pDate = 0; // special "unbounded" value
  704. LOG((MSP_INFO, "CConference::get_StartTime - unbounded/permanent "
  705. "- exit S_OK"));
  706. return S_OK;
  707. }
  708. // break the generalized time entry into the year,
  709. // month, day, hour and minute (local values)
  710. SYSTEMTIME Time;
  711. hr = NtpTimeToSystemTime(dwStartTime, Time);
  712. if( FAILED(hr) )
  713. {
  714. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  715. }
  716. DOUBLE vtime;
  717. if (SystemTimeToVariantTime(&Time, &vtime) == FALSE)
  718. {
  719. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  720. }
  721. *pDate = vtime;
  722. LOG((MSP_INFO, "CConference::get_StartTime - exit S_OK"));
  723. return S_OK;
  724. }
  725. STDMETHODIMP CConference::put_StartTime(DATE Date)
  726. {
  727. SYSTEMTIME Time;
  728. if (VariantTimeToSystemTime(Date, &Time) == FALSE)
  729. {
  730. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  731. }
  732. DWORD dwNtpStartTime;
  733. if (Date == 0)
  734. {
  735. // unbounded start time
  736. dwNtpStartTime = 0;
  737. }
  738. else if ( FIRST_POSSIBLE_YEAR > Time.wYear )
  739. {
  740. // cannot handle years less than FIRST_POSSIBLE_YEAR
  741. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  742. }
  743. else
  744. {
  745. BAIL_IF_FAIL(
  746. SystemTimeToNtpTime(Time, dwNtpStartTime),
  747. "getNtpDword"
  748. );
  749. }
  750. // notify the conference blob of the change
  751. HRESULT hr = m_pITConfBlobPrivate->SetStartTime(dwNtpStartTime);
  752. BAIL_IF_FAIL(hr, "SetStartTime from to blob");
  753. return S_OK;
  754. }
  755. STDMETHODIMP CConference::get_StopTime(DATE *pDate)
  756. {
  757. LOG((MSP_INFO, "CConference::get_StopTime - enter"));
  758. BAIL_IF_BAD_WRITE_PTR(pDate, E_POINTER);
  759. DWORD dwStopTime;
  760. HRESULT hr = m_pITConfBlobPrivate->GetStopTime(&dwStopTime);
  761. BAIL_IF_FAIL(hr, "GetStopTime from blob");
  762. // special case for permanent / unbounded conferences
  763. // return the variant time zero. In the put_ methods this
  764. // is also considered a special value. We will never
  765. // actually use zero as a valid time because it is so
  766. // far in the past.
  767. if ( dwStopTime == 0 )
  768. {
  769. *pDate = 0; // special "unbounded" value
  770. LOG((MSP_INFO, "CConference::get_StopTime - unbounded/permanent "
  771. "- exit S_OK"));
  772. return S_OK;
  773. }
  774. // break the generalized time entry into the year,
  775. // month, day, hour and minute (local values)
  776. SYSTEMTIME Time;
  777. hr =NtpTimeToSystemTime(dwStopTime, Time);
  778. if( FAILED(hr) )
  779. {
  780. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  781. }
  782. DOUBLE vtime;
  783. if (SystemTimeToVariantTime(&Time, &vtime) == FALSE)
  784. {
  785. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  786. }
  787. *pDate = vtime;
  788. LOG((MSP_INFO, "CConference::get_StopTime - exit S_OK"));
  789. return S_OK;
  790. }
  791. STDMETHODIMP CConference::put_StopTime(DATE Date)
  792. {
  793. SYSTEMTIME Time;
  794. if (VariantTimeToSystemTime(Date, &Time) == FALSE)
  795. {
  796. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  797. }
  798. DWORD dwNtpStopTime;
  799. if (Date == 0)
  800. {
  801. // unbounded start time
  802. dwNtpStopTime = 0;
  803. }
  804. else if ( FIRST_POSSIBLE_YEAR > Time.wYear )
  805. {
  806. // cannot handle years less than FIRST_POSSIBLE_YEAR
  807. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  808. }
  809. else
  810. {
  811. BAIL_IF_FAIL(
  812. SystemTimeToNtpTime(Time, dwNtpStopTime),
  813. "getNtpDword"
  814. );
  815. // determine current time
  816. time_t CurrentTime = time(NULL);
  817. if (dwNtpStopTime <= TimetToNtpTime(CurrentTime))
  818. {
  819. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  820. }
  821. }
  822. // notify the conference blob of the change
  823. HRESULT hr = m_pITConfBlobPrivate->SetStopTime(dwNtpStopTime);
  824. BAIL_IF_FAIL(hr, "SetStopTime from to blob");
  825. return S_OK;
  826. }
  827. /////////////////////////////////////////////////////////////////////////////
  828. // ITDirectoryObject
  829. /////////////////////////////////////////////////////////////////////////////
  830. STDMETHODIMP CConference::get_DialableAddrs(
  831. IN long dwAddressTypes, //defined in tapi.h
  832. OUT VARIANT * pVariant
  833. )
  834. {
  835. BAIL_IF_BAD_WRITE_PTR(pVariant, E_POINTER);
  836. BSTR *Addresses = new BSTR[1]; // only one for now.
  837. BAIL_IF_NULL(Addresses, E_OUTOFMEMORY);
  838. HRESULT hr;
  839. switch (dwAddressTypes) // ZoltanS fix
  840. {
  841. case LINEADDRESSTYPE_SDP:
  842. hr = UpdateConferenceBlob(m_pIUnkConfBlob);
  843. if ( FAILED(hr) )
  844. {
  845. LOG((MSP_ERROR, "CConference::get_DialableAddrs - "
  846. "failed to update blob attribute from the blob object"));
  847. }
  848. else
  849. {
  850. hr = GetSingleValueBstr(MA_CONFERENCE_BLOB, &Addresses[0]);
  851. }
  852. break;
  853. default:
  854. hr = E_FAIL; // just return 0 addresses
  855. break;
  856. }
  857. DWORD dwCount = (FAILED(hr)) ? 0 : 1;
  858. hr = ::CreateBstrCollection(dwCount, // count
  859. &Addresses[0], // begin pointer
  860. &Addresses[dwCount], // end pointer
  861. pVariant, // return value
  862. AtlFlagTakeOwnership); // flags
  863. // the collection will destroy the Addresses array eventually.
  864. // no need to free anything here. Even if we tell it to hand
  865. // out zero objects, it will delete the array on construction.
  866. // (ZoltanS verified.)
  867. return hr;
  868. }
  869. STDMETHODIMP CConference::EnumerateDialableAddrs(
  870. IN DWORD dwAddressTypes, //defined in tapi.h
  871. OUT IEnumDialableAddrs ** ppEnumDialableAddrs
  872. )
  873. {
  874. BAIL_IF_BAD_WRITE_PTR(ppEnumDialableAddrs, E_POINTER);
  875. BSTR *Addresses = new BSTR[1]; // only one for now.
  876. BAIL_IF_NULL(Addresses, E_OUTOFMEMORY);
  877. HRESULT hr;
  878. switch (dwAddressTypes) // ZoltanS fix
  879. {
  880. case LINEADDRESSTYPE_SDP:
  881. hr = UpdateConferenceBlob(m_pIUnkConfBlob);
  882. if ( FAILED(hr) )
  883. {
  884. LOG((MSP_ERROR, "CConference::EnumerateDialableAddrs - "
  885. "failed to update blob attribute from the blob object"));
  886. }
  887. else
  888. {
  889. hr = GetSingleValueBstr(MA_CONFERENCE_BLOB, &Addresses[0]);
  890. }
  891. break;
  892. default:
  893. hr = E_FAIL; // just return 0 addresses
  894. break;
  895. }
  896. DWORD dwCount = (FAILED(hr)) ? 0 : 1;
  897. hr = ::CreateDialableAddressEnumerator(
  898. &Addresses[0],
  899. &Addresses[dwCount],
  900. ppEnumDialableAddrs
  901. );
  902. // the enumerator will destroy the Addresses array eventually,
  903. // so no need to free anything here. Even if we tell it to hand
  904. // out zero objects, it will delete the array on destruction.
  905. // (ZoltanS verified.)
  906. return hr;
  907. }
  908. STDMETHODIMP CConference::GetAttribute(
  909. IN OBJECT_ATTRIBUTE Attribute,
  910. OUT BSTR * ppAttributeValue
  911. )
  912. {
  913. if (Attribute == MA_CONFERENCE_BLOB)
  914. {
  915. BAIL_IF_FAIL(
  916. UpdateConferenceBlob(m_pIUnkConfBlob),
  917. "update blob attribute from the blob object"
  918. );
  919. }
  920. return GetSingleValueBstr(Attribute, ppAttributeValue);
  921. }
  922. STDMETHODIMP CConference::SetAttribute(
  923. IN OBJECT_ATTRIBUTE Attribute,
  924. IN BSTR pAttributeValue
  925. )
  926. {
  927. // this function is never called in the current implementation.
  928. // However, it might be useful in the future.
  929. return SetSingleValue(Attribute, pAttributeValue);
  930. }
  931. STDMETHODIMP CConference::GetTTL(
  932. OUT DWORD * pdwTTL
  933. )
  934. {
  935. LOG((MSP_INFO, "CConference::GetTTL - enter"));
  936. //
  937. // Check arguments.
  938. //
  939. BAIL_IF_BAD_WRITE_PTR(pdwTTL, E_POINTER);
  940. //
  941. // Get the stop time from the conference blob.
  942. //
  943. DWORD dwStopTime;
  944. HRESULT hr = m_pITConfBlobPrivate->GetStopTime(&dwStopTime);
  945. BAIL_IF_FAIL(hr, "GetStopTime from blob");
  946. //
  947. // If the blob has zero as the stop time, then this conference does not
  948. // have an explicit end time. The RFC calls this an "unbounded" session
  949. // (or a "permanent" session if the start time is also zero. In this
  950. // case we use some very large value (MAX_TTL) as the TTL.
  951. //
  952. if ( dwStopTime == 0 )
  953. {
  954. *pdwTTL = MAX_TTL;
  955. LOG((MSP_INFO, "CConference::GetTTL - unbounded or permanent "
  956. "conference - exit S_OK"));
  957. return S_OK;
  958. }
  959. //
  960. // Determine the current NTP time.
  961. //
  962. time_t CurrentTime = time(NULL);
  963. DWORD dwCurrentTime = (DWORD) TimetToNtpTime(CurrentTime);
  964. //
  965. // Error if the current time is later than the conference stop time.
  966. //
  967. if ( dwStopTime <= dwCurrentTime )
  968. {
  969. LOG((MSP_ERROR, "CConference::GetTTL - bounded conference - "
  970. "current time is later than start time - "
  971. "exit RND_INVALID_TIME"));
  972. return HRESULT_FROM_ERROR_CODE(RND_INVALID_TIME);
  973. }
  974. //
  975. // Return how much time from now until the conference expires.
  976. //
  977. *pdwTTL = dwStopTime - (DWORD) TimetToNtpTime(CurrentTime);
  978. LOG((MSP_INFO, "CConference::GetTTL - bounded conference - "
  979. "exit S_OK"));
  980. return S_OK;
  981. }
  982. typedef IDispatchImpl<ITDirectoryObjectConferenceVtbl<CConference>, &IID_ITDirectoryObjectConference, &LIBID_RENDLib> CTDirObjConference;
  983. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  984. //
  985. // CConference::GetIDsOfNames
  986. //
  987. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  988. STDMETHODIMP CConference::GetIDsOfNames(REFIID riid,
  989. LPOLESTR* rgszNames,
  990. UINT cNames,
  991. LCID lcid,
  992. DISPID* rgdispid
  993. )
  994. {
  995. LOG((MSP_TRACE, "CConference::GetIDsOfNames[%p] - enter. Name [%S]",this, *rgszNames));
  996. HRESULT hr = DISP_E_UNKNOWNNAME;
  997. //
  998. // See if the requsted method belongs to the default interface
  999. //
  1000. hr = CTDirObjConference::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  1001. if (SUCCEEDED(hr))
  1002. {
  1003. LOG((MSP_TRACE, "CConference:GetIDsOfNames - found %S on CTDirObjConference", *rgszNames));
  1004. rgdispid[0] |= IDISPDIROBJCONFERENCE;
  1005. return hr;
  1006. }
  1007. //
  1008. // If not, then try the CDirectoryObject base class
  1009. //
  1010. hr = CDirectoryObject::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  1011. if (SUCCEEDED(hr))
  1012. {
  1013. LOG((MSP_TRACE, "CConference::GetIDsOfNames - found %S on CDirectoryObject", *rgszNames));
  1014. rgdispid[0] |= IDISPDIROBJECT;
  1015. return hr;
  1016. }
  1017. LOG((MSP_ERROR, "CConference::GetIDsOfNames[%p] - finish. didn't find %S on our iterfaces",*rgszNames));
  1018. return hr;
  1019. }
  1020. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1021. //
  1022. // CConference::Invoke
  1023. //
  1024. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1025. STDMETHODIMP CConference::Invoke(DISPID dispidMember,
  1026. REFIID riid,
  1027. LCID lcid,
  1028. WORD wFlags,
  1029. DISPPARAMS* pdispparams,
  1030. VARIANT* pvarResult,
  1031. EXCEPINFO* pexcepinfo,
  1032. UINT* puArgErr
  1033. )
  1034. {
  1035. LOG((MSP_TRACE, "CConference::Invoke[%p] - enter. dispidMember %lx",this, dispidMember));
  1036. HRESULT hr = DISP_E_MEMBERNOTFOUND;
  1037. DWORD dwInterface = (dispidMember & INTERFACEMASK);
  1038. //
  1039. // Call invoke for the required interface
  1040. //
  1041. switch (dwInterface)
  1042. {
  1043. case IDISPDIROBJCONFERENCE:
  1044. {
  1045. hr = CTDirObjConference::Invoke(dispidMember,
  1046. riid,
  1047. lcid,
  1048. wFlags,
  1049. pdispparams,
  1050. pvarResult,
  1051. pexcepinfo,
  1052. puArgErr
  1053. );
  1054. LOG((MSP_TRACE, "CConference::Invoke - ITDirectoryObjectConference"));
  1055. break;
  1056. }
  1057. case IDISPDIROBJECT:
  1058. {
  1059. hr = CDirectoryObject::Invoke(dispidMember,
  1060. riid,
  1061. lcid,
  1062. wFlags,
  1063. pdispparams,
  1064. pvarResult,
  1065. pexcepinfo,
  1066. puArgErr
  1067. );
  1068. LOG((MSP_TRACE, "CConference::Invoke - ITDirectoryObject"));
  1069. break;
  1070. }
  1071. } // end switch (dwInterface)
  1072. LOG((MSP_TRACE, "CConference::Invoke[%p] - finish. hr = %lx", hr));
  1073. return hr;
  1074. }
  1075. // eof