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.

912 lines
24 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: DPLMsgQ.cpp
  6. * Content: DirectPlay Lobby Message Queues
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 02/21/00 mjn Created
  12. * 04/26/00 mjn Fixed AddData() to return HRESULT
  13. * 07/06/00 rmt Bug #38111 - Fixed prefix bug
  14. * 07/08/2000 rmt Bug #38725 - Need to provide method to detect if app was lobby launched
  15. * rmt Bug #38757 - Callback messages for connections may return AFTER WaitForConnection returns
  16. * rmt Bug #38755 - No way to specify player name in Connection Settings
  17. * rmt Bug #38758 - DPLOBBY8.H has incorrect comments
  18. * rmt Bug #38783 - pvUserApplicationContext is only partially implemented
  19. * rmt Added DPLHANDLE_ALLCONNECTIONS and dwFlags (reserved field to couple of funcs).
  20. * 07/21/2000 rmt Removed assert which wasn't needed
  21. * 08/05/2000 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles.
  22. * 08/31/2000 rmt Bug #171831, 131832 (Prefix Bugs)
  23. * 01/31/2001 rmt WINBUG #295562 IDirectPlay8LobbyClient: SetConnectionSettings not sending DPL_CONNECTION_SETTINGS message to App
  24. *@@END_MSINTERNAL
  25. *
  26. ***************************************************************************/
  27. #include "dnlobbyi.h"
  28. // DirectPlay Lobby Message Queues
  29. //
  30. // We will use shared memory circular message buffers to implement this.
  31. // Each MsgQ has a set of synchronization objects to control access to the MsgQs.
  32. // The head of the shared memory file contains state information about the MsgQ:
  33. // pStartAddress
  34. // dwTotalUsableSpace
  35. // dwFirstMsgOffset
  36. // dwNextFreeOffset
  37. // dwFreeSpaceAtEnd
  38. // dwTotalFreeSpace
  39. // Messages are DWORD aligned in the MsgQ.
  40. // Each message in the MsgQ has a header:
  41. // dwMsgId
  42. // dwCurrentOffset
  43. // dwCurrentSize
  44. // dwTotalSize
  45. // Messages which fit in one frame have dwCurrentSize = dwTotalSize and dwCurrentOffset = 0.
  46. // Messages over multiple frames have dwCurrentSize < dwTotalSize.
  47. //**********************************************************************
  48. // Constant definitions
  49. //**********************************************************************
  50. //**********************************************************************
  51. // Macro definitions
  52. //**********************************************************************
  53. //**********************************************************************
  54. // Structure definitions
  55. //**********************************************************************
  56. //**********************************************************************
  57. // Variable definitions
  58. //**********************************************************************
  59. //**********************************************************************
  60. // Function prototypes
  61. //**********************************************************************
  62. //**********************************************************************
  63. // Function definitions
  64. //**********************************************************************
  65. //**********************************************************************
  66. // ------------------------------
  67. // CMessageQueue::Open
  68. //
  69. // Entry: const DWORD dwPID Id associated with this queue (user supplied)
  70. // const CHAR cSuffix Suffix character associated with this Q (user supp.)
  71. // const DWORD dwQueueSize Size of file map to use when implementing msg queue
  72. // const DWORD dwIdleTimeout Amount of time between idle messages == INFINITE to disable idle
  73. // const DWORD dwFlags TBA
  74. //
  75. //
  76. // Exit: HRESULT: DPN_OK If able to open an existing message queue,
  77. // or create a message queue if one didn't exist
  78. // DPNERR_OUTOFMEMORY
  79. // ------------------------------
  80. #undef DPF_MODNAME
  81. #define DPF_MODNAME "CMessageQueue::Open"
  82. HRESULT CMessageQueue::Open(const DWORD dwPID,
  83. const TCHAR cSuffix,
  84. const DWORD dwQueueSize,
  85. const DWORD dwIdleTimeout,
  86. const DWORD dwFlags)
  87. {
  88. HRESULT hResultCode;
  89. PTSTR pszObjectName = NULL;
  90. BOOL bQueueExists = FALSE;
  91. DWORD dwFileMapSize;
  92. #ifdef UNICODE
  93. DPFX(DPFPREP, 3,"Parameters: dwPID [0x%lx], cSuffix [%C], dwQueueSize [%ld], dwFlags [0x%lx]",
  94. dwPID,cSuffix,dwQueueSize,dwFlags);
  95. #else
  96. DPFX(DPFPREP, 3,"Parameters: dwPID [0x%lx], cSuffix [%c], dwQueueSize [%ld], dwFlags [0x%lx]",
  97. dwPID,cSuffix,dwQueueSize,dwFlags);
  98. #endif // UNICODE
  99. // Create Receive Thread Running Event
  100. // This will be set by the receive thread once it has spun up. We need it for synchronization
  101. m_hReceiveThreadRunningEvent = DNCreateEvent(NULL,TRUE,FALSE,NULL);
  102. if (m_hReceiveThreadRunningEvent == NULL)
  103. {
  104. DPFERR("Could not create recevie thread");
  105. hResultCode = DPNERR_OUTOFMEMORY;
  106. goto EXIT_Initialize;
  107. }
  108. // Create shared object name
  109. // pszObjectName : {SharedObjectChar}PID{cSuffix}{\0}
  110. if ((pszObjectName = (PTSTR)DNMalloc((1 + (sizeof(DWORD)*2) + 1 + 1) * sizeof (TCHAR))) == NULL)
  111. {
  112. DPFERR("Could not allocate space for lpszObjectName");
  113. hResultCode = DPNERR_OUTOFMEMORY;
  114. goto EXIT_Initialize;
  115. }
  116. wsprintf(pszObjectName,_T("-%08X%c"),dwPID,cSuffix);// save first char for object differentiation
  117. DPFX(DPFPREP, 5,"Shared object name [%s]",pszObjectName);
  118. // Set the filemap size big enough that the largest message (text) will be dwQueueSize
  119. // so we add on the MsgQ info structure at the front and 1 Msg header
  120. dwFileMapSize = dwQueueSize + sizeof(DPL_MSGQ_INFO) + sizeof(DPL_MSGQ_HEADER);
  121. dwFileMapSize = (dwFileMapSize + 3) & (~0x3); // DWORD align
  122. m_dwIdleTimeout = dwIdleTimeout;
  123. // Create File Mapping Object
  124. *pszObjectName = DPL_MSGQ_OBJECT_IDCHAR_FILEMAP;
  125. m_hFileMap = DNCreateFileMapping(INVALID_HANDLE_VALUE,DNGetNullDacl(),
  126. PAGE_READWRITE,(DWORD)0,dwQueueSize,pszObjectName);
  127. if (m_hFileMap == NULL)
  128. {
  129. DPFERR("CreateFileMapping() failed");
  130. hResultCode = DPNERR_GENERIC;
  131. goto EXIT_Initialize;
  132. }
  133. if (GetLastError() == ERROR_ALREADY_EXISTS)
  134. {
  135. bQueueExists = TRUE;
  136. }
  137. if ((dwFlags & DPL_MSGQ_OPEN_FLAG_NO_CREATE) && !bQueueExists)
  138. {
  139. DPFERR("Open existing queue failed - does not exist");
  140. hResultCode = DPNERR_DOESNOTEXIST;
  141. goto EXIT_Initialize;
  142. }
  143. // Map file
  144. m_pFileMapAddress = reinterpret_cast<BYTE*>(MapViewOfFile(HANDLE_FROM_DNHANDLE(m_hFileMap),FILE_MAP_ALL_ACCESS,0,0,0));
  145. if (m_pFileMapAddress == NULL)
  146. {
  147. DPFERR("MapViewOfFile() failed");
  148. hResultCode = DPNERR_OUTOFMEMORY;
  149. goto EXIT_Initialize;
  150. }
  151. // Create semaphore object
  152. *pszObjectName = DPL_MSGQ_OBJECT_IDCHAR_SEMAPHORE;
  153. m_hSemaphore = DNCreateSemaphore(DNGetNullDacl(),0,
  154. (dwQueueSize/sizeof(DPL_MSGQ_HEADER))+1,pszObjectName);
  155. if (m_hSemaphore == NULL)
  156. {
  157. DPFERR("CreateSemaphore() failed");
  158. hResultCode = DPNERR_OUTOFMEMORY;
  159. goto EXIT_Initialize;
  160. }
  161. // Create event object
  162. *pszObjectName = DPL_MSGQ_OBJECT_IDCHAR_EVENT;
  163. // Changed to a semaphore to ensure that we never miss an event signal
  164. m_hEvent = DNCreateSemaphore(DNGetNullDacl(), 0, (dwQueueSize/sizeof(DPL_MSGQ_HEADER))+1, pszObjectName );
  165. if( m_hEvent == NULL )
  166. {
  167. DPFERR( "CreateSemaphore() failed" );
  168. hResultCode = DPNERR_OUTOFMEMORY;
  169. goto EXIT_Initialize;
  170. }
  171. // Create mutex object
  172. *pszObjectName = DPL_MSGQ_OBJECT_IDCHAR_MUTEX;
  173. m_hMutex = DNCreateMutex(DNGetNullDacl(),FALSE,pszObjectName);
  174. if (m_hMutex == NULL)
  175. {
  176. DPFERR("CreateMutex() failed");
  177. hResultCode = DPNERR_OUTOFMEMORY;
  178. goto EXIT_Initialize;
  179. }
  180. // Update structure elements
  181. m_dwPID = dwPID;
  182. m_pInfo = reinterpret_cast<DPL_MSGQ_INFO*>(m_pFileMapAddress);
  183. // Initialize msg queue if it didn't exist
  184. if (!bQueueExists)
  185. {
  186. m_pInfo->dwFlags = dwFlags & 0x0000ffff; // Just last two bytes
  187. m_pInfo->dwStartOffset = 0;
  188. m_pInfo->dwEndOffset = 0;
  189. m_pInfo->dwQueueSize = dwQueueSize - sizeof(DPL_MSGQ_INFO);
  190. m_pInfo->dwFreeBytes = m_pInfo->dwQueueSize;
  191. m_pInfo->lRefCount = 0;
  192. }
  193. m_pData = (BYTE *) &m_pInfo[1];
  194. m_dwSig = DPL_MSGQ_SIGNATURE;
  195. // Increment user count
  196. Lock();
  197. m_pInfo->lRefCount++;
  198. Unlock();
  199. // If we made it this far, everything was okay
  200. hResultCode = DPN_OK;
  201. EXIT_Initialize:
  202. // Free object name string
  203. if (pszObjectName != NULL)
  204. DNFree(pszObjectName);
  205. // If there was a problem - close handles
  206. if (hResultCode != DPN_OK)
  207. {
  208. DPFERR("Errors encountered - closing");
  209. Close();
  210. }
  211. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  212. return(hResultCode);
  213. }
  214. //**********************************************************************
  215. // ------------------------------
  216. // CMessageQueue::Close
  217. //
  218. // Entry: Nothing
  219. //
  220. // Exit: Nothing
  221. // ------------------------------
  222. #undef DPF_MODNAME
  223. #define DPF_MODNAME "CMessageQueue::Close"
  224. void CMessageQueue::Close(void)
  225. {
  226. DPFX(DPFPREP, 3,"Parameters: (none)");
  227. if (m_hMutex != NULL)
  228. {
  229. // Decrement user count
  230. Lock();
  231. if( m_pInfo != NULL )
  232. {
  233. m_pInfo->lRefCount--;
  234. }
  235. Unlock();
  236. DPFX(DPFPREP, 5,"Close Mutex [0x%p]",m_hMutex);
  237. DNCloseHandle(m_hMutex);
  238. m_hMutex = NULL;
  239. }
  240. if (m_hEvent != NULL)
  241. {
  242. DPFX(DPFPREP, 5,"Close Event [0x%p]",m_hEvent);
  243. DNCloseHandle(m_hEvent);
  244. m_hEvent = NULL;
  245. }
  246. if (m_hSemaphore != NULL)
  247. {
  248. DPFX(DPFPREP, 5,"Close Semaphore [0x%p]",m_hSemaphore);
  249. DNCloseHandle(m_hSemaphore);
  250. m_hSemaphore = NULL;
  251. }
  252. if (m_pFileMapAddress != NULL)
  253. {
  254. DPFX(DPFPREP, 5,"UnMap View of File [0x%p]",m_pFileMapAddress);
  255. UnmapViewOfFile(m_pFileMapAddress);
  256. m_pFileMapAddress = NULL;
  257. }
  258. if (m_hFileMap != NULL)
  259. {
  260. DPFX(DPFPREP, 5,"Close FileMap [0x%p]",m_hFileMap);
  261. DNCloseHandle(m_hFileMap);
  262. m_hFileMap = NULL;
  263. }
  264. if (m_hReceiveThreadRunningEvent != NULL)
  265. {
  266. DPFX(DPFPREP, 5,"Close Event [0x%p]",m_hReceiveThreadRunningEvent);
  267. DNCloseHandle(m_hReceiveThreadRunningEvent);
  268. m_hReceiveThreadRunningEvent = NULL;
  269. }
  270. m_pInfo = NULL;
  271. DPFX(DPFPREP, 3,"Returning");
  272. }
  273. //**********************************************************************
  274. // ------------------------------
  275. // CMessageQueue::Terminate
  276. //
  277. // Entry: Nothing
  278. //
  279. // Exit: Nothing
  280. // ------------------------------
  281. #undef DPF_MODNAME
  282. #define DPF_MODNAME "CMessageQueue::Terminate"
  283. void CMessageQueue::Terminate(void)
  284. {
  285. BOOL bDone = FALSE;
  286. DPL_MSGQ_HEADER Header;
  287. Header.dwCurrentSize = 0;
  288. Header.dwTotalSize = 0;
  289. Header.dwMsgId = DPL_MSGQ_MSGID_TERMINATE;
  290. Header.hSender = 0xFFFFFFFF;
  291. Header.dwFlags = DPL_MSGQ_MSGFLAGS_QUEUESYSTEM;
  292. Header.dwCurrentOffset = 0;
  293. DPFX(DPFPREP, 3,"Parameters: (none)");
  294. DNASSERT(m_pInfo != NULL);
  295. while (!bDone)
  296. {
  297. // Wait until there's enough space for the message
  298. while (sizeof(DWORD) > m_pInfo->dwFreeBytes)
  299. WaitForConsumption(INFINITE);
  300. Lock();
  301. // Ensure there is space once we get the lock
  302. // (someone else might have beaten us here)
  303. if (sizeof(DWORD) <= m_pInfo->dwFreeBytes)
  304. {
  305. AddData(reinterpret_cast<BYTE*>(&Header),sizeof(DPL_MSGQ_HEADER));
  306. bDone = TRUE;
  307. IndicateMessage();
  308. }
  309. Unlock();
  310. }
  311. DPFX(DPFPREP, 3,"Returning");
  312. }
  313. // GetNextMessage
  314. //
  315. // Attempts to retrieve the next message from the queue
  316. //
  317. // pMsgHeader must be large enough to hold a message header.
  318. //
  319. // If no message is present in the queue then this function fills pMsgHeader with an
  320. // idle message header
  321. //
  322. HRESULT CMessageQueue::GetNextMessage( PDPL_MSGQ_HEADER pMsgHeader, BYTE *pbPayload, DWORD *pdwBufferSize )
  323. {
  324. HRESULT hr;
  325. Lock();
  326. hr = GetData( (BYTE *) pMsgHeader, sizeof( DPL_MSGQ_HEADER ) );
  327. // If there is no header on the queue fill in the header with an
  328. // idle message
  329. if( hr == DPNERR_DOESNOTEXIST )
  330. {
  331. pMsgHeader->dwCurrentSize = sizeof( DPL_MSGQ_HEADER );
  332. pMsgHeader->dwTotalSize = sizeof( DPL_MSGQ_HEADER );
  333. pMsgHeader->dwMsgId = DPL_MSGQ_MSGID_IDLE;
  334. pMsgHeader->hSender = 0;
  335. pMsgHeader->dwFlags = DPL_MSGQ_MSGFLAGS_QUEUESYSTEM;
  336. pMsgHeader->dwCurrentOffset = 0;
  337. Unlock();
  338. return DPN_OK;
  339. }
  340. //// DBG
  341. else if( FAILED( hr ) )
  342. {
  343. DNASSERT( FALSE );
  344. }
  345. else if( pMsgHeader->dwMsgId == 0xFFFFFFFF )
  346. {
  347. DNASSERT( FALSE );
  348. }
  349. DWORD dwPayloadSize = pMsgHeader->dwCurrentSize;
  350. // Otherwise it's a valid message of some kind
  351. if( *pdwBufferSize < dwPayloadSize || pbPayload == NULL )
  352. {
  353. *pdwBufferSize = dwPayloadSize;
  354. Unlock();
  355. return DPNERR_BUFFERTOOSMALL;
  356. }
  357. *pdwBufferSize = dwPayloadSize;
  358. Consume( sizeof(DPL_MSGQ_HEADER) );
  359. // There is no payload, only a header. Return here.
  360. if( dwPayloadSize == 0 )
  361. {
  362. Unlock();
  363. return DPN_OK;
  364. }
  365. hr = GetData( pbPayload, dwPayloadSize );
  366. if( FAILED( hr ) )
  367. {
  368. DPFX(DPFPREP, 0, "Error getting IPC queue message payload" );
  369. DNASSERT( FALSE );
  370. Unlock();
  371. return hr;
  372. }
  373. Consume( dwPayloadSize );
  374. Unlock();
  375. return DPN_OK;
  376. }
  377. // Consume
  378. //
  379. // Marks dwSize bytes as consumed
  380. //
  381. // Needs LOCK()
  382. void CMessageQueue::Consume( const DWORD dwSize )
  383. {
  384. DWORD dwAlignedSize = (dwSize + 3) & (~0x3);
  385. m_pInfo->dwStartOffset += dwAlignedSize;
  386. if( m_pInfo->dwStartOffset >= m_pInfo->dwQueueSize )
  387. {
  388. m_pInfo->dwStartOffset -= m_pInfo->dwQueueSize;
  389. }
  390. m_pInfo->dwFreeBytes += dwAlignedSize;
  391. DNASSERT( m_pInfo->dwFreeBytes <= m_pInfo->dwFreeBytes );
  392. IndicateConsumption();
  393. }
  394. // GetData
  395. //
  396. // Get dwSize bytes from the queue. If the queue is empty this function will return
  397. // DPNERR_DOESNOTEXIST. Once this function returns the dwSize bytes will be consumed
  398. //
  399. // REQUIRES LOCK
  400. //
  401. HRESULT CMessageQueue::GetData( BYTE *pbData, DWORD dwSize )
  402. {
  403. if( m_pInfo->dwQueueSize == m_pInfo->dwFreeBytes )
  404. {
  405. return DPNERR_DOESNOTEXIST;
  406. }
  407. if( pbData == NULL )
  408. {
  409. return DPNERR_BUFFERTOOSMALL;
  410. }
  411. // Calculate aligned size
  412. DWORD dwAlignedSize = (dwSize + 3) & (~0x3);
  413. // Data block we want is wrapped
  414. if( m_pInfo->dwStartOffset+dwAlignedSize > m_pInfo->dwQueueSize )
  415. {
  416. DWORD cbBytesLeft = m_pInfo->dwQueueSize - m_pInfo->dwStartOffset;
  417. DWORD cbSecondBlockAligned = dwAlignedSize - (cbBytesLeft);
  418. DWORD cbSecondBlock = dwSize - (cbBytesLeft);
  419. DNASSERT( dwAlignedSize > cbBytesLeft);
  420. memcpy( pbData, m_pData + m_pInfo->dwStartOffset, cbBytesLeft);
  421. memcpy( pbData + cbBytesLeft, m_pData , cbSecondBlock );
  422. }
  423. // Data block is contiguous
  424. else
  425. {
  426. memcpy( pbData, m_pData + m_pInfo->dwStartOffset, dwSize );
  427. }
  428. return DPN_OK;
  429. }
  430. //**********************************************************************
  431. // ------------------------------
  432. // CMessageQueue::AddData
  433. //
  434. // Entry: BYTE *const pBuffer
  435. // const DWORD dwSize
  436. //
  437. // Exit: HRESULT
  438. // ------------------------------
  439. //
  440. // REQUIRES LOCK!!
  441. //
  442. #undef DPF_MODNAME
  443. #define DPF_MODNAME "CMessageQueue::AddData"
  444. HRESULT CMessageQueue::AddData(BYTE *const pBuffer,
  445. const DWORD dwSize)
  446. {
  447. HRESULT hResultCode;
  448. DWORD dwAlignedSize;
  449. DPFX(DPFPREP, 3,"Parameters: pBuffer [0x%p], dwSize [%ld]",pBuffer,dwSize);
  450. dwAlignedSize = (dwSize + 3) & (~0x3);
  451. // Check to ensure there is space
  452. if( dwAlignedSize > m_pInfo->dwFreeBytes )
  453. {
  454. hResultCode = DPNERR_BUFFERTOOSMALL;
  455. goto Exit;
  456. }
  457. // We have a wrapping condition
  458. if( (m_pInfo->dwEndOffset+dwAlignedSize) > m_pInfo->dwQueueSize )
  459. {
  460. DWORD cbBytesLeft = m_pInfo->dwQueueSize - m_pInfo->dwEndOffset;
  461. DWORD cbSecondBlockAligned = dwAlignedSize - cbBytesLeft;
  462. DWORD cbSecondBlock = dwSize - cbBytesLeft;
  463. DNASSERT( dwAlignedSize > cbBytesLeft );
  464. memcpy( m_pData + m_pInfo->dwEndOffset, pBuffer, cbBytesLeft );
  465. memcpy( m_pData, pBuffer + cbBytesLeft, cbSecondBlock );
  466. m_pInfo->dwEndOffset = cbSecondBlockAligned;
  467. }
  468. // Queue is in the middle
  469. else
  470. {
  471. memcpy( m_pData + m_pInfo->dwEndOffset, pBuffer, dwSize );
  472. m_pInfo->dwEndOffset += dwAlignedSize;
  473. }
  474. m_pInfo->dwFreeBytes -= dwAlignedSize;
  475. hResultCode = DPN_OK;
  476. Exit:
  477. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  478. return(hResultCode);
  479. }
  480. //**********************************************************************
  481. // ------------------------------
  482. // CMessageQueue::Send
  483. //
  484. // Entry: BYTE *const pBuffer
  485. // const DWORD dwSize
  486. // const DWORD dwFlags
  487. //
  488. // Exit: HRESULT
  489. // ------------------------------
  490. #undef DPF_MODNAME
  491. #define DPF_MODNAME "CMessageQueue::Send"
  492. HRESULT CMessageQueue::Send(BYTE *const pBuffer,
  493. const DWORD dwSize,
  494. const DWORD dwTimeOut,
  495. const DWORD dwMsgFlags,
  496. const DWORD dwFlags)
  497. {
  498. HRESULT hResultCode;
  499. DWORD dwMsgSize; // DWORD aligned
  500. DWORD dwTotalMsgSize; // Msg + Header - DWORD aligned
  501. DPL_MSGQ_HEADER Header;
  502. BOOL bDone;
  503. DWORD dwTimeRemaining;
  504. DWORD dwTimeStart;
  505. DWORD dwTimeFinish;
  506. DPFX(DPFPREP, 3,"Parameters: pBuffer [0x%p], dwSize [%ld], dwFlags [0x%lx]",pBuffer,dwSize,dwFlags);
  507. DNASSERT( pBuffer != NULL );
  508. DNASSERT( dwSize <= m_pInfo->dwQueueSize );
  509. dwTimeRemaining = dwTimeOut;
  510. // Need DWORD aligned size
  511. dwMsgSize = (dwSize + 3) & (~0x3);
  512. dwTotalMsgSize = dwMsgSize + sizeof(DPL_MSGQ_HEADER);
  513. // Place the message into the MsgQ
  514. // Check to see if fragmentation is required
  515. // If we're at the end of the MsgQ and there isn't enough space for a Msg Header, REALIGN
  516. if (dwTotalMsgSize <= m_pInfo->dwQueueSize)
  517. {
  518. DPFX(DPFPREP, 5,"Message does not need to be fragmented");
  519. Header.dwMsgId = DPL_MSGQ_MSGID_SEND;
  520. Header.dwCurrentOffset = 0;
  521. Header.dwCurrentSize = dwSize;
  522. Header.dwTotalSize = dwSize;
  523. Header.hSender = m_hSender;
  524. Header.dwFlags = dwMsgFlags; // Mark this as a user message
  525. //// DBG
  526. if( Header.dwMsgId == 0xFFFFFFFF )
  527. {
  528. DNASSERT( FALSE );
  529. }
  530. bDone = FALSE;
  531. while (!bDone)
  532. {
  533. // Wait until there's enough space for the message
  534. while (dwTotalMsgSize > m_pInfo->dwFreeBytes)
  535. {
  536. if (dwTimeOut != INFINITE)
  537. {
  538. dwTimeStart = GETTIMESTAMP();
  539. }
  540. if (!WaitForConsumption(dwTimeRemaining))
  541. {
  542. return(DPNERR_TIMEDOUT);
  543. }
  544. if (dwTimeOut != INFINITE)
  545. {
  546. dwTimeFinish = GETTIMESTAMP();
  547. if ((dwTimeFinish - dwTimeStart) > dwTimeRemaining)
  548. {
  549. return(DPNERR_TIMEDOUT);
  550. }
  551. dwTimeRemaining -= (dwTimeFinish - dwTimeStart);
  552. }
  553. }
  554. Lock();
  555. // Ensure there is space once we get the lock
  556. // (someone else might have beaten us here)
  557. if (dwTotalMsgSize <= m_pInfo->dwFreeBytes)
  558. {
  559. //// DBG
  560. if( Header.dwMsgId == 0xFFFFFFFF )
  561. {
  562. DNASSERT( FALSE );
  563. }
  564. hResultCode = AddData(reinterpret_cast<BYTE*>(&Header),sizeof(DPL_MSGQ_HEADER));
  565. DNASSERT(hResultCode == DPN_OK);
  566. hResultCode = AddData(pBuffer,dwSize);
  567. DNASSERT(hResultCode == DPN_OK);
  568. bDone = TRUE;
  569. IndicateMessage();
  570. }
  571. Unlock();
  572. hResultCode = DPN_OK;
  573. }
  574. }
  575. else
  576. {
  577. DPFX(DPFPREP, 5,"Message needs to be fragmented");
  578. DNASSERT(FALSE);
  579. hResultCode = DPNERR_GENERIC;
  580. #pragma TODO(a-minara,"Implement this")
  581. }
  582. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  583. return(hResultCode);
  584. }
  585. //**********************************************************************
  586. // ------------------------------
  587. // DPLIsApplicationAvailable
  588. //
  589. // Entry: const DWORD dwPID PID to check
  590. //
  591. // Exit: BOOL TRUE If the application's queue's flags were retrieved successfully
  592. // and the application is waiting for a connection
  593. // FALSE Otherwise
  594. // ------------------------------
  595. #undef DPF_MODNAME
  596. #define DPF_MODNAME "DPLIsApplicationAvailable"
  597. BOOL DPLIsApplicationAvailable(const DWORD dwPID)
  598. {
  599. BOOL bReturnCode;
  600. CMessageQueue MessageQueue;
  601. DPFX(DPFPREP, 3,"Parameters: dwPID [%lx]",dwPID);
  602. if (MessageQueue.Open(dwPID,DPL_MSGQ_OBJECT_SUFFIX_APPLICATION,DPL_MSGQ_SIZE,
  603. INFINITE, DPL_MSGQ_OPEN_FLAG_NO_CREATE) != DPN_OK)
  604. {
  605. DPFERR("Could not open Msg Queue");
  606. return(FALSE);
  607. }
  608. bReturnCode = MessageQueue.IsAvailable();
  609. MessageQueue.Close();
  610. DPFX(DPFPREP, 3,"Returning: [%ld]",bReturnCode);
  611. return(bReturnCode);
  612. }
  613. //**********************************************************************
  614. // ------------------------------
  615. // DPLMakeApplicationUnavailable
  616. //
  617. // Entry: const DWORD dwPID PID to check
  618. //
  619. // Exit: HRESULT DPN_OK If the application was waiting for a connection
  620. // and made unavailable
  621. // DPNERR_INVALIDAPPLICATION
  622. // ------------------------------
  623. #undef DPF_MODNAME
  624. #define DPF_MODNAME "DPLMakeApplicationUnavailable"
  625. HRESULT DPLMakeApplicationUnavailable(const DWORD dwPID)
  626. {
  627. HRESULT hResultCode;
  628. CMessageQueue MessageQueue;
  629. DPFX(DPFPREP, 3,"Parameters: dwPID [%lx]",dwPID);
  630. if (MessageQueue.Open(dwPID,DPL_MSGQ_OBJECT_SUFFIX_APPLICATION,DPL_MSGQ_SIZE,
  631. DPL_MSGQ_OPEN_FLAG_NO_CREATE,INFINITE) != DPN_OK)
  632. {
  633. DPFERR("Could not open Msg Queue");
  634. return(DPNERR_INVALIDAPPLICATION);
  635. }
  636. if ((hResultCode = MessageQueue.MakeUnavailable()) != DPN_OK)
  637. {
  638. DPFERR("Could not make application unavailable");
  639. hResultCode = DPNERR_INVALIDAPPLICATION;
  640. }
  641. MessageQueue.Close();
  642. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  643. return(hResultCode);
  644. }
  645. //**********************************************************************
  646. // ------------------------------
  647. // DPLProcessMessageQueue
  648. //
  649. // Entry:
  650. //
  651. // Exit: HRESULT DPN_OK If the application was waiting for a connection
  652. // and made unavailable
  653. // DPNERR_INVALIDAPPLICATION
  654. // ------------------------------
  655. #undef DPF_MODNAME
  656. #define DPF_MODNAME "DPLProcessMessageQueue"
  657. DWORD WINAPI DPLProcessMessageQueue(PVOID pvReceiveQueue)
  658. {
  659. HRESULT hResultCode;
  660. DPL_MSGQ_HEADER dplMsgHeader;
  661. BYTE *pBuffer = NULL;
  662. DWORD dwBufferSize = 0;
  663. DWORD dwSize;
  664. CMessageQueue *pReceiveQueue;
  665. DWORD dwWaitResult;
  666. DPFX(DPFPREP, 3,"Parameters: (none)");
  667. COM_CoInitialize(NULL);
  668. pReceiveQueue = static_cast<CMessageQueue*>(pvReceiveQueue);
  669. // Indicate we are running
  670. pReceiveQueue->MakeReceiving();
  671. while(1)
  672. {
  673. dwWaitResult = pReceiveQueue->WaitForMessages();
  674. while( 1 )
  675. {
  676. dwSize = dwBufferSize;
  677. hResultCode = pReceiveQueue->GetNextMessage(&dplMsgHeader, pBuffer, &dwSize);
  678. if( hResultCode == DPNERR_BUFFERTOOSMALL )
  679. {
  680. if( pBuffer )
  681. delete [] pBuffer;
  682. pBuffer = new BYTE[dwSize];
  683. if( pBuffer == NULL )
  684. {
  685. DPFX(DPFPREP, 0, "Error allocating memory" );
  686. DNASSERT( FALSE );
  687. goto EXIT_DPLProcessMessageQueue;
  688. }
  689. dwBufferSize = dwSize;
  690. }
  691. else if( FAILED( hResultCode ) )
  692. {
  693. DPFX(DPFPREP, 0, "Error while getting messages from the queue" );
  694. DNASSERT( FALSE );
  695. goto EXIT_DPLProcessMessageQueue;
  696. }
  697. else
  698. {
  699. break;
  700. }
  701. }
  702. DPFX(DPFPREP, 5,"dwMsgId [0x%lx] dwTotalSize [0x%lx] dwCurrentSize [0x%lx] dwCurrentOffset [0x%lx] ",
  703. dplMsgHeader.dwMsgId, dplMsgHeader.dwTotalSize, dplMsgHeader.dwCurrentSize,
  704. dplMsgHeader.dwCurrentOffset );
  705. switch(dplMsgHeader.dwMsgId)
  706. {
  707. case DPL_MSGQ_MSGID_IDLE:
  708. {
  709. DPFX(DPFPREP, 6,"Idle message fired" );
  710. DWORD dwMsgId = DPL_MSGID_INTERNAL_IDLE_TIMEOUT;
  711. // 7/17/2000(RichGr) - IA64: Change last parm from sizeof(DWORD) to sizeof(BYTE*).
  712. hResultCode = pReceiveQueue->CallMessageHandler(NULL,DPL_MSGQ_MSGFLAGS_USER1,(BYTE *) &dwMsgId,sizeof(BYTE*));
  713. }
  714. break;
  715. case DPL_MSGQ_MSGID_SEND:
  716. {
  717. DPFX(DPFPREP, 5,"DPL_MSGQ_MSGID_SEND");
  718. hResultCode = pReceiveQueue->CallMessageHandler(dplMsgHeader.hSender,dplMsgHeader.dwFlags,pBuffer,dwSize);
  719. break;
  720. }
  721. case DPL_MSGQ_MSGID_TERMINATE:
  722. {
  723. DPFX(DPFPREP, 5,"DPL_MSGQ_MSGID_TERMINATE");
  724. hResultCode = DPN_OK;
  725. goto EXIT_DPLProcessMessageQueue;
  726. break;
  727. }
  728. default:
  729. {
  730. DPFX(DPFPREP, 5,"UNKNOWN - should never get here");
  731. DNASSERT(FALSE);
  732. hResultCode = DPNERR_GENERIC;
  733. goto EXIT_DPLProcessMessageQueue;
  734. break;
  735. }
  736. }
  737. }
  738. EXIT_DPLProcessMessageQueue:
  739. if( pBuffer )
  740. delete [] pBuffer;
  741. // Indicate we are no longer running
  742. pReceiveQueue->MakeNotReceiving();
  743. COM_CoUninitialize();
  744. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  745. return(hResultCode);
  746. }