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.

504 lines
15 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dvdxtran.cpp
  6. * Content: Implementation of transport class providing DirectXVoice transport
  7. * through the IDirectXVoiceTransport interface.
  8. *
  9. * History:
  10. * Date By Reason
  11. * ==== == ======
  12. * 07/23/99 rodtoll Modified from dvdptran.cpp
  13. * 08/03/99 rodtoll Modified to conform to new base class and minor fixes
  14. * for dplay integration.
  15. * 08/04/99 rodtoll Modified to allow group targets
  16. * 08/10/99 rodtoll Removed TODO pragmas
  17. * 08/25/99 rodtoll Fixed group membership check
  18. * 08/30/99 rodtoll Modified SendToServer to send to the server player in
  19. * client/server sessions.
  20. * 08/31/99 rodtoll Updated to use new debug libs
  21. * 09/01/99 rodtoll Updated so that constructor no longer calls into dplay
  22. * rodtoll Added check for valid pointers in func calls
  23. * 09/02/99 rodtoll Added checks to handle case no local player created
  24. * 09/20/99 rodtoll Added memory alloc failure checks
  25. * 09/21/99 rodtoll Fixed memory leak
  26. * 10/05/99 rodtoll Additional comments and DPF_MODNAMEs
  27. * 11/23/99 rodtoll Split CheckForValid into Group and Player
  28. * 12/16/99 rodtoll Bug #122629 - As part of new host migration update how
  29. * sends to server before first response are sent.
  30. * 01/14/2000 rodtoll Renamed SendToID to SendToIDS and updated parameter list
  31. * to accept multiple targets.
  32. * rodtoll Added GetNumPlayers call
  33. * 01/17/2000 rodtoll Debug statement removed that limited max players to 30
  34. * 03/28/2000 rodtoll Moved nametable from here to upper level classes
  35. * rodtoll Removed uneeded functions/members
  36. * 04/07/2000 rodtoll Updated to support new DP <--> DPV interface
  37. * rodtoll Updated to support no copy sends
  38. * rodtoll Bug #32179 - Prevent multiple client/server registrations on transport
  39. * 06/21/2000 rodtoll Bug #36820 - Host migrates to wrong client when client/server are on same interface
  40. * Condition exists where host sends leave message, client attempts to start new host
  41. * which fails because old host still registered. Now deregistering is two step
  42. * process DisableReceiveHook then DestroyTransport.
  43. * 07/22/20000 rodtoll Bug #40296, 38858 - Crashes due to shutdown race condition
  44. * Now ensures that all threads from transport have left and that
  45. * all notificatinos have been processed before shutdown is complete.
  46. * 01/04/2001 rodtoll WinBug #94200 - Remove stray comments
  47. * 01/22/2001 rodtoll WINBUG #288437 - IA64 Pointer misalignment due to wire packets
  48. *
  49. ***************************************************************************/
  50. #include "dxvoicepch.h"
  51. #define DVF_SEND_DEBUG_LEVEL DVF_INFOLEVEL
  52. #undef DPF_MODNAME
  53. #define DPF_MODNAME "CDirectVoiceDirectXTransport::CDirectVoiceDirectXTransport"
  54. CDirectVoiceDirectXTransport::CDirectVoiceDirectXTransport( LPDIRECTPLAYVOICETRANSPORT lpTransport
  55. ): m_lpTransport(NULL),
  56. m_dpidServer(DPID_ALLPLAYERS),
  57. m_dpidLocalPlayer(0),
  58. m_bLocalServer(TRUE),
  59. m_bActiveSession(TRUE),
  60. m_dwTransportFlags(0),
  61. m_lpVoiceEngine(NULL),
  62. m_dwMaxPlayers(0),
  63. m_initialized(FALSE),
  64. m_dwObjectType(0),
  65. m_fAdvised(FALSE)
  66. {
  67. lpTransport->QueryInterface( IID_IDirectPlayVoiceTransport, (void **) &m_lpTransport );
  68. m_dvTransportInfo.dwSize = sizeof( DVTRANSPORTINFO );
  69. }
  70. #undef DPF_MODNAME
  71. #define DPF_MODNAME "CDirectVoiceDirectXTransport::~CDirectVoiceDirectXTransport"
  72. CDirectVoiceDirectXTransport::~CDirectVoiceDirectXTransport()
  73. {
  74. if( m_lpTransport != NULL )
  75. m_lpTransport->Release();
  76. }
  77. #undef DPF_MODNAME
  78. #define DPF_MODNAME "CDirectVoiceDirectXTransport::DestroyTransport"
  79. // DestroyTransport
  80. //
  81. // This method is used to remove last references to transport that transport
  82. // layer has. There was a memory leak where
  83. //
  84. //
  85. void CDirectVoiceDirectXTransport::DestroyTransport()
  86. {
  87. if( m_lpTransport != NULL )
  88. {
  89. m_lpTransport->Release();
  90. m_lpTransport = NULL;
  91. }
  92. }
  93. #undef DPF_MODNAME
  94. #define DPF_MODNAME "CDirectVoiceDirectXTransport::Initialize"
  95. //
  96. // Initialize
  97. //
  98. // Called from the transport when Advise is called.
  99. //
  100. // Used to initialize this object.
  101. //
  102. HRESULT CDirectVoiceDirectXTransport::Initialize( )
  103. {
  104. HRESULT hr;
  105. hr = m_lpTransport->GetSessionInfo( &m_dvTransportInfo );
  106. if( FAILED( hr ) )
  107. {
  108. DPFX(DPFPREP, 0, "DXVT::Initialize: GetSessionInfo() failed! hr=0x%x", hr );
  109. return hr;
  110. }
  111. m_dwMaxPlayers = (m_dvTransportInfo.dwMaxPlayers==0) ? 255 : m_dvTransportInfo.dwMaxPlayers;
  112. m_dpidLocalPlayer = m_dvTransportInfo.dvidLocalID;
  113. // No longer needed, the server may not bee the host of the dplay session
  114. // m_dpidServer = m_dvTransportInfo.dvidSessionHost;
  115. m_dpidServer = DPID_ALLPLAYERS;
  116. m_initialized = TRUE;
  117. return S_OK;
  118. }
  119. #undef DPF_MODNAME
  120. #define DPF_MODNAME "CDirectVoiceDirectXTransport::GetMaxPlayers"
  121. DWORD CDirectVoiceDirectXTransport::GetMaxPlayers( )
  122. {
  123. return m_dwMaxPlayers;
  124. }
  125. #undef DPF_MODNAME
  126. #define DPF_MODNAME "CDirectVoiceDirectXTransport::SendHelper"
  127. HRESULT CDirectVoiceDirectXTransport::SendHelper( UNALIGNED DVID * pdvidTargets, DWORD dwNumTargets, PDVTRANSPORT_BUFFERDESC pBufferDesc, LPVOID pvContext, DWORD dwFlags )
  128. {
  129. HRESULT hr;
  130. if( dwNumTargets > 1 )
  131. {
  132. DNASSERT(pdvidTargets);
  133. DEBUG_ONLY( for( DWORD dwIndex = 0; dwIndex < dwNumTargets; dwIndex++ ) { )
  134. DPFX(DPFPREP, DVF_SEND_DEBUG_LEVEL, "Using multitargetted send [From=0x%x To=0x%x]", m_dpidLocalPlayer, pdvidTargets[dwIndex] );
  135. DEBUG_ONLY( } )
  136. hr = m_lpTransport->SendSpeechEx( m_dpidLocalPlayer, dwNumTargets, pdvidTargets, pBufferDesc, pvContext, dwFlags );
  137. }
  138. else if (dwNumTargets==1)
  139. {
  140. DNASSERT(pdvidTargets);
  141. DPFX(DPFPREP, DVF_SEND_DEBUG_LEVEL, "Single target for send [From=0x%x To=0x%x]", m_dpidLocalPlayer, pdvidTargets[0] );
  142. hr = m_lpTransport->SendSpeech( m_dpidLocalPlayer, *pdvidTargets, pBufferDesc, pvContext, dwFlags );
  143. }
  144. else
  145. {
  146. //no targets specified, so simply return the send buffer and do nothing
  147. DVEVENTMSG_SENDCOMPLETE sendCompleteEvent;
  148. sendCompleteEvent.pvUserContext=pvContext;
  149. sendCompleteEvent.hrSendResult=DPN_OK;
  150. m_lpVoiceEngine->SendComplete(&sendCompleteEvent);
  151. DPFX(DPFPREP, DVF_SEND_DEBUG_LEVEL, "Ignoring send from 0x%x, as dwNumTargets==0", m_dpidLocalPlayer);
  152. hr=DPN_OK;
  153. }
  154. /*
  155. DNASSERT( pdpidTargets != NULL );
  156. for( DWORD dwIndex = 0; dwIndex < dwNumTargets; dwIndex++ )
  157. {
  158. hr = m_lpTransport->SendSpeech( m_dpidLocalPlayer, pdpidTargets[dwIndex], lpBuffer, dwSize, dwFlags );
  159. } */
  160. return hr;
  161. }
  162. #undef DPF_MODNAME
  163. #define DPF_MODNAME "CDirectVoiceDirectXTransport::SendToServer"
  164. HRESULT CDirectVoiceDirectXTransport::SendToServer( PDVTRANSPORT_BUFFERDESC pBufferDesc, LPVOID pvContext, DWORD dwFlags )
  165. {
  166. if( m_dvTransportInfo.dwSessionType == DVTRANSPORT_SESSION_CLIENTSERVER )
  167. {
  168. DVID dvidTmp = DVID_SERVERPLAYER;
  169. DPFX(DPFPREP, DVF_SEND_DEBUG_LEVEL, "Sending to standard server player" );
  170. return SendHelper( &dvidTmp, 1, pBufferDesc, pvContext, dwFlags );
  171. }
  172. else
  173. {
  174. DPFX(DPFPREP, DVF_SEND_DEBUG_LEVEL, "Sending to server ID [ID=0x%x]", m_dpidServer );
  175. return SendHelper( &m_dpidServer, 1, pBufferDesc, pvContext, dwFlags );
  176. }
  177. }
  178. #undef DPF_MODNAME
  179. #define DPF_MODNAME "CDirectVoiceDirectXTransport::SendToIDS"
  180. HRESULT CDirectVoiceDirectXTransport::SendToIDS( UNALIGNED DVID * pdvidTargets, DWORD dwNumTargets, PDVTRANSPORT_BUFFERDESC pBufferDesc, LPVOID pvContext, DWORD dwFlags )
  181. {
  182. return SendHelper( pdvidTargets, dwNumTargets, pBufferDesc, pvContext, dwFlags );
  183. }
  184. #undef DPF_MODNAME
  185. #define DPF_MODNAME "CDirectVoiceDirectXTransport::SendToAll"
  186. HRESULT CDirectVoiceDirectXTransport::SendToAll( PDVTRANSPORT_BUFFERDESC pBufferDesc, LPVOID pvContext, DWORD dwFlags )
  187. {
  188. DVID dvidTmp = DPID_ALLPLAYERS;
  189. return SendHelper( &dvidTmp, 1, pBufferDesc, pvContext, dwFlags );
  190. }
  191. #undef DPF_MODNAME
  192. #define DPF_MODNAME "CDirectVoiceDirectXTransport::ConfirmValidGroup"
  193. BOOL CDirectVoiceDirectXTransport::ConfirmValidGroup( DVID dvid )
  194. {
  195. if( dvid == DVID_ALLPLAYERS )
  196. {
  197. return TRUE;
  198. }
  199. else if( m_dvTransportInfo.dwSessionType == DVTRANSPORT_SESSION_CLIENTSERVER )
  200. {
  201. return TRUE;
  202. }
  203. else
  204. {
  205. BOOL fResult;
  206. HRESULT hr;
  207. hr = m_lpTransport->IsValidGroup( dvid, &fResult );
  208. if( FAILED( hr ) )
  209. {
  210. DPFX(DPFPREP, DVF_ERRORLEVEL, "Error confirming valid group hr=0x%x", hr );
  211. return FALSE;
  212. }
  213. else
  214. {
  215. return fResult;
  216. }
  217. }
  218. return FALSE;
  219. }
  220. #undef DPF_MODNAME
  221. #define DPF_MODNAME "CDirectVoiceDirectXTransport::ConfirmValidEntity"
  222. //
  223. // ConfirmValidEntity
  224. //
  225. // Checks to ensure that the ID passed is a valid one for the session.
  226. //
  227. // Will return TRUE if the player iD is one of:
  228. // DVID_ALLPLAYERS, DVID_NOTARGET, (any value in client/server mode),
  229. // a player in the map, or a valid Transport group.
  230. //
  231. BOOL CDirectVoiceDirectXTransport::ConfirmValidEntity( DVID dvid )
  232. {
  233. if( m_dvTransportInfo.dwSessionType == DVTRANSPORT_SESSION_CLIENTSERVER )
  234. {
  235. return TRUE;
  236. }
  237. else
  238. {
  239. BOOL fResult;
  240. m_lpTransport->IsValidEntity( dvid, &fResult );
  241. return fResult;
  242. }
  243. return FALSE;
  244. }
  245. #undef DPF_MODNAME
  246. #define DPF_MODNAME "CDirectVoiceDirectXTransport::EnableReceiveHook"
  247. //
  248. // EnableReceiveHook
  249. //
  250. // This is used to activate the connection between the transport
  251. // and the transport class.
  252. //
  253. // We call advise, which will cause Initialize to be called on this
  254. // class before we return from Advise.
  255. //
  256. HRESULT CDirectVoiceDirectXTransport::EnableReceiveHook( LPDIRECTVOICEOBJECT dvObject, DWORD dwObjectType )
  257. {
  258. HRESULT hr;
  259. m_lpVoiceEngine = dvObject->lpDVEngine;
  260. m_dwObjectType = dwObjectType;
  261. // The transport will call Initialize on our notification interface
  262. // before returning from this function.
  263. //
  264. // Once we've returned from this function we should be ok.
  265. // FYI: This is safe, but using QueryInterface would be more "correct". However, we would
  266. // need to determine if this is a client or a server and call the appropriate QueryInterface.
  267. hr = m_lpTransport->Advise( (LPUNKNOWN) dvObject, m_dwObjectType );
  268. if( FAILED( hr ) )
  269. {
  270. DPFX(DPFPREP, DVF_ERRORLEVEL, "Advise failed. hr=0x%x", hr );
  271. m_fAdvised = FALSE;
  272. }
  273. else
  274. {
  275. m_fAdvised = TRUE;
  276. }
  277. return hr;
  278. }
  279. #undef DPF_MODNAME
  280. #define DPF_MODNAME "CDirectVoiceDirectXTransport::DisableReceiveHook"
  281. HRESULT CDirectVoiceDirectXTransport::WaitForDetachCompletion()
  282. {
  283. DPFX(DPFPREP, DVF_DISCONNECT_PROCEDURE_DEBUG_LEVEL, "# of threads remaining: %d", m_lRefCount );
  284. // Loop until all threads are done inside our layer
  285. while( m_lRefCount > 0 )
  286. Sleep( 5 );
  287. return DV_OK;
  288. }
  289. #undef DPF_MODNAME
  290. #define DPF_MODNAME "CDirectVoiceDirectXTransport::DisableReceiveHook"
  291. //
  292. // DisableReceiveHook
  293. //
  294. // Removes the hooks into the transport and releases the interface
  295. // reference this object holds for the transport.
  296. //
  297. // Also responsible for destroying the list of players maintained
  298. // by this object.
  299. //
  300. HRESULT CDirectVoiceDirectXTransport::DisableReceiveHook( )
  301. {
  302. if( m_fAdvised )
  303. {
  304. m_lpTransport->UnAdvise( m_dwObjectType );
  305. m_fAdvised = FALSE;
  306. m_initialized = FALSE;
  307. DPFX(DPFPREP, DVF_DISCONNECT_PROCEDURE_DEBUG_LEVEL, "Unhooking Transport" );
  308. }
  309. // When this is done no more indications will be waiting.
  310. return DV_OK;
  311. }
  312. #undef DPF_MODNAME
  313. #define DPF_MODNAME "CDirectVoiceDirectXTransport::ConfirmLocalHost"
  314. BOOL CDirectVoiceDirectXTransport::ConfirmLocalHost( )
  315. {
  316. if( !m_initialized )
  317. m_lpTransport->GetSessionInfo( &m_dvTransportInfo );
  318. if( m_dvTransportInfo.dwFlags & DVTRANSPORT_LOCALHOST )
  319. return TRUE;
  320. else
  321. return FALSE;
  322. }
  323. #undef DPF_MODNAME
  324. #define DPF_MODNAME "CDirectVoiceDirectXTransport::ConfirmSessionActive"
  325. BOOL CDirectVoiceDirectXTransport::ConfirmSessionActive( )
  326. {
  327. return TRUE;
  328. }
  329. #undef DPF_MODNAME
  330. #define DPF_MODNAME "CDirectVoiceDirectXTransport::GetTransportSettings"
  331. HRESULT CDirectVoiceDirectXTransport::GetTransportSettings( LPDWORD lpdwSessionType, LPDWORD lpdwFlags )
  332. {
  333. HRESULT hr = DV_OK;
  334. if( !m_initialized )
  335. hr = m_lpTransport->GetSessionInfo( &m_dvTransportInfo );
  336. if( FAILED( hr ) )
  337. {
  338. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to retrieve transport settings" );
  339. return hr;
  340. }
  341. *lpdwSessionType = m_dvTransportInfo.dwSessionType;
  342. *lpdwFlags = m_dvTransportInfo.dwFlags;
  343. return DV_OK;
  344. }
  345. #undef DPF_MODNAME
  346. #define DPF_MODNAME "CDirectVoiceDirectXTransport::AddPlayerEntry"
  347. HRESULT CDirectVoiceDirectXTransport::AddPlayerEntry( DVID dvidPlayer, LPVOID lpData )
  348. {
  349. return DVERR_NOTSUPPORTED;
  350. }
  351. #undef DPF_MODNAME
  352. #define DPF_MODNAME "CDirectVoiceDirectXTransport::DeletePlayerEntry"
  353. HRESULT CDirectVoiceDirectXTransport::DeletePlayerEntry( DVID dvidPlayer )
  354. {
  355. return DVERR_NOTSUPPORTED;
  356. }
  357. #undef DPF_MODNAME
  358. #define DPF_MODNAME "CDirectVoiceDirectXTransport::GetPlayerEntry"
  359. //
  360. // GetPlayerEntry
  361. //
  362. // Retrieves the player record for the specified player (if it exists).
  363. //
  364. HRESULT CDirectVoiceDirectXTransport::GetPlayerEntry( DVID dvidPlayer, CVoicePlayer **lplpPlayer )
  365. {
  366. return DVERR_NOTSUPPORTED;
  367. }
  368. ////////////////////////////////////////////////////////////////////////
  369. //
  370. // USEFUL FOR REMOTE VOICE SESSIONS
  371. //
  372. #undef DPF_MODNAME
  373. #define DPF_MODNAME "CDirectVoiceDirectXTransport::CreateGroup"
  374. HRESULT CDirectVoiceDirectXTransport::CreateGroup( LPDVID dvidGroup )
  375. {
  376. return S_OK;
  377. }
  378. #undef DPF_MODNAME
  379. #define DPF_MODNAME "CDirectVoiceDirectXTransport::DeleteGroup"
  380. HRESULT CDirectVoiceDirectXTransport::DeleteGroup( DVID dvidGroup )
  381. {
  382. return S_OK;
  383. }
  384. #undef DPF_MODNAME
  385. #define DPF_MODNAME "CDirectVoiceDirectXTransport::AddPlayerToGroup"
  386. HRESULT CDirectVoiceDirectXTransport::AddPlayerToGroup( LPDVID dvidGroup, DVID dvidPlayer )
  387. {
  388. return S_OK;
  389. }
  390. #undef DPF_MODNAME
  391. #define DPF_MODNAME "CDirectVoiceDirectXTransport::RemovePlayerFromGroup"
  392. HRESULT CDirectVoiceDirectXTransport::RemovePlayerFromGroup( DVID dvidGroup, DVID dvidPlayer )
  393. {
  394. return S_OK;
  395. }
  396. #undef DPF_MODNAME
  397. #define DPF_MODNAME "CDirectVoiceDirectXTransport::IsPlayerInGroup"
  398. BOOL CDirectVoiceDirectXTransport::IsPlayerInGroup( DVID dvidGroup, DVID dvidPlayer )
  399. {
  400. if( dvidGroup == DVID_ALLPLAYERS )
  401. {
  402. return TRUE;
  403. }
  404. if( dvidGroup == dvidPlayer )
  405. {
  406. return TRUE;
  407. }
  408. return (m_lpTransport->IsGroupMember( dvidGroup, dvidPlayer )==DV_OK);
  409. }
  410. #undef DPF_MODNAME
  411. #define DPF_MODNAME "CDirectVoiceDirectXTransport::MigrateHost"
  412. //
  413. // MigrateHost
  414. //
  415. // Updates server DPID to match new host
  416. //
  417. HRESULT CDirectVoiceDirectXTransport::MigrateHost( DVID dvidNewHost )
  418. {
  419. DPFX(DPFPREP, DVF_HOSTMIGRATE_DEBUG_LEVEL, "HOST MIGRATION: Setting host to 0x%x", dvidNewHost );
  420. m_dpidServer = dvidNewHost;
  421. return DV_OK;
  422. }
  423. #undef DPF_MODNAME
  424. #define DPF_MODNAME "CDirectVoiceDirectXTransport::MigrateHost"
  425. DVID CDirectVoiceDirectXTransport::GetLocalID()
  426. {
  427. m_dwDuumy = m_dpidLocalPlayer;
  428. return m_dpidLocalPlayer;
  429. }