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.

1503 lines
40 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 1999
  3. Module Name:
  4. mqtrans.cxx
  5. Abstract:
  6. Support for MSMQ (Falcon) datagram transport. Based on MarioGo's
  7. DG transport code (dgtrans.cxx).
  8. Author:
  9. Edward Reus (edwardr) 04-Jul-1997
  10. Revision History:
  11. --*/
  12. #include <precomp.hxx>
  13. #include <trans.hxx>
  14. #include <dgtrans.hxx>
  15. #include <wswrap.hxx>
  16. #include "mqtrans.hxx"
  17. ////////////////////////////////////////////////////////////////////////
  18. //
  19. // MSMQ datagram routines.
  20. //
  21. //----------------------------------------------------------------
  22. RPC_STATUS
  23. MQ_SubmitReceive( IN MQ_DATAGRAM_ENDPOINT *pEndpoint,
  24. IN MQ_DATAGRAM *pDatagram )
  25. /*++
  26. Arguments:
  27. pEndpoint - The endpoint on which the receive should be posted.
  28. pDatagram - The datagram object to manage the receive.
  29. Return Value:
  30. RPC_P_IO_PENDING - OK
  31. RPC_S_OUT_OF_MEMORY
  32. RPC_S_OUT_OF_RESOURCES
  33. --*/
  34. {
  35. RPC_STATUS status;
  36. BOOL fRetry = TRUE;
  37. DWORD dwBytes = 0;
  38. DWORD dwStatus;
  39. HRESULT hr;
  40. while (fRetry)
  41. {
  42. if (pDatagram->pPacket == 0)
  43. {
  44. pDatagram->dwPacketSize = dwBytes;
  45. status = I_RpcTransDatagramAllocate2( pEndpoint,
  46. (BUFFER *)&pDatagram->pPacket,
  47. (PUINT) &pDatagram->dwPacketSize,
  48. (PVOID *) &pDatagram->pAddress);
  49. if (status != RPC_S_OK)
  50. {
  51. return RPC_S_OUT_OF_MEMORY;
  52. }
  53. ASSERT( pDatagram->pPacket );
  54. memset(pDatagram->pAddress,0,sizeof(MQ_ADDRESS));
  55. }
  56. pDatagram->cRecvAddr = sizeof(MQ_ADDRESS);
  57. ASSERT(*(PDWORD)pDatagram->pPacket = 0xDEADF00D);
  58. hr = AsyncReadQueue( pEndpoint,
  59. &pDatagram->Read,
  60. pDatagram->pAddress,
  61. pDatagram->pPacket,
  62. pDatagram->dwPacketSize );
  63. if (!FAILED(hr))
  64. {
  65. return RPC_P_IO_PENDING;
  66. }
  67. if (hr == MQ_ERROR_BUFFER_OVERFLOW)
  68. {
  69. // This can happen if there is already a large sized call on the queue.
  70. dwBytes = pDatagram->Read.aMsgPropVar[1].ulVal;
  71. dwStatus = I_RpcTransDatagramFree( pEndpoint,
  72. (BUFFER)pDatagram->pPacket,
  73. (PVOID) pDatagram->pAddress);
  74. pDatagram->pPacket = 0;
  75. pDatagram->dwPacketSize = 0;
  76. if (dwStatus != RPC_S_OK)
  77. {
  78. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  79. DPFLTR_WARNING_LEVEL,
  80. RPCTRANS "MQ_SubmitReceive(): I_RpcTransDatagram() failed: %d\n",
  81. dwStatus));
  82. return RPC_S_OUT_OF_MEMORY;
  83. }
  84. }
  85. else
  86. {
  87. fRetry = FALSE;
  88. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  89. DPFLTR_WARNING_LEVEL,
  90. RPCTRANS "MQ_SubmitReceive(): AsyncReadQueue() failed: 0x%x\n",
  91. hr));
  92. }
  93. }
  94. return RPC_S_OUT_OF_RESOURCES;
  95. }
  96. //----------------------------------------------------------------
  97. void
  98. MQ_SubmitReceives(
  99. BASE_ADDRESS *ThisEndpoint
  100. )
  101. /*++
  102. Routine Description:
  103. Helper function called when the pending IO count
  104. on an address is too low.
  105. Arguments:
  106. ThisEndpoint - The address to submit IOs on.
  107. Return Value:
  108. None
  109. --*/
  110. {
  111. PMQ_DATAGRAM pDg;
  112. PMQ_DATAGRAM_ENDPOINT pEndpoint = (PMQ_DATAGRAM_ENDPOINT)ThisEndpoint;
  113. if ( (!pEndpoint->fAllowReceives) || (!pEndpoint->hQueue) )
  114. {
  115. return;
  116. }
  117. do
  118. {
  119. BOOL fIoSubmitted;
  120. fIoSubmitted = FALSE;
  121. // Only one thread should be trying to submit IOs at a time.
  122. // This saves locking each DATAGRAM object.
  123. // Simple lock - but requires a loop. See the comment at the end
  124. // of the loop.
  125. if (pEndpoint->fSubmittingIos != 0)
  126. break;
  127. if (InterlockedIncrement(&pEndpoint->fSubmittingIos) != 1)
  128. break;
  129. // Submit new IOs on all the idle datagram objects
  130. for (int i = 0; i < pEndpoint->cMaximumIos; i++)
  131. {
  132. pDg = &pEndpoint->aDatagrams[i];
  133. if (pDg->Busy)
  134. {
  135. continue;
  136. }
  137. // Must be all set for the IO to complete before trying
  138. // to submit the IO.
  139. InterlockedIncrement(&pEndpoint->cPendingIos);
  140. pDg->Busy = TRUE;
  141. if (MQ_SubmitReceive(pEndpoint, pDg) == RPC_P_IO_PENDING)
  142. {
  143. fIoSubmitted = TRUE;
  144. }
  145. else
  146. {
  147. pDg->Busy = FALSE;
  148. InterlockedDecrement(&pEndpoint->cPendingIos);
  149. break;
  150. }
  151. }
  152. // Release the "lock" on the endpoint object.
  153. //
  154. // Xeon processors have eratta G40:
  155. // Potential Loss of Data Coherency Duaring MP Data Ownership Transfer.
  156. // To work around it, it is necessary to use InterlockedExchange rather then an assignment
  157. // to force cache coherency.
  158. InterlockedExchange(&pEndpoint->fSubmittingIos, 0);
  159. if (!fIoSubmitted && pEndpoint->cPendingIos == 0)
  160. {
  161. // It appears that no IO is pending on the endpoint.
  162. COMMON_AddressManager(pEndpoint);
  163. return;
  164. }
  165. // Even if we submitted new IOs, they may all have completed
  166. // already. Which means we may need to loop and submit more
  167. // IOs. This is needed since the thread which completed the
  168. // last IO may have run into our lock and returned.
  169. }
  170. while (pEndpoint->cPendingIos == 0);
  171. return;
  172. }
  173. BOOL RPC_ENTRY MQ_AllowReceives(
  174. IN DG_TRANSPORT_ENDPOINT pvTransEndpoint,
  175. IN BOOL fAllowReceives,
  176. IN BOOL fCancelPendingIos )
  177. {
  178. BOOL fPrevAllowReceives;
  179. MQ_DATAGRAM_ENDPOINT *pEndpoint = (MQ_DATAGRAM_ENDPOINT*)pvTransEndpoint;
  180. fPrevAllowReceives = pEndpoint->fAllowReceives;
  181. pEndpoint->fAllowReceives = fAllowReceives;
  182. if (!pEndpoint->cPendingIos)
  183. {
  184. MQ_SubmitReceives(pEndpoint);
  185. }
  186. ASSERT( !fCancelPendingIos ); // Not implemented yet.
  187. return fPrevAllowReceives;
  188. }
  189. RPC_STATUS RPC_ENTRY
  190. MQ_SendPacket(
  191. IN DG_TRANSPORT_ENDPOINT ThisEndpoint,
  192. IN DG_TRANSPORT_ADDRESS pvAddress,
  193. IN BUFFER pHeader,
  194. IN unsigned cHeader,
  195. IN BUFFER pBody,
  196. IN unsigned cBody,
  197. IN BUFFER pTrailer,
  198. IN unsigned cTrailer
  199. )
  200. /*++
  201. Routine Description:
  202. Sends a packet to an address.
  203. The routine will send a packet built out of the three buffers supplied.
  204. All the buffers are optional, the actual packet sent will be built from
  205. all the buffers actually supplied. In each call at least buffer should
  206. NOT be null.
  207. Arguments:
  208. ThisEndpoint - Endpoint to send from.
  209. pAddress - Address to send to.
  210. pHeader - First data buffer
  211. cHeader - Size of the first data buffer or 0.
  212. pBody - Second data buffer
  213. cBody - Size of the second data buffer or 0.
  214. pTrailer - Third data buffer.
  215. cTrailer - Size of the third data buffer or 0.
  216. Return Value:
  217. RPC_S_OK
  218. RPC_S_OUT_OF_RESOURCES
  219. RPC_S_OUT_OF_MEMORY
  220. RPC_P_SEND_FAILED
  221. --*/
  222. {
  223. RPC_STATUS Status;
  224. MQ_DATAGRAM_ENDPOINT *pEndpoint = (MQ_DATAGRAM_ENDPOINT*)ThisEndpoint;
  225. MQ_ADDRESS *pAddress = (MQ_ADDRESS*)pvAddress;
  226. UCHAR *pBuffer;
  227. UCHAR *pTemp;
  228. DWORD dwBytes = cHeader + cBody + cTrailer;
  229. HRESULT hr;
  230. BOOL fNeedToFree = FALSE;
  231. ASSERT(dwBytes);
  232. //
  233. // Buffer assembly. I get the data PDU as up to three separate pieces,
  234. // so it needs to be assembled before being sent. For Falcon (which can't
  235. // do scatter/gather) this is expensive (allocate() + memcpy()'s). We try
  236. // to be cheap and avoid the allocation, or do an _alloca() off the stack
  237. // instead of the heap.
  238. //
  239. if ( (cHeader==0) && (cBody > 0) && (cTrailer == 0) )
  240. {
  241. pBuffer = pBody;
  242. }
  243. else if ( ((cBody == 0) && (cTrailer == 0))
  244. || ((pHeader+cHeader == pBody) && (pTrailer == 0)) )
  245. {
  246. pBuffer = pHeader;
  247. }
  248. else
  249. {
  250. pBuffer = (UCHAR*)I_RpcAllocate(dwBytes);
  251. fNeedToFree = TRUE;
  252. if (!pBuffer)
  253. {
  254. return RPC_S_OUT_OF_MEMORY;
  255. }
  256. pTemp = pBuffer;
  257. if (cHeader)
  258. {
  259. memcpy(pTemp,pHeader,cHeader);
  260. pTemp += cHeader;
  261. }
  262. if (cBody)
  263. {
  264. memcpy(pTemp,pBody,cBody);
  265. pTemp += cBody;
  266. }
  267. if (cTrailer)
  268. {
  269. memcpy(pTemp,pTrailer,cTrailer);
  270. }
  271. ASSERT(pTemp != pBuffer);
  272. }
  273. #ifdef MAJOR_DBG
  274. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  275. DPFLTR_WARNING_LEVEL,
  276. RPCTRANS "MQ_SendPacket():\n"));
  277. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  278. DPFLTR_WARNING_LEVEL,
  279. " To: %S: %S\n",
  280. pAddress->wsMachine,
  281. pAddress->wsQName));
  282. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  283. DPFLTR_WARNING_LEVEL,
  284. " Size: %d\n",
  285. dwBytes));
  286. DG_DbgPrintPacket(pBuffer);
  287. #endif
  288. hr = MQ_SendToQueue( pEndpoint, pAddress, pBuffer, dwBytes );
  289. Status = MQ_MapStatusCode(hr,RPC_P_SEND_FAILED);
  290. if (Status != RPC_S_OK)
  291. {
  292. if (fNeedToFree)
  293. {
  294. I_RpcFree(pBuffer);
  295. }
  296. return Status;
  297. }
  298. if ( (pEndpoint->cMinimumIos)
  299. && (pEndpoint->cPendingIos <= pEndpoint->cMaximumIos) )
  300. {
  301. MQ_SubmitReceives(pEndpoint);
  302. }
  303. if (fNeedToFree)
  304. {
  305. I_RpcFree(pBuffer);
  306. }
  307. return RPC_S_OK;
  308. }
  309. RPC_STATUS RPC_ENTRY
  310. MQ_ForwardPacket(
  311. IN DG_TRANSPORT_ENDPOINT ThisEndpoint,
  312. IN BUFFER pHeader,
  313. IN unsigned cHeader,
  314. IN BUFFER pBody,
  315. IN unsigned cBody,
  316. IN BUFFER pTrailer,
  317. IN unsigned cTrailer,
  318. IN CHAR * pszPort
  319. )
  320. /*++
  321. Routine Description:
  322. Sends a packet to the server it was originally destined for (that
  323. is, the client had a dynamic endpoint it wished the enpoint mapper
  324. to resolve and forward the packet to).
  325. Arguments:
  326. ThisEndpoint - The endpoint to forward the packet from.
  327. // Buffer like DG_SendPacket
  328. pszPort - Pointer to the server port num to forward to.
  329. This is in an Ansi string.
  330. Return Value:
  331. RPC_S_CANT_CREATE_ENDPOINT - pEndpoint invalid.
  332. results of MQ_SendPacket().
  333. --*/
  334. {
  335. PMQ_DATAGRAM_ENDPOINT pEndpoint = (PMQ_DATAGRAM_ENDPOINT)ThisEndpoint;
  336. MQ_ADDRESS Address;
  337. MQ_ADDRESS *pAddress = &Address;
  338. RPC_CHAR wsPort[MQ_MAX_Q_NAME_LEN];
  339. UNICODE_STRING UnicodePort;
  340. ANSI_STRING AsciiPort;
  341. DWORD Status;
  342. NTSTATUS NtStatus;
  343. //
  344. // Convert pszPort to Unicode:
  345. //
  346. RtlInitAnsiString(&AsciiPort, pszPort);
  347. UnicodePort.Buffer = wsPort;
  348. UnicodePort.Length = 0;
  349. UnicodePort.MaximumLength = MQ_MAX_Q_NAME_LEN * sizeof(RPC_CHAR);
  350. NtStatus = RtlAnsiStringToUnicodeString(&UnicodePort,
  351. &AsciiPort,
  352. FALSE);
  353. if (!NT_SUCCESS(NtStatus))
  354. {
  355. return RPC_S_CANT_CREATE_ENDPOINT;
  356. }
  357. //
  358. // Try to connect to the server (to forward the packet to):
  359. //
  360. Status = ConnectToServerQueue(pAddress, NULL, wsPort );
  361. if (Status != RPC_S_OK)
  362. {
  363. return RPC_S_CANT_CREATE_ENDPOINT;
  364. }
  365. //
  366. // Forward the packet on:
  367. //
  368. Status = MQ_SendPacket(ThisEndpoint,
  369. pAddress,
  370. pHeader,
  371. cHeader,
  372. pBody,
  373. cBody,
  374. pTrailer,
  375. cTrailer );
  376. //
  377. // Release the connection, we shouldn't need it any more:
  378. //
  379. DisconnectFromServer(pAddress);
  380. return Status;
  381. }
  382. RPC_STATUS
  383. RPC_ENTRY
  384. MQ_ResizePacket(
  385. IN DG_TRANSPORT_ENDPOINT ThisEndpoint,
  386. OUT DG_TRANSPORT_ADDRESS *pReplyAddress,
  387. OUT PUINT pBufferLength,
  388. OUT BUFFER *pBuffer
  389. )
  390. {
  391. RPC_STATUS Status = RPC_P_TIMEOUT;
  392. DWORD dwBytes = 0;
  393. MQ_DATAGRAM_ENDPOINT *pEndpoint = (MQ_DATAGRAM_ENDPOINT*)ThisEndpoint;
  394. MQ_DATAGRAM *pDatagram = &pEndpoint->aDatagrams[0];
  395. dwBytes = pDatagram->Read.aMsgPropVar[1].ulVal;
  396. ASSERT(dwBytes);
  397. #ifdef DBG
  398. DbgPrint("MQ_ResizePacket(): dwBytes: %d\n",dwBytes);
  399. #endif
  400. if ( (pDatagram->pPacket) && (pDatagram->dwPacketSize < dwBytes) )
  401. {
  402. Status = I_RpcTransDatagramFree( pEndpoint,
  403. (BUFFER)pDatagram->pPacket,
  404. (PVOID) pDatagram->pAddress);
  405. pDatagram->pPacket = 0;
  406. pDatagram->dwPacketSize = 0;
  407. if (Status != RPC_S_OK)
  408. {
  409. return RPC_S_OUT_OF_MEMORY;
  410. }
  411. }
  412. if (!pDatagram->pPacket)
  413. {
  414. pDatagram->dwPacketSize = dwBytes;
  415. Status = I_RpcTransDatagramAllocate2( pEndpoint,
  416. (BUFFER *)&pDatagram->pPacket,
  417. (PUINT) &pDatagram->dwPacketSize,
  418. (PVOID *) &pDatagram->pAddress);
  419. if (Status != RPC_S_OK)
  420. {
  421. return RPC_S_OUT_OF_MEMORY;
  422. }
  423. pDatagram->cRecvAddr = sizeof(MQ_ADDRESS);
  424. ASSERT( pDatagram->pPacket );
  425. }
  426. #ifdef DBG
  427. DbgPrint("MQ_ResizePacket(): Ok\n");
  428. #endif
  429. return RPC_P_TIMEOUT;
  430. }
  431. RPC_STATUS
  432. RPC_ENTRY
  433. MQ_ReceivePacket(
  434. IN DG_TRANSPORT_ENDPOINT ThisEndpoint,
  435. OUT DG_TRANSPORT_ADDRESS *pReplyAddress,
  436. OUT PUINT pBufferLength,
  437. OUT BUFFER *pBuffer,
  438. IN LONG Timeout
  439. )
  440. /*++
  441. Routine Description:
  442. Used to wait for a datagram from a server. Returns the data
  443. returned and the address of the machine which replied.
  444. This is a blocking API. It should only be called during sync
  445. client RPC threads.
  446. Arguments:
  447. Endpoint - The endpoint to receive from.
  448. ReplyAddress - Contain the source address of the datagram if
  449. successful.
  450. BufferLength - The size of Buffer on input, the size of the
  451. datagram received on output.
  452. Timeout - Milliseconds to wait for a datagram.
  453. Return Value:
  454. RPC_S_OK
  455. RPC_P_OVERSIZE_PACKET - Datagram > BufferLength arrived,
  456. first BufferLength bytes of Buffer contain the partial datagram.
  457. RPC_P_RECEIVE_FAILED
  458. RPC_P_TIMEOUT
  459. --*/
  460. {
  461. RPC_STATUS Status = RPC_P_TIMEOUT;
  462. DWORD dwBytes;
  463. BOOL fRetry = TRUE;
  464. HRESULT hr;
  465. MQ_DATAGRAM_ENDPOINT *pEndpoint = (MQ_DATAGRAM_ENDPOINT*)ThisEndpoint;
  466. MQ_DATAGRAM *pDatagram = &pEndpoint->aDatagrams[0];
  467. ASSERT((pEndpoint->type & TYPE_MASK) == CLIENT);
  468. ASSERT(pEndpoint->aDatagrams[0].Read.ol.hEvent);
  469. #if TRUE
  470. while (fRetry)
  471. {
  472. fRetry = FALSE;
  473. if (pDatagram->Busy == 0)
  474. {
  475. Status = MQ_SubmitReceive(pEndpoint,pDatagram);
  476. if (Status != RPC_P_IO_PENDING)
  477. {
  478. return Status;
  479. }
  480. pDatagram->Busy = TRUE;
  481. }
  482. else
  483. {
  484. ASSERT(pDatagram->Busy);
  485. ASSERT(pDatagram->pPacket);
  486. Status = RPC_P_IO_PENDING;
  487. }
  488. if (Status == RPC_P_IO_PENDING)
  489. {
  490. Status = WaitForSingleObjectEx(pDatagram->Read.ol.hEvent,
  491. Timeout,
  492. TRUE);
  493. if (Status != STATUS_WAIT_0)
  494. {
  495. // In the timeout case we just want to return.
  496. if (Status == WAIT_IO_COMPLETION)
  497. {
  498. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  499. DPFLTR_WARNING_LEVEL,
  500. RPCTRANS "MQ_ReceivePacket() cancelled.\n"));
  501. }
  502. else
  503. {
  504. ASSERT(Status == STATUS_TIMEOUT);
  505. }
  506. ASSERT(pDatagram->Busy);
  507. return RPC_P_TIMEOUT;
  508. }
  509. }
  510. MQ_FillInAddress(pDatagram->pAddress,pDatagram->Read.aMsgPropVar);
  511. }
  512. ASSERT((Status == RPC_S_OK)||(Status == RPC_P_OVERSIZE_PACKET));
  513. ASSERT(pDatagram->Busy);
  514. ASSERT(pDatagram->pPacket);
  515. // ASSERT(dwBytes <= pDatagram->dwPacketSize);
  516. *pBuffer = (BUFFER)pDatagram->pPacket;
  517. *pBufferLength = pDatagram->Read.aMsgPropVar[1].ulVal;
  518. // dwBytes;
  519. *pReplyAddress = pDatagram->pAddress;
  520. pDatagram->pPacket = 0;
  521. pDatagram->dwPacketSize = 0;
  522. pDatagram->Busy = 0;
  523. return Status;
  524. #else
  525. if (pDatagram->Busy == 0)
  526. {
  527. hr = PeekQueue( pEndpoint, Timeout, &dwBytes );
  528. Status = MQ_MapStatusCode(hr,RPC_P_RECEIVE_FAILED);
  529. if (Status != RPC_S_OK)
  530. {
  531. return Status;
  532. }
  533. if ( (pDatagram->pPacket) && (pDatagram->dwPacketSize < dwBytes) )
  534. {
  535. Status = I_RpcTransDatagramFree( pEndpoint,
  536. (BUFFER)pDatagram->pPacket,
  537. (PVOID) pDatagram->pAddress);
  538. pDatagram->pPacket = 0;
  539. pDatagram->dwPacketSize = 0;
  540. if (Status != RPC_S_OK)
  541. {
  542. return RPC_S_OUT_OF_MEMORY;
  543. }
  544. }
  545. if (!pDatagram->pPacket)
  546. {
  547. pDatagram->dwPacketSize = dwBytes;
  548. Status = I_RpcTransDatagramAllocate2( pEndpoint,
  549. (BUFFER *)&pDatagram->pPacket,
  550. (PUINT) &pDatagram->dwPacketSize,
  551. (PVOID *) &pDatagram->pAddress);
  552. if (Status != RPC_S_OK)
  553. {
  554. return RPC_S_OUT_OF_MEMORY;
  555. }
  556. pDatagram->cRecvAddr = sizeof(MQ_ADDRESS);
  557. ASSERT( pDatagram->pPacket );
  558. }
  559. pDatagram->Busy = TRUE;
  560. dwBytes = pDatagram->dwPacketSize;
  561. hr = ReadQueue( pEndpoint, Timeout, pDatagram->pAddress, pDatagram->pPacket, &dwBytes );
  562. Status = MQ_MapStatusCode(hr,RPC_P_RECEIVE_FAILED);
  563. if (FAILED(hr))
  564. {
  565. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  566. DPFLTR_WARNING_LEVEL,
  567. RPCTRANS "ReadQueue() failed: 0x%x\n",
  568. hr));
  569. pDatagram->Busy = FALSE;
  570. return Status;
  571. }
  572. }
  573. #ifdef MAJOR_DBG
  574. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  575. DPFLTR_WARNING_LEVEL,
  576. RPCTRANS "MQ_ReceivePacket():\n"));
  577. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  578. DPFLTR_WARNING_LEVEL,
  579. " Receive on: %S\n",
  580. pEndpoint->wsQName));
  581. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  582. DPFLTR_WARNING_LEVEL,
  583. " From: %S\n",
  584. pDatagram->pAddress->wsQName));
  585. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  586. DPFLTR_WARNING_LEVEL,
  587. " Size: %d\n",
  588. dwBytes));
  589. DG_DbgPrintPacket(pDatagram->pPacket);
  590. #endif
  591. ASSERT((Status == RPC_S_OK)||(Status == RPC_P_OVERSIZE_PACKET));
  592. ASSERT(pDatagram->Busy);
  593. ASSERT(pDatagram->pPacket);
  594. ASSERT(dwBytes <= pDatagram->dwPacketSize);
  595. *pBuffer = (BUFFER)pDatagram->pPacket;
  596. *pBufferLength = dwBytes;
  597. *pReplyAddress = pDatagram->pAddress;
  598. pDatagram->pPacket = 0;
  599. pDatagram->dwPacketSize = 0;
  600. pDatagram->Busy = 0;
  601. return Status;
  602. #endif
  603. }
  604. RPC_STATUS
  605. MQ_CreateEndpoint(
  606. OUT MQ_DATAGRAM_ENDPOINT *pEndpoint,
  607. IN MQ_ADDRESS *pAddress,
  608. IN void *pSecurityDescriptor,
  609. IN DWORD dwEndpointFlags,
  610. IN PROTOCOL_ID id,
  611. IN BOOL fClient,
  612. IN BOOL fAsync
  613. )
  614. /*++
  615. Routine Description:
  616. Creates a new endpoint.
  617. Arguments:
  618. pEndpoint - The runtime allocated endpoint structure to
  619. filled in.
  620. pSockAddr - An initialized sockaddr with the correct
  621. (or no) endpoint.
  622. id - The id of the protocol to use in creating the address.
  623. fClient - If TRUE this is a client endpoint
  624. fAsync - If TRUE this endpoint is "async" which means that
  625. a) It should be added to the IO completion port and
  626. b) that the transport should pend a number of receives
  627. on the endpoint automatically.
  628. Return Value:
  629. RPC_S_OK
  630. RPC_S_OUT_OF_MEMORY
  631. RPC_S_OUT_OF_RESOURCES
  632. RPC_S_CANT_CREATE_ENDPOINT
  633. RPC_S_DUPLICATE_ENDPOINT
  634. --*/
  635. {
  636. MQ_DATAGRAM *pDatagram;
  637. int i;
  638. int err;
  639. int length;
  640. RPC_STATUS Status = RPC_S_OK;
  641. HRESULT hr;
  642. UUID uuid;
  643. DWORD dwSize;
  644. RPC_CHAR *pwsUuid;
  645. RPC_CHAR wsQName[MQ_MAX_Q_NAME_LEN];
  646. RPC_CHAR wsMachine[MAX_COMPUTERNAME_LEN];
  647. pEndpoint->type = DATAGRAM | ADDRESS;
  648. pEndpoint->id = id;
  649. pEndpoint->pAddressVector = 0;
  650. pEndpoint->SubmitListen = MQ_SubmitReceives;
  651. pEndpoint->InAddressList = NotInList;
  652. pEndpoint->pNext = 0;
  653. pEndpoint->fSubmittingIos = 0;
  654. pEndpoint->cPendingIos = 0;
  655. pEndpoint->cMinimumIos = 0;
  656. pEndpoint->cMaximumIos = 0;
  657. pEndpoint->aDatagrams = 0;
  658. pEndpoint->pFirstAddress = pEndpoint;
  659. pEndpoint->pNextAddress = 0;
  660. pEndpoint->hQueue = 0;
  661. pEndpoint->hAdminQueue = 0;
  662. // If we're told not to listen, then we won't allow receives
  663. // until we are specifically told to do so...
  664. #ifdef RPC_C_MQ_DONT_LISTEN
  665. pEndpoint->fAllowReceives = !(dwEndpointFlags & RPC_C_MQ_DONT_LISTEN);
  666. #else
  667. pEndpoint->fAllowReceives = TRUE;
  668. #endif
  669. pEndpoint->fAck = FALSE;
  670. pEndpoint->ulDelivery = RPC_C_MQ_EXPRESS;
  671. pEndpoint->ulPriority = DEFAULT_PRIORITY;
  672. pEndpoint->ulJournaling = RPC_C_MQ_JOURNAL_NONE;
  673. pEndpoint->ulTimeToReachQueue = INFINITE;
  674. pEndpoint->ulTimeToReceive = INFINITE;
  675. pEndpoint->fAuthenticate = FALSE;
  676. pEndpoint->fEncrypt = FALSE;
  677. pEndpoint->ulPrivacyLevel = 0;
  678. // Machine name:
  679. dwSize = sizeof(wsMachine);
  680. if (!GetComputerName((RPC_SCHAR *)wsMachine,&dwSize))
  681. {
  682. return RPC_S_OUT_OF_MEMORY;
  683. }
  684. // Get the name of the machine that the QM (mqsvc.exe)
  685. // is running on:
  686. dwSize = sizeof(pEndpoint->wsMachine);
  687. hr = QueryQM(pEndpoint->wsMachine,&dwSize);
  688. if (FAILED(hr))
  689. {
  690. Status = MQ_MapStatusCode(hr,RPC_S_CANT_CREATE_ENDPOINT);
  691. return Status;
  692. }
  693. //
  694. // See if this is a call from an RPC server or RPC client:
  695. //
  696. if (fClient)
  697. {
  698. pEndpoint->type |= CLIENT;
  699. // Queue name (a unique string...):
  700. Status = UuidCreate(&uuid);
  701. if ((Status != RPC_S_OK) && (Status != RPC_S_UUID_LOCAL_ONLY))
  702. {
  703. return Status;
  704. }
  705. if (UuidToString(&uuid,&pwsUuid) != RPC_S_OK)
  706. {
  707. return RPC_S_OUT_OF_MEMORY;
  708. }
  709. RpcpStringCopy(wsQName,TEXT("RpcCl-"));
  710. RpcpStringCat(wsQName,pwsUuid);
  711. // Function UuidCreate() allocated a string, free it:
  712. RpcStringFree(&pwsUuid);
  713. //
  714. // Create the queue for this endpoint:
  715. //
  716. hr = ClientSetupQueue( pEndpoint, pEndpoint->wsMachine, wsQName );
  717. Status = MQ_MapStatusCode(hr,RPC_S_CANT_CREATE_ENDPOINT);
  718. if (Status == RPC_S_OK)
  719. {
  720. MQ_RegisterQueueToDelete(pEndpoint->wsQFormat,wsMachine);
  721. }
  722. }
  723. else
  724. {
  725. pEndpoint->type |= SERVER;
  726. //
  727. // Create the queue for this server endpoint:
  728. //
  729. hr = ServerSetupQueue( pEndpoint,
  730. pEndpoint->wsMachine,
  731. pEndpoint->wsQName,
  732. pSecurityDescriptor,
  733. dwEndpointFlags );
  734. Status = MQ_MapStatusCode(hr,RPC_S_CANT_CREATE_ENDPOINT);
  735. //
  736. // Check to see if this queue is temporary. If so, then
  737. // register it with RPCSS to delete.
  738. //
  739. if ((Status == RPC_S_OK) && !(RPC_C_MQ_PERMANENT & dwEndpointFlags))
  740. {
  741. MQ_RegisterQueueToDelete(pEndpoint->wsQFormat,wsMachine);
  742. }
  743. }
  744. //
  745. // If the endpoint is going to async initialize async part
  746. // and add the socket to the IO completion port.
  747. //
  748. if (Status == RPC_S_OK)
  749. {
  750. int cMaxIos;
  751. int cMinIos;
  752. ASSERT(fAsync || fClient);
  753. // Step one, figure out the high and low mark for ios.
  754. if (fAsync)
  755. {
  756. // PERF REVIEW these parameters.
  757. cMaxIos = 2
  758. + (gfServerPlatform == TRUE) * 2
  759. + (fClient == FALSE) * gNumberOfProcessors;
  760. // This should be larger than zero so that we'll generally submit new
  761. // recvs during idle time rather then just after receiving a datagram.
  762. cMinIos = 1 + (fClient == FALSE ) * (gNumberOfProcessors/2);
  763. cMinIos = 1;
  764. cMaxIos = 1;
  765. }
  766. else
  767. {
  768. // For sync endpoints we need to allocate a single datagram
  769. // object for the receive.
  770. cMinIos = 0;
  771. cMaxIos = 1;
  772. }
  773. // ASSERT(cMinIos < cMaxIos); Not currently true...
  774. pEndpoint->cMinimumIos = cMinIos;
  775. pEndpoint->cMaximumIos = cMaxIos;
  776. // Allocate a chunk on memory to hold the array of datagrams
  777. // PERF: For clients, allocate larger array but don't submit all
  778. // the IOs unless we determine that the port is "really" active.
  779. pEndpoint->aDatagrams = new MQ_DATAGRAM[cMaxIos];
  780. if (pEndpoint->aDatagrams)
  781. {
  782. UINT type;
  783. type = DATAGRAM | RECEIVE;
  784. type |= (fClient) ? CLIENT : SERVER;
  785. for (i = 0; i < cMaxIos; i++)
  786. {
  787. pDatagram = &pEndpoint->aDatagrams[i];
  788. pDatagram->id = id;
  789. pDatagram->type = type;
  790. pDatagram->pEndpoint = pEndpoint;
  791. pDatagram->Busy = 0;
  792. pDatagram->pPacket = 0;
  793. pDatagram->dwPacketSize = 0;
  794. memset(&pDatagram->Read, 0, sizeof(pDatagram->Read));
  795. pDatagram->Read.pAsyncObject = pDatagram;
  796. }
  797. if (fAsync)
  798. {
  799. Status = COMMON_PrepareNewHandle((HANDLE)pEndpoint->hQueue);
  800. }
  801. else
  802. {
  803. // The receive operation on sync endpoints will may span
  804. // several receives. This means it can't use the thread
  805. // event, so allocate an event for the receive.
  806. HANDLE hEvent = CreateEvent(0, TRUE, FALSE, 0);
  807. if (!hEvent)
  808. {
  809. Status = RPC_S_OUT_OF_RESOURCES;
  810. }
  811. else
  812. {
  813. ASSERT(pDatagram == &pEndpoint->aDatagrams[0]);
  814. pDatagram->Read.ol.hEvent = hEvent;
  815. }
  816. }
  817. }
  818. else
  819. {
  820. Status = RPC_S_OUT_OF_MEMORY;
  821. }
  822. }
  823. // If adding a new failure case here, add code to close the sync receive event.
  824. if (Status != RPC_S_OK)
  825. {
  826. delete pEndpoint->aDatagrams;
  827. return Status;
  828. }
  829. return(RPC_S_OK);
  830. }
  831. void RPC_ENTRY
  832. MQ_ServerAbortListen(
  833. IN DG_TRANSPORT_ENDPOINT ThisEndpoint
  834. )
  835. /*++
  836. Routine Description:
  837. Callback after DG_CreateEndpoint has completed successfully
  838. but the runtime for some reason is not going to be able to
  839. listen on the endpoint.
  840. --*/
  841. {
  842. HRESULT hr;
  843. MQ_DATAGRAM_ENDPOINT *pEndpoint = (MQ_DATAGRAM_ENDPOINT*)ThisEndpoint;
  844. #ifdef MAJOR_DBG
  845. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  846. DPFLTR_WARNING_LEVEL,
  847. RPCTRANS "MQ_ServerAbortListen(): %S\n",
  848. pEndpoint->wsQName));
  849. #endif
  850. ASSERT(pEndpoint->cPendingIos == 0);
  851. ASSERT(pEndpoint->hQueue);
  852. ASSERT(pEndpoint->pNext == 0);
  853. ASSERT(pEndpoint->type & SERVER);
  854. if (pEndpoint->pAddressVector)
  855. {
  856. delete pEndpoint->pAddressVector;
  857. }
  858. if (pEndpoint->aDatagrams)
  859. {
  860. delete pEndpoint->aDatagrams;
  861. }
  862. hr = ServerCloseQueue(pEndpoint);
  863. return;
  864. }
  865. RPC_STATUS RPC_ENTRY
  866. MQ_ClientCloseEndpoint(
  867. IN DG_TRANSPORT_ENDPOINT ThisEndpoint
  868. )
  869. /*++
  870. Routine Description:
  871. Called on sync client endpoints when they are no longer needed.
  872. Arguments:
  873. ThisEndpoint
  874. Return Value:
  875. RPC_S_OK
  876. --*/
  877. {
  878. HRESULT hr;
  879. PMQ_DATAGRAM_ENDPOINT pEndpoint = (PMQ_DATAGRAM_ENDPOINT)ThisEndpoint;
  880. PMQ_DATAGRAM pDatagram = &pEndpoint->aDatagrams[0];
  881. ASSERT((pEndpoint->type & TYPE_MASK) == CLIENT);
  882. ASSERT(pEndpoint->hQueue); // MQOpenQueue must have worked
  883. ASSERT(pEndpoint->cMinimumIos == 0);
  884. ASSERT(pEndpoint->cMaximumIos == 1); // Must not be async!
  885. ASSERT(pEndpoint->aDatagrams);
  886. // ASSERT(pEndpoint->Endpoint == 0);
  887. ASSERT(pEndpoint->pAddressVector == 0);
  888. // ASSERT(pEndpoint->pNext == 0);
  889. // Close & delete the client queue:
  890. hr = ClientCloseQueue(pEndpoint);
  891. // Free the receive buffer if allocated
  892. if (pDatagram->pPacket)
  893. {
  894. I_RpcTransDatagramFree(pEndpoint,
  895. (BUFFER)pDatagram->pPacket,
  896. pDatagram->pAddress
  897. );
  898. }
  899. if (pDatagram->Read.ol.hEvent)
  900. {
  901. CloseHandle(pDatagram->Read.ol.hEvent);
  902. }
  903. delete pDatagram;
  904. pEndpoint->aDatagrams = 0;
  905. return(RPC_S_OK);
  906. }
  907. RPC_STATUS RPC_ENTRY
  908. MQ_ServerListen(
  909. IN OUT DG_TRANSPORT_ENDPOINT ThisEndpoint,
  910. IN RPC_CHAR *NetworkAddress,
  911. IN OUT RPC_CHAR **ppEndpoint,
  912. IN void *pSecurityDescriptor,
  913. IN ULONG EndpointFlags,
  914. IN ULONG NICFlags,
  915. OUT NETWORK_ADDRESS_VECTOR **ppNetworkAddressVector
  916. )
  917. /*++
  918. Routine Description:
  919. Creates a server endpoint object to receive packets. New
  920. packets won't actually arrive until CompleteListen is
  921. called.
  922. Arguments:
  923. ThisEndpoint - Storage for the server endpoint object.
  924. ppEndpoint - The RPC_CHAR name of the endpoint to listen
  925. on or a pointer to 0 if the transport should choose
  926. the address. Contains the endpoint listened to on
  927. output. The caller should free this.
  928. EndpointFlags - Application flags passed into RPC via
  929. RpcServerUseProtseq*Ex.
  930. NICFlags - Application flags passed into RPC via
  931. RpcServerUseProtseq*Ex.
  932. pNetworkAddresses - A vector of the network addresses
  933. listened on by this call. This vector does
  934. not need to be freed.
  935. Return Value:
  936. RPC_S_OK
  937. RPC_S_OUT_OF_MEMORY
  938. RPC_S_OUT_OF_RESOURCES
  939. RPC_S_CANT_CREATE_ENDPOINT
  940. RPC_S_INVALID_ENDPOINT_FORMAT
  941. RPC_S_DUPLICATE_ENDPOINT
  942. --*/
  943. {
  944. RPC_STATUS Status;
  945. DWORD dwSize;
  946. UUID uuid;
  947. RPC_CHAR *pUuidStr;
  948. MQ_DATAGRAM_ENDPOINT *pEndpoint = (MQ_DATAGRAM_ENDPOINT*)ThisEndpoint;
  949. *ppNetworkAddressVector = 0;
  950. if (*ppEndpoint)
  951. {
  952. // Known Endpoint:
  953. RpcpStringCopy(pEndpoint->wsQName,*ppEndpoint);
  954. }
  955. else
  956. {
  957. // Dynamic Endpoint:
  958. Status = UuidCreate(&uuid);
  959. if ((Status != RPC_S_OK) && (Status != RPC_S_UUID_LOCAL_ONLY))
  960. {
  961. return Status;
  962. }
  963. Status = UuidToString(&uuid,&pUuidStr);
  964. if (Status != RPC_S_OK)
  965. {
  966. return Status;
  967. }
  968. RpcpStringCopy(pEndpoint->wsQName,TEXT("RpcSvr-"));
  969. RpcpStringCat(pEndpoint->wsQName,pUuidStr);
  970. RpcStringFree(&pUuidStr);
  971. dwSize = (1+RpcpStringLength(pEndpoint->wsQName))*(sizeof(RPC_CHAR));
  972. *ppEndpoint = (RPC_CHAR*)I_RpcAllocate(dwSize);
  973. if (!*ppEndpoint)
  974. {
  975. return RPC_S_OUT_OF_MEMORY;
  976. }
  977. RpcpStringCopy(*ppEndpoint,pEndpoint->wsQName);
  978. }
  979. //
  980. // Actually create the endpoint
  981. //
  982. Status = MQ_CreateEndpoint( pEndpoint,
  983. NULL,
  984. pSecurityDescriptor,
  985. EndpointFlags,
  986. MSMQ,
  987. FALSE, // Server
  988. TRUE ); // Async
  989. if (Status != RPC_S_OK)
  990. {
  991. return Status;
  992. }
  993. Status = MQ_BuildAddressVector(&pEndpoint->pAddressVector);
  994. if (Status != RPC_S_OK)
  995. {
  996. MQ_ServerAbortListen(ThisEndpoint);
  997. return Status;
  998. }
  999. *ppNetworkAddressVector = pEndpoint->pAddressVector;
  1000. #if FALSE
  1001. // If needed, figure out the dynamically allocated endpoint.
  1002. if (!*pPort)
  1003. {
  1004. *pPort = new RPC_CHAR[IP_MAXIMUM_ENDPOINT];
  1005. if (!*pPort)
  1006. {
  1007. MQ_ServerAbortListen(ThisEndpoint);
  1008. return(RPC_S_OUT_OF_MEMORY);
  1009. }
  1010. port = ntohs(addr.inetaddr.sin_port);
  1011. PortNumberToEndpoint(port, *pPort);
  1012. }
  1013. // Figure out the network addresses
  1014. status = IP_BuildAddressVector(&pEndpoint->pAddressVector);
  1015. if (status != RPC_S_OK)
  1016. {
  1017. MQ_ServerAbortListen(ThisEndpoint);
  1018. return(status);
  1019. }
  1020. *ppNetworkAddressVector = pEndpoint->pAddressVector;
  1021. #endif
  1022. return RPC_S_OK;
  1023. }
  1024. RPC_STATUS
  1025. MQ_QueryEndpoint
  1026. (
  1027. IN void * pOriginalEndpoint,
  1028. OUT RPC_CHAR * pClientEndpoint
  1029. )
  1030. {
  1031. MQ_ADDRESS *pAddress = (MQ_ADDRESS*)pOriginalEndpoint;
  1032. if (!RpcpStringLength(pAddress->wsQName))
  1033. {
  1034. ParseQueuePathName(pAddress->wsMsgLabel,
  1035. pAddress->wsMachine,
  1036. pAddress->wsQName);
  1037. }
  1038. RpcpStringCopy(pClientEndpoint,pAddress->wsQName);
  1039. return RPC_S_OK;
  1040. }
  1041. RPC_STATUS
  1042. MQ_QueryAddress
  1043. (
  1044. IN void * pOriginalEndpoint,
  1045. OUT RPC_CHAR * pClientAddress
  1046. )
  1047. {
  1048. MQ_ADDRESS *pAddress = (MQ_ADDRESS*)pOriginalEndpoint;
  1049. if (!RpcpStringLength(pAddress->wsMachine))
  1050. {
  1051. ParseQueuePathName(pAddress->wsMsgLabel,
  1052. pAddress->wsMachine,
  1053. pAddress->wsQName);
  1054. }
  1055. RpcpStringCopy(pClientAddress,pAddress->wsMachine);
  1056. return RPC_S_OK;
  1057. }
  1058. RPC_STATUS
  1059. RPC_ENTRY
  1060. MQ_ClientInitializeAddress
  1061. (
  1062. OUT DG_TRANSPORT_ADDRESS pvAddress,
  1063. IN RPC_CHAR *pNetworkAddress,
  1064. IN RPC_CHAR *pEndpoint,
  1065. IN BOOL fUseCache,
  1066. IN BOOL fBroadcast
  1067. )
  1068. /*++
  1069. Routine Description:
  1070. Initializes a address object for sending to a server.
  1071. Arguments:
  1072. pvAddress - Storage for the address
  1073. pNetworkAddress - The address of the server or 0 if local
  1074. pEndpoint - The endpoint of the server
  1075. fUseCache - If TRUE then the transport may use a cached
  1076. value from a previous call on the same NetworkAddress.
  1077. fBroadcast - If TRUE, NetworkAddress is ignored and a broadcast
  1078. address is used.
  1079. Return Value:
  1080. RPC_S_OK - Success, name resolved and, optionally, added to cache.
  1081. RPC_P_FOUND_IN_CACHE - Success, returned only if fUseCache is TRUE
  1082. and the was name found in local cache.
  1083. RPC_P_MATCHED_CACHE - Partial success, fUseCache is FALSE and the
  1084. result of the lookup was the same as the value previously
  1085. in the cache.
  1086. RPC_S_OUT_OF_MEMORY
  1087. RPC_S_OUT_OF_RESOURCES
  1088. RPC_S_INVALID_ENDPOINT_FORMAT
  1089. RPC_S_SERVER_UNAVAILABLE
  1090. --*/
  1091. {
  1092. RPC_STATUS Status = RPC_S_OK;
  1093. MQ_ADDRESS *pAddress = (MQ_ADDRESS*)pvAddress;
  1094. ASSERT(pvAddress);
  1095. Status = ConnectToServerQueue(pAddress,pNetworkAddress,pEndpoint);
  1096. return Status;
  1097. }
  1098. RPC_STATUS
  1099. RPC_ENTRY
  1100. MQ_ClientOpenEndpoint(
  1101. OUT DG_TRANSPORT_ENDPOINT ThisEndpoint,
  1102. IN BOOL fAsync,
  1103. DWORD Flags
  1104. )
  1105. {
  1106. RPC_STATUS Status;
  1107. MQ_DATAGRAM_ENDPOINT *pEndpoint = (MQ_DATAGRAM_ENDPOINT*)ThisEndpoint;
  1108. Status = MQ_CreateEndpoint(pEndpoint, NULL, NULL, 0, MSMQ, TRUE, fAsync);
  1109. return Status;
  1110. }
  1111. RPC_STATUS
  1112. RPC_ENTRY
  1113. MQ_GetEndpointStats(
  1114. IN DG_TRANSPORT_ENDPOINT ThisEndpoint,
  1115. OUT DG_ENDPOINT_STATS * pStats
  1116. )
  1117. {
  1118. pStats->PreferredPduSize = MQ_PREFERRED_PDU_SIZE;
  1119. pStats->MaxPduSize = MQ_MAX_PDU_SIZE;
  1120. pStats->MaxPacketSize = MQ_MAX_PACKET_SIZE;
  1121. pStats->ReceiveBufferSize = MQ_RECEIVE_BUFFER_SIZE;
  1122. return RPC_S_OK;
  1123. }
  1124. //----------------------------------------------------------------
  1125. // MQ_InquireAuthClient()
  1126. //
  1127. // Fill out security information for the transport.
  1128. //
  1129. // NOTE: The returned SID (ppSid) is a pointer to the one in the
  1130. // client endpoint. The caller can't free it and should make
  1131. // its own copy...
  1132. //----------------------------------------------------------------
  1133. RPC_STATUS
  1134. RPC_ENTRY
  1135. MQ_InquireAuthClient( void *pvClientEndpoint,
  1136. RPC_CHAR **ppPrincipal,
  1137. SID **ppSid,
  1138. ULONG *pulAuthnLevel,
  1139. ULONG *pulAuthnService,
  1140. ULONG *pulAuthzService )
  1141. {
  1142. RPC_STATUS Status = RPC_S_OK;
  1143. MQ_ADDRESS *pClientEndpoint = (MQ_ADDRESS*)(pvClientEndpoint);
  1144. SID *pClientSid;
  1145. DWORD dwSize;
  1146. ASSERT(pulAuthnLevel);
  1147. ASSERT(pulAuthnService);
  1148. ASSERT(pulAuthzService);
  1149. if (pClientEndpoint)
  1150. {
  1151. *ppPrincipal = NULL;
  1152. *pulAuthnService = RPC_C_AUTHN_MQ;
  1153. *pulAuthzService = RPC_C_AUTHZ_NONE;
  1154. //
  1155. // The authentication level:
  1156. //
  1157. if (pClientEndpoint->fAuthenticated)
  1158. {
  1159. if (pClientEndpoint->ulPrivacyLevel == MQMSG_PRIV_LEVEL_BODY_BASE)
  1160. *pulAuthnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
  1161. else
  1162. *pulAuthnLevel = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
  1163. }
  1164. else if (pClientEndpoint->ulPrivacyLevel == MQMSG_PRIV_LEVEL_BODY_BASE)
  1165. {
  1166. *pulAuthnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
  1167. }
  1168. else
  1169. {
  1170. *pulAuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
  1171. }
  1172. if ( IsValidSid((PSID)(pClientEndpoint->aSidBuffer)) )
  1173. *ppSid = (SID*)(pClientEndpoint->aSidBuffer);
  1174. else
  1175. *ppSid = NULL;
  1176. }
  1177. else
  1178. Status = RPC_S_BINDING_HAS_NO_AUTH;
  1179. return Status;
  1180. }