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.

908 lines
26 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. comObjs
  5. Abstract:
  6. This file provides the implementation for the communcation objects used in
  7. Calais. A communications object (CComObject and it's derivatives) is
  8. capable of transmitting itself across a CComChannel.
  9. Author:
  10. Doug Barlow (dbarlow) 11/6/1996
  11. Environment:
  12. Win32, C++ w/ Exceptions
  13. Notes:
  14. ?Notes?
  15. --*/
  16. #define __SUBROUTINE__
  17. #ifndef WIN32_LEAN_AND_MEAN
  18. #define WIN32_LEAN_AND_MEAN
  19. #endif
  20. #include <windows.h>
  21. #include <WinSCard.h>
  22. #include <CalMsgs.h>
  23. #include <CalCom.h>
  24. #include <limits.h>
  25. //
  26. // Maximum size for the payload of a service request or response.
  27. //
  28. // Current value is max size of an unsigned WORD, as this is the max
  29. // card packet size defined by ISO.
  30. //
  31. #define cbMAX_COM_REQUEST_RESPONSE_SIZE USHRT_MAX
  32. const DWORD
  33. CComObject::AUTOCOUNT = 0, // Force computing string length.
  34. CComObject::MULTISTRING = (DWORD)(-1); // Force computing multistring len.
  35. //
  36. //==============================================================================
  37. //
  38. // CComObject and derivatives.
  39. //
  40. /*++
  41. CComObject:
  42. This is the base constructor for a CComObject. These objects assume that
  43. they are not in charge of anything past their own internal buffers.
  44. Therefore they won't close handles, etc, when destructing.
  45. Arguments:
  46. None
  47. Return Value:
  48. None
  49. Throws:
  50. None
  51. Author:
  52. Doug Barlow (dbarlow) 11/13/1996
  53. --*/
  54. #undef __SUBROUTINE__
  55. #define __SUBROUTINE__ DBGT("CComObject::CComObject")
  56. CComObject::CComObject(
  57. void)
  58. : m_bfRequest(),
  59. m_bfResponse()
  60. {
  61. m_pbfActive = NULL;
  62. }
  63. /*++
  64. ReceiveComObject:
  65. This is a static member routine that creates the proper CComObject child
  66. object for the data coming in on a CComChannel.
  67. Arguments:
  68. pChannel supplies a pointer to the CComChannel on which the transfer
  69. structure will come in.
  70. Return Value:
  71. The newly created CComObject child object. This object must be cleaned up
  72. via the delete command.
  73. Throws:
  74. ?exceptions?
  75. Author:
  76. Doug Barlow (dbarlow) 11/13/1996
  77. --*/
  78. #undef __SUBROUTINE__
  79. #define __SUBROUTINE__ DBGT("CComObject::ReceiveComObject")
  80. CComObject *
  81. CComObject::ReceiveComObject(
  82. CComChannel *pChannel)
  83. {
  84. CComObject *pCom = NULL;
  85. DWORD dwMinSize = (DWORD)(-1);
  86. try
  87. {
  88. DWORD rgdwInData[2];
  89. //
  90. // See what's coming.
  91. //
  92. pChannel->Receive(rgdwInData, sizeof(rgdwInData));
  93. if (sizeof(rgdwInData) > rgdwInData[1])
  94. throw (DWORD)SCARD_F_COMM_ERROR;
  95. switch (rgdwInData[0]) // dwCommndId
  96. {
  97. case EstablishContext_request:
  98. dwMinSize = sizeof(ComEstablishContext::CObjEstablishContext_request);
  99. pCom = new ComEstablishContext;
  100. break;
  101. case EstablishContext_response:
  102. dwMinSize = sizeof(ComEstablishContext::CObjEstablishContext_response);
  103. pCom = new ComEstablishContext;
  104. break;
  105. case ReleaseContext_request:
  106. dwMinSize = sizeof(ComReleaseContext::CObjReleaseContext_request);
  107. pCom = new ComReleaseContext;
  108. break;
  109. case ReleaseContext_response:
  110. dwMinSize = sizeof(ComReleaseContext::CObjReleaseContext_response);
  111. pCom = new ComReleaseContext;
  112. break;
  113. case IsValidContext_request:
  114. dwMinSize = sizeof(ComIsValidContext::CObjIsValidContext_request);
  115. pCom = new ComIsValidContext;
  116. break;
  117. case IsValidContext_response:
  118. dwMinSize = sizeof(ComIsValidContext::CObjIsValidContext_response);
  119. pCom = new ComIsValidContext;
  120. break;
  121. case ListReaders_request:
  122. dwMinSize = sizeof(ComListReaders::CObjListReaders_request);
  123. pCom = new ComListReaders;
  124. break;
  125. case ListReaders_response:
  126. dwMinSize = sizeof(ComListReaders::CObjListReaders_response);
  127. pCom = new ComListReaders;
  128. break;
  129. #if 0
  130. case ListReaderGroups_request:
  131. dwMinSize = sizeof(ComListReaderGroups::CObjListReaderGroups_request);
  132. pCom = new ComListReaderGroups;
  133. break;
  134. case ListReaderGroups_response:
  135. dwMinSize = sizeof(ComListReaderGroups::CObjListReaderGroups_response);
  136. pCom = new ComListReaderGroups;
  137. break;
  138. case ListCards_request:
  139. dwMinSize = sizeof(ComListCards::CObjListCards_request);
  140. pCom = new ComListCards;
  141. break;
  142. case ListCards_response:
  143. dwMinSize = sizeof(ComListCards::CObjListCards_response);
  144. pCom = new ComListCards;
  145. break;
  146. case ListInterfaces_request:
  147. dwMinSize = sizeof(ComListInterfaces::CObjListInterfaces_request);
  148. pCom = new ComListInterfaces;
  149. break;
  150. case ListInterfaces_response:
  151. dwMinSize = sizeof(ComListInterfaces::CObjListInterfaces_response);
  152. pCom = new ComListInterfaces;
  153. break;
  154. case GetProviderId_request:
  155. dwMinSize = sizeof(ComGetProviderId::CObjGetProviderId_request);
  156. pCom = new ComGetProviderId;
  157. break;
  158. case GetProviderId_response:
  159. dwMinSize = sizeof(ComGetProviderId::CObjGetProviderId_response);
  160. pCom = new ComGetProviderId;
  161. break;
  162. case IntroduceReaderGroup_request:
  163. dwMinSize = sizeof(ComIntroduceReaderGroup::CObjIntroduceReaderGroup_request);
  164. pCom = new ComIntroduceReaderGroup;
  165. break;
  166. case IntroduceReaderGroup_response:
  167. dwMinSize = sizeof(ComIntroduceReaderGroup::CObjIntroduceReaderGroup_response);
  168. pCom = new ComIntroduceReaderGroup;
  169. break;
  170. case ForgetReaderGroup_request:
  171. dwMinSize = sizeof(ComForgetReaderGroup::CObjForgetReaderGroup_request);
  172. pCom = new ComForgetReaderGroup;
  173. break;
  174. case ForgetReaderGroup_response:
  175. dwMinSize = sizeof(ComForgetReaderGroup::CObjForgetReaderGroup_response);
  176. pCom = new ComForgetReaderGroup;
  177. break;
  178. case IntroduceReader_request:
  179. dwMinSize = sizeof(ComIntroduceReader::CObjIntroduceReader_request);
  180. pCom = new ComIntroduceReader;
  181. break;
  182. case IntroduceReader_response:
  183. dwMinSize = sizeof(ComIntroduceReader::CObjIntroduceReader_response);
  184. pCom = new ComIntroduceReader;
  185. break;
  186. case ForgetReader_request:
  187. dwMinSize = sizeof(ComForgetReader::CObjForgetReader_request);
  188. pCom = new ComForgetReader;
  189. break;
  190. case ForgetReader_response:
  191. dwMinSize = sizeof(ComForgetReader::CObjForgetReader_response);
  192. pCom = new ComForgetReader;
  193. break;
  194. case AddReaderToGroup_request:
  195. dwMinSize = sizeof(ComAddReaderToGroup::CObjAddReaderToGroup_request);
  196. pCom = new ComAddReaderToGroup;
  197. break;
  198. case AddReaderToGroup_response:
  199. dwMinSize = sizeof(ComAddReaderToGroup::CObjAddReaderToGroup_response);
  200. pCom = new ComAddReaderToGroup;
  201. break;
  202. case RemoveReaderFromGroup_request:
  203. dwMinSize = sizeof(ComRemoveReaderFromGroup::CObjRemoveReaderFromGroup_request);
  204. pCom = new ComRemoveReaderFromGroup;
  205. break;
  206. case RemoveReaderFromGroup_response:
  207. dwMinSize = sizeof(ComRemoveReaderFromGroup::CObjRemoveReaderFromGroup_response);
  208. pCom = new ComRemoveReaderFromGroup;
  209. break;
  210. case IntroduceCardType_request:
  211. dwMinSize = sizeof(ComIntroduceCardType::CObjIntroduceCardType_request);
  212. pCom = new ComIntroduceCardType;
  213. break;
  214. case IntroduceCardType_response:
  215. dwMinSize = sizeof(ComIntroduceCardType::CObjIntroduceCardType_response);
  216. pCom = new ComIntroduceCardType;
  217. break;
  218. case ForgetCardType_request:
  219. dwMinSize = sizeof(ComForgetCardType::CObjForgetCardType_request);
  220. pCom = new ComForgetCardType;
  221. break;
  222. case ForgetCardType_response:
  223. dwMinSize = sizeof(ComForgetCardType::CObjForgetCardType_response);
  224. pCom = new ComForgetCardType;
  225. break;
  226. case FreeMemory_request:
  227. dwMinSize = sizeof(ComFreeMemory::CObjFreeMemory_request);
  228. pCom = new ComFreeMemory;
  229. break;
  230. case FreeMemory_response:
  231. dwMinSize = sizeof(ComFreeMemory::CObjFreeMemory_response);
  232. pCom = new ComFreeMemory;
  233. break;
  234. case Cancel_request:
  235. dwMinSize = sizeof(ComCancel::CObjCancel_request);
  236. pCom = new ComCancel;
  237. break;
  238. case Cancel_response:
  239. dwMinSize = sizeof(ComCancel::CObjCancel_response);
  240. pCom = new ComCancel;
  241. break;
  242. #endif
  243. case LocateCards_request:
  244. dwMinSize = sizeof(ComLocateCards::CObjLocateCards_request);
  245. pCom = new ComLocateCards;
  246. break;
  247. case LocateCards_response:
  248. dwMinSize = sizeof(ComLocateCards::CObjLocateCards_response);
  249. pCom = new ComLocateCards;
  250. break;
  251. case GetStatusChange_request:
  252. dwMinSize = sizeof(ComGetStatusChange::CObjGetStatusChange_request);
  253. pCom = new ComGetStatusChange;
  254. break;
  255. case GetStatusChange_response:
  256. dwMinSize = sizeof(ComGetStatusChange::CObjGetStatusChange_response);
  257. pCom = new ComGetStatusChange;
  258. break;
  259. case Connect_request:
  260. dwMinSize = sizeof(ComConnect::CObjConnect_request);
  261. pCom = new ComConnect;
  262. break;
  263. case Connect_response:
  264. dwMinSize = sizeof(ComConnect::CObjConnect_response);
  265. pCom = new ComConnect;
  266. break;
  267. case Reconnect_request:
  268. dwMinSize = sizeof(ComReconnect::CObjReconnect_request);
  269. pCom = new ComReconnect;
  270. break;
  271. case Reconnect_response:
  272. dwMinSize = sizeof(ComReconnect::CObjReconnect_response);
  273. pCom = new ComReconnect;
  274. break;
  275. case Disconnect_request:
  276. dwMinSize = sizeof(ComDisconnect::CObjDisconnect_request);
  277. pCom = new ComDisconnect;
  278. break;
  279. case Disconnect_response:
  280. dwMinSize = sizeof(ComDisconnect::CObjDisconnect_response);
  281. pCom = new ComDisconnect;
  282. break;
  283. case BeginTransaction_request:
  284. dwMinSize = sizeof(ComBeginTransaction::CObjBeginTransaction_request);
  285. pCom = new ComBeginTransaction;
  286. break;
  287. case BeginTransaction_response:
  288. dwMinSize = sizeof(ComBeginTransaction::CObjBeginTransaction_response);
  289. pCom = new ComBeginTransaction;
  290. break;
  291. case EndTransaction_request:
  292. dwMinSize = sizeof(ComEndTransaction::CObjEndTransaction_request);
  293. pCom = new ComEndTransaction;
  294. break;
  295. case EndTransaction_response:
  296. dwMinSize = sizeof(ComEndTransaction::CObjEndTransaction_response);
  297. pCom = new ComEndTransaction;
  298. break;
  299. case Status_request:
  300. dwMinSize = sizeof(ComStatus::CObjStatus_request);
  301. pCom = new ComStatus;
  302. break;
  303. case Status_response:
  304. dwMinSize = sizeof(ComStatus::CObjStatus_response);
  305. pCom = new ComStatus;
  306. break;
  307. case Transmit_request:
  308. dwMinSize = sizeof(ComTransmit::CObjTransmit_request);
  309. pCom = new ComTransmit;
  310. break;
  311. case Transmit_response:
  312. dwMinSize = sizeof(ComTransmit::CObjTransmit_response);
  313. pCom = new ComTransmit;
  314. break;
  315. case OpenReader_request:
  316. dwMinSize = sizeof(ComOpenReader::CObjOpenReader_request);
  317. pCom = new ComOpenReader;
  318. break;
  319. case OpenReader_response:
  320. dwMinSize = sizeof(ComOpenReader::CObjOpenReader_response);
  321. pCom = new ComOpenReader;
  322. break;
  323. case Control_request:
  324. dwMinSize = sizeof(ComControl::CObjControl_request);
  325. pCom = new ComControl;
  326. break;
  327. case Control_response:
  328. dwMinSize = sizeof(ComControl::CObjControl_response);
  329. pCom = new ComControl;
  330. break;
  331. case GetAttrib_request:
  332. dwMinSize = sizeof(ComGetAttrib::CObjGetAttrib_request);
  333. pCom = new ComGetAttrib;
  334. break;
  335. case GetAttrib_response:
  336. dwMinSize = sizeof(ComGetAttrib::CObjGetAttrib_response);
  337. pCom = new ComGetAttrib;
  338. break;
  339. case SetAttrib_request:
  340. dwMinSize = sizeof(ComSetAttrib::CObjSetAttrib_request);
  341. pCom = new ComSetAttrib;
  342. break;
  343. case SetAttrib_response:
  344. dwMinSize = sizeof(ComSetAttrib::CObjSetAttrib_response);
  345. pCom = new ComSetAttrib;
  346. break;
  347. default:
  348. CalaisWarning(
  349. __SUBROUTINE__,
  350. DBGT("Invalid Comm Object Id on pipe"));
  351. throw (DWORD)SCARD_F_COMM_ERROR;
  352. }
  353. if (NULL == pCom)
  354. {
  355. CalaisWarning(
  356. __SUBROUTINE__,
  357. DBGT("No memory for incoming comm object"));
  358. throw (DWORD)SCARD_E_NO_MEMORY;
  359. }
  360. if (dwMinSize > rgdwInData[1])
  361. throw (DWORD)SCARD_F_COMM_ERROR;
  362. if (0 == (rgdwInData[0] & 0x01)) // Request or response?
  363. pCom->m_pbfActive = &pCom->m_bfRequest;
  364. else
  365. pCom->m_pbfActive = &pCom->m_bfResponse;
  366. //
  367. // Pull it in.
  368. //
  369. if (cbMAX_COM_REQUEST_RESPONSE_SIZE < rgdwInData[1])
  370. throw (DWORD) SCARD_E_INVALID_PARAMETER;
  371. pCom->m_pbfActive->Resize(rgdwInData[1]);
  372. CopyMemory(
  373. pCom->m_pbfActive->Access(),
  374. rgdwInData,
  375. sizeof(rgdwInData));
  376. pChannel->Receive(
  377. pCom->m_pbfActive->Access(sizeof(rgdwInData)),
  378. rgdwInData[1] - sizeof(rgdwInData));
  379. #ifdef DBG
  380. WriteApiLog(pCom->m_pbfActive->Access(), pCom->m_pbfActive->Length());
  381. for (DWORD ix = 0; ix < rgdwInData[1] / sizeof(DWORD); ix += 1)
  382. {
  383. ASSERT(0xcdcdcdcd != *(LPDWORD)pCom->m_pbfActive->Access(
  384. ix * sizeof(DWORD)));
  385. }
  386. #endif
  387. }
  388. catch (...)
  389. {
  390. if (NULL != pCom)
  391. delete pCom;
  392. throw;
  393. }
  394. return pCom;
  395. }
  396. /*++
  397. Receive:
  398. This function receives a specific com object.
  399. Arguments:
  400. pChannel supplies a pointer to the CComChannel on which the transfer
  401. structure will come in.
  402. Return Value:
  403. None
  404. Throws:
  405. ?exceptions?
  406. Author:
  407. Doug Barlow (dbarlow) 11/18/1996
  408. --*/
  409. #undef __SUBROUTINE__
  410. #define __SUBROUTINE__ DBGT("CComObject::Receive")
  411. CComObject::CObjGeneric_response *
  412. CComObject::Receive(
  413. CComChannel *pChannel)
  414. {
  415. DWORD rgdwInData[2];
  416. CComObject::CObjGeneric_response *pRsp
  417. = (CComObject::CObjGeneric_response *)Data();
  418. pChannel->Receive(rgdwInData, sizeof(rgdwInData));
  419. if (rgdwInData[0] != pRsp->dwCommandId)
  420. {
  421. CalaisWarning(
  422. __SUBROUTINE__,
  423. DBGT("Comm Object receive object mismatch"));
  424. throw (DWORD)SCARD_F_COMM_ERROR;
  425. }
  426. if (rgdwInData[1] < sizeof(CComObject::CObjGeneric_response))
  427. {
  428. CalaisWarning(
  429. __SUBROUTINE__,
  430. DBGT("Comm Object receive object invalid"));
  431. throw (DWORD)SCARD_F_COMM_ERROR;
  432. }
  433. ASSERT(m_pbfActive == ((0 == (rgdwInData[0] & 0x01)
  434. ? &m_bfRequest
  435. : &m_bfResponse)));
  436. //
  437. // Pull it in.
  438. //
  439. m_pbfActive->Resize(rgdwInData[1]);
  440. CopyMemory(
  441. m_pbfActive->Access(),
  442. rgdwInData,
  443. sizeof(rgdwInData));
  444. pChannel->Receive(
  445. m_pbfActive->Access(sizeof(rgdwInData)),
  446. rgdwInData[1] - sizeof(rgdwInData));
  447. #ifdef DBG
  448. for (DWORD ix = 0; ix < rgdwInData[1] / sizeof(DWORD); ix += 1)
  449. {
  450. ASSERT(0xcdcdcdcd != *(LPDWORD)m_pbfActive->Access(ix * sizeof(DWORD)));
  451. }
  452. WriteApiLog(m_pbfActive->Access(), m_pbfActive->Length());
  453. #endif
  454. return (CComObject::CObjGeneric_response *)m_pbfActive->Access();
  455. }
  456. /*++
  457. Send:
  458. This function sends the ComObject over the given Comm Channel.
  459. Arguments:
  460. pChannel supplies a pointer to the CComChannel on which the transfer
  461. structure will be sent.
  462. Return Value:
  463. None
  464. Throws:
  465. Errors are thrown as DWORD status codes.
  466. Remarks:
  467. Author:
  468. Doug Barlow (dbarlow) 8/5/1998
  469. --*/
  470. #undef __SUBROUTINE__
  471. #define __SUBROUTINE__ DBGT("CComObject::Send")
  472. DWORD
  473. CComObject::Send(
  474. CComChannel *pChannel)
  475. {
  476. #ifdef DBG
  477. ComObjCheck;
  478. WriteApiLog(Data(), Length());
  479. #endif
  480. return pChannel->Send(Data(), Length());
  481. }
  482. /*++
  483. InitStruct:
  484. This method implements simple base class preparation to build request and
  485. response structures.
  486. Arguments:
  487. dwCommandId supplies the command identifier.
  488. dwDataOffset supplies the size of the structure to be inserted.
  489. Return Value:
  490. None
  491. Throws:
  492. ?exceptions?
  493. Author:
  494. Doug Barlow (dbarlow) 11/13/1996
  495. --*/
  496. #undef __SUBROUTINE__
  497. #define __SUBROUTINE__ DBGT("CComObject::InitStruct")
  498. void
  499. CComObject::InitStruct(
  500. DWORD dwCommandId,
  501. DWORD dwDataOffset,
  502. DWORD dwExtra)
  503. {
  504. if (0 == (dwCommandId & 0x01))
  505. m_pbfActive = &m_bfRequest;
  506. else
  507. m_pbfActive = &m_bfResponse;
  508. ASSERT(NULL != m_pbfActive);
  509. ASSERT(0 == dwDataOffset % sizeof(DWORD));
  510. CObjGeneric_request *pReq =
  511. (CObjGeneric_request *)m_pbfActive->Presize(dwDataOffset + dwExtra);
  512. m_pbfActive->Resize(dwDataOffset, TRUE);
  513. pReq->dwCommandId = dwCommandId;
  514. pReq->dwTotalLength = dwDataOffset;
  515. pReq->dwDataOffset = dwDataOffset;
  516. }
  517. /*++
  518. Append:
  519. These methods append data to the transfer structure, updating the Total
  520. Length. Note that this action may affect the address of the structure being
  521. appended to. This routine returns the address of that structure, in case it
  522. changes.
  523. Arguments:
  524. dsc supplies the descriptor to fill in with the offset and length.
  525. szString supplies the data to be appended as a string value.
  526. cchLen supplies the length of the data to be appended in characters, or one
  527. of the following special flags:
  528. AUTOCOUNT - The string's size should be determined via lstrlen.
  529. MULTISTRING - The string's size should be determined via mstrlen;
  530. Return Value:
  531. The address of the updated structure, which may have moved in memory.
  532. Throws:
  533. None
  534. Author:
  535. Doug Barlow (dbarlow) 11/13/1996
  536. --*/
  537. #undef __SUBROUTINE__
  538. #define __SUBROUTINE__ DBGT("CComObject::Append")
  539. LPBYTE
  540. CComObject::Append(
  541. CComObject::Desc &dsc,
  542. LPCTSTR szString,
  543. DWORD cchLen)
  544. {
  545. DWORD dwLen;
  546. switch (cchLen)
  547. {
  548. case AUTOCOUNT:
  549. dwLen = lstrlen(szString) + 1; // Include trailing null char.
  550. break;
  551. case MULTISTRING:
  552. dwLen = MStrLen(szString); // It includes trailing null char.
  553. break;
  554. default:
  555. dwLen = cchLen;
  556. }
  557. dwLen *= sizeof(TCHAR);
  558. return Append(dsc, (LPCBYTE)szString, dwLen);
  559. }
  560. LPBYTE
  561. CComObject::Append(
  562. CComObject::Desc &dsc,
  563. LPCBYTE pbData,
  564. DWORD cbLength)
  565. {
  566. static const DWORD dwZero = 0;
  567. DWORD
  568. dwDataLength,
  569. dwPadLen;
  570. CObjGeneric_request *pData;
  571. ComObjCheck;
  572. dwPadLen = sizeof(DWORD) - cbLength % sizeof(DWORD);
  573. if (sizeof(DWORD) == dwPadLen)
  574. dwPadLen = 0;
  575. dwDataLength = m_pbfActive->Length() + cbLength + dwPadLen;
  576. dsc.dwOffset = m_pbfActive->Length();
  577. dsc.dwLength = cbLength;
  578. // Now we might change the address of dsc.
  579. m_pbfActive->Presize(dwDataLength, TRUE);
  580. m_pbfActive->Append(pbData, cbLength);
  581. m_pbfActive->Append((LPCBYTE)&dwZero, dwPadLen);
  582. pData = (CObjGeneric_request *)m_pbfActive->Access();
  583. pData->dwTotalLength = dwDataLength;
  584. return m_pbfActive->Access();
  585. }
  586. /*++
  587. Parse:
  588. This routine converts a given descriptor in the current communications
  589. object buffer back into a pointer and optional length.
  590. Arguments:
  591. dsc supplies the descriptor of the current communications object to be
  592. parsed.
  593. pcbLen receives the length, in bytes, of the value referenced by the
  594. descriptor. If this parameter is NULL, no length value is returned.
  595. Return Value:
  596. The address of the value referenced by the descriptor.
  597. Throws:
  598. ?exceptions?
  599. Author:
  600. Doug Barlow (dbarlow) 12/11/1996
  601. --*/
  602. #undef __SUBROUTINE__
  603. #define __SUBROUTINE__ DBGT("CComObject::Parse")
  604. LPCVOID
  605. CComObject::Parse(
  606. Desc &dsc,
  607. LPDWORD pcbLen)
  608. {
  609. CObjGeneric_request *pGen;
  610. ComObjCheck;
  611. pGen = (CObjGeneric_request *)m_pbfActive->Access();
  612. ASSERT((LPCVOID)&dsc > (LPCVOID)m_pbfActive->Access());
  613. ASSERT((LPCVOID)&dsc
  614. < (LPCVOID)m_pbfActive->Access(m_pbfActive->Length() - 1));
  615. ASSERT((LPCVOID)&dsc
  616. < (LPCVOID)m_pbfActive->Access(pGen->dwDataOffset - 1));
  617. if (dsc.dwOffset + dsc.dwLength > m_pbfActive->Length())
  618. throw (DWORD)SCARD_F_COMM_ERROR;
  619. if (NULL != pcbLen)
  620. *pcbLen = dsc.dwLength;
  621. return m_pbfActive->Access(dsc.dwOffset);
  622. }
  623. #ifdef DBG
  624. /*++
  625. dbgCheck:
  626. This routine validates the internal structure of a CComObject.
  627. Arguments:
  628. None
  629. Return Value:
  630. None
  631. Throws:
  632. None, but it will assert if something is wrong.
  633. Author:
  634. Doug Barlow (dbarlow) 12/11/1996
  635. --*/
  636. #undef __SUBROUTINE__
  637. #define __SUBROUTINE__ DBGT("CComObject::dbgCheck")
  638. void
  639. CComObject::dbgCheck(
  640. void)
  641. const
  642. {
  643. DWORD
  644. dwCommandId,
  645. dwDataLength,
  646. dwDataOffset;
  647. CObjGeneric_request *pData;
  648. ASSERT(EstablishContext_request == 0);
  649. ASSERT(NULL != m_pbfActive);
  650. ASSERT(3 * sizeof(DWORD) <= m_pbfActive->Length());
  651. pData = (CObjGeneric_request *)m_pbfActive->Access();
  652. dwCommandId = pData->dwCommandId;
  653. dwDataLength = pData->dwTotalLength;
  654. dwDataOffset = pData->dwDataOffset;
  655. ASSERT(dwDataLength == m_pbfActive->Length());
  656. ASSERT(dwDataOffset <= dwDataLength);
  657. ASSERT(0 == dwDataOffset % sizeof(DWORD));
  658. ASSERT(0 == dwDataLength % sizeof(DWORD));
  659. ASSERT(m_pbfActive
  660. == ((0 == (dwCommandId & 0x01))
  661. ? &m_bfRequest
  662. : &m_bfResponse));
  663. }
  664. typedef struct
  665. {
  666. SYSTEMTIME stLogTime;
  667. DWORD dwProcId;
  668. DWORD dwThreadId;
  669. } LogStamp;
  670. #undef __SUBROUTINE__
  671. #define __SUBROUTINE__ DBGT("WriteApiLog")
  672. void
  673. WriteApiLog(
  674. LPCVOID pvData,
  675. DWORD cbLength)
  676. {
  677. static HANDLE hLogMutex = NULL;
  678. BOOL fGotMutex = FALSE;
  679. HANDLE hLogFile = INVALID_HANDLE_VALUE;
  680. try
  681. {
  682. hLogFile = CreateFile(
  683. CalaisString(CALSTR_APITRACEFILENAME),
  684. GENERIC_WRITE,
  685. FILE_SHARE_READ | FILE_SHARE_WRITE,
  686. NULL,
  687. OPEN_EXISTING,
  688. FILE_ATTRIBUTE_NORMAL,
  689. NULL);
  690. if (INVALID_HANDLE_VALUE != hLogFile)
  691. {
  692. LogStamp stamp;
  693. DWORD dwLen;
  694. DWORD dwSts;
  695. BOOL fSts;
  696. if (NULL == hLogMutex)
  697. {
  698. CSecurityDescriptor acl;
  699. acl.Initialize();
  700. acl.Allow(
  701. &acl.SID_World,
  702. SEMAPHORE_ALL_ACCESS);
  703. hLogMutex = CreateMutex(
  704. acl,
  705. FALSE,
  706. TEXT("Microsoft Smart Card Logging synchronization"));
  707. }
  708. dwSts = WaitForAnObject(hLogMutex, 1000); // One second max.
  709. if (ERROR_SUCCESS == dwSts)
  710. {
  711. fGotMutex = TRUE;
  712. dwLen = SetFilePointer(hLogFile, 0, NULL, FILE_END);
  713. ASSERT(-1 != dwLen);
  714. GetLocalTime(&stamp.stLogTime);
  715. stamp.dwProcId = GetCurrentProcessId();
  716. stamp.dwThreadId = GetCurrentThreadId();
  717. fSts = WriteFile(
  718. hLogFile,
  719. &stamp,
  720. sizeof(stamp),
  721. &dwLen,
  722. NULL);
  723. ASSERT(fSts);
  724. fSts = WriteFile(
  725. hLogFile,
  726. pvData,
  727. cbLength,
  728. &dwLen,
  729. NULL);
  730. ASSERT(fSts);
  731. ASSERT(dwLen == cbLength);
  732. }
  733. }
  734. }
  735. catch (...) {}
  736. if (fGotMutex)
  737. ReleaseMutex(hLogMutex);
  738. if (INVALID_HANDLE_VALUE != hLogFile)
  739. CloseHandle(hLogFile);
  740. }
  741. #endif