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.

895 lines
26 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // File: gfxui.c
  4. //
  5. // This file defines the functions that are used by the Global
  6. // Effects (GFX) page to drive manipulate the effects for a
  7. // mixer.
  8. //
  9. // History:
  10. // 10 June 2000 RogerW
  11. // Created.
  12. //
  13. // Copyright (C) 2000 Microsoft Corporation All Rights Reserved.
  14. //
  15. // Microsoft Confidential
  16. //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. //=============================================================================
  19. // Include files
  20. //=============================================================================
  21. #include <windows.h>
  22. #include <windowsx.h>
  23. #include "mmcpl.h"
  24. #include <mmddkp.h>
  25. #include <olectl.h>
  26. #include <ocidl.h>
  27. #include "gfxui.h"
  28. #define ADDGFX
  29. #define REGSTR_VAL_FRIENDLYNAME TEXT("FriendlyName")
  30. //
  31. // IDataObject Implementation
  32. //
  33. class GFXDataObject : public IDataObject
  34. {
  35. public:
  36. GFXDataObject (DWORD dwGfxID) { m_cRef = 1; m_dwGfxID = dwGfxID; }
  37. // IUnknown interface
  38. STDMETHODIMP QueryInterface (REFIID riid, LPVOID *ppv);
  39. STDMETHODIMP_(ULONG) AddRef () { return ++m_cRef; }
  40. STDMETHODIMP_(ULONG) Release () { return --m_cRef; }
  41. STDMETHODIMP GetData (FORMATETC * pformatetcIn, STGMEDIUM * pmedium);
  42. STDMETHODIMP GetDataHere (FORMATETC * pformatetc, STGMEDIUM *pmedium) { return E_NOTIMPL; }
  43. STDMETHODIMP QueryGetData (FORMATETC * pformatetc) { return E_NOTIMPL; }
  44. STDMETHODIMP GetCanonicalFormatEtc (FORMATETC * pformatetcIn, FORMATETC * pFormatetcOut) { return E_NOTIMPL; }
  45. STDMETHODIMP SetData (FORMATETC * pformatetc, STGMEDIUM * pmedium, BOOL fRelease) { return E_NOTIMPL; }
  46. STDMETHODIMP EnumFormatEtc (DWORD dwDirection, IEnumFORMATETC ** ppenumFormatEtc ) { return E_NOTIMPL; }
  47. STDMETHODIMP DAdvise (FORMATETC * pformatetc, DWORD advf, IAdviseSink* pAdvSnk, DWORD * pdwConnection) { return E_NOTIMPL; }
  48. STDMETHODIMP DUnadvise (DWORD dwConnection) { return E_NOTIMPL; }
  49. STDMETHODIMP EnumDAdvise (IEnumSTATDATA ** ppenumAdvise) { return E_NOTIMPL; }
  50. private:
  51. UINT m_cRef;
  52. DWORD m_dwGfxID;
  53. };
  54. STDMETHODIMP GFXDataObject::QueryInterface (REFIID riid, LPVOID * ppvObj)
  55. {
  56. if (!ppvObj)
  57. return E_POINTER;
  58. *ppvObj = NULL;
  59. if (IsEqualIID(riid,IID_IDataObject) ||
  60. IsEqualIID(riid,IID_IUnknown))
  61. *ppvObj = (IDataObject *) this;
  62. else
  63. return E_NOINTERFACE;
  64. ((IUnknown *) *ppvObj) -> AddRef ();
  65. return S_OK;
  66. }
  67. STDMETHODIMP GFXDataObject::GetData (LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) // @parm Storage to be created.
  68. {
  69. HRESULT hr = E_INVALIDARG;
  70. if (pformatetc && pmedium && TYMED_HGLOBAL == pformatetc -> tymed)
  71. {
  72. HANDLE hGfx = NULL;
  73. #ifdef ADDGFX
  74. hr = gfxOpenGfx (m_dwGfxID, &hGfx);
  75. #endif // ADDGFX
  76. if (SUCCEEDED (hr))
  77. {
  78. pmedium -> tymed = TYMED_HGLOBAL;
  79. pmedium -> pUnkForRelease = NULL;
  80. pmedium -> hGlobal = hGfx;
  81. }
  82. }
  83. return hr;
  84. }
  85. HRESULT InitList (DWORD dwMixID, DWORD dwType, PPGFXUILIST ppList)
  86. {
  87. HRESULT hr = E_INVALIDARG;
  88. if (ppList)
  89. {
  90. PGFXUILIST pList = (PGFXUILIST) LocalAlloc (LPTR, sizeof (GFXUILIST));
  91. *ppList = NULL; // Init pointer
  92. if (pList)
  93. {
  94. hr = S_OK;
  95. pList -> dwType = dwType;
  96. pList -> puiList = NULL;
  97. #ifdef UNICODE
  98. pList -> pszZoneDi = (PWSTR) GetInterfaceName (dwMixID);
  99. #else
  100. pList -> pszZoneDi = NULL; // This should not happen
  101. #endif
  102. if (pList -> pszZoneDi)
  103. {
  104. // Return new list
  105. *ppList = pList;
  106. }
  107. else
  108. {
  109. // Error!
  110. LocalFree (pList);
  111. hr = E_OUTOFMEMORY;
  112. }
  113. }
  114. else
  115. hr = E_OUTOFMEMORY;
  116. }
  117. return hr;
  118. }
  119. void GFXUI_FreeList (PPGFXUILIST ppList)
  120. {
  121. if (ppList)
  122. {
  123. PGFXUILIST pList = *ppList;
  124. if (pList)
  125. {
  126. // Free Zone
  127. if (pList -> pszZoneDi)
  128. GlobalFreePtr (pList -> pszZoneDi);
  129. pList -> pszZoneDi = NULL;
  130. // Free GFX List
  131. FreeListNodes (&(pList -> puiList));
  132. // Free list
  133. LocalFree (pList);
  134. *ppList = NULL;
  135. }
  136. }
  137. }
  138. void FreeListNodes (PPGFXUI ppuiList)
  139. {
  140. if (ppuiList)
  141. {
  142. PGFXUI pNodeDelete;
  143. PGFXUI puiList = *ppuiList;
  144. // Free list nodes
  145. while (puiList)
  146. {
  147. pNodeDelete = puiList;
  148. puiList = puiList -> pNext;
  149. FreeNode (&pNodeDelete);
  150. }
  151. *ppuiList = NULL;
  152. }
  153. }
  154. void FreeNode (PPGFXUI ppNode)
  155. {
  156. if (ppNode && *ppNode)
  157. {
  158. PGFXUI pNode = *ppNode;
  159. // Free the strings
  160. if (pNode -> pszName)
  161. LocalFree (pNode -> pszName);
  162. if (pNode -> pszFactoryDi)
  163. LocalFree (pNode -> pszFactoryDi);
  164. // Free the node
  165. LocalFree (pNode);
  166. *ppNode = NULL;
  167. }
  168. }
  169. HKEY OpenGfxRegKey (PCWSTR pszGfxFactoryDi, REGSAM sam)
  170. {
  171. HKEY hkeyGfx = NULL;
  172. if (pszGfxFactoryDi)
  173. {
  174. HDEVINFO DeviceInfoSet = SetupDiCreateDeviceInfoList (NULL, NULL);
  175. if (INVALID_HANDLE_VALUE != DeviceInfoSet)
  176. {
  177. SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
  178. DeviceInterfaceData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
  179. if (SetupDiOpenDeviceInterface (DeviceInfoSet, pszGfxFactoryDi,
  180. 0, &DeviceInterfaceData))
  181. {
  182. hkeyGfx = SetupDiOpenDeviceInterfaceRegKey (
  183. DeviceInfoSet, &DeviceInterfaceData,
  184. 0, sam);
  185. }
  186. SetupDiDestroyDeviceInfoList (DeviceInfoSet);
  187. }
  188. }
  189. return hkeyGfx;
  190. }
  191. HRESULT GetFriendlyName (PCWSTR pszGfxFactoryDi, PWSTR* ppszName)
  192. {
  193. HRESULT hr = E_INVALIDARG;
  194. HKEY hkeyGfx = NULL;
  195. // Check parameters
  196. if (ppszName && pszGfxFactoryDi)
  197. {
  198. HKEY hkeyGfx = OpenGfxRegKey (pszGfxFactoryDi, KEY_READ);
  199. *ppszName = NULL;
  200. if (hkeyGfx)
  201. {
  202. WCHAR szBuffer[MAX_PATH];
  203. DWORD dwType = REG_SZ;
  204. DWORD cb = sizeof (szBuffer) / sizeof (szBuffer[0]);
  205. hr = S_OK;
  206. if (ERROR_SUCCESS == RegQueryValueEx (hkeyGfx, REGSTR_VAL_FRIENDLYNAME, NULL, &dwType, (LPBYTE)szBuffer, &cb))
  207. {
  208. *ppszName = (PWSTR) LocalAlloc (LPTR, lstrlen (szBuffer)*2+2);
  209. if (*ppszName)
  210. wcscpy (*ppszName, szBuffer);
  211. else
  212. hr = E_OUTOFMEMORY;
  213. }
  214. else
  215. hr = REGDB_E_READREGDB;
  216. RegCloseKey (hkeyGfx);
  217. }
  218. }
  219. return hr;
  220. }
  221. HRESULT AddFactoryNode (PCWSTR pszGfxFactoryDi, PPGFXUILIST ppList)
  222. {
  223. return AddNode (pszGfxFactoryDi, 0, GUID_NULL, 0, 0, 0, ppList);
  224. }
  225. HRESULT AddNode (PCWSTR pszGfxFactoryDi, DWORD Id, REFCLSID rclsid, DWORD Type,
  226. DWORD Order, DWORD nFlags, PPGFXUILIST ppList)
  227. {
  228. PGFXUI pNode = NULL;
  229. HRESULT hr = S_OK;
  230. // Check parameters
  231. if (!ppList || !(*ppList) || !pszGfxFactoryDi)
  232. return E_INVALIDARG;
  233. // Create node
  234. if (SUCCEEDED (hr = CreateNode (NULL, pszGfxFactoryDi, &pNode)))
  235. {
  236. if (pNode)
  237. {
  238. // Initilize the rest of the values
  239. pNode -> Id = Id;
  240. pNode -> Type = Type;
  241. pNode -> Order = Order;
  242. pNode -> nFlags = nFlags;
  243. pNode -> clsidUI = rclsid;
  244. if (FAILED (hr = AttachNode (ppList, pNode)))
  245. FreeNode (&pNode);
  246. }
  247. else
  248. hr = E_UNEXPECTED;
  249. }
  250. return hr;
  251. }
  252. // Note: This function always adds the node to the list IN ORDER
  253. // IFF (pNode -> nFlags & GFX_CREATED).
  254. HRESULT AttachNode (PPGFXUILIST ppList, PGFXUI pNode)
  255. {
  256. HRESULT hr = E_INVALIDARG;
  257. // Check parameters
  258. if (ppList && (*ppList) && pNode)
  259. {
  260. PGFXUI puiList = (*ppList) -> puiList;
  261. hr = S_OK;
  262. // Make sure our next pointer starts out null..
  263. pNode -> pNext = NULL;
  264. if (puiList)
  265. {
  266. if (!(pNode -> nFlags & GFX_CREATED) ||
  267. (puiList -> Order >= pNode -> Order))
  268. {
  269. // Order is not available, just stick it on the front or
  270. // the order happens to put the node at the front.
  271. pNode -> pNext = puiList;
  272. puiList = pNode;
  273. }
  274. else
  275. {
  276. PGFXUI pSearch = puiList;
  277. if (!(puiList -> pNext))
  278. {
  279. // One element list. We know the new node doesn't belong
  280. // at the head of the list, so it is behind.
  281. puiList -> pNext = pNode;
  282. } else {
  283. while (pSearch -> pNext)
  284. {
  285. if (!(pSearch -> pNext -> nFlags & GFX_CREATED))
  286. {
  287. hr = E_INVALIDARG;
  288. break; // Cannot mix list types
  289. }
  290. if (pSearch -> pNext -> Order >= pNode -> Order)
  291. {
  292. // We found the insertion point!
  293. pNode -> pNext = pSearch -> pNext;
  294. pSearch -> pNext = pNode;
  295. break;
  296. }
  297. if (!(pSearch -> pNext -> pNext))
  298. {
  299. // At end of list, attach node to end
  300. pSearch -> pNext -> pNext = pNode;
  301. break;
  302. }
  303. // Move to next element
  304. pSearch = pSearch -> pNext;
  305. }
  306. }
  307. }
  308. }
  309. else
  310. {
  311. // First element of the list
  312. puiList = pNode;
  313. }
  314. if (SUCCEEDED (hr))
  315. {
  316. // Ensure we pass back the correct list pointer
  317. (*ppList) -> puiList = puiList;
  318. }
  319. }
  320. return hr;
  321. }
  322. LONG GFXEnum (PVOID Context, DWORD Id, PCWSTR GfxFactoryDi, REFCLSID rclsid, DWORD Type, DWORD Order)
  323. {
  324. PGFXUILIST pList = (PGFXUILIST) Context;
  325. HRESULT hr = E_INVALIDARG;
  326. if (pList)
  327. {
  328. if (Type == pList->dwType)
  329. {
  330. if (FAILED (hr = AddNode (GfxFactoryDi, Id, rclsid, Type, Order, GFX_CREATED, &pList)))
  331. {
  332. // Error, free the list
  333. GFXUI_FreeList (&pList);
  334. Context = NULL;
  335. }
  336. }
  337. else hr = NOERROR;
  338. }
  339. return hr;
  340. }
  341. BOOL GFXUI_CheckDevice (DWORD dwMixID, DWORD dwType)
  342. {
  343. HRESULT hr = S_OK;
  344. BOOL fRet = FALSE;
  345. PGFXUILIST pList = NULL;
  346. if (SUCCEEDED (hr = InitList (dwMixID, dwType, &pList)))
  347. {
  348. if (pList && pList -> pszZoneDi)
  349. {
  350. PDEVICEINTERFACELIST pdiList = NULL;
  351. LONG lResult = NO_ERROR;
  352. lResult = gfxCreateGfxFactoriesList (pList -> pszZoneDi, &pdiList);
  353. if ((lResult == NO_ERROR) && pdiList)
  354. {
  355. fRet = TRUE;
  356. gfxDestroyDeviceInterfaceList (pdiList);
  357. }
  358. GFXUI_FreeList (&pList);
  359. }
  360. }
  361. return fRet;
  362. }
  363. HRESULT GFXUI_CreateList (DWORD dwMixID, DWORD dwType, BOOL fAll, PPGFXUILIST ppList)
  364. {
  365. HRESULT hr = E_INVALIDARG;
  366. if (ppList)
  367. {
  368. hr = S_OK;
  369. if (SUCCEEDED (hr = InitList (dwMixID, dwType, ppList)))
  370. {
  371. if (*ppList && (*ppList) -> pszZoneDi)
  372. {
  373. if (!fAll)
  374. {
  375. hr = gfxEnumerateGfxs ((*ppList) -> pszZoneDi, GFXEnum, (*ppList));
  376. }
  377. else
  378. {
  379. PDEVICEINTERFACELIST pdiList = NULL;
  380. hr = gfxCreateGfxFactoriesList ((*ppList) -> pszZoneDi, &pdiList);
  381. if (SUCCEEDED (hr) && pdiList)
  382. {
  383. LONG lIndex;
  384. for (lIndex = 0; lIndex < pdiList -> Count; lIndex++)
  385. {
  386. hr = AddFactoryNode ((pdiList -> DeviceInterface)[lIndex], ppList);
  387. if (FAILED (hr))
  388. {
  389. GFXUI_FreeList (ppList);
  390. break;
  391. }
  392. }
  393. gfxDestroyDeviceInterfaceList (pdiList);
  394. }
  395. else
  396. {
  397. GFXUI_FreeList (ppList);
  398. hr = E_OUTOFMEMORY;
  399. }
  400. }
  401. }
  402. else
  403. hr = E_UNEXPECTED;
  404. }
  405. }
  406. return hr;
  407. }
  408. HRESULT GFXUI_Properties (PGFXUI puiGFX, HWND hWndOwner)
  409. {
  410. HRESULT hr = E_INVALIDARG;
  411. if (puiGFX && GFXUI_CanShowProperties (puiGFX) && IsWindow (hWndOwner))
  412. {
  413. ISpecifyPropertyPages* pISpecifyPropertyPages = NULL;
  414. // Get the Vendor UI Property Pages Interface
  415. hr = CoCreateInstance (puiGFX -> clsidUI, NULL, CLSCTX_INPROC_SERVER, IID_ISpecifyPropertyPages, (void**)&pISpecifyPropertyPages);
  416. if (SUCCEEDED (hr) && !pISpecifyPropertyPages)
  417. hr = E_UNEXPECTED;
  418. if (SUCCEEDED (hr))
  419. {
  420. CAUUID Pages;
  421. ZeroMemory (&Pages, sizeof (Pages));
  422. // Get the VendorUI Property Page CLSID's
  423. hr = pISpecifyPropertyPages -> GetPages (&Pages);
  424. if (SUCCEEDED (hr) && (Pages.cElems == 0 || !Pages.pElems))
  425. hr = E_UNEXPECTED;
  426. if (SUCCEEDED (hr))
  427. {
  428. RECT rcWindow;
  429. if (GetWindowRect (hWndOwner, &rcWindow))
  430. {
  431. TCHAR szCaption[MAX_PATH];
  432. GFXDataObject DataObject (puiGFX -> Id);
  433. IUnknown* punkDataObject = &DataObject;
  434. // Load the VendorUI caption
  435. LoadString (ghInstance, IDS_EFFECTS_PROPERTY_CAPTION, szCaption, sizeof (szCaption)/sizeof(TCHAR));
  436. // Bring up the Vendor UI
  437. hr = OleCreatePropertyFrame (hWndOwner, rcWindow.left + 10, rcWindow.top + 10,
  438. szCaption, 1, &punkDataObject, Pages.cElems,
  439. Pages.pElems, GetSystemDefaultLangID (),
  440. 0, NULL);
  441. }
  442. else
  443. hr = E_FAIL;
  444. CoTaskMemFree (Pages.pElems);
  445. }
  446. pISpecifyPropertyPages -> Release ();
  447. }
  448. }
  449. return hr;
  450. }
  451. UINT GetListSize (PGFXUI puiList)
  452. {
  453. UINT uiSize = 0;
  454. PGFXUI puiListSeek = puiList;
  455. while (puiListSeek)
  456. {
  457. puiListSeek = puiListSeek -> pNext;
  458. uiSize++;
  459. }
  460. return uiSize;
  461. }
  462. HRESULT GFXUI_Apply (PPGFXUILIST ppListApply, PPGFXUI ppuiListDelete)
  463. {
  464. HRESULT hr = E_INVALIDARG;
  465. PGFXUILIST pListApply = (ppListApply ? *ppListApply : NULL);
  466. PGFXUI puiListDelete = (ppuiListDelete ? *ppuiListDelete : NULL);
  467. if ((pListApply && pListApply -> puiList) || puiListDelete)
  468. {
  469. PGFXREMOVEREQUEST paGfxRemoveRequests = NULL;
  470. PGFXMODIFYREQUEST paGfxModifyRequests = NULL;
  471. PGFXADDREQUEST paGfxAddRequests = NULL;
  472. ULONG cGfxRemoveRequests = 0;
  473. ULONG cGfxModifyRequests = 0;
  474. ULONG cGfxAddRequests = 0;
  475. ULONG cApplyList = GetListSize (pListApply ? pListApply -> puiList : NULL);
  476. ULONG cDeleteList = GetListSize (puiListDelete);
  477. PGFXUI puiListSeek = NULL;
  478. hr = S_OK;
  479. // This function needs to create:
  480. // - Deleted Array of GFXREMOVEREQUEST's
  481. // - Modify Array of GFXMODIFYREQUEST's
  482. // - Add Array of GFXADDREQUEST's
  483. //
  484. // The deleted array is fairly easy, just pull out the
  485. // marked ones. With the remaining, we need to loop through
  486. // them comparing order and create modify records as needed
  487. // to modify their order (except for the add records where
  488. // we must save the nessary order in the add request array).
  489. // Then we create the add array (perhaps with the modify array)
  490. // and fill in everything else (other than order).
  491. //
  492. // Then call GFX_BatchChange().
  493. //
  494. // Afterword, we need to update our list accordingly (i.e. delete
  495. // nodes, update order, etc).
  496. // Create our parameters
  497. // Note: These buffers are really upper bounds on the memory we will need.
  498. // We will count the actual requests we make and pass that value to
  499. // the GFX function call.
  500. if (0 < cDeleteList)
  501. {
  502. paGfxRemoveRequests = (PGFXREMOVEREQUEST) LocalAlloc (LPTR, sizeof (*paGfxRemoveRequests) * cDeleteList);
  503. if (!paGfxRemoveRequests)
  504. hr = E_OUTOFMEMORY;
  505. }
  506. if (0 < cApplyList)
  507. {
  508. paGfxModifyRequests = (PGFXMODIFYREQUEST) LocalAlloc (LPTR, sizeof (*paGfxModifyRequests) * cApplyList);
  509. paGfxAddRequests = (PGFXADDREQUEST) LocalAlloc (LPTR, sizeof (*paGfxAddRequests) * cApplyList);
  510. if (!paGfxModifyRequests || !paGfxAddRequests)
  511. hr = E_OUTOFMEMORY;
  512. }
  513. if (SUCCEEDED (hr))
  514. {
  515. UINT uiIndx;
  516. DWORD dwOrder = 0;
  517. // Create the remove parameter
  518. puiListSeek = puiListDelete;
  519. for (uiIndx = 0; uiIndx < cDeleteList; uiIndx++)
  520. {
  521. // Make sure this is created before we ask to delete it.
  522. // (It may be an AddNode that was deleted before creation).
  523. if (puiListSeek -> nFlags & GFX_CREATED)
  524. {
  525. (paGfxRemoveRequests + cGfxRemoveRequests) -> IdToRemove = puiListSeek -> Id;
  526. (paGfxRemoveRequests + cGfxRemoveRequests) -> Error = S_OK;
  527. cGfxRemoveRequests++;
  528. }
  529. puiListSeek = puiListSeek -> pNext;
  530. }
  531. // Create the modify and add parameters
  532. puiListSeek = pListApply ? pListApply -> puiList : NULL;
  533. for (uiIndx = 0; uiIndx < cApplyList; uiIndx++)
  534. {
  535. if (puiListSeek -> nFlags & GFX_ADD)
  536. {
  537. (paGfxAddRequests + cGfxAddRequests) -> ZoneFactoryDi = pListApply -> pszZoneDi;
  538. (paGfxAddRequests + cGfxAddRequests) -> GfxFactoryDi = puiListSeek -> pszFactoryDi;
  539. (paGfxAddRequests + cGfxAddRequests) -> Type = pListApply -> dwType;
  540. (paGfxAddRequests + cGfxAddRequests) -> Order = dwOrder++;
  541. (paGfxAddRequests + cGfxAddRequests) -> NewId = 0;
  542. (paGfxAddRequests + cGfxAddRequests) -> Error = S_OK;
  543. cGfxAddRequests++;
  544. }
  545. else
  546. {
  547. if (puiListSeek -> nFlags & GFX_CREATED)
  548. {
  549. // We only need to add modify records for GFX'es
  550. // that are no longer in order.
  551. if (puiListSeek -> Order < dwOrder)
  552. {
  553. (paGfxModifyRequests + cGfxModifyRequests) -> IdToModify = puiListSeek -> Id;
  554. (paGfxModifyRequests + cGfxModifyRequests) -> NewOrder = dwOrder++;
  555. (paGfxModifyRequests + cGfxModifyRequests) -> Error = S_OK;
  556. cGfxModifyRequests++;
  557. }
  558. else
  559. dwOrder = (puiListSeek -> Order + 1);
  560. }
  561. else
  562. {
  563. // Bogus list entry, abort everything!
  564. hr = E_INVALIDARG;
  565. break;
  566. }
  567. }
  568. puiListSeek = puiListSeek -> pNext;
  569. }
  570. if (SUCCEEDED (hr))
  571. {
  572. #ifdef ADDGFX
  573. hr = gfxBatchChange (paGfxRemoveRequests, cGfxRemoveRequests,
  574. paGfxModifyRequests, cGfxModifyRequests,
  575. paGfxAddRequests, cGfxAddRequests);
  576. #endif // ADDGFX
  577. if (SUCCEEDED (hr))
  578. {
  579. PGFXMODIFYREQUEST paGfxModifySeek = paGfxModifyRequests;
  580. PGFXADDREQUEST paGfxAddSeek = paGfxAddRequests;
  581. // Update the passed arrays
  582. FreeListNodes (ppuiListDelete);
  583. puiListSeek = pListApply ? pListApply -> puiList : NULL;
  584. for (uiIndx = 0; uiIndx < cApplyList; uiIndx++)
  585. {
  586. // Update the list items.
  587. if (puiListSeek -> nFlags & GFX_ADD)
  588. {
  589. // Update the newly create GFX
  590. puiListSeek -> nFlags = GFX_CREATED;
  591. puiListSeek -> Id = paGfxAddSeek -> NewId;
  592. puiListSeek -> Type = paGfxAddSeek -> Type;
  593. puiListSeek -> Order = paGfxAddSeek -> Order;
  594. paGfxAddSeek++;
  595. }
  596. else // must be (puiListSeek -> nFlags & GFX_CREATED)
  597. {
  598. // Update the order
  599. puiListSeek -> Order = paGfxModifySeek -> NewOrder;
  600. paGfxModifySeek++;
  601. }
  602. }
  603. }
  604. }
  605. }
  606. // Free parameters
  607. if (paGfxRemoveRequests)
  608. LocalFree (paGfxRemoveRequests);
  609. if (paGfxModifyRequests)
  610. LocalFree (paGfxModifyRequests);
  611. if (paGfxAddRequests)
  612. LocalFree (paGfxAddRequests);
  613. }
  614. return hr;
  615. }
  616. ///////////////////////////////////////////////////////////////////////////////////////////
  617. // Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
  618. ///////////////////////////////////////////////////////////////////////////////////////////
  619. PTCHAR GetInterfaceName (DWORD dwMixerID)
  620. {
  621. MMRESULT mmr;
  622. ULONG cbSize=0;
  623. TCHAR *szInterfaceName=NULL;
  624. //Query for the Device interface name
  625. mmr = mixerMessage(HMIXER_INDEX(dwMixerID), DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&cbSize, 0L);
  626. if(MMSYSERR_NOERROR == mmr)
  627. {
  628. szInterfaceName = (TCHAR *)GlobalAllocPtr(GHND, (cbSize+1)*sizeof(TCHAR));
  629. if(!szInterfaceName)
  630. {
  631. return NULL;
  632. }
  633. mmr = mixerMessage(HMIXER_INDEX(dwMixerID), DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)szInterfaceName, cbSize);
  634. if(MMSYSERR_NOERROR != mmr)
  635. {
  636. GlobalFreePtr(szInterfaceName);
  637. return NULL;
  638. }
  639. }
  640. return szInterfaceName;
  641. }
  642. BOOL GFXUI_CanShowProperties (PGFXUI puiGFX)
  643. {
  644. return (puiGFX && (puiGFX -> nFlags & GFX_CREATED) && (puiGFX -> clsidUI != GUID_NULL));
  645. }
  646. HRESULT CreateNode (PCWSTR pszName, PCWSTR pszGfxFactoryDi, PPGFXUI ppNode)
  647. {
  648. HRESULT hr = E_INVALIDARG;
  649. if (ppNode)
  650. {
  651. // Create node
  652. PGFXUI pNode = (PGFXUI) LocalAlloc (LPTR, sizeof (GFXUI));
  653. hr = S_OK;
  654. if (pNode)
  655. {
  656. ZeroMemory (pNode, sizeof (GFXUI));
  657. // Create the strings
  658. if (pszName)
  659. {
  660. pNode -> pszName = (PWSTR) LocalAlloc (LPTR, lstrlen (pszName)*2+2);
  661. if (pNode -> pszName)
  662. wcscpy (pNode -> pszName, pszName);
  663. else
  664. hr = E_OUTOFMEMORY;
  665. }
  666. else
  667. {
  668. // If there is no name, get it from the factory
  669. pNode -> pszName = NULL;
  670. if (pszGfxFactoryDi)
  671. hr = GetFriendlyName (pszGfxFactoryDi, &(pNode -> pszName));
  672. }
  673. if (SUCCEEDED (hr) && pszGfxFactoryDi)
  674. {
  675. pNode -> pszFactoryDi = (PWSTR) LocalAlloc (LPTR, lstrlen (pszGfxFactoryDi)*2+2);
  676. if (pNode -> pszFactoryDi)
  677. wcscpy (pNode -> pszFactoryDi, pszGfxFactoryDi);
  678. else
  679. hr = E_OUTOFMEMORY;
  680. }
  681. if (SUCCEEDED (hr))
  682. // Return node
  683. *ppNode = pNode;
  684. else
  685. // Free node
  686. FreeNode (&pNode);
  687. }
  688. else
  689. hr = E_OUTOFMEMORY;
  690. }
  691. return hr;
  692. }
  693. // This function creates an "addable" GFXUI element that will be able
  694. // to create a new GFX when you call GFXUI_Apply() with this new element
  695. // in the list.
  696. HRESULT GFXUI_CreateAddGFX (PPGFXUI ppuiGFXAdd, PGFXUI puiGFXSource)
  697. {
  698. HRESULT hr = E_INVALIDARG;
  699. if (ppuiGFXAdd && puiGFXSource)
  700. {
  701. *ppuiGFXAdd = NULL;
  702. hr = CreateNode (puiGFXSource -> pszName,
  703. puiGFXSource -> pszFactoryDi, ppuiGFXAdd);
  704. if (SUCCEEDED (hr))
  705. {
  706. if (*ppuiGFXAdd)
  707. {
  708. // Indicate that this is a new 'Add' node.
  709. (*ppuiGFXAdd) -> nFlags = GFX_ADD;
  710. }
  711. else
  712. hr = E_UNEXPECTED;
  713. }
  714. }
  715. return hr;
  716. }