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.

5540 lines
143 KiB

  1. /////////////////////////////////////////////////////////////////////
  2. //
  3. // Module: sndchan.c
  4. //
  5. // Purpose: Server-side audio redirection communication
  6. // module
  7. //
  8. // Copyright(C) Microsoft Corporation 2000
  9. //
  10. // History: 4-10-2000 vladimis [created]
  11. //
  12. /////////////////////////////////////////////////////////////////////
  13. #include <windef.h>
  14. #include <winsta.h>
  15. #include <wtsapi32.h>
  16. #include <pchannel.h>
  17. #include <malloc.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <winsock2.h>
  21. #include <mmsystem.h>
  22. #include <mmreg.h>
  23. #include <msacm.h>
  24. #include <aclapi.h>
  25. #include <sha.h>
  26. #include <rc4.h>
  27. #include <rdpstrm.h>
  28. //
  29. // Include security headers for RNG functions
  30. //
  31. #define NO_INCLUDE_LICENSING 1
  32. #include <tssec.h>
  33. #include "sndchan.h"
  34. #include "sndknown.h"
  35. #define TSSND_REG_MAXBANDWIDTH_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32\\Terminal Server\\RDP"
  36. #define TSSND_REG_MAXBANDWIDTH_VAL L"MaxBandwidth"
  37. #define TSSND_REG_MINBANDWIDTH_VAL L"MinBandwidth"
  38. #define TSSND_REG_DISABLEDGRAM_VAL L"DisableDGram"
  39. #define TSSND_REG_ENABLEMP3_VAL L"EnableMP3Codec"
  40. #define TSSND_REG_ALLOWCODECS L"AllowCodecs"
  41. #define TSSND_REG_MAXDGRAM L"MaxDGram"
  42. #define DEFAULT_RESPONSE_TIMEOUT 5000
  43. #define TSSND_TRAINING_BLOCKSIZE 1024
  44. //
  45. // --- READ THIS IF YOU ARE ADDING FEATURES ---
  46. // right now the encryption works only from server to client
  47. // there's no data send from server to client
  48. // if you read this in the future and you are planning to add
  49. // data stream from client to server, PLEASE ENCRYPT IT !!!
  50. // use SL_Encrypt function for that
  51. //
  52. #define MIN_ENCRYPT_LEVEL 2
  53. #define STAT_COUNT 32
  54. #define STAT_COUNT_INIT (STAT_COUNT - 8)
  55. #define READ_EVENT 0
  56. #define DISCONNECT_EVENT 1
  57. #define RECONNECT_EVENT 2
  58. #define DATAREADY_EVENT 3
  59. #define DGRAM_EVENT 4
  60. #define POWERWAKEUP_EVENT 5
  61. #define POWERSUSPEND_EVENT 6
  62. #define TOTAL_EVENTS 7
  63. #define NEW_CODEC_COVER 90 // minimum percentage a new codec has to cover
  64. // i.e if we are at 7kbps and the new meassurement is
  65. // for 10kbps we are not switching to codec which
  66. // does have more than NEW_CODEC_COVER * 10k / 100 bandwith
  67. // requirement
  68. //
  69. // Data for enabling private codecs
  70. // BUGBUG
  71. // Legal issue ?!
  72. //
  73. #ifndef G723MAGICWORD1
  74. #define G723MAGICWORD1 0xf7329ace
  75. #endif
  76. #ifndef G723MAGICWORD2
  77. #define G723MAGICWORD2 0xacdeaea2
  78. #endif
  79. #ifndef VOXWARE_KEY
  80. #define VOXWARE_KEY "35243410-F7340C0668-CD78867B74DAD857-AC71429AD8CAFCB5-E4E1A99E7FFD-371"
  81. #endif
  82. #define _RDPSNDWNDCLASS L"RDPSound window"
  83. #ifdef _WIN32
  84. #include <pshpack1.h>
  85. #else
  86. #ifndef RC_INVOKED
  87. #pragma pack(1)
  88. #endif
  89. #endif
  90. typedef struct msg723waveformat_tag {
  91. WAVEFORMATEX wfx;
  92. WORD wConfigWord;
  93. DWORD dwCodeword1;
  94. DWORD dwCodeword2;
  95. } MSG723WAVEFORMAT;
  96. typedef struct intelg723waveformat_tag {
  97. WAVEFORMATEX wfx;
  98. WORD wConfigWord;
  99. DWORD dwCodeword1;
  100. DWORD dwCodeword2;
  101. } INTELG723WAVEFORMAT;
  102. typedef struct tagVOXACM_WAVEFORMATEX
  103. {
  104. WAVEFORMATEX wfx;
  105. DWORD dwCodecId;
  106. DWORD dwMode;
  107. char szKey[72];
  108. } VOXACM_WAVEFORMATEX, *PVOXACM_WAVEFORMATEX, FAR *LPVOXACM_WAVEFORMATEX;
  109. #define WAVE_FORMAT_WMAUDIO2 0x161
  110. #ifdef _WIN32
  111. #include <poppack.h>
  112. #else
  113. #ifndef RC_INVOKED
  114. #pragma pack()
  115. #endif
  116. #endif
  117. typedef struct {
  118. SNDPROLOG Prolog;
  119. UINT uiPrologReceived;
  120. PVOID pBody;
  121. UINT uiBodyAllocated;
  122. UINT uiBodyReceived;
  123. } SNDMESSAGE, *PSNDMESSAGE;
  124. typedef struct _VCSNDFORMATLIST {
  125. struct _VCSNDFORMATLIST *pNext;
  126. HACMDRIVERID hacmDriverId;
  127. WAVEFORMATEX Format;
  128. // additional data for the format
  129. } VCSNDFORMATLIST, *PVCSNDFORMATLIST;
  130. typedef VOID (*PFNCONVERTER)( INT16 *, DWORD, DWORD * );
  131. static HANDLE g_hVC = NULL; // virtual channel handle
  132. BYTE g_Buffer[CHANNEL_CHUNK_LENGTH]; // receive buffer
  133. UINT g_uiBytesInBuffer = 0; //
  134. UINT g_uiBufferOffset = 0;
  135. OVERLAPPED g_OverlappedRead; // overlapped structure
  136. HANDLE g_hDataReadyEvent = NULL; // set by the client apps
  137. HANDLE g_hStreamIsEmptyEvent = NULL; // set by this code
  138. HANDLE g_hStreamMutex = NULL; // guard the stream data
  139. HANDLE g_hStream = NULL; // stream handle
  140. HANDLE g_hDisconnectEvent = NULL; // set for this VC
  141. PSNDSTREAM g_Stream; // stream data pointer
  142. BOOL g_bRunning = TRUE; // TRUE if running
  143. BOOL g_bDeviceOpened = FALSE; // TRUE if device opened
  144. BOOL g_bDisconnected = FALSE; // TRUE if disconnected
  145. DWORD g_dwLineBandwidth = 0; // current bandwidth
  146. DWORD g_dwCodecChangeThreshold = 10; // how mach the bandwith has to change in order
  147. // to change the codec ( in percents )
  148. // this number changes up to 50%
  149. PSNDFORMATITEM *g_ppNegotiatedFormats = NULL; // list of formats
  150. DWORD g_dwNegotiatedFormats = 0; // number of formats
  151. DWORD g_dwCurrentFormat = 0; // current format Id
  152. HACMDRIVERID g_hacmDriverId = NULL; // codec handles
  153. HACMDRIVER g_hacmDriver = NULL;
  154. HACMSTREAM g_hacmStream = NULL;
  155. PFNCONVERTER g_pfnConverter = NULL; // intermidiate converter
  156. DWORD g_dwDataRemain = 0;
  157. BYTE g_pCnvPrevData[ TSSND_BLOCKSIZE ];
  158. PVCSNDFORMATLIST g_pAllCodecsFormatList = NULL; // all available codecs
  159. DWORD g_dwAllCodecsNumber = 0;
  160. DWORD g_dwMaxBandwidth = (DWORD) -1; // options
  161. DWORD g_dwMinBandwidth = 0;
  162. DWORD g_dwDisableDGram = 0;
  163. DWORD g_dwEnableMP3Codec = 0;
  164. DWORD *g_AllowCodecs = NULL;
  165. DWORD g_AllowCodecsSize = 0;
  166. DWORD g_dwStatPing = 0; // statistics
  167. DWORD g_dwStatLatency = 0;
  168. DWORD g_dwBlocksOnTheNet = TSSND_BLOCKSONTHENET;
  169. DWORD g_dwStatCount = STAT_COUNT_INIT;
  170. DWORD g_dwPacketSize = 0;
  171. HANDLE g_hPowerWakeUpEvent = NULL; // power events
  172. HANDLE g_hPowerSuspendEvent = NULL;
  173. BOOL g_bSuspended = FALSE;
  174. BOOL g_bDeviceFailed = FALSE;
  175. //
  176. // datagram control
  177. //
  178. SOCKET g_hDGramSocket = INVALID_SOCKET;
  179. DWORD g_dwDGramPort = 0;
  180. DWORD g_dwDGramSize = 1460; // number good which is ok for LAN
  181. u_long g_ulDGramAddress = 0;
  182. DWORD g_EncryptionLevel = 3;
  183. DWORD g_wClientVersion = 0;
  184. DWORD g_HiBlockNo = 0;
  185. BYTE g_EncryptKey[RANDOM_KEY_LENGTH + 4];
  186. WSABUF g_wsabuf;
  187. BYTE g_pDGramRecvData[128];
  188. WSAOVERLAPPED g_WSAOverlapped;
  189. const CHAR *ALV = "TSSNDD::ALV - ";
  190. const CHAR *INF = "TSSNDD::INF - ";
  191. const CHAR *WRN = "TSSNDD::WRN - ";
  192. const CHAR *ERR = "TSSNDD::ERR - ";
  193. const CHAR *FATAL = "TSSNDD::FATAL - ";
  194. static HANDLE g_hThread = NULL;
  195. //
  196. // internal functions
  197. //
  198. BOOL
  199. ChannelBlockWrite(
  200. PVOID pBlock,
  201. ULONG ulBlockSize
  202. );
  203. BOOL
  204. VCSndAcquireStream(
  205. VOID
  206. );
  207. BOOL
  208. VCSndReleaseStream(
  209. VOID
  210. );
  211. BOOL
  212. _VCSndOpenConverter(
  213. VOID
  214. );
  215. VOID
  216. _VCSndCloseConverter(
  217. VOID
  218. );
  219. VOID
  220. _VCSndOrderFormatList(
  221. PVCSNDFORMATLIST *ppFormatList,
  222. DWORD *pdwNum
  223. );
  224. DWORD
  225. _VCSndChooseProperFormat(
  226. DWORD dwBandwidth
  227. );
  228. BOOL
  229. _VCSndGetACMDriverId(
  230. PSNDFORMATITEM pSndFmt
  231. );
  232. VOID
  233. DGramRead(
  234. HANDLE hDGramEvent,
  235. PVOID *ppBuff,
  236. DWORD *pdwRecvd
  237. );
  238. VOID
  239. DGramReadComplete(
  240. PVOID *ppBuff,
  241. DWORD *pdwRecvd
  242. );
  243. #if !( TSSND_NATIVE_SAMPLERATE - 22050 )
  244. //
  245. // converters
  246. // convert to the native format
  247. //
  248. #define CONVERTFROMNATIVETOMONO(_speed_) \
  249. VOID \
  250. _Convert##_speed_##Mono( \
  251. INT16 *pSrc, \
  252. DWORD dwSrcSize, \
  253. DWORD *pdwDstSize ) \
  254. { \
  255. DWORD dwDstSize; \
  256. DWORD i; \
  257. DWORD dwLeap; \
  258. INT16 *pDest = pSrc; \
  259. \
  260. ASSERT( TSSND_NATIVE_SAMPLERATE >= _speed_ ); \
  261. ASSERT( TSSND_NATIVE_CHANNELS == 2 ); \
  262. \
  263. dwDstSize = dwSrcSize * _speed_ / \
  264. ( TSSND_NATIVE_BLOCKALIGN * TSSND_NATIVE_SAMPLERATE ); \
  265. \
  266. for (i = 0, dwLeap = 0; \
  267. i < dwDstSize; \
  268. i ++) \
  269. { \
  270. INT sum; \
  271. \
  272. sum = pSrc[0] + pSrc[1]; \
  273. \
  274. if (sum > 0x7FFF) \
  275. sum = 0x7FFF; \
  276. if (sum < -0x8000) \
  277. sum = -0x8000; \
  278. \
  279. pDest[0] = (INT16)sum; \
  280. pDest ++; \
  281. \
  282. dwLeap += 2 * TSSND_NATIVE_SAMPLERATE; \
  283. pSrc += dwLeap / _speed_; \
  284. dwLeap %= _speed_; \
  285. } \
  286. \
  287. *pdwDstSize = dwDstSize * 2; \
  288. }
  289. #define CONVERTFROMNATIVETOSTEREO(_speed_) \
  290. VOID \
  291. _Convert##_speed_##Stereo( \
  292. INT16 *pSrc, \
  293. DWORD dwSrcSize, \
  294. DWORD *pdwDstSize ) \
  295. { \
  296. DWORD dwDstSize; \
  297. DWORD i; \
  298. DWORD dwLeap; \
  299. INT16 *pDest = pSrc; \
  300. \
  301. ASSERT( TSSND_NATIVE_SAMPLERATE >= _speed_ ); \
  302. \
  303. dwDstSize = dwSrcSize * _speed_ / \
  304. ( TSSND_NATIVE_BLOCKALIGN * TSSND_NATIVE_SAMPLERATE ); \
  305. for (i = 0, dwLeap = 0; \
  306. i < dwDstSize; \
  307. i ++) \
  308. { \
  309. INT sum; \
  310. \
  311. pDest[0] = pSrc[0]; \
  312. pDest ++; \
  313. pDest[0] = pSrc[1]; \
  314. pDest ++; \
  315. \
  316. dwLeap += 2 * TSSND_NATIVE_SAMPLERATE; \
  317. pSrc += dwLeap / _speed_; \
  318. dwLeap %= _speed_; \
  319. } \
  320. \
  321. *pdwDstSize = dwDstSize * 4; \
  322. }
  323. VOID
  324. _Convert11025Mono(
  325. INT16 *pSrc,
  326. DWORD dwSrcSize,
  327. DWORD *pdwDstSize )
  328. {
  329. DWORD dwDstSize;
  330. INT16 *pDest = pSrc;
  331. ASSERT( TSSND_NATIVE_SAMPLERATE >= 11025 );
  332. dwDstSize = dwSrcSize / ( TSSND_NATIVE_BLOCKALIGN * 2 );
  333. *pdwDstSize = 2 * dwDstSize;
  334. for (; dwDstSize; dwDstSize --)
  335. {
  336. INT sum = pSrc[0] + pSrc[1];
  337. if (sum > 0x7FFF)
  338. sum = 0x7FFF;
  339. if (sum < -0x8000)
  340. sum = -0x8000;
  341. pDest[0] = (INT16)sum;
  342. pDest ++;
  343. pSrc += 4;
  344. }
  345. }
  346. VOID
  347. _Convert22050Mono(
  348. INT16 *pSrc,
  349. DWORD dwSrcSize,
  350. DWORD *pdwDstSize )
  351. {
  352. DWORD dwDstSize;
  353. INT16 *pDest = pSrc;
  354. ASSERT( TSSND_NATIVE_SAMPLERATE >= 22050 );
  355. dwDstSize = dwSrcSize / ( TSSND_NATIVE_BLOCKALIGN );
  356. *pdwDstSize = 2 * dwDstSize;
  357. for (; dwDstSize; dwDstSize --)
  358. {
  359. INT sum = pSrc[0] + pSrc[1];
  360. if (sum > 0x7FFF)
  361. sum = 0x7FFF;
  362. if (sum < -0x8000)
  363. sum = -0x8000;
  364. pDest[0] = (INT16)sum;
  365. pDest ++;
  366. pSrc += 2;
  367. }
  368. }
  369. VOID
  370. _Convert11025Stereo(
  371. INT16 *pSrc,
  372. DWORD dwSrcSize,
  373. DWORD *pdwDstSize )
  374. {
  375. DWORD dwDstSize;
  376. INT16 *pDest = pSrc;
  377. ASSERT( TSSND_NATIVE_SAMPLERATE >= 22050 );
  378. dwDstSize = dwSrcSize / ( TSSND_NATIVE_BLOCKALIGN * 2 );
  379. *pdwDstSize = 4 * dwDstSize;
  380. for (; dwDstSize; dwDstSize --)
  381. {
  382. pDest[0] = pSrc[0];
  383. pSrc ++;
  384. pDest ++;
  385. pDest[0] = pSrc[0];
  386. pDest ++;
  387. pSrc ++;
  388. pSrc += 2;
  389. }
  390. }
  391. //
  392. // Make the actual code
  393. //
  394. CONVERTFROMNATIVETOMONO( 8000 )
  395. CONVERTFROMNATIVETOMONO( 12000 )
  396. CONVERTFROMNATIVETOMONO( 16000 )
  397. CONVERTFROMNATIVETOSTEREO( 8000 )
  398. CONVERTFROMNATIVETOSTEREO( 12000 )
  399. CONVERTFROMNATIVETOSTEREO( 16000 )
  400. #else
  401. #pragma error
  402. #endif
  403. u_long
  404. inet_addrW(
  405. LPCWSTR szAddressW
  406. )
  407. {
  408. CHAR szAddressA[32];
  409. *szAddressA = 0;
  410. WideCharToMultiByte(
  411. CP_ACP,
  412. 0,
  413. szAddressW,
  414. -1,
  415. szAddressA,
  416. sizeof(szAddressA),
  417. NULL, NULL);
  418. return inet_addr(szAddressA);
  419. }
  420. /*
  421. * create signature bits
  422. */
  423. VOID
  424. SL_Signature(
  425. PBYTE pSig,
  426. DWORD dwBlockNo
  427. )
  428. {
  429. BYTE ShaBits[A_SHA_DIGEST_LEN];
  430. A_SHA_CTX SHACtx;
  431. ASSERT( A_SHA_DIGEST_LEN > RDPSND_SIGNATURE_SIZE );
  432. A_SHAInit(&SHACtx);
  433. *((DWORD *)(g_EncryptKey + RANDOM_KEY_LENGTH)) = dwBlockNo;
  434. A_SHAUpdate(&SHACtx, (PBYTE)g_EncryptKey, sizeof(g_EncryptKey));
  435. A_SHAFinal(&SHACtx, ShaBits);
  436. memcpy( pSig, ShaBits, RDPSND_SIGNATURE_SIZE );
  437. }
  438. /*
  439. * signature which verifies the audio bits
  440. */
  441. VOID
  442. SL_AudioSignature(
  443. PBYTE pSig,
  444. DWORD dwBlockNo,
  445. PBYTE pData,
  446. DWORD dwDataSize
  447. )
  448. {
  449. BYTE ShaBits[A_SHA_DIGEST_LEN];
  450. A_SHA_CTX SHACtx;
  451. A_SHAInit(&SHACtx);
  452. *((DWORD *)(g_EncryptKey + RANDOM_KEY_LENGTH)) = dwBlockNo;
  453. A_SHAUpdate(&SHACtx, (PBYTE)g_EncryptKey, sizeof(g_EncryptKey));
  454. A_SHAUpdate(&SHACtx, pData, dwDataSize );
  455. A_SHAFinal(&SHACtx, ShaBits);
  456. memcpy( pSig, ShaBits, RDPSND_SIGNATURE_SIZE );
  457. }
  458. /*
  459. * encrypt/decrypt a block of data
  460. *
  461. */
  462. BOOL
  463. SL_Encrypt( PBYTE pBits, DWORD BlockNo, DWORD dwBitsLen )
  464. {
  465. BYTE ShaBits[A_SHA_DIGEST_LEN];
  466. RC4_KEYSTRUCT rc4key;
  467. DWORD i;
  468. PBYTE pbBuffer;
  469. A_SHA_CTX SHACtx;
  470. DWORD dw;
  471. DWORD_PTR *pdwBits;
  472. A_SHAInit(&SHACtx);
  473. // SHA the bits
  474. *((DWORD *)(g_EncryptKey + RANDOM_KEY_LENGTH)) = BlockNo;
  475. A_SHAUpdate(&SHACtx, (PBYTE)g_EncryptKey, sizeof(g_EncryptKey));
  476. A_SHAFinal(&SHACtx, ShaBits);
  477. rc4_key(&rc4key, A_SHA_DIGEST_LEN, ShaBits);
  478. rc4(&rc4key, dwBitsLen, pBits);
  479. return TRUE;
  480. }
  481. BOOL
  482. SL_SendKey( VOID )
  483. {
  484. SNDCRYPTKEY Key;
  485. Key.Prolog.Type = SNDC_CRYPTKEY;
  486. Key.Prolog.BodySize = sizeof( Key ) - sizeof( Key.Prolog );
  487. Key.Reserved = 0;
  488. memcpy( Key.Seed, g_EncryptKey, sizeof( Key.Seed ));
  489. return ChannelBlockWrite( &Key, sizeof( Key ));
  490. }
  491. /*
  492. * Function:
  493. * _StatsCollect
  494. *
  495. * Description:
  496. * Collects statistics for the line quality
  497. *
  498. */
  499. VOID
  500. _StatsCollect(
  501. DWORD dwTimeStamp
  502. )
  503. {
  504. DWORD dwTimeDiff;
  505. #if _DBG_STATS
  506. TRC(INF, "_StatsCollect: time now=%x, stamp=%x\n",
  507. GetTickCount() & 0xffff,
  508. dwTimeStamp);
  509. #endif
  510. dwTimeDiff = (( GetTickCount() & 0xffff ) - dwTimeStamp ) & 0xffff;
  511. // it is possible to receive time stamp
  512. // with time before the packet was sent,
  513. // this is because the client does adjusments to the time stamp
  514. // i.e. subtracts the time when the packet was played
  515. // catch and ignore this case
  516. //
  517. if ( dwTimeDiff > 0xf000 )
  518. {
  519. dwTimeDiff = 1;
  520. }
  521. if ( 0 == dwTimeDiff )
  522. dwTimeDiff = 1;
  523. if ( 0 == g_dwStatLatency )
  524. g_dwStatLatency = dwTimeDiff;
  525. else {
  526. //
  527. // increase by 30%
  528. //
  529. g_dwStatLatency = (( 7 * g_dwStatLatency ) + ( 3 * dwTimeDiff )) / 10;
  530. }
  531. g_dwStatCount ++;
  532. }
  533. /*
  534. * Function:
  535. * _StatsSendPing
  536. *
  537. * Description:
  538. * Sends a ping packet to the client
  539. *
  540. */
  541. VOID
  542. _StatSendPing(
  543. VOID
  544. )
  545. {
  546. //
  547. // send a ping request
  548. //
  549. SNDTRAINING SndTraining;
  550. SndTraining.Prolog.Type = SNDC_TRAINING;
  551. SndTraining.Prolog.BodySize = sizeof( SndTraining ) -
  552. sizeof( SndTraining.Prolog );
  553. SndTraining.wTimeStamp = (UINT16)GetTickCount();
  554. SndTraining.wPackSize = 0;
  555. if ( INVALID_SOCKET != g_hDGramSocket &&
  556. 0 != g_dwDGramPort &&
  557. 0 != g_ulDGramAddress
  558. )
  559. {
  560. struct sockaddr_in sin;
  561. INT rc;
  562. sin.sin_family = PF_INET;
  563. sin.sin_port = (u_short)g_dwDGramPort;
  564. sin.sin_addr.s_addr = g_ulDGramAddress;
  565. rc = sendto(
  566. g_hDGramSocket,
  567. (LPSTR)&SndTraining,
  568. sizeof( SndTraining ),
  569. 0,
  570. (struct sockaddr *)&sin, // to address
  571. sizeof(sin)
  572. );
  573. if (SOCKET_ERROR == rc)
  574. {
  575. TRC(ERR, "_StatsSendPing: sendto failed: %d\n",
  576. WSAGetLastError());
  577. }
  578. } else {
  579. BOOL bSuccess;
  580. bSuccess = ChannelBlockWrite( &SndTraining, sizeof( SndTraining ));
  581. if (!bSuccess)
  582. {
  583. TRC(ERR, "_StatSendPing: ChannelBlockWrite failed: %d\n",
  584. GetLastError());
  585. }
  586. }
  587. }
  588. /*
  589. * Function:
  590. * _StatsCheckResample
  591. *
  592. * Description:
  593. * Looks in the statistics and eventually changes the current
  594. * codec
  595. */
  596. BOOL
  597. _StatsCheckResample(
  598. VOID
  599. )
  600. {
  601. BOOL rv = FALSE;
  602. DWORD dwNewFmt;
  603. DWORD dwNewLatency;
  604. DWORD dwNewBandwidth;
  605. DWORD dwLatDiff;
  606. DWORD dwMsPerBlock;
  607. DWORD dwBlocksOnTheNet;
  608. DWORD dwCurrBandwith;
  609. if (( g_dwStatCount % STAT_COUNT ) == STAT_COUNT / 2 )
  610. _StatSendPing();
  611. if ( g_dwStatCount < STAT_COUNT )
  612. goto exitpt;
  613. if ( g_dwStatPing >= g_dwStatLatency )
  614. g_dwStatPing = g_dwStatLatency - 1;
  615. dwNewLatency = ( g_dwStatLatency - g_dwStatPing / 2 );
  616. if ( 0 == g_dwPacketSize )
  617. {
  618. TRC(INF, "_StatsCheckResample: invalid packet size\n");
  619. goto resetpt;
  620. }
  621. dwNewBandwidth = g_dwPacketSize * 1000 / dwNewLatency;
  622. if ( 0 == dwNewBandwidth )
  623. {
  624. TRC(INF, "_StatsCheckResample: invalid bandwidth\n");
  625. goto resetpt;
  626. }
  627. TRC(INF, "_StatsCheckResample: latency=%d, bandwidth=%d\n",
  628. dwNewLatency, dwNewBandwidth );
  629. //
  630. // g_dwBlocksOnTheNet is the latency in number of blocks
  631. //
  632. dwMsPerBlock = TSSND_BLOCKSIZE * 1000 / TSSND_NATIVE_AVGBYTESPERSEC;
  633. dwBlocksOnTheNet = ((g_dwStatLatency + dwMsPerBlock / 2) / dwMsPerBlock + 2);
  634. if ( dwBlocksOnTheNet > TSSND_BLOCKSONTHENET )
  635. {
  636. g_dwBlocksOnTheNet = TSSND_BLOCKSONTHENET;
  637. } else {
  638. g_dwBlocksOnTheNet = dwBlocksOnTheNet;
  639. }
  640. TRC( INF, "BlocksOnTheNet=%d\n", g_dwBlocksOnTheNet );
  641. //
  642. // check for at least 10% difference in the bandwidth
  643. //
  644. if ( dwNewBandwidth > g_dwMaxBandwidth )
  645. dwNewBandwidth = g_dwMaxBandwidth;
  646. if ( dwNewBandwidth < g_dwMinBandwidth )
  647. dwNewBandwidth = g_dwMinBandwidth;
  648. dwCurrBandwith = ( NULL != g_ppNegotiatedFormats[ g_dwCurrentFormat ] )?
  649. g_ppNegotiatedFormats[ g_dwCurrentFormat ]->nAvgBytesPerSec:
  650. g_dwLineBandwidth;
  651. if ( dwCurrBandwith > dwNewBandwidth )
  652. dwLatDiff = dwCurrBandwith - dwNewBandwidth;
  653. else
  654. dwLatDiff = dwNewBandwidth - dwCurrBandwith;
  655. if ( dwLatDiff < g_dwCodecChangeThreshold * dwCurrBandwith / 100 )
  656. goto resetpt;
  657. //
  658. // increment the threshold up to 50%
  659. //
  660. if ( g_dwCodecChangeThreshold < 50 )
  661. {
  662. g_dwCodecChangeThreshold += 5;
  663. }
  664. //
  665. // try to choose another format
  666. //
  667. dwNewFmt = _VCSndChooseProperFormat( dwNewBandwidth );
  668. if ( (DWORD)-1 != dwNewFmt &&
  669. dwNewFmt != g_dwCurrentFormat )
  670. {
  671. INT step;
  672. DWORD dwNextFmt;
  673. //
  674. // don't jump directly to the new format, just move
  675. // towards it
  676. //
  677. step = ( dwNewFmt > g_dwCurrentFormat )?1:-1;
  678. dwNextFmt = g_dwCurrentFormat + step;
  679. while( dwNextFmt != dwNewFmt &&
  680. NULL == g_ppNegotiatedFormats[dwNextFmt] )
  681. {
  682. dwNextFmt += step;
  683. }
  684. dwNewFmt = dwNextFmt;
  685. }
  686. if ( dwNewFmt == (DWORD)-1 ||
  687. dwNewFmt == g_dwCurrentFormat )
  688. goto resetpt;
  689. TRC(INF, "_StatsCheckResample: new bandwidth=%d resampling\n",
  690. dwNewBandwidth);
  691. //
  692. // resample, NOW
  693. //
  694. _VCSndCloseConverter();
  695. if ( _VCSndGetACMDriverId( g_ppNegotiatedFormats[dwNewFmt] ))
  696. {
  697. g_dwLineBandwidth = dwNewBandwidth;
  698. g_dwCurrentFormat = dwNewFmt;
  699. g_dwDataRemain = 0;
  700. }
  701. _VCSndOpenConverter();
  702. rv = TRUE;
  703. resetpt:
  704. g_dwStatLatency = 0;
  705. g_dwStatCount = 0;
  706. exitpt:
  707. return rv;
  708. }
  709. /*
  710. * Function:
  711. * _StatReset
  712. *
  713. * Description:
  714. * Resets the statistics
  715. *
  716. */
  717. VOID
  718. _StatReset(
  719. VOID
  720. )
  721. {
  722. g_dwStatLatency = 0;
  723. g_dwStatPing = 0;
  724. g_dwStatCount = STAT_COUNT_INIT;
  725. }
  726. /*
  727. * Function:
  728. * ChannelOpen
  729. *
  730. * Description:
  731. * Opens the virtual channel
  732. *
  733. *
  734. */
  735. BOOL
  736. ChannelOpen(
  737. VOID
  738. )
  739. {
  740. BOOL rv = FALSE;
  741. if (!g_hVC)
  742. g_hVC = WinStationVirtualOpen(
  743. NULL,
  744. LOGONID_CURRENT,
  745. _SNDVC_NAME
  746. );
  747. rv = (g_hVC != NULL);
  748. return rv;
  749. }
  750. /*
  751. * Function:
  752. * ChannelClose
  753. *
  754. * Description:
  755. * Closes the virtual channel
  756. */
  757. VOID
  758. ChannelClose(
  759. VOID
  760. )
  761. {
  762. if (g_hVC)
  763. {
  764. CloseHandle(g_hVC);
  765. g_hVC = NULL;
  766. }
  767. g_uiBytesInBuffer = 0;
  768. g_uiBufferOffset = 0;
  769. }
  770. /*
  771. * Function:
  772. * ChannelBlockWrite
  773. *
  774. * Description:
  775. * Writes a block thru the virtual channel
  776. *
  777. */
  778. BOOL
  779. ChannelBlockWrite(
  780. PVOID pBlock,
  781. ULONG ulBlockSize
  782. )
  783. {
  784. BOOL bSuccess = TRUE;
  785. PCHAR pData = (PCHAR) pBlock;
  786. ULONG ulBytesWritten;
  787. ULONG ulBytesToWrite = ulBlockSize;
  788. HANDLE hVC;
  789. hVC = g_hVC;
  790. if (!hVC)
  791. {
  792. TRC(ERR, "ChannelBlockWrite: vc handle is NULL\n");
  793. bSuccess = FALSE;
  794. goto exitpt;
  795. }
  796. while (bSuccess && ulBytesToWrite)
  797. {
  798. OVERLAPPED Overlapped;
  799. Overlapped.hEvent = NULL;
  800. Overlapped.Offset = 0;
  801. Overlapped.OffsetHigh = 0;
  802. bSuccess = WriteFile(
  803. hVC,
  804. pData,
  805. ulBytesToWrite,
  806. &ulBytesWritten,
  807. &Overlapped
  808. );
  809. if (!bSuccess && ERROR_IO_PENDING == GetLastError())
  810. bSuccess = GetOverlappedResult(
  811. hVC,
  812. &Overlapped,
  813. &ulBytesWritten,
  814. TRUE);
  815. if (bSuccess)
  816. {
  817. TRC(ALV, "VirtualChannelWrite: Wrote %d bytes\n",
  818. ulBytesWritten);
  819. ulBytesToWrite -= ulBytesWritten;
  820. pData += ulBytesWritten;
  821. } else {
  822. TRC(ERR, "VirtualChannelWrite failed, GetLastError=%d\n",
  823. GetLastError());
  824. }
  825. }
  826. exitpt:
  827. return bSuccess;
  828. }
  829. /*
  830. * Function:
  831. * ChannelMessageWrite
  832. *
  833. * Description:
  834. * Writes a two pieces message as a single one (uses ChannelBlockWrite)
  835. *
  836. */
  837. BOOL
  838. ChannelMessageWrite(
  839. PVOID pProlog,
  840. ULONG ulPrologSize,
  841. PVOID pBody,
  842. ULONG ulBodySize
  843. )
  844. {
  845. BOOL rv = FALSE;
  846. if ( 0 != ulBodySize )
  847. {
  848. //
  849. // create a new prolog message
  850. // in which a UINT32 word is added at the end
  851. // this word is the same as the first word of the prolog
  852. // the client is aware of this and will reconstruct
  853. // to the correct messages
  854. //
  855. PVOID pNewProlog;
  856. __try {
  857. pNewProlog = alloca( ulPrologSize + sizeof(UINT32) );
  858. } __except((EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) ?
  859. EXCEPTION_EXECUTE_HANDLER :
  860. EXCEPTION_CONTINUE_SEARCH)
  861. {
  862. _resetstkoflw();
  863. pNewProlog = NULL;
  864. }
  865. if ( NULL == pNewProlog )
  866. {
  867. TRC(ERR, "ChannelMessageWrite: alloca failed for %d bytes\n",
  868. ulPrologSize + sizeof(UINT32) );
  869. goto exitpt;
  870. }
  871. memcpy(pNewProlog, pProlog, ulPrologSize);
  872. // replace the word, put SNDC_NONE in the body
  873. //
  874. ASSERT( ulBodySize >= sizeof(UINT32));
  875. *(DWORD *)(((LPSTR)pNewProlog) + ulPrologSize) =
  876. *(DWORD *)pBody;
  877. *(DWORD *)pBody = SNDC_NONE;
  878. pProlog = pNewProlog;
  879. ulPrologSize += sizeof(UINT32);
  880. }
  881. rv = ChannelBlockWrite(
  882. pProlog,
  883. ulPrologSize
  884. );
  885. if (!rv)
  886. {
  887. TRC(ERR, "ChannelMessageWrite: failed while sending the prolog\n");
  888. goto exitpt;
  889. }
  890. rv = ChannelBlockWrite(
  891. pBody,
  892. ulBodySize
  893. );
  894. if (!rv)
  895. {
  896. TRC(ERR, "ChannelMessageWrite: failed while sending the body\n");
  897. }
  898. exitpt:
  899. return rv;
  900. }
  901. /*
  902. * Function:
  903. * ChannelBlockRead
  904. *
  905. * Description:
  906. * Read a block, as much as possible
  907. *
  908. */
  909. BOOL
  910. ChannelBlockRead(
  911. PVOID pBlock,
  912. ULONG ulBlockSize,
  913. ULONG *pulBytesRead,
  914. ULONG ulTimeout,
  915. HANDLE hEvent
  916. )
  917. {
  918. BOOL bSuccess = FALSE;
  919. PCHAR pData = (PCHAR) pBlock;
  920. ULONG ulBytesRead = 0;
  921. HANDLE hVC;
  922. hVC = g_hVC;
  923. if (NULL == hVC)
  924. {
  925. TRC(ERR, "ChannelBlockRead: vc handle is invalid(NULL)\n");
  926. goto exitpt;
  927. }
  928. if (NULL == pulBytesRead)
  929. {
  930. TRC(ERR, "ChannelBlockRead: pulBytesRead is NULL\n");
  931. goto exitpt;
  932. }
  933. if (!g_uiBytesInBuffer)
  934. {
  935. g_OverlappedRead.hEvent = hEvent;
  936. g_OverlappedRead.Offset = 0;
  937. g_OverlappedRead.OffsetHigh = 0;
  938. bSuccess = ReadFile(
  939. hVC,
  940. g_Buffer,
  941. sizeof(g_Buffer),
  942. (LPDWORD) &g_uiBytesInBuffer,
  943. &g_OverlappedRead
  944. );
  945. if (ERROR_IO_PENDING == GetLastError())
  946. {
  947. bSuccess = FALSE;
  948. goto exitpt;
  949. }
  950. if (!bSuccess)
  951. {
  952. TRC(ERR, "VirtualChannelRead failed, "
  953. "GetLastError=%d\n",
  954. GetLastError());
  955. g_uiBytesInBuffer = 0;
  956. } else {
  957. TRC(ALV, "VirtualChannelRead: read %d bytes\n",
  958. g_uiBytesInBuffer);
  959. SetLastError(ERROR_SUCCESS);
  960. }
  961. }
  962. if (g_uiBytesInBuffer)
  963. {
  964. ulBytesRead = (g_uiBytesInBuffer < ulBlockSize)
  965. ? g_uiBytesInBuffer : ulBlockSize;
  966. memcpy(pData, g_Buffer + g_uiBufferOffset, ulBytesRead);
  967. g_uiBufferOffset += ulBytesRead;
  968. g_uiBytesInBuffer -= ulBytesRead;
  969. bSuccess = TRUE;
  970. }
  971. // if the buffer is completed, zero the offset
  972. //
  973. if (0 == g_uiBytesInBuffer)
  974. g_uiBufferOffset = 0;
  975. TRC(ALV, "ChannelBlockRead: block size %d was read\n", ulBlockSize);
  976. exitpt:
  977. if (NULL != pulBytesRead)
  978. *pulBytesRead = ulBytesRead;
  979. return bSuccess;
  980. }
  981. /*
  982. * Function:
  983. * ChannelBlockReadComplete
  984. *
  985. * Description:
  986. * Read completion
  987. *
  988. */
  989. BOOL
  990. ChannelBlockReadComplete(
  991. VOID
  992. )
  993. {
  994. BOOL bSuccess = FALSE;
  995. if (!g_hVC)
  996. {
  997. TRC(ERR, "ChannelBlockReadComplete: vc handle is invalid(NULL)\n");
  998. goto exitpt;
  999. }
  1000. bSuccess = GetOverlappedResult(
  1001. g_hVC,
  1002. &g_OverlappedRead,
  1003. (LPDWORD) &g_uiBytesInBuffer,
  1004. FALSE
  1005. );
  1006. if (bSuccess)
  1007. {
  1008. TRC(ALV, "VirtualChannelRead: read %d bytes\n",
  1009. g_uiBytesInBuffer);
  1010. ;
  1011. } else {
  1012. TRC(ERR, "GetOverlappedResult failed, "
  1013. "GetLastError=%d\n",
  1014. GetLastError());
  1015. }
  1016. exitpt:
  1017. return bSuccess;
  1018. }
  1019. /*
  1020. * Function:
  1021. * ChannelCancelIo
  1022. *
  1023. * Description:
  1024. * Cancel the current IO
  1025. *
  1026. */
  1027. BOOL
  1028. ChannelCancelIo(
  1029. VOID
  1030. )
  1031. {
  1032. BOOL rv = FALSE;
  1033. if (!g_hVC)
  1034. {
  1035. TRC(ERR, "ChannelCancelIo: vc handle is invalid(NULL)\n");
  1036. goto exitpt;
  1037. }
  1038. rv = CancelIo(g_hVC);
  1039. if (rv)
  1040. SetLastError(ERROR_IO_INCOMPLETE);
  1041. exitpt:
  1042. return rv;
  1043. }
  1044. /*
  1045. * Function:
  1046. * ChannelReceiveMessage
  1047. *
  1048. * Description:
  1049. * Attempts to read two piece message,
  1050. * returns TRUE if the whole message is received
  1051. *
  1052. */
  1053. BOOL
  1054. ChannelReceiveMessage(
  1055. PSNDMESSAGE pSndMessage,
  1056. HANDLE hReadEvent
  1057. )
  1058. {
  1059. BOOL rv = FALSE;
  1060. HANDLE hVC = g_hVC;
  1061. UINT uiBytesReceived = 0;
  1062. ASSERT( NULL != pSndMessage );
  1063. ASSERT( NULL != hReadEvent );
  1064. if (NULL == hVC)
  1065. {
  1066. TRC(ERR, "ChannelReceiveMessage: VC is NULL\n");
  1067. goto exitpt;
  1068. }
  1069. //
  1070. // loop until PENDING or message is received
  1071. //
  1072. do {
  1073. if (pSndMessage->uiPrologReceived < sizeof(pSndMessage->Prolog))
  1074. {
  1075. if (ChannelBlockRead(
  1076. ((LPSTR)(&pSndMessage->Prolog)) +
  1077. pSndMessage->uiPrologReceived,
  1078. sizeof(pSndMessage->Prolog) -
  1079. pSndMessage->uiPrologReceived,
  1080. (ULONG*) &uiBytesReceived,
  1081. DEFAULT_VC_TIMEOUT,
  1082. hReadEvent
  1083. ))
  1084. {
  1085. pSndMessage->uiPrologReceived += uiBytesReceived;
  1086. }
  1087. else
  1088. {
  1089. if (ERROR_IO_PENDING != GetLastError())
  1090. {
  1091. // Perform cleanup
  1092. //
  1093. pSndMessage->uiPrologReceived = 0;
  1094. }
  1095. goto exitpt;
  1096. }
  1097. }
  1098. // Reallocate a new body if needed
  1099. //
  1100. if (pSndMessage->uiBodyAllocated < pSndMessage->Prolog.BodySize)
  1101. {
  1102. PVOID pBody;
  1103. pBody = (NULL == pSndMessage->pBody)?
  1104. TSMALLOC(pSndMessage->Prolog.BodySize):
  1105. TSREALLOC(pSndMessage->pBody,
  1106. pSndMessage->Prolog.BodySize);
  1107. if ( NULL == pBody && NULL != pSndMessage->pBody )
  1108. {
  1109. TSFREE( pSndMessage->pBody );
  1110. }
  1111. pSndMessage->pBody = pBody;
  1112. if (!pSndMessage->pBody)
  1113. {
  1114. TRC(ERR, "ChannelMessageRead: can't allocate %d bytes\n",
  1115. pSndMessage->Prolog.BodySize);
  1116. pSndMessage->uiBodyAllocated = 0;
  1117. goto exitpt;
  1118. } else
  1119. pSndMessage->uiBodyAllocated = pSndMessage->Prolog.BodySize;
  1120. }
  1121. // Receive the body
  1122. //
  1123. if (pSndMessage->uiBodyReceived < pSndMessage->Prolog.BodySize)
  1124. {
  1125. if (ChannelBlockRead(
  1126. ((LPSTR)(pSndMessage->pBody)) + pSndMessage->uiBodyReceived,
  1127. pSndMessage->Prolog.BodySize - pSndMessage->uiBodyReceived,
  1128. (ULONG*) &uiBytesReceived,
  1129. DEFAULT_VC_TIMEOUT,
  1130. hReadEvent
  1131. ))
  1132. {
  1133. pSndMessage->uiBodyReceived += uiBytesReceived;
  1134. }
  1135. else
  1136. {
  1137. if (ERROR_IO_PENDING != GetLastError())
  1138. {
  1139. // Perform cleanup
  1140. //
  1141. pSndMessage->uiPrologReceived = 0;
  1142. pSndMessage->uiBodyReceived = 0;
  1143. }
  1144. goto exitpt;
  1145. }
  1146. }
  1147. // check if the message is received
  1148. //
  1149. } while (pSndMessage->uiBodyReceived != pSndMessage->Prolog.BodySize);
  1150. rv = TRUE;
  1151. exitpt:
  1152. return rv;
  1153. }
  1154. /*
  1155. * Function:
  1156. * VCSndDataArrived
  1157. *
  1158. * Description:
  1159. * Arrived message demultiplexer
  1160. *
  1161. */
  1162. VOID
  1163. VCSndDataArrived(
  1164. PSNDMESSAGE pSndMessage
  1165. )
  1166. {
  1167. if (pSndMessage->Prolog.BodySize &&
  1168. NULL == pSndMessage->pBody)
  1169. {
  1170. TRC(ERR, "_VCSndDataArrived: pBody is NULL\n");
  1171. goto exitpt;
  1172. }
  1173. // first, get the stream
  1174. //
  1175. if (!VCSndAcquireStream())
  1176. {
  1177. TRC(FATAL, "VCSndDataArrived: somebody is holding the "
  1178. "Stream mutext for too long\n");
  1179. ASSERT(0);
  1180. goto exitpt;
  1181. }
  1182. switch (pSndMessage->Prolog.Type)
  1183. {
  1184. case SNDC_WAVECONFIRM:
  1185. {
  1186. PSNDWAVECONFIRM pSndConfirm;
  1187. if ( pSndMessage->Prolog.BodySize <
  1188. sizeof( *pSndConfirm ) - sizeof( SNDPROLOG ))
  1189. {
  1190. TRC( ERR, "VCSndDataArrived: Invalid confirmation received\n" );
  1191. break;
  1192. }
  1193. pSndConfirm = (PSNDWAVECONFIRM)
  1194. (((LPSTR)pSndMessage->pBody) -
  1195. sizeof(pSndMessage->Prolog));
  1196. _StatsCollect( pSndConfirm->wTimeStamp );
  1197. TRC(ALV, "VCSndDataArrived: SNDC_WAVECONFIRM, block no %d\n",
  1198. pSndConfirm->cConfirmedBlockNo);
  1199. if ( (BYTE)(g_Stream->cLastBlockSent -
  1200. pSndConfirm->cConfirmedBlockNo) > TSSND_BLOCKSONTHENET )
  1201. {
  1202. TRC(WRN, "VCSndDataArrived: confirmation for block #%d "
  1203. "which wasn't sent. Last sent=%d. DROPPING !!!\n",
  1204. pSndConfirm->cConfirmedBlockNo,
  1205. g_Stream->cLastBlockSent);
  1206. break;
  1207. }
  1208. if ( (BYTE)(pSndConfirm->cConfirmedBlockNo -
  1209. g_Stream->cLastBlockConfirmed) < TSSND_BLOCKSONTHENET )
  1210. {
  1211. // move the mark
  1212. //
  1213. g_Stream->cLastBlockConfirmed = pSndConfirm->cConfirmedBlockNo + 1;
  1214. } else {
  1215. TRC(WRN, "VCSndDataArrived: difference in confirmed blocks "
  1216. "last=%d, this one=%d\n",
  1217. g_Stream->cLastBlockConfirmed,
  1218. pSndConfirm->cConfirmedBlockNo
  1219. );
  1220. }
  1221. PulseEvent(g_hStreamIsEmptyEvent);
  1222. }
  1223. break;
  1224. case SNDC_TRAINING:
  1225. {
  1226. PSNDTRAINING pSndTraining;
  1227. DWORD dwLatency;
  1228. if ( pSndMessage->Prolog.BodySize <
  1229. sizeof ( *pSndTraining ) - sizeof ( pSndTraining->Prolog ))
  1230. {
  1231. TRC(ERR, "VCSndDataArrived: SNDC_TRAINING invalid length "
  1232. "for the body=%d\n",
  1233. pSndMessage->Prolog.BodySize );
  1234. break;
  1235. }
  1236. pSndTraining = (PSNDTRAINING)
  1237. (((LPSTR)pSndMessage->pBody) -
  1238. sizeof(pSndMessage->Prolog));
  1239. if ( 0 != pSndTraining->wPackSize )
  1240. {
  1241. TRC(INF, "VCSndDataArrived: SNDC_TRAINING received (ignoring)\n");
  1242. //
  1243. // these type of messages are handled
  1244. // in _VCSndLineVCTraining(), bail out
  1245. //
  1246. break;
  1247. }
  1248. dwLatency = (GetTickCount() & 0xffff) - pSndTraining->wTimeStamp;
  1249. TRC(INF, "VCSndDataArrived: SNDC_TRAINING Latency=%d\n",
  1250. dwLatency );
  1251. //
  1252. // increase by 30%
  1253. //
  1254. if ( 0 == g_dwStatPing )
  1255. g_dwStatPing = dwLatency;
  1256. else
  1257. g_dwStatPing = (( 7 * g_dwStatPing ) + ( 3 * dwLatency )) / 10;
  1258. }
  1259. break;
  1260. case SNDC_FORMATS:
  1261. //
  1262. // this is handled in VCSndNegotiateWaveFormat()
  1263. //
  1264. TRC(INF, "VCSndDataArrived: SNDC_FORMATS reveived (ignoring)\n");
  1265. break;
  1266. default:
  1267. {
  1268. TRC(ERR, "_VCSndDataArrived: unknow message received: %d\n",
  1269. pSndMessage->Prolog.Type);
  1270. ASSERT(0);
  1271. }
  1272. }
  1273. VCSndReleaseStream();
  1274. exitpt:
  1275. ;
  1276. }
  1277. /*
  1278. * Function:
  1279. * VCSndAcquireStream
  1280. *
  1281. * Description:
  1282. * Locks the stream
  1283. *
  1284. */
  1285. BOOL
  1286. VCSndAcquireStream(
  1287. VOID
  1288. )
  1289. {
  1290. BOOL rv = FALSE;
  1291. DWORD dwres;
  1292. if (NULL == g_hStream ||
  1293. NULL == g_Stream)
  1294. {
  1295. TRC(FATAL, "VCSndAcquireStream: the stream handle is NULL\n");
  1296. goto exitpt;
  1297. }
  1298. if (NULL == g_hStreamMutex)
  1299. {
  1300. TRC(FATAL, "VCSndAcquireStream: the stream mutex is NULL\n");
  1301. goto exitpt;
  1302. }
  1303. dwres = WaitForSingleObject(g_hStreamMutex, DEFAULT_VC_TIMEOUT);
  1304. if (WAIT_TIMEOUT == dwres ||
  1305. WAIT_ABANDONED == dwres )
  1306. {
  1307. TRC(ERR, "VCSndAcquireStream: "
  1308. "timed out waiting for the stream mutex or owner crashed=%d\n", dwres );
  1309. //
  1310. // possible app crash
  1311. //
  1312. ASSERT(0);
  1313. goto exitpt;
  1314. }
  1315. rv = TRUE;
  1316. exitpt:
  1317. return rv;
  1318. }
  1319. /*
  1320. * Function:
  1321. * VCSndReleaseStream
  1322. *
  1323. * Description:
  1324. * Release the stream data
  1325. *
  1326. */
  1327. BOOL
  1328. VCSndReleaseStream(
  1329. VOID
  1330. )
  1331. {
  1332. BOOL rv = TRUE;
  1333. ASSERT(NULL != g_hStream);
  1334. ASSERT(NULL != g_Stream);
  1335. ASSERT(NULL != g_hStreamMutex);
  1336. if (!ReleaseMutex(g_hStreamMutex))
  1337. rv = FALSE;
  1338. return rv;
  1339. }
  1340. /*
  1341. * Function:
  1342. * _DGramOpen
  1343. *
  1344. * Description:
  1345. * Opens a datagram socket
  1346. *
  1347. */
  1348. VOID
  1349. _DGramOpen(
  1350. VOID
  1351. )
  1352. {
  1353. // create a datagram socket if needed
  1354. //
  1355. if (INVALID_SOCKET == g_hDGramSocket)
  1356. {
  1357. g_hDGramSocket = socket(AF_INET, SOCK_DGRAM, 0);
  1358. if (INVALID_SOCKET == g_hDGramSocket)
  1359. TRC(ERR, "_DGramOpen: failed to crate dgram socket: %d\n",
  1360. WSAGetLastError());
  1361. else
  1362. TRC(ALV, "_DGramOpen: datagram socket created\n");
  1363. }
  1364. // get the max datagram size
  1365. //
  1366. if (INVALID_SOCKET != g_hDGramSocket)
  1367. {
  1368. UINT optval = 0;
  1369. UINT optlen = sizeof(optval);
  1370. getsockopt(g_hDGramSocket,
  1371. SOL_SOCKET,
  1372. SO_MAX_MSG_SIZE,
  1373. (LPSTR)(&optval),
  1374. (int *) &optlen);
  1375. TRC(ALV, "_DGramOpen: max allowed datagram: %d\n",
  1376. optval);
  1377. optval = (optval < TSSND_BLOCKSIZE)?optval:TSSND_BLOCKSIZE;
  1378. // align the dgram to DWORD
  1379. //
  1380. optval /= sizeof(DWORD);
  1381. optval *= sizeof(DWORD);
  1382. if ( optval < RDPSND_MIN_FRAG_SIZE )
  1383. {
  1384. g_dwDGramSize = 0;
  1385. } else if ( optval < g_dwDGramSize )
  1386. {
  1387. g_dwDGramSize = optval;
  1388. TRC( INF, "DGram size downgraded to %d\n", g_dwDGramSize );
  1389. }
  1390. TRC(ALV, "_DGramOpen: max datagram size: %d\n",
  1391. optval);
  1392. // get client's ip address
  1393. //
  1394. {
  1395. WINSTATIONCLIENT ClientData;
  1396. ULONG ulReturnLength;
  1397. BOOL rc;
  1398. u_long ulDGramClientAddress;
  1399. rc = WinStationQueryInformation(
  1400. SERVERNAME_CURRENT,
  1401. LOGONID_CURRENT,
  1402. WinStationClient,
  1403. &ClientData,
  1404. sizeof(ClientData),
  1405. &ulReturnLength);
  1406. if (rc)
  1407. {
  1408. g_EncryptionLevel = ClientData.EncryptionLevel;
  1409. if (PF_INET == ClientData.ClientAddressFamily)
  1410. {
  1411. TRC(ALV, "_VCSndSendOpenDevice: client address is: %S\n",
  1412. ClientData.ClientAddress);
  1413. ulDGramClientAddress = inet_addrW(ClientData.ClientAddress);
  1414. if (INADDR_NONE != ulDGramClientAddress)
  1415. g_ulDGramAddress = ulDGramClientAddress;
  1416. else
  1417. TRC(ERR, "_VCSndSendOpenDevice: client address is NONE\n");
  1418. }
  1419. else
  1420. TRC(ERR, "_VCSndSendOpenDevice: "
  1421. "Invalid address family: %d\n",
  1422. ClientData.ClientAddressFamily);
  1423. } else
  1424. TRC(ERR, "_VCSndSendOpenDevice: "
  1425. "WinStationQueryInformation failed. %d\n",
  1426. GetLastError());
  1427. }
  1428. }
  1429. }
  1430. VOID
  1431. _FillWithGarbage(
  1432. PVOID pBuff,
  1433. DWORD dwSize
  1434. )
  1435. {
  1436. PBYTE pbBuff = (PBYTE)pBuff;
  1437. for ( ; dwSize; pbBuff++, dwSize-- )
  1438. {
  1439. pbBuff[0] = (BYTE)rand();
  1440. }
  1441. }
  1442. /*
  1443. * Function:
  1444. * _VCSndReadRegistry
  1445. *
  1446. * Description:
  1447. * Reads current options
  1448. */
  1449. VOID
  1450. _VCSndReadRegistry(
  1451. VOID
  1452. )
  1453. {
  1454. DWORD rv = (DWORD) -1;
  1455. DWORD sysrc;
  1456. HKEY hkey = NULL;
  1457. DWORD dwKeyType;
  1458. DWORD dwKeyLen;
  1459. WINSTATIONCONFIG config;
  1460. ULONG Length = 0;
  1461. DWORD dw;
  1462. sysrc = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1463. TSSND_REG_MAXBANDWIDTH_KEY,
  1464. 0, // reserved
  1465. KEY_READ,
  1466. &hkey);
  1467. if ( ERROR_SUCCESS != sysrc )
  1468. {
  1469. TRC(WRN, "_VCSndReadRegistry: "
  1470. "RegOpenKeyEx failed: %d\n",
  1471. sysrc );
  1472. goto exitpt;
  1473. }
  1474. dwKeyType = REG_DWORD;
  1475. dwKeyLen = sizeof( rv );
  1476. sysrc = RegQueryValueEx( hkey,
  1477. TSSND_REG_MAXBANDWIDTH_VAL,
  1478. NULL, // reserved
  1479. &dwKeyType,
  1480. (LPBYTE)&rv,
  1481. &dwKeyLen);
  1482. if ( ERROR_SUCCESS != sysrc )
  1483. {
  1484. TRC(WRN, "_VCSndReadRegistry: "
  1485. "RegQueryValueEx failed: %d\n",
  1486. sysrc );
  1487. } else {
  1488. g_dwMaxBandwidth = rv;
  1489. }
  1490. sysrc = RegQueryValueEx( hkey,
  1491. TSSND_REG_MINBANDWIDTH_VAL,
  1492. NULL, // reserved
  1493. &dwKeyType,
  1494. (LPBYTE)&rv,
  1495. &dwKeyLen);
  1496. if ( ERROR_SUCCESS != sysrc )
  1497. {
  1498. TRC(ALV, "_VCSndReadRegistry: "
  1499. "RegQueryValueEx failed: %d\n",
  1500. sysrc );
  1501. } else {
  1502. g_dwMinBandwidth = rv;
  1503. }
  1504. sysrc = RegQueryValueEx( hkey,
  1505. TSSND_REG_DISABLEDGRAM_VAL,
  1506. NULL, // reserved
  1507. &dwKeyType,
  1508. (LPBYTE)&rv,
  1509. &dwKeyLen);
  1510. if ( ERROR_SUCCESS != sysrc )
  1511. {
  1512. TRC(ALV, "_VCSndReadRegistry: "
  1513. "RegQueryValueEx failed: %d\n",
  1514. sysrc );
  1515. } else {
  1516. g_dwDisableDGram = rv;
  1517. }
  1518. sysrc = RegQueryValueEx( hkey,
  1519. TSSND_REG_ENABLEMP3_VAL,
  1520. NULL, // reserved
  1521. &dwKeyType,
  1522. (LPBYTE)&rv,
  1523. &dwKeyLen);
  1524. if ( ERROR_SUCCESS != sysrc )
  1525. {
  1526. TRC(WRN, "_VCSndReadRegistry: "
  1527. "RegQueryValueEx failed: %d\n",
  1528. sysrc );
  1529. } else {
  1530. g_dwEnableMP3Codec = rv;
  1531. }
  1532. sysrc = RegQueryValueEx( hkey,
  1533. TSSND_REG_MAXDGRAM,
  1534. NULL,
  1535. &dwKeyType,
  1536. (LPBYTE)&rv,
  1537. &dwKeyLen );
  1538. if ( ERROR_SUCCESS != sysrc )
  1539. {
  1540. TRC( WRN, "_VCSndReadRegistry: "
  1541. "RegQueryValueEx failed for \"%s\": %d\n",
  1542. TSSND_REG_MAXDGRAM, sysrc );
  1543. } else {
  1544. if ( rv < g_dwDGramSize && rv >= RDPSND_MIN_FRAG_SIZE )
  1545. {
  1546. g_dwDGramSize = rv;
  1547. TRC( INF, "DGram size forced to %d\n", g_dwDGramSize );
  1548. }
  1549. }
  1550. dwKeyLen = 0;
  1551. sysrc = RegQueryValueEx( hkey,
  1552. TSSND_REG_ALLOWCODECS,
  1553. NULL,
  1554. &dwKeyType,
  1555. NULL,
  1556. &dwKeyLen );
  1557. if ( ERROR_MORE_DATA != sysrc || REG_BINARY != dwKeyType )
  1558. {
  1559. TRC( ALV, "_VCSndReadRegistry: "
  1560. "RegQueryValueEx failed for AllowCodecs: %d\n",
  1561. sysrc );
  1562. } else {
  1563. if ( NULL != g_AllowCodecs )
  1564. TSFREE( g_AllowCodecs );
  1565. g_AllowCodecs = (DWORD *)TSMALLOC( dwKeyLen );
  1566. if ( NULL == g_AllowCodecs )
  1567. {
  1568. TRC( WRN, "_VCSndReadRegistry: "
  1569. "malloc failed for %d bytes\n",
  1570. dwKeyLen );
  1571. } else {
  1572. sysrc = RegQueryValueEx( hkey,
  1573. TSSND_REG_ALLOWCODECS,
  1574. NULL,
  1575. &dwKeyType,
  1576. (LPBYTE)g_AllowCodecs,
  1577. &dwKeyLen );
  1578. if ( ERROR_SUCCESS != sysrc )
  1579. {
  1580. TRC( WRN, "_VCSndReadRegistry: "
  1581. "RegQueryValueEx failed: %d\n",
  1582. sysrc );
  1583. TSFREE( g_AllowCodecs );
  1584. g_AllowCodecs = NULL;
  1585. g_AllowCodecsSize = 0;
  1586. } else {
  1587. g_AllowCodecsSize = dwKeyLen;
  1588. }
  1589. }
  1590. }
  1591. exitpt:
  1592. if ( NULL != hkey )
  1593. RegCloseKey( hkey );
  1594. }
  1595. /*
  1596. * Function:
  1597. * _VCSndLineVCTraining
  1598. *
  1599. * Description:
  1600. * Meassures the line speed thru the virtual channel
  1601. *
  1602. */
  1603. DWORD
  1604. _VCSndLineVCTraining(
  1605. HANDLE hReadEvent
  1606. )
  1607. {
  1608. PSNDTRAINING pSndTraining;
  1609. SNDMESSAGE SndMessage;
  1610. DWORD dwSuggestedBaudRate;
  1611. DWORD dwLatency;
  1612. PSNDTRAINING pSndTrainingResp;
  1613. memset(&SndMessage, 0, sizeof(SndMessage));
  1614. dwLatency = 0;
  1615. if (NULL == hReadEvent)
  1616. {
  1617. TRC(ERR, "_VCSndLineVCTraining: hReadEvent is NULL\n");
  1618. goto exitpt;
  1619. }
  1620. __try
  1621. {
  1622. pSndTraining = (PSNDTRAINING) alloca( TSSND_TRAINING_BLOCKSIZE );
  1623. } __except((EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) ?
  1624. EXCEPTION_EXECUTE_HANDLER :
  1625. EXCEPTION_CONTINUE_SEARCH)
  1626. {
  1627. _resetstkoflw();
  1628. pSndTraining = NULL;
  1629. }
  1630. if (NULL == pSndTraining)
  1631. {
  1632. TRC(ERR, "_VCSndLineVCTraining: can't alloca %d bytes\n",
  1633. TSSND_TRAINING_BLOCKSIZE);
  1634. goto exitpt;
  1635. }
  1636. _FillWithGarbage( pSndTraining, TSSND_TRAINING_BLOCKSIZE);
  1637. pSndTraining->Prolog.Type = SNDC_TRAINING;
  1638. pSndTraining->Prolog.BodySize = TSSND_TRAINING_BLOCKSIZE -
  1639. sizeof (pSndTraining->Prolog);
  1640. pSndTraining->wTimeStamp = (UINT16)GetTickCount();
  1641. pSndTraining->wPackSize = (UINT16)TSSND_TRAINING_BLOCKSIZE;
  1642. //
  1643. // send the packet
  1644. //
  1645. if (!ChannelBlockWrite(pSndTraining, TSSND_TRAINING_BLOCKSIZE))
  1646. {
  1647. TRC(ERR, "_VCSndLineVCTraining: failed to send a block: %d\n",
  1648. GetLastError());
  1649. goto exitpt;
  1650. }
  1651. //
  1652. // wait for response to arrive
  1653. //
  1654. do {
  1655. SndMessage.uiPrologReceived = 0;
  1656. SndMessage.uiBodyReceived = 0;
  1657. while(!ChannelReceiveMessage(&SndMessage, hReadEvent))
  1658. {
  1659. if (ERROR_IO_PENDING == GetLastError())
  1660. {
  1661. DWORD dwres;
  1662. HANDLE ahEvents[2];
  1663. ahEvents[0] = hReadEvent;
  1664. ahEvents[1] = g_hDisconnectEvent;
  1665. dwres = WaitForMultipleObjects(
  1666. sizeof(ahEvents)/sizeof(ahEvents[0]), // count
  1667. ahEvents, // events
  1668. FALSE, // wait all
  1669. DEFAULT_RESPONSE_TIMEOUT);
  1670. if (WAIT_TIMEOUT == dwres ||
  1671. WAIT_OBJECT_0 + 1 == dwres)
  1672. {
  1673. TRC(WRN, "_VCSndLineVCTraining: timeout "
  1674. "waiting for response\n");
  1675. ChannelCancelIo();
  1676. ResetEvent(hReadEvent);
  1677. goto exitpt;
  1678. }
  1679. ChannelBlockReadComplete();
  1680. ResetEvent(hReadEvent);
  1681. } else
  1682. if (ERROR_SUCCESS != GetLastError())
  1683. {
  1684. TRC(ERR, "_VCSndLineVCTraining: "
  1685. "ChannelReceiveMessage failed: %d\n",
  1686. GetLastError());
  1687. goto exitpt;
  1688. }
  1689. }
  1690. } while ( SNDC_TRAINING != SndMessage.Prolog.Type ||
  1691. sizeof(SNDTRAINING) - sizeof(SNDPROLOG) <
  1692. SndMessage.Prolog.BodySize);
  1693. TRC(ALV, "_VCSndLineVCTraining: response received\n");
  1694. pSndTrainingResp = (PSNDTRAINING)
  1695. (((LPSTR)SndMessage.pBody) -
  1696. sizeof(SndMessage.Prolog));
  1697. //
  1698. // calculate latency (nonzero)
  1699. //
  1700. dwLatency = ((WORD)GetTickCount()) - pSndTrainingResp->wTimeStamp + 1;
  1701. exitpt:
  1702. TRC(INF, "_VCSndLineVCTraining: dwLatency = %d\n",
  1703. dwLatency);
  1704. if (0 != dwLatency)
  1705. {
  1706. //
  1707. // the latency is in miliseconds, so compute it bytes per seconds
  1708. // and get nonzero result
  1709. //
  1710. dwSuggestedBaudRate = 1 + (1000 * ( pSndTrainingResp->wPackSize +
  1711. sizeof( *pSndTraining ))
  1712. / dwLatency);
  1713. }
  1714. else
  1715. dwSuggestedBaudRate = 0;
  1716. TRC(INF, "_VCSndLineVCTraining: dwSuggestedBaudRate = %d\n",
  1717. dwSuggestedBaudRate);
  1718. if (NULL != SndMessage.pBody)
  1719. TSFREE(SndMessage.pBody);
  1720. return dwSuggestedBaudRate;
  1721. }
  1722. /*
  1723. * Function:
  1724. * _VCSndLineDGramTraining
  1725. *
  1726. * Description:
  1727. * Meassures the line speed thru UDP channel
  1728. *
  1729. */
  1730. DWORD
  1731. _VCSndLineDGramTraining(
  1732. HANDLE hDGramEvent
  1733. )
  1734. {
  1735. PSNDTRAINING pSndTraining;
  1736. PSNDTRAINING pSndTrainingResp;
  1737. struct sockaddr_in sin;
  1738. DWORD dwRetries;
  1739. DWORD dwSuggestedBaudRate;
  1740. DWORD dwDGramLatency = 0;
  1741. INT sendres;
  1742. DWORD dwPackSize;
  1743. DWORD dwRespSize;
  1744. dwDGramLatency = 0;
  1745. if (NULL == hDGramEvent)
  1746. {
  1747. TRC(ERR, "_VCSndLineDGramTraining: hDGramEvent is NULL\n");
  1748. goto exitpt;
  1749. }
  1750. if (INVALID_SOCKET == g_hDGramSocket ||
  1751. 0 == g_dwDGramPort ||
  1752. g_dwDGramSize < sizeof(*pSndTraining) ||
  1753. 0 == g_ulDGramAddress)
  1754. {
  1755. TRC(ERR, "_VCSndLineDGramTraining: no dgram support. Can't train the line\n");
  1756. goto exitpt;
  1757. }
  1758. dwPackSize = ( g_dwDGramSize < TSSND_TRAINING_BLOCKSIZE )?
  1759. g_dwDGramSize:
  1760. TSSND_TRAINING_BLOCKSIZE;
  1761. __try
  1762. {
  1763. pSndTraining = (PSNDTRAINING) alloca( dwPackSize );
  1764. } __except((EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) ?
  1765. EXCEPTION_EXECUTE_HANDLER :
  1766. EXCEPTION_CONTINUE_SEARCH)
  1767. {
  1768. _resetstkoflw();
  1769. pSndTraining = NULL;
  1770. }
  1771. if (NULL == pSndTraining)
  1772. {
  1773. TRC(ERR, "_VCSndLineDGramTraining: can't alloca %d bytes\n",
  1774. dwPackSize);
  1775. goto exitpt;
  1776. }
  1777. _FillWithGarbage( pSndTraining, dwPackSize );
  1778. //
  1779. // send a block and measure the time when it will arrive
  1780. //
  1781. // prepare the to address
  1782. //
  1783. sin.sin_family = PF_INET;
  1784. sin.sin_port = (u_short)g_dwDGramPort;
  1785. sin.sin_addr.s_addr = g_ulDGramAddress;
  1786. pSndTraining->Prolog.Type = SNDC_TRAINING;
  1787. pSndTraining->Prolog.BodySize = (UINT16)( dwPackSize -
  1788. sizeof (pSndTraining->Prolog));
  1789. pSndTraining->wPackSize = (UINT16)TSSND_TRAINING_BLOCKSIZE;
  1790. dwRetries = 2 * DEFAULT_RESPONSE_TIMEOUT / 1000;
  1791. do {
  1792. pSndTraining->wTimeStamp = (WORD)GetTickCount();
  1793. //
  1794. // send the datagram
  1795. // the type is SNDC_WAVE but the structure is of SNDWAVE
  1796. // wTimeStamp contains the sending time
  1797. //
  1798. sendres = sendto(
  1799. g_hDGramSocket,
  1800. (LPSTR)pSndTraining,
  1801. dwPackSize,
  1802. 0, // flags
  1803. (struct sockaddr *)&sin, // to address
  1804. sizeof(sin)
  1805. );
  1806. if (SOCKET_ERROR == sendres)
  1807. {
  1808. TRC(ERR, "_VCSndLineDGramTraining: sendto failed: %d\n",
  1809. WSAGetLastError());
  1810. goto exitpt;
  1811. }
  1812. //
  1813. // wait for a response
  1814. //
  1815. do {
  1816. pSndTrainingResp = NULL;
  1817. dwRespSize = 0;
  1818. DGramRead( hDGramEvent, (PVOID*) &pSndTrainingResp, &dwRespSize );
  1819. if ( NULL == pSndTrainingResp )
  1820. {
  1821. DWORD dwres;
  1822. HANDLE ahEvents[2];
  1823. ahEvents[0] = hDGramEvent;
  1824. ahEvents[1] = g_hDisconnectEvent;
  1825. dwres = WaitForMultipleObjects(
  1826. sizeof(ahEvents)/sizeof(ahEvents[0]), // count
  1827. ahEvents, // events
  1828. FALSE, // wait all
  1829. 1000);
  1830. if ( WAIT_OBJECT_0 + 1 == dwres )
  1831. {
  1832. TRC(WRN, "_VCSndLineDGramTraining: disconnected\n");
  1833. goto exitpt;
  1834. }
  1835. if (WAIT_TIMEOUT == dwres)
  1836. {
  1837. TRC(WRN, "_VCSndLineDGramTraining: timeout "
  1838. "waiting for response\n");
  1839. goto try_again;
  1840. }
  1841. DGramReadComplete( (PVOID*) &pSndTrainingResp, &dwRespSize );
  1842. }
  1843. } while ( NULL == pSndTrainingResp ||
  1844. sizeof( *pSndTrainingResp ) != dwRespSize ||
  1845. SNDC_TRAINING != pSndTrainingResp->Prolog.Type ||
  1846. sizeof(SNDTRAINING) - sizeof(SNDPROLOG) <
  1847. pSndTrainingResp->Prolog.BodySize );
  1848. TRC(ALV, "_VCSndLineDGramTraining: response received\n");
  1849. break;
  1850. try_again:
  1851. dwRetries --;
  1852. } while (0 != dwRetries);
  1853. if (0 != dwRetries)
  1854. {
  1855. //
  1856. // calculate latency (nonzero)
  1857. //
  1858. dwDGramLatency = ((WORD)GetTickCount()) -
  1859. pSndTrainingResp->wTimeStamp + 1;
  1860. }
  1861. exitpt:
  1862. TRC(INF, "_VCSndLineDGramTraining: dwDGramLatency = %d\n",
  1863. dwDGramLatency);
  1864. if (0 != dwDGramLatency)
  1865. {
  1866. //
  1867. // the latency is in miliseconds, so compute it bytes per seconds
  1868. // and get nonzero result
  1869. //
  1870. dwSuggestedBaudRate = 1 + (1000 * ( pSndTrainingResp->wPackSize +
  1871. sizeof( *pSndTrainingResp ))
  1872. / dwDGramLatency);
  1873. }
  1874. else
  1875. dwSuggestedBaudRate = 0;
  1876. TRC(INF, "_VCSndLineDGramTraining: dwSuggestedBaudRate = %d\n",
  1877. dwSuggestedBaudRate);
  1878. return dwSuggestedBaudRate;
  1879. }
  1880. //
  1881. // puts code licensing codes into the header
  1882. //
  1883. BOOL
  1884. _VCSndFixHeader(
  1885. PWAVEFORMATEX pFmt
  1886. )
  1887. {
  1888. BOOL rv = FALSE;
  1889. switch (pFmt->wFormatTag)
  1890. {
  1891. case WAVE_FORMAT_MSG723:
  1892. ASSERT(pFmt->cbSize == 10);
  1893. if ( pFmt->cbSize == 10 )
  1894. {
  1895. ((MSG723WAVEFORMAT *) pFmt)->dwCodeword1 = G723MAGICWORD1;
  1896. ((MSG723WAVEFORMAT *) pFmt)->dwCodeword2 = G723MAGICWORD2;
  1897. rv = TRUE;
  1898. }
  1899. break;
  1900. case WAVE_FORMAT_MSRT24:
  1901. //
  1902. // assume call control will take care of the other
  1903. // params ?
  1904. //
  1905. ASSERT(pFmt->cbSize == sizeof( VOXACM_WAVEFORMATEX ) - sizeof( WAVEFORMATEX ) );
  1906. if ( sizeof( VOXACM_WAVEFORMATEX ) - sizeof( WAVEFORMATEX ) == pFmt->cbSize )
  1907. {
  1908. VOXACM_WAVEFORMATEX *pVOX = (VOXACM_WAVEFORMATEX *)pFmt;
  1909. ASSERT( strlen( VOXWARE_KEY ) + 1 == sizeof( pVOX->szKey ));
  1910. strncpy( pVOX->szKey, VOXWARE_KEY, sizeof( pVOX->szKey ));
  1911. rv = TRUE;
  1912. }
  1913. break;
  1914. // this format eats too much from the CPU
  1915. //
  1916. case WAVE_FORMAT_MPEGLAYER3:
  1917. if ( g_dwEnableMP3Codec )
  1918. rv = TRUE;
  1919. break;
  1920. case WAVE_FORMAT_WMAUDIO2:
  1921. if ( g_dwEnableMP3Codec )
  1922. {
  1923. rv = TRUE;
  1924. }
  1925. break;
  1926. default:
  1927. rv = TRUE;
  1928. }
  1929. return rv;
  1930. }
  1931. /*
  1932. * Function:
  1933. * _VCSndFindSuggestedConverter
  1934. *
  1935. * Description:
  1936. * Searches for intermidiate converter
  1937. *
  1938. */
  1939. BOOL
  1940. _VCSndFindSuggestedConverter(
  1941. HACMDRIVERID hadid,
  1942. LPWAVEFORMATEX pDestFormat,
  1943. LPWAVEFORMATEX pInterrimFmt,
  1944. PFNCONVERTER *ppfnConverter
  1945. )
  1946. {
  1947. BOOL rv = FALSE;
  1948. MMRESULT mmres;
  1949. HACMDRIVER hacmDriver = NULL;
  1950. PFNCONVERTER pfnConverter = NULL;
  1951. HACMSTREAM hacmStream = NULL;
  1952. ASSERT( NULL != pDestFormat );
  1953. ASSERT( NULL != hadid );
  1954. ASSERT( NULL != pInterrimFmt );
  1955. *ppfnConverter = NULL;
  1956. //
  1957. // first, open the destination acm driver
  1958. //
  1959. mmres = acmDriverOpen(&hacmDriver, hadid, 0);
  1960. if ( MMSYSERR_NOERROR != mmres )
  1961. {
  1962. TRC(ERR, "_VCSndFindSuggestedConverter: can't "
  1963. "open the acm driver: %d\n",
  1964. mmres);
  1965. goto exitpt;
  1966. }
  1967. //
  1968. // first probe with the native format
  1969. // if it passes, we don't need intermidiate
  1970. // format converter
  1971. //
  1972. pInterrimFmt->wFormatTag = WAVE_FORMAT_PCM;
  1973. pInterrimFmt->nChannels = TSSND_NATIVE_CHANNELS;
  1974. pInterrimFmt->nSamplesPerSec = TSSND_NATIVE_SAMPLERATE;
  1975. pInterrimFmt->nAvgBytesPerSec = TSSND_NATIVE_AVGBYTESPERSEC;
  1976. pInterrimFmt->nBlockAlign = TSSND_NATIVE_BLOCKALIGN;
  1977. pInterrimFmt->wBitsPerSample = TSSND_NATIVE_BITSPERSAMPLE;
  1978. pInterrimFmt->cbSize = 0;
  1979. mmres = acmStreamOpen(
  1980. &hacmStream,
  1981. hacmDriver,
  1982. pInterrimFmt,
  1983. pDestFormat,
  1984. NULL, // filter
  1985. 0, // callback
  1986. 0, // dwinstance
  1987. ACM_STREAMOPENF_NONREALTIME
  1988. );
  1989. if ( MMSYSERR_NOERROR == mmres )
  1990. {
  1991. //
  1992. // format is supported
  1993. //
  1994. rv = TRUE;
  1995. goto exitpt;
  1996. } else {
  1997. TRC(ALV, "_VCSndFindSuggestedConverter: format is not supported\n");
  1998. }
  1999. //
  2000. // find a suggested intermidiate PCM format
  2001. //
  2002. mmres = acmFormatSuggest(
  2003. hacmDriver,
  2004. pDestFormat,
  2005. pInterrimFmt,
  2006. sizeof( *pInterrimFmt ),
  2007. ACM_FORMATSUGGESTF_WFORMATTAG
  2008. );
  2009. if ( MMSYSERR_NOERROR != mmres )
  2010. {
  2011. TRC(ALV, "_VCSndFindSuggestedConverter: can't find "
  2012. "interrim format: %d\n",
  2013. mmres);
  2014. goto exitpt;
  2015. }
  2016. if ( 16 != pInterrimFmt->wBitsPerSample ||
  2017. ( 1 != pInterrimFmt->nChannels &&
  2018. 2 != pInterrimFmt->nChannels) ||
  2019. ( 8000 != pInterrimFmt->nSamplesPerSec &&
  2020. 11025 != pInterrimFmt->nSamplesPerSec &&
  2021. 12000 != pInterrimFmt->nSamplesPerSec &&
  2022. 16000 != pInterrimFmt->nSamplesPerSec &&
  2023. 22050 != pInterrimFmt->nSamplesPerSec)
  2024. )
  2025. {
  2026. TRC(ALV, "_VCSndFindSuggestedConverter: not supported "
  2027. "interrim format. Details:\n");
  2028. TRC(ALV, "Channels - %d\n", pInterrimFmt->nChannels);
  2029. TRC(ALV, "SamplesPerSec - %d\n", pInterrimFmt->nSamplesPerSec);
  2030. TRC(ALV, "AvgBytesPerSec - %d\n", pInterrimFmt->nAvgBytesPerSec);
  2031. TRC(ALV, "BlockAlign - %d\n", pInterrimFmt->nBlockAlign);
  2032. TRC(ALV, "BitsPerSample - %d\n", pInterrimFmt->wBitsPerSample);
  2033. goto exitpt;
  2034. }
  2035. if ( 1 == pInterrimFmt->nChannels )
  2036. {
  2037. switch ( pInterrimFmt->nSamplesPerSec )
  2038. {
  2039. case 8000: pfnConverter = _Convert8000Mono; break;
  2040. case 11025: pfnConverter = _Convert11025Mono; break;
  2041. case 12000: pfnConverter = _Convert12000Mono; break;
  2042. case 16000: pfnConverter = _Convert16000Mono; break;
  2043. case 22050: pfnConverter = _Convert22050Mono; break;
  2044. default:
  2045. ASSERT( 0 );
  2046. }
  2047. } else {
  2048. switch ( pInterrimFmt->nSamplesPerSec )
  2049. {
  2050. case 8000: pfnConverter = _Convert8000Stereo; break;
  2051. case 11025: pfnConverter = _Convert11025Stereo; break;
  2052. case 12000: pfnConverter = _Convert12000Stereo; break;
  2053. case 16000: pfnConverter = _Convert16000Stereo; break;
  2054. case 22050: pfnConverter = NULL; break;
  2055. default:
  2056. ASSERT( 0 );
  2057. }
  2058. }
  2059. //
  2060. // probe with this format
  2061. //
  2062. mmres = acmStreamOpen(
  2063. &hacmStream,
  2064. hacmDriver,
  2065. pInterrimFmt,
  2066. pDestFormat,
  2067. NULL, // filter
  2068. 0, // callback
  2069. 0, // dwinstance
  2070. ACM_STREAMOPENF_NONREALTIME
  2071. );
  2072. if ( MMSYSERR_NOERROR != mmres )
  2073. {
  2074. TRC(ALV, "_VCSndFindSuggestedConverter: probing the suggested "
  2075. "format failed: %d\n",
  2076. mmres);
  2077. goto exitpt;
  2078. }
  2079. TRC(ALV, "_VCSndFindSuggestedConverter: found intermidiate PCM format\n");
  2080. TRC(ALV, "Channels - %d\n", pInterrimFmt->nChannels);
  2081. TRC(ALV, "SamplesPerSec - %d\n", pInterrimFmt->nSamplesPerSec);
  2082. TRC(ALV, "AvgBytesPerSec - %d\n", pInterrimFmt->nAvgBytesPerSec);
  2083. TRC(ALV, "BlockAlign - %d\n", pInterrimFmt->nBlockAlign);
  2084. TRC(ALV, "BitsPerSample - %d\n", pInterrimFmt->wBitsPerSample);
  2085. rv = TRUE;
  2086. exitpt:
  2087. if ( NULL != hacmStream )
  2088. acmStreamClose( hacmStream, 0 );
  2089. if ( NULL != hacmDriver )
  2090. acmDriverClose( hacmDriver, 0 );
  2091. *ppfnConverter = pfnConverter;
  2092. return rv;
  2093. }
  2094. /*
  2095. * Function:
  2096. * VCSndEnumAllCodecFormats
  2097. *
  2098. * Description:
  2099. * Creates a list of all codecs/formats
  2100. *
  2101. */
  2102. BOOL
  2103. VCSndEnumAllCodecFormats(
  2104. PVCSNDFORMATLIST *ppFormatList,
  2105. DWORD *pdwNumberOfFormats
  2106. )
  2107. {
  2108. BOOL rv = FALSE;
  2109. PVCSNDFORMATLIST pIter;
  2110. PVCSNDFORMATLIST pPrev;
  2111. PVCSNDFORMATLIST pNext;
  2112. MMRESULT mmres;
  2113. DWORD dwNum = 0;
  2114. UINT count, codecsize;
  2115. ASSERT( ppFormatList );
  2116. ASSERT( pdwNumberOfFormats );
  2117. *ppFormatList = NULL;
  2118. //
  2119. // convert the known format list to a linked list
  2120. //
  2121. for ( count = 0, codecsize = 0; count < sizeof( KnownFormats ); count += codecsize )
  2122. {
  2123. PWAVEFORMATEX pSndFmt = (PWAVEFORMATEX)(KnownFormats + count);
  2124. codecsize = sizeof( WAVEFORMATEX ) + pSndFmt->cbSize;
  2125. //
  2126. // skip mp3s if disabled
  2127. //
  2128. if (( WAVE_FORMAT_MPEGLAYER3 == pSndFmt->wFormatTag ||
  2129. WAVE_FORMAT_WMAUDIO2 == pSndFmt->wFormatTag ) &&
  2130. !g_dwEnableMP3Codec )
  2131. {
  2132. continue;
  2133. }
  2134. UINT entrysize = sizeof( VCSNDFORMATLIST ) + pSndFmt->cbSize;
  2135. PVCSNDFORMATLIST pNewEntry;
  2136. pNewEntry = (PVCSNDFORMATLIST) TSMALLOC( entrysize );
  2137. if ( NULL != pNewEntry )
  2138. {
  2139. memcpy( &pNewEntry->Format, pSndFmt, codecsize );
  2140. pNewEntry->hacmDriverId = NULL;
  2141. pNewEntry->pNext = *ppFormatList;
  2142. *ppFormatList = pNewEntry;
  2143. }
  2144. }
  2145. //
  2146. // additional codecs
  2147. // these are codecs not included initially, it reads them from the registry
  2148. // see AllowCodecs initialization
  2149. //
  2150. for ( count = 0, codecsize = 0; count < g_AllowCodecsSize ; count += codecsize )
  2151. {
  2152. PWAVEFORMATEX pSndFmt = (PWAVEFORMATEX)(((PBYTE)g_AllowCodecs) + count);
  2153. codecsize = sizeof( WAVEFORMATEX ) + pSndFmt->cbSize;
  2154. if ( codecsize + count > g_AllowCodecsSize )
  2155. {
  2156. TRC( ERR, "Invalid size of additional codec\n" );
  2157. break;
  2158. }
  2159. //
  2160. // skip mp3s if disabled
  2161. //
  2162. if (( WAVE_FORMAT_MPEGLAYER3 == pSndFmt->wFormatTag ||
  2163. WAVE_FORMAT_WMAUDIO2 == pSndFmt->wFormatTag ) &&
  2164. !g_dwEnableMP3Codec )
  2165. {
  2166. continue;
  2167. }
  2168. UINT entrysize = sizeof( VCSNDFORMATLIST ) + pSndFmt->cbSize;
  2169. PVCSNDFORMATLIST pNewEntry;
  2170. pNewEntry = (PVCSNDFORMATLIST) TSMALLOC( entrysize );
  2171. if ( NULL != pNewEntry )
  2172. {
  2173. memcpy( &pNewEntry->Format, pSndFmt, codecsize );
  2174. pNewEntry->hacmDriverId = NULL;
  2175. pNewEntry->pNext = *ppFormatList;
  2176. *ppFormatList = pNewEntry;
  2177. }
  2178. }
  2179. //
  2180. // add the native format
  2181. //
  2182. pIter = (PVCSNDFORMATLIST) TSMALLOC( sizeof( *pIter ) );
  2183. if ( NULL != pIter )
  2184. {
  2185. pIter->Format.wFormatTag = WAVE_FORMAT_PCM;
  2186. pIter->Format.nChannels = TSSND_NATIVE_CHANNELS;
  2187. pIter->Format.nSamplesPerSec = TSSND_NATIVE_SAMPLERATE;
  2188. pIter->Format.nAvgBytesPerSec = TSSND_NATIVE_AVGBYTESPERSEC;
  2189. pIter->Format.nBlockAlign = TSSND_NATIVE_BLOCKALIGN;
  2190. pIter->Format.wBitsPerSample = TSSND_NATIVE_BITSPERSAMPLE;
  2191. pIter->Format.cbSize = 0;
  2192. pIter->hacmDriverId = NULL;
  2193. pIter->pNext = *ppFormatList;
  2194. *ppFormatList = pIter;
  2195. }
  2196. if (NULL == *ppFormatList)
  2197. {
  2198. TRC(WRN, "VCSndEnumAllCodecFormats: failed to add formats\n");
  2199. goto exitpt;
  2200. }
  2201. _VCSndOrderFormatList( ppFormatList, &dwNum );
  2202. //
  2203. // number of formats is passed as UINT16, delete all after those
  2204. //
  2205. if ( dwNum > 0xffff )
  2206. {
  2207. DWORD dwLimit = 0xfffe;
  2208. pIter = *ppFormatList;
  2209. while ( 0 != dwLimit )
  2210. {
  2211. pIter = pIter->pNext;
  2212. dwLimit --;
  2213. }
  2214. pNext = pIter->pNext;
  2215. pIter->pNext = NULL;
  2216. pIter = pNext;
  2217. while( NULL != pIter )
  2218. {
  2219. pNext = pIter->pNext;
  2220. TSFREE( pNext );
  2221. pIter = pNext;
  2222. }
  2223. dwNum = 0xffff;
  2224. }
  2225. rv = TRUE;
  2226. exitpt:
  2227. if (!rv)
  2228. {
  2229. //
  2230. // in case of error free the allocated list of formats
  2231. //
  2232. pIter = *ppFormatList;
  2233. while( NULL != pIter )
  2234. {
  2235. PVCSNDFORMATLIST pNext = pIter->pNext;
  2236. TSFREE( pIter );
  2237. pIter = pNext;
  2238. }
  2239. *ppFormatList = NULL;
  2240. }
  2241. *pdwNumberOfFormats = dwNum;
  2242. return rv;
  2243. }
  2244. BOOL
  2245. CALLBACK
  2246. acmDriverEnumCallbackGetACM(
  2247. HACMDRIVERID hadid,
  2248. DWORD_PTR dwInstance,
  2249. DWORD fdwSupport
  2250. )
  2251. {
  2252. BOOL rv = TRUE;
  2253. MMRESULT mmres;
  2254. ASSERT(dwInstance);
  2255. ASSERT( NULL != hadid );
  2256. if ( (0 != ( fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC ) ||
  2257. 0 != ( fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CONVERTER )))
  2258. {
  2259. //
  2260. // a codec found
  2261. //
  2262. ACMFORMATTAGDETAILS fdwDetails;
  2263. PVCSNDFORMATLIST pFmt = (PVCSNDFORMATLIST)dwInstance;
  2264. fdwDetails.cbStruct = sizeof( fdwDetails );
  2265. fdwDetails.fdwSupport = 0;
  2266. fdwDetails.dwFormatTag = pFmt->Format.wFormatTag;
  2267. mmres = acmFormatTagDetails( (HACMDRIVER)hadid, &fdwDetails, ACM_FORMATTAGDETAILSF_FORMATTAG );
  2268. if ( MMSYSERR_NOERROR == mmres )
  2269. {
  2270. WAVEFORMATEX WaveFormat; // dummy parameter
  2271. PFNCONVERTER pfnConverter; // dummy parameter
  2272. if ( _VCSndFindSuggestedConverter(
  2273. (HACMDRIVERID)hadid,
  2274. &(pFmt->Format),
  2275. &WaveFormat,
  2276. &pfnConverter ))
  2277. {
  2278. pFmt->hacmDriverId = hadid;
  2279. rv = FALSE;
  2280. }
  2281. }
  2282. }
  2283. //
  2284. // continue to the next driver
  2285. //
  2286. return rv;
  2287. }
  2288. BOOL
  2289. _VCSndGetACMDriverId( PSNDFORMATITEM pSndFmt )
  2290. {
  2291. DWORD rv = FALSE;
  2292. PVCSNDFORMATLIST pIter;
  2293. //
  2294. // Find the acm format id
  2295. //
  2296. for( pIter = g_pAllCodecsFormatList; NULL != pIter; pIter = pIter->pNext )
  2297. {
  2298. if (pIter->Format.wFormatTag == pSndFmt->wFormatTag &&
  2299. pIter->Format.nChannels == pSndFmt->nChannels &&
  2300. pIter->Format.nSamplesPerSec == pSndFmt->nSamplesPerSec &&
  2301. pIter->Format.nAvgBytesPerSec == pSndFmt->nAvgBytesPerSec &&
  2302. pIter->Format.nBlockAlign == pSndFmt->nBlockAlign &&
  2303. pIter->Format.wBitsPerSample == pSndFmt->wBitsPerSample &&
  2304. pIter->Format.cbSize == pSndFmt->cbSize &&
  2305. 0 == memcmp((&pIter->Format) + 1, pSndFmt + 1, pIter->Format.cbSize))
  2306. {
  2307. //
  2308. // format is found
  2309. //
  2310. DWORD_PTR dwp = (DWORD_PTR)pIter;
  2311. MMRESULT mmres;
  2312. if ( NULL != pIter->hacmDriverId )
  2313. {
  2314. // found already
  2315. rv = TRUE;
  2316. break;
  2317. }
  2318. mmres = acmDriverEnum(
  2319. acmDriverEnumCallbackGetACM,
  2320. (DWORD_PTR)dwp,
  2321. 0
  2322. );
  2323. if ( MMSYSERR_NOERROR == mmres )
  2324. {
  2325. if ( NULL != pIter->hacmDriverId )
  2326. {
  2327. rv = TRUE;
  2328. } else {
  2329. ASSERT( 0 );
  2330. }
  2331. }
  2332. break;
  2333. }
  2334. }
  2335. return rv;
  2336. }
  2337. /*
  2338. * Function:
  2339. * _VCSndChooseProperFormat
  2340. *
  2341. * Description:
  2342. * Chooses the closest format to a given bandwidth
  2343. *
  2344. */
  2345. DWORD
  2346. _VCSndChooseProperFormat(
  2347. DWORD dwBandwidth
  2348. )
  2349. {
  2350. // choose a format from the list
  2351. // closest to the measured bandwidth
  2352. //
  2353. DWORD i;
  2354. DWORD fmt = (DWORD)-1;
  2355. DWORD lastgood = (DWORD)-1;
  2356. if ( NULL == g_ppNegotiatedFormats )
  2357. {
  2358. TRC(ERR, "_VCSndChooseProperFormat: no negotiated formats\n");
  2359. goto exitpt;
  2360. }
  2361. for( i = 0; i < g_dwNegotiatedFormats; i++ )
  2362. {
  2363. if ( NULL == g_ppNegotiatedFormats[i] )
  2364. {
  2365. continue;
  2366. }
  2367. lastgood = i;
  2368. if ( dwBandwidth != g_dwLineBandwidth )
  2369. {
  2370. //
  2371. // we are looking for new codec here, make sure we cover at least 90%
  2372. // of the requested bandwith
  2373. //
  2374. if ( g_ppNegotiatedFormats[i]->nAvgBytesPerSec <= dwBandwidth * NEW_CODEC_COVER / 100 )
  2375. {
  2376. fmt = i;
  2377. break;
  2378. }
  2379. } else if ( g_ppNegotiatedFormats[i]->nAvgBytesPerSec <= dwBandwidth )
  2380. {
  2381. fmt = i;
  2382. break;
  2383. }
  2384. }
  2385. //
  2386. // get the last format inc case that all format are not
  2387. // suitable for our bandwidth
  2388. //
  2389. if ( (DWORD)-1 == fmt && 0 != g_dwNegotiatedFormats )
  2390. {
  2391. fmt = lastgood;
  2392. }
  2393. ASSERT( fmt != (DWORD)-1 );
  2394. exitpt:
  2395. return fmt;
  2396. }
  2397. /*
  2398. * Function:
  2399. * _VCSndOrderFormatList
  2400. *
  2401. * Description:
  2402. * Order all formats in descendant order
  2403. *
  2404. */
  2405. VOID
  2406. _VCSndOrderFormatList(
  2407. PVCSNDFORMATLIST *ppFormatList,
  2408. DWORD *pdwNum
  2409. )
  2410. {
  2411. PVCSNDFORMATLIST pFormatList;
  2412. PVCSNDFORMATLIST pLessThan;
  2413. PVCSNDFORMATLIST pPrev;
  2414. PVCSNDFORMATLIST pNext;
  2415. PVCSNDFORMATLIST pIter;
  2416. PVCSNDFORMATLIST pIter2;
  2417. DWORD dwNum = 0;
  2418. ASSERT ( NULL != ppFormatList );
  2419. pFormatList = *ppFormatList;
  2420. pLessThan = NULL;
  2421. //
  2422. // fill both lists
  2423. //
  2424. pIter = pFormatList;
  2425. while ( NULL != pIter )
  2426. {
  2427. pNext = pIter->pNext;
  2428. pIter->pNext = NULL;
  2429. //
  2430. // descending order
  2431. //
  2432. pIter2 = pLessThan;
  2433. pPrev = NULL;
  2434. while ( NULL != pIter2 &&
  2435. pIter2->Format.nAvgBytesPerSec >
  2436. pIter->Format.nAvgBytesPerSec )
  2437. {
  2438. pPrev = pIter2;
  2439. pIter2 = pIter2->pNext;
  2440. }
  2441. pIter->pNext = pIter2;
  2442. if ( NULL == pPrev )
  2443. pLessThan = pIter;
  2444. else
  2445. pPrev->pNext = pIter;
  2446. pIter = pNext;
  2447. dwNum ++;
  2448. }
  2449. *ppFormatList = pLessThan;
  2450. if ( NULL != pdwNum )
  2451. *pdwNum = dwNum;
  2452. }
  2453. /*
  2454. * Function:
  2455. * _VCSndLineTraining
  2456. *
  2457. * Description:
  2458. * Meassures the line bandwidth
  2459. *
  2460. */
  2461. BOOL
  2462. _VCSndLineTraining(
  2463. HANDLE hReadEvent,
  2464. HANDLE hDGramEvent
  2465. )
  2466. {
  2467. BOOL rv = FALSE;
  2468. DWORD dwLineBandwidth = 0;
  2469. _DGramOpen();
  2470. //
  2471. // test this line while it's hot
  2472. //
  2473. if ( !g_dwDisableDGram )
  2474. {
  2475. dwLineBandwidth = _VCSndLineDGramTraining( hDGramEvent );
  2476. }
  2477. if (0 == dwLineBandwidth || g_dwDisableDGram)
  2478. {
  2479. TRC(WRN, "_VCSndLineTraining: no bandwidth trough UDP\n");
  2480. g_ulDGramAddress = 0;
  2481. g_dwDGramPort = 0;
  2482. g_EncryptionLevel = 0;
  2483. dwLineBandwidth = _VCSndLineVCTraining( hReadEvent );
  2484. if (0 == dwLineBandwidth)
  2485. {
  2486. TRC(WRN, "_VCSndLineTraining: no bandwidth "
  2487. "trough VC either. GIVING up\n");
  2488. goto exitpt;
  2489. }
  2490. } else {
  2491. if ( g_wClientVersion == 1 )
  2492. g_EncryptionLevel = 0;
  2493. }
  2494. //
  2495. // check for encryption
  2496. //
  2497. if ( g_EncryptionLevel >= MIN_ENCRYPT_LEVEL )
  2498. {
  2499. TRC( INF, "Encryption enabled\n" );
  2500. if ( TSRNG_GenerateRandomBits( g_EncryptKey, RANDOM_KEY_LENGTH))
  2501. {
  2502. SL_SendKey();
  2503. } else {
  2504. TRC( ERR, "_VCSndLineTraining: failing to generate random numbers. GIVING up\n" );
  2505. goto exitpt;
  2506. }
  2507. }
  2508. //
  2509. // check for limitations
  2510. //
  2511. if ((DWORD)-1 != g_dwMaxBandwidth &&
  2512. dwLineBandwidth > g_dwMaxBandwidth )
  2513. {
  2514. dwLineBandwidth = g_dwMaxBandwidth;
  2515. TRC(INF, "Bandwidth limited up to %d\n",
  2516. dwLineBandwidth );
  2517. }
  2518. if ( dwLineBandwidth < g_dwMinBandwidth )
  2519. {
  2520. dwLineBandwidth = g_dwMinBandwidth;
  2521. TRC(INF, "Bandwidth limited to at least %d\n",
  2522. dwLineBandwidth );
  2523. }
  2524. rv = TRUE;
  2525. exitpt:
  2526. g_dwLineBandwidth = dwLineBandwidth;
  2527. return rv;
  2528. }
  2529. /*
  2530. * Function:
  2531. * VCSndNegotiateWaveFormat
  2532. *
  2533. * Description:
  2534. * Requests the client for a list of supported formats
  2535. *
  2536. */
  2537. BOOL
  2538. VCSndNegotiateWaveFormat(
  2539. HANDLE hReadEvent,
  2540. HANDLE hDGramEvent
  2541. )
  2542. {
  2543. BOOL rv = FALSE;
  2544. PVCSNDFORMATLIST pIter;
  2545. BOOL bSuccess;
  2546. PSNDFORMATMSG pSndFormats;
  2547. PSNDFORMATMSG pSndResp;
  2548. PSNDFORMATITEM pSndFmt;
  2549. SNDMESSAGE SndMessage;
  2550. DWORD msgsize;
  2551. DWORD maxsize;
  2552. DWORD i;
  2553. DWORD dwNewFmt;
  2554. DWORD dwSoundCaps = 0;
  2555. DWORD dwVolume;
  2556. DWORD dwPitch;
  2557. DWORD BestChannels;
  2558. DWORD BestSamplesPerSec;
  2559. DWORD BestBitsPerSample;
  2560. DWORD dwPacketSize;
  2561. BOOL bWMADetected = FALSE;
  2562. //
  2563. // clean the previously negotiated format
  2564. //
  2565. if (NULL != g_ppNegotiatedFormats)
  2566. {
  2567. DWORD i;
  2568. for ( i = 0; i < g_dwNegotiatedFormats; i++ )
  2569. {
  2570. if ( NULL != g_ppNegotiatedFormats[i] )
  2571. TSFREE( g_ppNegotiatedFormats[i] );
  2572. }
  2573. TSFREE( g_ppNegotiatedFormats );
  2574. g_ppNegotiatedFormats = NULL;
  2575. g_dwNegotiatedFormats = 0;
  2576. g_hacmDriverId = NULL;
  2577. }
  2578. memset( &SndMessage, 0, sizeof( SndMessage ));
  2579. //
  2580. // get the list of all codec formats
  2581. //
  2582. if ( NULL == g_pAllCodecsFormatList )
  2583. {
  2584. bSuccess = VCSndEnumAllCodecFormats(
  2585. &g_pAllCodecsFormatList,
  2586. &g_dwAllCodecsNumber
  2587. );
  2588. if (!bSuccess)
  2589. goto exitpt;
  2590. }
  2591. //
  2592. // create a packet huge enough to hold all formats
  2593. //
  2594. msgsize = sizeof( *pSndFormats ) +
  2595. sizeof( SNDFORMATITEM ) * g_dwAllCodecsNumber;
  2596. //
  2597. // calculate the extra data needed by all format
  2598. //
  2599. for( maxsize = 0, pIter = g_pAllCodecsFormatList;
  2600. NULL != pIter;
  2601. pIter = pIter->pNext )
  2602. {
  2603. msgsize += pIter->Format.cbSize;
  2604. if (maxsize < pIter->Format.cbSize)
  2605. maxsize = pIter->Format.cbSize;
  2606. }
  2607. __try {
  2608. pSndFormats = (PSNDFORMATMSG) alloca( msgsize );
  2609. } __except((EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) ?
  2610. EXCEPTION_EXECUTE_HANDLER :
  2611. EXCEPTION_CONTINUE_SEARCH)
  2612. {
  2613. _resetstkoflw();
  2614. pSndFormats = NULL;
  2615. }
  2616. if ( NULL == pSndFormats )
  2617. {
  2618. TRC(ERR, "VCSndNegotiateWaveFormat: alloca failed for %d bytes\n",
  2619. msgsize);
  2620. goto exitpt;
  2621. }
  2622. pSndFormats->Prolog.Type = SNDC_FORMATS;
  2623. pSndFormats->Prolog.BodySize = (UINT16)( msgsize - sizeof( pSndFormats->Prolog ));
  2624. pSndFormats->wNumberOfFormats = (UINT16)g_dwAllCodecsNumber;
  2625. pSndFormats->cLastBlockConfirmed = g_Stream->cLastBlockConfirmed;
  2626. pSndFormats->wVersion = RDPSND_PROTOCOL_VERSION;
  2627. for ( i = 0, pSndFmt = (PSNDFORMATITEM) (pSndFormats + 1),
  2628. pIter = g_pAllCodecsFormatList;
  2629. i < g_dwAllCodecsNumber;
  2630. i++,
  2631. pSndFmt = (PSNDFORMATITEM)
  2632. (((LPSTR)pSndFmt) +
  2633. sizeof( *pSndFmt ) + pSndFmt->cbSize),
  2634. pIter = pIter->pNext )
  2635. {
  2636. ASSERT(NULL != pIter);
  2637. pSndFmt->wFormatTag = pIter->Format.wFormatTag;
  2638. pSndFmt->nChannels = pIter->Format.nChannels;
  2639. pSndFmt->nSamplesPerSec = pIter->Format.nSamplesPerSec;
  2640. pSndFmt->nAvgBytesPerSec = pIter->Format.nAvgBytesPerSec;
  2641. pSndFmt->nBlockAlign = pIter->Format.nBlockAlign;
  2642. pSndFmt->wBitsPerSample = pIter->Format.wBitsPerSample;
  2643. pSndFmt->cbSize = pIter->Format.cbSize;
  2644. //
  2645. // copy the rest of the format data
  2646. //
  2647. memcpy( pSndFmt + 1, (&pIter->Format) + 1, pSndFmt->cbSize );
  2648. }
  2649. bSuccess = ChannelBlockWrite( pSndFormats, msgsize );
  2650. if (!bSuccess)
  2651. {
  2652. TRC(ERR, "VCSndNegotiateWaveFormat: ChannelBlockWrite failed: %d\n",
  2653. GetLastError());
  2654. goto exitpt;
  2655. }
  2656. do {
  2657. //
  2658. // Wait for response with a valid message
  2659. //
  2660. SndMessage.uiPrologReceived = 0;
  2661. SndMessage.uiBodyReceived = 0;
  2662. while(!ChannelReceiveMessage(&SndMessage, hReadEvent))
  2663. {
  2664. if (ERROR_IO_PENDING == GetLastError())
  2665. {
  2666. DWORD dwres;
  2667. HANDLE ahEvents[2];
  2668. ahEvents[0] = hReadEvent;
  2669. ahEvents[1] = g_hDisconnectEvent;
  2670. dwres = WaitForMultipleObjects(
  2671. sizeof(ahEvents)/sizeof(ahEvents[0]), // count
  2672. ahEvents, // events
  2673. FALSE, // wait all
  2674. DEFAULT_VC_TIMEOUT);
  2675. if (WAIT_TIMEOUT == dwres ||
  2676. WAIT_OBJECT_0 + 1 == dwres)
  2677. {
  2678. TRC(WRN, "VCSndNegotiateWaveFormat: timeout "
  2679. "waiting for response\n");
  2680. ChannelCancelIo();
  2681. ResetEvent(hReadEvent);
  2682. goto exitpt;
  2683. }
  2684. ChannelBlockReadComplete();
  2685. ResetEvent(hReadEvent);
  2686. } else
  2687. if (ERROR_SUCCESS != GetLastError())
  2688. {
  2689. TRC(ERR, "VCSndNegotiateWaveFormat: "
  2690. "ChannelReceiveMessage failed: %d\n",
  2691. GetLastError());
  2692. goto exitpt;
  2693. }
  2694. }
  2695. } while (SNDC_FORMATS != SndMessage.Prolog.Type);
  2696. if (SndMessage.Prolog.BodySize <
  2697. sizeof( SNDFORMATMSG ) - sizeof( SNDPROLOG ))
  2698. {
  2699. TRC(ERR, "VCSndNegotiateWaveFormat: SNDC_FORMAT message "
  2700. "invalid body size: %d\n",
  2701. SndMessage.Prolog.BodySize );
  2702. }
  2703. pSndResp = (PSNDFORMATMSG)
  2704. (((LPSTR)SndMessage.pBody) - sizeof( SNDPROLOG ));
  2705. // save the capabilities
  2706. //
  2707. dwSoundCaps = pSndResp->dwFlags;
  2708. dwVolume = pSndResp->dwVolume;
  2709. dwPitch = pSndResp->dwPitch;
  2710. g_dwDGramPort = pSndResp->wDGramPort;
  2711. g_wClientVersion = pSndResp->wVersion;
  2712. //
  2713. // Expect at least one format returned
  2714. //
  2715. if (SndMessage.Prolog.BodySize <
  2716. sizeof( SNDFORMATITEM ) +
  2717. sizeof( SNDFORMATMSG ) - sizeof( SNDPROLOG ))
  2718. {
  2719. TRC(ERR, "VCSndNegotiateWaveFormat: SNDC_FORMAT message "
  2720. "w/ invalid size (%d). No supported formats\n",
  2721. SndMessage.Prolog.BodySize );
  2722. goto exitpt;
  2723. }
  2724. //
  2725. // train this line
  2726. //
  2727. if ( 0 != ( dwSoundCaps & TSSNDCAPS_ALIVE ))
  2728. {
  2729. if (!_VCSndLineTraining( hReadEvent, hDGramEvent ))
  2730. {
  2731. TRC( WRN, "VCSndIo: can't talk to the client, go silent\n" );
  2732. dwSoundCaps = 0;
  2733. }
  2734. }
  2735. //
  2736. // allocate a new list
  2737. //
  2738. g_dwNegotiatedFormats = pSndResp->wNumberOfFormats;
  2739. g_ppNegotiatedFormats = (PSNDFORMATITEM*) TSMALLOC( sizeof( g_ppNegotiatedFormats[0] ) *
  2740. g_dwNegotiatedFormats );
  2741. memset( g_ppNegotiatedFormats, 0,
  2742. sizeof( g_ppNegotiatedFormats[0] ) * g_dwNegotiatedFormats );
  2743. if ( NULL == g_ppNegotiatedFormats )
  2744. {
  2745. TRC(ERR, "VCSndNegotiateWaveFormat: can't allocate %d bytes\n",
  2746. sizeof( g_ppNegotiatedFormats[0] ) * g_dwNegotiatedFormats);
  2747. goto exitpt;
  2748. }
  2749. //
  2750. // allocate space for each entry in the list
  2751. //
  2752. for ( i = 0; i < g_dwNegotiatedFormats; i ++ )
  2753. {
  2754. g_ppNegotiatedFormats[i] = (PSNDFORMATITEM) TSMALLOC( sizeof( **g_ppNegotiatedFormats ) +
  2755. maxsize);
  2756. if ( NULL == g_ppNegotiatedFormats[i] )
  2757. {
  2758. TRC(ERR, "VCSndNegotiateWaveFormat: can't allocate %d bytes\n",
  2759. sizeof( **g_ppNegotiatedFormats ) + maxsize );
  2760. goto exitpt;
  2761. }
  2762. }
  2763. //
  2764. // Fill in the global list
  2765. //
  2766. pSndFmt = (PSNDFORMATITEM)(pSndResp + 1);
  2767. dwPacketSize = sizeof( SNDPROLOG ) + SndMessage.Prolog.BodySize - sizeof( *pSndResp );
  2768. for( i = 0; i < g_dwNegotiatedFormats; i++)
  2769. {
  2770. DWORD adv = sizeof( *pSndFmt ) + pSndFmt->cbSize;
  2771. if ( adv > dwPacketSize )
  2772. {
  2773. TRC( ERR, "VCSndNegotiateWaveFormat: invalid response packet size\n" );
  2774. ASSERT( 0 );
  2775. goto exitpt;
  2776. }
  2777. if ( pSndFmt->cbSize > maxsize )
  2778. {
  2779. TRC(ERR, "VCSndNegotiateWaveFormat: invalid format size\n" );
  2780. ASSERT( 0 );
  2781. goto exitpt;
  2782. }
  2783. memcpy( g_ppNegotiatedFormats[i],
  2784. pSndFmt,
  2785. sizeof( *g_ppNegotiatedFormats[0] ) + pSndFmt->cbSize );
  2786. //
  2787. // advance to the next format
  2788. //
  2789. pSndFmt = (PSNDFORMATITEM)(((LPSTR)pSndFmt) + adv);
  2790. dwPacketSize -= adv;
  2791. }
  2792. ASSERT( 0 == dwPacketSize );
  2793. //
  2794. // prune the formats
  2795. // ie, don't allow 8khZ mono codec to be between
  2796. // 22kHz and 11kHz stereo
  2797. // This is the order of imporatnce: frquency, channels, bits, bytes/s
  2798. //
  2799. #if DBG
  2800. TRC( INF, "======== Pruning formats =========. num=%d\n\n", g_dwNegotiatedFormats );
  2801. #endif
  2802. BestSamplesPerSec = 0;
  2803. BestChannels = 0;
  2804. BestBitsPerSample = 0;
  2805. for( i = g_dwNegotiatedFormats; i > 0; i-- )
  2806. {
  2807. PSNDFORMATITEM pDest = g_ppNegotiatedFormats[i - 1];
  2808. if ( WAVE_FORMAT_MPEGLAYER3 == pDest->wFormatTag && bWMADetected )
  2809. {
  2810. goto bad_codec;
  2811. }
  2812. if ( WAVE_FORMAT_WMAUDIO2 == pDest->wFormatTag )
  2813. {
  2814. bWMADetected = TRUE;
  2815. }
  2816. //
  2817. // a complex check for the order
  2818. //
  2819. if ( BestSamplesPerSec > pDest->nSamplesPerSec )
  2820. {
  2821. goto bad_codec;
  2822. } else if ( BestSamplesPerSec == pDest->nSamplesPerSec )
  2823. {
  2824. if ( BestChannels > pDest->nChannels )
  2825. {
  2826. goto bad_codec;
  2827. #if 0
  2828. } else if ( BestChannels == pDest->nChannels )
  2829. {
  2830. if ( BestBitsPerSample > pDest->wBitsPerSample )
  2831. {
  2832. goto bad_codec;
  2833. }
  2834. #endif
  2835. }
  2836. }
  2837. //
  2838. // good codec, keep it
  2839. //
  2840. BestChannels = pDest->nChannels;
  2841. BestBitsPerSample = pDest->wBitsPerSample;
  2842. BestSamplesPerSec = pDest->nSamplesPerSec;
  2843. #if 0
  2844. TRC(INF, "GOOD ag=%d chans=%d rate=%d, bps=%d, bpsamp=%d\n",
  2845. pDest->wFormatTag, pDest->nChannels, pDest->nSamplesPerSec, pDest->nAvgBytesPerSec, pDest->wBitsPerSample
  2846. );
  2847. #endif
  2848. continue;
  2849. bad_codec:
  2850. //
  2851. // bad codec, delete
  2852. //
  2853. #if 0
  2854. TRC(INF, "BAD ag=%d chans=%d rate=%d, bps=%d, bpsamp=%d\n",
  2855. pDest->wFormatTag, pDest->nChannels, pDest->nSamplesPerSec, pDest->nAvgBytesPerSec, pDest->wBitsPerSample
  2856. );
  2857. #endif
  2858. TSFREE( pDest );
  2859. g_ppNegotiatedFormats[i - 1] = NULL;
  2860. }
  2861. //
  2862. // choose the first format as a default
  2863. //
  2864. dwNewFmt = _VCSndChooseProperFormat( g_dwLineBandwidth );
  2865. if (dwNewFmt != (DWORD) -1)
  2866. {
  2867. //
  2868. // get a valid driver id
  2869. //
  2870. _VCSndGetACMDriverId( g_ppNegotiatedFormats[ dwNewFmt ] );
  2871. g_dwCurrentFormat = dwNewFmt;
  2872. //
  2873. // correct the new bandwidth
  2874. //
  2875. g_dwLineBandwidth = g_ppNegotiatedFormats[ dwNewFmt ]->nAvgBytesPerSec;
  2876. }
  2877. //
  2878. // remember the stream settings
  2879. //
  2880. if ( 0 != dwSoundCaps )
  2881. {
  2882. //
  2883. // set the remote sound caps
  2884. //
  2885. if (VCSndAcquireStream())
  2886. {
  2887. g_Stream->dwSoundCaps = dwSoundCaps;
  2888. g_Stream->dwVolume = dwVolume;
  2889. g_Stream->dwPitch = dwPitch;
  2890. VCSndReleaseStream();
  2891. }
  2892. }
  2893. rv = TRUE;
  2894. exitpt:
  2895. // don't forget to free the body of the eventually received message
  2896. //
  2897. if ( NULL != SndMessage.pBody )
  2898. TSFREE( SndMessage.pBody );
  2899. //
  2900. // in case of error cleanup the negotiated format
  2901. //
  2902. if ( !rv && NULL != g_ppNegotiatedFormats )
  2903. {
  2904. for ( i = 0; i < g_dwNegotiatedFormats; i++ )
  2905. {
  2906. if ( NULL != g_ppNegotiatedFormats[i] )
  2907. TSFREE( g_ppNegotiatedFormats[i] );
  2908. }
  2909. TSFREE( g_ppNegotiatedFormats );
  2910. g_ppNegotiatedFormats = NULL;
  2911. g_dwNegotiatedFormats = 0;
  2912. g_hacmDriverId = NULL;
  2913. }
  2914. return rv;
  2915. }
  2916. /*
  2917. * Function:
  2918. * _VCSndFindNativeFormat
  2919. *
  2920. * Description:
  2921. * returns the ID of the native format ( no codecs available )
  2922. *
  2923. */
  2924. DWORD
  2925. _VCSndFindNativeFormat(
  2926. VOID
  2927. )
  2928. {
  2929. PSNDFORMATITEM pIter;
  2930. DWORD rv = 0;
  2931. if ( NULL == g_ppNegotiatedFormats )
  2932. {
  2933. TRC(ERR, "_VCSndFindNativeFormat: no format cache\n");
  2934. goto exitpt;
  2935. }
  2936. for( rv = 0; rv < g_dwNegotiatedFormats; rv++ )
  2937. {
  2938. pIter = g_ppNegotiatedFormats[ rv ];
  2939. if (pIter->wFormatTag == WAVE_FORMAT_PCM &&
  2940. pIter->nChannels == TSSND_NATIVE_CHANNELS &&
  2941. pIter->nSamplesPerSec == TSSND_NATIVE_SAMPLERATE &&
  2942. pIter->nAvgBytesPerSec == TSSND_NATIVE_AVGBYTESPERSEC &&
  2943. pIter->nBlockAlign == TSSND_NATIVE_BLOCKALIGN &&
  2944. pIter->wBitsPerSample == TSSND_NATIVE_BITSPERSAMPLE &&
  2945. pIter->cbSize == 0)
  2946. //
  2947. // format is found
  2948. //
  2949. break;
  2950. }
  2951. ASSERT( rv < g_dwNegotiatedFormats );
  2952. exitpt:
  2953. return rv;
  2954. }
  2955. /*
  2956. * Function:
  2957. * _VCSndOpenConverter
  2958. *
  2959. * Description:
  2960. * Opens a codec
  2961. *
  2962. */
  2963. BOOL
  2964. _VCSndOpenConverter(
  2965. VOID
  2966. )
  2967. {
  2968. BOOL rv = FALSE;
  2969. MMRESULT mmres;
  2970. WAVEFORMATEX NativeFormat;
  2971. PSNDFORMATITEM pSndFmt;
  2972. PVCSNDFORMATLIST pIter;
  2973. BOOL bSucc;
  2974. //
  2975. // assert that these wasn't opened before
  2976. //
  2977. ASSERT(NULL == g_hacmDriver);
  2978. ASSERT(NULL == g_hacmStream);
  2979. if ( NULL == g_ppNegotiatedFormats )
  2980. {
  2981. TRC(INF, "_VCSndOpenConverter: no acm format specified\n");
  2982. goto exitpt;
  2983. }
  2984. //
  2985. // Find the acm format id
  2986. //
  2987. pSndFmt = g_ppNegotiatedFormats[ g_dwCurrentFormat ];
  2988. for( pIter = g_pAllCodecsFormatList; NULL != pIter; pIter = pIter->pNext )
  2989. {
  2990. if (pIter->Format.wFormatTag == pSndFmt->wFormatTag &&
  2991. pIter->Format.nChannels == pSndFmt->nChannels &&
  2992. pIter->Format.nSamplesPerSec == pSndFmt->nSamplesPerSec &&
  2993. pIter->Format.nAvgBytesPerSec == pSndFmt->nAvgBytesPerSec &&
  2994. pIter->Format.nBlockAlign == pSndFmt->nBlockAlign &&
  2995. pIter->Format.wBitsPerSample == pSndFmt->wBitsPerSample &&
  2996. pIter->Format.cbSize == pSndFmt->cbSize &&
  2997. 0 == memcmp((&pIter->Format) + 1, pSndFmt + 1, pIter->Format.cbSize)
  2998. )
  2999. {
  3000. //
  3001. // format is found
  3002. //
  3003. g_hacmDriverId = pIter->hacmDriverId;
  3004. break;
  3005. }
  3006. }
  3007. if (NULL == g_hacmDriverId)
  3008. {
  3009. TRC(ERR, "_VCSndOpenConverter: acm driver id was not found\n");
  3010. goto exitpt;
  3011. }
  3012. TRC(INF, "_VCSndOpenConverter: format received is:\n");
  3013. TRC(INF, "FormatTag - %d\n", pSndFmt->wFormatTag);
  3014. TRC(INF, "Channels - %d\n", pSndFmt->nChannels);
  3015. TRC(INF, "SamplesPerSec - %d\n", pSndFmt->nSamplesPerSec);
  3016. TRC(INF, "AvgBytesPerSec - %d\n", pSndFmt->nAvgBytesPerSec);
  3017. TRC(INF, "BlockAlign - %d\n", pSndFmt->nBlockAlign);
  3018. TRC(INF, "BitsPerSample - %d\n", pSndFmt->wBitsPerSample);
  3019. TRC(INF, "cbSize - %d\n", pSndFmt->cbSize);
  3020. TRC(INF, "acmFormatId - %p\n", g_hacmDriverId);
  3021. mmres = acmDriverOpen(
  3022. &g_hacmDriver,
  3023. g_hacmDriverId,
  3024. 0
  3025. );
  3026. if (MMSYSERR_NOERROR != mmres)
  3027. {
  3028. TRC(ERR, "_VCSndOpenConverter: unable to open acm driver: %d\n",
  3029. mmres);
  3030. goto exitpt;
  3031. }
  3032. TRC(ALV, "_VCSndOpenConverter: Driver is open, DriverId = %p\n",
  3033. g_hacmDriverId);
  3034. //
  3035. // first, find a suggested format for this converter
  3036. //
  3037. pSndFmt = g_ppNegotiatedFormats[ g_dwCurrentFormat ];
  3038. if ( WAVE_FORMAT_PCM == pSndFmt->wFormatTag &&
  3039. TSSND_NATIVE_CHANNELS == pSndFmt->nChannels &&
  3040. TSSND_NATIVE_SAMPLERATE == pSndFmt->nSamplesPerSec &&
  3041. TSSND_NATIVE_AVGBYTESPERSEC == pSndFmt->nAvgBytesPerSec &&
  3042. TSSND_NATIVE_BLOCKALIGN == pSndFmt->nBlockAlign &&
  3043. TSSND_NATIVE_BITSPERSAMPLE == pSndFmt->wBitsPerSample &&
  3044. 0 == pSndFmt->cbSize )
  3045. {
  3046. TRC(INF, "_VCSndOpenConverter: opening native format, no converter\n");
  3047. goto exitpt;
  3048. }
  3049. bSucc = _VCSndFindSuggestedConverter(
  3050. g_hacmDriverId,
  3051. (LPWAVEFORMATEX)pSndFmt,
  3052. &NativeFormat,
  3053. &g_pfnConverter);
  3054. if (!bSucc)
  3055. {
  3056. TRC(FATAL, "_VCSndOpenConverter: can't find a suggested format\n");
  3057. goto exitpt;
  3058. }
  3059. TRC(ALV, "_VCSndOpenConverter: SOURCE format is:\n");
  3060. TRC(ALV, "FormatTag - %d\n", NativeFormat.wFormatTag);
  3061. TRC(ALV, "Channels - %d\n", NativeFormat.nChannels);
  3062. TRC(ALV, "SamplesPerSec - %d\n", NativeFormat.nSamplesPerSec);
  3063. TRC(ALV, "AvgBytesPerSec - %d\n", NativeFormat.nAvgBytesPerSec);
  3064. TRC(ALV, "BlockAlign - %d\n", NativeFormat.nBlockAlign);
  3065. TRC(ALV, "BitsPerSample - %d\n", NativeFormat.wBitsPerSample);
  3066. TRC(ALV, "cbSize - %d\n", NativeFormat.cbSize);
  3067. TRC(ALV, "_VCSndOpenConverter: DESTINATION format is:\n");
  3068. TRC(ALV, "FormatTag - %d\n", pSndFmt->wFormatTag);
  3069. TRC(ALV, "Channels - %d\n", pSndFmt->nChannels);
  3070. TRC(ALV, "SamplesPerSec - %d\n", pSndFmt->nSamplesPerSec);
  3071. TRC(ALV, "AvgBytesPerSec - %d\n", pSndFmt->nAvgBytesPerSec);
  3072. TRC(ALV, "BlockAlign - %d\n", pSndFmt->nBlockAlign);
  3073. TRC(ALV, "BitsPerSample - %d\n", pSndFmt->wBitsPerSample);
  3074. TRC(ALV, "cbSize - %d\n", pSndFmt->cbSize);
  3075. mmres = acmStreamOpen(
  3076. &g_hacmStream,
  3077. g_hacmDriver,
  3078. &NativeFormat,
  3079. (LPWAVEFORMATEX)pSndFmt,
  3080. NULL, // no filter
  3081. 0, // no callback
  3082. 0, // no callback instance
  3083. ACM_STREAMOPENF_NONREALTIME
  3084. );
  3085. if (MMSYSERR_NOERROR != mmres)
  3086. {
  3087. TRC(ERR, "_VCSndOpenConverter: unable to open acm stream: %d\n",
  3088. mmres);
  3089. goto exitpt;
  3090. }
  3091. g_dwDataRemain = 0;
  3092. rv = TRUE;
  3093. exitpt:
  3094. if (!rv)
  3095. {
  3096. _VCSndCloseConverter();
  3097. g_dwCurrentFormat = _VCSndFindNativeFormat();
  3098. }
  3099. return rv;
  3100. }
  3101. /*
  3102. * Function:
  3103. * _VCSndCloseConverter
  3104. *
  3105. * Description:
  3106. * Closes the codec
  3107. *
  3108. */
  3109. VOID
  3110. _VCSndCloseConverter(
  3111. VOID
  3112. )
  3113. {
  3114. if (g_hacmStream)
  3115. {
  3116. acmStreamClose( g_hacmStream, 0 );
  3117. g_hacmStream = NULL;
  3118. }
  3119. if (g_hacmDriver)
  3120. {
  3121. acmDriverClose( g_hacmDriver, 0 );
  3122. g_hacmDriver = NULL;
  3123. }
  3124. }
  3125. /*
  3126. * Function:
  3127. * _VCSndConvert
  3128. *
  3129. * Description:
  3130. * Convert a block
  3131. *
  3132. */
  3133. BOOL
  3134. _VCSndConvert(
  3135. PBYTE pSrc,
  3136. DWORD dwSrcSize,
  3137. PBYTE pDest,
  3138. DWORD *pdwDestSize )
  3139. {
  3140. BOOL rv = FALSE;
  3141. ACMSTREAMHEADER acmStreamHdr;
  3142. MMRESULT mmres, mmres2;
  3143. DWORD dwDestSize = 0;
  3144. DWORD dwSrcBlockAlign = 0;
  3145. DWORD dwNewDestSize = 0;
  3146. PBYTE pbRemDst;
  3147. DWORD dwRemDstLength;
  3148. ASSERT( NULL != g_hacmStream );
  3149. ASSERT( NULL != pdwDestSize );
  3150. //
  3151. // check if we have interrim converter
  3152. // use it, if so
  3153. //
  3154. if ( NULL != g_pfnConverter )
  3155. {
  3156. DWORD dwInterrimSize;
  3157. g_pfnConverter( (INT16 *)pSrc,
  3158. dwSrcSize,
  3159. &dwInterrimSize );
  3160. dwSrcSize = dwInterrimSize;
  3161. }
  3162. //
  3163. // compute the destination size
  3164. //
  3165. mmres = acmStreamSize(
  3166. g_hacmStream,
  3167. dwSrcSize,
  3168. &dwNewDestSize,
  3169. ACM_STREAMSIZEF_SOURCE
  3170. );
  3171. if ( MMSYSERR_NOERROR != mmres )
  3172. {
  3173. TRC(ERR, "_VCSndConvert: acmStreamSize failed: %d\n",
  3174. mmres);
  3175. g_dwDataRemain = 0;
  3176. goto go_convert;
  3177. }
  3178. //
  3179. // align the source to a block of the destination
  3180. // the remainder put in a buffer for consequentive use
  3181. //
  3182. mmres = acmStreamSize(
  3183. g_hacmStream,
  3184. g_ppNegotiatedFormats[ g_dwCurrentFormat ]->nBlockAlign,
  3185. &dwSrcBlockAlign,
  3186. ACM_STREAMSIZEF_DESTINATION
  3187. );
  3188. if ( MMSYSERR_NOERROR != mmres )
  3189. {
  3190. TRC(ALV, "_VCSndConvert: acmStreamSize failed for dst len: %d\n",
  3191. mmres);
  3192. g_dwDataRemain = 0;
  3193. goto go_convert;
  3194. }
  3195. dwNewDestSize += g_ppNegotiatedFormats[ g_dwCurrentFormat ]->nBlockAlign;
  3196. if ( dwNewDestSize > *pdwDestSize )
  3197. {
  3198. TRC( FATAL, "_VCSndConvert: dest size(%d) "
  3199. "bigger than passed buffer(%d)\n",
  3200. dwNewDestSize,
  3201. *pdwDestSize);
  3202. goto exitpt;
  3203. }
  3204. *pdwDestSize = dwNewDestSize;
  3205. if ( dwSrcBlockAlign <= g_dwDataRemain )
  3206. g_dwDataRemain = 0;
  3207. go_convert:
  3208. //
  3209. // prepare the acm stream header
  3210. //
  3211. memset( &acmStreamHdr, 0, sizeof( acmStreamHdr ));
  3212. acmStreamHdr.cbStruct = sizeof( acmStreamHdr );
  3213. acmStreamHdr.pbDst = pDest;
  3214. acmStreamHdr.cbDstLength = *pdwDestSize;
  3215. //
  3216. // first convert the remainding data from the previous call
  3217. // add the data needed to complete one block
  3218. //
  3219. if ( 0 != g_dwDataRemain)
  3220. {
  3221. DWORD dwDataToCopy = dwSrcBlockAlign - g_dwDataRemain;
  3222. memcpy( g_pCnvPrevData + g_dwDataRemain,
  3223. pSrc,
  3224. dwDataToCopy);
  3225. pSrc += dwDataToCopy;
  3226. ASSERT( dwSrcSize > dwDataToCopy );
  3227. dwSrcSize -= dwDataToCopy;
  3228. acmStreamHdr.pbSrc = g_pCnvPrevData;
  3229. acmStreamHdr.cbSrcLength = dwSrcBlockAlign;
  3230. mmres = acmStreamPrepareHeader(
  3231. g_hacmStream,
  3232. &acmStreamHdr,
  3233. 0
  3234. );
  3235. if ( MMSYSERR_NOERROR != mmres )
  3236. {
  3237. TRC(ERR, "_VCSndConvert: acmStreamPrepareHeader failed: %d\n",
  3238. mmres);
  3239. goto exitpt;
  3240. }
  3241. mmres = acmStreamConvert(
  3242. g_hacmStream,
  3243. &acmStreamHdr,
  3244. ACM_STREAMCONVERTF_BLOCKALIGN
  3245. );
  3246. mmres2 = acmStreamUnprepareHeader(
  3247. g_hacmStream,
  3248. &acmStreamHdr,
  3249. 0
  3250. );
  3251. ASSERT( mmres == MMSYSERR_NOERROR );
  3252. if ( MMSYSERR_NOERROR != mmres )
  3253. {
  3254. TRC(ERR, "_VCSndConvert: acmStreamConvert failed: %d\n",
  3255. mmres );
  3256. } else {
  3257. dwDestSize += acmStreamHdr.cbDstLengthUsed;
  3258. acmStreamHdr.cbSrcLengthUsed= 0;
  3259. acmStreamHdr.pbDst += acmStreamHdr.cbDstLengthUsed;
  3260. acmStreamHdr.cbDstLength -= acmStreamHdr.cbDstLengthUsed;
  3261. acmStreamHdr.cbDstLengthUsed= 0;
  3262. }
  3263. }
  3264. //
  3265. // if we don't have fully aligned block
  3266. // skip this conversion, but don't forget to save
  3267. // this block
  3268. //
  3269. if (dwSrcSize < dwSrcBlockAlign)
  3270. {
  3271. g_dwDataRemain = dwSrcSize;
  3272. memcpy( g_pCnvPrevData, pSrc, g_dwDataRemain );
  3273. rv = TRUE;
  3274. goto exitpt;
  3275. }
  3276. pbRemDst = acmStreamHdr.pbDst;
  3277. dwRemDstLength = acmStreamHdr.cbDstLength;
  3278. acmStreamHdr.pbSrc = pSrc;
  3279. acmStreamHdr.cbSrcLength = dwSrcSize;
  3280. acmStreamHdr.fdwStatus = 0;
  3281. mmres = acmStreamPrepareHeader(
  3282. g_hacmStream,
  3283. &acmStreamHdr,
  3284. 0
  3285. );
  3286. if ( MMSYSERR_NOERROR != mmres )
  3287. {
  3288. TRC(ERR, "_VCSndConvert: can't prepare header: %d\n",
  3289. mmres);
  3290. goto exitpt;
  3291. }
  3292. while (acmStreamHdr.cbSrcLength > dwSrcBlockAlign)
  3293. {
  3294. mmres = acmStreamConvert(
  3295. g_hacmStream,
  3296. &acmStreamHdr,
  3297. ACM_STREAMCONVERTF_BLOCKALIGN
  3298. );
  3299. if ( MMSYSERR_NOERROR != mmres )
  3300. {
  3301. TRC(ERR, "_VCSndConvert: acmStreamConvert failed: %d\n",
  3302. mmres);
  3303. goto exitpt;
  3304. }
  3305. //
  3306. // advance the buffer positions
  3307. //
  3308. acmStreamHdr.pbSrc += acmStreamHdr.cbSrcLengthUsed;
  3309. acmStreamHdr.pbDst += acmStreamHdr.cbDstLengthUsed;
  3310. acmStreamHdr.cbSrcLength -= acmStreamHdr.cbSrcLengthUsed;
  3311. acmStreamHdr.cbDstLength -= acmStreamHdr.cbDstLengthUsed;
  3312. dwDestSize += acmStreamHdr.cbDstLengthUsed;
  3313. acmStreamHdr.cbSrcLengthUsed= 0;
  3314. acmStreamHdr.cbDstLengthUsed= 0;
  3315. }
  3316. rv = TRUE;
  3317. //
  3318. // save the unaligned data
  3319. //
  3320. if ( 0 != dwSrcBlockAlign )
  3321. {
  3322. g_dwDataRemain = acmStreamHdr.cbSrcLength;
  3323. memcpy( g_pCnvPrevData, acmStreamHdr.pbSrc, g_dwDataRemain );
  3324. }
  3325. //
  3326. // restore the header and unprepare
  3327. //
  3328. acmStreamHdr.pbSrc = pSrc;
  3329. acmStreamHdr.pbDst = pbRemDst;
  3330. acmStreamHdr.cbSrcLength = dwSrcSize;
  3331. acmStreamHdr.cbSrcLengthUsed= 0;
  3332. acmStreamHdr.cbDstLength = dwRemDstLength;
  3333. acmStreamHdr.cbDstLengthUsed= 0;
  3334. mmres = acmStreamUnprepareHeader(
  3335. g_hacmStream,
  3336. &acmStreamHdr,
  3337. 0
  3338. );
  3339. ASSERT( mmres == MMSYSERR_NOERROR );
  3340. exitpt:
  3341. *pdwDestSize = dwDestSize;
  3342. return rv;
  3343. }
  3344. /*
  3345. * Function:
  3346. * _VCSndCheckDevice
  3347. *
  3348. * Description:
  3349. * Initializes capabilities negotiations with the client
  3350. *
  3351. */
  3352. VOID
  3353. _VCSndCheckDevice(
  3354. HANDLE hReadEvent,
  3355. HANDLE hDGramEvent
  3356. )
  3357. {
  3358. SNDPROLOG Prolog;
  3359. BOOL bSuccess;
  3360. //
  3361. // no sound caps yet
  3362. //
  3363. g_Stream->dwSoundCaps = 0;
  3364. //
  3365. // find the best compression for this audio line
  3366. //
  3367. if ( !VCSndNegotiateWaveFormat( hReadEvent, hDGramEvent ))
  3368. {
  3369. ChannelClose();
  3370. }
  3371. }
  3372. /*
  3373. * Function:
  3374. * _VCSndCloseDevice
  3375. *
  3376. * Description:
  3377. * Closes the remote device
  3378. *
  3379. */
  3380. VOID
  3381. _VCSndCloseDevice(
  3382. VOID
  3383. )
  3384. {
  3385. if (!VCSndAcquireStream())
  3386. {
  3387. TRC(FATAL, "_VCSndCloseDevice: Can't acquire stream mutex. exit\n");
  3388. goto exitpt;
  3389. }
  3390. // disable the local audio
  3391. //
  3392. g_Stream->dwSoundCaps = 0;
  3393. g_bDeviceOpened = FALSE;
  3394. g_dwLineBandwidth = 0;
  3395. VCSndReleaseStream();
  3396. exitpt:
  3397. ;
  3398. }
  3399. /*
  3400. * Function:
  3401. * _VCSndSendWave
  3402. *
  3403. * Description:
  3404. * Sends a wave data to the client using UDP
  3405. *
  3406. */
  3407. BOOL
  3408. _VCSndSendWaveDGram(
  3409. BYTE cBlockNo,
  3410. PVOID pData,
  3411. DWORD dwDataSize
  3412. )
  3413. {
  3414. BOOL bSucc = FALSE;
  3415. struct sockaddr_in sin;
  3416. INT sendres;
  3417. PSNDWAVE pSndWave;
  3418. //
  3419. // encrypt the packet if necessary
  3420. //
  3421. if ( g_EncryptionLevel >= MIN_ENCRYPT_LEVEL )
  3422. if ( !SL_Encrypt( (PBYTE)pData, ( g_HiBlockNo << 8 ) + cBlockNo, dwDataSize ))
  3423. goto exitpt;
  3424. __try {
  3425. pSndWave = (PSNDWAVE) alloca(g_dwDGramSize);
  3426. } __except((EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) ?
  3427. EXCEPTION_EXECUTE_HANDLER :
  3428. EXCEPTION_CONTINUE_SEARCH)
  3429. {
  3430. _resetstkoflw();
  3431. pSndWave = NULL;
  3432. TRC(ERR, "_VCSndSendWaveDGram: alloca generate exception: %d\n",
  3433. GetExceptionCode());
  3434. }
  3435. if (NULL == pSndWave)
  3436. goto exitpt;
  3437. pSndWave->Prolog.Type = (g_EncryptionLevel >= MIN_ENCRYPT_LEVEL)?SNDC_WAVEENCRYPT:SNDC_WAVE;
  3438. pSndWave->wFormatNo = (UINT16)g_dwCurrentFormat;
  3439. pSndWave->wTimeStamp = (UINT16)GetTickCount();
  3440. pSndWave->dwBlockNo = (g_HiBlockNo << 8) + cBlockNo;
  3441. // prepare the to address
  3442. //
  3443. sin.sin_family = PF_INET;
  3444. sin.sin_port = (u_short)g_dwDGramPort;
  3445. sin.sin_addr.s_addr = g_ulDGramAddress;
  3446. // Send the block in chunks of dwDGramSize
  3447. //
  3448. while (dwDataSize)
  3449. {
  3450. DWORD dwWaveDataLen;
  3451. dwWaveDataLen = (dwDataSize + sizeof(*pSndWave)
  3452. < g_dwDGramSize)
  3453. ?
  3454. dwDataSize:
  3455. g_dwDGramSize - sizeof(*pSndWave);
  3456. pSndWave->Prolog.BodySize = (UINT16)
  3457. ( sizeof(*pSndWave) -
  3458. sizeof(pSndWave->Prolog) +
  3459. dwWaveDataLen );
  3460. memcpy(pSndWave + 1, pData, dwWaveDataLen);
  3461. sendres = sendto(g_hDGramSocket,
  3462. (LPSTR)pSndWave,
  3463. sizeof(*pSndWave) + dwWaveDataLen,
  3464. 0, // flags
  3465. (struct sockaddr *)&sin, // to address
  3466. sizeof(sin));
  3467. if (SOCKET_ERROR == sendres)
  3468. {
  3469. TRC(ERR, "_VCSndSendWaveDGram: sendto failed: %d\n",
  3470. WSAGetLastError());
  3471. goto exitpt;
  3472. }
  3473. g_dwPacketSize = sizeof(*pSndWave) + dwWaveDataLen;
  3474. dwDataSize -= dwWaveDataLen;
  3475. pData = ((LPSTR)(pData)) + dwWaveDataLen;
  3476. }
  3477. bSucc = TRUE;
  3478. exitpt:
  3479. return bSucc;
  3480. }
  3481. BOOL
  3482. _VCSndSendWaveDGramInFrags(
  3483. BYTE cBlockNo,
  3484. PVOID pData,
  3485. DWORD dwDataSize
  3486. )
  3487. {
  3488. BOOL bSucc = FALSE;
  3489. struct sockaddr_in sin;
  3490. INT sendres;
  3491. PSNDUDPWAVE pWave;
  3492. PSNDUDPWAVELAST pLast;
  3493. PBYTE pSource;
  3494. PBYTE pEnd;
  3495. DWORD dwFragSize;
  3496. DWORD dwNumFrags;
  3497. DWORD count;
  3498. DWORD dwSize;
  3499. PVOID pBuffer;
  3500. UINT16 wStartTime;
  3501. ASSERT( CanUDPFragment( g_wClientVersion ) && dwDataSize <= 0x8000 + RDPSND_SIGNATURE_SIZE );
  3502. __try {
  3503. pBuffer = _alloca( g_dwDGramSize );
  3504. } __except((EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) ?
  3505. EXCEPTION_EXECUTE_HANDLER :
  3506. EXCEPTION_CONTINUE_SEARCH)
  3507. {
  3508. _resetstkoflw();
  3509. pBuffer = 0;
  3510. }
  3511. if ( NULL == pBuffer )
  3512. {
  3513. goto exitpt;
  3514. }
  3515. //
  3516. // calculate number of frags etc
  3517. //
  3518. dwFragSize = g_dwDGramSize - sizeof( *pLast );
  3519. dwNumFrags = dwDataSize / dwFragSize;
  3520. pSource = (PBYTE)pData;
  3521. pEnd = pSource + dwDataSize;
  3522. wStartTime = (UINT16)GetTickCount();
  3523. // prepare the to address
  3524. //
  3525. sin.sin_family = PF_INET;
  3526. sin.sin_port = (u_short)g_dwDGramPort;
  3527. sin.sin_addr.s_addr = g_ulDGramAddress;
  3528. //
  3529. // make sure we can fit all the frag counters
  3530. //
  3531. ASSERT( dwNumFrags < 0x7fff );
  3532. if ( 0 != dwNumFrags )
  3533. {
  3534. pWave = (PSNDUDPWAVE)pBuffer;
  3535. pWave->Type = SNDC_UDPWAVE;
  3536. pWave->cBlockNo = cBlockNo;
  3537. for( count = 0; count < dwNumFrags; count++ )
  3538. {
  3539. PBYTE pDest = (PBYTE)(&pWave->cFragNo);
  3540. dwSize = sizeof( *pWave ) + dwFragSize;
  3541. if ( count >= RDPSND_FRAGNO_EXT )
  3542. {
  3543. *pDest = (BYTE)(((count >> 8) & (~RDPSND_FRAGNO_EXT)) | RDPSND_FRAGNO_EXT);
  3544. pDest++;
  3545. *pDest = (BYTE)(count & 0xff);
  3546. dwSize++;
  3547. } else {
  3548. *pDest = (BYTE)count;
  3549. }
  3550. pDest++;
  3551. memcpy( pDest, pSource, dwFragSize );
  3552. sendres = sendto(
  3553. g_hDGramSocket,
  3554. (LPSTR)pWave,
  3555. dwSize,
  3556. 0, // flags
  3557. (struct sockaddr *)&sin, // to address
  3558. sizeof(sin));
  3559. if (SOCKET_ERROR == sendres)
  3560. {
  3561. TRC(ERR, "_VCSndSendWaveDGramInFrags: sendto failed: %d\n",
  3562. WSAGetLastError());
  3563. goto exitpt;
  3564. }
  3565. pSource += dwFragSize;
  3566. }
  3567. }
  3568. ASSERT( pSource <= pEnd );
  3569. //
  3570. // send the last fragment with all the extra info
  3571. //
  3572. pLast = (PSNDUDPWAVELAST)pBuffer;
  3573. pLast->Type = SNDC_UDPWAVELAST;
  3574. pLast->wTotalSize = (UINT16)dwDataSize;
  3575. pLast->wTimeStamp = wStartTime;
  3576. pLast->wFormatNo = (UINT16)g_dwCurrentFormat;
  3577. pLast->dwBlockNo = (g_HiBlockNo << 8) + cBlockNo;
  3578. dwSize = PtrToLong( (PVOID)( pEnd - pSource ));
  3579. memcpy( pLast + 1, pSource, dwSize );
  3580. sendres = sendto(
  3581. g_hDGramSocket,
  3582. (LPSTR)pLast,
  3583. dwSize + sizeof( *pLast ),
  3584. 0,
  3585. (struct sockaddr *)&sin,
  3586. sizeof(sin)
  3587. );
  3588. if (SOCKET_ERROR == sendres)
  3589. {
  3590. TRC(ERR, "_VCSndSendWaveDGramInFrags: sendto failed: %d\n",
  3591. WSAGetLastError());
  3592. goto exitpt;
  3593. }
  3594. g_dwPacketSize = dwNumFrags * sizeof( *pWave ) + sizeof( *pLast ) + dwDataSize;
  3595. bSucc = TRUE;
  3596. exitpt:
  3597. return bSucc;
  3598. }
  3599. BOOL
  3600. _VCSndSendWaveVC(
  3601. BYTE cBlockNo,
  3602. PVOID pData,
  3603. DWORD dwDataSize
  3604. )
  3605. {
  3606. BOOL bSucc = FALSE;
  3607. SNDWAVE Wave;
  3608. //
  3609. // send this block through the virtual channel
  3610. //
  3611. TRC(ALV, "_VCSndSendWave: sending through VC\n");
  3612. Wave.Prolog.Type = SNDC_WAVE;
  3613. Wave.cBlockNo = cBlockNo;
  3614. Wave.wFormatNo = (UINT16)g_dwCurrentFormat;
  3615. Wave.wTimeStamp = (UINT16)GetTickCount();
  3616. Wave.Prolog.BodySize = (UINT16)( sizeof(Wave) - sizeof(Wave.Prolog) +
  3617. dwDataSize );
  3618. bSucc = ChannelMessageWrite(
  3619. &Wave,
  3620. sizeof(Wave),
  3621. pData,
  3622. dwDataSize
  3623. );
  3624. g_dwPacketSize = sizeof(Wave) + Wave.Prolog.BodySize;
  3625. if (!bSucc)
  3626. {
  3627. TRC(ERR, "_VCSndSendWave: failed to send wave: %d\n",
  3628. GetLastError());
  3629. }
  3630. return bSucc;
  3631. }
  3632. /*
  3633. * Function:
  3634. * _VCSndSendWave
  3635. *
  3636. * Description:
  3637. * Sends a wave data to the client
  3638. *
  3639. */
  3640. BOOL
  3641. _VCSndSendWave(
  3642. BYTE cBlockNo,
  3643. PVOID pData,
  3644. DWORD dwDataSize
  3645. )
  3646. {
  3647. BOOL bSucc = FALSE;
  3648. static BYTE s_pDest[ TSSND_BLOCKSIZE + RDPSND_SIGNATURE_SIZE ];
  3649. PBYTE pDest = s_pDest + RDPSND_SIGNATURE_SIZE;
  3650. #if _SIM_RESAMPLE
  3651. //
  3652. // resample randomly
  3653. //
  3654. if ( NULL != g_ppNegotiatedFormats && 0 == (cBlockNo % 32) )
  3655. {
  3656. _VCSndCloseConverter();
  3657. g_dwCurrentFormat = rand() % g_dwNegotiatedFormats;
  3658. g_dwDataRemain = 0;
  3659. _VCSndOpenConverter();
  3660. }
  3661. #endif
  3662. _StatsCheckResample();
  3663. if ( NULL != g_hacmStream )
  3664. {
  3665. DWORD dwDestSize = TSSND_BLOCKSIZE;
  3666. if (!_VCSndConvert( (PBYTE) pData, dwDataSize, pDest, &dwDestSize ))
  3667. {
  3668. TRC(ERR, "_VCSndSendWave: conversion failed\n");
  3669. goto exitpt;
  3670. } else {
  3671. pData = pDest;
  3672. dwDataSize = dwDestSize;
  3673. }
  3674. } else {
  3675. //
  3676. // no conversion
  3677. // use the data as it is
  3678. // copy it in the s_pDest buffer
  3679. //
  3680. ASSERT( dwDataSize <= TSSND_BLOCKSIZE );
  3681. memcpy( pDest, pData, dwDataSize );
  3682. }
  3683. if (
  3684. INVALID_SOCKET != g_hDGramSocket &&
  3685. 0 != g_dwDGramPort &&
  3686. 0 != g_dwDGramSize &&
  3687. 0 != g_ulDGramAddress &&
  3688. 0 != g_dwLineBandwidth // if this is 0, we don't have UDP
  3689. )
  3690. {
  3691. // Send a datagram
  3692. //
  3693. if ( !CanUDPFragment( g_wClientVersion ) &&
  3694. dwDataSize + sizeof( SNDWAVE ) + RDPSND_SIGNATURE_SIZE > g_dwDGramSize )
  3695. {
  3696. //
  3697. // if the wave doesn't fit in the UDP packet use VCs
  3698. //
  3699. bSucc = _VCSndSendWaveVC( cBlockNo, pData, dwDataSize );
  3700. } else {
  3701. //
  3702. // add signature if necessary
  3703. //
  3704. if ( IsDGramWaveSigned( g_wClientVersion ))
  3705. {
  3706. if ( !IsDGramWaveAudioSigned( g_wClientVersion ))
  3707. {
  3708. SL_Signature( s_pDest, (g_HiBlockNo << 8) + cBlockNo );
  3709. } else {
  3710. SL_AudioSignature( s_pDest, (g_HiBlockNo << 8) + cBlockNo,
  3711. (PBYTE)pData, dwDataSize );
  3712. }
  3713. pData = s_pDest;
  3714. dwDataSize += RDPSND_SIGNATURE_SIZE;
  3715. }
  3716. if ( CanUDPFragment( g_wClientVersion ) &&
  3717. dwDataSize + sizeof( SNDWAVE ) > g_dwDGramSize )
  3718. {
  3719. bSucc = _VCSndSendWaveDGramInFrags( cBlockNo, pData, dwDataSize );
  3720. } else {
  3721. bSucc = _VCSndSendWaveDGram( cBlockNo, pData, dwDataSize );
  3722. }
  3723. }
  3724. } else {
  3725. bSucc = _VCSndSendWaveVC( cBlockNo, pData, dwDataSize );
  3726. }
  3727. TRC(ALV, "_VCSndSendWave: BlockNo: %d sent\n", cBlockNo);
  3728. exitpt:
  3729. return bSucc;
  3730. }
  3731. INT
  3732. WSInit(
  3733. VOID
  3734. )
  3735. {
  3736. WORD versionRequested;
  3737. WSADATA wsaData;
  3738. int intRC;
  3739. versionRequested = MAKEWORD(1, 1);
  3740. intRC = WSAStartup(versionRequested, &wsaData);
  3741. if (intRC != 0)
  3742. {
  3743. TRC(ERR, "Failed to initialize WinSock rc:%d\n", intRC);
  3744. }
  3745. return intRC;
  3746. }
  3747. /*
  3748. * Function:
  3749. * DGramRead
  3750. *
  3751. * Description:
  3752. * Reads an UDP message (datagram)
  3753. *
  3754. */
  3755. VOID
  3756. DGramRead(
  3757. HANDLE hDGramEvent,
  3758. PVOID *ppBuff,
  3759. DWORD *pdwSize
  3760. )
  3761. {
  3762. DWORD dwRecvd;
  3763. DWORD dwFlags;
  3764. INT rc;
  3765. if ( INVALID_SOCKET == g_hDGramSocket )
  3766. goto exitpt;
  3767. ASSERT( NULL != hDGramEvent );
  3768. do {
  3769. memset(&g_WSAOverlapped, 0, sizeof(g_WSAOverlapped));
  3770. g_WSAOverlapped.hEvent = hDGramEvent;
  3771. dwRecvd = 0;
  3772. dwFlags = 0;
  3773. g_wsabuf.len = sizeof( g_pDGramRecvData );
  3774. g_wsabuf.buf = (char *) g_pDGramRecvData;
  3775. rc = WSARecvFrom(
  3776. g_hDGramSocket,
  3777. &g_wsabuf,
  3778. 1,
  3779. &dwRecvd,
  3780. &dwFlags,
  3781. NULL, // no from address
  3782. NULL,
  3783. &g_WSAOverlapped,
  3784. NULL); // no completion routine
  3785. if ( 0 == rc )
  3786. {
  3787. //
  3788. // data received
  3789. //
  3790. SNDMESSAGE SndMsg;
  3791. if ( NULL != ppBuff && NULL != pdwSize )
  3792. {
  3793. //
  3794. // pass the data to the caller
  3795. //
  3796. *ppBuff = g_pDGramRecvData;
  3797. *pdwSize = dwRecvd;
  3798. goto exitpt;
  3799. }
  3800. if ( dwRecvd < sizeof( SNDPROLOG ))
  3801. {
  3802. TRC(WRN, "DGramRead: invalid message received: len=%d\n",
  3803. dwRecvd );
  3804. continue;
  3805. }
  3806. memcpy( &SndMsg.Prolog, g_pDGramRecvData, sizeof( SNDPROLOG ));
  3807. SndMsg.pBody = g_pDGramRecvData + sizeof( SNDPROLOG );
  3808. TRC(ALV, "DGramRead: data received\n");
  3809. // parse this packet
  3810. //
  3811. VCSndDataArrived( &SndMsg );
  3812. }
  3813. }
  3814. while ( SOCKET_ERROR != rc );
  3815. exitpt:
  3816. ;
  3817. }
  3818. /*
  3819. * Function:
  3820. * DGramReadCompletion
  3821. *
  3822. * Description:
  3823. * Datagram read completion
  3824. *
  3825. */
  3826. VOID
  3827. DGramReadComplete(
  3828. PVOID *ppBuff,
  3829. DWORD *pdwSize
  3830. )
  3831. {
  3832. BOOL rc;
  3833. SNDMESSAGE SndMsg;
  3834. DWORD dwFlags = 0;
  3835. DWORD dwRecvd = 0;
  3836. ASSERT( INVALID_SOCKET != g_hDGramSocket );
  3837. rc = WSAGetOverlappedResult(
  3838. g_hDGramSocket,
  3839. &g_WSAOverlapped,
  3840. &dwRecvd,
  3841. FALSE,
  3842. &dwFlags
  3843. );
  3844. if ( !rc )
  3845. {
  3846. TRC(ERR, "DGramReadComplete: WSAGetOverlappedResult failed=%d\n",
  3847. WSAGetLastError());
  3848. goto exitpt;
  3849. }
  3850. //
  3851. // data received
  3852. //
  3853. if ( dwRecvd < sizeof( SNDPROLOG ))
  3854. {
  3855. TRC(WRN, "DGramReadComplete: invalid message received: len=%d\n",
  3856. dwRecvd );
  3857. goto exitpt;
  3858. }
  3859. if ( NULL != ppBuff && NULL != pdwSize )
  3860. {
  3861. //
  3862. // pass the data to the caller
  3863. //
  3864. *ppBuff = g_pDGramRecvData;
  3865. *pdwSize = dwRecvd;
  3866. goto exitpt;
  3867. }
  3868. memcpy( &SndMsg.Prolog, g_pDGramRecvData, sizeof( SNDPROLOG ));
  3869. SndMsg.pBody = g_pDGramRecvData + sizeof( SNDPROLOG );
  3870. TRC(ALV, "DGramReadComplete: data received\n");
  3871. // parse this packet
  3872. //
  3873. VCSndDataArrived( &SndMsg );
  3874. exitpt:
  3875. ;
  3876. }
  3877. /*
  3878. * Add an ACE to object security descriptor
  3879. */
  3880. DWORD
  3881. AddAceToObjectsSecurityDescriptor (
  3882. HANDLE hObject, // handle to object
  3883. SE_OBJECT_TYPE ObjectType, // type of object
  3884. LPTSTR pszTrustee, // trustee for new ACE
  3885. TRUSTEE_FORM TrusteeForm, // format of TRUSTEE structure
  3886. DWORD dwAccessRights, // access mask for new ACE
  3887. ACCESS_MODE AccessMode, // type of ACE
  3888. DWORD dwInheritance // inheritance flags for new ACE
  3889. )
  3890. {
  3891. DWORD dwRes;
  3892. PACL pOldDACL = NULL, pNewDACL = NULL;
  3893. PSECURITY_DESCRIPTOR pSD = NULL;
  3894. EXPLICIT_ACCESS ea;
  3895. if (NULL == hObject)
  3896. return ERROR_INVALID_PARAMETER;
  3897. // Get a pointer to the existing DACL.
  3898. dwRes = GetSecurityInfo(hObject, ObjectType,
  3899. DACL_SECURITY_INFORMATION,
  3900. NULL, NULL, &pOldDACL, NULL, &pSD);
  3901. if (ERROR_SUCCESS != dwRes)
  3902. {
  3903. TRC( ERR, "GetSecurityInfo Error %u\n", dwRes );
  3904. goto exitpt;
  3905. }
  3906. // Initialize an EXPLICIT_ACCESS structure for the new ACE.
  3907. ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
  3908. ea.grfAccessPermissions = dwAccessRights;
  3909. ea.grfAccessMode = AccessMode;
  3910. ea.grfInheritance= dwInheritance;
  3911. ea.Trustee.TrusteeForm = TrusteeForm;
  3912. ea.Trustee.ptstrName = pszTrustee;
  3913. // Create a new ACL that merges the new ACE
  3914. // into the existing DACL.
  3915. dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL);
  3916. if (ERROR_SUCCESS != dwRes)
  3917. {
  3918. TRC( ERR, "SetEntriesInAcl Error %u\n", dwRes );
  3919. goto exitpt;
  3920. }
  3921. // Attach the new ACL as the object's DACL.
  3922. dwRes = SetSecurityInfo(hObject, ObjectType,
  3923. DACL_SECURITY_INFORMATION,
  3924. NULL, NULL, pNewDACL, NULL);
  3925. if (ERROR_SUCCESS != dwRes)
  3926. {
  3927. TRC( ERR, "SetSecurityInfo Error %u\n", dwRes );
  3928. goto exitpt;
  3929. }
  3930. exitpt:
  3931. if(pSD != NULL)
  3932. LocalFree((HLOCAL) pSD);
  3933. if(pNewDACL != NULL)
  3934. LocalFree((HLOCAL) pNewDACL);
  3935. return dwRes;
  3936. }
  3937. /*
  3938. * Add "system" account with full control over this handle
  3939. *
  3940. */
  3941. BOOL
  3942. _ObjectAllowSystem(
  3943. HANDLE h
  3944. )
  3945. {
  3946. BOOL rv = FALSE;
  3947. PSID pSidSystem;
  3948. SID_IDENTIFIER_AUTHORITY AuthorityNt = SECURITY_NT_AUTHORITY;
  3949. DWORD dw;
  3950. if (!AllocateAndInitializeSid(&AuthorityNt, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSidSystem))
  3951. {
  3952. TRC( ERR, "AllocateAndInitializeSid failed: %d\n",
  3953. GetLastError() );
  3954. goto exitpt;
  3955. }
  3956. ASSERT(IsValidSid(pSidSystem));
  3957. dw = AddAceToObjectsSecurityDescriptor (
  3958. h, // handle to object
  3959. SE_KERNEL_OBJECT, // type of object
  3960. (LPTSTR)pSidSystem, // trustee for new ACE
  3961. TRUSTEE_IS_SID, // format of TRUSTEE structure
  3962. GENERIC_ALL, // access mask for new ACE
  3963. GRANT_ACCESS, // type of ACE
  3964. 0 // inheritance flags for new ACE
  3965. );
  3966. if ( ERROR_SUCCESS != dw )
  3967. {
  3968. TRC( ERR, "AddAceToObjectsSecurityDescriptor failed=%d\n", dw );
  3969. goto exitpt;
  3970. }
  3971. rv = TRUE;
  3972. exitpt:
  3973. return rv;
  3974. }
  3975. VOID
  3976. _SignalInitializeDone(
  3977. VOID
  3978. )
  3979. {
  3980. HANDLE hInitEvent = OpenEvent( EVENT_MODIFY_STATE,
  3981. FALSE,
  3982. TSSND_WAITTOINIT );
  3983. g_Stream->dwSoundCaps |= TSSNDCAPS_INITIALIZED;
  3984. if ( NULL != hInitEvent )
  3985. {
  3986. PulseEvent( hInitEvent );
  3987. CloseHandle( hInitEvent );
  3988. }
  3989. TRC( INF, "Audio host is ready!\n" );
  3990. }
  3991. /*
  3992. * Function:
  3993. * VCSndIoThread
  3994. *
  3995. * Description:
  3996. * Main entry pint for this thread
  3997. *
  3998. */
  3999. INT
  4000. WINAPI
  4001. VCSndIoThread(
  4002. PVOID pParam
  4003. )
  4004. {
  4005. HANDLE ahEvents[TOTAL_EVENTS];
  4006. HANDLE hReadEvent = NULL;
  4007. HANDLE hDGramEvent = NULL;
  4008. SNDMESSAGE SndMessage;
  4009. DWORD dwres;
  4010. ULONG logonId;
  4011. HANDLE hReconnectEvent = NULL;
  4012. WCHAR szEvName[64];
  4013. BYTE i;
  4014. _VCSndReadRegistry();
  4015. memset (&SndMessage, 0, sizeof(SndMessage));
  4016. WSInit();
  4017. // create the global/local events
  4018. //
  4019. g_hDataReadyEvent = CreateEvent(NULL,
  4020. FALSE,
  4021. FALSE,
  4022. TSSND_DATAREADYEVENT);
  4023. g_hStreamIsEmptyEvent = CreateEvent(NULL,
  4024. FALSE,
  4025. TRUE,
  4026. TSSND_STREAMISEMPTYEVENT);
  4027. g_hStreamMutex = CreateMutex(NULL, FALSE, TSSND_STREAMMUTEX);
  4028. hReadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  4029. hDGramEvent = WSACreateEvent();
  4030. if (NULL == g_hDataReadyEvent ||
  4031. NULL == g_hStreamIsEmptyEvent ||
  4032. NULL == g_hStreamMutex ||
  4033. NULL == hReadEvent ||
  4034. NULL == hDGramEvent)
  4035. {
  4036. TRC(FATAL, "VCSndIoThread: no events\n");
  4037. goto exitpt;
  4038. }
  4039. // adjust privileges on the events
  4040. //
  4041. if (!_ObjectAllowSystem( g_hDataReadyEvent ))
  4042. goto exitpt;
  4043. if (!_ObjectAllowSystem( g_hStreamIsEmptyEvent ))
  4044. goto exitpt;
  4045. if (!_ObjectAllowSystem( g_hStreamMutex ))
  4046. goto exitpt;
  4047. // create the stream
  4048. //
  4049. g_hStream = CreateFileMapping(
  4050. INVALID_HANDLE_VALUE, //PG.SYS
  4051. NULL, // security
  4052. PAGE_READWRITE,
  4053. 0, // Size high
  4054. sizeof(*g_Stream), // Size low
  4055. TSSND_STREAMNAME // mapping name
  4056. );
  4057. if (NULL == g_hStream)
  4058. {
  4059. TRC(FATAL, "DllInstanceInit: failed to create mapping: %d\n",
  4060. GetLastError());
  4061. goto exitpt;
  4062. }
  4063. if (!_ObjectAllowSystem( g_hStream ))
  4064. goto exitpt;
  4065. g_Stream = (PSNDSTREAM) MapViewOfFile(
  4066. g_hStream,
  4067. FILE_MAP_ALL_ACCESS,
  4068. 0, 0, // offset
  4069. sizeof(*g_Stream)
  4070. );
  4071. if (NULL == g_Stream)
  4072. {
  4073. TRC(ERR, "VCSndIoThread: "
  4074. "can't map the stream view: %d\n",
  4075. GetLastError());
  4076. goto exitpt;
  4077. }
  4078. // Initialize the stream
  4079. //
  4080. if (VCSndAcquireStream())
  4081. {
  4082. memset(g_Stream, 0, sizeof(*g_Stream) - sizeof(g_Stream->pSndData));
  4083. memset(g_Stream->pSndData, 0x00000000, sizeof(g_Stream->pSndData));
  4084. g_Stream->cLastBlockConfirmed = g_Stream->cLastBlockSent - 1;
  4085. //
  4086. // no socket created, so far
  4087. //
  4088. g_hDGramSocket = INVALID_SOCKET;
  4089. VCSndReleaseStream();
  4090. } else {
  4091. TRC(FATAL, "VCSndIoThread, can't map the stream: %d, aborting\n",
  4092. GetLastError());
  4093. goto exitpt;
  4094. }
  4095. if (!ProcessIdToSessionId(GetCurrentProcessId(), &logonId))
  4096. {
  4097. TRC(FATAL, "VCSndIoThread: failed to het session Id. %d\n",
  4098. GetLastError());
  4099. goto exitpt;
  4100. }
  4101. // create disconnect/reconnect events
  4102. //
  4103. wcsncpy(szEvName, L"RDPSound-Disconnect", sizeof(szEvName)/sizeof(szEvName[0]));
  4104. g_hDisconnectEvent = CreateEvent(NULL, FALSE, FALSE, szEvName);
  4105. if (NULL == g_hDisconnectEvent)
  4106. {
  4107. TRC(FATAL, "VCSndIoThread: can't create disconnect event. %d\n",
  4108. GetLastError());
  4109. goto exitpt;
  4110. }
  4111. wcsncpy(szEvName, L"RDPSound-Reconnect", sizeof(szEvName)/sizeof(szEvName[0]));
  4112. hReconnectEvent = CreateEvent(NULL, FALSE, FALSE, szEvName);
  4113. if (NULL == hReconnectEvent)
  4114. {
  4115. TRC(FATAL, "VCSndIoThread: can't create reconnect event. %d\n",
  4116. GetLastError());
  4117. goto exitpt;
  4118. }
  4119. if (!ChannelOpen())
  4120. {
  4121. TRC(FATAL, "VCSndIoThread: unable to open virtual channel\n");
  4122. goto exitpt;
  4123. }
  4124. ahEvents[READ_EVENT] = hReadEvent;
  4125. ahEvents[DISCONNECT_EVENT] = g_hDisconnectEvent;
  4126. ahEvents[RECONNECT_EVENT] = hReconnectEvent;
  4127. ahEvents[DATAREADY_EVENT] = g_hDataReadyEvent;
  4128. ahEvents[DGRAM_EVENT] = hDGramEvent;
  4129. ahEvents[POWERWAKEUP_EVENT] = g_hPowerWakeUpEvent;
  4130. ahEvents[POWERSUSPEND_EVENT] = g_hPowerSuspendEvent;
  4131. _VCSndCheckDevice( hReadEvent, hDGramEvent );
  4132. // Check the channel for data
  4133. //
  4134. while (ChannelReceiveMessage(&SndMessage, hReadEvent))
  4135. {
  4136. VCSndDataArrived(&SndMessage);
  4137. SndMessage.uiPrologReceived = 0;
  4138. SndMessage.uiBodyReceived = 0;
  4139. }
  4140. DGramRead( hDGramEvent, NULL, NULL );
  4141. //
  4142. // signal all workers waiting for initialize
  4143. //
  4144. _SignalInitializeDone();
  4145. // main loop
  4146. //
  4147. while (g_bRunning)
  4148. {
  4149. DWORD dwNumEvents = sizeof(ahEvents)/sizeof(ahEvents[0]);
  4150. dwres = WaitForMultipleObjectsEx(
  4151. dwNumEvents, // count
  4152. ahEvents, // events
  4153. FALSE, // wait all
  4154. DEFAULT_RESPONSE_TIMEOUT,
  4155. FALSE // non alertable
  4156. );
  4157. if (!g_bRunning)
  4158. TRC(ALV, "VCSndIoThread: time to exit\n");
  4159. if (WAIT_TIMEOUT != dwres)
  4160. TRC(ALV, "VCSndIoThread: an event was fired\n");
  4161. if (READ_EVENT == dwres)
  4162. //
  4163. // data is ready to read
  4164. //
  4165. {
  4166. ChannelBlockReadComplete();
  4167. ResetEvent(ahEvents[0]);
  4168. // Check the channel for data
  4169. //
  4170. while (ChannelReceiveMessage(&SndMessage, hReadEvent))
  4171. {
  4172. VCSndDataArrived(&SndMessage);
  4173. SndMessage.uiPrologReceived = 0;
  4174. SndMessage.uiBodyReceived = 0;
  4175. }
  4176. } else if (( DISCONNECT_EVENT == dwres ) || // disconnect event
  4177. ( POWERSUSPEND_EVENT == dwres )) // suspend event
  4178. {
  4179. // disconnect event
  4180. //
  4181. TRC(INF, "VCSndIoThread: DISCONNECTED\n");
  4182. _VCSndCloseDevice();
  4183. _VCSndCloseConverter();
  4184. ChannelClose();
  4185. _StatReset();
  4186. if ( DISCONNECT_EVENT == dwres )
  4187. {
  4188. g_bDisconnected = TRUE;
  4189. } else {
  4190. g_bSuspended = TRUE;
  4191. }
  4192. continue;
  4193. } else if (( RECONNECT_EVENT == dwres ) || // reconnect event
  4194. ( POWERWAKEUP_EVENT == dwres ))
  4195. {
  4196. // reconnect event
  4197. //
  4198. if ( POWERWAKEUP_EVENT == dwres )
  4199. {
  4200. // power wakeup event
  4201. // here, we may have not received suspend event, but in that case we
  4202. // had failed to send, so check the g_bDeviceFailed flag and act only if it is on
  4203. if ( g_bDisconnected )
  4204. {
  4205. // no reason to process power wake up if we are not remote
  4206. //
  4207. g_bSuspended = FALSE;
  4208. continue;
  4209. }
  4210. if ( !g_bSuspended && !g_bDeviceFailed )
  4211. {
  4212. // if neither of these happend
  4213. // then we don't care
  4214. continue;
  4215. }
  4216. }
  4217. TRC(INF, "VCSndIoThread: RECONNECTED\n");
  4218. if (!ChannelOpen())
  4219. {
  4220. TRC(FATAL, "VCSndIoThread: unable to open virtual channel\n");
  4221. } else {
  4222. _VCSndCheckDevice( hReadEvent, hDGramEvent );
  4223. //
  4224. // start the receive loop again
  4225. //
  4226. if (ChannelReceiveMessage(&SndMessage, hReadEvent))
  4227. {
  4228. VCSndDataArrived(&SndMessage);
  4229. SndMessage.uiPrologReceived = 0;
  4230. SndMessage.uiBodyReceived = 0;
  4231. }
  4232. if ( RECONNECT_EVENT == dwres )
  4233. {
  4234. g_bDisconnected = FALSE;
  4235. } else {
  4236. g_bSuspended = FALSE;
  4237. }
  4238. g_bDeviceFailed = FALSE;
  4239. // kick the player
  4240. //
  4241. PulseEvent( g_hStreamIsEmptyEvent );
  4242. _SignalInitializeDone();
  4243. }
  4244. } else if ( DGRAM_EVENT == dwres )
  4245. {
  4246. //
  4247. // DGram ready
  4248. //
  4249. DGramReadComplete( NULL, NULL );
  4250. //
  4251. // atttempt more read
  4252. //
  4253. DGramRead( hDGramEvent, NULL, NULL );
  4254. }
  4255. // Check for data available from the apps
  4256. //
  4257. if (!VCSndAcquireStream())
  4258. {
  4259. TRC(FATAL, "VCSndIoThread: somebody is holding the "
  4260. "Stream mutext for too long\n");
  4261. continue;
  4262. }
  4263. // if this was a reconnect
  4264. // roll back to the last block sent
  4265. //
  4266. if ( RECONNECT_EVENT == dwres)
  4267. {
  4268. //
  4269. // clean this chunk for the next mix
  4270. //
  4271. memset( g_Stream->pSndData, 0, TSSND_MAX_BLOCKS * TSSND_BLOCKSIZE );
  4272. g_Stream->cLastBlockConfirmed = g_Stream->cLastBlockSent;
  4273. }
  4274. //
  4275. // if we have not received confirmation
  4276. // for the packets sent, just give up and continue
  4277. //
  4278. if (WAIT_TIMEOUT == dwres &&
  4279. g_bDeviceOpened &&
  4280. g_Stream->cLastBlockSent != g_Stream->cLastBlockConfirmed)
  4281. {
  4282. BYTE cCounter;
  4283. TRC(WRN, "VCSndIoThread: not received confirmation for blocks "
  4284. "between %d and %d\n",
  4285. g_Stream->cLastBlockConfirmed,
  4286. g_Stream->cLastBlockSent);
  4287. for ( cCounter = g_Stream->cLastBlockConfirmed;
  4288. cCounter != (BYTE)(g_Stream->cLastBlockSent + 1);
  4289. cCounter++)
  4290. {
  4291. _StatsCollect(( GetTickCount() - DEFAULT_RESPONSE_TIMEOUT ) &
  4292. 0xffff );
  4293. }
  4294. //
  4295. // end of the loop
  4296. //
  4297. g_Stream->cLastBlockConfirmed = g_Stream->cLastBlockSent;
  4298. //
  4299. // kick the player
  4300. //
  4301. PulseEvent(g_hStreamIsEmptyEvent);
  4302. }
  4303. // Check for control commands
  4304. //
  4305. // Volume
  4306. //
  4307. if ( g_bDeviceOpened && g_Stream->bNewVolume &&
  4308. 0 != (g_Stream->dwSoundCaps & TSSNDCAPS_VOLUME))
  4309. {
  4310. SNDSETVOLUME SetVolume;
  4311. TRC(ALV, "VCSndIoThread: new volume\n");
  4312. SetVolume.Prolog.Type = SNDC_SETVOLUME;
  4313. SetVolume.Prolog.BodySize = sizeof(SetVolume) - sizeof(SetVolume.Prolog);
  4314. SetVolume.dwVolume = g_Stream->dwVolume;
  4315. ChannelBlockWrite(
  4316. &SetVolume,
  4317. sizeof(SetVolume)
  4318. );
  4319. g_Stream->bNewVolume = FALSE;
  4320. }
  4321. // Pitch
  4322. //
  4323. if ( g_bDeviceOpened && g_Stream->bNewPitch &&
  4324. 0 != (g_Stream->dwSoundCaps & TSSNDCAPS_PITCH))
  4325. {
  4326. SNDSETPITCH SetPitch;
  4327. TRC(ALV, "VCSndIoThread: new pitch\n");
  4328. SetPitch.Prolog.Type = SNDC_SETPITCH;
  4329. SetPitch.Prolog.BodySize = sizeof(SetPitch) - sizeof(SetPitch.Prolog);
  4330. SetPitch.dwPitch = g_Stream->dwPitch;
  4331. ChannelBlockWrite(
  4332. &SetPitch,
  4333. sizeof(SetPitch)
  4334. );
  4335. g_Stream->bNewPitch = FALSE;
  4336. }
  4337. // Check for data available from the apps
  4338. //
  4339. if (g_Stream->cLastBlockSent != g_Stream->cLastBlockQueued &&
  4340. (BYTE)(g_Stream->cLastBlockSent - g_Stream->cLastBlockConfirmed) <
  4341. g_dwBlocksOnTheNet
  4342. )
  4343. {
  4344. // Aha, here's some data to send
  4345. //
  4346. TRC(ALV, "VCSndIoThread: will send some data\n");
  4347. if (g_bDisconnected || g_bSuspended || g_bDeviceFailed)
  4348. {
  4349. TRC(ALV, "Device is disconnected. ignore the packets\n");
  4350. g_Stream->cLastBlockSent = g_Stream->cLastBlockQueued;
  4351. g_Stream->cLastBlockConfirmed = g_Stream->cLastBlockSent - 1;
  4352. PulseEvent( g_hStreamIsEmptyEvent );
  4353. } else
  4354. if (!g_bDeviceOpened)
  4355. {
  4356. // send an "open device" command
  4357. //
  4358. SNDPROLOG Prolog;
  4359. //
  4360. // first, try to open the acm converter
  4361. //
  4362. _VCSndOpenConverter();
  4363. //
  4364. // if we failed width the converter will
  4365. // send in native format
  4366. //
  4367. g_bDeviceOpened = TRUE;
  4368. }
  4369. for (i = g_Stream->cLastBlockSent;
  4370. i != g_Stream->cLastBlockQueued &&
  4371. (BYTE)(g_Stream->cLastBlockSent -
  4372. g_Stream->cLastBlockConfirmed) <
  4373. g_dwBlocksOnTheNet;
  4374. i++)
  4375. {
  4376. BOOL bSucc;
  4377. // TRC( INF, "Sending block # %d, last conf=%d, last queued=%d\n", i, g_Stream->cLastBlockConfirmed, g_Stream->cLastBlockSent );
  4378. bSucc = _VCSndSendWave(
  4379. i, // block no
  4380. ((LPSTR)g_Stream->pSndData) +
  4381. ((i % TSSND_MAX_BLOCKS) * TSSND_BLOCKSIZE),
  4382. TSSND_BLOCKSIZE
  4383. );
  4384. //
  4385. // clean this chunk for the next mix
  4386. //
  4387. memset(g_Stream->pSndData +
  4388. (i % TSSND_MAX_BLOCKS) *
  4389. TSSND_BLOCKSIZE,
  4390. 0x00000000,
  4391. TSSND_BLOCKSIZE);
  4392. if ( 0xff == i )
  4393. g_HiBlockNo++;
  4394. if (bSucc)
  4395. {
  4396. g_Stream->cLastBlockSent = i + 1;
  4397. }
  4398. else
  4399. {
  4400. TRC(WRN, "VCSndIoThread: failed to send, "
  4401. "disabling the device\n");
  4402. //
  4403. // act the same way as DISCONNECT
  4404. //
  4405. _VCSndCloseDevice();
  4406. _VCSndCloseConverter();
  4407. ChannelClose();
  4408. g_Stream->cLastBlockConfirmed =
  4409. g_Stream->cLastBlockSent = g_Stream->cLastBlockQueued;
  4410. _StatReset();
  4411. g_bDeviceFailed = TRUE;
  4412. //
  4413. // Break this loop
  4414. //
  4415. break;
  4416. }
  4417. }
  4418. }
  4419. // Check if there's no more data
  4420. // if so, close the remote device
  4421. //
  4422. if (g_bDeviceOpened &&
  4423. g_Stream->cLastBlockQueued == g_Stream->cLastBlockSent &&
  4424. g_Stream->cLastBlockSent == g_Stream->cLastBlockConfirmed)
  4425. {
  4426. SNDPROLOG Prolog;
  4427. TRC(ALV, "VCSndIoThread: no more data, closing the device\n");
  4428. _VCSndCloseConverter();
  4429. Prolog.Type = SNDC_CLOSE;
  4430. Prolog.BodySize = 0;
  4431. ChannelBlockWrite(&Prolog, sizeof(Prolog));
  4432. g_bDeviceOpened = FALSE;
  4433. }
  4434. VCSndReleaseStream();
  4435. }
  4436. exitpt:
  4437. ChannelClose();
  4438. if (NULL != hReadEvent)
  4439. CloseHandle(hReadEvent);
  4440. if (NULL != hDGramEvent)
  4441. WSACloseEvent( hDGramEvent );
  4442. if (SndMessage.pBody)
  4443. TSFREE(SndMessage.pBody);
  4444. if (NULL != hReconnectEvent)
  4445. CloseHandle(hReconnectEvent);
  4446. if (NULL != g_hDisconnectEvent)
  4447. CloseHandle(g_hDisconnectEvent);
  4448. if (NULL != g_hStreamIsEmptyEvent)
  4449. CloseHandle(g_hStreamIsEmptyEvent);
  4450. if (VCSndAcquireStream())
  4451. {
  4452. //
  4453. // mark the device dead
  4454. //
  4455. g_Stream->dwSoundCaps = TSSNDCAPS_TERMINATED;
  4456. VCSndReleaseStream();
  4457. _SignalInitializeDone();
  4458. }
  4459. if (NULL != g_Stream)
  4460. {
  4461. if (INVALID_SOCKET != g_hDGramSocket)
  4462. closesocket(g_hDGramSocket);
  4463. UnmapViewOfFile(g_Stream);
  4464. }
  4465. if (NULL != g_hStream)
  4466. CloseHandle(g_hStream);
  4467. if (NULL != g_hStreamMutex)
  4468. CloseHandle(g_hStreamMutex);
  4469. // clean the previously negotiated format
  4470. //
  4471. if (NULL != g_ppNegotiatedFormats)
  4472. {
  4473. DWORD i;
  4474. for ( i = 0; i < g_dwNegotiatedFormats; i++ )
  4475. {
  4476. if ( NULL != g_ppNegotiatedFormats[i] )
  4477. TSFREE( g_ppNegotiatedFormats[i] );
  4478. }
  4479. TSFREE( g_ppNegotiatedFormats );
  4480. }
  4481. //
  4482. // cleanup the format list
  4483. //
  4484. if ( NULL != g_pAllCodecsFormatList )
  4485. {
  4486. PVCSNDFORMATLIST pIter;
  4487. pIter = g_pAllCodecsFormatList;
  4488. while( NULL != pIter )
  4489. {
  4490. PVCSNDFORMATLIST pNext = pIter->pNext;
  4491. TSFREE( pIter );
  4492. pIter = pNext;
  4493. }
  4494. }
  4495. if ( NULL != g_AllowCodecs )
  4496. {
  4497. TSFREE( g_AllowCodecs );
  4498. g_AllowCodecs = NULL;
  4499. g_AllowCodecsSize = 0;
  4500. }
  4501. WSACleanup();
  4502. TRC(INF, "VCSndIoThread: EXIT !\n");
  4503. return 0;
  4504. }
  4505. /////////////////////////////////////////////////////////////////////
  4506. //
  4507. // Startup code
  4508. //
  4509. /////////////////////////////////////////////////////////////////////
  4510. VOID
  4511. TSSNDD_Term(
  4512. VOID
  4513. )
  4514. {
  4515. if ( NULL == g_hThread )
  4516. return;
  4517. g_bRunning = FALSE;
  4518. //
  4519. // kick the io thread
  4520. //
  4521. if (NULL != g_hDataReadyEvent)
  4522. SetEvent(g_hDataReadyEvent);
  4523. if ( NULL != g_hThread )
  4524. {
  4525. WaitForSingleObject(g_hThread, DEFAULT_VC_TIMEOUT);
  4526. CloseHandle(g_hThread);
  4527. g_hThread = NULL;
  4528. }
  4529. if (NULL != g_hDataReadyEvent)
  4530. {
  4531. CloseHandle(g_hDataReadyEvent);
  4532. g_hDataReadyEvent = NULL;
  4533. }
  4534. if ( NULL != g_hPowerWakeUpEvent )
  4535. {
  4536. CloseHandle( g_hPowerWakeUpEvent );
  4537. g_hPowerWakeUpEvent = NULL;
  4538. }
  4539. if ( NULL != g_hPowerSuspendEvent )
  4540. {
  4541. CloseHandle( g_hPowerSuspendEvent );
  4542. g_hPowerSuspendEvent = NULL;
  4543. }
  4544. }
  4545. LRESULT
  4546. TSSNDD_PowerMessage(
  4547. WPARAM wParam,
  4548. LPARAM lParam
  4549. )
  4550. {
  4551. switch( wParam )
  4552. {
  4553. case PBT_APMSUSPEND:
  4554. //
  4555. // signal only if connected
  4556. //
  4557. if ( NULL != g_hPowerSuspendEvent )
  4558. {
  4559. SetEvent( g_hPowerSuspendEvent );
  4560. }
  4561. break;
  4562. case PBT_APMRESUMEAUTOMATIC:
  4563. case PBT_APMRESUMECRITICAL:
  4564. case PBT_APMRESUMESUSPEND:
  4565. //
  4566. // signal only if not connected
  4567. //
  4568. if ( NULL != g_hPowerWakeUpEvent )
  4569. {
  4570. SetEvent( g_hPowerWakeUpEvent );
  4571. }
  4572. break;
  4573. }
  4574. return TRUE;
  4575. }
  4576. LRESULT
  4577. CALLBACK
  4578. _VCSndWndProc(
  4579. HWND hwnd,
  4580. UINT uiMessage,
  4581. WPARAM wParam,
  4582. LPARAM lParam
  4583. )
  4584. {
  4585. LRESULT rv = 0;
  4586. switch( uiMessage )
  4587. {
  4588. case WM_CREATE:
  4589. break;
  4590. case WM_CLOSE:
  4591. DestroyWindow(hwnd);
  4592. break;
  4593. case WM_DESTROY:
  4594. PostQuitMessage(0);
  4595. break;
  4596. case WM_ENDSESSION:
  4597. TSSNDD_Term();
  4598. break;
  4599. case WM_POWERBROADCAST:
  4600. rv = TSSNDD_PowerMessage( wParam, lParam );
  4601. break;
  4602. default:
  4603. rv = DefWindowProc(hwnd, uiMessage, wParam, lParam);
  4604. }
  4605. return rv;
  4606. }
  4607. BOOL
  4608. TSSNDD_Loop(
  4609. HINSTANCE hInstance
  4610. )
  4611. {
  4612. BOOL rv = FALSE;
  4613. WNDCLASS wc;
  4614. DWORD dwLastErr;
  4615. HWND hWnd = NULL;
  4616. MSG msg;
  4617. memset(&wc, 0, sizeof(wc));
  4618. wc.lpfnWndProc = _VCSndWndProc;
  4619. wc.hInstance = hInstance;
  4620. wc.hbrBackground = (HBRUSH)GetStockObject(HOLLOW_BRUSH);
  4621. wc.lpszClassName = _RDPSNDWNDCLASS;
  4622. if (!RegisterClass (&wc) &&
  4623. (dwLastErr = GetLastError()) &&
  4624. dwLastErr != ERROR_CLASS_ALREADY_EXISTS)
  4625. {
  4626. TRC(ERR,
  4627. "TSSNDD_Loop: Can't register class. GetLastError=%d\n",
  4628. GetLastError());
  4629. goto exitpt;
  4630. }
  4631. hWnd = CreateWindow(
  4632. _RDPSNDWNDCLASS,
  4633. _RDPSNDWNDCLASS, // Window name
  4634. WS_OVERLAPPEDWINDOW, // dwStyle
  4635. 0, // x
  4636. 0, // y
  4637. 100, // nWidth
  4638. 100, // nHeight
  4639. NULL, // hWndParent
  4640. NULL, // hMenu
  4641. hInstance,
  4642. NULL); // lpParam
  4643. if (!hWnd)
  4644. {
  4645. TRC(ERR, "TSSNDD_Loop: Failed to create message window: %d\n",
  4646. GetLastError());
  4647. goto exitpt;
  4648. }
  4649. while (GetMessage(&msg, NULL, 0, 0))
  4650. {
  4651. TranslateMessage(&msg);
  4652. DispatchMessage(&msg);
  4653. }
  4654. rv = TRUE;
  4655. exitpt:
  4656. return rv;
  4657. }
  4658. BOOL
  4659. TSSNDD_Init(
  4660. )
  4661. {
  4662. BOOL rv = FALSE;
  4663. DWORD dwThreadId;
  4664. g_bRunning = TRUE;
  4665. if ( NULL == g_hPowerWakeUpEvent )
  4666. {
  4667. g_hPowerWakeUpEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  4668. if ( NULL == g_hPowerWakeUpEvent )
  4669. {
  4670. TRC( FATAL, "TSSNDD_Init: failed to create power wakeup notification message: %d\n", GetLastError() );
  4671. goto exitpt;
  4672. }
  4673. }
  4674. if ( NULL == g_hPowerSuspendEvent )
  4675. {
  4676. g_hPowerSuspendEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  4677. if ( NULL == g_hPowerSuspendEvent )
  4678. {
  4679. TRC( FATAL, "TSSNDD_Init: failed to create power suspend notification message: %d\n", GetLastError() );
  4680. goto exitpt;
  4681. }
  4682. }
  4683. g_hThread = CreateThread(
  4684. NULL,
  4685. 0,
  4686. (LPTHREAD_START_ROUTINE)VCSndIoThread,
  4687. NULL,
  4688. 0,
  4689. &dwThreadId
  4690. );
  4691. if (NULL == g_hThread)
  4692. {
  4693. TRC(FATAL, "WinMain: can't create thread: %d. Aborting\n",
  4694. GetLastError());
  4695. goto exitpt;
  4696. }
  4697. rv = TRUE;
  4698. exitpt:
  4699. return rv;
  4700. }
  4701. /////////////////////////////////////////////////////////////////////
  4702. //
  4703. // Tracing
  4704. //
  4705. /////////////////////////////////////////////////////////////////////
  4706. VOID
  4707. _cdecl
  4708. _DebugMessage(
  4709. LPCSTR szLevel,
  4710. LPCSTR szFormat,
  4711. ...
  4712. )
  4713. {
  4714. CHAR szBuffer[256];
  4715. va_list arglist;
  4716. if (szLevel == ALV)
  4717. return;
  4718. va_start (arglist, szFormat);
  4719. _vsnprintf (szBuffer, RTL_NUMBER_OF(szBuffer), szFormat, arglist);
  4720. va_end (arglist);
  4721. szBuffer[ RTL_NUMBER_OF( szBuffer ) - 1 ] = 0;
  4722. OutputDebugStringA(szLevel);
  4723. OutputDebugStringA(szBuffer);
  4724. }