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.

593 lines
14 KiB

  1. /////////////////////////////////////////////////////////////////////
  2. //
  3. // Module: rdpsnd.c
  4. //
  5. // Purpose: User-mode audio driver for terminal server
  6. // audio redirection
  7. //
  8. // Copyright(C) Microsoft Corporation 2000
  9. //
  10. // History: 4-10-2000 vladimis [created]
  11. //
  12. /////////////////////////////////////////////////////////////////////
  13. #include "rdpsnd.h"
  14. #include <stdio.h>
  15. #include <aclapi.h>
  16. #include <psapi.h>
  17. #define WINLOGON_EXE L"\\??\\%SystemRoot%\\system32\\winlogon.exe"
  18. const CHAR *ALV = "TSSND::ALV - ";
  19. const CHAR *INF = "TSSND::INF - ";
  20. const CHAR *WRN = "TSSND::WRN - ";
  21. const CHAR *ERR = "TSSND::ERR - ";
  22. const CHAR *FATAL = "TSSND::FATAL - ";
  23. HANDLE g_hHeap = NULL;
  24. HANDLE g_hMixerThread = NULL;
  25. HINSTANCE g_hDllInst = NULL;
  26. BOOL g_bPersonalTS = FALSE;
  27. BOOL bInitializedSuccessfully = FALSE;
  28. /*
  29. * Function:
  30. * DllInstanceInit
  31. *
  32. * Description:
  33. * Dll main enrty point
  34. *
  35. */
  36. BOOL
  37. DllInstanceInit(
  38. HINSTANCE hDllInst,
  39. DWORD dwReason,
  40. LPVOID fImpLoad
  41. )
  42. {
  43. BOOL rv = FALSE;
  44. if (DLL_PROCESS_ATTACH == dwReason)
  45. {
  46. TRC(ALV, "DLL_PROCESS_ATTACH\n");
  47. TSHEAPINIT;
  48. if (!TSISHEAPOK)
  49. {
  50. TRC(FATAL, "DllInstanceInit: can't create heap\n");
  51. goto exitpt;
  52. }
  53. __try {
  54. InitializeCriticalSection(&g_cs);
  55. rv = TRUE;
  56. }
  57. __except (EXCEPTION_EXECUTE_HANDLER)
  58. {
  59. rv = FALSE;
  60. }
  61. if (!rv)
  62. {
  63. TRC(FATAL, "DllInstanceInit: can't initialize critical section\n");
  64. goto exitpt;
  65. }
  66. DisableThreadLibraryCalls(hDllInst);
  67. g_hDllInst = hDllInst;
  68. rv = TRUE;
  69. } else if (DLL_PROCESS_DETACH == dwReason)
  70. {
  71. TRC(ALV, "DLL_PROCESS_DETACH\n");
  72. TSHEAPDESTROY;
  73. rv = TRUE;
  74. }
  75. exitpt:
  76. return rv;
  77. }
  78. BOOL
  79. IsPersonalTerminalServicesEnabled(
  80. VOID
  81. )
  82. {
  83. BOOL fRet;
  84. DWORDLONG dwlConditionMask;
  85. OSVERSIONINFOEX osVersionInfo;
  86. RtlZeroMemory(&osVersionInfo, sizeof(OSVERSIONINFOEX));
  87. osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  88. osVersionInfo.wProductType = VER_NT_WORKSTATION;
  89. osVersionInfo.wSuiteMask = VER_SUITE_SINGLEUSERTS;
  90. dwlConditionMask = 0;
  91. VER_SET_CONDITION(dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL);
  92. VER_SET_CONDITION(dwlConditionMask, VER_SUITENAME, VER_OR);
  93. fRet = VerifyVersionInfo(
  94. &osVersionInfo,
  95. VER_PRODUCT_TYPE | VER_SUITENAME,
  96. dwlConditionMask
  97. );
  98. return(fRet);
  99. }
  100. BOOL
  101. RunningInWinlogon()
  102. {
  103. WCHAR szWinlogonOrg[128];
  104. WCHAR szFile[128];
  105. static BOOL s_bWinlogonChecked = FALSE;
  106. static BOOL s_bWinlogonResult = FALSE;
  107. if ( s_bWinlogonChecked )
  108. {
  109. goto exitpt;
  110. }
  111. szWinlogonOrg[0] = 0;
  112. if (!ExpandEnvironmentStrings( WINLOGON_EXE, szWinlogonOrg, RTL_NUMBER_OF( szWinlogonOrg )))
  113. {
  114. TRC( ERR, "Failed to get winlogon path: GetLastError=%d\n", GetLastError());
  115. goto exitpt;
  116. }
  117. if ( !GetModuleFileNameEx(
  118. GetCurrentProcess(),
  119. GetModuleHandle( NULL ),
  120. szFile,
  121. RTL_NUMBER_OF( szFile )))
  122. {
  123. TRC( ERR, "GetModuleFileNameEx failed: GetLastError=%d\n", GetLastError());
  124. goto exitpt;
  125. }
  126. s_bWinlogonChecked = TRUE;
  127. s_bWinlogonResult = ( 0 == _wcsicmp( szFile, szWinlogonOrg ));
  128. exitpt:
  129. return s_bWinlogonResult;
  130. }
  131. HANDLE
  132. _CreateInitEvent(
  133. VOID
  134. )
  135. {
  136. SECURITY_ATTRIBUTES SA;
  137. PSECURITY_DESCRIPTOR pSD = NULL;
  138. EXPLICIT_ACCESS ea[2];
  139. SID_IDENTIFIER_AUTHORITY siaWorld = SECURITY_WORLD_SID_AUTHORITY;
  140. SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY;
  141. PSID pSidWorld = NULL;
  142. PSID pSidNT = NULL;
  143. PACL pNewDAcl = NULL;
  144. DWORD dwres;
  145. HANDLE hWaitToInit = NULL;
  146. //
  147. // wait, before creating this event, check if we are running inside winlogon
  148. // only then create this event, because only then we have to delay
  149. // audio rendering of the logon sound (aka "TADA")
  150. //
  151. if ( !RunningInWinlogon() )
  152. {
  153. goto exitpt;
  154. } else {
  155. TRC( INF, "running in winlogon, delayed audio rendering\n" );
  156. }
  157. pSD = (PSECURITY_DESCRIPTOR) TSMALLOC(SECURITY_DESCRIPTOR_MIN_LENGTH);
  158. if ( NULL == pSD )
  159. goto exitpt;
  160. if ( !AllocateAndInitializeSid(
  161. &siaWorld, 1, SECURITY_WORLD_RID,
  162. 0, 0, 0, 0, 0, 0, 0, &pSidWorld))
  163. {
  164. goto exitpt;
  165. }
  166. if ( !AllocateAndInitializeSid(
  167. &siaNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  168. 0, 0, 0, 0, 0, 0, 0, &pSidNT ))
  169. {
  170. goto exitpt;
  171. }
  172. ZeroMemory(ea, sizeof(ea));
  173. ea[0].grfAccessPermissions = EVENT_MODIFY_STATE;
  174. ea[0].grfAccessMode = GRANT_ACCESS;
  175. ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  176. ea[0].Trustee.ptstrName = (LPTSTR)pSidWorld;
  177. ea[1].grfAccessPermissions = GENERIC_ALL;
  178. ea[1].grfAccessMode = GRANT_ACCESS;
  179. ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  180. ea[1].Trustee.ptstrName = (LPTSTR)pSidNT;
  181. dwres = SetEntriesInAcl(2, ea, NULL, &pNewDAcl );
  182. if ( ERROR_SUCCESS != dwres )
  183. {
  184. goto exitpt;
  185. }
  186. if (!InitializeSecurityDescriptor(pSD,
  187. SECURITY_DESCRIPTOR_REVISION))
  188. goto exitpt;
  189. if (!SetSecurityDescriptorDacl(pSD,
  190. TRUE, // specifying a disc. ACL
  191. pNewDAcl,
  192. FALSE)) // not a default disc. ACL
  193. goto exitpt;
  194. SA.nLength = sizeof( SA );
  195. SA.lpSecurityDescriptor = pSD;
  196. SA.bInheritHandle = FALSE;
  197. hWaitToInit = CreateEvent( &SA,
  198. FALSE,
  199. FALSE,
  200. TSSND_WAITTOINIT );
  201. if ( NULL == hWaitToInit )
  202. {
  203. TRC( ALV, "Failed to create WaitToInit event:%d\n",
  204. GetLastError());
  205. } else if ( ERROR_ALREADY_EXISTS == GetLastError() )
  206. {
  207. CloseHandle( hWaitToInit );
  208. TRC( ALV, "Init event already exists\n" );
  209. hWaitToInit = NULL;
  210. }
  211. exitpt:
  212. if ( NULL != pNewDAcl )
  213. {
  214. LocalFree( pNewDAcl );
  215. }
  216. if ( NULL != pSidNT )
  217. {
  218. LocalFree( pSidNT );
  219. }
  220. if ( NULL != pSidWorld )
  221. {
  222. LocalFree( pSidWorld );
  223. }
  224. if ( NULL != pSD )
  225. {
  226. TSFREE( pSD );
  227. }
  228. return hWaitToInit;
  229. }
  230. /*
  231. * Function:
  232. * drvEnable
  233. *
  234. * Description:
  235. * Initializes the driver
  236. *
  237. */
  238. LRESULT
  239. drvEnable(
  240. VOID
  241. )
  242. {
  243. LRESULT rv = 1;
  244. EnterCriticalSection(&g_cs);
  245. if (bInitializedSuccessfully)
  246. {
  247. rv = 1;
  248. goto exitpt;
  249. }
  250. if ( NULL == g_hDataReadyEvent )
  251. g_hDataReadyEvent = OpenEvent(EVENT_ALL_ACCESS,
  252. FALSE,
  253. TSSND_DATAREADYEVENT);
  254. if (NULL == g_hDataReadyEvent)
  255. {
  256. TRC(ALV, "DRV_ENABLE: can't open %S: %d\n",
  257. TSSND_DATAREADYEVENT,
  258. GetLastError());
  259. rv = 0;
  260. }
  261. if ( NULL == g_hStreamIsEmptyEvent )
  262. g_hStreamIsEmptyEvent = OpenEvent(EVENT_ALL_ACCESS,
  263. FALSE,
  264. TSSND_STREAMISEMPTYEVENT);
  265. if (NULL == g_hDataReadyEvent)
  266. {
  267. TRC(ALV, "DRV_ENABLE: can't open %S: %d\n",
  268. TSSND_STREAMISEMPTYEVENT,
  269. GetLastError());
  270. rv = 0;
  271. }
  272. if ( NULL == g_hStreamMutex )
  273. g_hStreamMutex = OpenMutex(SYNCHRONIZE,
  274. FALSE,
  275. TSSND_STREAMMUTEX);
  276. if (NULL == g_hDataReadyEvent)
  277. {
  278. TRC(ALV, "DRV_ENABLE: can't open %S: %d\n",
  279. TSSND_STREAMMUTEX,
  280. GetLastError());
  281. rv = 0;
  282. }
  283. if ( NULL == g_hMixerEvent )
  284. g_hMixerEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  285. if (NULL == g_hMixerEvent)
  286. {
  287. TRC(ERR, "DRV_ENABLE: can't create mixer event: %d\n",
  288. GetLastError());
  289. rv = 0;
  290. }
  291. if ( NULL == g_hStream )
  292. g_hStream = OpenFileMapping(
  293. FILE_MAP_ALL_ACCESS,
  294. FALSE,
  295. TSSND_STREAMNAME
  296. );
  297. if (NULL == g_hStream)
  298. {
  299. TRC(ALV, "Can't open the stream mapping\n");
  300. rv = 0;
  301. }
  302. if ( (NULL == g_Stream) && (NULL != g_hStream) )
  303. g_Stream = MapViewOfFile(
  304. g_hStream,
  305. FILE_MAP_ALL_ACCESS,
  306. 0, 0, // offset
  307. sizeof(*g_Stream)
  308. );
  309. if (NULL == g_Stream)
  310. {
  311. TRC(ALV, "drvEnale: "
  312. "can't map the stream view: %d\n",
  313. GetLastError());
  314. rv = 0;
  315. }
  316. g_bPersonalTS = IsPersonalTerminalServicesEnabled();
  317. if ( 1 == rv &&
  318. NULL != g_Stream &&
  319. 0 != ( g_Stream->dwSoundCaps & TSSNDCAPS_INITIALIZED ))
  320. {
  321. rv = _EnableMixerThread();
  322. }
  323. exitpt:
  324. if (0 != rv)
  325. {
  326. bInitializedSuccessfully = TRUE;
  327. }
  328. //
  329. // waiting for initialization ?
  330. //
  331. if (( 0 == rv ||
  332. NULL == g_Stream ||
  333. 0 == ( g_Stream->dwSoundCaps & TSSNDCAPS_INITIALIZED )) &&
  334. !AudioRedirDisabled() &&
  335. NULL == g_hWaitToInitialize )
  336. {
  337. g_hWaitToInitialize = _CreateInitEvent();
  338. }
  339. LeaveCriticalSection(&g_cs);
  340. return rv;
  341. }
  342. /*
  343. * Function:
  344. * drvDisable
  345. *
  346. * Description:
  347. * Driver cleanup
  348. *
  349. */
  350. LRESULT
  351. drvDisable(
  352. VOID
  353. )
  354. {
  355. HANDLE hStreamMutex;
  356. EnterCriticalSection(&g_cs);
  357. hStreamMutex = g_hStreamMutex;
  358. _waveAcquireStream();
  359. TRC( INF, "drvDisable PID(0x%x)\n", GetCurrentProcessId() );
  360. if (NULL == g_hMixerThread ||
  361. NULL == g_hMixerEvent)
  362. goto exitpt;
  363. //
  364. // Disable the mixer
  365. //
  366. g_bMixerRunning = FALSE;
  367. //
  368. // Kick the mixer thread, so it exits
  369. //
  370. SetEvent(g_hMixerEvent);
  371. WaitForSingleObject(g_hMixerThread, INFINITE);
  372. exitpt:
  373. if ( NULL != g_hWaitToInitialize )
  374. {
  375. CloseHandle( g_hWaitToInitialize );
  376. }
  377. if (NULL != g_hDataReadyEvent)
  378. CloseHandle(g_hDataReadyEvent);
  379. if (NULL != g_hStreamIsEmptyEvent)
  380. CloseHandle(g_hStreamIsEmptyEvent);
  381. if (NULL != g_hMixerEvent)
  382. CloseHandle(g_hMixerEvent);
  383. if (NULL != g_Stream)
  384. UnmapViewOfFile(g_Stream);
  385. if (NULL != g_hStream)
  386. CloseHandle(g_hStream);
  387. if (NULL != g_hMixerThread)
  388. CloseHandle(g_hMixerThread);
  389. g_hWaitToInitialize = NULL;
  390. g_hDataReadyEvent = NULL;
  391. g_hStreamIsEmptyEvent = NULL;
  392. g_hMixerEvent = NULL;
  393. g_hStreamMutex = NULL;
  394. g_Stream = NULL;
  395. g_hStream = NULL;
  396. g_hMixerThread = NULL;
  397. g_bMixerRunning = FALSE;
  398. bInitializedSuccessfully = FALSE;
  399. if (NULL != hStreamMutex)
  400. CloseHandle(hStreamMutex); // this will release the stream
  401. LeaveCriticalSection(&g_cs);
  402. return 1;
  403. }
  404. /*
  405. * Function:
  406. * DriverProc
  407. *
  408. * Description:
  409. * Driver main entry point
  410. *
  411. */
  412. LRESULT
  413. DriverProc(
  414. DWORD_PTR dwDriverID,
  415. HANDLE hDriver,
  416. UINT uiMessage,
  417. LPARAM lParam1,
  418. LPARAM lParam2
  419. )
  420. {
  421. LRESULT rv = 0;
  422. // Here, we don't do anything but trace and call DefDriverProc
  423. //
  424. switch (uiMessage)
  425. {
  426. case DRV_LOAD:
  427. TRC(ALV, "DRV_LOAD\n");
  428. rv = 1;
  429. break;
  430. case DRV_FREE:
  431. TRC(ALV, "DRV_FREE\n");
  432. rv = 1;
  433. break;
  434. case DRV_OPEN:
  435. TRC(ALV, "DRV_OPEN\n");
  436. rv = 1;
  437. break;
  438. case DRV_CLOSE:
  439. TRC(ALV, "DRV_CLOSE\n");
  440. rv = 1;
  441. break;
  442. case DRV_ENABLE:
  443. TRC(ALV, "DRV_ENABLE\n");
  444. rv = 1;
  445. break;
  446. case DRV_DISABLE:
  447. TRC(ALV, "DRV_DISABLE\n");
  448. rv = drvDisable();
  449. break;
  450. case DRV_QUERYCONFIGURE:
  451. TRC(ALV, "DRV_QUERYCONFIGURE\n");
  452. rv = 0;
  453. break;
  454. case DRV_CONFIGURE:
  455. TRC(ALV, "DRV_CONFIGURE\n");
  456. rv = 0;
  457. break;
  458. default:
  459. rv = DefDriverProc(
  460. dwDriverID,
  461. hDriver,
  462. uiMessage,
  463. lParam1,
  464. lParam2
  465. );
  466. TRC(ALV, "DRV_UNKNOWN(%d): DefDriverProc returned %d\n",
  467. uiMessage, rv);
  468. }
  469. return rv;
  470. }
  471. VOID
  472. _cdecl
  473. _DebugMessage(
  474. LPCSTR szLevel,
  475. LPCSTR szFormat,
  476. ...
  477. )
  478. {
  479. CHAR szBuffer[256];
  480. va_list arglist;
  481. if (ALV == szLevel)
  482. return;
  483. va_start (arglist, szFormat);
  484. _vsnprintf (szBuffer, RTL_NUMBER_OF(szBuffer), szFormat, arglist);
  485. va_end (arglist);
  486. szBuffer[ RTL_NUMBER_OF( szBuffer ) - 1 ] = 0;
  487. OutputDebugStringA(szLevel);
  488. OutputDebugStringA(szBuffer);
  489. }