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.

672 lines
18 KiB

  1. #include "stdafx.h"
  2. #include "Direct.h"
  3. #include "dms.h"
  4. #include "dPlayVoiceServerObj.h"
  5. #include "dvoice.h"
  6. extern BSTR GUIDtoBSTR(LPGUID pGuid);
  7. extern HRESULT DPLAYBSTRtoGUID(LPGUID,BSTR);
  8. extern void *g_dxj_DirectPlayVoiceServer;
  9. #define SAFE_DELETE(p) { if(p) { delete (p); p=NULL; } }
  10. #define SAFE_RELEASE(p) { __try { if(p) { int i = 0; i = (p)->Release(); DPF1(1,"--DirectPlayVoiceServer SafeRelease (RefCount = %d)\n",i); if (!i) { (p)=NULL;}} } __except(EXCEPTION_EXECUTE_HANDLER) { (p) = NULL;} }
  11. DWORD WINAPI ReleaseVoiceThreadProc(void* lpParam);
  12. ///////////////////////////////////////////////////////////////////
  13. // InternalAddRef
  14. ///////////////////////////////////////////////////////////////////
  15. DWORD C_dxj_DirectPlayVoiceServerObject::InternalAddRef(){
  16. DWORD i;
  17. i=CComObjectRoot::InternalAddRef();
  18. DPF1(1,"------ DXVB: DirectPlayVoiceServer AddRef %d \n",i);
  19. return i;
  20. }
  21. ///////////////////////////////////////////////////////////////////
  22. // InternalRelease
  23. ///////////////////////////////////////////////////////////////////
  24. DWORD C_dxj_DirectPlayVoiceServerObject::InternalRelease(){
  25. DWORD i;
  26. i=CComObjectRoot::InternalRelease();
  27. DPF1(1,"DirectPlayVoiceServer Release %d \n",i);
  28. return i;
  29. }
  30. ///////////////////////////////////////////////////////////////////
  31. // C_dxj_DirectPlayVoiceServerObject
  32. ///////////////////////////////////////////////////////////////////
  33. C_dxj_DirectPlayVoiceServerObject::C_dxj_DirectPlayVoiceServerObject(){
  34. DPF(1,"------ DXVB: Constructor Creation DirectPlayVoiceServer Object \n ");
  35. m__dxj_DirectPlayVoiceServer = NULL;
  36. m_pEventStream=NULL;
  37. m_fInit = FALSE;
  38. m_fHandleVoiceClientEvents = FALSE;
  39. m_dwMsgCount = 0;
  40. }
  41. ///////////////////////////////////////////////////////////////////
  42. // ~C_dxj_DirectPlayVoiceServerObject
  43. ///////////////////////////////////////////////////////////////////
  44. C_dxj_DirectPlayVoiceServerObject::~C_dxj_DirectPlayVoiceServerObject()
  45. {
  46. DPF(1,"------ DXVB: Entering ~C_dxj_DirectPlayVoiceServerObject destructor \n");
  47. m_fHandleVoiceClientEvents = FALSE;
  48. FlushBuffer(0);
  49. SAFE_RELEASE(m_pEventStream);
  50. HANDLE hThread = NULL;
  51. DWORD dwThread = 0;
  52. // We are quitting anyway, so we don't really care what is going on in this thread..
  53. hThread = CreateThread(NULL, 0, ReleaseVoiceThreadProc, this->m__dxj_DirectPlayVoiceServer, 0, &dwThread);
  54. }
  55. HRESULT C_dxj_DirectPlayVoiceServerObject::InternalGetObject(IUnknown **pUnk){
  56. *pUnk=(IUnknown*)m__dxj_DirectPlayVoiceServer;
  57. return S_OK;
  58. }
  59. HRESULT C_dxj_DirectPlayVoiceServerObject::InternalSetObject(IUnknown *pUnk){
  60. m__dxj_DirectPlayVoiceServer=(LPDIRECTPLAYVOICESERVER)pUnk;
  61. return S_OK;
  62. }
  63. HRESULT CALLBACK VoiceMessageHandlerServer(LPVOID lpvUserContext, DWORD dwMessageType,
  64. LPVOID lpMessage)
  65. {
  66. HRESULT hr=S_OK;
  67. // User context for the message handler is a pointer to our class module.
  68. C_dxj_DirectPlayVoiceServerObject *lpPeer = (C_dxj_DirectPlayVoiceServerObject*)lpvUserContext;
  69. DPF2(1,"-----Entering (VoiceServer) MessageHandler call... (Current msg count=%d) MSGID = %d\n", lpPeer->m_dwMsgCount, dwMessageType );
  70. //Increment the msg count
  71. InterlockedIncrement(&lpPeer->m_dwMsgCount);
  72. if (!lpPeer)
  73. {
  74. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  75. DPF(1,"-----Leaving (VoiceServer) MessageHandler call (No lpPeer member)...\n");
  76. return E_FAIL;
  77. }
  78. if (!lpPeer->m_pEventStream)
  79. {
  80. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  81. DPF(1,"-----Leaving (VoiceServer) MessageHandler call (No stream)...\n");
  82. return E_FAIL;
  83. }
  84. if (!lpPeer->m_fHandleVoiceClientEvents)
  85. {
  86. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  87. DPF(1,"-----Leaving (VoiceServer) MessageHandler call (Not handling events)...\n");
  88. return S_OK;
  89. }
  90. // First we need to set our stream seek back to the beginning
  91. // We will do this every time we enter this function since we don't know if
  92. // we are on the same thread or not...
  93. LARGE_INTEGER l;
  94. I_dxj_DPVoiceEvent *lpEvent = NULL;
  95. l.QuadPart = 0;
  96. lpPeer->m_pEventStream->Seek(l, STREAM_SEEK_SET, NULL);
  97. hr = CoUnmarshalInterface(lpPeer->m_pEventStream, IID_I_dxj_DPVoiceEvent, (void**)&lpEvent);
  98. if (!lpEvent)
  99. {
  100. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  101. return hr;
  102. }
  103. switch (dwMessageType)
  104. {
  105. case DVMSGID_LOCALHOSTSETUP:
  106. {
  107. DVMSG_LOCALHOSTSETUP *msg = (DVMSG_LOCALHOSTSETUP*)lpMessage;
  108. msg->pvContext = lpvUserContext;
  109. msg->pMessageHandler = VoiceMessageHandlerServer;
  110. break;
  111. }
  112. case DVMSGID_SESSIONLOST:
  113. {
  114. DVMSG_SESSIONLOST *msg = (DVMSG_SESSIONLOST*)lpMessage;
  115. lpEvent->SessionLost(msg->hrResult);
  116. break;
  117. }
  118. case DVMSGID_HOSTMIGRATED:
  119. {
  120. DVMSG_HOSTMIGRATED *msg = (DVMSG_HOSTMIGRATED*)lpMessage;
  121. I_dxj_DirectPlayVoiceServer *lpServer = NULL;
  122. INTERNAL_CREATE_ADDRESS(_dxj_DirectPlayVoiceServer, msg->pdvServerInterface, &lpServer);
  123. lpEvent->HostMigrated(msg->dvidNewHostID, lpServer);
  124. break;
  125. }
  126. case DVMSGID_RECORDSTART:
  127. {
  128. DVMSG_RECORDSTART *pMsg = (DVMSG_RECORDSTART*)lpMessage;
  129. lpEvent->RecordStart(pMsg->dwPeakLevel);
  130. break;
  131. }
  132. case DVMSGID_RECORDSTOP:
  133. {
  134. DVMSG_RECORDSTOP *pMsg = (DVMSG_RECORDSTOP*)lpMessage;
  135. lpEvent->RecordStop(pMsg->dwPeakLevel);
  136. break;
  137. }
  138. case DVMSGID_PLAYERVOICESTART:
  139. {
  140. DVMSG_PLAYERVOICESTART *pMsg = (DVMSG_PLAYERVOICESTART*)lpMessage;
  141. lpEvent->PlayerVoiceStart(pMsg->dvidSourcePlayerID);
  142. break;
  143. }
  144. case DVMSGID_PLAYERVOICESTOP:
  145. {
  146. DVMSG_PLAYERVOICESTOP *pMsg = (DVMSG_PLAYERVOICESTOP*)lpMessage;
  147. lpEvent->PlayerVoiceStop(pMsg->dvidSourcePlayerID);
  148. break;
  149. }
  150. case DVMSGID_CONNECTRESULT:
  151. {
  152. DVMSG_CONNECTRESULT *msg = (DVMSG_CONNECTRESULT*)lpMessage;
  153. lpEvent->ConnectResult(msg->hrResult);
  154. break;
  155. }
  156. case DVMSGID_DISCONNECTRESULT:
  157. {
  158. DVMSG_DISCONNECTRESULT *pMsg = (DVMSG_DISCONNECTRESULT*)lpMessage;
  159. lpEvent->DisconnectResult(pMsg->hrResult);
  160. break;
  161. }
  162. case DVMSGID_INPUTLEVEL:
  163. {
  164. DVMSG_INPUTLEVEL *pMsg = (DVMSG_INPUTLEVEL*)lpMessage;
  165. lpEvent->InputLevel(pMsg->dwPeakLevel,pMsg->lRecordVolume);
  166. break;
  167. }
  168. case DVMSGID_OUTPUTLEVEL:
  169. {
  170. DVMSG_OUTPUTLEVEL *pMsg = (DVMSG_OUTPUTLEVEL*)lpMessage;
  171. lpEvent->OutputLevel(pMsg->dwPeakLevel,pMsg->lOutputVolume);
  172. break;
  173. }
  174. case DVMSGID_PLAYEROUTPUTLEVEL:
  175. {
  176. DVMSG_PLAYEROUTPUTLEVEL *pMsg = (DVMSG_PLAYEROUTPUTLEVEL*)lpMessage;
  177. lpEvent->PlayerOutputLevel(pMsg->dvidSourcePlayerID,pMsg->dwPeakLevel);
  178. break;
  179. }
  180. case DVMSGID_CREATEVOICEPLAYER:
  181. {
  182. DVMSG_CREATEVOICEPLAYER *pMsg = (DVMSG_CREATEVOICEPLAYER*)lpMessage;
  183. lpEvent->CreateVoicePlayer(pMsg->dvidPlayer, pMsg->dwFlags);
  184. break;
  185. }
  186. case DVMSGID_DELETEVOICEPLAYER:
  187. {
  188. DVMSG_DELETEVOICEPLAYER *pMsg = (DVMSG_DELETEVOICEPLAYER*)lpMessage;
  189. lpEvent->DeleteVoicePlayer(pMsg->dvidPlayer);
  190. break;
  191. }
  192. case DVMSGID_SETTARGETS:
  193. break;
  194. }
  195. DPF(1,"-----Leaving (VoiceServer) MessageHandler call...\n");
  196. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  197. return S_OK;
  198. }
  199. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::Initialize (
  200. IUnknown *DplayObj,
  201. long lFlags)
  202. {
  203. HRESULT hr;
  204. IUnknown *lpDplay = NULL;
  205. I_dxj_DirectPlayPeer *lpPeer = NULL;
  206. I_dxj_DirectPlayClient *lpClient = NULL;
  207. I_dxj_DirectPlayServer *lpServer = NULL;
  208. __try {
  209. DPF(1,"-----Entering (VoiceServer) Initialize call...\n");
  210. // First we need to get our IUnknown pointer from whatever we pass in
  211. hr = DplayObj->QueryInterface(IID_I_dxj_DirectPlayPeer, (void**)&lpPeer);
  212. if (SUCCEEDED(hr))
  213. {
  214. lpPeer->InternalGetObject(&lpDplay);
  215. SAFE_RELEASE(lpPeer);
  216. }
  217. else
  218. {
  219. hr = DplayObj->QueryInterface(IID_I_dxj_DirectPlayClient, (void**)&lpClient);
  220. if (SUCCEEDED(hr))
  221. {
  222. lpClient->InternalGetObject(&lpDplay);
  223. SAFE_RELEASE(lpClient);
  224. }
  225. else
  226. {
  227. hr = DplayObj->QueryInterface(IID_I_dxj_DirectPlayServer, (void**)&lpServer);
  228. if (SUCCEEDED(hr))
  229. {
  230. lpServer->InternalGetObject(&lpDplay);
  231. SAFE_RELEASE(lpServer);
  232. }
  233. }
  234. }
  235. if (!lpDplay)
  236. return E_INVALIDARG;
  237. if (!m_fInit)
  238. {
  239. if (FAILED( hr=m__dxj_DirectPlayVoiceServer->Initialize(lpDplay, &VoiceMessageHandlerServer,
  240. this,0,(DWORD)lFlags)))
  241. return hr;
  242. m_fInit = TRUE;
  243. }
  244. }
  245. __except(EXCEPTION_EXECUTE_HANDLER)
  246. {
  247. return E_FAIL;
  248. }
  249. return S_OK;
  250. }
  251. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::StartSession (
  252. DVSESSIONDESC_CDESC *SessionDesc,
  253. long lFlags)
  254. {
  255. DVSESSIONDESC dvSession;
  256. HRESULT hr;
  257. GUID pguidCT;
  258. __try {
  259. DPF(1,"-----Entering (VoiceServer) StartSession call...\n");
  260. FlushBuffer(0);
  261. ZeroMemory(&dvSession, sizeof(DVSESSIONDESC));
  262. dvSession.dwSize = sizeof(DVSESSIONDESC);
  263. dvSession.dwBufferAggressiveness = SessionDesc->lBufferAggressiveness;
  264. dvSession.dwBufferQuality = SessionDesc->lBufferQuality;
  265. dvSession.dwFlags = SessionDesc->lFlags;
  266. dvSession.dwSessionType = SessionDesc->lSessionType;
  267. if ( SessionDesc->guidCT == NULL )
  268. dvSession.guidCT = DPVCTGUID_DEFAULT;
  269. else
  270. {
  271. hr = DPLAYBSTRtoGUID(&pguidCT, SessionDesc->guidCT);
  272. dvSession.guidCT = pguidCT;
  273. }
  274. if (FAILED ( hr = m__dxj_DirectPlayVoiceServer->StartSession( &dvSession, (DWORD)lFlags)))
  275. return hr;
  276. }
  277. __except(EXCEPTION_EXECUTE_HANDLER)
  278. {
  279. return E_FAIL;
  280. }
  281. return S_OK;
  282. }
  283. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::StopSession (
  284. long lFlags)
  285. {
  286. HRESULT hr;
  287. __try {
  288. DPF(1,"-----Entering (VoiceServer) StopSession call...\n");
  289. FlushBuffer(0);
  290. if (FAILED ( hr = m__dxj_DirectPlayVoiceServer->StopSession((DWORD)lFlags)))
  291. return hr;
  292. }
  293. __except(EXCEPTION_EXECUTE_HANDLER)
  294. {
  295. return E_FAIL;
  296. }
  297. return S_OK;
  298. }
  299. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::GetSessionDesc (
  300. DVSESSIONDESC_CDESC *SessionDesc)
  301. {
  302. HRESULT hr;
  303. DVSESSIONDESC dvSession;
  304. __try {
  305. DPF(1,"-----Entering (VoiceServer) GetSessionDesc call...\n");
  306. FlushBuffer(0);
  307. dvSession.dwSize = sizeof(DVSESSIONDESC);
  308. //Now get the buffer
  309. if ( FAILED(hr = m__dxj_DirectPlayVoiceServer->GetSessionDesc(&dvSession)))
  310. return hr;
  311. //Cast into return buffer
  312. SessionDesc->lFlags = (long)dvSession.dwFlags;
  313. SessionDesc->lSessionType = (long)dvSession.dwSessionType;
  314. SessionDesc->guidCT = GUIDtoBSTR(&dvSession.guidCT);
  315. SessionDesc->lBufferQuality = (long)dvSession.dwBufferQuality;
  316. SessionDesc->lBufferAggressiveness = (long)dvSession.dwBufferAggressiveness;
  317. }
  318. __except(EXCEPTION_EXECUTE_HANDLER)
  319. {
  320. return E_FAIL;
  321. }
  322. return S_OK;
  323. }
  324. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::SetSessionDesc (
  325. DVSESSIONDESC_CDESC *SessionDesc)
  326. {
  327. DVSESSIONDESC dvSession;
  328. HRESULT hr;
  329. GUID pguidCT;
  330. __try {
  331. DPF(1,"-----Entering (VoiceServer) SetSessionDesc call...\n");
  332. FlushBuffer(0);
  333. ZeroMemory(&dvSession, sizeof(DVSESSIONDESC));
  334. dvSession.dwSize = sizeof(DVSESSIONDESC);
  335. dvSession.dwBufferAggressiveness = SessionDesc->lBufferAggressiveness;
  336. dvSession.dwBufferQuality = SessionDesc->lBufferQuality;
  337. dvSession.dwFlags = SessionDesc->lFlags;
  338. dvSession.dwSessionType = SessionDesc->lSessionType;
  339. if ( SessionDesc->guidCT == NULL )
  340. dvSession.guidCT = DPVCTGUID_DEFAULT;
  341. else
  342. {
  343. hr = DPLAYBSTRtoGUID(&pguidCT, SessionDesc->guidCT);
  344. dvSession.guidCT = pguidCT;
  345. }
  346. if (FAILED ( hr = m__dxj_DirectPlayVoiceServer->SetSessionDesc(&dvSession)))
  347. return hr;
  348. }
  349. __except(EXCEPTION_EXECUTE_HANDLER)
  350. {
  351. return E_FAIL;
  352. }
  353. return S_OK;
  354. }
  355. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::GetCaps (
  356. DVCAPS_CDESC *Caps)
  357. {
  358. HRESULT hr;
  359. __try {
  360. DPF(1,"-----Entering (VoiceServer) GetCaps call...\n");
  361. FlushBuffer(0);
  362. Caps->lSize=sizeof(DVCAPS);
  363. if (FAILED ( hr = m__dxj_DirectPlayVoiceServer->GetCaps((DVCAPS*)Caps)))
  364. return hr;
  365. }
  366. __except(EXCEPTION_EXECUTE_HANDLER)
  367. {
  368. return E_FAIL;
  369. }
  370. return S_OK;
  371. }
  372. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::GetCompressionTypeCount (
  373. long *retval)
  374. {
  375. HRESULT hr;
  376. DWORD dwSize = 0;
  377. DWORD dwNumElements = 0;
  378. __try {
  379. DPF(1,"-----Entering (VoiceServer) GetCompressionTypeCount call...\n");
  380. FlushBuffer(0);
  381. hr = m__dxj_DirectPlayVoiceServer->GetCompressionTypes(NULL, &dwSize, &dwNumElements ,0);
  382. if ( hr != DVERR_BUFFERTOOSMALL && FAILED(hr) ) //We didn't expect this error
  383. return hr;
  384. *retval = (long)dwNumElements;
  385. }
  386. __except(EXCEPTION_EXECUTE_HANDLER)
  387. {
  388. return E_FAIL;
  389. }
  390. return S_OK;
  391. }
  392. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::GetCompressionType (
  393. long lIndex,
  394. DVCOMPRESSIONINFO_CDESC *Data,
  395. long lFlags)
  396. {
  397. HRESULT hr;
  398. LPBYTE pBuffer = NULL;
  399. DWORD dwSize = 0;
  400. DWORD dwNumElements = 0;
  401. LPDVCOMPRESSIONINFO pdvCompressionInfo;
  402. LPGUID pGuid;
  403. __try {
  404. DPF(1,"-----Entering (VoiceServer) GetCompressionType call...\n");
  405. FlushBuffer(0);
  406. hr = m__dxj_DirectPlayVoiceServer->GetCompressionTypes(pBuffer, &dwSize, &dwNumElements ,0);
  407. if ( hr != DVERR_BUFFERTOOSMALL && FAILED(hr) ) //We didn't expect this error
  408. return hr;
  409. pBuffer = new BYTE[dwSize];
  410. if (!pBuffer)
  411. return E_OUTOFMEMORY;
  412. if ( FAILED ( hr = m__dxj_DirectPlayVoiceServer->GetCompressionTypes(pBuffer, &dwSize, &dwNumElements, (DWORD)lFlags)))
  413. return hr;
  414. if (lIndex > (long)dwNumElements)
  415. return DVERR_INVALIDPARAM;
  416. pdvCompressionInfo = (LPDVCOMPRESSIONINFO) pBuffer;
  417. pGuid = new GUID;
  418. if (!pGuid)
  419. return E_OUTOFMEMORY;
  420. // Ok, fill up our struct
  421. ZeroMemory(Data, sizeof(DVCOMPRESSIONINFO_CDESC));
  422. Data->lSize = sizeof(DVCOMPRESSIONINFO_CDESC);
  423. Data->lFlags = pdvCompressionInfo[lIndex-1].dwFlags;
  424. Data->lMaxBitsPerSecond = pdvCompressionInfo[lIndex-1].dwMaxBitsPerSecond;
  425. Data->strDescription = SysAllocString(pdvCompressionInfo[lIndex-1].lpszDescription);
  426. Data->strName = SysAllocString(pdvCompressionInfo[lIndex-1].lpszName);
  427. (*pGuid) = pdvCompressionInfo[lIndex-1].guidType;
  428. Data->guidType = GUIDtoBSTR(pGuid);
  429. SAFE_DELETE(pGuid);
  430. SAFE_DELETE(pBuffer);
  431. }
  432. __except(EXCEPTION_EXECUTE_HANDLER)
  433. {
  434. return E_FAIL;
  435. }
  436. return S_OK;
  437. }
  438. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::SetTransmitTargets (
  439. long playerSourceID,
  440. SAFEARRAY **playerTargetIDs,
  441. long lFlags)
  442. {
  443. HRESULT hr;
  444. DWORD dwNumTarget = ((SAFEARRAY*)*playerTargetIDs)->rgsabound[0].cElements;
  445. __try {
  446. DPF(1,"-----Entering (VoiceServer) SetTransmitTargets call...\n");
  447. FlushBuffer(0);
  448. if (FAILED( hr = m__dxj_DirectPlayVoiceServer->SetTransmitTargets((DVID)playerSourceID ,
  449. (DVID*)((SAFEARRAY*)*playerTargetIDs)->pvData, dwNumTarget, (DWORD) lFlags )))
  450. return hr;
  451. }
  452. __except(EXCEPTION_EXECUTE_HANDLER)
  453. {
  454. return E_FAIL;
  455. }
  456. return S_OK;
  457. }
  458. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::GetTransmitTargets (
  459. long playerSourceID,
  460. long lFlags,
  461. SAFEARRAY **ret)
  462. {
  463. HRESULT hr;
  464. DVID *dwPlayers = NULL;
  465. DWORD dwNumPlayers=0;
  466. SAFEARRAY *lpData = NULL;
  467. SAFEARRAYBOUND rgsabound[1];
  468. __try {
  469. DPF(1,"-----Entering (VoiceServer) GetTransmitTargets call...\n");
  470. FlushBuffer(0);
  471. hr =m__dxj_DirectPlayVoiceServer->GetTransmitTargets((DVID)playerSourceID, NULL, &dwNumPlayers, (DWORD) lFlags );
  472. if (FAILED(hr) && ( hr != DVERR_BUFFERTOOSMALL))
  473. return hr;
  474. dwPlayers = (DVID*)new BYTE[sizeof(DVID) * dwNumPlayers];
  475. if (!dwPlayers)
  476. return E_OUTOFMEMORY;
  477. if (FAILED( hr = m__dxj_DirectPlayVoiceServer->GetTransmitTargets((DVID)playerSourceID, dwPlayers, &dwNumPlayers, (DWORD) lFlags )))
  478. return hr;
  479. if (dwNumPlayers)
  480. {
  481. // Now let's create a safearray to pass back
  482. rgsabound[0].lLbound = 0;
  483. rgsabound[0].cElements = dwNumPlayers;
  484. lpData = SafeArrayCreate(VT_UI4, 1, rgsabound);
  485. memcpy(lpData->pvData,dwPlayers,sizeof(DVID) * dwNumPlayers);
  486. }
  487. *ret = lpData;
  488. SAFE_DELETE(dwPlayers);
  489. }
  490. __except(EXCEPTION_EXECUTE_HANDLER)
  491. {
  492. return E_FAIL;
  493. }
  494. return S_OK;
  495. }
  496. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::StartServerNotification(I_dxj_DPVoiceEvent *event)
  497. {
  498. HRESULT hr=S_OK;
  499. LPSTREAM pStm=NULL;
  500. if (!event) return E_INVALIDARG;
  501. DPF(1,"-----Entering (VoiceServer) StartServerNotification call...\n");
  502. SAFE_RELEASE(m_pEventStream);
  503. // Create a global stream. The stream needs to be global so we can
  504. // marshal once, and unmarshal as many times as necessary
  505. hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
  506. if FAILED(hr) return hr;
  507. // Now we can marshal our IUnknown interface. We use MSHLFLAGS_TABLEWEAK
  508. // so we can unmarshal any number of times
  509. hr = CoMarshalInterface(pStm, IID_I_dxj_DPVoiceEvent, event, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
  510. if FAILED(hr) return hr;
  511. // Now we need to set the seek location of the stream to the beginning
  512. LARGE_INTEGER l;
  513. l.QuadPart = 0;
  514. pStm->Seek(l, STREAM_SEEK_SET, NULL);
  515. m_pEventStream=pStm;
  516. m_fHandleVoiceClientEvents = TRUE;
  517. return hr;
  518. }
  519. HRESULT C_dxj_DirectPlayVoiceServerObject::UnRegisterMessageHandler()
  520. {
  521. DPF(1,"-----Entering (VoiceServer) UnregisterMessageHandler call...\n");
  522. m_fHandleVoiceClientEvents = FALSE;
  523. FlushBuffer(0);
  524. return S_OK;
  525. }
  526. HRESULT C_dxj_DirectPlayVoiceServerObject::FlushBuffer(LONG dwNumMessagesLeft)
  527. {
  528. DWORD dwTime = GetTickCount();
  529. DPF(1,"-----Entering (VoiceServer) FlushBuffer call...\n");
  530. //Clear out the messages currently waiting
  531. while (m_dwMsgCount > dwNumMessagesLeft)
  532. {
  533. if (GetTickCount() - dwTime > 5000)
  534. {
  535. // Don't let FlushBuffer wait more than 5 seconds
  536. DPF1(1,"-----Leaving (VoiceServer) FlushBuffer call (All messages *not* flushed - %d remained)...\n", m_dwMsgCount);
  537. return S_OK;
  538. }
  539. //Give another thread a chance
  540. Sleep(0);
  541. }
  542. DPF(1,"-----Leaving (VoiceServer) FlushBuffer call (All messages flushed)...\n");
  543. return S_OK;
  544. }
  545. DWORD WINAPI ReleaseVoiceThreadProc(void* lpParam)
  546. {
  547. // User context for the message handler is a pointer to our class module.
  548. LPDIRECTPLAYVOICESERVER lpPeer = (LPDIRECTPLAYVOICESERVER)lpParam;
  549. SAFE_RELEASE(lpPeer);
  550. CloseHandle(GetCurrentThread());
  551. return 0;
  552. }