Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4554 lines
134 KiB

  1. /* agfxs.cpp
  2. * Server side code for agfx.
  3. * Created by FrankYe on 7/3/2000
  4. * Copyright (c) 2000-2001 Microsoft Corporation
  5. */
  6. extern "C" {
  7. #include <nt.h>
  8. #include <ntrtl.h>
  9. #include <nturtl.h>
  10. #include <tchar.h>
  11. #include <windows.h>
  12. #include <sddl.h>
  13. #include <winsta.h>
  14. #include <wtsapi32.h>
  15. #include <syslib.h>
  16. #include <mmsystem.h>
  17. #include <mmsysp.h>
  18. #include <regstr.h>
  19. #include <objbase.h>
  20. #include <setupapi.h>
  21. #include <wdmguid.h>
  22. #include <ks.h>
  23. #include <ksmedia.h>
  24. }
  25. #include "debug.h"
  26. #include "list.h"
  27. #include "service.h"
  28. #include "audiosrv.h"
  29. #include "reg.h"
  30. #include "sad.h"
  31. #include "ksi.h"
  32. #include "agfxs.h"
  33. #include "agfxsp.h"
  34. /*===========================================================================//
  35. === ISSUE-2000/09/24-FrankYe TODO Notes ===
  36. -
  37. - Figure out correct way to pass handle through RPC to s_gfxOpenGfx
  38. - Does RPC server unregister its endpoint when shutting down?
  39. - Should turn on strick type checking
  40. - Ensure there are no Order duplicates
  41. - Handle NULL global lists. Perhaps put lists in a context
  42. - Need to listen to PnP queries and unload GFXs if PnP wishes
  43. to remove them. Repro problem by Uninstalling a GFX via
  44. Device Manager. Note it asks for reboot.
  45. - Create client contexts at least to ensure input GFX IDs are
  46. valid for the current user. Otherwise one user can manipulate
  47. the gfx settings of another user via gfxOpenGfx.
  48. - Be consistent in whether s_* functions return LONG or RPC_STATUS
  49. - Modify to handle Render and Capture device specs
  50. - When loading all CuAutoLoad and CuUserLoad, confirm active
  51. - Move all string constants to header
  52. - Should AutoLoad HardwareId be MULTI_SZ
  53. //===========================================================================*/
  54. //=============================================================================
  55. //=== Constants ===
  56. //=============================================================================
  57. #define REGSTR_PATH_GFX REGSTR_PATH_MULTIMEDIA TEXT("\\Audio\\Gfx")
  58. #define REGSTR_PATH_GFX_AUTOLOAD TEXT("AutoLoad")
  59. #define REGSTR_PATH_GFX_USERLOAD TEXT("UserLoad")
  60. #define REGSTR_PATH_DI_GFX TEXT("Gfx")
  61. #define REGSTR_PATH_GFXAUTOLOAD REGSTR_PATH_GFX TEXT("\\") REGSTR_PATH_GFX_AUTOLOAD
  62. #define REGSTR_PATH_GFXUSERLOAD REGSTR_PATH_GFX TEXT("\\") REGSTR_PATH_GFX_USERLOAD
  63. #define REGSTR_PATH_GFXDI_USERINTERFACECLSID TEXT("UserInterface\\CLSID")
  64. #define REGSTR_PATH_GFXUSERLOADID_FILTERSETTINGS TEXT("FilterSettings")
  65. #define REGSTR_VAL_GFX_IDGEN TEXT("IdGeneration")
  66. #define REGSTR_VAL_GFX_ZONEDI TEXT("ZoneDi")
  67. #define REGSTR_VAL_GFX_GFXDI TEXT("GfxDi")
  68. #define REGSTR_VAL_GFX_TYPE TEXT("Type")
  69. #define REGSTR_VAL_GFX_ORDER TEXT("Order")
  70. #define REGSTR_VAL_GFX_ID TEXT("Id")
  71. #define REGSTR_VAL_GFX_CUAUTOLOADID TEXT("CuAutoLoadId")
  72. #define REGSTR_VAL_GFX_LMAUTOLOADID TEXT("LmAutoLoadId")
  73. #define REGSTR_VAL_GFX_HARDWAREID TEXT("HardwareId")
  74. #define REGSTR_VAL_GFX_REFERENCESTRING TEXT("ReferenceString")
  75. #define REGSTR_VAL_GFX_NEWAUTOLOAD TEXT("NewAutoLoad")
  76. //=============================================================================
  77. //=== Global data ===
  78. //=============================================================================
  79. //
  80. // resource object protecting GFX support initialization and termination. This
  81. // is required since initialization/termination might happen either on RPC calls
  82. // to s_gfxLogon/s_gfxLogoff or on SERVICE_CONTROL_STOP event to the service
  83. // control handler. Also, other RPC interface functions might be executing
  84. // on one thread while s_gfxLogon, s_gfxLogoff, or SERVICE_CONTROL_STOP happens
  85. // on another thread.
  86. //
  87. RTL_RESOURCE GfxResource;
  88. BOOL gfGfxResource = FALSE;
  89. //
  90. // Are GFX functions initialized and functional
  91. //
  92. BOOL gfGfxInitialized = FALSE;
  93. //
  94. // The current console user
  95. //
  96. CUser* gpConsoleUser = NULL;
  97. //
  98. // The process global lists below are locked/unlocked together using
  99. // the functions LockGlobalLists and UnlockGlobalLists. We don't
  100. // attempt to lock at finer granulatiry
  101. //
  102. CListGfxFactories *gplistGfxFactories = NULL;
  103. CListZoneFactories *gplistZoneFactories = NULL;
  104. CListCuUserLoads *gplistCuUserLoads = NULL;
  105. //
  106. // The sysaudio data below is locked by a critical section accessed
  107. // by calling LockSysaudio and UnlockSysaudio
  108. //
  109. PTSTR gpstrSysaudioDeviceInterface = NULL;
  110. HANDLE ghSysaudio = INVALID_HANDLE_VALUE;
  111. LONG gfCsSysaudio = FALSE;
  112. CRITICAL_SECTION gcsSysaudio;
  113. //
  114. // If both the global lists lock and the sysaudio lock are required
  115. // at the same time, then the global lists lock must be acquired first!
  116. //
  117. //=============================================================================
  118. //=== debug helpers ===
  119. //=============================================================================
  120. #ifdef DBG
  121. #endif
  122. //=============================================================================
  123. //=== Heap helpers ===
  124. //=============================================================================
  125. static BOOL HeapFreeIfNotNull(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem)
  126. {
  127. return lpMem ? HeapFree(hHeap, dwFlags, lpMem) : TRUE;
  128. }
  129. void* __cdecl operator new(size_t cbBuffer)
  130. {
  131. ASSERT(cbBuffer);
  132. return HeapAlloc(hHeap, 0, cbBuffer);
  133. }
  134. void __cdecl operator delete(void *p)
  135. {
  136. ASSERT(p);
  137. HeapFree(hHeap, 0, p);
  138. }
  139. //=============================================================================
  140. //=== String helpers ===
  141. //=============================================================================
  142. int lstrcmpiMulti(PCTSTR pstrMulti, PCTSTR pstrKey)
  143. {
  144. int iresult;
  145. do {
  146. iresult = lstrcmpi(pstrMulti, pstrKey);
  147. pstrMulti += lstrlen(pstrMulti)+1;
  148. } while (iresult && lstrlen(pstrMulti));
  149. return iresult;
  150. }
  151. PTSTR lstrDuplicate(PCTSTR pstr)
  152. {
  153. PTSTR pstrDuplicate = (PTSTR)HeapAlloc(hHeap, 0, (lstrlen(pstr)+1)*sizeof(TCHAR));
  154. if (pstrDuplicate) lstrcpy(pstrDuplicate, pstr);
  155. return pstrDuplicate;
  156. }
  157. //=============================================================================
  158. //=== Rtl resource helpers ===
  159. //=============================================================================
  160. /*-----------------------------------------------------------------------------
  161. RtlInterlockedTestAcquireResourceShared
  162. Given a resource, and a BOOLEAN flag protected by the resource, this
  163. function acquires the resource shared and tests the flag. If the flag is
  164. true, this function returns TREU with the resource acquired shared. If the
  165. flag is false, this function releases the resource and returns FALSE.
  166. -----------------------------------------------------------------------------*/
  167. BOOL RtlInterlockedTestAcquireResourceShared(
  168. PRTL_RESOURCE Resource,
  169. PBOOL ResourceFlag
  170. )
  171. {
  172. RtlAcquireResourceShared(Resource, TRUE);
  173. if (*ResourceFlag) return TRUE;
  174. RtlReleaseResource(Resource);
  175. return FALSE;
  176. }
  177. //=============================================================================
  178. //
  179. // Security helpers
  180. //
  181. // The semantics are similar to other security-related Win32 APIs. That is
  182. // the return value is a BOOL where TRUE means success, FALSE means failure,
  183. // and GetLastError will return an error code after a failure.
  184. //
  185. //=============================================================================
  186. /*-----------------------------------------------------------------------------
  187. GetCurrentUserTokenW
  188. Private function implemented in irnotif.lib. Retrieves the token of the
  189. user logged onto the specified winstation. I've been advised that the
  190. caller of this function is responsible for closing the returned handle.
  191. Returns NULL on failure.
  192. -----------------------------------------------------------------------------*/
  193. EXTERN_C HANDLE GetCurrentUserTokenW(IN WCHAR Winsta[], IN DWORD DesiredAccess);
  194. /*-----------------------------------------------------------------------------
  195. CreateStringSidFromSid
  196. Same function as the Win32 API ConvertSidToStringSid but ensures the
  197. resulting string is allocated on the heap specified by the global
  198. variable hHeap.
  199. -----------------------------------------------------------------------------*/
  200. BOOL CreateStringSidFromSid(IN PSID pSid, OUT PTSTR *ppStringSid)
  201. {
  202. PTSTR StringSid;
  203. LONG LastError;
  204. ASSERT(pSid);
  205. if (ConvertSidToStringSid(pSid, &StringSid))
  206. {
  207. PTSTR outStringSid;
  208. // dprintf(TEXT("CreateStringSidFromSid: StringSid=%s\n"), StringSid);
  209. outStringSid = lstrDuplicate(StringSid);
  210. if (outStringSid) {
  211. *ppStringSid = outStringSid;
  212. LastError = NO_ERROR;
  213. } else {
  214. LastError = ERROR_OUTOFMEMORY;
  215. }
  216. LocalFree(StringSid);
  217. } else {
  218. LastError = GetLastError();
  219. dprintf(TEXT("CreateStringSidFromSid: ConvertSidToStringSid LastError=%d\n"), GetLastError());
  220. }
  221. SetLastError(LastError);
  222. return (NO_ERROR == LastError);
  223. }
  224. /*-----------------------------------------------------------------------------
  225. CreateTokenSid
  226. Given a token handle, create a SID for the token user.
  227. The SID is allocated on the heap specified by the global variable hHeap.
  228. The caller is responsible for freeing the storage for ths SID. The
  229. function returns TRUE if successful and FALSE otherwise. LastError is
  230. set.
  231. -----------------------------------------------------------------------------*/
  232. BOOL CreateTokenSid(HANDLE TokenHandle, OUT PSID *ppSid)
  233. {
  234. DWORD cbTokenUserInformation;
  235. LONG LastError;
  236. LastError = NO_ERROR;
  237. if (!GetTokenInformation(TokenHandle, TokenUser, NULL, 0, &cbTokenUserInformation)) LastError = GetLastError();
  238. if ((NO_ERROR == LastError) || (ERROR_INSUFFICIENT_BUFFER == LastError))
  239. {
  240. PTOKEN_USER TokenUserInformation;
  241. ASSERT(cbTokenUserInformation > 0);
  242. TokenUserInformation = (PTOKEN_USER)HeapAlloc(hHeap, 0, cbTokenUserInformation);
  243. if (TokenUserInformation)
  244. {
  245. if (GetTokenInformation(TokenHandle, TokenUser, TokenUserInformation, cbTokenUserInformation, &cbTokenUserInformation))
  246. {
  247. DWORD cbSid = GetLengthSid(TokenUserInformation->User.Sid);
  248. PSID pSid = HeapAlloc(hHeap, 0, cbSid);
  249. if (pSid)
  250. {
  251. if (CopySid(cbSid, pSid, TokenUserInformation->User.Sid))
  252. {
  253. *ppSid = pSid;
  254. LastError = NO_ERROR;
  255. } else {
  256. LastError = GetLastError();
  257. dprintf(TEXT("CreateTokenSid: CopySid failed, LastError=%d\n"), LastError);
  258. }
  259. } else {
  260. LastError = ERROR_OUTOFMEMORY;
  261. }
  262. } else {
  263. LastError = GetLastError();
  264. dprintf(TEXT("CreateTokenSid: GetTokenInformation (second) LastError=%d\n"), LastError);
  265. }
  266. HeapFree(hHeap, 0, TokenUserInformation);
  267. } else {
  268. LastError = ERROR_OUTOFMEMORY;
  269. }
  270. } else {
  271. LastError = GetLastError();
  272. dprintf(TEXT("CreateTokenSid: GetTokenInformation (first) LastError=%d\n"), LastError);
  273. }
  274. SetLastError(LastError);
  275. return (NO_ERROR == LastError);
  276. }
  277. BOOL OpenSessionToken(ULONG SessionId, PHANDLE pToken)
  278. {
  279. HANDLE Token;
  280. LONG error;
  281. if (GetWinStationUserToken(SessionId, &Token))
  282. {
  283. error = NO_ERROR;
  284. }
  285. else if (0 == SessionId)
  286. {
  287. // ISSUE-2001-03-21-FrankYe This appears to fail during
  288. // logoff notification
  289. Token = GetCurrentUserTokenW(L"WinSta0", TOKEN_ALL_ACCESS);
  290. if (Token)
  291. {
  292. error = NO_ERROR;
  293. }
  294. else
  295. {
  296. error = GetLastError();
  297. ASSERT(NO_ERROR != error);
  298. dprintf(TEXT("OpenSessionToken : error: GetCurrentUserTokenW failed, LastError=%d\n"), error);
  299. }
  300. }
  301. else
  302. {
  303. error = GetLastError();
  304. ASSERT(NO_ERROR != error);
  305. }
  306. if (NO_ERROR == error) *pToken = Token;
  307. SetLastError(error);
  308. return (NO_ERROR == error);
  309. }
  310. /*-----------------------------------------------------------------------------
  311. CreateSessionUserSid
  312. Given a session ID, create a SID for the session user.
  313. The SID is allocated on the heap specified by the global variable hHeap.
  314. The caller is responsible for freeing the storage for ths SID. The
  315. function returns TRUE if successful and FALSE otherwise. LastError is
  316. set.
  317. -----------------------------------------------------------------------------*/
  318. BOOL CreateSessionUserSid(IN DWORD dwSessionId, OUT PSID *ppSid)
  319. {
  320. HANDLE hToken;
  321. LONG error;
  322. if (OpenSessionToken(dwSessionId, &hToken))
  323. {
  324. PSID pSid;
  325. if (CreateTokenSid(hToken, &pSid))
  326. {
  327. *ppSid = pSid;
  328. error = NO_ERROR;
  329. } else {
  330. error = GetLastError();
  331. dprintf(TEXT("CreateSessionUserSid: CreateTokenSid failed, LastError=%d\n"), error);
  332. }
  333. CloseHandle(hToken);
  334. } else {
  335. error = GetLastError();
  336. dprintf(TEXT("CreateSessionUserSid: OpenSessionToken failed, LastError=%d\n"), error);
  337. }
  338. SetLastError(error);
  339. return (NO_ERROR == error);
  340. }
  341. /*-----------------------------------------------------------------------------
  342. CreateThreadImpersonationSid
  343. Given a thread handle, create a SID for the user that the thread is
  344. impersonating.
  345. The SID is allocated on the heap specified by the global variable hHeap.
  346. The caller is responsible for freeing the storage for ths SID. The
  347. function returns TRUE if successful and FALSE otherwise. LastError is
  348. set.
  349. -----------------------------------------------------------------------------*/
  350. BOOL CreateThreadImpersonationSid(IN HANDLE ThreadHandle, OUT PSID *ppSid)
  351. {
  352. HANDLE TokenHandle;
  353. LONG LastError;
  354. if (OpenThreadToken(ThreadHandle, TOKEN_QUERY, FALSE, &TokenHandle))
  355. {
  356. if (CreateTokenSid(TokenHandle, ppSid))
  357. {
  358. LastError = NO_ERROR;
  359. } else {
  360. LastError = GetLastError();
  361. dprintf(TEXT("CreateThreadImpersonationSid: CreateTokenSid LastError=%d\n"), LastError);
  362. }
  363. CloseHandle(TokenHandle);
  364. } else {
  365. LastError = GetLastError();
  366. dprintf(TEXT("OpenThreadToken LastError=%d\n"), LastError);
  367. }
  368. SetLastError(LastError);
  369. return (NO_ERROR == LastError);
  370. }
  371. /*--------------------------------------------------------------------------
  372. IsUserProfileLoaded
  373. Silly way to determine whether the user's profile is loaded
  374. Arguments:
  375. IN HANDLE hUserToken : Token for user whose profile to check
  376. Return value:
  377. BOOL : Indicates whether user profile is loaded and available
  378. TRUE : User profile is available
  379. FALSE : User profie is not available or an error was encountered.
  380. Call GetLastError to get an error code describing what failure
  381. was encountered.
  382. Comments:
  383. -------------------------------------------------------------------------*/
  384. BOOL IsUserProfileLoaded(HANDLE hUserToken)
  385. {
  386. PSID pSid;
  387. BOOL success;
  388. LONG error = NO_ERROR;
  389. success = CreateTokenSid(hUserToken, &pSid);
  390. if (success)
  391. {
  392. PTSTR StringSid;
  393. success = CreateStringSidFromSid(pSid, &StringSid);
  394. if (success)
  395. {
  396. HKEY hkUser;
  397. error = RegOpenKeyEx(HKEY_USERS, StringSid, 0, KEY_QUERY_VALUE, &hkUser);
  398. success = (NO_ERROR == error);
  399. if (success) RegCloseKey(hkUser);
  400. HeapFree(hHeap, 0, StringSid);
  401. }
  402. else
  403. {
  404. error = GetLastError();
  405. }
  406. HeapFree(hHeap, 0, pSid);
  407. }
  408. else
  409. {
  410. error = GetLastError();
  411. }
  412. // if (error) dprintf(TEXT("IsUserProfileLoaded : warning: returning error %d\n"), error);
  413. ASSERT(success == (NO_ERROR == error));
  414. SetLastError(error);
  415. return success;
  416. }
  417. //=============================================================================
  418. //=== Rpc helpers ===
  419. //=============================================================================
  420. /*-----------------------------------------------------------------------------
  421. RpcClientHasUserSid
  422. Checks whether the current thread's RPC client's SID matches the given SID.
  423. It does this by impersonating the client using RpcImpersonateClient,
  424. calling the helper function CreateThreadImpersonationSid, and then
  425. RpcRevertToSelf.
  426. The function returns TRUE the SIDs are equal, or FALSE if there is an error
  427. or of the SIDs are not equal. LastError is set.
  428. -----------------------------------------------------------------------------*/
  429. BOOL RpcClientHasUserSid(PSID Sid)
  430. {
  431. LONG LastError;
  432. BOOL result = FALSE;
  433. LastError = RpcImpersonateClient(NULL);
  434. if (NO_ERROR == LastError)
  435. {
  436. PSID ClientSid;
  437. if (CreateThreadImpersonationSid(GetCurrentThread(), &ClientSid))
  438. {
  439. LastError = NO_ERROR;
  440. if (EqualSid(ClientSid, Sid)) result = TRUE;
  441. HeapFree(hHeap, 0, ClientSid);
  442. } else {
  443. LastError = GetLastError();
  444. dprintf(TEXT("RpcClientHasUserSid: CreateThreadImpersonationSid failed, LastError=%d\n"), LastError);
  445. }
  446. RpcRevertToSelf();
  447. }
  448. // We should never match the SID if there was a failure.
  449. ASSERT( ! ((TRUE == result) && (NO_ERROR != LastError)) );
  450. SetLastError(LastError);
  451. return result;
  452. }
  453. //=============================================================================
  454. //=== SetupDi helpers ===
  455. //=============================================================================
  456. BOOL SetupDiCreateDeviceInterfaceDetail(HDEVINFO hdi, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, PSP_DEVICE_INTERFACE_DETAIL_DATA *ppDeviceInterfaceDetailData, PSP_DEVINFO_DATA pDeviceInfoData)
  457. {
  458. DWORD cbDeviceInterfaceDetailData;
  459. BOOL fresult;
  460. fresult = SetupDiGetDeviceInterfaceDetail(hdi, DeviceInterfaceData, NULL, 0, &cbDeviceInterfaceDetailData, NULL);
  461. if (fresult || ERROR_INSUFFICIENT_BUFFER == GetLastError())
  462. {
  463. PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;
  464. DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(hHeap, 0, cbDeviceInterfaceDetailData);
  465. if (DeviceInterfaceDetailData) {
  466. SP_DEVINFO_DATA DeviceInfoData;
  467. DeviceInterfaceDetailData->cbSize = sizeof(*DeviceInterfaceDetailData);
  468. DeviceInfoData.cbSize = sizeof(DeviceInfoData);
  469. fresult = SetupDiGetDeviceInterfaceDetail(hdi, DeviceInterfaceData, DeviceInterfaceDetailData, cbDeviceInterfaceDetailData, NULL, &DeviceInfoData);
  470. if (fresult) {
  471. if (ppDeviceInterfaceDetailData) *ppDeviceInterfaceDetailData = DeviceInterfaceDetailData;
  472. if (pDeviceInfoData) *pDeviceInfoData = DeviceInfoData;
  473. }
  474. if (!fresult || !ppDeviceInterfaceDetailData) {
  475. DWORD dw = GetLastError();
  476. HeapFree(hHeap, 0, DeviceInterfaceDetailData);
  477. SetLastError(dw);
  478. }
  479. }
  480. } else {
  481. DWORD dw = GetLastError();
  482. }
  483. return fresult;
  484. }
  485. BOOL SetupDiGetDeviceInterfaceHardwareId(HDEVINFO hdi, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, PTSTR *ppstrHardwareId)
  486. {
  487. SP_DEVINFO_DATA DeviceInfoData;
  488. PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetailData;
  489. BOOL fresult;
  490. DeviceInfoData.cbSize = sizeof(DeviceInfoData);
  491. fresult = SetupDiCreateDeviceInterfaceDetail(hdi, DeviceInterfaceData, &pDeviceInterfaceDetailData, &DeviceInfoData);
  492. if (fresult) {
  493. DWORD cbHardwareId;
  494. fresult = SetupDiGetDeviceRegistryProperty(hdi, &DeviceInfoData,
  495. SPDRP_HARDWAREID, NULL, NULL, 0, &cbHardwareId);
  496. if (fresult || ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
  497. PTSTR HardwareId;
  498. HardwareId = (PTSTR)HeapAlloc(hHeap, 0, cbHardwareId);
  499. fresult = SetupDiGetDeviceRegistryProperty(hdi, &DeviceInfoData,
  500. SPDRP_HARDWAREID, NULL, (PBYTE)HardwareId, cbHardwareId, NULL);
  501. if (fresult) {
  502. *ppstrHardwareId = HardwareId;
  503. } else {
  504. HeapFree(hHeap, 0, HardwareId);
  505. }
  506. }
  507. HeapFree(hHeap, 0, pDeviceInterfaceDetailData);
  508. }
  509. return fresult;
  510. }
  511. BOOL SetupDiGetDeviceInterfaceBusId(HDEVINFO hdi, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, LPGUID pBusTypeGuid)
  512. {
  513. SP_DEVINFO_DATA DeviceInfoData;
  514. DWORD dwNeeded;
  515. BOOL fresult;
  516. DeviceInfoData.cbSize = sizeof(DeviceInfoData);
  517. fresult = SetupDiGetDeviceInterfaceDetail(hdi, DeviceInterfaceData, NULL, 0, &dwNeeded, &DeviceInfoData);
  518. if (fresult || ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
  519. GUID BusTypeGuid;
  520. ULONG cbBusTypeGuid;
  521. cbBusTypeGuid = sizeof(BusTypeGuid);
  522. fresult = SetupDiGetDeviceRegistryProperty(hdi, &DeviceInfoData, SPDRP_BUSTYPEGUID, NULL, (PBYTE)&BusTypeGuid, cbBusTypeGuid, &cbBusTypeGuid);
  523. if (fresult) *pBusTypeGuid = BusTypeGuid;
  524. }
  525. return fresult;
  526. }
  527. BOOL SetupDiCreateAliasDeviceInterfaceFromDeviceInterface(
  528. IN PCTSTR pDeviceInterface,
  529. IN LPCGUID pAliasInterfaceClassGuid,
  530. OUT PTSTR *ppAliasDeviceInterface
  531. )
  532. {
  533. HDEVINFO hdi;
  534. PSP_DEVICE_INTERFACE_DETAIL_DATA pAudioDeviceInterfaceDetail;
  535. PTSTR pAliasDeviceInterface;
  536. BOOL fresult;
  537. LONG error;
  538. hdi = SetupDiCreateDeviceInfoList(NULL, NULL);
  539. if (INVALID_HANDLE_VALUE != hdi)
  540. {
  541. SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
  542. DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData);
  543. fresult = SetupDiOpenDeviceInterface(hdi, pDeviceInterface, 0, &DeviceInterfaceData);
  544. if (fresult)
  545. {
  546. SP_DEVICE_INTERFACE_DATA AliasDeviceInterfaceData;
  547. PSP_DEVICE_INTERFACE_DETAIL_DATA pAliasDeviceInterfaceDetail;
  548. AliasDeviceInterfaceData.cbSize = sizeof(AliasDeviceInterfaceData);
  549. fresult = SetupDiGetDeviceInterfaceAlias(hdi, &DeviceInterfaceData, pAliasInterfaceClassGuid, &AliasDeviceInterfaceData);
  550. if (fresult)
  551. {
  552. fresult = SetupDiCreateDeviceInterfaceDetail(hdi, &AliasDeviceInterfaceData, &pAliasDeviceInterfaceDetail, NULL);
  553. if (fresult)
  554. {
  555. pAliasDeviceInterface = lstrDuplicate(pAliasDeviceInterfaceDetail->DevicePath);
  556. error = pAliasDeviceInterface ? NO_ERROR : ERROR_OUTOFMEMORY;
  557. HeapFree(hHeap, 0, pAliasDeviceInterfaceDetail);
  558. } else {
  559. error = GetLastError();
  560. }
  561. } else {
  562. error = GetLastError();
  563. }
  564. } else {
  565. error = GetLastError();
  566. }
  567. SetupDiDestroyDeviceInfoList(hdi);
  568. } else {
  569. error = GetLastError();
  570. }
  571. if (NO_ERROR == error)
  572. {
  573. *ppAliasDeviceInterface = pAliasDeviceInterface;
  574. }
  575. return (NO_ERROR == error);
  576. }
  577. //=============================================================================
  578. //
  579. // Reg helpers
  580. //
  581. // The semantics of these functions are designed to be as similar to the
  582. // Win32 API registry functions as reasonably possible.
  583. //
  584. //=============================================================================
  585. LONG RegPrepareEnum(HKEY hkey, PDWORD pcSubkeys, PTSTR *ppstrSubkeyNameBuffer, PDWORD pcchSubkeyNameBuffer)
  586. {
  587. DWORD cSubkeys;
  588. DWORD cchMaxSubkeyName;
  589. LONG lresult;
  590. lresult = RegQueryInfoKey(hkey, NULL, NULL, NULL, &cSubkeys, &cchMaxSubkeyName, NULL, NULL, NULL, NULL, NULL, NULL);
  591. if (NO_ERROR == lresult) {
  592. PTSTR SubkeyName;
  593. SubkeyName = (PTSTR)HeapAlloc(hHeap, 0, (cchMaxSubkeyName+1) * sizeof(TCHAR));
  594. if (SubkeyName) {
  595. *pcSubkeys = cSubkeys;
  596. *ppstrSubkeyNameBuffer = SubkeyName;
  597. *pcchSubkeyNameBuffer = cchMaxSubkeyName+1;
  598. } else {
  599. lresult = ERROR_OUTOFMEMORY;
  600. }
  601. }
  602. return lresult;
  603. }
  604. LONG RegEnumOpenKey(HKEY hkey, DWORD dwIndex, PTSTR SubkeyName, DWORD cchSubkeyName, REGSAM samDesired, PHKEY phkeyResult)
  605. {
  606. LONG lresult;
  607. lresult = RegEnumKeyEx(hkey, dwIndex, SubkeyName, &cchSubkeyName, NULL, NULL, NULL, NULL);
  608. if (NO_ERROR == lresult) {
  609. HKEY hkeyResult;
  610. lresult = RegOpenKeyEx(hkey, SubkeyName, 0, samDesired, &hkeyResult);
  611. if (NO_ERROR == lresult) *phkeyResult = hkeyResult;
  612. }
  613. return lresult;
  614. }
  615. LONG RegDeleteKeyRecursive(HKEY hkey, PCTSTR pstrSubkey)
  616. {
  617. HKEY hkeySub;
  618. LONG lresult;
  619. lresult = RegOpenKeyEx(hkey, pstrSubkey, 0, KEY_READ | KEY_WRITE, &hkeySub);
  620. if (NO_ERROR == lresult)
  621. {
  622. DWORD cSubkeys;
  623. DWORD cchSubkeyNameBuffer;
  624. PTSTR pstrSubkeyNameBuffer;
  625. lresult = RegPrepareEnum(hkeySub, &cSubkeys, &pstrSubkeyNameBuffer, &cchSubkeyNameBuffer);
  626. if (NO_ERROR == lresult)
  627. {
  628. DWORD iSubkey;
  629. for (iSubkey = 0; iSubkey < cSubkeys; iSubkey++)
  630. {
  631. DWORD cchSubkeyNameBufferT;
  632. cchSubkeyNameBufferT = cchSubkeyNameBuffer;
  633. lresult = RegEnumKeyEx(hkeySub, iSubkey, pstrSubkeyNameBuffer, &cchSubkeyNameBufferT, NULL, NULL, NULL, NULL);
  634. if (NO_ERROR != lresult) break;
  635. lresult = RegDeleteKeyRecursive(hkeySub, pstrSubkeyNameBuffer);
  636. if (NO_ERROR != lresult) break;
  637. }
  638. HeapFree(hHeap, 0, pstrSubkeyNameBuffer);
  639. }
  640. RegCloseKey(hkeySub);
  641. }
  642. if (NO_ERROR == lresult) lresult = RegDeleteKey(hkey, pstrSubkey);
  643. return lresult;
  644. }
  645. //=============================================================================
  646. //=== Utilities ===
  647. //=============================================================================
  648. LONG XxNextId(HKEY hkey, PDWORD pId)
  649. {
  650. HKEY hkeyGfx;
  651. DWORD Id;
  652. LONG lresult;
  653. lresult = RegCreateKeyEx(hkey, REGSTR_PATH_GFX, 0, NULL, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, NULL, &hkeyGfx, NULL);
  654. if (NO_ERROR == lresult)
  655. {
  656. lresult = RegQueryDwordValue(hkeyGfx, REGSTR_VAL_GFX_IDGEN, &Id);
  657. if (ERROR_FILE_NOT_FOUND == lresult) {
  658. Id = 0;
  659. lresult = NO_ERROR;
  660. }
  661. if (NO_ERROR == lresult) {
  662. Id++;
  663. lresult = RegSetDwordValue(hkeyGfx, REGSTR_VAL_GFX_IDGEN, Id);
  664. }
  665. RegCloseKey(hkeyGfx);
  666. }
  667. if (NO_ERROR == lresult) *pId = Id;
  668. return lresult;
  669. }
  670. LONG LmNextId(PDWORD pId)
  671. {
  672. return XxNextId(HKEY_LOCAL_MACHINE, pId);
  673. }
  674. LONG CuNextId(CUser *pUser, PDWORD pId)
  675. {
  676. HKEY hkeyCu;
  677. LONG lresult;
  678. lresult = pUser->RegOpen(KEY_READ, &hkeyCu);
  679. if (!lresult)
  680. {
  681. lresult = XxNextId(hkeyCu, pId);
  682. RegCloseKey(hkeyCu);
  683. }
  684. return lresult;
  685. }
  686. BOOL ZoneTypeHasRender(IN ULONG Type)
  687. {
  688. if (ZONETYPE_RENDERCAPTURE == Type) return TRUE;
  689. if (ZONETYPE_RENDER == Type) return TRUE;
  690. return FALSE;
  691. }
  692. BOOL ZoneTypeHasCapture(IN ULONG Type)
  693. {
  694. if (ZONETYPE_RENDERCAPTURE == Type) return TRUE;
  695. if (ZONETYPE_CAPTURE == Type) return TRUE;
  696. return FALSE;
  697. }
  698. void LockGlobalLists(void)
  699. {
  700. ASSERT(gplistZoneFactories);
  701. ASSERT(gplistGfxFactories);
  702. ASSERT(gplistCuUserLoads);
  703. gplistZoneFactories->Lock();
  704. gplistGfxFactories->Lock();
  705. gplistCuUserLoads->Lock();
  706. return;
  707. }
  708. void UnlockGlobalLists(void)
  709. {
  710. ASSERT(gplistZoneFactories);
  711. ASSERT(gplistGfxFactories);
  712. ASSERT(gplistCuUserLoads);
  713. gplistCuUserLoads->Unlock();
  714. gplistGfxFactories->Unlock();
  715. gplistZoneFactories->Unlock();
  716. return;
  717. }
  718. void LockSysaudio(void)
  719. {
  720. ASSERT(gfCsSysaudio);
  721. EnterCriticalSection(&gcsSysaudio);
  722. return;
  723. }
  724. void UnlockSysaudio(void)
  725. {
  726. ASSERT(gfCsSysaudio);
  727. LeaveCriticalSection(&gcsSysaudio);
  728. return;
  729. }
  730. //=============================================================================
  731. //=== CuUserLoad ===
  732. //=============================================================================
  733. CCuUserLoad::CCuUserLoad(CUser *pUser)
  734. {
  735. ASSERT(pUser);
  736. m_User = pUser;
  737. m_ZoneFactoryDi = NULL;
  738. m_GfxFactoryDi = NULL;
  739. m_FilterHandle = INVALID_HANDLE_VALUE;
  740. m_ErrorFilterCreate = NO_ERROR;
  741. m_pZoneFactory = NULL;
  742. m_posZoneGfxList = NULL;
  743. }
  744. CCuUserLoad::~CCuUserLoad(void)
  745. {
  746. RemoveFromZoneGraph();
  747. HeapFreeIfNotNull(hHeap, 0, m_ZoneFactoryDi);
  748. HeapFreeIfNotNull(hHeap, 0, m_GfxFactoryDi);
  749. }
  750. /*--------------------------------------------------------------------------
  751. CCuUserLoad::AddGfxToGraph
  752. Adds an instantiated gfx to the sysaudio graph for a zone factory.
  753. Arguments:
  754. IN CCuUserLoad *pCuUserLoad : The gfx to add to the graph
  755. OUT POSITION *pZoneGfxListPosition : The resulting list position
  756. in the zone factory's list of gfxs.
  757. Return value:
  758. LONG : error code defined in winerror.h
  759. ERROR_OUTOFMEMORY :
  760. Comments:
  761. The caller should have already instantiated the gfx.
  762. This function walks the zone factory's gfx list (either render or
  763. capture list depending on the type of gfx being added) to find an
  764. insertion point. The gfx list is sorted by gfx order. Finally, the
  765. resulting list position is returned to the caller so that it can be
  766. passed back to RemoveFromGraph or ChangeGfxOrderInGraph later.
  767. -------------------------------------------------------------------------*/
  768. LONG CCuUserLoad::AddGfxToGraph(void)
  769. {
  770. CListCuUserLoads *plistGfxs;
  771. POSITION posNextGfx;
  772. CCuUserLoad *pNextGfx;
  773. LONG error;
  774. // dprintf(TEXT("CCuUserLoad::AddGfxToGraph\n"));
  775. ASSERT(INVALID_HANDLE_VALUE != m_FilterHandle);
  776. ASSERT(NULL == m_posZoneGfxList);
  777. error = NO_ERROR;
  778. if (GFXTYPE_CAPTURE == m_Type) plistGfxs = &m_pZoneFactory->m_listCaptureGfxs;
  779. else if (GFXTYPE_RENDER == m_Type) plistGfxs = &m_pZoneFactory->m_listRenderGfxs;
  780. else ASSERT(FALSE);
  781. //
  782. // Find possible insertion point for the new gfx by scanning list up to
  783. // a point where all previous gfxs have lower order values.
  784. //
  785. for (posNextGfx = plistGfxs->GetHeadPosition(); posNextGfx; plistGfxs->GetNext(posNextGfx))
  786. {
  787. pNextGfx = plistGfxs->GetAt(posNextGfx);
  788. if (m_Order <= pNextGfx->m_Order) break;
  789. }
  790. //
  791. // If there is a conflict with an existing gfx at the insertion point
  792. // then either shift the conflicting gfx to a higher order or bump the
  793. // insertion point and the new gfx's order and try again, depending
  794. // on whether this gfx "wins the conflict" with the conflicting gfx.
  795. //
  796. while (!error && posNextGfx && (m_Order == pNextGfx->m_Order))
  797. {
  798. if (WinsConflictWith(pNextGfx))
  799. {
  800. error = pNextGfx->ModifyOrder(pNextGfx->m_Order + 1);
  801. }
  802. else
  803. {
  804. plistGfxs->GetNext(posNextGfx);
  805. if (posNextGfx) pNextGfx = plistGfxs->GetAt(posNextGfx);
  806. m_Order++;
  807. }
  808. }
  809. //
  810. // We've finally determined the proper insertion point and resolved any
  811. // conflicts. Insert the gfx into the gfx list, add the gfx to the
  812. // sysaudio graph, and finally persist the gfx again if the final order
  813. // is different than original.
  814. //
  815. if (!error)
  816. {
  817. POSITION posGfx;
  818. posGfx = plistGfxs->InsertBefore(posNextGfx, this);
  819. if (!posGfx) error = ERROR_OUTOFMEMORY;
  820. if (!error)
  821. {
  822. // ISSUE-2000/09/21-FrankYe Need to pass friendly name
  823. error = SadAddGfxToZoneGraph(ghSysaudio, m_FilterHandle, TEXT("ISSUE-2000//09//21-FrankYe Need to pass friendly name"), m_ZoneFactoryDi, m_Type, m_Order);
  824. if (error) dprintf(TEXT("CCuUserLoad::AddGfxToZoneGraph : error: SadAddGfxToZoneGraph returned %d\n"), error);
  825. if (!error) m_posZoneGfxList = posGfx;
  826. else plistGfxs->RemoveAt(posGfx);
  827. }
  828. }
  829. return error;
  830. }
  831. //--------------------------------------------------------------------------;
  832. //
  833. // CCuUserLoad::AddToZoneGraph
  834. //
  835. // Instantiates and adds a GFX filter to a zone graph.
  836. //
  837. // Arguments:
  838. // CZoneFactory *pZoneFactory : Identifies the zone to which the GFX
  839. // is added.
  840. //
  841. // Return value:
  842. // LONG : error code defined in winerror.h
  843. //
  844. // Comments:
  845. // Instantiates the filter.
  846. // Advises filter of target device id.
  847. // Unserializes persistent properties to filter.
  848. // Calls AddToGraph on the ZoneFactory.
  849. //
  850. //--------------------------------------------------------------------------;
  851. LONG CCuUserLoad::AddToZoneGraph(CZoneFactory *pZoneFactory)
  852. {
  853. LONG error;
  854. dprintf(TEXT("CCuUserLoad::AddToZoneGraph : note: instantiating %s Gfx[%s] in Zone[%s]\n"), (GFXTYPE_RENDER == m_Type) ? TEXT("render") : TEXT("capture"), m_GfxFactoryDi, m_ZoneFactoryDi);
  855. ASSERT(NULL == m_pZoneFactory);
  856. ASSERT(NULL == m_posZoneGfxList);
  857. ASSERT(INVALID_HANDLE_VALUE == m_FilterHandle);
  858. //
  859. // Instantiate the GFX filter
  860. //
  861. m_FilterHandle = CreateFile(m_GfxFactoryDi,
  862. GENERIC_READ | GENERIC_WRITE,
  863. 0,
  864. NULL,
  865. OPEN_EXISTING,
  866. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  867. NULL);
  868. error = (INVALID_HANDLE_VALUE == m_FilterHandle) ? GetLastError() : NO_ERROR;
  869. //
  870. // Advise filter of the zone's target hardware IDs
  871. //
  872. if (!error)
  873. {
  874. switch(m_Type)
  875. {
  876. case GFXTYPE_RENDER:
  877. KsSetAudioGfxRenderTargetDeviceId(m_FilterHandle, pZoneFactory->GetTargetHardwareId());
  878. break;
  879. case GFXTYPE_CAPTURE:
  880. KsSetAudioGfxCaptureTargetDeviceId(m_FilterHandle, pZoneFactory->GetTargetHardwareId());
  881. break;
  882. case GFXTYPE_RENDERCAPTURE:
  883. // NTRAID#298244-2000/12/18-FrankYe Someday implement RENDERCAPTURE GFXs
  884. ASSERT(FALSE);
  885. break;
  886. default:
  887. ASSERT(FALSE);
  888. }
  889. }
  890. //
  891. // Restore filter settings from registry
  892. //
  893. if (!error)
  894. {
  895. HKEY hkFilterSettings;
  896. if (NO_ERROR == RegOpenFilterKey(REGSTR_PATH_GFXUSERLOADID_FILTERSETTINGS, KEY_READ, &hkFilterSettings)) {
  897. KsUnserializeFilterStateFromReg(m_FilterHandle, hkFilterSettings);
  898. RegCloseKey(hkFilterSettings);
  899. }
  900. }
  901. //
  902. // Save pointer to the zone factory to which we're adding this gfx
  903. //
  904. if (!error)
  905. {
  906. m_pZoneFactory = pZoneFactory;
  907. }
  908. //
  909. // Tell zone factory to add this gfx to its graph
  910. //
  911. if (!error)
  912. {
  913. error = AddGfxToGraph();
  914. }
  915. //
  916. // Unwind if error
  917. //
  918. if (error)
  919. {
  920. if (INVALID_HANDLE_VALUE != m_FilterHandle)
  921. {
  922. CloseHandle(m_FilterHandle);
  923. m_FilterHandle = INVALID_HANDLE_VALUE;
  924. }
  925. }
  926. m_ErrorFilterCreate = error;
  927. return error;
  928. }
  929. /*--------------------------------------------------------------------------
  930. CCuUserLoad::ChangeGfxOrderInGraph
  931. Changes the order of a gfx already in the zone graph.
  932. Arguments:
  933. IN ULONG NewGfxOrder : The new order value for the gfx.
  934. Return value:
  935. LONG : error code defined in winerror.h
  936. ERROR_INVALID_PARAMETER : A gfx already occupies the
  937. requested order.
  938. ERROR_OUTOFMEMORY :
  939. Comments:
  940. -------------------------------------------------------------------------*/
  941. LONG CCuUserLoad::ChangeGfxOrderInGraph(IN ULONG NewGfxOrder)
  942. {
  943. CListCuUserLoads *plistGfxs;
  944. CCuUserLoad *pNextGfx;
  945. POSITION posNextGfx;
  946. LONG error;
  947. // dprintf(TEXT("CCuUserLoad::ChangeGfxOrderInGraph\n"));
  948. error = NO_ERROR;
  949. if (GFXTYPE_CAPTURE == m_Type) plistGfxs = &m_pZoneFactory->m_listCaptureGfxs;
  950. else if (GFXTYPE_RENDER == m_Type) plistGfxs = &m_pZoneFactory->m_listRenderGfxs;
  951. else ASSERT(FALSE);
  952. error = SadRemoveGfxFromZoneGraph(ghSysaudio, m_FilterHandle, TEXT("ISSUE-2000//09//21-FrankYe Need to pass friendly name"), m_ZoneFactoryDi, m_Type, m_Order);
  953. if (error) dprintf(TEXT("CCuUserLoad::ChangeGfxToZoneGraph : error: SadRemoveGfxFromZoneGraph returned %d\n"), error);
  954. if (!error)
  955. {
  956. POSITION posOriginalNextGfx;
  957. posOriginalNextGfx = m_posZoneGfxList;
  958. plistGfxs->GetNext(posOriginalNextGfx);
  959. // Find insertion position
  960. for (posNextGfx = plistGfxs->GetHeadPosition(); posNextGfx; plistGfxs->GetNext(posNextGfx))
  961. {
  962. pNextGfx = plistGfxs->GetAt(posNextGfx);
  963. if (NewGfxOrder <= pNextGfx->m_Order) break;
  964. }
  965. // posNextGfx is now the list position after the insertion point
  966. plistGfxs->MoveBefore(posNextGfx, m_posZoneGfxList);
  967. if (posNextGfx && (NewGfxOrder == pNextGfx->m_Order))
  968. {
  969. dprintf(TEXT("CCuUserLoad::ChangeGfxOrderInGraph : note: attempting to move conflicting GFX ID %08X moving from %d to %d\n"),
  970. pNextGfx->GetId(), pNextGfx->m_Order, pNextGfx->m_Order + 1);
  971. plistGfxs->SetAt(m_posZoneGfxList, NULL);
  972. error = pNextGfx->ModifyOrder(pNextGfx->m_Order + 1);
  973. plistGfxs->SetAt(m_posZoneGfxList, this);
  974. }
  975. if (!error)
  976. {
  977. // ISSUE-2000/09/21-FrankYe Need to pass friendly name
  978. error = SadAddGfxToZoneGraph(ghSysaudio, m_FilterHandle, TEXT("ISSUE-2000//09//21-FrankYe Need to pass friendly name"), m_ZoneFactoryDi, m_Type, NewGfxOrder);
  979. if (error) dprintf(TEXT("CCuUserLoadFactory::ChangeGfxOrderInGraph : error: SadAddGfxToZoneGraph returned %d\n"), error);
  980. if (!error)
  981. {
  982. m_Order = NewGfxOrder;
  983. if (!error) Write();
  984. }
  985. }
  986. else
  987. {
  988. plistGfxs->MoveBefore(posOriginalNextGfx, m_posZoneGfxList);
  989. }
  990. }
  991. return error;
  992. }
  993. LONG CCuUserLoad::CreateFromAutoLoad(ULONG CuAutoLoadId)
  994. {
  995. LONG lresult;
  996. CCuAutoLoad *pCuAutoLoad = new CCuAutoLoad(m_User);
  997. ASSERT(!m_GfxFactoryDi);
  998. ASSERT(!m_ZoneFactoryDi);
  999. if (pCuAutoLoad)
  1000. {
  1001. lresult = pCuAutoLoad->Initialize(CuAutoLoadId);
  1002. if (!lresult)
  1003. {
  1004. m_CuUserLoadId = CuAutoLoadId;
  1005. m_CuAutoLoadId = CuAutoLoadId;
  1006. m_Type = pCuAutoLoad->GetType();
  1007. m_Order = 0;
  1008. m_GfxFactoryDi = lstrDuplicate(pCuAutoLoad->GetGfxFactoryDi());
  1009. if (m_GfxFactoryDi) m_ZoneFactoryDi = lstrDuplicate(pCuAutoLoad->GetZoneFactoryDi());
  1010. if (!m_ZoneFactoryDi) lresult = ERROR_OUTOFMEMORY;
  1011. }
  1012. delete pCuAutoLoad;
  1013. } else {
  1014. lresult = ERROR_OUTOFMEMORY;
  1015. }
  1016. return lresult;
  1017. }
  1018. LONG CCuUserLoad::CreateFromUser(PCTSTR GfxFactoryDi, PCTSTR ZoneFactoryDi, ULONG Type, ULONG Order)
  1019. {
  1020. LONG lresult;
  1021. ASSERT((GFXTYPE_RENDER == Type) || (GFXTYPE_CAPTURE == Type));
  1022. ASSERT(GFX_MAXORDER >= Order);
  1023. ASSERT(!m_GfxFactoryDi);
  1024. ASSERT(!m_ZoneFactoryDi);
  1025. lresult = CuNextId(m_User, &m_CuUserLoadId);
  1026. if (!lresult)
  1027. {
  1028. m_CuAutoLoadId = 0;
  1029. m_Type = Type;
  1030. m_Order = Order;
  1031. m_GfxFactoryDi = lstrDuplicate(GfxFactoryDi);
  1032. m_ZoneFactoryDi = lstrDuplicate(ZoneFactoryDi);
  1033. if (!m_GfxFactoryDi || !m_ZoneFactoryDi) lresult = ERROR_OUTOFMEMORY;
  1034. }
  1035. return lresult;
  1036. }
  1037. LONG CCuUserLoad::Erase(void)
  1038. {
  1039. HKEY hkeyCu;
  1040. HKEY hkeyCuUserLoadEnum;
  1041. LONG lresult;
  1042. lresult = m_User->RegOpen(KEY_READ, &hkeyCu);
  1043. if (!lresult)
  1044. {
  1045. lresult = RegOpenKeyEx(hkeyCu, REGSTR_PATH_GFXUSERLOAD, 0, KEY_CREATE_SUB_KEY, &hkeyCuUserLoadEnum);
  1046. if (!lresult)
  1047. {
  1048. TCHAR szCuUserLoad[9];
  1049. wsprintf(szCuUserLoad, TEXT("%08X"), m_CuUserLoadId);
  1050. lresult = RegDeleteKeyRecursive(hkeyCuUserLoadEnum, szCuUserLoad);
  1051. RegCloseKey(hkeyCuUserLoadEnum);
  1052. }
  1053. RegCloseKey(hkeyCu);
  1054. }
  1055. return lresult;
  1056. }
  1057. /*-----------------------------------------------------------------------------
  1058. CCuUserLoad::GetGfxFactoryClsid
  1059. Uses the specified list of Gfx factories (CListGfxFactories) to find the
  1060. user interface CLSID of the Gfx factory whose device interface matches the
  1061. one associated with this CCuUserLoad object
  1062. Caller must acquire locks on rlistGfxFactories
  1063. -----------------------------------------------------------------------------*/
  1064. LONG CCuUserLoad::GetGfxFactoryClsid(CListGfxFactories &rlistGfxFactories, LPCLSID pClsid)
  1065. {
  1066. CGfxFactory *pGfxFactory;
  1067. LONG lresult;
  1068. ASSERT(m_GfxFactoryDi);
  1069. pGfxFactory = CGfxFactory::ListSearchOnDi(rlistGfxFactories, m_GfxFactoryDi);
  1070. if (pGfxFactory)
  1071. {
  1072. *pClsid = pGfxFactory->GetClsid();
  1073. lresult = NO_ERROR;
  1074. } else {
  1075. // ISSUE-2000/09/15-FrankYe : Best error code?
  1076. *pClsid = GUID_NULL;
  1077. lresult = ERROR_DEVICE_NOT_AVAILABLE;
  1078. }
  1079. return lresult;
  1080. }
  1081. PCTSTR CCuUserLoad::GetGfxFactoryDi(void)
  1082. {
  1083. return m_GfxFactoryDi;
  1084. }
  1085. HANDLE CCuUserLoad::GetFilterHandle(void)
  1086. {
  1087. ASSERT((INVALID_HANDLE_VALUE != m_FilterHandle) || (NO_ERROR != m_ErrorFilterCreate));
  1088. SetLastError(m_ErrorFilterCreate);
  1089. return m_FilterHandle;
  1090. }
  1091. DWORD CCuUserLoad::GetId(void)
  1092. {
  1093. return m_CuUserLoadId;
  1094. }
  1095. ULONG CCuUserLoad::GetOrder(void)
  1096. {
  1097. return m_Order;
  1098. }
  1099. ULONG CCuUserLoad::GetType(void)
  1100. {
  1101. return m_Type;
  1102. }
  1103. PCTSTR CCuUserLoad::GetZoneFactoryDi(void)
  1104. {
  1105. return m_ZoneFactoryDi;
  1106. }
  1107. LONG CCuUserLoad::Initialize(PCTSTR pstrUserLoadId)
  1108. {
  1109. HKEY hkeyCu;
  1110. HKEY hkeyCuUserLoadEnum;
  1111. PTSTR pstrEnd;
  1112. LONG lresult;
  1113. m_CuUserLoadId = _tcstoul((PTSTR)pstrUserLoadId, &pstrEnd, 16);
  1114. // dprintf(TEXT("CCuUserLoad::Initialize : subkey [%s] CuUserLoadId=%08X\n"), pstrUserLoadId, m_CuUserLoadId);
  1115. lresult = m_User->RegOpen(KEY_READ, &hkeyCu);
  1116. if (!lresult)
  1117. {
  1118. lresult = RegOpenKeyEx(hkeyCu, REGSTR_PATH_GFXUSERLOAD, 0, KEY_ENUMERATE_SUB_KEYS, &hkeyCuUserLoadEnum);
  1119. if (!lresult)
  1120. {
  1121. HKEY hkeyCuUserLoad;
  1122. lresult = RegOpenKeyEx(hkeyCuUserLoadEnum, pstrUserLoadId, 0, KEY_QUERY_VALUE, &hkeyCuUserLoad);
  1123. if (!lresult)
  1124. {
  1125. lresult = RegQuerySzValue(hkeyCuUserLoad, REGSTR_VAL_GFX_ZONEDI, &m_ZoneFactoryDi);
  1126. if (!lresult) lresult = RegQuerySzValue(hkeyCuUserLoad, REGSTR_VAL_GFX_GFXDI, &m_GfxFactoryDi);
  1127. if (!lresult) lresult = RegQueryDwordValue(hkeyCuUserLoad, REGSTR_VAL_GFX_TYPE, &m_Type);
  1128. if (!lresult) lresult = RegQueryDwordValue(hkeyCuUserLoad, REGSTR_VAL_GFX_ORDER, &m_Order);
  1129. if (!lresult && (m_Order > GFX_MAXORDER)) lresult = ERROR_BADDB;
  1130. if (!lresult)
  1131. {
  1132. lresult = RegQueryDwordValue(hkeyCuUserLoad, REGSTR_VAL_GFX_CUAUTOLOADID, &m_CuAutoLoadId);
  1133. if (!lresult && 0 != m_CuAutoLoadId)
  1134. {
  1135. CCuAutoLoad *pCuAutoLoad = new CCuAutoLoad(m_User);
  1136. if (pCuAutoLoad)
  1137. {
  1138. lresult = pCuAutoLoad->Initialize(m_CuAutoLoadId);
  1139. delete pCuAutoLoad;
  1140. } else {
  1141. lresult = ERROR_OUTOFMEMORY;
  1142. }
  1143. } else if (ERROR_FILE_NOT_FOUND == lresult) {
  1144. m_CuAutoLoadId = 0;
  1145. lresult = NO_ERROR;
  1146. }
  1147. }
  1148. RegCloseKey(hkeyCuUserLoad);
  1149. }
  1150. RegCloseKey(hkeyCuUserLoadEnum);
  1151. }
  1152. RegCloseKey(hkeyCu);
  1153. }
  1154. return lresult;
  1155. }
  1156. /*--------------------------------------------------------------------------
  1157. CCuUserLoad::WinsConflictWith
  1158. Attempts to determine which gfx factory should be given priority (i.e.,
  1159. be closer to the render or capture device).
  1160. Arguments:
  1161. IN CCuUserLoad pOther : Other gfx to compare against.
  1162. Return value:
  1163. BOOL : True if this gfx wins the conflict.
  1164. Comments:
  1165. If both gfxs have LmAutoLoadIds then we compare those. The higher ID
  1166. (more recently insalled) wins. If only one has an LmAutoLoadId then it
  1167. wins because we favor autoload GFXs over generic GFXs. If neither have
  1168. LmAutoLoadIds, then this CuUserLoad object wins, arbitrarily.
  1169. -------------------------------------------------------------------------*/
  1170. BOOL CCuUserLoad::WinsConflictWith(IN CCuUserLoad *that)
  1171. {
  1172. ULONG thisId = 0;
  1173. ULONG thatId = 0;;
  1174. if (this->m_CuAutoLoadId)
  1175. {
  1176. CCuAutoLoad *pCuAutoLoad = new CCuAutoLoad(m_User);
  1177. if (pCuAutoLoad)
  1178. {
  1179. if (NO_ERROR == pCuAutoLoad->Initialize(this->m_CuAutoLoadId))
  1180. {
  1181. thisId = pCuAutoLoad->GetLmAutoLoadId();
  1182. }
  1183. delete pCuAutoLoad;
  1184. }
  1185. }
  1186. if (that->m_CuAutoLoadId)
  1187. {
  1188. CCuAutoLoad *pCuAutoLoad = new CCuAutoLoad(m_User);
  1189. if (pCuAutoLoad)
  1190. {
  1191. if (NO_ERROR == pCuAutoLoad->Initialize(that->m_CuAutoLoadId))
  1192. {
  1193. thatId = pCuAutoLoad->GetLmAutoLoadId();
  1194. }
  1195. delete pCuAutoLoad;
  1196. }
  1197. }
  1198. return (thisId >= thatId);
  1199. }
  1200. //--------------------------------------------------------------------------;
  1201. //
  1202. // CCuUserLoad::ModifyOrder
  1203. //
  1204. // Modfies the position of a gfx in a zone graph.
  1205. //
  1206. // Arguments:
  1207. // IN ULONG NewOrder : The new position for the gfx.
  1208. //
  1209. // Return value:
  1210. // LONG : error code defined in winerror.h
  1211. // ERROR_INVALID_FUNCTION : gfx not yet in a zone graph
  1212. //
  1213. // Comments:
  1214. // The gfx should already be in a zone graph before calling this
  1215. // function. Otherwise, it returns an error. This function calls
  1216. // ChangeGfxOrderInGraph on the ZoneFactory to do the buld of the work.
  1217. //
  1218. //--------------------------------------------------------------------------;
  1219. LONG CCuUserLoad::ModifyOrder(IN ULONG NewOrder)
  1220. {
  1221. LONG error = NO_ERROR;
  1222. if (NO_ERROR != m_ErrorFilterCreate) return m_ErrorFilterCreate;
  1223. ASSERT(INVALID_HANDLE_VALUE != m_FilterHandle);
  1224. ASSERT(m_pZoneFactory);
  1225. ASSERT(m_posZoneGfxList);
  1226. if (m_Order != NewOrder) error = ChangeGfxOrderInGraph(NewOrder);
  1227. else dprintf(TEXT("CCuUserLoad::ModifyOrder : warning: new order same as old\n"));
  1228. return error;
  1229. }
  1230. LONG CCuUserLoad::RegCreateFilterKey(IN PCTSTR SubKey, IN REGSAM samDesired, OUT PHKEY phkResult)
  1231. {
  1232. HKEY hkCu;
  1233. LONG result;
  1234. result = m_User->RegOpen(KEY_READ, &hkCu);
  1235. if (NO_ERROR == result)
  1236. {
  1237. HKEY hkCuUserLoad;
  1238. TCHAR strRegPath[] = REGSTR_PATH_GFXUSERLOAD TEXT("\\00000000");
  1239. wsprintf(strRegPath, TEXT("%s\\%08X"), REGSTR_PATH_GFXUSERLOAD, m_CuUserLoadId);
  1240. result = RegOpenKeyEx(hkCu, strRegPath, 0, KEY_CREATE_SUB_KEY, &hkCuUserLoad);
  1241. if (NO_ERROR == result)
  1242. {
  1243. result = RegCreateKeyEx(hkCuUserLoad, SubKey, 0, NULL, REG_OPTION_NON_VOLATILE, samDesired, NULL, phkResult, NULL);
  1244. RegCloseKey(hkCuUserLoad);
  1245. }
  1246. RegCloseKey(hkCu);
  1247. }
  1248. return result;
  1249. }
  1250. LONG CCuUserLoad::RegOpenFilterKey(IN PCTSTR SubKey, IN REGSAM samDesired, OUT PHKEY phkResult)
  1251. {
  1252. HKEY hkCu;
  1253. LONG result;
  1254. result = m_User->RegOpen(KEY_READ, &hkCu);
  1255. if (NO_ERROR == result)
  1256. {
  1257. HKEY hkCuUserLoad;
  1258. TCHAR strRegPath[] = REGSTR_PATH_GFXUSERLOAD TEXT("\\00000000");
  1259. wsprintf(strRegPath, TEXT("%s\\%08X"), REGSTR_PATH_GFXUSERLOAD, m_CuUserLoadId);
  1260. result = RegOpenKeyEx(hkCu, strRegPath, 0, KEY_ENUMERATE_SUB_KEYS, &hkCuUserLoad);
  1261. if (NO_ERROR == result)
  1262. {
  1263. result = RegOpenKeyEx(hkCuUserLoad, SubKey, 0, samDesired, phkResult);
  1264. RegCloseKey(hkCuUserLoad);
  1265. }
  1266. RegCloseKey(hkCu);
  1267. }
  1268. return result;
  1269. }
  1270. /*--------------------------------------------------------------------------
  1271. CCuUserLoad::RemoveFromGraph
  1272. Removes a gfx from the zone factory's sysaudio graph.
  1273. Arguments:
  1274. Return value:
  1275. LONG : error code defined in winerror.h
  1276. Comments:
  1277. -------------------------------------------------------------------------*/
  1278. LONG CCuUserLoad::RemoveFromGraph(void)
  1279. {
  1280. CListCuUserLoads *plistGfxs = NULL;
  1281. LONG error;
  1282. ASSERT(INVALID_HANDLE_VALUE != m_FilterHandle);
  1283. error = NO_ERROR;
  1284. if (GFXTYPE_CAPTURE == m_Type) plistGfxs = &m_pZoneFactory->m_listCaptureGfxs;
  1285. else if (GFXTYPE_RENDER == m_Type) plistGfxs = &m_pZoneFactory->m_listRenderGfxs;
  1286. else ASSERT(FALSE);
  1287. //
  1288. // Command Sysaudio to disconnect the filter from the
  1289. // zone's graph.
  1290. //
  1291. // ISSUE-2000/09/21-FrankYe Need to pass friendly name
  1292. error = SadRemoveGfxFromZoneGraph(ghSysaudio, m_FilterHandle, TEXT("ISSUE-2000//09//21-FrankYe Need to pass friendly name"), m_ZoneFactoryDi, m_Type, m_Order);
  1293. if (error) dprintf(TEXT("CCuUserLoad::RemoveFromGraph : error: SadRemoveGfxFromZoneGraph returned %d\n"), error);
  1294. if (!error && plistGfxs) plistGfxs->RemoveAt(m_posZoneGfxList);
  1295. return error;
  1296. }
  1297. //--------------------------------------------------------------------------;
  1298. //
  1299. // CCuUserLoad::RemoveFromZoneGraph
  1300. //
  1301. // Removes a gfx from its zone graph.
  1302. //
  1303. // Arguments:
  1304. //
  1305. // Return value:
  1306. // void
  1307. //
  1308. // Comments:
  1309. // If the GFX has been added to a zone graph, this function removes it from
  1310. // the graph. First it persists any settings on the GFX, then it calls
  1311. // RemoveFromGraph on the ZoneFactory. Finally it finally closes the GFX
  1312. // handle.
  1313. //
  1314. // This method is called from this object's destructor, so it is important
  1315. // that this function do its best to handle any errors.
  1316. //
  1317. //--------------------------------------------------------------------------;
  1318. void CCuUserLoad::RemoveFromZoneGraph(void)
  1319. {
  1320. if (INVALID_HANDLE_VALUE != m_FilterHandle)
  1321. {
  1322. HKEY hkFilterSettings;
  1323. LONG error;
  1324. ASSERT(m_pZoneFactory);
  1325. ASSERT(m_posZoneGfxList);
  1326. ASSERT(INVALID_HANDLE_VALUE != ghSysaudio);
  1327. //
  1328. // Save filter settings to registry
  1329. //
  1330. if (NO_ERROR == RegCreateFilterKey(REGSTR_PATH_GFXUSERLOADID_FILTERSETTINGS, KEY_WRITE, &hkFilterSettings)) {
  1331. KsSerializeFilterStateToReg(m_FilterHandle, hkFilterSettings);
  1332. RegCloseKey(hkFilterSettings);
  1333. }
  1334. error = RemoveFromGraph();
  1335. m_pZoneFactory = NULL;
  1336. m_posZoneGfxList = NULL;
  1337. m_ErrorFilterCreate = error;
  1338. if (!error)
  1339. {
  1340. CloseHandle(m_FilterHandle);
  1341. m_FilterHandle = INVALID_HANDLE_VALUE;
  1342. }
  1343. }
  1344. return;
  1345. }
  1346. LONG CCuUserLoad::Write(void)
  1347. {
  1348. HKEY hkeyCu;
  1349. HKEY hkeyCuUserLoadEnum;
  1350. LONG lresult;
  1351. lresult = m_User->RegOpen(KEY_READ, &hkeyCu);
  1352. if (!lresult)
  1353. {
  1354. lresult = RegCreateKeyEx(hkeyCu, REGSTR_PATH_GFXUSERLOAD, 0, NULL, 0, KEY_CREATE_SUB_KEY, NULL, &hkeyCuUserLoadEnum, NULL);
  1355. if (NO_ERROR == lresult)
  1356. {
  1357. TCHAR szUserLoad[9];
  1358. HKEY hkeyCuUserLoad;
  1359. wsprintf(szUserLoad, TEXT("%08X"), m_CuUserLoadId);
  1360. lresult = RegCreateKeyEx(hkeyCuUserLoadEnum, szUserLoad, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkeyCuUserLoad, NULL);
  1361. if (!lresult)
  1362. {
  1363. lresult = RegSetSzValue(hkeyCuUserLoad, REGSTR_VAL_GFX_GFXDI, m_GfxFactoryDi);
  1364. if (!lresult) lresult = RegSetSzValue(hkeyCuUserLoad, REGSTR_VAL_GFX_ZONEDI, m_ZoneFactoryDi);
  1365. if (!lresult) lresult = RegSetDwordValue(hkeyCuUserLoad, REGSTR_VAL_GFX_TYPE, m_Type);
  1366. if (!lresult) lresult = RegSetDwordValue(hkeyCuUserLoad, REGSTR_VAL_GFX_ORDER, m_Order);
  1367. if (!lresult && (0 != m_CuAutoLoadId)) lresult = RegSetDwordValue(hkeyCuUserLoad, REGSTR_VAL_GFX_CUAUTOLOADID, m_CuAutoLoadId);
  1368. RegCloseKey(hkeyCuUserLoad);
  1369. // Any errors writing the values would leave an invalid reg entry. So delete if errors
  1370. if (lresult) RegDeleteKey(hkeyCuUserLoadEnum, szUserLoad);
  1371. }
  1372. RegCloseKey(hkeyCuUserLoadEnum);
  1373. }
  1374. RegCloseKey(hkeyCu);
  1375. }
  1376. return lresult;
  1377. }
  1378. /*-----------------------------------------------------------------------------
  1379. CCuUserLoad::FillListFromReg
  1380. Adds elements to the specified list of user-loads (CListCuUserLoads) based
  1381. on the contents of the REGSTR_PATH_GFXUSERLOAD registry information
  1382. Caller must acquire any necessary locks on rlistCuUserLoads
  1383. -----------------------------------------------------------------------------*/
  1384. void CCuUserLoad::FillListFromReg(CUser *pUser, CListCuUserLoads &rlistCuUserLoads)
  1385. {
  1386. HKEY hkeyCu;
  1387. HKEY hkeyCuUserLoadEnum;
  1388. LONG lresult;
  1389. ASSERT(pUser);
  1390. lresult = pUser->RegOpen(KEY_READ, &hkeyCu);
  1391. if (!lresult)
  1392. {
  1393. lresult = RegOpenKeyEx(hkeyCu, REGSTR_PATH_GFXUSERLOAD, 0, KEY_READ, &hkeyCuUserLoadEnum);
  1394. if (!lresult)
  1395. {
  1396. DWORD cSubkeys;
  1397. DWORD cchSubkeyNameBuffer;
  1398. PTSTR pstrSubkeyNameBuffer;
  1399. lresult = RegPrepareEnum(hkeyCuUserLoadEnum, &cSubkeys, &pstrSubkeyNameBuffer, &cchSubkeyNameBuffer);
  1400. if (NO_ERROR == lresult)
  1401. {
  1402. CListCuUserLoads listCuUserLoadsErase;
  1403. lresult = listCuUserLoadsErase.Initialize();
  1404. if (!lresult)
  1405. {
  1406. POSITION pos;
  1407. DWORD dwIndex;
  1408. for (dwIndex = 0; dwIndex < cSubkeys; dwIndex++)
  1409. {
  1410. DWORD cchSubkeyNameBufferT;
  1411. cchSubkeyNameBufferT = cchSubkeyNameBuffer;
  1412. lresult = RegEnumKeyEx(hkeyCuUserLoadEnum, dwIndex, pstrSubkeyNameBuffer, &cchSubkeyNameBufferT, NULL, NULL, NULL, NULL);
  1413. if (!lresult)
  1414. {
  1415. CCuUserLoad *pCuUserLoad = new CCuUserLoad(pUser);
  1416. if (pCuUserLoad)
  1417. {
  1418. lresult = pCuUserLoad->Initialize(pstrSubkeyNameBuffer);
  1419. if (ERROR_FILE_NOT_FOUND == lresult) {
  1420. if (!listCuUserLoadsErase.AddTail(pCuUserLoad))
  1421. {
  1422. lresult = ERROR_OUTOFMEMORY;
  1423. delete pCuUserLoad;
  1424. }
  1425. } else if (NO_ERROR == lresult) {
  1426. if (!rlistCuUserLoads.AddTail(pCuUserLoad))
  1427. {
  1428. lresult = ERROR_OUTOFMEMORY;
  1429. delete pCuUserLoad;
  1430. }
  1431. } else {
  1432. delete pCuUserLoad;
  1433. }
  1434. } else {
  1435. lresult = ERROR_OUTOFMEMORY;
  1436. }
  1437. }
  1438. }
  1439. pos = listCuUserLoadsErase.GetHeadPosition();
  1440. while (pos)
  1441. {
  1442. CCuUserLoad *pCuUserLoad = listCuUserLoadsErase.GetNext(pos);
  1443. pCuUserLoad->Erase();
  1444. delete pCuUserLoad;
  1445. }
  1446. }
  1447. }
  1448. RegCloseKey(hkeyCuUserLoadEnum);
  1449. }
  1450. else
  1451. {
  1452. // dprintf(TEXT("CCuUserLoad::FillListFromReg : error: RegOpenKeyEx returned %d\n"), lresult);
  1453. }
  1454. RegCloseKey(hkeyCu);
  1455. }
  1456. else
  1457. {
  1458. dprintf(TEXT("CCuUserLoad::FillListFromReg : error: pUser->RegOpen returned %d\n"), lresult);
  1459. }
  1460. return;
  1461. }
  1462. /*-----------------------------------------------------------------------------
  1463. CCuUserLoad::Scan
  1464. The caller must acquire any locks required for rlistZoneFactories and
  1465. rlistGfxFactories
  1466. -----------------------------------------------------------------------------*/
  1467. LONG CCuUserLoad::Scan(CListZoneFactories &rlistZoneFactories, CListGfxFactories &rlistGfxFactories)
  1468. {
  1469. LONG lresult;
  1470. // dprintf(TEXT("CCuUserLoad::Scan\n"));
  1471. if (m_CuAutoLoadId != 0)
  1472. {
  1473. // Confirm the CuAutoLoad is still valid
  1474. CCuAutoLoad *pCuAutoLoad = new CCuAutoLoad(m_User);
  1475. if (pCuAutoLoad)
  1476. {
  1477. lresult = pCuAutoLoad->Initialize(m_CuAutoLoadId);
  1478. delete pCuAutoLoad;
  1479. } else {
  1480. lresult = ERROR_OUTOFMEMORY;
  1481. }
  1482. } else {
  1483. lresult = NO_ERROR;
  1484. }
  1485. LockSysaudio();
  1486. if (!lresult && (INVALID_HANDLE_VALUE == m_FilterHandle) && (INVALID_HANDLE_VALUE != ghSysaudio))
  1487. {
  1488. // dprintf(TEXT("Checking Gfx[%s] and Zone[%s}\n"), m_GfxFactoryDi, m_ZoneFactoryDi);
  1489. // See if this CuUserLoad needs loaded. It needs loaded if:
  1490. // a) The GfxFactory exists,
  1491. // b) The ZoneFactory exists
  1492. // c) The ZoneFactory is the proper type
  1493. CZoneFactory *pZoneFactory = CZoneFactory::ListSearchOnDi(rlistZoneFactories, m_ZoneFactoryDi);
  1494. if (pZoneFactory)
  1495. {
  1496. CGfxFactory *pGfxFactory = CGfxFactory::ListSearchOnDi(rlistGfxFactories, m_GfxFactoryDi);
  1497. if (pGfxFactory)
  1498. {
  1499. lresult = AddToZoneGraph(pZoneFactory);
  1500. }
  1501. }
  1502. }
  1503. UnlockSysaudio();
  1504. return lresult;
  1505. }
  1506. /*-----------------------------------------------------------------------------
  1507. CCuUserLoad::ScanList
  1508. This function walks all members of a user-load list (CListCuUserLoads)
  1509. and invokes Scan on each of them.
  1510. The caller must acquire any necessary lock on rlistCuUserLoads,
  1511. rlistZoneFactories, and rlistGfxFactories.
  1512. -----------------------------------------------------------------------------*/
  1513. void CCuUserLoad::ScanList(CListCuUserLoads& rlistCuUserLoads, CListZoneFactories& rlistZoneFactories, CListGfxFactories& rlistGfxFactories)
  1514. {
  1515. POSITION posNext;
  1516. posNext = rlistCuUserLoads.GetHeadPosition();
  1517. while (posNext)
  1518. {
  1519. POSITION posThis = posNext;
  1520. CCuUserLoad& rCuUserLoad = *rlistCuUserLoads.GetNext(posNext);
  1521. LONG lresult = rCuUserLoad.Scan(rlistZoneFactories, rlistGfxFactories);
  1522. if (ERROR_FILE_NOT_FOUND == lresult)
  1523. {
  1524. rCuUserLoad.Erase();
  1525. rlistCuUserLoads.RemoveAt(posThis);
  1526. delete &rCuUserLoad;
  1527. }
  1528. }
  1529. return;
  1530. }
  1531. void CCuUserLoad::ListRemoveGfxFactoryDi(IN CListCuUserLoads &rlistCuUserLoads, IN PCTSTR DeviceInterface)
  1532. {
  1533. POSITION pos;
  1534. pos = rlistCuUserLoads.GetHeadPosition();
  1535. while (pos) {
  1536. CCuUserLoad& rCuUserLoad = *rlistCuUserLoads.GetNext(pos);
  1537. if (!lstrcmpi(DeviceInterface, rCuUserLoad.GetGfxFactoryDi())) rCuUserLoad.RemoveFromZoneGraph();
  1538. }
  1539. return;
  1540. }
  1541. void CCuUserLoad::ListRemoveZoneFactoryDi(IN CListCuUserLoads &rlistCuUserLoads, IN PCTSTR DeviceInterface)
  1542. {
  1543. POSITION pos;
  1544. pos = rlistCuUserLoads.GetHeadPosition();
  1545. while (pos) {
  1546. CCuUserLoad& rCuUserLoad = *rlistCuUserLoads.GetNext(pos);
  1547. if (!lstrcmpi(DeviceInterface, rCuUserLoad.GetZoneFactoryDi())) rCuUserLoad.RemoveFromZoneGraph();
  1548. }
  1549. return;
  1550. }
  1551. void CCuUserLoad::ListRemoveZoneFactoryDiRender(IN CListCuUserLoads &rlistCuUserLoads, IN PCTSTR DeviceInterface)
  1552. {
  1553. POSITION pos;
  1554. pos = rlistCuUserLoads.GetHeadPosition();
  1555. while (pos) {
  1556. CCuUserLoad& rCuUserLoad = *rlistCuUserLoads.GetNext(pos);
  1557. if (!lstrcmpi(DeviceInterface, rCuUserLoad.GetZoneFactoryDi()))
  1558. {
  1559. ULONG GfxType = rCuUserLoad.GetType();
  1560. if ((GFXTYPE_RENDER == GfxType) || (GFXTYPE_RENDERCAPTURE == GfxType)) rCuUserLoad.RemoveFromZoneGraph();
  1561. }
  1562. }
  1563. }
  1564. void CCuUserLoad::ListRemoveZoneFactoryDiCapture(IN CListCuUserLoads &rlistCuUserLoads, IN PCTSTR DeviceInterface)
  1565. {
  1566. POSITION pos;
  1567. pos = rlistCuUserLoads.GetHeadPosition();
  1568. while (pos) {
  1569. CCuUserLoad& rCuUserLoad = *rlistCuUserLoads.GetNext(pos);
  1570. if (!lstrcmpi(DeviceInterface, rCuUserLoad.GetZoneFactoryDi()))
  1571. {
  1572. ULONG GfxType = rCuUserLoad.GetType();
  1573. if ((GFXTYPE_CAPTURE == GfxType) || (GFXTYPE_RENDERCAPTURE == GfxType)) rCuUserLoad.RemoveFromZoneGraph();
  1574. }
  1575. }
  1576. }
  1577. //=============================================================================
  1578. //=== CuAutoLoad ===
  1579. //=============================================================================
  1580. CCuAutoLoad::CCuAutoLoad(CUser *pUser)
  1581. {
  1582. ASSERT(pUser);
  1583. m_User = pUser;
  1584. m_ZoneFactoryDi = NULL;
  1585. m_GfxFactoryDi = NULL;
  1586. }
  1587. CCuAutoLoad::~CCuAutoLoad(void)
  1588. {
  1589. HeapFreeIfNotNull(hHeap, 0, m_ZoneFactoryDi);
  1590. HeapFreeIfNotNull(hHeap, 0, m_GfxFactoryDi);
  1591. }
  1592. LONG CCuAutoLoad::Create(PCTSTR ZoneFactoryDi, ULONG LmAutoLoadId)
  1593. {
  1594. LONG lresult;
  1595. CLmAutoLoad *pLmAutoLoad = new CLmAutoLoad;
  1596. if (pLmAutoLoad)
  1597. {
  1598. lresult = pLmAutoLoad->Initialize(LmAutoLoadId);
  1599. if (!lresult)
  1600. {
  1601. lresult = CuNextId(m_User, &m_CuAutoLoadId);
  1602. if (!lresult)
  1603. {
  1604. m_LmAutoLoadId = LmAutoLoadId;
  1605. m_Type = pLmAutoLoad->GetType();
  1606. m_ZoneFactoryDi = lstrDuplicate(ZoneFactoryDi);
  1607. if (m_ZoneFactoryDi) m_GfxFactoryDi = lstrDuplicate(pLmAutoLoad->GetGfxFactoryDi());
  1608. if (!m_GfxFactoryDi) lresult = ERROR_OUTOFMEMORY;
  1609. }
  1610. }
  1611. delete pLmAutoLoad;
  1612. } else {
  1613. lresult = ERROR_OUTOFMEMORY;
  1614. }
  1615. return lresult;
  1616. }
  1617. /*-----------------------------------------------------------------------------
  1618. CCuAutoLoad::Erase
  1619. This function erases the registry data representing this CCuAutoLoad object.
  1620. -----------------------------------------------------------------------------*/
  1621. LONG CCuAutoLoad::Erase(void)
  1622. {
  1623. HKEY hkeyCu;
  1624. LONG lresult;
  1625. lresult = m_User->RegOpen(KEY_READ, &hkeyCu);
  1626. if (!lresult)
  1627. {
  1628. HKEY hkeyCuAutoLoadEnum;
  1629. lresult = RegOpenKeyEx(hkeyCu, REGSTR_PATH_GFXAUTOLOAD, 0, KEY_WRITE, &hkeyCuAutoLoadEnum);
  1630. if (!lresult)
  1631. {
  1632. TCHAR szCuAutoLoad[9];
  1633. wsprintf(szCuAutoLoad, TEXT("%08X"), m_CuAutoLoadId);
  1634. lresult = RegDeleteKeyRecursive(hkeyCuAutoLoadEnum, szCuAutoLoad);
  1635. RegCloseKey(hkeyCuAutoLoadEnum);
  1636. }
  1637. RegCloseKey(hkeyCu);
  1638. }
  1639. return lresult;
  1640. }
  1641. PCTSTR CCuAutoLoad::GetGfxFactoryDi(void)
  1642. {
  1643. return m_GfxFactoryDi;
  1644. }
  1645. ULONG CCuAutoLoad::GetLmAutoLoadId(void)
  1646. {
  1647. return m_LmAutoLoadId;
  1648. }
  1649. ULONG CCuAutoLoad::GetType(void)
  1650. {
  1651. return m_Type;
  1652. }
  1653. PCTSTR CCuAutoLoad::GetZoneFactoryDi(void)
  1654. {
  1655. return m_ZoneFactoryDi;
  1656. }
  1657. LONG CCuAutoLoad::Initialize(ULONG CuAutoLoadId)
  1658. {
  1659. HKEY hkeyCu;
  1660. LONG lresult;
  1661. m_CuAutoLoadId = CuAutoLoadId;
  1662. lresult = m_User->RegOpen(KEY_READ, &hkeyCu);
  1663. if (!lresult)
  1664. {
  1665. HKEY hkeyCuAutoLoadEnum;
  1666. lresult = RegOpenKeyEx(hkeyCu, REGSTR_PATH_GFXAUTOLOAD, 0, KEY_ENUMERATE_SUB_KEYS, &hkeyCuAutoLoadEnum);
  1667. if (!lresult)
  1668. {
  1669. HKEY hkeyCuAutoLoad;
  1670. TCHAR szCuAutoLoad[9];
  1671. wsprintf(szCuAutoLoad, TEXT("%08X"), m_CuAutoLoadId);
  1672. lresult = RegOpenKeyEx(hkeyCuAutoLoadEnum, szCuAutoLoad, 0, KEY_QUERY_VALUE, &hkeyCuAutoLoad);
  1673. if (!lresult)
  1674. {
  1675. lresult = RegQuerySzValue(hkeyCuAutoLoad, REGSTR_VAL_GFX_ZONEDI, &m_ZoneFactoryDi);
  1676. if (!lresult) lresult = RegQueryDwordValue(hkeyCuAutoLoad, REGSTR_VAL_GFX_LMAUTOLOADID, &m_LmAutoLoadId);
  1677. if (!lresult)
  1678. {
  1679. CLmAutoLoad *pLmAutoLoad = new CLmAutoLoad;
  1680. if (pLmAutoLoad)
  1681. {
  1682. lresult = pLmAutoLoad->Initialize(m_LmAutoLoadId);
  1683. if (!lresult)
  1684. {
  1685. m_Type = pLmAutoLoad->GetType();
  1686. m_GfxFactoryDi = lstrDuplicate(pLmAutoLoad->GetGfxFactoryDi());
  1687. if (!m_GfxFactoryDi) lresult = ERROR_OUTOFMEMORY;
  1688. }
  1689. delete pLmAutoLoad;
  1690. } else {
  1691. lresult = ERROR_OUTOFMEMORY;
  1692. }
  1693. }
  1694. // ISSUE-2000/09/25-FrankYe a FILE_NOT_FOUND error on any values would indicate a corrupt reg entry!
  1695. RegCloseKey(hkeyCuAutoLoad);
  1696. }
  1697. RegCloseKey(hkeyCuAutoLoadEnum);
  1698. }
  1699. RegCloseKey(hkeyCu);
  1700. }
  1701. return lresult;
  1702. }
  1703. /*-----------------------------------------------------------------------------
  1704. CCuAutoLoad::ScanReg
  1705. -----------------------------------------------------------------------------*/
  1706. void CCuAutoLoad::ScanReg(IN CUser *pUser, IN PCTSTR ZoneFactoryDi, IN ULONG LmAutoLoadId, IN CListCuUserLoads &rlistCuUserLoads)
  1707. {
  1708. HKEY hkeyCu;
  1709. LONG lresult;
  1710. ASSERT(pUser);
  1711. lresult = pUser->RegOpen(KEY_READ, &hkeyCu);
  1712. if (!lresult)
  1713. {
  1714. HKEY hkeyCuAutoLoadEnum;
  1715. lresult = RegOpenKeyEx(hkeyCu, REGSTR_PATH_GFXAUTOLOAD, 0, KEY_READ, &hkeyCuAutoLoadEnum);
  1716. if (!lresult)
  1717. {
  1718. DWORD cSubkeys;
  1719. PTSTR pstrSubkeyNameBuffer;
  1720. DWORD cchSubkeyNameBuffer;
  1721. lresult = RegPrepareEnum(hkeyCuAutoLoadEnum, &cSubkeys, &pstrSubkeyNameBuffer, &cchSubkeyNameBuffer);
  1722. if (!lresult)
  1723. {
  1724. DWORD dwIndex;
  1725. lresult = ERROR_FILE_NOT_FOUND;
  1726. for (dwIndex = 0; (dwIndex < cSubkeys) && (ERROR_FILE_NOT_FOUND == lresult); dwIndex++)
  1727. {
  1728. DWORD cchSubkeyNameBufferT = cchSubkeyNameBuffer;
  1729. lresult = RegEnumKeyEx(hkeyCuAutoLoadEnum, dwIndex, pstrSubkeyNameBuffer, &cchSubkeyNameBufferT, NULL, NULL, NULL, NULL);
  1730. if (!lresult)
  1731. {
  1732. CCuAutoLoad *pCuAutoLoad = new CCuAutoLoad(pUser);
  1733. if (pCuAutoLoad)
  1734. {
  1735. PTSTR pstrEnd;
  1736. ULONG CuAutoLoadId = _tcstoul(pstrSubkeyNameBuffer, &pstrEnd, 16);
  1737. lresult = pCuAutoLoad->Initialize(CuAutoLoadId);
  1738. if (!lresult)
  1739. {
  1740. if (LmAutoLoadId != pCuAutoLoad->m_LmAutoLoadId ||
  1741. lstrcmpi(ZoneFactoryDi, pCuAutoLoad->m_ZoneFactoryDi))
  1742. {
  1743. lresult = ERROR_FILE_NOT_FOUND;
  1744. }
  1745. }
  1746. delete pCuAutoLoad;
  1747. } else {
  1748. lresult = ERROR_OUTOFMEMORY;
  1749. }
  1750. }
  1751. }
  1752. HeapFree(hHeap, 0, pstrSubkeyNameBuffer);
  1753. }
  1754. RegCloseKey(hkeyCuAutoLoadEnum);
  1755. }
  1756. if (ERROR_FILE_NOT_FOUND == lresult)
  1757. {
  1758. //
  1759. // For this user, create and write a CuAutoLoad to the registry
  1760. // and create and write a counterpart CuUserLoad to the registry.
  1761. // If writing the CuUserLoad to registry fails, we should erase
  1762. // the CuAutoLoad from the registry. Then, audiosrv will retry
  1763. // creating the CuAutoLoad and CuUserLoad reg entries next time.
  1764. //
  1765. CCuAutoLoad *pCuAutoLoad = new CCuAutoLoad(pUser);
  1766. if (pCuAutoLoad)
  1767. {
  1768. CCuUserLoad *pCuUserLoad = new CCuUserLoad(pUser);
  1769. if (pCuUserLoad)
  1770. {
  1771. lresult = pCuAutoLoad->Create(ZoneFactoryDi, LmAutoLoadId);
  1772. if (!lresult) lresult = pCuAutoLoad->Write();
  1773. if (!lresult)
  1774. {
  1775. lresult = pCuUserLoad->CreateFromAutoLoad(pCuAutoLoad->m_CuAutoLoadId);
  1776. if (!lresult) lresult = pCuUserLoad->Write();
  1777. if (lresult) pCuAutoLoad->Erase();
  1778. if (!lresult) if (!rlistCuUserLoads.AddTail(pCuUserLoad))
  1779. if (lresult) delete pCuUserLoad;
  1780. }
  1781. }
  1782. delete pCuAutoLoad;
  1783. }
  1784. }
  1785. RegCloseKey(hkeyCu);
  1786. }
  1787. }
  1788. /*-------------------------------------------------------------------
  1789. CCuAutoLoad::Write
  1790. Creates a registry entry in REGSTR_PATH_GFXAUTOLOAD representing
  1791. this CCuAutoLoad object.
  1792. -------------------------------------------------------------------*/
  1793. LONG CCuAutoLoad::Write(void)
  1794. {
  1795. HKEY hkeyCu;
  1796. LONG lresult;
  1797. lresult = m_User->RegOpen(KEY_READ, &hkeyCu);
  1798. if (!lresult)
  1799. {
  1800. HKEY hkeyCuAutoLoadEnum;
  1801. lresult = RegCreateKeyEx(hkeyCu, REGSTR_PATH_GFXAUTOLOAD, 0, NULL, 0, KEY_CREATE_SUB_KEY, NULL, &hkeyCuAutoLoadEnum, NULL);
  1802. if (!lresult)
  1803. {
  1804. HKEY hkeyCuAutoLoad;
  1805. TCHAR szCuAutoLoad[9];
  1806. wsprintf(szCuAutoLoad, TEXT("%08X"), m_CuAutoLoadId);
  1807. lresult = RegCreateKeyEx(hkeyCuAutoLoadEnum, szCuAutoLoad, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkeyCuAutoLoad, NULL);
  1808. if (!lresult)
  1809. {
  1810. lresult = RegSetSzValue(hkeyCuAutoLoad, REGSTR_VAL_GFX_ZONEDI, m_ZoneFactoryDi);
  1811. if (!lresult) lresult = RegSetDwordValue(hkeyCuAutoLoad, REGSTR_VAL_GFX_LMAUTOLOADID, m_LmAutoLoadId);
  1812. RegCloseKey(hkeyCuAutoLoad);
  1813. // If any of the above failed, let's not leave this CuAutoLoad in the registry
  1814. if (lresult) RegDeleteKeyRecursive(hkeyCuAutoLoadEnum, szCuAutoLoad);
  1815. }
  1816. RegCloseKey(hkeyCuAutoLoadEnum);
  1817. }
  1818. RegCloseKey(hkeyCu);
  1819. }
  1820. return lresult;
  1821. }
  1822. //=============================================================================
  1823. //=== LmAutoLoad ===
  1824. //=============================================================================
  1825. CLmAutoLoad::CLmAutoLoad(void)
  1826. {
  1827. m_GfxFactoryDi = NULL;
  1828. m_HardwareId = NULL;
  1829. m_ReferenceString = NULL;
  1830. }
  1831. CLmAutoLoad::~CLmAutoLoad(void)
  1832. {
  1833. HeapFreeIfNotNull(hHeap, 0, m_GfxFactoryDi);
  1834. HeapFreeIfNotNull(hHeap, 0, m_HardwareId);
  1835. HeapFreeIfNotNull(hHeap, 0, m_ReferenceString);
  1836. }
  1837. LONG CLmAutoLoad::Create(DWORD Id, PCTSTR GfxFactoryDi, PCTSTR HardwareId, PCTSTR ReferenceString, ULONG Type)
  1838. {
  1839. ASSERT(!m_GfxFactoryDi);
  1840. ASSERT(!m_HardwareId);
  1841. ASSERT(!m_ReferenceString);
  1842. m_Id = Id;
  1843. m_Type = Type;
  1844. m_GfxFactoryDi = lstrDuplicate(GfxFactoryDi);
  1845. if (m_GfxFactoryDi) m_HardwareId = lstrDuplicate(HardwareId);
  1846. if (m_HardwareId) m_ReferenceString = lstrDuplicate(ReferenceString);
  1847. return m_ReferenceString ? NO_ERROR : ERROR_OUTOFMEMORY;
  1848. }
  1849. LONG CLmAutoLoad::Erase(void)
  1850. {
  1851. HKEY hkeyLmAutoLoadEnum;
  1852. LONG lresult;
  1853. lresult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_GFXAUTOLOAD, 0, KEY_CREATE_SUB_KEY, &hkeyLmAutoLoadEnum);
  1854. if (!lresult)
  1855. {
  1856. TCHAR szLmAutoLoad[9];
  1857. wsprintf(szLmAutoLoad, TEXT("%08x"), m_Id);
  1858. lresult = RegDeleteKeyRecursive(hkeyLmAutoLoadEnum, szLmAutoLoad);
  1859. RegCloseKey(hkeyLmAutoLoadEnum);
  1860. }
  1861. return lresult;
  1862. }
  1863. PCTSTR CLmAutoLoad::GetGfxFactoryDi(void)
  1864. {
  1865. return m_GfxFactoryDi;
  1866. }
  1867. ULONG CLmAutoLoad::GetType(void)
  1868. {
  1869. return m_Type;
  1870. }
  1871. LONG CLmAutoLoad::Initialize(DWORD Id)
  1872. {
  1873. HKEY hkeyLmAutoLoadEnum;
  1874. LONG lresult;
  1875. m_Id = Id;
  1876. lresult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_GFXAUTOLOAD, 0, KEY_ENUMERATE_SUB_KEYS, &hkeyLmAutoLoadEnum);
  1877. if (!lresult)
  1878. {
  1879. TCHAR szLmAutoLoad[9];
  1880. HKEY hkeyLmAutoLoad;
  1881. wsprintf(szLmAutoLoad, TEXT("%08x"), m_Id);
  1882. lresult = RegOpenKeyEx(hkeyLmAutoLoadEnum, szLmAutoLoad, 0, KEY_QUERY_VALUE, &hkeyLmAutoLoad);
  1883. if (!lresult)
  1884. {
  1885. lresult = RegQuerySzValue(hkeyLmAutoLoad, REGSTR_VAL_GFX_GFXDI, &m_GfxFactoryDi);
  1886. if (!lresult) lresult = RegQuerySzValue(hkeyLmAutoLoad, REGSTR_VAL_GFX_HARDWAREID, &m_HardwareId);
  1887. if (!lresult) lresult = RegQuerySzValue(hkeyLmAutoLoad, REGSTR_VAL_GFX_REFERENCESTRING, &m_ReferenceString);
  1888. if (!lresult) lresult = RegQueryDwordValue(hkeyLmAutoLoad, REGSTR_VAL_GFX_TYPE, &m_Type);
  1889. RegCloseKey(hkeyLmAutoLoad);
  1890. if (ERROR_FILE_NOT_FOUND == lresult)
  1891. {
  1892. // If any of these values are missing, then this
  1893. // registry data is corrupt
  1894. lresult = ERROR_BADDB;
  1895. }
  1896. }
  1897. RegCloseKey(hkeyLmAutoLoadEnum);
  1898. }
  1899. return lresult;
  1900. }
  1901. BOOL CLmAutoLoad::IsCompatibleZoneFactory(CZoneFactory& rZoneFactory)
  1902. {
  1903. if (!rZoneFactory.HasHardwareId(m_HardwareId)) return FALSE;
  1904. if (!rZoneFactory.HasReferenceString(m_ReferenceString)) return FALSE;
  1905. if (!rZoneFactory.HasCompatibleType(m_Type)) return FALSE;
  1906. return TRUE;
  1907. }
  1908. LONG CLmAutoLoad::Write(void)
  1909. {
  1910. HKEY hkeyLmAutoLoadEnum;
  1911. LONG lresult;
  1912. lresult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_GFXAUTOLOAD, 0, NULL, 0, KEY_CREATE_SUB_KEY, NULL, &hkeyLmAutoLoadEnum, NULL);
  1913. if (!lresult)
  1914. {
  1915. TCHAR szLmAutoLoad[9];
  1916. HKEY hkeyLmAutoLoad;
  1917. wsprintf(szLmAutoLoad, TEXT("%08x"), m_Id);
  1918. lresult = RegCreateKeyEx(hkeyLmAutoLoadEnum, szLmAutoLoad, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkeyLmAutoLoad, NULL);
  1919. if (!lresult)
  1920. {
  1921. lresult = RegSetSzValue(hkeyLmAutoLoad, REGSTR_VAL_GFX_GFXDI, m_GfxFactoryDi);
  1922. if (!lresult) lresult = RegSetSzValue(hkeyLmAutoLoad, REGSTR_VAL_GFX_HARDWAREID, m_HardwareId);
  1923. if (!lresult) lresult = RegSetSzValue(hkeyLmAutoLoad, REGSTR_VAL_GFX_REFERENCESTRING, m_ReferenceString);
  1924. if (!lresult) lresult = RegSetDwordValue(hkeyLmAutoLoad, REGSTR_VAL_GFX_TYPE, m_Type);
  1925. RegCloseKey(hkeyLmAutoLoad);
  1926. if (lresult) RegDeleteKeyRecursive(hkeyLmAutoLoadEnum, szLmAutoLoad);
  1927. }
  1928. RegCloseKey(hkeyLmAutoLoadEnum);
  1929. }
  1930. return lresult;
  1931. }
  1932. CListLmAutoLoads* CLmAutoLoad::CreateListFromReg(void)
  1933. {
  1934. CListLmAutoLoads *pListLmAutoLoads = new CListLmAutoLoads;
  1935. if (pListLmAutoLoads)
  1936. {
  1937. LONG lresult;
  1938. lresult = pListLmAutoLoads->Initialize();
  1939. if (!lresult) {
  1940. HKEY hkeyLmAutoLoadEnum;
  1941. lresult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_GFXAUTOLOAD, 0, KEY_READ, &hkeyLmAutoLoadEnum);
  1942. if (!lresult)
  1943. {
  1944. DWORD cSubkeys;
  1945. PTSTR pstrSubkeyNameBuffer;
  1946. DWORD cchSubkeyNameBuffer;
  1947. lresult = RegPrepareEnum(hkeyLmAutoLoadEnum, &cSubkeys, &pstrSubkeyNameBuffer, &cchSubkeyNameBuffer);
  1948. if (!lresult)
  1949. {
  1950. DWORD dwIndex = 0;
  1951. for (dwIndex = 0; dwIndex < cSubkeys; dwIndex++)
  1952. {
  1953. DWORD cchSubkeyNameBufferT = cchSubkeyNameBuffer;
  1954. lresult = RegEnumKeyEx(hkeyLmAutoLoadEnum, dwIndex, pstrSubkeyNameBuffer, &cchSubkeyNameBufferT, 0, NULL, 0, NULL);
  1955. if (!lresult) {
  1956. CLmAutoLoad *pLmAutoLoad = new CLmAutoLoad;
  1957. if (pLmAutoLoad)
  1958. {
  1959. PTSTR pstrEnd;
  1960. ULONG Id = _tcstoul(pstrSubkeyNameBuffer, &pstrEnd, 16);
  1961. if (pLmAutoLoad->Initialize(Id) || !pListLmAutoLoads->AddTail(pLmAutoLoad))
  1962. {
  1963. delete pLmAutoLoad;
  1964. }
  1965. }
  1966. }
  1967. }
  1968. HeapFree(hHeap, 0, pstrSubkeyNameBuffer);
  1969. }
  1970. RegCloseKey(hkeyLmAutoLoadEnum);
  1971. }
  1972. } else {
  1973. delete pListLmAutoLoads;
  1974. pListLmAutoLoads = NULL;
  1975. }
  1976. }
  1977. return pListLmAutoLoads;
  1978. }
  1979. void CLmAutoLoad::DestroyList(CListLmAutoLoads *pListLmAutoLoads)
  1980. {
  1981. POSITION pos = pListLmAutoLoads->GetHeadPosition();
  1982. while (pos) delete pListLmAutoLoads->GetNext(pos);
  1983. delete pListLmAutoLoads;
  1984. }
  1985. /*-----------------------------------------------------------------------------
  1986. CLmAutoLoad::ScanRegOnGfxFactory
  1987. This function reads the local machine auto-load instructions from the
  1988. registry. Given a Gfx factory (CGfxFactory) and a list of Zone factories
  1989. (CListZoneFactories) it finds any auto loads (CLmAutoLoad) that can
  1990. be loaded and added to a specified CCuUserLoad list. For such auto-loads
  1991. that it finds, it notifies any corresonding auto load for the current user.
  1992. The caller must acquire any necessary locks on the GfxFactory,
  1993. listZoneFactories, and listCuUserLoads.
  1994. -----------------------------------------------------------------------------*/
  1995. void CLmAutoLoad::ScanRegOnGfxFactory(CUser *pUser, CGfxFactory& rGfxFactory, CListZoneFactories& rlistZoneFactories, CListCuUserLoads &rlistCuUserLoads)
  1996. {
  1997. CListLmAutoLoads *pListLmAutoLoads = CLmAutoLoad::CreateListFromReg();
  1998. ASSERT(pUser);
  1999. if (pListLmAutoLoads)
  2000. {
  2001. POSITION posLmAutoLoads = pListLmAutoLoads->GetHeadPosition();
  2002. while (posLmAutoLoads)
  2003. {
  2004. CLmAutoLoad& rLmAutoLoad = *pListLmAutoLoads->GetNext(posLmAutoLoads);
  2005. if (lstrcmpi(rGfxFactory.GetDeviceInterface(), rLmAutoLoad.m_GfxFactoryDi)) continue;
  2006. POSITION posZoneFactories = rlistZoneFactories.GetHeadPosition();
  2007. while (posZoneFactories)
  2008. {
  2009. CZoneFactory& rZoneFactory = *rlistZoneFactories.GetNext(posZoneFactories);
  2010. if (!rLmAutoLoad.IsCompatibleZoneFactory(rZoneFactory)) continue;
  2011. // This is more like a notification than a scan
  2012. CCuAutoLoad::ScanReg(pUser, rZoneFactory.GetDeviceInterface(), rLmAutoLoad.m_Id, rlistCuUserLoads);
  2013. }
  2014. }
  2015. CLmAutoLoad::DestroyList(pListLmAutoLoads);
  2016. }
  2017. }
  2018. /*-----------------------------------------------------------------------------
  2019. CLmAutoLoad::ScanRegOnZoneFactory
  2020. This function reads the local machine auto load instructions from the
  2021. registry. Given a Zone factory (CZoneFactory) and a list of Gfx factories
  2022. (CListGfxFactories) it finds any auto loads (CLmAutoLoad) that can
  2023. be loaded. For such auto loads that it finds, it notifies any
  2024. corresonding auto load for the current user.
  2025. The caller must acquire any necessary locks on the ZoneFactory and the
  2026. listGfxFactories.
  2027. -----------------------------------------------------------------------------*/
  2028. void CLmAutoLoad::ScanRegOnZoneFactory(CUser *pUser, CZoneFactory& rZoneFactory, CListGfxFactories& rlistGfxFactories, CListCuUserLoads& rlistCuUserLoads)
  2029. {
  2030. CListLmAutoLoads *pListLmAutoLoads = CLmAutoLoad::CreateListFromReg();
  2031. ASSERT(pUser);
  2032. if (pListLmAutoLoads)
  2033. {
  2034. POSITION posLmAutoLoads = pListLmAutoLoads->GetHeadPosition();
  2035. while (posLmAutoLoads)
  2036. {
  2037. CLmAutoLoad& rLmAutoLoad = *pListLmAutoLoads->GetNext(posLmAutoLoads);
  2038. if (!rLmAutoLoad.IsCompatibleZoneFactory(rZoneFactory)) continue;
  2039. POSITION posGfxFactories = rlistGfxFactories.GetHeadPosition();
  2040. while (posGfxFactories)
  2041. {
  2042. CGfxFactory& rGfxFactory = *rlistGfxFactories.GetNext(posGfxFactories);
  2043. if (lstrcmpi(rGfxFactory.GetDeviceInterface(), rLmAutoLoad.m_GfxFactoryDi)) continue;
  2044. // This is more like a notification than a scan
  2045. CCuAutoLoad::ScanReg(pUser, rZoneFactory.GetDeviceInterface(), rLmAutoLoad.m_Id, rlistCuUserLoads);
  2046. }
  2047. }
  2048. CLmAutoLoad::DestroyList(pListLmAutoLoads);
  2049. }
  2050. }
  2051. //=============================================================================
  2052. //=== InfAutoLoad ===
  2053. //=============================================================================
  2054. CInfAutoLoad::CInfAutoLoad(void)
  2055. {
  2056. m_hkey = NULL;
  2057. m_GfxFactoryDi = NULL;
  2058. m_HardwareId = NULL;
  2059. m_ReferenceString = NULL;
  2060. }
  2061. CInfAutoLoad::~CInfAutoLoad(void)
  2062. {
  2063. HeapFreeIfNotNull(hHeap, 0, m_GfxFactoryDi);
  2064. HeapFreeIfNotNull(hHeap, 0, m_HardwareId);
  2065. HeapFreeIfNotNull(hHeap, 0, m_ReferenceString);
  2066. if (m_hkey) RegCloseKey(m_hkey);
  2067. }
  2068. LONG CInfAutoLoad::Initialize(HKEY hkey, CGfxFactory *pGfxFactory)
  2069. {
  2070. LONG lresult;
  2071. m_pGfxFactory = pGfxFactory;
  2072. m_GfxFactoryDi = lstrDuplicate(pGfxFactory->GetDeviceInterface());
  2073. if (m_GfxFactoryDi)
  2074. {
  2075. lresult = RegOpenKeyEx(hkey, NULL, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &m_hkey);
  2076. if (lresult) m_hkey = NULL;
  2077. if (!lresult) lresult = RegQuerySzValue(m_hkey, REGSTR_VAL_GFX_HARDWAREID, &m_HardwareId);
  2078. if (!lresult) lresult = RegQuerySzValue(m_hkey, REGSTR_VAL_GFX_REFERENCESTRING, &m_ReferenceString);
  2079. if (!lresult) lresult = RegQueryDwordValue(m_hkey , REGSTR_VAL_GFX_TYPE, &m_Type);
  2080. if (!lresult) lresult = RegQueryDwordValue(m_hkey , REGSTR_VAL_GFX_NEWAUTOLOAD, &m_NewAutoLoad);
  2081. if (!lresult)
  2082. {
  2083. lresult = RegQueryDwordValue(m_hkey , REGSTR_VAL_GFX_ID, &m_Id);
  2084. if (ERROR_FILE_NOT_FOUND == lresult)
  2085. {
  2086. m_Id = 0;
  2087. lresult = NO_ERROR;
  2088. }
  2089. }
  2090. } else {
  2091. lresult = ERROR_OUTOFMEMORY;
  2092. }
  2093. return (lresult);
  2094. }
  2095. LONG CInfAutoLoad::Scan(void)
  2096. {
  2097. LONG lresult;
  2098. DWORD LmId;
  2099. CLmAutoLoad *pLmAutoLoad = new CLmAutoLoad;
  2100. if (pLmAutoLoad)
  2101. {
  2102. lresult = pLmAutoLoad->Initialize(m_Id);
  2103. if (lresult)
  2104. {
  2105. delete pLmAutoLoad;
  2106. pLmAutoLoad = NULL;
  2107. }
  2108. } else {
  2109. lresult = ERROR_OUTOFMEMORY;
  2110. }
  2111. // a) new infautoload, found old lmautoload -> erase and free old lmautoload, create new lmautoload and add to list
  2112. // b) new infautolaod, no old lmautoload -> create new lmautoload and add to list
  2113. // c) new infautoload, error on old lmautoload -> abort
  2114. // d) current infautoload, found lmautoload -> add to list
  2115. // e) current infautoload, no lmautoload -> create new lmautoload and add to list
  2116. // f) current infautoload, error on lmautoload -> abort
  2117. if (m_NewAutoLoad && !lresult)
  2118. {
  2119. lresult = pLmAutoLoad->Erase();
  2120. delete pLmAutoLoad;
  2121. pLmAutoLoad = NULL;
  2122. if (!lresult) lresult = ERROR_FILE_NOT_FOUND;
  2123. }
  2124. if (ERROR_FILE_NOT_FOUND == lresult)
  2125. {
  2126. ASSERT( pLmAutoLoad == NULL );
  2127. // create new
  2128. lresult = LmNextId(&LmId);
  2129. if (!lresult)
  2130. {
  2131. pLmAutoLoad = new CLmAutoLoad;
  2132. if (pLmAutoLoad)
  2133. {
  2134. lresult = pLmAutoLoad->Create(LmId, m_GfxFactoryDi, m_HardwareId, m_ReferenceString, m_Type);
  2135. if (!lresult) lresult = pLmAutoLoad->Write();
  2136. if (!lresult)
  2137. {
  2138. lresult = RegSetDwordValue(m_hkey, REGSTR_VAL_GFX_ID, LmId);
  2139. if (!lresult)
  2140. {
  2141. m_Id = LmId;
  2142. lresult = RegSetDwordValue(m_hkey, REGSTR_VAL_GFX_NEWAUTOLOAD, 0);
  2143. if (!lresult) m_NewAutoLoad = 0;
  2144. }
  2145. if (lresult) pLmAutoLoad->Erase();
  2146. }
  2147. if (lresult)
  2148. {
  2149. delete pLmAutoLoad;
  2150. pLmAutoLoad = NULL;
  2151. }
  2152. } else {
  2153. lresult = ERROR_OUTOFMEMORY;
  2154. }
  2155. }
  2156. }
  2157. if (NO_ERROR == lresult)
  2158. {
  2159. ASSERT( pLmAutoLoad != NULL );
  2160. // add to list
  2161. if (!m_pGfxFactory->GetListLmAutoLoads().AddTail(pLmAutoLoad))
  2162. {
  2163. delete pLmAutoLoad;
  2164. pLmAutoLoad = NULL;
  2165. lresult = ERROR_OUTOFMEMORY;
  2166. }
  2167. }
  2168. return lresult;
  2169. }
  2170. LONG CInfAutoLoad::ScanReg(HKEY hkey, CGfxFactory *pGfxFactory)
  2171. {
  2172. HKEY hkeyInfAutoLoadEnum;
  2173. BOOL lresult;
  2174. lresult = RegOpenKeyEx(hkey, REGSTR_PATH_GFX_AUTOLOAD, 0, KEY_READ, &hkeyInfAutoLoadEnum);
  2175. if (NO_ERROR == lresult) {
  2176. DWORD cSubkeys;
  2177. PTSTR SubkeyName;
  2178. DWORD cchSubkeyName;
  2179. lresult = RegPrepareEnum(hkeyInfAutoLoadEnum, &cSubkeys, &SubkeyName, &cchSubkeyName);
  2180. if (NO_ERROR == lresult)
  2181. {
  2182. DWORD i;
  2183. for (i = 0; i < cSubkeys; i++) {
  2184. HKEY hkeyInfAutoLoad;
  2185. lresult = RegEnumOpenKey(hkeyInfAutoLoadEnum, i, SubkeyName, cchSubkeyName, KEY_QUERY_VALUE | KEY_SET_VALUE, &hkeyInfAutoLoad);
  2186. if (NO_ERROR == lresult)
  2187. {
  2188. CInfAutoLoad *pInfAutoLoad = new CInfAutoLoad;
  2189. if (pInfAutoLoad)
  2190. {
  2191. lresult = pInfAutoLoad->Initialize(hkeyInfAutoLoad, pGfxFactory);
  2192. if (!lresult) lresult = pInfAutoLoad->Scan();
  2193. delete pInfAutoLoad;
  2194. }
  2195. else
  2196. {
  2197. lresult = ERROR_OUTOFMEMORY;
  2198. }
  2199. RegCloseKey(hkeyInfAutoLoad);
  2200. }
  2201. }
  2202. HeapFree(hHeap, 0, SubkeyName);
  2203. }
  2204. RegCloseKey(hkeyInfAutoLoadEnum);
  2205. }
  2206. else
  2207. {
  2208. // If there is no autoload information, then that's not really an error
  2209. if (ERROR_FILE_NOT_FOUND == lresult) lresult = NO_ERROR;
  2210. }
  2211. return lresult;
  2212. }
  2213. //=============================================================================
  2214. //=== ZoneFactory ===
  2215. //=============================================================================
  2216. CZoneFactory::CZoneFactory(void)
  2217. {
  2218. m_DeviceInterface = NULL;
  2219. m_HardwareId = NULL;
  2220. m_ReferenceString = NULL;
  2221. }
  2222. CZoneFactory::~CZoneFactory(void)
  2223. {
  2224. ASSERT(m_listCaptureGfxs.IsEmpty());
  2225. ASSERT(m_listRenderGfxs.IsEmpty());
  2226. HeapFreeIfNotNull(hHeap, 0, m_DeviceInterface);
  2227. HeapFreeIfNotNull(hHeap, 0, m_HardwareId);
  2228. HeapFreeIfNotNull(hHeap, 0, m_ReferenceString);
  2229. }
  2230. LONG CZoneFactory::AddType(IN ULONG Type)
  2231. {
  2232. BOOL fRender, fCapture;
  2233. fRender = ZoneTypeHasRender(m_Type) || ZoneTypeHasRender(Type);
  2234. fCapture = ZoneTypeHasCapture(m_Type) || ZoneTypeHasCapture(Type);
  2235. ASSERT(fRender || fCapture);
  2236. if (fRender && fCapture) m_Type = ZONETYPE_RENDERCAPTURE;
  2237. else if (fRender) m_Type = ZONETYPE_RENDER;
  2238. else if (fCapture) m_Type = ZONETYPE_CAPTURE;
  2239. else m_Type = 0;
  2240. ASSERT(0 != m_Type);
  2241. return m_Type;
  2242. }
  2243. PCTSTR CZoneFactory::GetDeviceInterface(void)
  2244. {
  2245. return m_DeviceInterface;
  2246. }
  2247. PCTSTR CZoneFactory::GetTargetHardwareId(void)
  2248. {
  2249. return m_HardwareId;
  2250. }
  2251. BOOL CZoneFactory::HasHardwareId(IN PCTSTR HardwareId)
  2252. {
  2253. return 0 == lstrcmpiMulti(m_HardwareId, HardwareId);
  2254. }
  2255. BOOL CZoneFactory::HasReferenceString(IN PCTSTR ReferenceString)
  2256. {
  2257. return 0 == lstrcmpi(m_ReferenceString, ReferenceString);
  2258. }
  2259. BOOL CZoneFactory::HasCompatibleType(ULONG Type)
  2260. {
  2261. if (ZoneTypeHasRender(Type) && !ZoneTypeHasRender(m_Type)) return FALSE;
  2262. if (ZoneTypeHasCapture(Type) && !ZoneTypeHasCapture(m_Type)) return FALSE;
  2263. return TRUE;
  2264. }
  2265. LONG CZoneFactory::Initialize(IN PCTSTR DeviceInterface, IN ULONG Type)
  2266. {
  2267. HDEVINFO hdi;
  2268. SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
  2269. BOOL success;
  2270. LONG error;
  2271. hdi = NULL;
  2272. m_Type = Type;
  2273. error = m_listCaptureGfxs.Initialize();
  2274. if (!error)
  2275. {
  2276. error = m_listRenderGfxs.Initialize();
  2277. }
  2278. if (!error)
  2279. {
  2280. m_DeviceInterface = lstrDuplicate(DeviceInterface);
  2281. if (!m_DeviceInterface) error = ERROR_OUTOFMEMORY;
  2282. }
  2283. if (!error)
  2284. {
  2285. hdi = SetupDiCreateDeviceInfoList(NULL, NULL);
  2286. if (!hdi) error = GetLastError();
  2287. }
  2288. if (!error)
  2289. {
  2290. DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData);
  2291. success = SetupDiOpenDeviceInterface(hdi, m_DeviceInterface, 0, &DeviceInterfaceData);
  2292. if (!success) error = GetLastError();
  2293. }
  2294. if (!error)
  2295. {
  2296. success = SetupDiGetDeviceInterfaceHardwareId(hdi, &DeviceInterfaceData, &m_HardwareId);
  2297. if (!success) error = GetLastError();
  2298. }
  2299. if (!error)
  2300. {
  2301. PTSTR pstr = m_DeviceInterface;
  2302. pstr += 4; // go past "\\?\"
  2303. while ((TEXT('\\') != *pstr) && (TEXT('\0') != *pstr)) pstr++;
  2304. if (*pstr == TEXT('\\'))
  2305. {
  2306. pstr += 1; // go past the '\' delimiter preceding the ref string
  2307. m_ReferenceString = lstrDuplicate(pstr);
  2308. if (!m_ReferenceString) error = ERROR_OUTOFMEMORY;
  2309. }
  2310. }
  2311. if (hdi)
  2312. {
  2313. SetupDiDestroyDeviceInfoList(hdi);
  2314. }
  2315. return error;
  2316. }
  2317. LONG CZoneFactory::RemoveType(IN ULONG Type)
  2318. {
  2319. BOOL fRender, fCapture;
  2320. fRender = ZoneTypeHasRender(m_Type) && !ZoneTypeHasRender(Type);
  2321. fCapture = ZoneTypeHasCapture(m_Type) && !ZoneTypeHasCapture(Type);
  2322. if (fRender && fCapture) m_Type = ZONETYPE_RENDERCAPTURE;
  2323. else if (fRender) m_Type = ZONETYPE_RENDER;
  2324. else if (fCapture) m_Type = ZONETYPE_CAPTURE;
  2325. else m_Type = 0;
  2326. return m_Type;
  2327. }
  2328. void CZoneFactory::ListRemoveZoneFactoryDi(IN CListZoneFactories &rlistZoneFactories, IN PCTSTR DeviceInterface)
  2329. {
  2330. POSITION pos;
  2331. // Scan all ZoneFactories and delete if matched
  2332. pos = rlistZoneFactories.GetHeadPosition();
  2333. while (pos) {
  2334. POSITION posThis = pos;
  2335. CZoneFactory& rZoneFactory = *rlistZoneFactories.GetNext(pos);
  2336. if (!lstrcmpi(DeviceInterface, rZoneFactory.GetDeviceInterface())) {
  2337. rlistZoneFactories.RemoveAt(posThis);
  2338. delete &rZoneFactory;
  2339. }
  2340. }
  2341. return;
  2342. }
  2343. void CZoneFactory::ListRemoveZoneFactoryDiRender(IN CListZoneFactories &rlistZoneFactories, IN PCTSTR DeviceInterface)
  2344. {
  2345. POSITION pos;
  2346. // Scan all ZoneFactories and delete if matched
  2347. pos = rlistZoneFactories.GetHeadPosition();
  2348. while (pos) {
  2349. POSITION posThis = pos;
  2350. CZoneFactory& rZoneFactory = *rlistZoneFactories.GetNext(pos);
  2351. if (!lstrcmpi(DeviceInterface, rZoneFactory.GetDeviceInterface())) {
  2352. if (0 == rZoneFactory.RemoveType(ZONETYPE_RENDER))
  2353. {
  2354. rlistZoneFactories.RemoveAt(posThis);
  2355. delete &rZoneFactory;
  2356. }
  2357. }
  2358. }
  2359. return;
  2360. }
  2361. void CZoneFactory::ListRemoveZoneFactoryDiCapture(IN CListZoneFactories &rlistZoneFactories, IN PCTSTR DeviceInterface)
  2362. {
  2363. POSITION pos;
  2364. // Scan all ZoneFactories and delete if matched
  2365. pos = rlistZoneFactories.GetHeadPosition();
  2366. while (pos) {
  2367. POSITION posThis = pos;
  2368. CZoneFactory& rZoneFactory = *rlistZoneFactories.GetNext(pos);
  2369. if (!lstrcmpi(DeviceInterface, rZoneFactory.GetDeviceInterface())) {
  2370. if (0 == rZoneFactory.RemoveType(ZONETYPE_CAPTURE))
  2371. {
  2372. rlistZoneFactories.RemoveAt(posThis);
  2373. delete &rZoneFactory;
  2374. }
  2375. }
  2376. }
  2377. return;
  2378. }
  2379. /*-----------------------------------------------------------------------------
  2380. CZoneFactory::ListSearchOnDi
  2381. Finds a zone factory (CZoneFactory) in a specified list (CListZoneFactories)
  2382. having the specified device interface.
  2383. The caller must acquire any necessary locks on rlist before calling
  2384. this function
  2385. -----------------------------------------------------------------------------*/
  2386. CZoneFactory* CZoneFactory::ListSearchOnDi(CListZoneFactories& rlist, PCTSTR Di)
  2387. {
  2388. POSITION pos = rlist.GetHeadPosition();
  2389. while (pos)
  2390. {
  2391. CZoneFactory& rZoneFactory = *rlist.GetNext(pos);
  2392. if (!lstrcmpi(rZoneFactory.GetDeviceInterface(), Di)) return &rZoneFactory;
  2393. }
  2394. return NULL;
  2395. }
  2396. //=============================================================================
  2397. //=== GfxFactory ===
  2398. //=============================================================================
  2399. CGfxFactory::CGfxFactory(void)
  2400. {
  2401. m_plistLmAutoLoads = NULL;;
  2402. m_DeviceInterface = NULL;
  2403. }
  2404. CGfxFactory::~CGfxFactory(void)
  2405. {
  2406. if (m_plistLmAutoLoads) CLmAutoLoad::DestroyList(m_plistLmAutoLoads);
  2407. HeapFreeIfNotNull(hHeap, 0, m_DeviceInterface);
  2408. }
  2409. REFCLSID CGfxFactory::GetClsid(void)
  2410. {
  2411. return m_Clsid;
  2412. }
  2413. PCTSTR CGfxFactory::GetDeviceInterface(void)
  2414. {
  2415. return m_DeviceInterface;
  2416. }
  2417. CListLmAutoLoads& CGfxFactory::GetListLmAutoLoads(void)
  2418. {
  2419. return *m_plistLmAutoLoads;
  2420. }
  2421. LONG CGfxFactory::Initialize(HKEY hkey, PCTSTR DeviceInterface)
  2422. {
  2423. LONG lresult;
  2424. m_plistLmAutoLoads = new CListLmAutoLoads;
  2425. lresult = m_plistLmAutoLoads ? NO_ERROR : ERROR_OUTOFMEMORY;
  2426. if (!lresult) {
  2427. lresult = m_plistLmAutoLoads->Initialize();
  2428. if (!lresult) {
  2429. m_DeviceInterface = lstrDuplicate(DeviceInterface);
  2430. lresult = m_DeviceInterface ? NO_ERROR : ERROR_OUTOFMEMORY;
  2431. if (!lresult)
  2432. {
  2433. HKEY hkeyUi;
  2434. m_Clsid = GUID_NULL;
  2435. // Read UI CLSID from registry
  2436. lresult = RegOpenKeyEx(hkey, REGSTR_PATH_GFXDI_USERINTERFACECLSID, 0, KEY_QUERY_VALUE, &hkeyUi);
  2437. if (NO_ERROR == lresult)
  2438. {
  2439. TCHAR strClsid[] = TEXT("{00000000-0000-0000-0000-000000000000}");
  2440. DWORD dwType;
  2441. DWORD cbstrClsid;
  2442. cbstrClsid = (lstrlen(strClsid) + 1) * sizeof(strClsid[0]);
  2443. dwType = REG_SZ;
  2444. lresult = RegQueryValueEx(hkeyUi, NULL, NULL, &dwType, (PBYTE)strClsid, &cbstrClsid);
  2445. if (NO_ERROR == lresult)
  2446. {
  2447. HRESULT hr;
  2448. CLSID clsid;
  2449. hr = CLSIDFromString(strClsid, &clsid);
  2450. if (SUCCEEDED(hr))
  2451. {
  2452. m_Clsid = clsid;
  2453. }
  2454. }
  2455. RegCloseKey(hkeyUi);
  2456. }
  2457. // Ignore errors reading CLSID
  2458. lresult = NO_ERROR;
  2459. // Note the following must have HKLM write priviledges
  2460. lresult = CInfAutoLoad::ScanReg(hkey, this);
  2461. }
  2462. }
  2463. // Assuming above logic leaves nothing in the list on error
  2464. if (lresult) delete m_plistLmAutoLoads;
  2465. }
  2466. return lresult;
  2467. }
  2468. BOOL CGfxFactory::IsCompatibleZoneFactory(IN ULONG Type, IN CZoneFactory& rZoneFactory)
  2469. {
  2470. // Fix 394279: Limit to one GFX per device
  2471. if ((Type == GFXTYPE_RENDER) && (rZoneFactory.m_listRenderGfxs.GetCount() > 0))
  2472. {
  2473. return FALSE;
  2474. }
  2475. else if ((Type == GFXTYPE_CAPTURE) && (rZoneFactory.m_listCaptureGfxs.GetCount() > 0))
  2476. {
  2477. return FALSE;
  2478. }
  2479. else if ((Type == GFXTYPE_RENDERCAPTURE) &&
  2480. ((rZoneFactory.m_listRenderGfxs.GetCount() > 0) || (rZoneFactory.m_listCaptureGfxs.GetCount() > 0)))
  2481. {
  2482. return FALSE;
  2483. }
  2484. POSITION pos;
  2485. // dprintf(TEXT("CGfxFactory::IsCompatibleZoneFactory : checking Type compatibility: Requested Type=%d\n"), Type);
  2486. if (!rZoneFactory.HasCompatibleType(Type)) return FALSE;
  2487. // dprintf(TEXT("CGfxFactory::IsCompatibleZoneFactory : Type is compatible\n"));
  2488. if (0 == m_plistLmAutoLoads->GetCount()) return FALSE; //Fix 394279: Only allow autoload GFX
  2489. pos = m_plistLmAutoLoads->GetHeadPosition();
  2490. while (pos) {
  2491. CLmAutoLoad& rLmAutoLoad = *m_plistLmAutoLoads->GetNext(pos);
  2492. if (rLmAutoLoad.IsCompatibleZoneFactory(rZoneFactory)) return TRUE;
  2493. }
  2494. return FALSE;
  2495. }
  2496. void CGfxFactory::ListRemoveGfxFactoryDi(IN CListGfxFactories &rlistGfxFactories, IN PCTSTR DeviceInterface)
  2497. {
  2498. POSITION pos;
  2499. // Scan all GfxFactories and delete if matched
  2500. pos = rlistGfxFactories.GetHeadPosition();
  2501. while (pos) {
  2502. POSITION posThis = pos;
  2503. CGfxFactory& rGfxFactory = *rlistGfxFactories.GetNext(pos);
  2504. if (!lstrcmpi(DeviceInterface, rGfxFactory.GetDeviceInterface())) {
  2505. rlistGfxFactories.RemoveAt(posThis);
  2506. delete &rGfxFactory;
  2507. }
  2508. }
  2509. return;
  2510. }
  2511. /*-----------------------------------------------------------------------------
  2512. CGfxFactory::ListSearchOnDi
  2513. The caller must acquire any necessary locks on rlist
  2514. -----------------------------------------------------------------------------*/
  2515. CGfxFactory* CGfxFactory::ListSearchOnDi(IN CListGfxFactories& rlist, IN PCTSTR Di)
  2516. {
  2517. POSITION pos = rlist.GetHeadPosition();
  2518. while (pos) {
  2519. CGfxFactory& rGfxFactory = *rlist.GetNext(pos);
  2520. if (!lstrcmpi(rGfxFactory.GetDeviceInterface(), Di)) return &rGfxFactory;
  2521. }
  2522. return NULL;
  2523. }
  2524. //=============================================================================
  2525. //=== CUser ===
  2526. //=============================================================================
  2527. LONG CreateUser(IN DWORD SessionId, OUT CUser **ppUser)
  2528. {
  2529. CUser *pUser;
  2530. LONG error;
  2531. pUser = new CUser;
  2532. if (pUser)
  2533. {
  2534. error = pUser->Initialize(SessionId);
  2535. if (error) delete pUser;
  2536. }
  2537. else
  2538. {
  2539. error = ERROR_OUTOFMEMORY;
  2540. }
  2541. if (!error) *ppUser = pUser;
  2542. return error;
  2543. }
  2544. CUser::CUser(void)
  2545. {
  2546. m_hUserToken = NULL;
  2547. m_SessionId = LOGONID_NONE;
  2548. m_pSid = NULL;
  2549. m_fcsRegistry = FALSE;
  2550. m_refRegistry = 0;
  2551. m_hRegistry = NULL;
  2552. }
  2553. CUser::~CUser(void)
  2554. {
  2555. if (m_hRegistry) RegCloseKey(m_hRegistry);
  2556. HeapFreeIfNotNull(hHeap, 0, m_pSid);
  2557. if (m_hUserToken) CloseHandle(m_hUserToken);
  2558. if (m_fcsRegistry) DeleteCriticalSection(&m_csRegistry);
  2559. }
  2560. BOOL CUser::operator==(const CUser& other)
  2561. {
  2562. if (m_SessionId != other.m_SessionId) return FALSE;
  2563. if (!EqualSid(m_pSid, other.m_pSid)) return FALSE;
  2564. return TRUE;
  2565. }
  2566. void CUser::CloseUserRegistry(void)
  2567. {
  2568. ASSERT(m_pSid);
  2569. ASSERT(m_hRegistry);
  2570. ASSERT(m_fcsRegistry);
  2571. EnterCriticalSection(&m_csRegistry);
  2572. ASSERT(m_refRegistry > 0);
  2573. if (0 == --m_refRegistry)
  2574. {
  2575. LONG result;
  2576. result = RegCloseKey(m_hRegistry);
  2577. ASSERT(NO_ERROR == result);
  2578. m_hRegistry = NULL;
  2579. }
  2580. LeaveCriticalSection(&m_csRegistry);
  2581. return;
  2582. }
  2583. PSID CUser::GetSid(void)
  2584. {
  2585. ASSERT(m_pSid);
  2586. return m_pSid;
  2587. }
  2588. LONG CUser::Initialize(DWORD SessionId)
  2589. {
  2590. LONG error;
  2591. m_SessionId = SessionId;
  2592. // Initialize registry critical section
  2593. __try {
  2594. InitializeCriticalSection(&m_csRegistry);
  2595. error = NO_ERROR;
  2596. m_fcsRegistry = TRUE;
  2597. } __except(EXCEPTION_EXECUTE_HANDLER) {
  2598. error = ERROR_OUTOFMEMORY;
  2599. m_fcsRegistry = FALSE;
  2600. }
  2601. // Open a user token for the session's user
  2602. if (!error)
  2603. {
  2604. if (OpenSessionToken(m_SessionId, &m_hUserToken))
  2605. {
  2606. if (!IsUserProfileLoaded(m_hUserToken))
  2607. {
  2608. error = GetLastError();
  2609. CloseHandle(m_hUserToken);
  2610. m_hUserToken = NULL;
  2611. }
  2612. }
  2613. else
  2614. {
  2615. error = GetLastError();
  2616. dprintf(TEXT("CUser::Initialize : error: OpenSessionToken returned error=%d\n"), error);
  2617. }
  2618. }
  2619. // Create a SID for this user
  2620. if (!error)
  2621. {
  2622. if (!CreateTokenSid(m_hUserToken, &m_pSid))
  2623. {
  2624. error = GetLastError();
  2625. dprintf(TEXT("CUser::Initialize : error: CreateTokenSid failed, LastError=%d\n"), error);
  2626. }
  2627. }
  2628. return error;
  2629. }
  2630. LONG CUser::RegOpen(IN REGSAM samDesired, OUT PHKEY phkResult)
  2631. {
  2632. LONG error;
  2633. if (OpenUserRegistry())
  2634. {
  2635. ASSERT(m_hRegistry);
  2636. error = RegOpenKeyEx(m_hRegistry, NULL, 0, samDesired, phkResult);
  2637. CloseUserRegistry();
  2638. }
  2639. else
  2640. {
  2641. // Can't think of a better error code
  2642. error = ERROR_INVALID_FUNCTION;
  2643. }
  2644. return error;
  2645. }
  2646. BOOL CUser::OpenUserRegistry(void)
  2647. {
  2648. BOOL success = FALSE;
  2649. ASSERT(m_fcsRegistry);
  2650. ASSERT(m_hUserToken);
  2651. EnterCriticalSection(&m_csRegistry);
  2652. ASSERT(m_refRegistry >= 0);
  2653. if (0 == m_refRegistry++)
  2654. {
  2655. ASSERT(NULL == m_hRegistry);
  2656. if (ImpersonateLoggedOnUser(m_hUserToken))
  2657. {
  2658. NTSTATUS status;
  2659. status = RtlOpenCurrentUser(MAXIMUM_ALLOWED, (PHANDLE)&m_hRegistry);
  2660. if (NT_SUCCESS(status))
  2661. {
  2662. success = TRUE;
  2663. }
  2664. else
  2665. {
  2666. dprintf(TEXT("CUser::OpenUserRegistry : error: RtlOpenCurrentUser returned status=%08Xh\n"), status);
  2667. m_hRegistry = NULL;
  2668. }
  2669. RevertToSelf();
  2670. }
  2671. else
  2672. {
  2673. LONG error = GetLastError();
  2674. dprintf(TEXT("CUser::OpenUserRegistry : error: ImpersonateLoggedOnUser failed, LastError=%d\n"), error);
  2675. }
  2676. if (!success) m_refRegistry--;
  2677. }
  2678. else
  2679. {
  2680. // dprintf(TEXT("CUser::OpenUserRegistry : note: reusing registry handle\n"));
  2681. success = TRUE;
  2682. }
  2683. LeaveCriticalSection(&m_csRegistry);
  2684. return success;
  2685. }
  2686. //=============================================================================
  2687. //=== ===
  2688. //=============================================================================
  2689. void
  2690. ZoneFactoryInterfaceCheck(
  2691. IN CUser *pUser,
  2692. IN HDEVINFO DevInfo,
  2693. IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
  2694. IN ULONG Type
  2695. )
  2696. {
  2697. GUID BusTypeGuid;
  2698. BOOL fresult;
  2699. ASSERT(pUser);
  2700. //
  2701. // For now, we support GFXs only on USB bus because we want to limit
  2702. // GFXs to only non-accelerated audio devices
  2703. //
  2704. fresult = SetupDiGetDeviceInterfaceBusId(DevInfo, DeviceInterfaceData, &BusTypeGuid);
  2705. if (fresult && (GUID_BUS_TYPE_USB == BusTypeGuid))
  2706. {
  2707. PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetail;
  2708. fresult = SetupDiCreateDeviceInterfaceDetail(DevInfo, DeviceInterfaceData, &DeviceInterfaceDetail, NULL);
  2709. if (fresult)
  2710. {
  2711. LockGlobalLists();
  2712. CZoneFactory *pZoneFactory;
  2713. // We scan AutoLoad and UserLoads only if we are enhancing the type
  2714. // of an existing zone or we are adding a new zone
  2715. pZoneFactory = CZoneFactory::ListSearchOnDi(*gplistZoneFactories, DeviceInterfaceDetail->DevicePath);
  2716. if (pZoneFactory)
  2717. {
  2718. if (pZoneFactory->HasCompatibleType(Type))
  2719. {
  2720. pZoneFactory = NULL;
  2721. }
  2722. else
  2723. {
  2724. pZoneFactory->AddType(Type);
  2725. }
  2726. }
  2727. else
  2728. {
  2729. pZoneFactory = new CZoneFactory;
  2730. if (pZoneFactory)
  2731. {
  2732. if (pZoneFactory->Initialize(DeviceInterfaceDetail->DevicePath, Type) || !gplistZoneFactories->AddTail(pZoneFactory))
  2733. {
  2734. delete pZoneFactory;
  2735. pZoneFactory = NULL;
  2736. }
  2737. }
  2738. }
  2739. if (pZoneFactory)
  2740. {
  2741. CLmAutoLoad::ScanRegOnZoneFactory(pUser, *pZoneFactory, *gplistGfxFactories, *gplistCuUserLoads);
  2742. CCuUserLoad::ScanList(*gplistCuUserLoads, *gplistZoneFactories, *gplistGfxFactories);
  2743. }
  2744. UnlockGlobalLists();
  2745. HeapFree(hHeap, 0, DeviceInterfaceDetail);
  2746. } else {
  2747. dprintf(TEXT("ZoneFactoryInterfaceCheck: SetupDiCreateDeviceInterfaceDetail failed\n"));
  2748. }
  2749. }
  2750. else
  2751. {
  2752. if (fresult)
  2753. {
  2754. // dprintf(TEXT("ZoneFactoryInterfaceCheck found interface on non USB bus [%s]\n"), DeviceInterface);
  2755. }
  2756. else
  2757. {
  2758. // DWORD dw = GetLastError();
  2759. // dprintf(TEXT("ZoneFactoryInterfaceCheck: error calling SetupDiGetDeviceInterfaceBusId\n")
  2760. // TEXT(" DeviceInterface=%s\n")
  2761. // TEXT(" LastError=%d\n"),
  2762. // DeviceInterface, dw);
  2763. }
  2764. }
  2765. return;
  2766. }
  2767. void
  2768. GfxFactoryInterfaceCheck(
  2769. IN CUser *pUser,
  2770. IN HDEVINFO DevInfo,
  2771. IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
  2772. )
  2773. {
  2774. HKEY hkeyDi;
  2775. ASSERT(pUser);
  2776. hkeyDi = SetupDiOpenDeviceInterfaceRegKey(DevInfo, DeviceInterfaceData, 0, KEY_ENUMERATE_SUB_KEYS);
  2777. if (hkeyDi)
  2778. {
  2779. HKEY hkeyDiGfx;
  2780. LONG lresult;
  2781. // If the KSCATEGORY_AUDIO device interface key has a GFX
  2782. // subkey then this is a GFX factory
  2783. lresult = RegOpenKeyEx(hkeyDi, REGSTR_PATH_DI_GFX, 0, KEY_QUERY_VALUE, &hkeyDiGfx);
  2784. if (NO_ERROR == lresult)
  2785. {
  2786. PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetail;
  2787. BOOL fresult;
  2788. fresult = SetupDiCreateDeviceInterfaceDetail(DevInfo, DeviceInterfaceData, &DeviceInterfaceDetail, NULL);
  2789. if (fresult)
  2790. {
  2791. LockGlobalLists();
  2792. // Ensure it's not already in the list
  2793. if (!CGfxFactory::ListSearchOnDi(*gplistGfxFactories, DeviceInterfaceDetail->DevicePath))
  2794. {
  2795. CGfxFactory *pGfxFactory = new CGfxFactory;
  2796. if (pGfxFactory)
  2797. {
  2798. if (!pGfxFactory->Initialize(hkeyDiGfx, DeviceInterfaceDetail->DevicePath) && gplistGfxFactories->AddTail(pGfxFactory))
  2799. {
  2800. CLmAutoLoad::ScanRegOnGfxFactory(pUser, *pGfxFactory, *gplistZoneFactories, *gplistCuUserLoads);
  2801. CCuUserLoad::ScanList(*gplistCuUserLoads, *gplistZoneFactories, *gplistGfxFactories);
  2802. }
  2803. else
  2804. {
  2805. delete pGfxFactory;
  2806. }
  2807. }
  2808. }
  2809. UnlockGlobalLists();
  2810. HeapFree(hHeap, 0, DeviceInterfaceDetail);
  2811. }
  2812. RegCloseKey(hkeyDiGfx);
  2813. }
  2814. RegCloseKey(hkeyDi);
  2815. }
  2816. return;
  2817. }
  2818. /*-----------------------------------------------------------------------------
  2819. GFX_InterfaceArrival
  2820. -----------------------------------------------------------------------------*/
  2821. void GFX_InterfaceArrival(PCTSTR ArrivalDeviceInterface)
  2822. {
  2823. CUser *pUser;
  2824. HDEVINFO hdi;
  2825. SP_DEVICE_INTERFACE_DATA ArrivalDeviceInterfaceData;
  2826. if (!RtlInterlockedTestAcquireResourceShared(&GfxResource, &gfGfxInitialized)) return;
  2827. pUser = gpConsoleUser;
  2828. ASSERT(pUser);
  2829. hdi = SetupDiCreateDeviceInfoList(NULL, NULL);
  2830. if (INVALID_HANDLE_VALUE != hdi)
  2831. {
  2832. BOOL fresult;
  2833. ArrivalDeviceInterfaceData.cbSize = sizeof(ArrivalDeviceInterfaceData);
  2834. fresult = SetupDiOpenDeviceInterface(hdi, ArrivalDeviceInterface, 0, &ArrivalDeviceInterfaceData);
  2835. if (fresult)
  2836. {
  2837. SP_DEVICE_INTERFACE_DATA AudioDeviceInterfaceData;
  2838. SP_DEVICE_INTERFACE_DATA AliasDeviceInterfaceData;
  2839. BOOL fRender;
  2840. BOOL fCapture;
  2841. BOOL fDataTransform;
  2842. BOOL fAudio;
  2843. // dprintf(TEXT("GFX_InterfaceArrival: checking interface aliases on %s\n"), ArrivalDeviceInterface);
  2844. AudioDeviceInterfaceData.cbSize = sizeof(AudioDeviceInterfaceData);
  2845. fAudio = SetupDiGetDeviceInterfaceAlias(hdi, &ArrivalDeviceInterfaceData, &KSCATEGORY_AUDIO, &AudioDeviceInterfaceData);
  2846. fAudio = fAudio && (AudioDeviceInterfaceData.Flags & SPINT_ACTIVE);
  2847. AliasDeviceInterfaceData.cbSize = sizeof(AliasDeviceInterfaceData);
  2848. fRender = SetupDiGetDeviceInterfaceAlias(hdi, &ArrivalDeviceInterfaceData, &KSCATEGORY_RENDER, &AliasDeviceInterfaceData);
  2849. fRender = fRender && (AliasDeviceInterfaceData.Flags & SPINT_ACTIVE);
  2850. AliasDeviceInterfaceData.cbSize = sizeof(AliasDeviceInterfaceData);
  2851. fCapture = SetupDiGetDeviceInterfaceAlias(hdi, &ArrivalDeviceInterfaceData, &KSCATEGORY_CAPTURE, &AliasDeviceInterfaceData);
  2852. fCapture = fCapture && (AliasDeviceInterfaceData.Flags & SPINT_ACTIVE);
  2853. AliasDeviceInterfaceData.cbSize = sizeof(AliasDeviceInterfaceData);
  2854. fDataTransform = SetupDiGetDeviceInterfaceAlias(hdi, &ArrivalDeviceInterfaceData, &KSCATEGORY_DATATRANSFORM, &AliasDeviceInterfaceData);
  2855. fDataTransform = fDataTransform && (AliasDeviceInterfaceData.Flags & SPINT_ACTIVE);
  2856. /*
  2857. if (fAudio) dprintf(TEXT("GFX_InterfaceArrival: interface has Audio alias\n"));
  2858. if (fRender) dprintf(TEXT("GFX_InterfaceArrival: interface has Render alias\n"));
  2859. if (fCapture) dprintf(TEXT("GFX_InterfaceArrival: interface has Capture alias\n"));
  2860. if (fDataTransform) dprintf(TEXT("GFX_InterfaceArrival: interface has DataTransform alias\n"));
  2861. */
  2862. if (fAudio && fDataTransform) GfxFactoryInterfaceCheck(pUser, hdi, &AudioDeviceInterfaceData);
  2863. if (fAudio && fRender && fCapture) ZoneFactoryInterfaceCheck(pUser, hdi, &AudioDeviceInterfaceData, ZONETYPE_RENDERCAPTURE);
  2864. else if (fAudio && fRender) ZoneFactoryInterfaceCheck(pUser, hdi, &AudioDeviceInterfaceData, ZONETYPE_RENDER);
  2865. else if (fAudio && fCapture) ZoneFactoryInterfaceCheck(pUser, hdi, &AudioDeviceInterfaceData, ZONETYPE_CAPTURE);
  2866. }
  2867. SetupDiDestroyDeviceInfoList(hdi);
  2868. }
  2869. RtlReleaseResource(&GfxResource);
  2870. return;
  2871. }
  2872. void GFX_AudioInterfaceArrival(PCTSTR ArrivalDeviceInterface)
  2873. {
  2874. // dprintf(TEXT("GFX_AudioInterfaceArrival: %s\n"), ArrivalDeviceInterface);
  2875. GFX_InterfaceArrival(ArrivalDeviceInterface);
  2876. return;
  2877. }
  2878. void GFX_DataTransformInterfaceArrival(PCTSTR ArrivalDeviceInterface)
  2879. {
  2880. // dprintf(TEXT("GFX_DataTransformInterfaceArrival: %s\n"), ArrivalDeviceInterface);
  2881. GFX_InterfaceArrival(ArrivalDeviceInterface);
  2882. return;
  2883. }
  2884. void GFX_RenderInterfaceArrival(PCTSTR ArrivalDeviceInterface)
  2885. {
  2886. // dprintf(TEXT("GFX_RenderInterfaceArrival: %s\n"), ArrivalDeviceInterface);
  2887. GFX_InterfaceArrival(ArrivalDeviceInterface);
  2888. return;
  2889. }
  2890. void GFX_CaptureInterfaceArrival(PCTSTR ArrivalDeviceInterface)
  2891. {
  2892. // dprintf(TEXT("GFX_CaptureInterfaceArrival: %s\n"), ArrivalDeviceInterface);
  2893. GFX_InterfaceArrival(ArrivalDeviceInterface);
  2894. return;
  2895. }
  2896. /*-----------------------------------------------------------------------------
  2897. GFX_AudioInterfaceRemove
  2898. -----------------------------------------------------------------------------*/
  2899. void GFX_AudioInterfaceRemove(PCTSTR DeviceInterface)
  2900. {
  2901. POSITION pos;
  2902. // dprintf(TEXT("GFX_AudioInterfaceRemove: %s\n"), DeviceInterface);
  2903. if (!RtlInterlockedTestAcquireResourceShared(&GfxResource, &gfGfxInitialized)) return;
  2904. LockGlobalLists();
  2905. CCuUserLoad::ListRemoveZoneFactoryDi(*gplistCuUserLoads, DeviceInterface);
  2906. CCuUserLoad::ListRemoveGfxFactoryDi(*gplistCuUserLoads, DeviceInterface);
  2907. CZoneFactory::ListRemoveZoneFactoryDi(*gplistZoneFactories, DeviceInterface);
  2908. CGfxFactory::ListRemoveGfxFactoryDi(*gplistGfxFactories, DeviceInterface);
  2909. UnlockGlobalLists();
  2910. RtlReleaseResource(&GfxResource);
  2911. return;
  2912. }
  2913. void GFX_DataTransformInterfaceRemove(PCTSTR DataTransformDeviceInterface)
  2914. {
  2915. PTSTR AudioDeviceInterface;
  2916. BOOL fresult;
  2917. // dprintf(TEXT("GFX_DataTransformInterfaceRemove: %s\n"), DataTransformDeviceInterface);
  2918. if (!RtlInterlockedTestAcquireResourceShared(&GfxResource, &gfGfxInitialized)) return;
  2919. fresult = SetupDiCreateAliasDeviceInterfaceFromDeviceInterface(DataTransformDeviceInterface, &KSCATEGORY_AUDIO, &AudioDeviceInterface);
  2920. if (fresult)
  2921. {
  2922. LockGlobalLists();
  2923. CCuUserLoad::ListRemoveGfxFactoryDi(*gplistCuUserLoads, AudioDeviceInterface);
  2924. CGfxFactory::ListRemoveGfxFactoryDi(*gplistGfxFactories, AudioDeviceInterface);
  2925. UnlockGlobalLists();
  2926. HeapFree(hHeap, 0, AudioDeviceInterface);
  2927. }
  2928. RtlReleaseResource(&GfxResource);
  2929. return;
  2930. }
  2931. void GFX_RenderInterfaceRemove(PCTSTR RemoveDeviceInterface)
  2932. {
  2933. PTSTR AudioDeviceInterface;
  2934. BOOL fresult;
  2935. // dprintf(TEXT("GFX_RenderInterfaceRemove: %s\n"), RemoveDeviceInterface);
  2936. if (!RtlInterlockedTestAcquireResourceShared(&GfxResource, &gfGfxInitialized)) return;
  2937. fresult = SetupDiCreateAliasDeviceInterfaceFromDeviceInterface(RemoveDeviceInterface, &KSCATEGORY_AUDIO, &AudioDeviceInterface);
  2938. if (fresult)
  2939. {
  2940. LockGlobalLists();
  2941. CCuUserLoad::ListRemoveZoneFactoryDiRender(*gplistCuUserLoads, AudioDeviceInterface);
  2942. CZoneFactory::ListRemoveZoneFactoryDiRender(*gplistZoneFactories, AudioDeviceInterface);
  2943. UnlockGlobalLists();
  2944. HeapFree(hHeap, 0, AudioDeviceInterface);
  2945. }
  2946. RtlReleaseResource(&GfxResource);
  2947. return;
  2948. }
  2949. void GFX_CaptureInterfaceRemove(PCTSTR RemoveDeviceInterface)
  2950. {
  2951. PTSTR AudioDeviceInterface;
  2952. BOOL fresult;
  2953. // dprintf(TEXT("GFX_CaptureInterfaceRemove: %s\n"), RemoveDeviceInterface);
  2954. if (!RtlInterlockedTestAcquireResourceShared(&GfxResource, &gfGfxInitialized)) return;
  2955. fresult = SetupDiCreateAliasDeviceInterfaceFromDeviceInterface(RemoveDeviceInterface, &KSCATEGORY_AUDIO, &AudioDeviceInterface);
  2956. if (fresult)
  2957. {
  2958. LockGlobalLists();
  2959. CCuUserLoad::ListRemoveZoneFactoryDiCapture(*gplistCuUserLoads, AudioDeviceInterface);
  2960. CZoneFactory::ListRemoveZoneFactoryDiCapture(*gplistZoneFactories, AudioDeviceInterface);
  2961. UnlockGlobalLists();
  2962. HeapFree(hHeap, 0, AudioDeviceInterface);
  2963. }
  2964. RtlReleaseResource(&GfxResource);
  2965. return;
  2966. }
  2967. /*-----------------------------------------------------------------------------
  2968. GFX_SysaudioInterfaceArrival
  2969. -----------------------------------------------------------------------------*/
  2970. void GFX_SysaudioInterfaceArrival(PCTSTR DeviceInterface)
  2971. {
  2972. if (!RtlInterlockedTestAcquireResourceShared(&GfxResource, &gfGfxInitialized)) return;
  2973. LockSysaudio();
  2974. if (INVALID_HANDLE_VALUE == ghSysaudio)
  2975. {
  2976. gpstrSysaudioDeviceInterface = lstrDuplicate(DeviceInterface);
  2977. if (gpstrSysaudioDeviceInterface)
  2978. {
  2979. ghSysaudio = CreateFile(gpstrSysaudioDeviceInterface,
  2980. GENERIC_READ | GENERIC_WRITE,
  2981. 0,
  2982. NULL,
  2983. OPEN_EXISTING,
  2984. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  2985. NULL);
  2986. if (INVALID_HANDLE_VALUE == ghSysaudio)
  2987. {
  2988. HeapFree(hHeap, 0, gpstrSysaudioDeviceInterface);
  2989. gpstrSysaudioDeviceInterface = NULL;
  2990. }
  2991. }
  2992. } else {
  2993. // Sysaudio already open
  2994. ASSERT(gpstrSysaudioDeviceInterface);
  2995. if (lstrcmpi(DeviceInterface, gpstrSysaudioDeviceInterface))
  2996. {
  2997. // We have two Sysaudio devices in the system!!! What to do???
  2998. dprintf(TEXT("GFX_SysaudioInterfaceArrival: warning: received two arrivals!\n"));
  2999. ASSERT(FALSE);
  3000. }
  3001. }
  3002. UnlockSysaudio();
  3003. //
  3004. // Even though we read the value of ghSysaudio here, we don't lock
  3005. // sysaudio. If some other thread is changing it from invalid to valid
  3006. // then that thread will scan user-loads. If some other thread changes
  3007. // it from valid to invalid, it is okay that we do a wasteful scan of
  3008. // user-loads.
  3009. //
  3010. if (INVALID_HANDLE_VALUE != ghSysaudio)
  3011. {
  3012. LockGlobalLists();
  3013. CCuUserLoad::ScanList(*gplistCuUserLoads, *gplistZoneFactories, *gplistGfxFactories);
  3014. UnlockGlobalLists();
  3015. }
  3016. RtlReleaseResource(&GfxResource);
  3017. return;
  3018. }
  3019. /*-----------------------------------------------------------------------------
  3020. GFX_SysaudioInterfaceRemove
  3021. If this matches our sysaudio interface then scan all CuUserLoads and remove
  3022. them from zones. Then close our handle to Sysaudio.
  3023. -----------------------------------------------------------------------------*/
  3024. void GFX_SysaudioInterfaceRemove(PCTSTR DeviceInterface)
  3025. {
  3026. POSITION pos;
  3027. if (!RtlInterlockedTestAcquireResourceShared(&GfxResource, &gfGfxInitialized)) return;
  3028. LockGlobalLists();
  3029. LockSysaudio();
  3030. //
  3031. // Scan all CuUserLoads and remove them from zone
  3032. //
  3033. pos = gplistCuUserLoads->GetHeadPosition();
  3034. while (pos) {
  3035. CCuUserLoad& rCuUserLoad = *gplistCuUserLoads->GetNext(pos);
  3036. rCuUserLoad.RemoveFromZoneGraph();
  3037. }
  3038. //
  3039. // Close sysaudio
  3040. //
  3041. if (INVALID_HANDLE_VALUE != ghSysaudio) {
  3042. CloseHandle(ghSysaudio);
  3043. HeapFree(hHeap, 0, gpstrSysaudioDeviceInterface);
  3044. ghSysaudio = INVALID_HANDLE_VALUE;
  3045. gpstrSysaudioDeviceInterface = NULL;
  3046. }
  3047. UnlockSysaudio();
  3048. UnlockGlobalLists();
  3049. RtlReleaseResource(&GfxResource);
  3050. return;
  3051. }
  3052. //=============================================================================
  3053. //=== RPC server interface ===
  3054. //=============================================================================
  3055. LONG s_gfxRemoveGfx(ULONG CuUserLoadId)
  3056. {
  3057. LONG lresult;
  3058. dprintf(TEXT("gfxRemoveGfx: CuUserLoadId=%08Xh\n"), CuUserLoadId);
  3059. if (!RtlInterlockedTestAcquireResourceShared(&GfxResource, &gfGfxInitialized)) return ERROR_INVALID_FUNCTION;
  3060. lresult = RpcClientHasUserSid(gpConsoleUser->GetSid()) ? NO_ERROR : ERROR_INVALID_FUNCTION;
  3061. if (!lresult)
  3062. {
  3063. POSITION pos;
  3064. lresult = ERROR_BAD_DEVICE; // Cannot find the device specified
  3065. LockGlobalLists();
  3066. pos = gplistCuUserLoads->GetHeadPosition();
  3067. while (pos) {
  3068. CCuUserLoad *pCuUserLoad = gplistCuUserLoads->GetAt(pos);
  3069. if (pCuUserLoad->GetId() == CuUserLoadId) {
  3070. lresult = pCuUserLoad->Erase();
  3071. if (!lresult) {
  3072. gplistCuUserLoads->RemoveAt(pos);
  3073. delete pCuUserLoad;
  3074. lresult = NO_ERROR;
  3075. }
  3076. break;
  3077. }
  3078. gplistCuUserLoads->GetNext(pos);
  3079. }
  3080. UnlockGlobalLists();
  3081. }
  3082. RtlReleaseResource(&GfxResource);
  3083. return lresult;
  3084. }
  3085. LONG s_gfxModifyGfx(ULONG CuUserLoadId, DWORD Order)
  3086. {
  3087. LONG lresult;
  3088. // Validate the Order parameter
  3089. if (GFX_MAXORDER < Order)
  3090. {
  3091. dprintf(TEXT("gfxModifyGfx: error: Order=%d is invalid\n"), Order);
  3092. return ERROR_INVALID_PARAMETER;
  3093. }
  3094. if (!RtlInterlockedTestAcquireResourceShared(&GfxResource, &gfGfxInitialized)) return ERROR_INVALID_FUNCTION;
  3095. lresult = RpcClientHasUserSid(gpConsoleUser->GetSid()) ? NO_ERROR : ERROR_INVALID_FUNCTION;
  3096. if (!lresult)
  3097. {
  3098. POSITION pos;
  3099. lresult = ERROR_BAD_DEVICE; // Cannot find the device specified
  3100. LockGlobalLists();
  3101. pos = gplistCuUserLoads->GetHeadPosition();
  3102. while (pos) {
  3103. CCuUserLoad *pCuUserLoad = gplistCuUserLoads->GetAt(pos);
  3104. if (pCuUserLoad->GetId() == CuUserLoadId) {
  3105. dprintf(TEXT("gfxModify : note: Moving GFX ID %08X from %d to %d\n"), CuUserLoadId, pCuUserLoad->GetOrder(), Order);
  3106. lresult = pCuUserLoad->ModifyOrder(Order);
  3107. break;
  3108. }
  3109. gplistCuUserLoads->GetNext(pos);
  3110. }
  3111. UnlockGlobalLists();
  3112. }
  3113. RtlReleaseResource(&GfxResource);
  3114. return lresult;
  3115. }
  3116. RPC_STATUS s_gfxAddGfx(IN PWSTR ZoneFactoryDi, IN PWSTR GfxFactoryDi, IN ULONG Type, IN ULONG Order, OUT PDWORD pNewId)
  3117. {
  3118. LONG lresult;
  3119. dprintf(TEXT("gfxAddGfx: ZoneFactoryDi = %s\n"), ZoneFactoryDi);
  3120. dprintf(TEXT("gfxAddGfx: GfxFactoryDi = %s\n"), GfxFactoryDi);
  3121. dprintf(TEXT("gfxAddGfx: Type = %s\n"), GFXTYPE_RENDER == Type ? TEXT("Render") : TEXT("Capture"));
  3122. dprintf(TEXT("gfxAddGfx: Order = %d\n"), Order);
  3123. // Validate the Type parameter
  3124. if (GFXTYPE_RENDER != Type &&
  3125. GFXTYPE_CAPTURE != Type &&
  3126. GFXTYPE_RENDERCAPTURE != Type)
  3127. {
  3128. dprintf(TEXT("gfxAddGfx: error: Type=%d is invalid\n"), Type);
  3129. return ERROR_INVALID_PARAMETER;
  3130. }
  3131. // Validate the Order parameter
  3132. if (GFX_MAXORDER < Order)
  3133. {
  3134. dprintf(TEXT("gfxAddGfx: error: Order=%d is invalid\n"), Order);
  3135. return ERROR_INVALID_PARAMETER;
  3136. }
  3137. if (!RtlInterlockedTestAcquireResourceShared(&GfxResource, &gfGfxInitialized)) return ERROR_INVALID_FUNCTION;
  3138. lresult = RpcClientHasUserSid(gpConsoleUser->GetSid()) ? NO_ERROR : ERROR_INVALID_FUNCTION;
  3139. if (!lresult)
  3140. {
  3141. LockGlobalLists();
  3142. CGfxFactory *pGfxFactory = CGfxFactory::ListSearchOnDi(*gplistGfxFactories, GfxFactoryDi);
  3143. CZoneFactory *pZoneFactory = CZoneFactory::ListSearchOnDi(*gplistZoneFactories, ZoneFactoryDi);
  3144. if (pGfxFactory && pZoneFactory && pGfxFactory->IsCompatibleZoneFactory(Type, *pZoneFactory))
  3145. {
  3146. CCuUserLoad *pCuUserLoad = new CCuUserLoad(gpConsoleUser);
  3147. if (pCuUserLoad) {
  3148. lresult = pCuUserLoad->CreateFromUser(GfxFactoryDi, ZoneFactoryDi, Type, Order);
  3149. if (!lresult)
  3150. {
  3151. POSITION pos;
  3152. pos = gplistCuUserLoads->AddTail(pCuUserLoad);
  3153. if (pos)
  3154. {
  3155. lresult = pCuUserLoad->Scan(*gplistZoneFactories, *gplistGfxFactories);
  3156. if (!lresult)
  3157. {
  3158. pCuUserLoad->Write(); // Ignoring errors
  3159. *pNewId = pCuUserLoad->GetId();
  3160. } else {
  3161. gplistCuUserLoads->RemoveAt(pos);
  3162. }
  3163. } else {
  3164. lresult = ERROR_OUTOFMEMORY;
  3165. }
  3166. }
  3167. if (lresult) delete pCuUserLoad;
  3168. } else {
  3169. lresult = ERROR_OUTOFMEMORY;
  3170. }
  3171. } else {
  3172. lresult = ERROR_INVALID_PARAMETER;
  3173. }
  3174. UnlockGlobalLists();
  3175. }
  3176. lresult ? dprintf(TEXT("gfxAddGfx: returning error=%lu\n"), lresult) :
  3177. dprintf(TEXT("gfxAddGfx: returning NewId=%08Xh\n"), *pNewId);
  3178. RtlReleaseResource(&GfxResource);
  3179. return lresult;
  3180. }
  3181. RPC_STATUS s_gfxCreateGfxList(IN PWSTR ZoneFactoryDi, OUT UNIQUE_PGFXLIST *ppGfxList)
  3182. {
  3183. UNIQUE_PGFXLIST pGfxList;
  3184. int cGfx;
  3185. LONG lresult;
  3186. if (!RtlInterlockedTestAcquireResourceShared(&GfxResource, &gfGfxInitialized)) return ERROR_INVALID_FUNCTION;
  3187. lresult = RpcClientHasUserSid(gpConsoleUser->GetSid()) ? NO_ERROR : ERROR_INVALID_FUNCTION;
  3188. if (!lresult)
  3189. {
  3190. LockGlobalLists();
  3191. if (!CZoneFactory::ListSearchOnDi(*gplistZoneFactories, ZoneFactoryDi)) lresult = ERROR_DEVICE_NOT_AVAILABLE;
  3192. if (!lresult)
  3193. {
  3194. pGfxList = NULL;
  3195. lresult = NO_ERROR;
  3196. cGfx = gplistCuUserLoads->GetCount();
  3197. if (cGfx > 0)
  3198. {
  3199. SIZE_T cbGfxList;
  3200. cbGfxList = sizeof(*pGfxList) - sizeof(pGfxList->Gfx[0]) + (cGfx * sizeof(pGfxList->Gfx[0]));
  3201. pGfxList = (UNIQUE_PGFXLIST)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbGfxList);
  3202. if (pGfxList)
  3203. {
  3204. POSITION pos = gplistCuUserLoads->GetHeadPosition();
  3205. PGFX pGfx = &pGfxList->Gfx[0];
  3206. cGfx = 0;
  3207. while (pos && !lresult)
  3208. {
  3209. CCuUserLoad& rCuUserLoad = *gplistCuUserLoads->GetNext(pos);
  3210. if (!lstrcmpi(ZoneFactoryDi, rCuUserLoad.GetZoneFactoryDi()))
  3211. {
  3212. pGfx->Type = rCuUserLoad.GetType();
  3213. pGfx->Id = rCuUserLoad.GetId();
  3214. pGfx->Order = rCuUserLoad.GetOrder();
  3215. rCuUserLoad.GetGfxFactoryClsid(*gplistGfxFactories, (LPCLSID)&pGfx->Clsid);
  3216. ASSERT(rCuUserLoad.GetGfxFactoryDi());
  3217. pGfx->GfxFactoryDi = lstrDuplicate(rCuUserLoad.GetGfxFactoryDi());
  3218. if (!pGfx->GfxFactoryDi) lresult = ERROR_OUTOFMEMORY;
  3219. pGfx++;
  3220. cGfx++;
  3221. }
  3222. }
  3223. if (lresult)
  3224. {
  3225. pGfx = &pGfxList->Gfx[0];
  3226. while (cGfx > 0)
  3227. {
  3228. HeapFreeIfNotNull(hHeap, 0, pGfx->GfxFactoryDi);
  3229. pGfx++;
  3230. cGfx--;
  3231. }
  3232. HeapFree(hHeap, 0, pGfxList);
  3233. pGfxList = NULL;
  3234. }
  3235. } else {
  3236. lresult = ERROR_OUTOFMEMORY;
  3237. }
  3238. }
  3239. if (!lresult)
  3240. {
  3241. if (pGfxList) pGfxList->Count = cGfx;
  3242. *ppGfxList = pGfxList;
  3243. }
  3244. }
  3245. UnlockGlobalLists();
  3246. }
  3247. RtlReleaseResource(&GfxResource);
  3248. return lresult;
  3249. }
  3250. RPC_STATUS s_gfxCreateGfxFactoriesList(IN PWSTR ZoneFactoryDi, OUT UNIQUE_PDILIST *ppDiList)
  3251. {
  3252. RPC_STATUS status;
  3253. CZoneFactory *pZoneFactory;
  3254. if (!RtlInterlockedTestAcquireResourceShared(&GfxResource, &gfGfxInitialized)) return ERROR_INVALID_FUNCTION;
  3255. status = RpcClientHasUserSid(gpConsoleUser->GetSid()) ? NO_ERROR : ERROR_INVALID_FUNCTION;
  3256. if (!status)
  3257. {
  3258. LockGlobalLists();
  3259. pZoneFactory = CZoneFactory::ListSearchOnDi(*gplistZoneFactories, ZoneFactoryDi);
  3260. if (!pZoneFactory) status = ERROR_DEVICE_NOT_AVAILABLE;
  3261. if (!status)
  3262. {
  3263. UNIQUE_PDILIST pDiList;
  3264. SIZE_T cbDiList;
  3265. int cElements;
  3266. PWSTR *pDi;
  3267. cElements = gplistGfxFactories->GetCount();
  3268. cbDiList = (sizeof(*pDiList) - sizeof(pDiList->DeviceInterface[0])) + (cElements * sizeof(pDiList->DeviceInterface[0]));
  3269. pDiList = (UNIQUE_PDILIST)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbDiList);
  3270. if (pDiList)
  3271. {
  3272. pDi = &pDiList->DeviceInterface[0];
  3273. POSITION pos = gplistGfxFactories->GetHeadPosition();
  3274. pDiList->Count = 0;
  3275. for (pos = gplistGfxFactories->GetHeadPosition(); pos; *gplistGfxFactories->GetNext(pos))
  3276. {
  3277. // If this gfx factory is an auto-load, then we need
  3278. // to check whether the zone factory is compatible before
  3279. // returning this gfx factory in the gfx factories list
  3280. CGfxFactory& rGfxFactory = *gplistGfxFactories->GetAt(pos);
  3281. if (rGfxFactory.GetListLmAutoLoads().GetCount())
  3282. {
  3283. // See if this ZoneFactoryDi works on any of the LmAutoLoads
  3284. POSITION posLmAutoLoad;
  3285. for (posLmAutoLoad = rGfxFactory.GetListLmAutoLoads().GetHeadPosition();
  3286. posLmAutoLoad;
  3287. rGfxFactory.GetListLmAutoLoads().GetNext(posLmAutoLoad))
  3288. {
  3289. CLmAutoLoad& rLmAutoLoad = *rGfxFactory.GetListLmAutoLoads().GetAt(posLmAutoLoad);
  3290. if (rLmAutoLoad.IsCompatibleZoneFactory(*pZoneFactory)) break;
  3291. }
  3292. if (!posLmAutoLoad) continue;
  3293. } else continue; // Fix 394279: Only enumerate Auto-load GFX
  3294. ASSERT(rGfxFactory.GetDeviceInterface());
  3295. *pDi = lstrDuplicate(rGfxFactory.GetDeviceInterface());
  3296. if (NULL == *pDi) break;
  3297. pDi++; // Next slot
  3298. pDiList->Count++;
  3299. }
  3300. if (pos)
  3301. {
  3302. pDi = &pDiList->DeviceInterface[0];
  3303. while (*pDi) HeapFree(hHeap, 0, *(pDi++));
  3304. HeapFree(hHeap, 0, pDiList);
  3305. pDiList = NULL;
  3306. }
  3307. if (pDiList) *ppDiList = pDiList;
  3308. status = pDiList ? NO_ERROR : ERROR_OUTOFMEMORY;
  3309. }
  3310. }
  3311. UnlockGlobalLists();
  3312. }
  3313. RtlReleaseResource(&GfxResource);
  3314. return status;
  3315. }
  3316. RPC_STATUS s_gfxCreateZoneFactoriesList(OUT UNIQUE_PDILIST *ppDiList)
  3317. {
  3318. UNIQUE_PDILIST pDiList;
  3319. SIZE_T cbDiList;
  3320. int cElements;
  3321. RPC_STATUS status;
  3322. if (!RtlInterlockedTestAcquireResourceShared(&GfxResource, &gfGfxInitialized)) return ERROR_INVALID_FUNCTION;
  3323. status = RpcClientHasUserSid(gpConsoleUser->GetSid()) ? NO_ERROR : ERROR_INVALID_FUNCTION;
  3324. if (!status)
  3325. {
  3326. PWSTR *pDi;
  3327. LockGlobalLists();
  3328. cElements = gplistZoneFactories->GetCount();
  3329. cbDiList = (sizeof(*pDiList) - sizeof(pDiList->DeviceInterface[0])) + (cElements * sizeof(pDiList->DeviceInterface[0]));
  3330. pDiList = (UNIQUE_PDILIST) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbDiList);
  3331. if (pDiList)
  3332. {
  3333. pDi = &pDiList->DeviceInterface[0];
  3334. POSITION pos = gplistZoneFactories->GetHeadPosition();
  3335. pDiList->Count = cElements;
  3336. while (pos)
  3337. {
  3338. CZoneFactory& rZoneFactory = *gplistZoneFactories->GetAt(pos);
  3339. *pDi = lstrDuplicate(rZoneFactory.GetDeviceInterface());
  3340. if (NULL == *pDi) break;
  3341. gplistZoneFactories->GetNext(pos);
  3342. pDi++;
  3343. }
  3344. if (pos)
  3345. {
  3346. pDi = &pDiList->DeviceInterface[0];
  3347. while (*pDi) HeapFree(hHeap, 0, *(pDi++));
  3348. HeapFree(hHeap, 0, pDiList);
  3349. pDiList = NULL;
  3350. }
  3351. }
  3352. UnlockGlobalLists();
  3353. if (pDiList) *ppDiList = pDiList;
  3354. status = pDiList ? NO_ERROR : ERROR_OUTOFMEMORY;
  3355. }
  3356. RtlReleaseResource(&GfxResource);
  3357. return status;
  3358. }
  3359. LONG s_gfxOpenGfx(IN DWORD dwProcessId, IN DWORD dwGfxId, OUT RHANDLE *pFileHandle)
  3360. {
  3361. HANDLE hClientProcess;
  3362. RPC_STATUS status;
  3363. HANDLE hGfxFilter;
  3364. POSITION pos;
  3365. if (!RtlInterlockedTestAcquireResourceShared(&GfxResource, &gfGfxInitialized)) return ERROR_INVALID_FUNCTION;
  3366. status = RpcClientHasUserSid(gpConsoleUser->GetSid()) ? NO_ERROR : ERROR_INVALID_FUNCTION;
  3367. if (!status)
  3368. {
  3369. LockGlobalLists();
  3370. status = ERROR_BAD_DEVICE; // Cannot find the device specified
  3371. pos = gplistCuUserLoads->GetHeadPosition();
  3372. while (pos) {
  3373. CCuUserLoad *pCuUserLoad = gplistCuUserLoads->GetAt(pos);
  3374. if (pCuUserLoad->GetId() == dwGfxId) {
  3375. hGfxFilter = pCuUserLoad->GetFilterHandle();
  3376. status = (INVALID_HANDLE_VALUE != hGfxFilter) ? NO_ERROR : GetLastError();
  3377. break;
  3378. }
  3379. gplistCuUserLoads->GetNext(pos);
  3380. }
  3381. if (!status)
  3382. {
  3383. hClientProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
  3384. if (hClientProcess)
  3385. {
  3386. HANDLE hGfxFilterClient;
  3387. if (DuplicateHandle(GetCurrentProcess(), hGfxFilter, hClientProcess, &hGfxFilterClient, 0, FALSE, DUPLICATE_SAME_ACCESS))
  3388. {
  3389. dprintf(TEXT("hGfxFilter=%p, hGfxFilterClient=%p\n"), hGfxFilter, hGfxFilterClient);
  3390. *pFileHandle = (RHANDLE)hGfxFilterClient;
  3391. } else {
  3392. status = GetLastError();
  3393. }
  3394. CloseHandle(hClientProcess);
  3395. } else {
  3396. status = GetLastError();
  3397. }
  3398. }
  3399. UnlockGlobalLists();
  3400. }
  3401. RtlReleaseResource(&GfxResource);
  3402. return status;
  3403. }
  3404. //=============================================================================
  3405. //=== Startup/shutdown ===
  3406. //=============================================================================
  3407. void EnumeratedInterface(LPCGUID ClassGuid, PCTSTR DeviceInterface)
  3408. {
  3409. if (IsEqualGUID(KSCATEGORY_AUDIO, *ClassGuid)) GFX_AudioInterfaceArrival(DeviceInterface);
  3410. if (IsEqualGUID(KSCATEGORY_RENDER, *ClassGuid)) GFX_RenderInterfaceArrival(DeviceInterface);
  3411. if (IsEqualGUID(KSCATEGORY_CAPTURE, *ClassGuid)) GFX_CaptureInterfaceArrival(DeviceInterface);
  3412. if (IsEqualGUID(KSCATEGORY_DATATRANSFORM, *ClassGuid)) GFX_DataTransformInterfaceArrival(DeviceInterface);
  3413. if (IsEqualGUID(KSCATEGORY_SYSAUDIO, *ClassGuid)) GFX_SysaudioInterfaceArrival(DeviceInterface);
  3414. return;
  3415. }
  3416. void EnumerateInterfaces(LPCGUID ClassGuid)
  3417. {
  3418. HDEVINFO hdi;
  3419. hdi = SetupDiGetClassDevs(ClassGuid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
  3420. if (hdi) {
  3421. DWORD i;
  3422. BOOL fresult;
  3423. i = (-1);
  3424. do {
  3425. SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
  3426. i += 1;
  3427. DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData);
  3428. fresult = SetupDiEnumDeviceInterfaces(hdi, NULL, ClassGuid, i, &DeviceInterfaceData);
  3429. if (fresult) {
  3430. DWORD cbDeviceInterfaceDetailData;
  3431. if ( SetupDiGetDeviceInterfaceDetail(hdi, &DeviceInterfaceData, NULL, 0, &cbDeviceInterfaceDetailData, NULL)
  3432. || ERROR_INSUFFICIENT_BUFFER == GetLastError())
  3433. {
  3434. PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;
  3435. DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(hHeap, 0, cbDeviceInterfaceDetailData);
  3436. if (DeviceInterfaceDetailData) {
  3437. DeviceInterfaceDetailData->cbSize = sizeof(*DeviceInterfaceDetailData);
  3438. if (SetupDiGetDeviceInterfaceDetail(hdi, &DeviceInterfaceData, DeviceInterfaceDetailData, cbDeviceInterfaceDetailData, NULL, NULL)) {
  3439. EnumeratedInterface(ClassGuid, DeviceInterfaceDetailData->DevicePath);
  3440. }
  3441. HeapFree(hHeap, 0, DeviceInterfaceDetailData);
  3442. }
  3443. }
  3444. }
  3445. } while (fresult);
  3446. SetupDiDestroyDeviceInfoList(hdi);
  3447. }
  3448. return;
  3449. }
  3450. void Initialize(void)
  3451. {
  3452. LONG result;
  3453. ASSERT(FALSE == gfGfxInitialized);
  3454. // dprintf(TEXT("GFX_Initialize\n"));
  3455. //
  3456. // Sysaudio critical section
  3457. //
  3458. ASSERT(!gfCsSysaudio);
  3459. __try {
  3460. InitializeCriticalSection(&gcsSysaudio);
  3461. gfCsSysaudio = TRUE;
  3462. result = NO_ERROR;
  3463. } __except(EXCEPTION_EXECUTE_HANDLER) {
  3464. result = ERROR_OUTOFMEMORY;
  3465. }
  3466. //
  3467. // Create gobal lists
  3468. //
  3469. if (NO_ERROR == result)
  3470. {
  3471. gplistGfxFactories = new CListGfxFactories;
  3472. gplistZoneFactories = new CListZoneFactories;
  3473. gplistCuUserLoads = new CListCuUserLoads;
  3474. if (gplistGfxFactories && gplistZoneFactories && gplistCuUserLoads)
  3475. {
  3476. result = gplistGfxFactories->Initialize();
  3477. if (NO_ERROR == result) result = gplistZoneFactories->Initialize();
  3478. if (NO_ERROR == result) result = gplistCuUserLoads->Initialize();
  3479. } else {
  3480. result = ERROR_OUTOFMEMORY;
  3481. }
  3482. }
  3483. if (NO_ERROR == result) {
  3484. gfGfxInitialized = TRUE;
  3485. //
  3486. // Fill global lists
  3487. //
  3488. // Note we do not acquire global lists lock. We assume that this
  3489. // function is called before any other functions that might access
  3490. // the lists.
  3491. //
  3492. CCuUserLoad::FillListFromReg(gpConsoleUser, *gplistCuUserLoads);
  3493. // Pnp notifications are already set up. We need to enumerate any |
  3494. // existing interfaces. We don't really need to enumerate render,
  3495. // capture, and datatransform since we check for those aliases when we
  3496. // check audio interfaces. If a capture, render, or datatransform
  3497. // interface is not yet enabled when we check an audio interface, then
  3498. // we will get it via pnp notification.
  3499. EnumerateInterfaces(&KSCATEGORY_SYSAUDIO);
  3500. EnumerateInterfaces(&KSCATEGORY_AUDIO);
  3501. // EnumerateInterfaces(&KSCATEGORY_RENDER);
  3502. // EnumerateInterfaces(&KSCATEGORY_CAPTURE);
  3503. // EnumerateInterfaces(&KSCATEGORY_DATATRANSFORM);
  3504. } else {
  3505. //
  3506. // Unwind due to error
  3507. //
  3508. if (gplistGfxFactories) delete gplistGfxFactories;
  3509. if (gplistZoneFactories) delete gplistZoneFactories;
  3510. if (gplistCuUserLoads) delete gplistCuUserLoads;
  3511. gplistGfxFactories = NULL;
  3512. gplistZoneFactories = NULL;
  3513. gplistCuUserLoads = NULL;
  3514. if (gfCsSysaudio) DeleteCriticalSection(&gcsSysaudio);
  3515. gfCsSysaudio = FALSE;
  3516. }
  3517. return;
  3518. }
  3519. void Terminate(void)
  3520. {
  3521. POSITION pos;
  3522. // dprintf(TEXT("GFX_Terminate\n"));
  3523. gfGfxInitialized = FALSE;
  3524. //
  3525. // Clean up glistGfxFactories, glistZoneFactories, glistUserLoads
  3526. //
  3527. if (gplistCuUserLoads) {
  3528. pos = gplistCuUserLoads->GetHeadPosition();
  3529. while (pos) {
  3530. CCuUserLoad *pCuUserLoad = gplistCuUserLoads->GetNext(pos);
  3531. delete pCuUserLoad;
  3532. }
  3533. gplistCuUserLoads->RemoveAll();
  3534. delete gplistCuUserLoads;
  3535. gplistCuUserLoads = NULL;
  3536. }
  3537. if (gplistGfxFactories) {
  3538. pos = gplistGfxFactories->GetHeadPosition();
  3539. while (pos) {
  3540. CGfxFactory *pGfxFactory = gplistGfxFactories->GetNext(pos);
  3541. delete pGfxFactory;
  3542. }
  3543. gplistGfxFactories->RemoveAll();
  3544. delete gplistGfxFactories;
  3545. gplistGfxFactories = NULL;
  3546. }
  3547. if (gplistZoneFactories) {
  3548. pos = gplistZoneFactories->GetHeadPosition();
  3549. while (pos) {
  3550. CZoneFactory *pZoneFactory = gplistZoneFactories->GetNext(pos);
  3551. delete pZoneFactory;
  3552. }
  3553. gplistZoneFactories->RemoveAll();
  3554. delete gplistZoneFactories;
  3555. gplistZoneFactories = NULL;
  3556. }
  3557. //
  3558. // Close sysaudio
  3559. //
  3560. if (INVALID_HANDLE_VALUE != ghSysaudio) {
  3561. CloseHandle(ghSysaudio);
  3562. HeapFree(hHeap, 0, gpstrSysaudioDeviceInterface);
  3563. ghSysaudio = INVALID_HANDLE_VALUE;
  3564. gpstrSysaudioDeviceInterface = NULL;
  3565. }
  3566. //
  3567. // Sysaudio critical section
  3568. //
  3569. if (gfCsSysaudio) DeleteCriticalSection(&gcsSysaudio);
  3570. gfCsSysaudio = FALSE;
  3571. //
  3572. // Console user
  3573. //
  3574. if (gpConsoleUser) delete gpConsoleUser;
  3575. gpConsoleUser = NULL;
  3576. return;
  3577. }
  3578. /*-----------------------------------------------------------------------------
  3579. InitializeForNewConsoleUser
  3580. Evaluates current console user. If the user is different than before,
  3581. then terminate and reinitialize the GFX objects and data structures.
  3582. Assume GfxResource is acquired exclusive.
  3583. Assumes gdwConsoleSessionId has been set properly.
  3584. Might change gpConsoleUserSid.
  3585. -----------------------------------------------------------------------------*/
  3586. void InitializeForNewConsoleUser(DWORD ConsoleSessionId)
  3587. {
  3588. CUser *pOldConsoleUser = gpConsoleUser;
  3589. CUser *pNewConsoleUser = NULL;
  3590. BOOL IsNewConsoleUser = TRUE;
  3591. CreateUser(ConsoleSessionId, &pNewConsoleUser);
  3592. if ((!pNewConsoleUser && !pOldConsoleUser) ||
  3593. (pNewConsoleUser && pOldConsoleUser && (*pNewConsoleUser == *pOldConsoleUser)))
  3594. {
  3595. IsNewConsoleUser = FALSE;
  3596. }
  3597. if (IsNewConsoleUser)
  3598. {
  3599. Terminate();
  3600. gpConsoleUser = pNewConsoleUser;
  3601. if (gpConsoleUser)
  3602. {
  3603. #ifdef DBG
  3604. {
  3605. PTSTR StringSid;
  3606. if (CreateStringSidFromSid(gpConsoleUser->GetSid(), &StringSid))
  3607. {
  3608. dprintf(TEXT("note: new console user SID %s\n"), StringSid);
  3609. HeapFree(hHeap, 0, StringSid);
  3610. }
  3611. }
  3612. #endif
  3613. Initialize();
  3614. }
  3615. } else {
  3616. delete pNewConsoleUser;
  3617. }
  3618. return;
  3619. }
  3620. void GFX_SessionChange(DWORD EventType, LPVOID EventData)
  3621. {
  3622. PWTSSESSION_NOTIFICATION pWtsNotification = (PWTSSESSION_NOTIFICATION)EventData;
  3623. static DWORD ConsoleSessionId = 0; // Initial console session ID
  3624. switch (EventType)
  3625. {
  3626. case WTS_CONSOLE_CONNECT:
  3627. {
  3628. RtlAcquireResourceExclusive(&GfxResource, TRUE);
  3629. ConsoleSessionId = pWtsNotification->dwSessionId;
  3630. InitializeForNewConsoleUser(ConsoleSessionId);
  3631. RtlReleaseResource(&GfxResource);
  3632. break;
  3633. }
  3634. case WTS_CONSOLE_DISCONNECT:
  3635. {
  3636. RtlAcquireResourceExclusive(&GfxResource, TRUE);
  3637. Terminate();
  3638. ConsoleSessionId = LOGONID_NONE;
  3639. RtlReleaseResource(&GfxResource);
  3640. break;
  3641. }
  3642. case WTS_REMOTE_CONNECT:
  3643. {
  3644. break;
  3645. }
  3646. case WTS_REMOTE_DISCONNECT:
  3647. {
  3648. break;
  3649. }
  3650. case WTS_SESSION_LOGON:
  3651. {
  3652. RtlAcquireResourceExclusive(&GfxResource, TRUE);
  3653. if (ConsoleSessionId == pWtsNotification->dwSessionId) InitializeForNewConsoleUser(ConsoleSessionId);
  3654. RtlReleaseResource(&GfxResource);
  3655. break;
  3656. }
  3657. case WTS_SESSION_LOGOFF:
  3658. {
  3659. RtlAcquireResourceExclusive(&GfxResource, TRUE);
  3660. if (ConsoleSessionId == pWtsNotification->dwSessionId) Terminate();
  3661. RtlReleaseResource(&GfxResource);
  3662. break;
  3663. }
  3664. default:
  3665. {
  3666. dprintf(TEXT("GFX_SessionChange: Unhandled EventType=%d\n"), EventType);
  3667. break;
  3668. }
  3669. }
  3670. return;
  3671. }
  3672. void GFX_ServiceStop(void)
  3673. {
  3674. RtlAcquireResourceExclusive(&GfxResource, TRUE);
  3675. Terminate();
  3676. RtlReleaseResource(&GfxResource);
  3677. return;
  3678. }
  3679. void s_gfxLogon(IN handle_t hBinding, IN DWORD dwProcessId)
  3680. {
  3681. // dprintf(TEXT("s_gfxLogon\n"));
  3682. // ISSUE-2001/01/29-FrankYe I should be able to completely remove this and
  3683. // s_gfxLogoff after Windows Bugs 296884 is fixed.
  3684. return;
  3685. }
  3686. void s_gfxLogoff(void)
  3687. {
  3688. // dprintf(TEXT("s_gfxLogoff\n"));
  3689. return;
  3690. }
  3691. //=============================================================================
  3692. //=== GFX-specific DLL attach/detach ===
  3693. //=============================================================================
  3694. BOOL GFX_DllProcessAttach(void)
  3695. {
  3696. BOOL result;
  3697. NTSTATUS ntstatus;
  3698. __try {
  3699. RtlInitializeResource(&GfxResource);
  3700. ntstatus = STATUS_SUCCESS;
  3701. } __except(EXCEPTION_EXECUTE_HANDLER) {
  3702. ntstatus = GetExceptionCode();
  3703. }
  3704. gfGfxResource = (NT_SUCCESS(ntstatus));
  3705. result = (NT_SUCCESS(ntstatus));
  3706. return result;
  3707. }
  3708. void GFX_DllProcessDetach(void)
  3709. {
  3710. if (gfGfxResource) {
  3711. RtlDeleteResource(&GfxResource);
  3712. }
  3713. return;
  3714. }