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.

1329 lines
40 KiB

  1. /*
  2. - INSCODEC.CPP
  3. -
  4. * Microsoft NetMeeting
  5. * Network Access Controller (NAC) DLL
  6. * Installable codecs interfaces
  7. *
  8. * Revision History:
  9. *
  10. * When Who What
  11. * -------- ------------------ ---------------------------------------
  12. * 01.29.96 Yoram Yaacovi Created
  13. *
  14. * Functions:
  15. * CInstallCodecs
  16. * QueryInterface
  17. * AddRef
  18. * Release
  19. * Initialize
  20. * TranslateHr
  21. * CInstallAudioCodecs
  22. * QueryInterface
  23. * AddRef
  24. * Release
  25. * AddACMFormat
  26. * RemoveACMFormat
  27. * ReorderFormats
  28. * EnumFormats
  29. * FreeBuffer
  30. * CInstallVideoCodecs
  31. * QueryInterface
  32. * AddRef
  33. * Release
  34. * AddVCMFormat
  35. * RemoveVCMFormat
  36. * ReorderFormats
  37. * EnumFormats
  38. * FreeBuffer
  39. * Public:
  40. * Private:
  41. * FreeBuffer
  42. * External:
  43. * CreateInstallCodecs
  44. *
  45. *
  46. * @doc EXTERNAL
  47. *
  48. * Notes:
  49. * @topic Implementation Notes | Below are some implementation notes.
  50. *
  51. * @devnote To add an audio or video format for use with NetMeeting, first obtain the
  52. * appropriate interface by calling the COM CoCreateInstance, providing the desired
  53. * interface (IInstallAudioCodecs or IInstallVideoCodecs). Then call the Add>CMFormat
  54. * method on this interface to add a format, or Remove?CMFormat to remove one. Use
  55. * the EnumFormats method to enumerate the list of formats known to NetMeeting, or
  56. * ReorderFormats to make NetMeeting use these formats in a different priority order
  57. * (see comment in the ReorderFormats description).
  58. *
  59. * @devnote When a vendor uses our API to add a codec format for use with NetMeeting,
  60. * the information about this format is stored in the registry. Whenever we do
  61. * an upgrade install of NetMeeting, we blow away these registry entry,
  62. * together with all the standard registry entries. This is required to avoid
  63. * incompatibility problems. This means that if a user installed a 3rd party codec,
  64. * and then upgraded NetMeeting, he will have to re-add the custom codec.
  65. *
  66. */
  67. #include <precomp.h>
  68. #include <confreg.h> // for setting NetMeeting to manual codec selection
  69. #include <regentry.h> // for setting NetMeeting to manual codec selection
  70. EXTERN_C int g_cICObjects=0;
  71. EXTERN_C HANDLE g_hMutex=NULL;
  72. class CInstallCodecs *g_pIC;
  73. /***************************************************************************
  74. CInstallCodecs
  75. ***************************************************************************/
  76. /***************************************************************************
  77. IUnknown Methods
  78. ***************************************************************************/
  79. HRESULT CInstallCodecs::QueryInterface (REFIID riid, LPVOID *lppNewObj)
  80. {
  81. HRESULT hr = NOERROR;
  82. DEBUGMSG(ZONE_INSTCODEC,("CInstallCodecs::QueryInterface\n"));
  83. #ifdef DEBUG
  84. // parameter validation
  85. if (IsBadReadPtr(&riid, (UINT) sizeof(IID)))
  86. {
  87. hr = ResultFromScode(E_INVALIDARG);
  88. goto out;
  89. }
  90. if (IsBadWritePtr(lppNewObj, sizeof(LPVOID)))
  91. {
  92. hr = ResultFromScode(E_INVALIDARG);
  93. goto out;
  94. }
  95. #endif // DEBUG
  96. *lppNewObj = 0;
  97. if (riid == IID_IUnknown || riid == IID_IInstallCodecs)
  98. *lppNewObj = (IInstallCodecs *) this;
  99. else if (riid == IID_IInstallAudioCodecs)
  100. *lppNewObj = (IInstallAudioCodecs *) &ifAudio;
  101. else if (riid == IID_IInstallVideoCodecs)
  102. *lppNewObj = (IInstallVideoCodecs *) &ifVideo;
  103. else
  104. {
  105. hr = E_NOINTERFACE;
  106. goto out;
  107. }
  108. ((IUnknown *)*lppNewObj)->AddRef ();
  109. out:
  110. DEBUGMSG(ZONE_INSTCODEC,("CInstallCodecs::QueryInterface - leave, hr=0x%x\n", hr));
  111. return hr;
  112. }
  113. ULONG CInstallCodecs::AddRef (void)
  114. {
  115. DEBUGMSG(ZONE_INSTCODEC,("CInstallCodecs::AddRef\n"));
  116. InterlockedIncrement((long *) &m_cRef);
  117. DEBUGMSG(ZONE_INSTCODEC,("CInstallCodecs::AddRef - leave, m_cRef=%d\n", m_cRef));
  118. return m_cRef;
  119. }
  120. ULONG CInstallCodecs::Release (void)
  121. {
  122. DEBUGMSG(ZONE_INSTCODEC,("CInstallCodecs::Release\n"));
  123. // if the cRef is already 0 (shouldn't happen), assert, but let it through
  124. ASSERT(m_cRef);
  125. if (InterlockedDecrement((long *) &m_cRef) == 0)
  126. {
  127. delete this;
  128. }
  129. DEBUGMSG(ZONE_INSTCODEC,("CInstallCodecs::Release - leave, m_cRef=%d\n", m_cRef));
  130. return m_cRef;
  131. }
  132. /***************************************************************************
  133. CInstallAudioCodecs
  134. ***************************************************************************/
  135. /****************************************************************************
  136. * @doc EXTERNAL COMPFUNC AUDIO
  137. *
  138. * @interface IInstallAudioCodecs | This interface provides methods for
  139. * adding audio codec formats for use with NetMeeting, as well as
  140. * removing these formats, enumerating them, and change their use order.
  141. *
  142. ***************************************************************************/
  143. /***************************************************************************
  144. IUnknown Methods
  145. Calling the containing object respective methods
  146. ***************************************************************************/
  147. /****************************************************************************
  148. *
  149. * @method HRESULT | IInstallAudioCodecs | QueryInterface | QueryInterface
  150. *
  151. ***************************************************************************/
  152. HRESULT CInstallAudioCodecs::QueryInterface (REFIID riid, LPVOID *lppNewObj)
  153. {
  154. CInstallCodecs *This=IMPL(CInstallCodecs, ifAudio, this); // the containing object
  155. DEBUGMSG(ZONE_INSTCODEC,("CInstallAudioCodecs::QueryInterface\n"));
  156. DEBUGMSG(ZONE_INSTCODEC,("CInstallAudioCodecs::QueryInterface - leave\n"));
  157. return (This->QueryInterface(riid, lppNewObj));
  158. }
  159. /****************************************************************************
  160. *
  161. * @method ULONG | IInstallAudioCodecs | AddRef | AddRef
  162. *
  163. ***************************************************************************/
  164. ULONG CInstallAudioCodecs::AddRef (void)
  165. {
  166. CInstallCodecs *This=IMPL(CInstallCodecs, ifAudio, this); // the containing object
  167. DEBUGMSG(ZONE_INSTCODEC,("CInstallAudioCodecs::AddRef\n"));
  168. DEBUGMSG(ZONE_INSTCODEC,("CInstallAudioCodecs::AddRef - leave\n"));
  169. return (This->AddRef());
  170. }
  171. /****************************************************************************
  172. *
  173. * @method ULONG | IInstallAudioCodecs | Release | Release
  174. *
  175. ***************************************************************************/
  176. ULONG CInstallAudioCodecs::Release (void)
  177. {
  178. CInstallCodecs *This=IMPL(CInstallCodecs, ifAudio, this); // the containing object
  179. DEBUGMSG(ZONE_INSTCODEC,("CInstallAudioCodecs::Release\n"));
  180. DEBUGMSG(ZONE_INSTCODEC,("CInstallAudioCodecs::Release - leave\n"));
  181. return (This->Release());
  182. }
  183. /****************************************************************************
  184. *
  185. * AddACMFormat
  186. *
  187. * @method HRESULT | IInstallAudioCodecs | AddACMFormat | Adds an ACM encoding
  188. * format for use with NetMeeting
  189. *
  190. * @parm LPWAVEFORMATEX | lpwfx | Pointer to the WAVEFORMATEX structure of the
  191. * format to add
  192. *
  193. * @parm PAUDCAP_INFO | pAudCapInfo | Additional format info that is not in the
  194. * WAVEFORMATEX structure
  195. *
  196. * @rdesc Returns zero (NOERROR) if the function was successful. Otherwise, it returns
  197. * a standard HRESULT, with the WIN32 facility code (7), or the specific facility
  198. * code for installable codecs (0x301).
  199. * Possible error codes:
  200. * @flag E_INVALIDARG | Invalid argument
  201. * @flag IC_E_NO_SUCH_FORMAT | The specified WAVEFORMATEX was not found with ACM.
  202. * The format must be installed with ACM before it can be added for use
  203. * with NetMeeting.
  204. * @flag IC_E_INTERNAL_ERROR | the Network Audio/Video Controller
  205. * reported a system error
  206. *
  207. ***************************************************************************/
  208. HRESULT CInstallAudioCodecs::AddACMFormat(LPWAVEFORMATEX lpwfx, PAUDCAP_INFO pAudCapInfo)
  209. {
  210. CInstallCodecs *This=IMPL(CInstallCodecs, ifAudio, this); // the containing object
  211. HRESULT hr=NOERROR;
  212. DEBUGMSG(ZONE_INSTCODEC,("CInstallAudioCodecs::AddACMFormat\n"));
  213. /*
  214. * Parameter validation
  215. */
  216. // parameters
  217. if (!lpwfx || !pAudCapInfo ||
  218. IsBadReadPtr(lpwfx, (UINT) sizeof(WAVEFORMATEX)) ||
  219. IsBadReadPtr(pAudCapInfo, (UINT) sizeof(AUDCAP_INFO)))
  220. {
  221. hr = E_INVALIDARG;
  222. goto out;
  223. }
  224. // NAC doesn't like a nBlockAlign of 0
  225. if (lpwfx->nBlockAlign == 0)
  226. {
  227. hr = E_INVALIDARG;
  228. goto out;
  229. }
  230. // the format tags in the WAVEFORMAT and the AUDCAP_INFO should match
  231. if (lpwfx->wFormatTag != pAudCapInfo->wFormatTag)
  232. {
  233. hr = E_INVALIDARG;
  234. goto out;
  235. }
  236. // only supporting formats with one audio channel
  237. if (lpwfx->nChannels != 1)
  238. {
  239. hr = E_INVALIDARG;
  240. goto out;
  241. }
  242. /*
  243. * Add the format
  244. */
  245. // add
  246. hr = This->m_pAudAppCaps->AddACMFormat(lpwfx, pAudCapInfo);
  247. out:
  248. if (FAILED(hr))
  249. {
  250. ERRORMSG(("CInstallAudioCodecs::AddACMFormat failed, hr=0x%x\n", hr));
  251. }
  252. DEBUGMSG(ZONE_INSTCODEC,("CInstallAudioCodecs::AddACMFormat - leave\n"));
  253. return This->TranslateHr(hr);
  254. }
  255. /****************************************************************************
  256. *
  257. * RemoveACMFormat
  258. *
  259. * @method HRESULT | IInstallAudioCodecs | RemoveACMFormat | Removes an ACM
  260. * format from the list of formats used by NetMeeting
  261. *
  262. * @parm LPWAVEFORMATEX | lpwfx | Pointer to the WAVEFORMATEX structure for the
  263. * format to remove
  264. *
  265. * @rdesc Returns zero (NOERROR) if the function was successful. Otherwise, it returns
  266. * a standard HRESULT, with the WIN32 facility code (0x7), or the specific facility
  267. * code for installable codecs (0x301).
  268. * Possible error codes:
  269. * @flag E_INVALIDARG | Invalid argument
  270. * @flag IC_E_NO_SUCH_FORMAT | The specified format was not found.
  271. * @flag IC_E_INTERNAL_ERROR | the Network Audio/Video Controller
  272. * reported a system error
  273. *
  274. ***************************************************************************/
  275. HRESULT CInstallAudioCodecs::RemoveACMFormat(LPWAVEFORMATEX lpwfx)
  276. {
  277. CInstallCodecs *This=IMPL(CInstallCodecs, ifAudio, this); // the containing object
  278. HRESULT hr=NOERROR;
  279. DEBUGMSG(ZONE_INSTCODEC,("CInstallAudioCodecs::RemoveACMFormat\n"));
  280. /*
  281. * Parameter validation
  282. */
  283. if (!lpwfx ||
  284. IsBadReadPtr(lpwfx, (UINT) sizeof(WAVEFORMATEX)))
  285. {
  286. hr = E_INVALIDARG;
  287. goto out;
  288. }
  289. // NAC doesn't like a nBlockAlign of 0
  290. if (lpwfx->nBlockAlign == 0)
  291. {
  292. hr = E_INVALIDARG;
  293. goto out;
  294. }
  295. // only supporting formats with one audio channel
  296. if (lpwfx->nChannels != 1)
  297. {
  298. hr = E_INVALIDARG;
  299. goto out;
  300. }
  301. hr = This->m_pAudAppCaps->RemoveACMFormat(lpwfx);
  302. out:
  303. if (FAILED(hr))
  304. {
  305. ERRORMSG(("CInstallAudioCodecs::RemoveACMFormat failed, hr=0x%x\n", hr));
  306. }
  307. DEBUGMSG(ZONE_INSTCODEC,("CInstallAudioCodecs::RemoveACMFormat - leave\n"));
  308. return This->TranslateHr(hr);
  309. }
  310. /****************************************************************************
  311. *
  312. * ReorderFormats
  313. *
  314. * @method HRESULT | IInstallAudioCodecs | ReorderFormats | Reorders the audio
  315. * formats for use with Netmeeting
  316. *
  317. * @parm PAUDCAP_INFO_LIST | pAudCapInfoList | Pointer to a structure with a count
  318. * and a pointer to a list of the formats to reorder. The list is of the
  319. * format AUDCAP_INFO_LIST.
  320. *
  321. * @rdesc Returns zero (NOERROR) if the function was successful. Otherwise, it returns
  322. * a standard HRESULT, with the WIN32 facility code (7), or the specific facility
  323. * code for installable codecs (0x301).
  324. * Possible error codes:
  325. * @flag E_INVALIDARG | Invalid argument
  326. * @flag IC_E_INTERNAL_ERROR | the Network Audio/Video Controller
  327. * reported a system error
  328. *
  329. * @comm Since ReorderFormats can only reorder formats that are known to NetMeeting,
  330. * it is recommended that the caller will first call EnumFormats, to get the
  331. * of all formats known to NetMeeting, assign new sort indices (wSortIndex),
  332. * and then call ReorderFormats with the modified list.
  333. *
  334. * @comm Arranging the formats in a specific order, by using ReorderFormats, does
  335. * not guarantee that the top ranked formats will be used before lower ranked
  336. * formats are used. For example, if the sending system is not capable of
  337. * encoding a top ranked format, this format will not be used. The same
  338. * will happen if the receiving system cannot decode this format.
  339. *
  340. ***************************************************************************/
  341. HRESULT CInstallAudioCodecs::ReorderFormats(PAUDCAP_INFO_LIST pAudCapInfoList)
  342. {
  343. CInstallCodecs *This=IMPL(CInstallCodecs, ifAudio, this); // the containing object
  344. RegEntry re( AUDIO_KEY, HKEY_CURRENT_USER );
  345. HRESULT hr=NOERROR;
  346. DEBUGMSG(ZONE_INSTCODEC,("CInstallAudioCodecs::ReorderFormats\n"));
  347. /*
  348. * Parameter validation
  349. */
  350. if (!pAudCapInfoList ||
  351. IsBadReadPtr(pAudCapInfoList, sizeof(DWORD)) ||
  352. IsBadReadPtr(pAudCapInfoList,
  353. sizeof(AUDCAP_INFO_LIST) + ((pAudCapInfoList->cFormats-1) * sizeof(AUDCAP_INFO))))
  354. {
  355. hr = E_INVALIDARG;
  356. goto out;
  357. }
  358. // fill in the format buffer here
  359. hr = This->m_pAudAppCaps->ApplyAppFormatPrefs(pAudCapInfoList->aFormats,
  360. pAudCapInfoList->cFormats);
  361. if (FAILED(hr))
  362. goto out;
  363. /*
  364. * switch NetMeeting to manual mode
  365. */
  366. // set the registry. failing here won't fail ReorderFormats
  367. re.SetValue(REGVAL_CODECCHOICE, CODECCHOICE_MANUAL);
  368. out:
  369. if (FAILED(hr))
  370. {
  371. ERRORMSG(("CInstallAudioCodecs::ReorderFormats failed, hr=0x%x\n", hr));
  372. }
  373. DEBUGMSG(ZONE_INSTCODEC,("CInstallAudioCodecs::ReorderFormats - leave\n"));
  374. return This->TranslateHr(hr);
  375. }
  376. /****************************************************************************
  377. *
  378. * EnumFormats
  379. *
  380. * @method HRESULT | IInstallAudioCodecs | EnumFormats | Enumerates the audio
  381. * codec formats known to NetMeeting
  382. *
  383. * @parm PAUDCAP_INFO_LIST * | ppAudCapInfoList | Address where this method
  384. * will put a pointer to a AUDCAP_INFO_LIST list, where enumerated formats
  385. * are listed.
  386. *
  387. * @rdesc Returns zero (NOERROR) if the function was successful. Otherwise, it returns
  388. * a standard HRESULT, with the WIN32 facility code (7), or the specific facility
  389. * code for installable codecs (0x301).
  390. * Possible error codes:
  391. * @flag E_INVALIDARG | Invalid argument
  392. * @flag E_OUTOFMEMORY | Not enough memory for allocating the enumeration buffer
  393. * @flag IC_E_NO_FORMATS | No formats were available to enumerate
  394. * @flag IC_E_INTERNAL_ERROR | the Network Audio/Video Controller
  395. * reported a system error
  396. *
  397. * @comm The caller is expected to free the returned list, by calling FreeBuffer
  398. * on the same interface.
  399. *
  400. ***************************************************************************/
  401. HRESULT CInstallAudioCodecs::EnumFormats(PAUDCAP_INFO_LIST *ppAudCapInfoList)
  402. {
  403. CInstallCodecs *This=IMPL(CInstallCodecs, ifAudio, this); // the containing object
  404. ULONG cFormats = 0;
  405. UINT uBufSize = 0;
  406. HRESULT hr=NOERROR;
  407. DEBUGMSG(ZONE_INSTCODEC,("CInstallAudioCodecs::EnumFormats\n"));
  408. /*
  409. * Parameter validation
  410. */
  411. if (!ppAudCapInfoList ||
  412. IsBadWritePtr(ppAudCapInfoList, sizeof(PAUDCAP_INFO_LIST)))
  413. {
  414. hr = E_INVALIDARG;
  415. goto out;
  416. }
  417. // nothing yet....
  418. *ppAudCapInfoList = NULL;
  419. // are there any formats ?
  420. if (HR_FAILED(This->m_pAudAppCaps->GetNumFormats((UINT *) &cFormats)) ||
  421. (cFormats == 0))
  422. {
  423. hr = IC_E_NO_FORMATS;
  424. goto out;
  425. }
  426. // allocate a buffer for the call. the caller is expected to call
  427. // FreeBuffer to free
  428. // AUDCAP_INFO_LIST already includes one AUDCAP_INFO
  429. uBufSize = sizeof(AUDCAP_INFO_LIST) + (cFormats-1) * sizeof(AUDCAP_INFO);
  430. *ppAudCapInfoList = (PAUDCAP_INFO_LIST) MEMALLOC (uBufSize);
  431. if (!(*ppAudCapInfoList))
  432. {
  433. hr = E_OUTOFMEMORY;
  434. goto out;
  435. }
  436. hr = This->m_pAudAppCaps->EnumFormats((*ppAudCapInfoList)->aFormats, uBufSize,
  437. (UINT *) &((*ppAudCapInfoList)->cFormats));
  438. out:
  439. if (FAILED(hr))
  440. {
  441. ERRORMSG(("CInstallAudioCodecs::EnumFormats failed, hr=0x%x\n", hr));
  442. }
  443. DEBUGMSG(ZONE_INSTCODEC,("CInstallAudioCodecs::EnumFormats - leave\n"));
  444. return This->TranslateHr(hr);
  445. }
  446. /****************************************************************************
  447. *
  448. * FreeBuffer
  449. *
  450. * @method HRESULT | IInstallAudioCodecs | FreeBuffer | Free a buffer that was
  451. * returned by the IInstallAudioCodec interface
  452. *
  453. * @parm LPVOID | lpBuffer | Address of the buffer to free. This buffer must have
  454. * been allocated by one of the IInstallAudioCodecs methods
  455. *
  456. * @rdesc Returns zero (NOERROR) if the function was successful. Otherwise, it returns
  457. * a standard HRESULT, with the WIN32 facility code (7), or the specific facility
  458. * code for installable codecs (0x301).
  459. * Possible error codes:
  460. * None
  461. *
  462. ***************************************************************************/
  463. HRESULT CInstallAudioCodecs::FreeBuffer(LPVOID lpBuffer)
  464. {
  465. CInstallCodecs *This=IMPL(CInstallCodecs, ifAudio, this); // the containing object
  466. HRESULT hr = NOERROR;
  467. DEBUGMSG(ZONE_INSTCODEC,("CInstallAudioCodecs::FreeBuffer\n"));
  468. hr = This->FreeBuffer(lpBuffer);
  469. if (FAILED(hr))
  470. {
  471. ERRORMSG(("CInstallAudioCodecs::FreeBuffer failed, hr=0x%x\n", hr));
  472. }
  473. DEBUGMSG(ZONE_INSTCODEC,("CInstallAudioCodecs::FreeBuffer - leave, hr=0x%x\n", hr));
  474. return This->TranslateHr(hr);
  475. }
  476. /***************************************************************************
  477. CInstallVideoCodecs
  478. ***************************************************************************/
  479. /****************************************************************************
  480. * @doc EXTERNAL COMPFUNC VIDEO
  481. ***************************************************************************/
  482. /***************************************************************************
  483. IUnknown Methods
  484. Calling the containing object respective methods
  485. ***************************************************************************/
  486. /****************************************************************************
  487. *
  488. * @method HRESULT | IInstallVideoCodecs | QueryInterface | QueryInterface
  489. *
  490. ***************************************************************************/
  491. HRESULT CInstallVideoCodecs::QueryInterface (REFIID riid, LPVOID *lppNewObj)
  492. {
  493. CInstallCodecs *This=IMPL(CInstallCodecs, ifVideo, this); // the containing object
  494. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::QueryInterface\n"));
  495. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::QueryInterface - leave\n"));
  496. return (This->QueryInterface(riid, lppNewObj));
  497. }
  498. /****************************************************************************
  499. *
  500. * @method ULONG | IInstallVideoCodecs | AddRef | AddRef
  501. *
  502. ***************************************************************************/
  503. ULONG CInstallVideoCodecs::AddRef (void)
  504. {
  505. CInstallCodecs *This=IMPL(CInstallCodecs, ifVideo, this); // the containing object
  506. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::AddRef\n"));
  507. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::AddRef - leave\n"));
  508. return (This->AddRef());
  509. }
  510. /****************************************************************************
  511. *
  512. * @method ULONG | IInstallVideoCodecs | Release | Release
  513. *
  514. ***************************************************************************/
  515. ULONG CInstallVideoCodecs::Release (void)
  516. {
  517. CInstallCodecs *This=IMPL(CInstallCodecs, ifVideo, this); // the containing object
  518. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::Release\n"));
  519. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::Release - leave\n"));
  520. return (This->Release());
  521. }
  522. /****************************************************************************
  523. *
  524. * AddVCMFormat
  525. *
  526. * @method HRESULT | IInstallVideoCodecs | AddVCMFormat | Adds an video encoding
  527. * format for use with NetMeeting
  528. *
  529. * @parm PAUDCAP_INFO | pVidCapInfo | Information on the format to add
  530. *
  531. * @rdesc Returns zero (NOERROR) if the function was successful. Otherwise, it returns
  532. * a standard HRESULT, with the WIN32 facility code (7), or the specific facility
  533. * code for installable codecs (0x301).
  534. * Possible error codes:
  535. * @flag E_INVALIDARG | Invalid argument
  536. * @flag IC_E_NO_SUCH_FORMAT | The specified format was not found. The format
  537. * must be installed with Video For Windows before it can be added for use
  538. * with NetMeeting.
  539. * @flag IC_E_INTERNAL_ERROR | the Network Audio/Video Controller
  540. * reported a system error
  541. *
  542. ***************************************************************************/
  543. HRESULT CInstallVideoCodecs::AddVCMFormat(PVIDCAP_INFO pVidCapInfo)
  544. {
  545. CInstallCodecs *This=IMPL(CInstallCodecs, ifVideo, this); // the containing object
  546. HRESULT hr=NOERROR;
  547. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::AddVCMFormat\n"));
  548. /*
  549. * Add the format
  550. */
  551. hr = AddRemoveVCMFormat(pVidCapInfo, TRUE);
  552. if (FAILED(hr))
  553. {
  554. ERRORMSG(("CInstallVideoCodecs::AddVCMFormat failed, hr=0x%x\n", hr));
  555. }
  556. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::AddVCMFormat - leave\n"));
  557. return This->TranslateHr(hr);
  558. }
  559. /****************************************************************************
  560. *
  561. * RemoveVCMFormat
  562. *
  563. * @method HRESULT | IInstallVideoCodecs | RemoveVCMFormat | Removes an video
  564. * format from the list of formats used by NetMeeting
  565. *
  566. * @parm PVIDCAP_INFO | pVidCapInfo | Pointer to the PVIDCAP_INFO structure
  567. * describing the format to remove
  568. *
  569. * @rdesc Returns zero (NOERROR) if the function was successful. Otherwise, it returns
  570. * a standard HRESULT, with the WIN32 facility code (0x7), or the specific facility
  571. * code for installable codecs (0x301).
  572. * Possible error codes:
  573. * @flag E_INVALIDARG | Invalid argument
  574. * @flag IC_E_NO_SUCH_FORMAT | The specified format was not found.
  575. * @flag IC_E_INTERNAL_ERROR | the Network Audio/Video Controller
  576. * reported a system error
  577. *
  578. ***************************************************************************/
  579. HRESULT CInstallVideoCodecs::RemoveVCMFormat(PVIDCAP_INFO pVidCapInfo)
  580. {
  581. CInstallCodecs *This=IMPL(CInstallCodecs, ifVideo, this); // the containing object
  582. HRESULT hr=NOERROR;
  583. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::RemoveVCMFormat\n"));
  584. /*
  585. * Remove the format
  586. */
  587. hr = AddRemoveVCMFormat(pVidCapInfo, FALSE);
  588. if (FAILED(hr))
  589. {
  590. ERRORMSG(("CInstallVideoCodecs::RemoveVCMFormat failed, hr=0x%x\n", hr));
  591. }
  592. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::RemoveVCMFormat - leave\n"));
  593. return This->TranslateHr(hr);
  594. }
  595. /****************************************************************************
  596. *
  597. * ReorderFormats
  598. *
  599. * @method HRESULT | IInstallVideoCodecs | ReorderFormats | Reorders the video
  600. * formats for use with Netmeeting
  601. *
  602. * @parm PVIDCAP_INFO_LIST | pVidCapInfoList | Pointer to a structure with a count
  603. * and a pointer to a list of the formats to reorder. The list is of the
  604. * format VIDCAP_INFO_LIST.
  605. *
  606. * @rdesc Returns zero (NOERROR) if the function was successful. Otherwise, it returns
  607. * a standard HRESULT, with the WIN32 facility code (7), or the specific facility
  608. * code for installable codecs (0x301).
  609. * Possible error codes:
  610. * @flag E_INVALIDARG | Invalid argument
  611. * @flag IC_E_INTERNAL_ERROR | the Network Audio/Video Controller
  612. * reported a system error
  613. *
  614. * @comm Since ReorderFormats can only reorder formats that are known to NetMeeting,
  615. * it is recommended that the caller will first call EnumFormats, to get the
  616. * of all formats known to NetMeeting, assign new sort indices (wSortIndex),
  617. * and then call ReorderFormats with the modified list.
  618. *
  619. * @comm Arranging the formats in a specific order, by using ReorderFormats, does
  620. * not guarantee that the top ranked formats will be used before lower ranked
  621. * formats are used. For example, if the sending system is not capable of
  622. * encoding a top ranked format, this format will not be used. The same
  623. * will happen if the receiving system cannot decode this format.
  624. *
  625. ***************************************************************************/
  626. HRESULT CInstallVideoCodecs::ReorderFormats(PVIDCAP_INFO_LIST pVidCapInfoList)
  627. {
  628. CInstallCodecs *This=IMPL(CInstallCodecs, ifVideo, this); // the containing object
  629. HRESULT hr=NOERROR;
  630. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::ReorderFormats\n"));
  631. /*
  632. * Parameter validation
  633. */
  634. if (!pVidCapInfoList ||
  635. IsBadReadPtr(pVidCapInfoList, sizeof(DWORD)) ||
  636. IsBadReadPtr(pVidCapInfoList,
  637. sizeof(VIDCAP_INFO_LIST) + ((pVidCapInfoList->cFormats-1) * sizeof(VIDCAP_INFO))))
  638. {
  639. hr = E_INVALIDARG;
  640. goto out;
  641. }
  642. hr = This->m_pVidAppCaps->ApplyAppFormatPrefs(pVidCapInfoList->aFormats,
  643. pVidCapInfoList->cFormats);
  644. out:
  645. if (FAILED(hr))
  646. {
  647. ERRORMSG(("CInstallVideoCodecs::ReorderFormats failed, hr=0x%x\n", hr));
  648. }
  649. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::ReorderFormats - leave\n"));
  650. return This->TranslateHr(hr);
  651. }
  652. /****************************************************************************
  653. *
  654. * EnumFormats
  655. *
  656. * @method HRESULT | IInstallVideoCodecs | EnumFormats | Enumerates the video
  657. * codec formats known to NetMeeting
  658. *
  659. * @parm PVIDCAP_INFO_LIST * | ppVidCapInfoList | Address where this method
  660. * will put a pointer to a VIDCAP_INFO_LIST list, where enumerated formats
  661. * are listed.
  662. *
  663. * @rdesc Returns zero (NOERROR) if the function was successful. Otherwise, it returns
  664. * a standard HRESULT, with the WIN32 facility code (7), or the specific facility
  665. * code for installable codecs (0x301).
  666. * Possible error codes:
  667. * @flag E_INVALIDARG | Invalid argument
  668. * @flag E_OUTOFMEMORY | Not enough memory for allocating the enumeration buffer
  669. * @flag IC_E_NO_FORMATS | No formats were available to enumerate
  670. * @flag IC_E_INTERNAL_ERROR | the Network Audio/Video Controller
  671. * reported a system error
  672. *
  673. * @comm The caller is expected to free the returned list, by calling FreeBuffer
  674. * on the same interface.
  675. *
  676. ***************************************************************************/
  677. HRESULT CInstallVideoCodecs::EnumFormats(PVIDCAP_INFO_LIST *ppVidCapInfoList)
  678. {
  679. CInstallCodecs *This=IMPL(CInstallCodecs, ifVideo, this); // the containing object
  680. ULONG cFormats = 0;
  681. UINT uBufSize = 0;
  682. HRESULT hr=NOERROR;
  683. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::EnumFormats\n"));
  684. /*
  685. * Parameter validation
  686. */
  687. if (!ppVidCapInfoList ||
  688. IsBadWritePtr(ppVidCapInfoList, sizeof(PVIDCAP_INFO_LIST)))
  689. {
  690. hr = E_INVALIDARG;
  691. goto out;
  692. }
  693. // nothing yet....
  694. *ppVidCapInfoList = NULL;
  695. // are there any formats ?
  696. if (HR_FAILED(This->m_pVidAppCaps->GetNumFormats((UINT *) &cFormats)) ||
  697. (cFormats == 0))
  698. {
  699. hr = IC_E_NO_FORMATS;
  700. goto out;
  701. }
  702. // allocate a buffer for the call. the caller is expected to call
  703. // FreeBuffer to free
  704. // VIDCAP_INFO_LIST already includes one VIDCAP_INFO
  705. uBufSize = sizeof(VIDCAP_INFO_LIST) + (cFormats-1) * sizeof(VIDCAP_INFO);
  706. *ppVidCapInfoList = (PVIDCAP_INFO_LIST) MEMALLOC (uBufSize);
  707. if (!(*ppVidCapInfoList))
  708. {
  709. hr = E_OUTOFMEMORY;
  710. goto out;
  711. }
  712. hr = This->m_pVidAppCaps->EnumFormats((*ppVidCapInfoList)->aFormats, uBufSize,
  713. (UINT *) &((*ppVidCapInfoList)->cFormats));
  714. out:
  715. if (FAILED(hr))
  716. {
  717. ERRORMSG(("CInstallVideoCodecs::EnumFormats failed, hr=0x%x\n", hr));
  718. }
  719. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::EnumFormats - leave\n"));
  720. return This->TranslateHr(hr);
  721. }
  722. /****************************************************************************
  723. *
  724. * FreeBuffer
  725. *
  726. * @method HRESULT | IInstallVideoCodecs | FreeBuffer | Free a buffer that was
  727. * returned by the IInstallVideoCodec interface
  728. *
  729. * @parm LPVOID | lpBuffer | Address of the buffer to free. This buffer must have
  730. * been allocated by one of the IInstallVideoCodecs methods
  731. *
  732. * @rdesc Returns zero (NOERROR) if the function was successful. Otherwise, it returns
  733. * a standard HRESULT, with the WIN32 facility code (7), or the specific facility
  734. * code for installable codecs (0x301).
  735. * Possible error codes:
  736. * None
  737. *
  738. ***************************************************************************/
  739. HRESULT CInstallVideoCodecs::FreeBuffer(LPVOID lpBuffer)
  740. {
  741. CInstallCodecs *This=IMPL(CInstallCodecs, ifVideo, this); // the containing object
  742. HRESULT hr = NOERROR;
  743. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::FreeBuffer\n"));
  744. hr = This->FreeBuffer(lpBuffer);
  745. if (FAILED(hr))
  746. {
  747. ERRORMSG(("CInstallVideoCodecs::FreeBuffer failed, hr=0x%x\n", hr));
  748. }
  749. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::FreeBuffer - leave, hr=0x%x\n", hr));
  750. return This->TranslateHr(hr);
  751. }
  752. /****************************************************************************
  753. * @doc INTERNAL COMPFUNC
  754. ***************************************************************************/
  755. /****************************************************************************
  756. *
  757. * AddRemoveVCMFormat
  758. *
  759. * @method HRESULT | IInstallVideoCodecs | AddRemoveVCMFormat | Adds or
  760. * removes a VCM format for use with NetMeeting
  761. *
  762. * @parm PAUDCAP_INFO | pVidCapInfo | Information on the format to add/remove
  763. *
  764. * @parm BOOL | bAdd | TRUE = Add the format, FALSE = Remove the format
  765. *
  766. * @rdesc Returns zero (NOERROR) if the function was successful. Otherwise, it returns
  767. * a standard HRESULT, with the WIN32 facility code (7), or the specific facility
  768. * code for installable codecs (0x301).
  769. * Possible error codes:
  770. * @flag E_INVALIDARG | Invalid argument
  771. * @flag IC_E_NO_SUCH_FORMAT | The specified format was not found. The format
  772. * must be installed with Video For Windows before it can be added for use
  773. * with NetMeeting.
  774. * @flag IC_E_INTERNAL_ERROR | the Network Audio/Video Controller
  775. * reported a system error
  776. *
  777. ***************************************************************************/
  778. HRESULT CInstallVideoCodecs::AddRemoveVCMFormat(PVIDCAP_INFO pVidCapInfo,
  779. BOOL bAdd)
  780. {
  781. CInstallCodecs *This=IMPL(CInstallCodecs, ifVideo, this); // the containing object
  782. VIDEOFORMATEX vfx;
  783. HRESULT hr=NOERROR;
  784. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::AddVCMFormat\n"));
  785. /*
  786. * Parameter validation
  787. */
  788. if (!pVidCapInfo ||
  789. IsBadReadPtr(pVidCapInfo, (UINT) sizeof(VIDCAP_INFO)))
  790. {
  791. hr = E_INVALIDARG;
  792. goto out;
  793. }
  794. // some fields should not be zero
  795. if ((pVidCapInfo->uFrameRate == 0) ||
  796. (pVidCapInfo->uAvgBitrate == 0) ||
  797. ((pVidCapInfo->dwBitsPerSample == 0) &&
  798. (pVidCapInfo->bih.biBitCount == 0)))
  799. {
  800. hr = E_INVALIDARG;
  801. goto out;
  802. }
  803. // make sure dwBitsPerSample and biBitCount match
  804. if (pVidCapInfo->dwBitsPerSample == 0)
  805. pVidCapInfo->dwBitsPerSample = pVidCapInfo->bih.biBitCount;
  806. if (pVidCapInfo->bih.biBitCount == 0)
  807. pVidCapInfo->bih.biBitCount = LOWORD(pVidCapInfo->dwBitsPerSample);
  808. if (LOWORD(pVidCapInfo->dwBitsPerSample) != pVidCapInfo->bih.biBitCount)
  809. {
  810. hr = E_INVALIDARG;
  811. goto out;
  812. }
  813. /*
  814. * Make a VIDEOFORMATEX structure
  815. */
  816. RtlZeroMemory((PVOID) &vfx, sizeof(VIDEOFORMATEX));
  817. // Make sure it's Upper Case
  818. if (pVidCapInfo->dwFormatTag > 256)
  819. CharUpperBuff((LPTSTR)&pVidCapInfo->dwFormatTag, sizeof(DWORD));
  820. vfx.dwFormatTag = pVidCapInfo->dwFormatTag;
  821. vfx.nSamplesPerSec = pVidCapInfo->uFrameRate;
  822. vfx.wBitsPerSample = pVidCapInfo->dwBitsPerSample; // wBitPerSample is a DWORD
  823. vfx.nAvgBytesPerSec = pVidCapInfo->uAvgBitrate;
  824. RtlCopyMemory(&vfx.bih, &pVidCapInfo->bih, sizeof(BITMAPINFOHEADER));
  825. /*
  826. * Add or remove the format
  827. */
  828. if (bAdd)
  829. hr = This->m_pVidAppCaps->AddVCMFormat(&vfx, pVidCapInfo);
  830. else
  831. hr = This->m_pVidAppCaps->RemoveVCMFormat(&vfx);
  832. out:
  833. DEBUGMSG(ZONE_INSTCODEC,("CInstallVideoCodecs::AddRemoveVCMFormat - leave\n"));
  834. return This->TranslateHr(hr);
  835. }
  836. /***************************************************************************
  837. Name : CInstallCodecs::CInstallCodecs
  838. Purpose : The CInstallCodecs object constructor
  839. Parameters: none
  840. Returns : None
  841. Comment :
  842. ***************************************************************************/
  843. inline CInstallCodecs::CInstallCodecs (void)
  844. {
  845. m_cRef = 0; // will be bumped to 1 by the explicit QI in the create function
  846. m_pAudAppCaps = NULL;
  847. m_pVidAppCaps = NULL;
  848. // can't use ++ because RISC processors may translate to several instructions
  849. InterlockedIncrement((long *) &g_cICObjects);
  850. }
  851. /***************************************************************************
  852. Name : CInstallCodecs::~CInstallCodecs
  853. Purpose : The CInstallCodecs object destructor
  854. Parameters: none
  855. Returns : None
  856. Comment :
  857. ***************************************************************************/
  858. inline CInstallCodecs::~CInstallCodecs (void)
  859. {
  860. // let the caps interfaces and objects go
  861. if (m_pAudAppCaps)
  862. m_pAudAppCaps->Release();
  863. if (m_pVidAppCaps)
  864. m_pVidAppCaps->Release();
  865. // can't use ++ because RISC processors may translate to several instructions
  866. if (!InterlockedDecrement((long *) &g_cICObjects))
  867. {
  868. if (g_hMutex)
  869. CloseHandle(g_hMutex);
  870. g_hMutex = NULL;
  871. }
  872. g_pIC = (CInstallCodecs *)NULL;
  873. }
  874. /***************************************************************************
  875. Name : CInstallCodecs::FreeBuffer
  876. Purpose : Frees a buffer allocated by the the installable codecs interfaces.
  877. Parameters: lpBuffer - a pointer to the buffer to free. This buffer must
  878. have been allocated by installable codecs interfaces
  879. Returns : HRESULT
  880. Comment :
  881. ***************************************************************************/
  882. HRESULT CInstallCodecs::FreeBuffer(LPVOID lpBuffer)
  883. {
  884. HRESULT hr = NOERROR;
  885. DEBUGMSG(ZONE_INSTCODEC,("CInstallCodecs::FreeBuffer\n"));
  886. if (lpBuffer)
  887. MEMFREE(lpBuffer);
  888. DEBUGMSG(ZONE_INSTCODEC,("CInstallCodecs::FreeBuffer - leave, hr=0x%x\n", hr));
  889. return TranslateHr(hr);
  890. }
  891. /***************************************************************************
  892. Name : CInstallCodecs::TranslateHr
  893. Purpose : Translates an HRESULT to an external installable codecs value
  894. Parameters: hr - [in] the HRESULT value to translate
  895. Returns : HRESULT - the translated value
  896. Comment :
  897. ***************************************************************************/
  898. HRESULT CInstallCodecs::TranslateHr(HRESULT hr)
  899. {
  900. switch (hr)
  901. {
  902. case CAPS_E_NOMATCH:
  903. hr = IC_E_NO_SUCH_FORMAT;
  904. break;
  905. case CAPS_E_INVALID_PARAM:
  906. hr = E_INVALIDARG;
  907. break;
  908. case CAPS_E_SYSTEM_ERROR:
  909. hr = IC_E_INTERNAL_ERROR;
  910. break;
  911. default:
  912. break;
  913. }
  914. return hr;
  915. }
  916. /****************************************************************************
  917. *
  918. * Initialize
  919. *
  920. * @func HRESULT | Initialize | Initializes the CinstallCodecs object
  921. *
  922. * @parm REFIID | riid | Reference to the identifier of the interface
  923. *
  924. * @rdesc Returns zero (NOERROR) if the function was successful. Otherwise, it returns
  925. * a standard HRESULT, with the WIN32 facility code (7), or the specific facility
  926. * code for installable codecs (0x301).
  927. * Possible error codes:
  928. * @flag E_INVALIDARG | Invalid argument
  929. * @flag E_OUTOFMEMORY | Not enough memory for creating the object
  930. * @flag IC_E_CAPS_INSTANTIATION_FAILURE | Could not instantiate a capability object
  931. * @flag IC_E_CAPS_INITIALIZATION_FAILURE | Could not initialize a capability object
  932. *
  933. ***************************************************************************/
  934. HRESULT CInstallCodecs::Initialize(REFIID riid)
  935. {
  936. HRESULT hr=NOERROR;
  937. CMsiaCapability *pAudCapObj = NULL;
  938. CMsivCapability *pVidCapObj = NULL;
  939. /*
  940. * Instantiate
  941. */
  942. ACQMUTEX(g_hMutex);
  943. /*
  944. * Audio
  945. */
  946. if ((riid == IID_IInstallAudioCodecs) &&
  947. !m_pAudAppCaps)
  948. {
  949. // instantiate the audio capability object
  950. DBG_SAVE_FILE_LINE
  951. pAudCapObj = new CMsiaCapability;
  952. if (!pAudCapObj)
  953. {
  954. hr = IC_E_CAPS_INSTANTIATION_FAILURE;
  955. goto out;
  956. }
  957. // get an appcap interface on the capability objects
  958. // this interface will be used for most calls
  959. hr = pAudCapObj->QueryInterface(IID_IAppAudioCap, (void **)&m_pAudAppCaps);
  960. if(!HR_SUCCEEDED(hr))
  961. {
  962. hr = IC_E_CAPS_INSTANTIATION_FAILURE;
  963. goto out;
  964. }
  965. pAudCapObj->Release(); // this balances the refcount of "new CMsiaCapability"
  966. // initialize the capability objects
  967. if (!(pAudCapObj->Init()))
  968. {
  969. hr = IC_E_CAPS_INITIALIZATION_FAILURE;
  970. goto out;
  971. }
  972. }
  973. /*
  974. * Video
  975. */
  976. if ((riid == IID_IInstallVideoCodecs) &&
  977. !m_pVidAppCaps)
  978. {
  979. // instantiate the video capability object
  980. DBG_SAVE_FILE_LINE
  981. pVidCapObj = new CMsivCapability;
  982. if (!pVidCapObj)
  983. {
  984. hr = IC_E_CAPS_INSTANTIATION_FAILURE;
  985. goto out;
  986. }
  987. // get an appcap interface on the capability objects
  988. // this interface will be used for most calls
  989. hr = pVidCapObj->QueryInterface(IID_IAppVidCap, (void **)&m_pVidAppCaps);
  990. if(!HR_SUCCEEDED(hr))
  991. {
  992. hr = IC_E_CAPS_INSTANTIATION_FAILURE;
  993. goto out;
  994. }
  995. pVidCapObj->Release(); // this balances the refcount of "new CMsivCapability"
  996. if (!(pVidCapObj->Init()))
  997. {
  998. hr = IC_E_CAPS_INITIALIZATION_FAILURE;
  999. goto out;
  1000. }
  1001. }
  1002. out:
  1003. if (FAILED(hr))
  1004. {
  1005. ERRORMSG(("CInstallCodecs::Initialize failed, hr=0x%x\n", hr));
  1006. }
  1007. RELMUTEX(g_hMutex);
  1008. return TranslateHr(hr);
  1009. }
  1010. /****************************************************************************
  1011. * @doc EXTERNAL COMPFUNC
  1012. ***************************************************************************/
  1013. /****************************************************************************
  1014. *
  1015. * CreateInstallCodecs
  1016. *
  1017. * @func HRESULT | CreateInstallCodecs | Creates an instance of the CInstallCodecs
  1018. * object, and returns the requested interface. This function should only be
  1019. * called indirectly through CoCreateInstance.
  1020. * @parm LPUNKNOWN | punkOuter | Pointer to whether object is or isnt part
  1021. * of an aggregate
  1022. *
  1023. * @parm REFIID | riid | Reference to the identifier of the interface
  1024. *
  1025. * @parm LPVOID * | ppv | Indirect pointer to requested interface
  1026. *
  1027. * @rdesc Returns zero (NOERROR) if the function was successful. Otherwise, it returns
  1028. * a standard HRESULT, with the WIN32 facility code (7), or the specific facility
  1029. * code for installable codecs (0x301).
  1030. * Possible error codes:
  1031. * @flag E_INVALIDARG | Invalid argument
  1032. * @flag E_OUTOFMEMORY | Not enough memory for creating the object
  1033. * @flag CLASS_E_NOAGGREGATION | Aggregation is not supported for this object
  1034. * @flag IC_E_CAPS_INSTANTIATION_FAILURE | Could not instantiate a capability object
  1035. * @flag IC_E_CAPS_INITIALIZATION_FAILURE | Could not initialize a capability object
  1036. *
  1037. * @comm CreateInstallCodecs should not be called directly. Clients of installable
  1038. * codecs should use the COM CoCreateInstance to instantiate the object, expecting
  1039. * the same return values.
  1040. *
  1041. ***************************************************************************/
  1042. extern "C" HRESULT WINAPI CreateInstallCodecs ( IUnknown *pUnkOuter,
  1043. REFIID riid,
  1044. void **ppv)
  1045. {
  1046. CInstallCodecs *pIC;
  1047. HRESULT hr = NOERROR;
  1048. *ppv = 0;
  1049. if (pUnkOuter)
  1050. {
  1051. hr = CLASS_E_NOAGGREGATION;
  1052. goto out;
  1053. }
  1054. /*
  1055. * instantiate the object
  1056. */
  1057. // create a mutex to control access to QoS object data
  1058. //
  1059. // NOTE: I'm taking some chance here: the code that creates the mutex must be
  1060. // executed by one thread at a time, so it should really be in the PROCESS_ATTACH
  1061. // for NAC.DLL. However, since this code is expected to be called rarely, and in
  1062. // order not to add code to the NAC load time, I put it here.
  1063. if (!g_hMutex)
  1064. {
  1065. g_hMutex = CreateMutex(NULL, FALSE, NULL);
  1066. ASSERT(g_hMutex);
  1067. if (!g_hMutex)
  1068. {
  1069. ERRORMSG(("CreateInstallCodecs: CreateMutex failed, 0x%x\n", GetLastError()));
  1070. hr = E_FAIL;
  1071. goto out;
  1072. }
  1073. }
  1074. ACQMUTEX(g_hMutex);
  1075. // only instantiate a new object if it doesn't already exist
  1076. if (!g_pIC)
  1077. {
  1078. DBG_SAVE_FILE_LINE
  1079. if (!(pIC = new CInstallCodecs))
  1080. {
  1081. hr = E_OUTOFMEMORY;
  1082. RELMUTEX(g_hMutex);
  1083. goto out;
  1084. }
  1085. // Save pointer
  1086. g_pIC = pIC;
  1087. }
  1088. else
  1089. {
  1090. // this is the case when the object was already instantiaed in this
  1091. // process, so we only want to return the object pointer.
  1092. pIC = g_pIC;
  1093. }
  1094. // always initialize the object. Initialize will only initialize what
  1095. // is not yet initialized
  1096. hr = pIC->Initialize(riid);
  1097. RELMUTEX(g_hMutex);
  1098. // get the requested interface for the caller
  1099. if (pIC)
  1100. {
  1101. // QueryInterface will get us the interface pointer and will AddRef
  1102. // the object
  1103. hr = pIC->QueryInterface (riid, ppv);
  1104. }
  1105. else
  1106. hr = E_FAIL;
  1107. out:
  1108. if (FAILED(hr))
  1109. {
  1110. ERRORMSG(("CreateInstallCodecs failed, hr=0x%x\n", hr));
  1111. }
  1112. return hr;
  1113. }