Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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