Source code of Windows XP (NT5)
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.

1376 lines
30 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. smcvxd.c
  5. Abstract:
  6. This is the Windows 9x specific driver file for the smart card library.
  7. The smart card library is actually more a library as a driver.
  8. It contains support functions for smart card driver/reader systems.
  9. This driver should be loaded through an entry in the registry.
  10. Environment:
  11. Windows 9x Static VxD
  12. Notes:
  13. Revision History:
  14. - Created June 1997 by Klaus Schutz
  15. --*/
  16. #define _ISO_TABLES_
  17. #define WIN40SERVICES
  18. #include "..\..\inc\smclib.h"
  19. #define REGISTRY_PATH_LEN 128
  20. static PUCHAR DevicePath = "System\\CurrentControlSet\\Services\\VxD\\Smclib\\Devices";
  21. static BOOLEAN DriverInitialized;
  22. #include "errmap.h"
  23. DWORD
  24. _stdcall
  25. SMCLIB_Init(void)
  26. /*++
  27. Routine Description:
  28. This function will be called by the Windows Kernel upon init of this driver
  29. Arguments:
  30. -
  31. Return Value:
  32. VXD_SUCCESS - This driver loaded successfully
  33. VXD_FAILURE - Load was not successful
  34. --*/
  35. {
  36. if (DriverInitialized == FALSE) {
  37. HANDLE hKey;
  38. ULONG i;
  39. DriverInitialized = TRUE;
  40. SmartcardDebug(
  41. DEBUG_DRIVER,
  42. ("%s(SMCLIB_Init): Enter. %s %s\n",
  43. DRIVER_NAME,
  44. __DATE__,
  45. __TIME__)
  46. );
  47. //
  48. // Delete old device names
  49. //
  50. if(_RegOpenKey(
  51. HKEY_LOCAL_MACHINE,
  52. DevicePath,
  53. &hKey
  54. ) != ERROR_SUCCESS) {
  55. SmartcardDebug(
  56. DEBUG_ERROR,
  57. ("%s(SMCLIB_Init): Unable to open registry key\n",
  58. DRIVER_NAME)
  59. );
  60. } else {
  61. _RegDeleteKey(
  62. hKey,
  63. ""
  64. );
  65. _RegCloseKey(hKey);
  66. }
  67. //
  68. // Create new device sub-key
  69. //
  70. _RegCreateKey(
  71. HKEY_LOCAL_MACHINE,
  72. DevicePath,
  73. &hKey
  74. );
  75. _RegCloseKey(hKey);
  76. }
  77. return(VXD_SUCCESS);
  78. }
  79. ULONG
  80. SMCLIB_MapNtStatusToWinError(
  81. NTSTATUS status
  82. )
  83. /*++
  84. Routine Description:
  85. Maps a NT status code to a Win32 error value
  86. Arguments:
  87. status - nt status code to map to a Win32 error value
  88. Return Value:
  89. Win32 error value
  90. --*/
  91. {
  92. ULONG i;
  93. for (i = 0;i < sizeof(CodePairs) / sizeof(CodePairs[0]); i += 2) {
  94. if (CodePairs[i] == status) {
  95. return CodePairs[i + 1];
  96. }
  97. }
  98. SmartcardDebug(
  99. DEBUG_ERROR,
  100. ("%s(MapNtStatusToWinError): NTSTATUS %lx unknown\n",
  101. DRIVER_NAME,
  102. status)
  103. );
  104. //
  105. // We were unable to map the error code
  106. //
  107. return ERROR_GEN_FAILURE;
  108. }
  109. void
  110. SMCLIB_Assert(
  111. PVOID FailedAssertion,
  112. PVOID FileName,
  113. ULONG LineNumber,
  114. PCHAR Message
  115. )
  116. /*++
  117. Routine Description:
  118. This is a simple assert function that gets called using the ASSERT
  119. macro. Windows 9x does not offer this functionality
  120. Arguments:
  121. FailedAssertion - The assertion we tested
  122. FileName - Yes, this is the name of the source file
  123. LineNumber - What might this be ?
  124. Message - An additional message supplied using ASSERTMSG
  125. Return Value:
  126. -
  127. --*/
  128. {
  129. #ifdef DEBUG
  130. Debug_Printf(
  131. "Assertion Failed: %s in %s(%ld)",
  132. FailedAssertion,
  133. FileName,
  134. LineNumber
  135. );
  136. if (Message)
  137. Debug_Printf(" %s",Message);
  138. Debug_Printf("\n");
  139. #endif
  140. }
  141. //#ifdef _vmm_add_ddb_to_do
  142. BOOL
  143. VXDINLINE
  144. _VMM_Add_DDB(
  145. struct VxD_Desc_Block *pDeviceDDB
  146. )
  147. /*++
  148. Routine Description:
  149. This routine is used to create a new device instance for a driver
  150. that supports multiple instances - like a serial based driver that
  151. supports more than one device -
  152. Arguments:
  153. pDeviceDDB - The DDB struct that is to be added to the system
  154. Return Value:
  155. TRUE - Yope, it worked
  156. FALSE - Out of business (May be the device name already exists)
  157. --*/
  158. {
  159. _asm mov edi, pDeviceDDB
  160. VxDCall(VMM_Add_DDB)
  161. _asm {
  162. mov eax, 1
  163. jnc exit
  164. mov eax, 0
  165. exit:
  166. }
  167. }
  168. BOOL
  169. VXDINLINE
  170. _VMM_Remove_DDB(
  171. struct VxD_Desc_Block *pDeviceDDB
  172. )
  173. /*++
  174. Routine Description:
  175. Removes a DDB (device) that was created using VMM_Add_DDB
  176. Arguments:
  177. The address of the DDB to remove
  178. Return Value:
  179. TRUE - OK, DDB removed otherwise FALSE
  180. --*/
  181. {
  182. _asm mov edi, pDeviceDDB
  183. VxDCall(VMM_Remove_DDB)
  184. _asm {
  185. mov eax, 1
  186. jnc exit
  187. mov eax, 0
  188. exit:
  189. }
  190. }
  191. //#endif
  192. PVMMDDB
  193. SMCLIB_VxD_CreateDevice(
  194. char *Device,
  195. void (*ControlProc)(void)
  196. )
  197. /*++
  198. Routine Description:
  199. Creates a new device. This routine allows a driver to create additional devices.
  200. Arguments:
  201. Device - Name of the device to be created. At most 8 characters
  202. ControlProc - Address of the VxD control procedure. (NOT the DeviceIoControl function!)
  203. Return Value:
  204. The newly created DDB if successful or NULL otherwise
  205. --*/
  206. {
  207. PVMMDDB pDDB;
  208. UCHAR DeviceName[9];
  209. ASSERT(Device != NULL);
  210. ASSERT(strlen(Device) <= 8);
  211. ASSERT(ControlProc != NULL);
  212. if (strlen(Device) > 8) {
  213. return NULL;
  214. }
  215. _Sprintf(DeviceName, "%-8s", Device);
  216. //
  217. // Allocate space for the VxD description block
  218. //
  219. pDDB = (PVMMDDB) _HeapAllocate(
  220. sizeof(struct VxD_Desc_Block),
  221. HEAPZEROINIT
  222. );
  223. if (pDDB)
  224. {
  225. pDDB->DDB_SDK_Version = DDK_VERSION;
  226. pDDB->DDB_Req_Device_Number = UNDEFINED_DEVICE_ID;
  227. pDDB->DDB_Dev_Major_Version = 1;
  228. pDDB->DDB_Dev_Minor_Version = 0;
  229. memcpy(pDDB->DDB_Name, DeviceName, 8);
  230. pDDB->DDB_Init_Order = UNDEFINED_INIT_ORDER;
  231. pDDB->DDB_Control_Proc = (ULONG) ControlProc;
  232. pDDB->DDB_Reference_Data = 0;
  233. pDDB->DDB_Prev = 'Prev';
  234. pDDB->DDB_Size = sizeof(struct VxD_Desc_Block);
  235. pDDB->DDB_Reserved1 = 'Rsv1';
  236. pDDB->DDB_Reserved2 = 'Rsv2';
  237. pDDB->DDB_Reserved3 = 'Rsv3';
  238. //
  239. // Now create the DDB
  240. //
  241. if (!_VMM_Add_DDB(pDDB)) {
  242. _HeapFree(pDDB, 0);
  243. return NULL;
  244. }
  245. }
  246. return pDDB;
  247. }
  248. BOOL
  249. SMCLIB_VxD_DeleteDevice(
  250. PVMMDDB pDDB
  251. )
  252. /*++
  253. Routine Description:
  254. Deleted a device. This function can be used to delete
  255. a device that was created using VxD_CreateDevice
  256. Arguments:
  257. pDDB - The DDB to be deleted
  258. Return Value:
  259. TRUE - device successfully deleted
  260. FALSE - device not deleted
  261. --*/
  262. {
  263. ASSERT(pDDB != NULL);
  264. if(pDDB == NULL || !_VMM_Remove_DDB(pDDB)) {
  265. return FALSE;
  266. }
  267. _HeapFree(pDDB, 0);
  268. return TRUE;
  269. }
  270. DWORD
  271. _stdcall
  272. VxD_PageLock(
  273. DWORD lpMem,
  274. DWORD cbSize
  275. )
  276. /*++
  277. Routine Description:
  278. This function lock the page
  279. Arguments:
  280. lpMem - pointer to the datablock which has to be locked
  281. cbSize - length of the datablock
  282. Return Value:
  283. - pointer to the locked datablock
  284. --*/
  285. {
  286. DWORD LinPageNum;
  287. DWORD LinOffset;
  288. DWORD nPages;
  289. DWORD dwRet;
  290. LinOffset = lpMem & 0xfff; // page offset of memory to map
  291. LinPageNum = lpMem >> 12; // generate page number
  292. // Calculate # of pages to map globally
  293. nPages = ((lpMem + cbSize) >> 12) - LinPageNum + 1;
  294. //
  295. // Return global mapping of passed in pointer, as this new pointer
  296. // is how the memory must be accessed out of context.
  297. //
  298. dwRet = _LinPageLock(LinPageNum, nPages, PAGEMAPGLOBAL | PAGEMARKDIRTY);
  299. ASSERT(dwRet != 0);
  300. SmartcardDebug(
  301. DEBUG_ERROR,
  302. ("%s!VxD_PageLock: LinPageNum = %lx, nPages = %lx, dwRet = %lx\n",
  303. DRIVER_NAME,
  304. LinPageNum,
  305. nPages,
  306. dwRet)
  307. );
  308. return (dwRet + LinOffset);
  309. }
  310. void
  311. _stdcall
  312. VxD_PageUnlock(
  313. DWORD lpMem,
  314. DWORD cbSize
  315. )
  316. /*++
  317. Routine Description:
  318. This function unlocks a datablock
  319. Arguments:
  320. lpMem - pointer to the datablock which has to be unlocked
  321. cbSize - length of the datablock
  322. Return Value:
  323. -
  324. --*/
  325. {
  326. DWORD LinPageNum;
  327. DWORD nPages;
  328. DWORD dwRet;
  329. LinPageNum = lpMem >> 12;
  330. nPages = ((lpMem + cbSize) >> 12) - LinPageNum + 1;
  331. SmartcardDebug(
  332. DEBUG_ERROR,
  333. ("%s!VxD_PageUnlock: LinPageNum = %lx, nPages = %lx\n",
  334. DRIVER_NAME,
  335. LinPageNum,
  336. nPages)
  337. );
  338. // Free globally mapped memory
  339. dwRet = _LinPageUnlock(LinPageNum, nPages, PAGEMAPGLOBAL);
  340. ASSERT(dwRet != 0);
  341. }
  342. void
  343. SMCLIB_SmartcardCompleteCardTracking(
  344. PSMARTCARD_EXTENSION SmartcardExtension
  345. )
  346. /*++
  347. Routine Description:
  348. This routine calls i/o completion for the pending
  349. card tracking operation. It also unlocks the previously
  350. locked memory that was used for the overlapped strucutre
  351. Arguments:
  352. SmartcardExtension
  353. Return Value:
  354. -
  355. --*/
  356. {
  357. if (SmartcardExtension->OsData->NotificationOverlappedData) {
  358. DWORD O_Internal = SmartcardExtension->OsData->NotificationOverlappedData->O_Internal;
  359. SmartcardDebug(
  360. DEBUG_ERROR,
  361. ("%s(SmartcardCompleteCardTracking): Completing %lx\n",
  362. DRIVER_NAME,
  363. SmartcardExtension->OsData->NotificationOverlappedData)
  364. );
  365. //
  366. // set number of bytes returned to 0
  367. //
  368. SmartcardExtension->OsData->NotificationOverlappedData->O_InternalHigh = 0;
  369. _asm mov ebx, O_Internal
  370. VxDCall(VWIN32_DIOCCompletionRoutine)
  371. _HeapFree(
  372. SmartcardExtension->OsData->NotificationOverlappedData,
  373. 0
  374. );
  375. SmartcardExtension->OsData->NotificationOverlappedData = NULL;
  376. }
  377. }
  378. void
  379. SMCLIB_SmartcardCompleteRequest(
  380. PSMARTCARD_EXTENSION SmartcardExtension
  381. )
  382. /*++
  383. Routine Description:
  384. This routine calls i/o completion for a pending
  385. io operation. It also unlocks the previously
  386. locked memory that was used for the overlapped structure
  387. Arguments:
  388. SmartcardExtension
  389. Return Value:
  390. -
  391. --*/
  392. {
  393. DWORD O_Internal = SmartcardExtension->OsData->CurrentOverlappedData->O_Internal;
  394. _asm mov ebx, O_Internal
  395. VxDCall(VWIN32_DIOCCompletionRoutine)
  396. VxD_PageUnlock(
  397. (DWORD) SmartcardExtension->OsData->CurrentOverlappedData,
  398. sizeof(OVERLAPPED)
  399. );
  400. VxD_PageUnlock(
  401. (DWORD) SmartcardExtension->IoRequest.RequestBuffer,
  402. SmartcardExtension->IoRequest.RequestBufferLength
  403. );
  404. VxD_PageUnlock(
  405. (DWORD) SmartcardExtension->IoRequest.ReplyBuffer,
  406. SmartcardExtension->IoRequest.ReplyBufferLength
  407. );
  408. SmartcardExtension->OsData->CurrentDiocParams = NULL;
  409. }
  410. NTSTATUS
  411. SMCLIB_SmartcardCreateLink(
  412. PUCHAR LinkName,
  413. PUCHAR DeviceName
  414. )
  415. /*++
  416. Routine Description:
  417. This routine creates a symbolic link name for the given device name.
  418. It means it creates a 'STRING-value' in the registry ..VxD\smclib\devices
  419. like SCReader[0-9] = DeviceName.
  420. The smart card resource manager uses these entries in order to figure out
  421. what smart card devices are currently running.
  422. We do this because we don't have the ability to create a dynamic device
  423. name like we can do in Windows NT.
  424. Arguments:
  425. LinkName - receives the created link name
  426. DeviceName - the device name for which the link should be created
  427. Return Value:
  428. NTSTATUS
  429. --*/
  430. {
  431. PUCHAR Value;
  432. ULONG i;
  433. HANDLE hKey;
  434. if (DriverInitialized == FALSE) {
  435. SMCLIB_Init();
  436. }
  437. SmartcardDebug(
  438. DEBUG_TRACE,
  439. ("%s(SmartcardCreateLink): Enter\n",
  440. DRIVER_NAME)
  441. );
  442. ASSERT(LinkName != NULL);
  443. ASSERT(DeviceName != NULL);
  444. ASSERT(strlen(DeviceName) <= 12);
  445. if (LinkName == NULL) {
  446. return STATUS_INVALID_PARAMETER_1;
  447. }
  448. if (DeviceName == NULL) {
  449. return STATUS_INVALID_PARAMETER_2;
  450. }
  451. //
  452. // Open the key where the device names are stored
  453. //
  454. if(_RegOpenKey(
  455. HKEY_LOCAL_MACHINE,
  456. DevicePath,
  457. &hKey
  458. ) != ERROR_SUCCESS) {
  459. return STATUS_UNSUCCESSFUL;
  460. }
  461. //
  462. // Allocate a buffer for enumeration of the registry
  463. //
  464. Value = (PUCHAR) _HeapAllocate(REGISTRY_PATH_LEN, 0);
  465. if (Value == NULL) {
  466. SmartcardDebug(
  467. DEBUG_ERROR,
  468. ("%s(SmartcardCreateLink): Allocation failed\n",
  469. DRIVER_NAME)
  470. );
  471. return STATUS_INSUFFICIENT_RESOURCES;
  472. }
  473. //
  474. // Now find a free device name
  475. //
  476. for (i = 0; i < MAXIMUM_SMARTCARD_READERS ; i++) {
  477. _Sprintf(
  478. Value,
  479. "SCReader%d",
  480. i
  481. );
  482. //
  483. // Check for existence of the key
  484. //
  485. if(_RegQueryValueEx(
  486. hKey,
  487. Value,
  488. NULL,
  489. NULL,
  490. NULL,
  491. NULL
  492. ) != ERROR_SUCCESS) {
  493. break;
  494. }
  495. }
  496. //
  497. // Free the buffer since we don't need it anymore
  498. //
  499. _HeapFree(Value, 0);
  500. if (i >= MAXIMUM_SMARTCARD_READERS) {
  501. SmartcardDebug(
  502. DEBUG_ERROR,
  503. ("%s(SmartcardCreateLink): Can't create link: Too many readers\n",
  504. DRIVER_NAME)
  505. );
  506. return STATUS_UNSUCCESSFUL;
  507. }
  508. //
  509. // Create the link name...
  510. //
  511. _Sprintf(
  512. LinkName,
  513. "SCReader%d",
  514. i
  515. );
  516. //
  517. // ...and store it in the registry
  518. //
  519. _RegSetValueEx(
  520. hKey,
  521. LinkName,
  522. NULL,
  523. REG_SZ,
  524. DeviceName,
  525. strlen(DeviceName)
  526. );
  527. _RegCloseKey(hKey);
  528. SmartcardDebug(
  529. DEBUG_DRIVER,
  530. ("%s(SmartcardCreateLink): Link %s created for Driver %s\n",
  531. DRIVER_NAME,
  532. LinkName,
  533. DeviceName)
  534. );
  535. SmartcardDebug(
  536. DEBUG_TRACE,
  537. ("%s(SmartcardCreateLink): Exit\n",
  538. DRIVER_NAME)
  539. );
  540. return STATUS_SUCCESS;
  541. }
  542. NTSTATUS
  543. SMCLIB_SmartcardDeleteLink(
  544. PUCHAR LinkName
  545. )
  546. /*++
  547. Routine Description:
  548. Deletes the link previously created with SmartcardCreateLink()
  549. This routine deletes the symbolic link name that is stored in the
  550. registry. A driver ususally calls this function upon unload.
  551. Arguments:
  552. LinkName - The link that is to be deleted
  553. Return Value:
  554. NTSTATUS
  555. --*/
  556. {
  557. HANDLE hKey;
  558. NTSTATUS status;
  559. SmartcardDebug(
  560. DEBUG_TRACE,
  561. ("%s(SmartcardDeleteLink): Enter\n",
  562. DRIVER_NAME)
  563. );
  564. ASSERT(LinkName);
  565. ASSERT(strlen(LinkName) <= 10);
  566. //
  567. // Open the key where the device names are stored
  568. //
  569. if(_RegOpenKey(
  570. HKEY_LOCAL_MACHINE,
  571. DevicePath,
  572. &hKey
  573. ) != ERROR_SUCCESS) {
  574. return STATUS_UNSUCCESSFUL;
  575. }
  576. if(_RegDeleteValue(
  577. hKey,
  578. LinkName
  579. ) == ERROR_SUCCESS) {
  580. SmartcardDebug(
  581. DEBUG_DRIVER,
  582. ("%s(SmartcardDeleteLink): Link %s deleted\n",
  583. DRIVER_NAME,
  584. LinkName)
  585. );
  586. status = STATUS_SUCCESS;
  587. } else {
  588. SmartcardDebug(
  589. DEBUG_ERROR,
  590. ("%s(SmartcardDeleteLink): Can't delete link %s\n",
  591. DRIVER_NAME,
  592. LinkName)
  593. );
  594. status = STATUS_UNSUCCESSFUL;
  595. }
  596. _RegCloseKey(hKey);
  597. SmartcardDebug(
  598. DEBUG_TRACE,
  599. ("%s(SmartcardDeleteLink): Exit",
  600. DRIVER_NAME)
  601. );
  602. return status;
  603. }
  604. NTSTATUS
  605. SMCLIB_SmartcardInitialize(
  606. PSMARTCARD_EXTENSION SmartcardExtension
  607. )
  608. /*++
  609. Routine Description:
  610. This function allocated the send and receive buffers for smart card
  611. data. It also sets the pointer to 2 ISO tables to make them accessible
  612. to the driver
  613. Arguments:
  614. SmartcardExtension
  615. Return Value:
  616. NTSTATUS
  617. --*/
  618. {
  619. NTSTATUS status = STATUS_SUCCESS;
  620. SmartcardDebug(
  621. DEBUG_TRACE,
  622. ("%s(SmartcardInitialize): Enter - Version %lx, %s %s\n",
  623. DRIVER_NAME,
  624. SMCLIB_VERSION,
  625. __DATE__,
  626. __TIME__)
  627. );
  628. ASSERT(SmartcardExtension != NULL);
  629. ASSERT(SmartcardExtension->OsData == NULL);
  630. if (SmartcardExtension == NULL) {
  631. return STATUS_INVALID_PARAMETER;
  632. }
  633. if (SmartcardExtension->Version < SMCLIB_VERSION_REQUIRED) {
  634. SmartcardDebug(
  635. DEBUG_ERROR,
  636. ("%s(SmartcardInitialize): Invalid Version in SMARTCARD_EXTENSION. Must be %lx\n",
  637. DRIVER_NAME,
  638. SMCLIB_VERSION)
  639. );
  640. return STATUS_UNSUCCESSFUL;
  641. }
  642. if (SmartcardExtension->SmartcardRequest.BufferSize < MIN_BUFFER_SIZE) {
  643. SmartcardDebug(
  644. DEBUG_ERROR,
  645. ("%s(SmartcardInitialize): WARNING: SmartcardRequest.BufferSize (%ld) < MIN_BUFFER_SIZE (%ld)\n",
  646. DRIVER_NAME,
  647. SmartcardExtension->SmartcardRequest.BufferSize,
  648. MIN_BUFFER_SIZE)
  649. );
  650. SmartcardExtension->SmartcardRequest.BufferSize = MIN_BUFFER_SIZE;
  651. }
  652. if (SmartcardExtension->SmartcardReply.BufferSize < MIN_BUFFER_SIZE) {
  653. SmartcardDebug(
  654. DEBUG_ERROR,
  655. ("%s(SmartcardInitialize): WARNING: SmartcardReply.BufferSize (%ld) < MIN_BUFFER_SIZE (%ld)\n",
  656. DRIVER_NAME,
  657. SmartcardExtension->SmartcardReply.BufferSize,
  658. MIN_BUFFER_SIZE)
  659. );
  660. SmartcardExtension->SmartcardReply.BufferSize = MIN_BUFFER_SIZE;
  661. }
  662. SmartcardExtension->SmartcardRequest.Buffer = _HeapAllocate(
  663. SmartcardExtension->SmartcardRequest.BufferSize,
  664. 0
  665. );
  666. SmartcardExtension->SmartcardReply.Buffer = _HeapAllocate(
  667. SmartcardExtension->SmartcardReply.BufferSize,
  668. 0
  669. );
  670. SmartcardExtension->OsData = _HeapAllocate(
  671. sizeof(OS_DEP_DATA),
  672. 0
  673. );
  674. //
  675. // Check if one of the above allocations failed
  676. //
  677. if (SmartcardExtension->SmartcardRequest.Buffer == NULL ||
  678. SmartcardExtension->SmartcardReply.Buffer == NULL ||
  679. SmartcardExtension->OsData == NULL) {
  680. status = STATUS_INSUFFICIENT_RESOURCES;
  681. if (SmartcardExtension->SmartcardRequest.Buffer) {
  682. _HeapFree(SmartcardExtension->SmartcardRequest.Buffer, 0);
  683. }
  684. if (SmartcardExtension->SmartcardReply.Buffer) {
  685. _HeapFree(SmartcardExtension->SmartcardReply.Buffer, 0);
  686. }
  687. if (SmartcardExtension->OsData == NULL) {
  688. _HeapFree(SmartcardExtension->OsData, 0);
  689. }
  690. }
  691. if (status != STATUS_SUCCESS) {
  692. return status;
  693. }
  694. memset(SmartcardExtension->OsData, 0, sizeof(OS_DEP_DATA));
  695. //
  696. // Create mutex that is used to synch access to the driver
  697. //
  698. SmartcardExtension->OsData->Mutex = _CreateMutex(0, 0);
  699. //
  700. // Make the 2 ISO tables accessible to the driver
  701. //
  702. SmartcardExtension->CardCapabilities.ClockRateConversion =
  703. &ClockRateConversion[0];
  704. SmartcardExtension->CardCapabilities.BitRateAdjustment =
  705. &BitRateAdjustment[0];
  706. SmartcardDebug(
  707. DEBUG_TRACE,
  708. ("%s(SmartcardInitialize): Exit\n",
  709. DRIVER_NAME)
  710. );
  711. return status;
  712. }
  713. VOID
  714. SMCLIB_SmartcardExit(
  715. PSMARTCARD_EXTENSION SmartcardExtension
  716. )
  717. /*++
  718. Routine Description:
  719. This routine frees the send and receive buffer.
  720. It is usually called when the driver unloads.
  721. Arguments:
  722. SmartcardExtension
  723. Return Value:
  724. NTSTATUS
  725. --*/
  726. {
  727. SmartcardDebug(
  728. DEBUG_TRACE,
  729. ("%s(SmartcardExit): Enter\n",
  730. DRIVER_NAME)
  731. );
  732. if (SmartcardExtension->SmartcardRequest.Buffer) {
  733. _HeapFree(SmartcardExtension->SmartcardRequest.Buffer, 0);
  734. }
  735. if (SmartcardExtension->SmartcardReply.Buffer) {
  736. _HeapFree(SmartcardExtension->SmartcardReply.Buffer, 0);
  737. }
  738. if (SmartcardExtension->OsData) {
  739. _HeapFree(SmartcardExtension->OsData, 0);
  740. }
  741. SmartcardDebug(
  742. DEBUG_TRACE,
  743. ("%s(SmartcardExit): Exit\n",
  744. DRIVER_NAME)
  745. );
  746. }
  747. VOID
  748. SMCLIB_SmartcardLogError(
  749. )
  750. /*++
  751. Routine Description:
  752. This routine allocates an error log entry, copies the supplied data
  753. to it, and requests that it be written to the error log file.
  754. Arguments:
  755. Return Value:
  756. --*/
  757. {
  758. SmartcardDebug(
  759. DEBUG_ERROR,
  760. ("%s(SmartcardLogError): Not yet implemented\n",
  761. DRIVER_NAME)
  762. );
  763. }
  764. NTSTATUS
  765. SMCLIB_SmartcardDeviceControl(
  766. PSMARTCARD_EXTENSION SmartcardExtension,
  767. DIOCPARAMETERS *lpDiocParams
  768. )
  769. /*++
  770. Routine Description:
  771. The routine is the general device control dispatch function for VxD drivers.
  772. Arguments:
  773. SmartcardExtension - The pointer to the smart card datae
  774. lpDiocParams - struct containing the caller parameter
  775. Return Value:
  776. NTSTATUS
  777. --*/
  778. {
  779. NTSTATUS status = STATUS_SUCCESS;
  780. ASSERT(SmartcardExtension != NULL);
  781. if (SmartcardExtension == NULL) {
  782. return STATUS_INVALID_PARAMETER_1;
  783. }
  784. ASSERT(lpDiocParams != NULL);
  785. if (lpDiocParams == NULL) {
  786. return STATUS_INVALID_PARAMETER_2;
  787. }
  788. ASSERT(lpDiocParams->lpoOverlapped != 0);
  789. if (lpDiocParams->lpoOverlapped == 0) {
  790. return STATUS_INVALID_PARAMETER;
  791. }
  792. // Check the version that the driver requires
  793. ASSERT(SmartcardExtension->Version >= SMCLIB_VERSION_REQUIRED);
  794. if (SmartcardExtension->Version < SMCLIB_VERSION_REQUIRED) {
  795. return STATUS_INVALID_PARAMETER;
  796. }
  797. // Synchronize access to the driver
  798. _EnterMutex(
  799. SmartcardExtension->OsData->Mutex,
  800. BLOCK_SVC_INTS | BLOCK_THREAD_IDLE
  801. );
  802. if (status == STATUS_SUCCESS) {
  803. SmartcardDebug(
  804. DEBUG_IOCTL,
  805. ("SMCLIB(SmartcardDeviceControl): Ioctl = %s, DIOCP = %lx\n",
  806. MapIoControlCodeToString(lpDiocParams->dwIoControlCode),
  807. lpDiocParams)
  808. );
  809. // Return if device is busy
  810. if (SmartcardExtension->OsData->CurrentDiocParams != NULL) {
  811. SmartcardDebug(
  812. DEBUG_IOCTL,
  813. ("%s(SmartcardDeviceControl): Device is busy\n",
  814. DRIVER_NAME)
  815. );
  816. status = STATUS_DEVICE_BUSY;
  817. }
  818. }
  819. if (status == STATUS_SUCCESS) {
  820. if (lpDiocParams->lpcbBytesReturned) {
  821. // Default number of bytes returned
  822. *(PULONG) lpDiocParams->lpcbBytesReturned = 0;
  823. }
  824. switch (lpDiocParams->dwIoControlCode) {
  825. //
  826. // We have to check for _IS_ABSENT and _IS_PRESENT first,
  827. // since these are (the only allowed) asynchronous requests
  828. //
  829. case IOCTL_SMARTCARD_IS_ABSENT:
  830. case IOCTL_SMARTCARD_IS_PRESENT:
  831. if (SmartcardExtension->ReaderFunction[RDF_CARD_TRACKING] == NULL) {
  832. status = STATUS_NOT_SUPPORTED;
  833. break;
  834. }
  835. // Now check if the driver is already processing notification
  836. if (SmartcardExtension->OsData->NotificationOverlappedData != NULL) {
  837. status = STATUS_DEVICE_BUSY;
  838. break;
  839. }
  840. //
  841. // Lock the overlapped structure that has to be notified
  842. // about the completion into memory
  843. //
  844. SmartcardExtension->OsData->NotificationOverlappedData =
  845. _HeapAllocate( sizeof(OVERLAPPED), HEAPZEROINIT );
  846. if (SmartcardExtension->OsData->NotificationOverlappedData == NULL) {
  847. return STATUS_INSUFFICIENT_RESOURCES;
  848. }
  849. memcpy(
  850. SmartcardExtension->OsData->NotificationOverlappedData,
  851. (PVOID) lpDiocParams->lpoOverlapped,
  852. sizeof(OVERLAPPED)
  853. );
  854. if (lpDiocParams->dwIoControlCode == IOCTL_SMARTCARD_IS_ABSENT) {
  855. //
  856. // If the card is already (or still) absent, we can return immediatly.
  857. // Otherwise we must statrt event tracking.
  858. //
  859. if (SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT) {
  860. status = SmartcardExtension->ReaderFunction[RDF_CARD_TRACKING](
  861. SmartcardExtension
  862. );
  863. }
  864. } else {
  865. //
  866. // If the card is already (or still) present, we can return immediatly.
  867. // Otherwise we must statrt event tracking.
  868. //
  869. if (SmartcardExtension->ReaderCapabilities.CurrentState <= SCARD_ABSENT) {
  870. status = SmartcardExtension->ReaderFunction[RDF_CARD_TRACKING](
  871. SmartcardExtension
  872. );
  873. }
  874. }
  875. if (status != STATUS_PENDING) {
  876. //
  877. // Unlock the overlapped structure again since the driver
  878. // doesn't need it anymore
  879. //
  880. _HeapFree(
  881. SmartcardExtension->OsData->NotificationOverlappedData,
  882. 0
  883. );
  884. SmartcardExtension->OsData->NotificationOverlappedData = NULL;
  885. }
  886. break;
  887. default:
  888. // Check if buffers are properly allocated
  889. ASSERT(SmartcardExtension->SmartcardRequest.Buffer);
  890. ASSERT(SmartcardExtension->SmartcardReply.Buffer);
  891. SmartcardExtension->OsData->CurrentDiocParams = lpDiocParams;
  892. // Get major io control code
  893. SmartcardExtension->MajorIoControlCode =
  894. lpDiocParams->dwIoControlCode;
  895. if (lpDiocParams->lpvInBuffer) {
  896. //
  897. // Transfer minor io control code, even if it doesn't make sense for
  898. // this particular major code
  899. //
  900. SmartcardExtension->MinorIoControlCode =
  901. *(PULONG) (lpDiocParams->lpvInBuffer);
  902. // Lock memory and save pointer to and length of request buffer
  903. SmartcardExtension->IoRequest.RequestBuffer = (PUCHAR) VxD_PageLock(
  904. lpDiocParams->lpvInBuffer,
  905. lpDiocParams->cbInBuffer
  906. );
  907. SmartcardExtension->IoRequest.RequestBufferLength =
  908. lpDiocParams->cbInBuffer;
  909. } else {
  910. SmartcardExtension->IoRequest.RequestBuffer = NULL;
  911. SmartcardExtension->IoRequest.RequestBufferLength = 0;
  912. }
  913. if (lpDiocParams->lpvOutBuffer) {
  914. // Lock memory an save pointer to and length of reply buffer
  915. SmartcardExtension->IoRequest.ReplyBuffer = (PUCHAR) VxD_PageLock(
  916. lpDiocParams->lpvOutBuffer,
  917. lpDiocParams->cbOutBuffer
  918. );
  919. SmartcardExtension->IoRequest.ReplyBufferLength =
  920. lpDiocParams->cbOutBuffer;
  921. } else {
  922. SmartcardExtension->IoRequest.ReplyBuffer = NULL;
  923. SmartcardExtension->IoRequest.ReplyBufferLength = 0;
  924. }
  925. // Lock overlapped struct into memory
  926. SmartcardExtension->OsData->CurrentOverlappedData =
  927. (OVERLAPPED *) VxD_PageLock(
  928. lpDiocParams->lpoOverlapped,
  929. sizeof(OVERLAPPED)
  930. );
  931. if (SmartcardExtension->OsData->CurrentOverlappedData) {
  932. //
  933. // Pointer to variable that receives the actual number
  934. // of bytes returned. Since we don't know yet if the
  935. // driver will return STATUS_PENDING, we use the
  936. // overlapped data to store the number of bytes returned
  937. //
  938. SmartcardExtension->IoRequest.Information =
  939. &SmartcardExtension->OsData->CurrentOverlappedData->O_InternalHigh;
  940. // Set the default number of bytes returned to 0
  941. *SmartcardExtension->IoRequest.Information = 0;
  942. // Process the ioctl-request
  943. status = SmartcardDeviceIoControl(SmartcardExtension);
  944. if (status != STATUS_PENDING) {
  945. if(lpDiocParams->lpcbBytesReturned) {
  946. *(PULONG) (lpDiocParams->lpcbBytesReturned) =
  947. *(SmartcardExtension->IoRequest.Information);
  948. }
  949. //
  950. // The driver satisfied the call immediatly. So we don't use the overlapped
  951. // data to return information to the caller. We can transfer the 'number
  952. // of bytes returned' directly
  953. //
  954. if (SmartcardExtension->OsData->CurrentOverlappedData) {
  955. // Unlock all memory
  956. VxD_PageUnlock(
  957. (DWORD) SmartcardExtension->OsData->CurrentOverlappedData,
  958. sizeof(OVERLAPPED)
  959. );
  960. }
  961. if (SmartcardExtension->IoRequest.RequestBuffer) {
  962. VxD_PageUnlock(
  963. (DWORD) SmartcardExtension->IoRequest.RequestBuffer,
  964. SmartcardExtension->IoRequest.RequestBufferLength
  965. );
  966. }
  967. if (SmartcardExtension->IoRequest.ReplyBuffer) {
  968. VxD_PageUnlock(
  969. (DWORD) SmartcardExtension->IoRequest.ReplyBuffer,
  970. SmartcardExtension->IoRequest.ReplyBufferLength
  971. );
  972. }
  973. //
  974. // If the devcie is not busy, we can set the
  975. // current parameters back to NULL
  976. //
  977. SmartcardExtension->OsData->CurrentDiocParams = NULL;
  978. }
  979. } else {
  980. status = STATUS_INSUFFICIENT_RESOURCES;
  981. }
  982. break;
  983. }
  984. }
  985. SmartcardDebug(
  986. DEBUG_IOCTL,
  987. ("SMCLIB(SmartcardDeviceControl): Exit\n")
  988. );
  989. _LeaveMutex(SmartcardExtension->OsData->Mutex);
  990. return status;
  991. }
  992. DWORD
  993. _stdcall
  994. SMCLIB_DeviceIoControl(
  995. DWORD dwService,
  996. DWORD dwDDB,
  997. DWORD hDevice,
  998. DIOCPARAMETERS *lpDIOCParms
  999. )
  1000. {
  1001. return 0;
  1002. }
  1003. SMCLIB_Get_Version()
  1004. {
  1005. return SMCLIB_VERSION;
  1006. }