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.

4877 lines
136 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. scredir
  5. Abstract:
  6. This module redirects the SCard* API calls
  7. Author:
  8. reidk 7/27/2000
  9. --*/
  10. #include <nt.h>
  11. #include <ntrtl.h>
  12. #include <nturtl.h>
  13. #include <windows.h>
  14. #include <stdio.h>
  15. #include <winscard.h>
  16. #include "scredir.h"
  17. #include "scioctl.h"
  18. #include "calmsgs.h"
  19. #include "calaislb.h"
  20. #include "rdpdr.h"
  21. //
  22. // from secpkg.h
  23. //
  24. typedef NTSTATUS (NTAPI LSA_IMPERSONATE_CLIENT) (VOID);
  25. typedef LSA_IMPERSONATE_CLIENT * PLSA_IMPERSONATE_CLIENT;
  26. #define wszWinSCardRegKeyRedirector (L"Software\\Microsoft\\SmartCard\\Redirector")
  27. #define wszWinSCardRegVersion (L"Version")
  28. #define wszWinSCardRegName (L"Name")
  29. #define wszWinSCardRegNameValue (L"scredir.dll")
  30. // This is the version number of the interface.
  31. // The high word is the major version which must match exactly.
  32. // The low word is the minor version. The dll must implement
  33. // a minor version that is greater than or equal to the system
  34. // minor version. This means that if we add a new funtion to the API,
  35. // we increase the minor version and a remoting DLL can still be
  36. // backward compatible. This is just like RPC version numbers
  37. #define REDIRECTION_VERSION 0x00010000
  38. #define ERROR_RETURN(x) lReturn = x; goto ErrorReturn;
  39. #define MAX_SCARDCONTEXT_SIZE 32
  40. #define MAX_SCARDHANDLE_SIZE 32
  41. typedef struct _REDIR_LOCAL_SCARDCONTEXT
  42. {
  43. REDIR_SCARDCONTEXT Context;
  44. HANDLE hHeap;
  45. } REDIR_LOCAL_SCARDCONTEXT;
  46. typedef struct _REDIR_LOCAL_SCARDHANDLE
  47. {
  48. REDIR_LOCAL_SCARDCONTEXT *pRedirContext;
  49. REDIR_SCARDHANDLE Handle;
  50. } REDIR_LOCAL_SCARDHANDLE;
  51. //
  52. // This structure is used to maintain a list of buffers that are
  53. // used for the _SendSCardIOCTL calls
  54. //
  55. #define INITIAL_BUFFER_SIZE 512
  56. typedef struct _BUFFER_LIST_STRUCT
  57. {
  58. void *pNext;
  59. BOOL fInUse;
  60. BYTE *pbBytes;
  61. unsigned long cbBytes;
  62. unsigned long cbBytesUsed;
  63. } BUFFER_LIST_STRUCT;
  64. HMODULE g_hModule = NULL;
  65. CRITICAL_SECTION g_CreateCS;
  66. CRITICAL_SECTION g_SetStartedEventStateCS;
  67. CRITICAL_SECTION g_StartedEventCreateCS;
  68. CRITICAL_SECTION g_ProcessDetachEventCreateCS;
  69. CRITICAL_SECTION g_BufferListCS;
  70. HANDLE g_hRdpdrDeviceHandle = INVALID_HANDLE_VALUE;
  71. HANDLE g_hRedirStartedEvent = NULL;
  72. HANDLE g_hProcessDetachEvent = NULL;
  73. LONG g_lProcessDetachEventClients = 0;
  74. BOOL g_fInTheProcessOfSettingStartedEvent = FALSE;
  75. HANDLE g_hRegisteredWaitHandle = NULL;
  76. HANDLE g_hWaitEvent = NULL;
  77. IO_STATUS_BLOCK g_StartedStatusBlock;
  78. HANDLE g_hUnifiedStartedEvent = NULL;
  79. BOOL g_fInProcessDetach = FALSE;
  80. BUFFER_LIST_STRUCT *g_pBufferList = NULL;
  81. #define IOCTL_RETURN_BUFFER_SIZE 256
  82. BYTE g_rgbIOCTLReturnBuffer[IOCTL_RETURN_BUFFER_SIZE];
  83. unsigned long g_cbIOCTLReturnBuffer;
  84. #define _TRY_(y) __try \
  85. { \
  86. y; \
  87. } \
  88. __except(EXCEPTION_EXECUTE_HANDLER) \
  89. { \
  90. ERROR_RETURN(GetExceptionCode()) \
  91. }
  92. #define _TRY_2(y) __try \
  93. { \
  94. y; \
  95. } \
  96. __except(EXCEPTION_EXECUTE_HANDLER){} // do nothing
  97. //
  98. // Forward declarations
  99. //
  100. NTSTATUS
  101. _SendSCardIOCTLWithWaitForCallback(
  102. ULONG IoControlCode,
  103. PVOID InputBuffer,
  104. ULONG InputBufferLength,
  105. WAITORTIMERCALLBACK Callback);
  106. void
  107. SafeMesHandleFree(
  108. handle_t *ph);
  109. LONG
  110. I_DecodeLongReturn(
  111. BYTE *pb,
  112. unsigned long cb);
  113. BOOL
  114. _SetStartedEventToCorrectState(void);
  115. //---------------------------------------------------------------------------------------
  116. //
  117. // MIDL allocation routines
  118. //
  119. //---------------------------------------------------------------------------------------
  120. void __RPC_FAR *__RPC_USER MIDL_user_allocate(size_t size)
  121. {
  122. void *pv;
  123. if (NULL == (pv = (void *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size)))
  124. {
  125. SetLastError(ERROR_OUTOFMEMORY);
  126. }
  127. return (pv);
  128. }
  129. void __RPC_USER MIDL_user_free(void __RPC_FAR *pv)
  130. {
  131. if (pv != NULL)
  132. {
  133. HeapFree(GetProcessHeap(), 0, pv);
  134. }
  135. }
  136. void * SCRedirAlloc(REDIR_LOCAL_SCARDCONTEXT *pRedirContext, size_t size)
  137. {
  138. return (HeapAlloc(
  139. (pRedirContext != NULL) ? pRedirContext->hHeap : GetProcessHeap(),
  140. HEAP_ZERO_MEMORY,
  141. size));
  142. }
  143. LONG
  144. _MakeSCardError(NTSTATUS Status)
  145. {
  146. switch (Status)
  147. {
  148. case STATUS_DEVICE_NOT_CONNECTED:
  149. return (SCARD_E_NO_SERVICE);
  150. break;
  151. case STATUS_CANCELLED:
  152. return (SCARD_E_SYSTEM_CANCELLED);
  153. break;
  154. default:
  155. return (SCARD_E_NO_SERVICE);
  156. }
  157. }
  158. //---------------------------------------------------------------------------------------
  159. //
  160. // DllRegisterServer
  161. //
  162. //---------------------------------------------------------------------------------------
  163. STDAPI
  164. DllRegisterServer(void)
  165. {
  166. HRESULT hr = ERROR_SUCCESS;
  167. HKEY hKey;
  168. DWORD dwDisposition;
  169. DWORD dwVersion = REDIRECTION_VERSION;
  170. hr = RegCreateKeyExW(
  171. HKEY_LOCAL_MACHINE,
  172. wszWinSCardRegKeyRedirector,
  173. 0,
  174. NULL,
  175. REG_OPTION_NON_VOLATILE,
  176. KEY_ALL_ACCESS,
  177. NULL,
  178. &hKey,
  179. &dwDisposition);
  180. if (hr == ERROR_SUCCESS)
  181. {
  182. hr = RegSetValueExW(
  183. hKey,
  184. wszWinSCardRegName,
  185. 0,
  186. REG_SZ,
  187. (BYTE *) wszWinSCardRegNameValue,
  188. (wcslen(wszWinSCardRegNameValue) + 1) * sizeof(WCHAR));
  189. if (hr == ERROR_SUCCESS)
  190. {
  191. hr = RegSetValueExW(
  192. hKey,
  193. wszWinSCardRegVersion,
  194. 0,
  195. REG_DWORD,
  196. (BYTE *) &dwVersion,
  197. sizeof(DWORD));
  198. }
  199. RegCloseKey(hKey);
  200. }
  201. return (hr);
  202. }
  203. //---------------------------------------------------------------------------------------
  204. //
  205. // DllUnregisterServer
  206. //
  207. //---------------------------------------------------------------------------------------
  208. STDAPI
  209. DllUnregisterServer(void)
  210. {
  211. HRESULT hr = ERROR_SUCCESS;
  212. HKEY hKey;
  213. DWORD dwDisposition;
  214. DWORD dwVersion = REDIRECTION_VERSION;
  215. hr = RegCreateKeyExW(
  216. HKEY_LOCAL_MACHINE,
  217. wszWinSCardRegKeyRedirector,
  218. 0,
  219. NULL,
  220. REG_OPTION_NON_VOLATILE,
  221. KEY_ALL_ACCESS,
  222. NULL,
  223. &hKey,
  224. &dwDisposition);
  225. if (hr == ERROR_SUCCESS)
  226. {
  227. RegDeleteValueW(hKey, wszWinSCardRegName);
  228. RegDeleteValueW(hKey, wszWinSCardRegVersion);
  229. RegCloseKey(hKey);
  230. }
  231. return (hr);
  232. }
  233. //---------------------------------------------------------------------------------------
  234. //
  235. // DllMain
  236. //
  237. //---------------------------------------------------------------------------------------
  238. BOOL WINAPI
  239. DllMain(HMODULE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
  240. {
  241. DWORD dwTryCount = 0;
  242. DWORD dwCritSecsInitialized = 0;
  243. BUFFER_LIST_STRUCT *pTemp = NULL;
  244. switch (fdwReason)
  245. {
  246. case DLL_PROCESS_ATTACH:
  247. g_hModule = hInstDLL;
  248. __try
  249. {
  250. InitializeCriticalSection(&g_CreateCS);
  251. dwCritSecsInitialized++;
  252. InitializeCriticalSection(&g_SetStartedEventStateCS);
  253. dwCritSecsInitialized++;
  254. InitializeCriticalSection(&g_StartedEventCreateCS);
  255. dwCritSecsInitialized++;
  256. InitializeCriticalSection(&g_ProcessDetachEventCreateCS);
  257. dwCritSecsInitialized++;
  258. InitializeCriticalSection(&g_BufferListCS);
  259. dwCritSecsInitialized++;
  260. }
  261. __except(EXCEPTION_EXECUTE_HANDLER)
  262. {
  263. if (dwCritSecsInitialized >= 1)
  264. {
  265. DeleteCriticalSection(&g_CreateCS);
  266. }
  267. if (dwCritSecsInitialized >= 2)
  268. {
  269. DeleteCriticalSection(&g_SetStartedEventStateCS);
  270. }
  271. if (dwCritSecsInitialized >= 3)
  272. {
  273. DeleteCriticalSection(&g_StartedEventCreateCS);
  274. }
  275. if (dwCritSecsInitialized >= 4)
  276. {
  277. DeleteCriticalSection(&g_ProcessDetachEventCreateCS);
  278. }
  279. if (dwCritSecsInitialized >= 5)
  280. {
  281. DeleteCriticalSection(&g_BufferListCS);
  282. }
  283. SetLastError(GetExceptionCode());
  284. return (FALSE);
  285. }
  286. break;
  287. case DLL_PROCESS_DETACH:
  288. g_fInProcessDetach = TRUE;
  289. //
  290. // The third parameter, lpvReserved, passed to DllMain
  291. // is NULL for FreeLibrary and non-NULL for ProcessExit.
  292. // Only clean up for FreeLibrary
  293. //
  294. //if (lpvReserved == NULL)
  295. {
  296. //
  297. // If we are currently waiting for the started event then kill
  298. // that wait
  299. //
  300. EnterCriticalSection(&g_SetStartedEventStateCS);
  301. if (g_hRegisteredWaitHandle != NULL)
  302. {
  303. UnregisterWaitEx(g_hRegisteredWaitHandle, INVALID_HANDLE_VALUE);
  304. g_hRegisteredWaitHandle = NULL;
  305. }
  306. if (g_hWaitEvent != NULL)
  307. {
  308. CloseHandle(g_hWaitEvent);
  309. g_hWaitEvent = NULL;
  310. }
  311. LeaveCriticalSection(&g_SetStartedEventStateCS);
  312. //
  313. // If there are clients waiting on IOCTLs to complete, then let them go.
  314. //
  315. if (g_hProcessDetachEvent != NULL)
  316. {
  317. SetEvent(g_hProcessDetachEvent);
  318. }
  319. if (g_hProcessDetachEvent != NULL)
  320. {
  321. //
  322. // wait for all clients until they are done with the event
  323. //
  324. while ((g_lProcessDetachEventClients > 0) && (dwTryCount < 50))
  325. {
  326. Sleep(10);
  327. dwTryCount++;
  328. }
  329. if (dwTryCount < 50)
  330. {
  331. CloseHandle(g_hProcessDetachEvent);
  332. }
  333. }
  334. if (g_hRdpdrDeviceHandle != INVALID_HANDLE_VALUE)
  335. {
  336. CloseHandle(g_hRdpdrDeviceHandle);
  337. }
  338. if (g_hRedirStartedEvent != NULL)
  339. {
  340. CloseHandle(g_hRedirStartedEvent);
  341. }
  342. //
  343. // Free all the buffers used for the IOCTL calls
  344. //
  345. pTemp = g_pBufferList;
  346. while (pTemp != NULL)
  347. {
  348. g_pBufferList = (BUFFER_LIST_STRUCT *) pTemp->pNext;
  349. MIDL_user_free(pTemp->pbBytes);
  350. MIDL_user_free(pTemp);
  351. pTemp = g_pBufferList;
  352. }
  353. DeleteCriticalSection(&g_CreateCS);
  354. DeleteCriticalSection(&g_SetStartedEventStateCS);
  355. DeleteCriticalSection(&g_StartedEventCreateCS);
  356. DeleteCriticalSection(&g_ProcessDetachEventCreateCS);
  357. DeleteCriticalSection(&g_BufferListCS);
  358. }
  359. break;
  360. }
  361. return (TRUE);
  362. }
  363. //---------------------------------------------------------------------------------------
  364. //
  365. // GetBuffer
  366. //
  367. //---------------------------------------------------------------------------------------
  368. BUFFER_LIST_STRUCT *
  369. GetBuffer(void)
  370. {
  371. BUFFER_LIST_STRUCT *pTemp = NULL;
  372. BUFFER_LIST_STRUCT *p1 = NULL;
  373. BUFFER_LIST_STRUCT *p2 = NULL;
  374. EnterCriticalSection(&g_BufferListCS);
  375. //
  376. // See if there are any buffers allocated yet
  377. //
  378. if (g_pBufferList == NULL)
  379. {
  380. g_pBufferList = (BUFFER_LIST_STRUCT *)
  381. MIDL_user_allocate(sizeof(BUFFER_LIST_STRUCT));
  382. if (g_pBufferList == NULL)
  383. {
  384. goto Return;
  385. }
  386. g_pBufferList->pbBytes = (BYTE *) MIDL_user_allocate(INITIAL_BUFFER_SIZE);
  387. if (g_pBufferList->pbBytes == NULL)
  388. {
  389. MIDL_user_free(g_pBufferList);
  390. goto Return;
  391. }
  392. g_pBufferList->pNext = NULL;
  393. g_pBufferList->fInUse = TRUE;
  394. g_pBufferList->cbBytes = INITIAL_BUFFER_SIZE;
  395. pTemp = g_pBufferList;
  396. goto Return;
  397. }
  398. //
  399. // Walk the existing list to see if a free buffer can be found
  400. //
  401. pTemp = g_pBufferList;
  402. while ((pTemp != NULL) && (pTemp->fInUse))
  403. {
  404. pTemp = (BUFFER_LIST_STRUCT *)pTemp->pNext;
  405. }
  406. if (pTemp != NULL)
  407. {
  408. pTemp->fInUse = TRUE;
  409. //
  410. // Get rid of any buffers that exist which aren't being used
  411. //
  412. p1 = pTemp;
  413. p2 = (BUFFER_LIST_STRUCT *) pTemp->pNext;
  414. while (p2 != NULL)
  415. {
  416. if (!(p2->fInUse))
  417. {
  418. p1->pNext = p2->pNext;
  419. MIDL_user_free(p2->pbBytes);
  420. MIDL_user_free(p2);
  421. p2 = (BUFFER_LIST_STRUCT *) p1->pNext;
  422. }
  423. else
  424. {
  425. p1 = (BUFFER_LIST_STRUCT *) p1->pNext;
  426. p2 = (BUFFER_LIST_STRUCT *) p2->pNext;
  427. }
  428. }
  429. goto Return;
  430. }
  431. //
  432. // No free buffers, so create a new one
  433. //
  434. pTemp = (BUFFER_LIST_STRUCT *)
  435. MIDL_user_allocate(sizeof(BUFFER_LIST_STRUCT));
  436. if (pTemp == NULL)
  437. {
  438. goto Return;
  439. }
  440. pTemp->pbBytes = (BYTE *) MIDL_user_allocate(INITIAL_BUFFER_SIZE);
  441. if (pTemp->pbBytes == NULL)
  442. {
  443. MIDL_user_free(pTemp);
  444. goto Return;
  445. }
  446. pTemp->fInUse = TRUE;
  447. pTemp->cbBytes = INITIAL_BUFFER_SIZE;
  448. pTemp->pNext = g_pBufferList;
  449. g_pBufferList = pTemp;
  450. Return:
  451. LeaveCriticalSection(&g_BufferListCS);
  452. return(pTemp);
  453. }
  454. //---------------------------------------------------------------------------------------
  455. //
  456. // FreeBuffer
  457. //
  458. //---------------------------------------------------------------------------------------
  459. void
  460. FreeBuffer(BUFFER_LIST_STRUCT *pBuffer)
  461. {
  462. if (pBuffer != NULL)
  463. {
  464. pBuffer->fInUse = FALSE;
  465. }
  466. }
  467. //---------------------------------------------------------------------------------------
  468. //
  469. // GrowBuffer
  470. //
  471. //---------------------------------------------------------------------------------------
  472. BOOL
  473. GrowBuffer(BUFFER_LIST_STRUCT *pBuffer)
  474. {
  475. BYTE *pTemp;
  476. BOOL fRet = TRUE;
  477. pTemp = pBuffer->pbBytes;
  478. pBuffer->pbBytes = (BYTE *) MIDL_user_allocate(pBuffer->cbBytes * 2);
  479. if (pBuffer->pbBytes == NULL)
  480. {
  481. pBuffer->pbBytes = pTemp;
  482. fRet = FALSE;
  483. }
  484. else
  485. {
  486. MIDL_user_free(pTemp);
  487. pBuffer->cbBytes = pBuffer->cbBytes * 2;
  488. }
  489. return (fRet);
  490. }
  491. //---------------------------------------------------------------------------------------
  492. //
  493. // _GetProcessDetachEventHandle
  494. //
  495. //---------------------------------------------------------------------------------------
  496. HANDLE
  497. _GetProcessDetachEventHandle(void)
  498. {
  499. EnterCriticalSection(&g_ProcessDetachEventCreateCS);
  500. if (NULL == g_hProcessDetachEvent)
  501. {
  502. try
  503. {
  504. g_hProcessDetachEvent =
  505. CreateEvent(
  506. NULL, // pointer to security attributes
  507. TRUE, // flag for manual-reset event
  508. FALSE, // flag for initial state
  509. NULL); // event-object name
  510. }
  511. catch (...)
  512. {
  513. goto Return;
  514. }
  515. }
  516. LeaveCriticalSection(&g_ProcessDetachEventCreateCS);
  517. Return:
  518. if (g_hProcessDetachEvent != NULL)
  519. {
  520. InterlockedIncrement(&g_lProcessDetachEventClients);
  521. }
  522. return (g_hProcessDetachEvent);
  523. }
  524. void
  525. _ReleaseProcessDetachEventHandle(void)
  526. {
  527. InterlockedDecrement(&g_lProcessDetachEventClients);
  528. }
  529. //---------------------------------------------------------------------------------------
  530. //
  531. // All the code below is to solve the problem of weather or not the redirect Smart
  532. // Card Subsystem is available. It is available if we are connected to the client,
  533. // and if the clients Smart Card Subsystem is running
  534. //
  535. //---------------------------------------------------------------------------------------
  536. HANDLE
  537. _GetStartedEventHandle(void)
  538. {
  539. EnterCriticalSection(&g_StartedEventCreateCS);
  540. if (NULL == g_hRedirStartedEvent)
  541. {
  542. g_hRedirStartedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  543. }
  544. LeaveCriticalSection(&g_StartedEventCreateCS);
  545. return (g_hRedirStartedEvent);
  546. }
  547. VOID CALLBACK
  548. AccessStartedEventIOCTLCallback(
  549. PVOID lpParameter,
  550. BOOLEAN TimerOrWaitFired)
  551. {
  552. HANDLE h = NULL;
  553. BOOL fRetry = FALSE;
  554. //OutputDebugString("SCREDIR: AccessStartedEventIOCTLCallback\n");
  555. //
  556. // Close the handle that was used to fire this callback
  557. //
  558. EnterCriticalSection(&g_SetStartedEventStateCS);
  559. h = g_hRegisteredWaitHandle;
  560. g_hRegisteredWaitHandle = NULL;
  561. LeaveCriticalSection(&g_SetStartedEventStateCS);
  562. //OutputDebugString("SCREDIR: AccessStartedEventIOCTLCallback - through the CS\n");
  563. if (h != NULL)
  564. {
  565. UnregisterWait(h);
  566. }
  567. //
  568. // Make sure the AccessStartedEvent IOCTL completed and wasn't timed out
  569. //
  570. if (!TimerOrWaitFired)
  571. {
  572. //
  573. // Make sure the AccessStartedEvent IOCTL completed successfully
  574. //
  575. if (g_StartedStatusBlock.Status == STATUS_SUCCESS)
  576. {
  577. //OutputDebugString("SCREDIR: AccessStartedEventIOCTLCallback - g_StartedStatusBlock.Status == STATUS_SUCCESS\n");
  578. g_cbIOCTLReturnBuffer =
  579. (unsigned long) g_StartedStatusBlock.Information;
  580. //
  581. // Look at the value returned from the SCARD_IOCTL_ACCESSSTARTEDEVENT
  582. // call to see if we should set the local started event
  583. //
  584. if (I_DecodeLongReturn(
  585. g_rgbIOCTLReturnBuffer,
  586. g_cbIOCTLReturnBuffer) == SCARD_S_SUCCESS)
  587. {
  588. //OutputDebugString("SCREDIR: AccessStartedEventIOCTLCallback - SetEvent\n");
  589. SetEvent(g_hRedirStartedEvent);
  590. }
  591. }
  592. else if (g_StartedStatusBlock.Status == STATUS_CANCELLED)
  593. {
  594. //OutputDebugString("SCREDIR: AccessStartedEventIOCTLCallback - Got STATUS_CANCELLED\n");
  595. //
  596. // Retry
  597. //
  598. fRetry = TRUE;
  599. }
  600. else
  601. {
  602. char a[256];
  603. sprintf(a, "SCREDIR: AccessStartedEventIOCTLCallback - Status = %lx\n", g_StartedStatusBlock.Status);
  604. //OutputDebugString(a);
  605. }
  606. }
  607. else
  608. {
  609. //OutputDebugString("SCREDIR: AccessStartedEventIOCTLCallback - Timed out\n");
  610. }
  611. //
  612. // Unset the g_fInTheProcessOfSettingStartedEvent boolean
  613. //
  614. EnterCriticalSection(&g_SetStartedEventStateCS);
  615. g_fInTheProcessOfSettingStartedEvent = FALSE;
  616. LeaveCriticalSection(&g_SetStartedEventStateCS);
  617. if (fRetry)
  618. {
  619. _SetStartedEventToCorrectState();
  620. }
  621. }
  622. VOID CALLBACK
  623. SCardOnLineIOCTLCallback(
  624. PVOID lpParameter,
  625. BOOLEAN TimerOrWaitFired)
  626. {
  627. BOOL fOperationDone = FALSE;
  628. NTSTATUS Status = STATUS_SUCCESS;
  629. BYTE rgb[4];
  630. HANDLE h = NULL;
  631. //
  632. // Close the handle that was used to fire this callback
  633. //
  634. EnterCriticalSection(&g_SetStartedEventStateCS);
  635. h = g_hRegisteredWaitHandle;
  636. g_hRegisteredWaitHandle = NULL;
  637. LeaveCriticalSection(&g_SetStartedEventStateCS);
  638. if (h != NULL)
  639. {
  640. UnregisterWait(h);
  641. }
  642. //
  643. // Make sure the online IOCTL completed and wasn't timed out
  644. //
  645. if (TimerOrWaitFired)
  646. {
  647. //
  648. // Timed out, so just cancel operation
  649. //
  650. fOperationDone = TRUE;
  651. }
  652. else
  653. {
  654. //
  655. // Make sure the SCardOnLine IOCTL completed successfully, then try to
  656. // send the IOCTL which will wait on the clients started event
  657. //
  658. if (g_StartedStatusBlock.Status == STATUS_SUCCESS)
  659. {
  660. Status = _SendSCardIOCTLWithWaitForCallback(
  661. SCARD_IOCTL_ACCESSSTARTEDEVENT,
  662. rgb,
  663. 4,
  664. AccessStartedEventIOCTLCallback);
  665. if (Status == STATUS_SUCCESS)
  666. {
  667. //OutputDebugString("SCREDIR: SCardOnLineIOCTLCallback - _SendSCardIOCTLWithWaitForCallback(SCARD_IOCTL_ACCESSSTARTEDEVENT) - suceeded\n");
  668. g_cbIOCTLReturnBuffer =
  669. (unsigned long) g_StartedStatusBlock.Information;
  670. //
  671. // Look at the value returned from the SCARD_IOCTL_ACCESSSTARTEDEVENT
  672. // call to see if we should set the local started event
  673. //
  674. if (I_DecodeLongReturn(
  675. g_rgbIOCTLReturnBuffer,
  676. g_cbIOCTLReturnBuffer) == SCARD_S_SUCCESS)
  677. {
  678. SetEvent(g_hRedirStartedEvent);
  679. }
  680. fOperationDone = TRUE;
  681. }
  682. else if (Status == STATUS_PENDING)
  683. {
  684. //OutputDebugString("SCREDIR: SCardOnLineIOCTLCallback - _SendSCardIOCTLWithWaitForCallback(SCARD_IOCTL_ACCESSSTARTEDEVENT) - PENDING\n");
  685. //
  686. // This OK, since the AccessStartedEventIOCTLCallback function
  687. // will handle the return once the operation is complete
  688. //
  689. }
  690. else
  691. {
  692. fOperationDone = TRUE;
  693. }
  694. }
  695. else
  696. {
  697. fOperationDone = TRUE;
  698. }
  699. }
  700. if (fOperationDone)
  701. {
  702. EnterCriticalSection(&g_SetStartedEventStateCS);
  703. g_fInTheProcessOfSettingStartedEvent = FALSE;
  704. LeaveCriticalSection(&g_SetStartedEventStateCS);
  705. }
  706. }
  707. BOOL
  708. _SetStartedEventToCorrectState(void)
  709. {
  710. BOOL fRet = TRUE;
  711. BOOL fOperationDone = FALSE;
  712. HANDLE h = NULL;
  713. NTSTATUS Status = STATUS_SUCCESS;
  714. BYTE rgb[4];
  715. //
  716. // Make sure the event is created
  717. //
  718. if (NULL == (h = _GetStartedEventHandle()))
  719. {
  720. fRet = FALSE;
  721. goto Return;
  722. }
  723. //
  724. // If the event is already set then just return
  725. //
  726. /*if (WAIT_OBJECT_0 == WaitForSingleObject(h, 0))
  727. {
  728. //OutputDebugString("SCREDIR: _SetStartedEventToCorrectState - Event already set\n");
  729. goto Return;
  730. }*/
  731. EnterCriticalSection(&g_SetStartedEventStateCS);
  732. //
  733. // If we are already in the process of setting the started event, then just get out
  734. //
  735. if (g_fInTheProcessOfSettingStartedEvent)
  736. {
  737. //OutputDebugString("SCREDIR: _SetStartedEventToCorrectState - g_fInTheProcessOfSettingStartedEvent set\n");
  738. LeaveCriticalSection(&g_SetStartedEventStateCS);
  739. goto Return;
  740. }
  741. g_fInTheProcessOfSettingStartedEvent = TRUE;
  742. LeaveCriticalSection(&g_SetStartedEventStateCS);
  743. ResetEvent(g_hRedirStartedEvent);
  744. //
  745. // Make the blocking call to rdpdr.sys that will only return after the
  746. // client is connected, and the scard device announce has been processed
  747. //
  748. // NOTE: If this fails, then we can't do much,
  749. //
  750. Status = _SendSCardIOCTLWithWaitForCallback(
  751. SCARD_IOCTL_SMARTCARD_ONLINE,
  752. NULL,
  753. 0,
  754. SCardOnLineIOCTLCallback);
  755. if (Status == STATUS_SUCCESS)
  756. {
  757. //OutputDebugString("SCREDIR: _SetStartedEventToCorrectState - _SendSCardIOCTLWithWaitForCallback(SCARD_IOCTL_SMARTCARD_ONLINE) - suceeded\n");
  758. //
  759. // Since the SCARD_IOCTL_SMARTCARD_ONLINE succeeded immediately, we
  760. // can just make the SCARD_IOCTL_ACCESSSTARTEDEVENT right now.
  761. //
  762. Status = _SendSCardIOCTLWithWaitForCallback(
  763. SCARD_IOCTL_ACCESSSTARTEDEVENT,
  764. rgb,
  765. 4,
  766. AccessStartedEventIOCTLCallback);
  767. if (Status == STATUS_SUCCESS)
  768. {
  769. //OutputDebugString("SCREDIR: _SetStartedEventToCorrectState - _SendSCardIOCTLWithWaitForCallback(SCARD_IOCTL_ACCESSSTARTEDEVENT) - suceeded\n");
  770. g_cbIOCTLReturnBuffer =
  771. (unsigned long) g_StartedStatusBlock.Information;
  772. //
  773. // Look at the value returned from the SCARD_IOCTL_ACCESSSTARTEDEVENT
  774. // call to see if we should set the local started event
  775. //
  776. if (I_DecodeLongReturn(
  777. g_rgbIOCTLReturnBuffer,
  778. g_cbIOCTLReturnBuffer) == SCARD_S_SUCCESS)
  779. {
  780. SetEvent(g_hRedirStartedEvent);
  781. }
  782. fOperationDone = TRUE;
  783. }
  784. else if (Status == STATUS_PENDING)
  785. {
  786. //OutputDebugString("SCREDIR: _SetStartedEventToCorrectState - _SendSCardIOCTLWithWaitForCallback(SCARD_IOCTL_ACCESSSTARTEDEVENT) - PENDING\n");
  787. //
  788. // This OK, since the AccessStartedEventIOCTLCallback function
  789. // will handle the return once the operation is complete
  790. //
  791. }
  792. else
  793. {
  794. fOperationDone = TRUE;
  795. }
  796. }
  797. else if (Status == STATUS_PENDING)
  798. {
  799. //OutputDebugString("SCREDIR: _SetStartedEventToCorrectState - _SendSCardIOCTLWithWaitForCallback(SCARD_IOCTL_SMARTCARD_ONLINE) - PENDING\n");
  800. //
  801. // This is OK, the SCardOnLineIOCTLCallback will make the next call
  802. // to _SendSCardIOCTLWithWaitForCallback with SCARD_IOCTL_ACCESSSTARTEDEVENT
  803. //
  804. }
  805. else
  806. {
  807. fOperationDone = TRUE;
  808. }
  809. if (fOperationDone)
  810. {
  811. EnterCriticalSection(&g_SetStartedEventStateCS);
  812. g_fInTheProcessOfSettingStartedEvent = FALSE;
  813. LeaveCriticalSection(&g_SetStartedEventStateCS);
  814. }
  815. //
  816. // Now check to see if the operation completed successfully
  817. //
  818. if ((Status != STATUS_PENDING) && (Status != STATUS_SUCCESS))
  819. {
  820. fRet = FALSE;
  821. }
  822. Return:
  823. return (fRet);
  824. }
  825. //---------------------------------------------------------------------------------------
  826. //
  827. // _CreateRdpdrDeviceHandle
  828. //
  829. //---------------------------------------------------------------------------------------
  830. HANDLE
  831. _CreateRdpdrDeviceHandle()
  832. {
  833. WCHAR wszDeviceName[56];
  834. swprintf(wszDeviceName, L"\\\\TSCLIENT\\%S", DR_SMARTCARD_SUBSYSTEM);
  835. return (CreateFileW(
  836. wszDeviceName,
  837. GENERIC_READ | GENERIC_WRITE,
  838. FILE_SHARE_READ | FILE_SHARE_WRITE,
  839. NULL,
  840. CREATE_ALWAYS,
  841. FILE_FLAG_OVERLAPPED,
  842. NULL));
  843. }
  844. //---------------------------------------------------------------------------------------
  845. //
  846. // _CreateGlobalRdpdrHandle
  847. //
  848. //---------------------------------------------------------------------------------------
  849. NTSTATUS
  850. _CreateGlobalRdpdrHandle()
  851. {
  852. NTSTATUS Status = STATUS_SUCCESS;
  853. EnterCriticalSection(&g_CreateCS);
  854. //
  855. // Check to see if the SCardDevice handle has been created
  856. // yet, if not, then create it
  857. //
  858. if (g_hRdpdrDeviceHandle == INVALID_HANDLE_VALUE)
  859. {
  860. g_hRdpdrDeviceHandle = _CreateRdpdrDeviceHandle();
  861. if (g_hRdpdrDeviceHandle == INVALID_HANDLE_VALUE)
  862. {
  863. Status = STATUS_OPEN_FAILED;
  864. }
  865. }
  866. LeaveCriticalSection(&g_CreateCS);
  867. return (Status);
  868. }
  869. //---------------------------------------------------------------------------------------
  870. //
  871. // _SendSCardIOCTLWithWaitForCallback
  872. //
  873. //---------------------------------------------------------------------------------------
  874. NTSTATUS
  875. _SendSCardIOCTLWithWaitForCallback(
  876. ULONG IoControlCode,
  877. PVOID InputBuffer,
  878. ULONG InputBufferLength,
  879. WAITORTIMERCALLBACK Callback)
  880. {
  881. NTSTATUS Status = STATUS_SUCCESS;
  882. if (g_fInProcessDetach)
  883. {
  884. goto ErrorReturn;
  885. }
  886. Status = _CreateGlobalRdpdrHandle();
  887. if (Status != STATUS_SUCCESS)
  888. {
  889. return (Status);
  890. }
  891. //
  892. // Create the event which is set when the function successfully completes
  893. //
  894. if (g_hWaitEvent == NULL)
  895. {
  896. g_hWaitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  897. if (g_hWaitEvent == NULL)
  898. {
  899. goto ErrorReturn;
  900. }
  901. }
  902. else
  903. {
  904. ResetEvent(g_hWaitEvent);
  905. }
  906. Status = NtDeviceIoControlFile(
  907. g_hRdpdrDeviceHandle,
  908. g_hWaitEvent,
  909. NULL,
  910. NULL,
  911. &g_StartedStatusBlock,
  912. IoControlCode,
  913. InputBuffer,
  914. InputBufferLength,
  915. g_rgbIOCTLReturnBuffer,
  916. IOCTL_RETURN_BUFFER_SIZE);
  917. if (Status == STATUS_PENDING)
  918. {
  919. EnterCriticalSection(&g_SetStartedEventStateCS);
  920. //
  921. // The g_hWaitEvent being set by the driver will trigger this registered callback
  922. //
  923. if (!RegisterWaitForSingleObject(
  924. &g_hRegisteredWaitHandle,
  925. g_hWaitEvent,
  926. Callback,
  927. NULL,
  928. INFINITE,
  929. WT_EXECUTEONLYONCE))
  930. {
  931. LeaveCriticalSection(&g_SetStartedEventStateCS);
  932. goto ErrorReturn;
  933. }
  934. LeaveCriticalSection(&g_SetStartedEventStateCS);
  935. }
  936. else if (Status == STATUS_SUCCESS)
  937. {
  938. g_cbIOCTLReturnBuffer = (unsigned long) g_StartedStatusBlock.Information;
  939. }
  940. else
  941. {
  942. g_cbIOCTLReturnBuffer = 0;
  943. }
  944. Return:
  945. return (Status);
  946. ErrorReturn:
  947. Status = STATUS_INSUFFICIENT_RESOURCES;
  948. goto Return;
  949. }
  950. //---------------------------------------------------------------------------------------
  951. //
  952. // _SendSCardIOCTL
  953. //
  954. //---------------------------------------------------------------------------------------
  955. NTSTATUS
  956. _SendSCardIOCTL(
  957. ULONG IoControlCode,
  958. PVOID InputBuffer,
  959. ULONG InputBufferLength,
  960. BUFFER_LIST_STRUCT **ppOutputBuffer)
  961. {
  962. NTSTATUS Status = STATUS_SUCCESS;
  963. IO_STATUS_BLOCK StatusBlock;
  964. HANDLE rgWaitHandles[2];
  965. DWORD dwIndex;
  966. *ppOutputBuffer = NULL;
  967. rgWaitHandles[0] = NULL;
  968. rgWaitHandles[1] = NULL;
  969. //
  970. // Make sure the handle to the rdpdr device is created
  971. //
  972. Status = _CreateGlobalRdpdrHandle();
  973. if (Status != STATUS_SUCCESS)
  974. {
  975. return (Status);
  976. }
  977. //
  978. // Get an output buffer for the call
  979. //
  980. *ppOutputBuffer = GetBuffer();
  981. if (*ppOutputBuffer == NULL)
  982. {
  983. return (STATUS_NO_MEMORY);
  984. }
  985. //
  986. // Create the event that will be signaled when the IOCTL is complete
  987. //
  988. rgWaitHandles[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
  989. if (rgWaitHandles[0] == NULL)
  990. {
  991. return (STATUS_INSUFFICIENT_RESOURCES);
  992. }
  993. while (1)
  994. {
  995. Status = NtDeviceIoControlFile(
  996. g_hRdpdrDeviceHandle,
  997. rgWaitHandles[0],
  998. NULL,
  999. NULL,
  1000. &StatusBlock,
  1001. IoControlCode,
  1002. InputBuffer,
  1003. InputBufferLength,
  1004. (*ppOutputBuffer)->pbBytes,
  1005. (*ppOutputBuffer)->cbBytes);
  1006. if (Status == STATUS_PENDING)
  1007. {
  1008. rgWaitHandles[1] = _GetProcessDetachEventHandle();
  1009. if (rgWaitHandles[1] == NULL)
  1010. {
  1011. Status = STATUS_INSUFFICIENT_RESOURCES;
  1012. break;
  1013. }
  1014. dwIndex = WaitForMultipleObjects(2, rgWaitHandles, FALSE, INFINITE);
  1015. if (dwIndex != WAIT_FAILED)
  1016. {
  1017. dwIndex = dwIndex - WAIT_OBJECT_0;
  1018. //
  1019. // The IOCTL wait event was signaled if dwIndex == 0. Otherwise the
  1020. // process detach event was signaled
  1021. //
  1022. if (dwIndex == 0)
  1023. {
  1024. Status = StatusBlock.Status;
  1025. }
  1026. }
  1027. else
  1028. {
  1029. Status = STATUS_UNEXPECTED_IO_ERROR;
  1030. }
  1031. _ReleaseProcessDetachEventHandle();
  1032. }
  1033. if (Status == STATUS_BUFFER_TOO_SMALL)
  1034. {
  1035. if (!GrowBuffer(*ppOutputBuffer))
  1036. {
  1037. Status = STATUS_NO_MEMORY;
  1038. break;
  1039. }
  1040. ResetEvent(rgWaitHandles[0]);
  1041. }
  1042. else
  1043. {
  1044. break;
  1045. }
  1046. }
  1047. if (Status != STATUS_SUCCESS)
  1048. {
  1049. //
  1050. // If we got the STATUS_DEVICE_NOT_CONNECTED error, then go back to waiting
  1051. // for a connect
  1052. //
  1053. if (Status == STATUS_DEVICE_NOT_CONNECTED)
  1054. {
  1055. _SetStartedEventToCorrectState();
  1056. }
  1057. else if ((Status == STATUS_CANCELLED) &&
  1058. (g_hUnifiedStartedEvent != NULL))
  1059. {
  1060. //OutputDebugString("SCREDIR: _SendSCardIOCTL: resetting g_hUnifiedStartedEvent\n");
  1061. ResetEvent(g_hUnifiedStartedEvent);
  1062. _SetStartedEventToCorrectState();
  1063. }
  1064. (*ppOutputBuffer)->cbBytesUsed = 0;
  1065. goto Return;
  1066. }
  1067. (*ppOutputBuffer)->cbBytesUsed = (unsigned long) StatusBlock.Information;
  1068. Return:
  1069. if (rgWaitHandles[0] != NULL)
  1070. {
  1071. CloseHandle(rgWaitHandles[0]);
  1072. }
  1073. return (Status);
  1074. }
  1075. //---------------------------------------------------------------------------------------
  1076. //
  1077. // SafeMesHandleFree
  1078. //
  1079. //---------------------------------------------------------------------------------------
  1080. void
  1081. SafeMesHandleFree(handle_t *ph)
  1082. {
  1083. if (*ph != 0)
  1084. {
  1085. MesHandleFree(*ph);
  1086. *ph = 0;
  1087. }
  1088. }
  1089. //---------------------------------------------------------------------------------------
  1090. //
  1091. // _CalculateNumBytesInMultiStringA
  1092. //
  1093. //---------------------------------------------------------------------------------------
  1094. DWORD
  1095. _CalculateNumBytesInMultiStringA(LPCSTR psz)
  1096. {
  1097. DWORD dwTotal = sizeof(char); // trailing '/0'
  1098. DWORD dwNumChars = 0;
  1099. LPCSTR pszCurrent = psz;
  1100. if (psz == NULL)
  1101. {
  1102. return (0);
  1103. }
  1104. if (pszCurrent[0] == '\0')
  1105. {
  1106. if (pszCurrent[1] == '\0')
  1107. {
  1108. return (2 * sizeof(char));
  1109. }
  1110. pszCurrent++;
  1111. dwTotal += sizeof(char);
  1112. }
  1113. while (pszCurrent[0] != '\0')
  1114. {
  1115. dwNumChars = strlen(pszCurrent) + 1;
  1116. dwTotal += dwNumChars * sizeof(char);
  1117. pszCurrent += dwNumChars;
  1118. }
  1119. return (dwTotal);
  1120. }
  1121. //---------------------------------------------------------------------------------------
  1122. //
  1123. // _CalculateNumBytesInMultiStringW
  1124. //
  1125. //---------------------------------------------------------------------------------------
  1126. DWORD
  1127. _CalculateNumBytesInMultiStringW(LPCWSTR pwsz)
  1128. {
  1129. DWORD dwTotal = sizeof(WCHAR); // trailing L'/0'
  1130. DWORD dwNumChars = 0;
  1131. LPCWSTR pwszCurrent = pwsz;
  1132. if (pwsz == NULL)
  1133. {
  1134. return (0);
  1135. }
  1136. if (pwszCurrent[0] == L'\0')
  1137. {
  1138. if (pwszCurrent[1] == L'\0')
  1139. {
  1140. (2 * sizeof(WCHAR));
  1141. }
  1142. pwszCurrent++;
  1143. dwTotal += sizeof(WCHAR);
  1144. }
  1145. while (pwszCurrent[0] != L'\0')
  1146. {
  1147. dwNumChars = wcslen(pwszCurrent) + 1;
  1148. dwTotal += dwNumChars * sizeof(WCHAR);
  1149. pwszCurrent += dwNumChars;
  1150. }
  1151. return (dwTotal);
  1152. }
  1153. //---------------------------------------------------------------------------------------
  1154. //
  1155. // _CalculateNumBytesInAtr
  1156. //
  1157. //---------------------------------------------------------------------------------------
  1158. DWORD
  1159. _CalculateNumBytesInAtr(LPCBYTE pbAtr)
  1160. {
  1161. DWORD dwAtrLen = 0;
  1162. if (ParseAtr(pbAtr, &dwAtrLen, NULL, NULL, 33))
  1163. {
  1164. return (dwAtrLen);
  1165. }
  1166. else
  1167. {
  1168. return (0);
  1169. }
  1170. }
  1171. //---------------------------------------------------------------------------------------
  1172. //
  1173. // _CopyReturnToCallerBuffer
  1174. //
  1175. //---------------------------------------------------------------------------------------
  1176. #define BYTE_TYPE_RETURN 1
  1177. #define SZ_TYPE_RETURN 2
  1178. #define WSZ_TYPE_RETURN 3
  1179. LONG
  1180. _CopyReturnToCallerBuffer(
  1181. REDIR_LOCAL_SCARDCONTEXT *pRedirContext,
  1182. LPBYTE pbReturn,
  1183. DWORD cbReturn,
  1184. LPBYTE pbUserBuffer,
  1185. LPDWORD pcbUserBuffer,
  1186. DWORD dwReturnType)
  1187. {
  1188. LPBYTE *ppBuf;
  1189. BOOL fAutoAllocate = (*pcbUserBuffer == SCARD_AUTOALLOCATE);
  1190. DWORD dwEnd;
  1191. DWORD dwCallersBufferSize = *pcbUserBuffer;
  1192. //
  1193. // The number of chars or bytes, depending on the type of return.
  1194. //
  1195. if (dwReturnType == WSZ_TYPE_RETURN)
  1196. {
  1197. *pcbUserBuffer = cbReturn / sizeof(WCHAR);
  1198. }
  1199. else if (dwReturnType == SZ_TYPE_RETURN)
  1200. {
  1201. *pcbUserBuffer = cbReturn / sizeof(char);
  1202. }
  1203. else
  1204. {
  1205. *pcbUserBuffer = cbReturn;
  1206. }
  1207. //
  1208. // If pbUserBuffer is not NULL, then the caller wants the data,
  1209. // not just the size, so give it to em'
  1210. //
  1211. if ((pbReturn != NULL) &&
  1212. (pbUserBuffer != NULL))
  1213. {
  1214. //
  1215. // validate the data
  1216. //
  1217. if (dwReturnType == WSZ_TYPE_RETURN)
  1218. {
  1219. //
  1220. // If we aren't auto allocating and the users buffer is too small then
  1221. // get out. This is just extra protection to ensure that the client
  1222. // isn't ill behaved. Since the client was passed the size of our
  1223. // callers buffer the client should really fail if the buffer isn't
  1224. // big enough, but since we can't trust the client, do this extra check.
  1225. //
  1226. if ((!fAutoAllocate) && (dwCallersBufferSize < (cbReturn / sizeof(WCHAR))))
  1227. {
  1228. return (SCARD_E_UNEXPECTED);
  1229. }
  1230. dwEnd = cbReturn / sizeof(WCHAR);
  1231. if ((dwEnd < 2) || // must be at least two chars
  1232. (((LPWSTR) pbReturn)[dwEnd-1] != L'\0') || // last char must be '\0'
  1233. (((LPWSTR) pbReturn)[dwEnd-2] != L'\0')) // second to last char must be '\0'
  1234. {
  1235. return (SCARD_E_UNEXPECTED);
  1236. }
  1237. }
  1238. else if (dwReturnType == SZ_TYPE_RETURN)
  1239. {
  1240. //
  1241. // If we aren't auto allocating and the users buffer is too small then
  1242. // get out. This is just extra protection to ensure that the client
  1243. // isn't ill behaved. Since the client was passed the size of our
  1244. // callers buffer the client should really fail if the buffer isn't
  1245. // big enough, but since we can't trust the client, do this extra check.
  1246. //
  1247. if ((!fAutoAllocate) && (dwCallersBufferSize < (cbReturn / sizeof(char))))
  1248. {
  1249. return (SCARD_E_UNEXPECTED);
  1250. }
  1251. dwEnd = cbReturn / sizeof(char);
  1252. if ((dwEnd < 2) || // must be at least two chars
  1253. (((LPSTR) pbReturn)[dwEnd-1] != '\0') || // last char must be '\0'
  1254. (((LPSTR) pbReturn)[dwEnd-2] != '\0')) // second to last char must be '\0'
  1255. {
  1256. return (SCARD_E_UNEXPECTED);
  1257. }
  1258. }
  1259. else
  1260. {
  1261. //
  1262. // If we aren't auto allocating and the users buffer is too small then
  1263. // get out. This is just extra protection to ensure that the client
  1264. // isn't ill behaved. Since the client was passed the size of our
  1265. // callers buffer the client should really fail if the buffer isn't
  1266. // big enough, but since we can't trust the client, do this extra check.
  1267. //
  1268. if ((!fAutoAllocate) && (dwCallersBufferSize < cbReturn))
  1269. {
  1270. return (SCARD_E_UNEXPECTED);
  1271. }
  1272. }
  1273. //
  1274. // Allocate space for caller if requested, else, copy to callers
  1275. // supplied buffer
  1276. //
  1277. if (fAutoAllocate)
  1278. {
  1279. ppBuf = (LPBYTE *) pbUserBuffer;
  1280. *ppBuf = (LPBYTE) SCRedirAlloc(pRedirContext, cbReturn);
  1281. if (*ppBuf != NULL)
  1282. {
  1283. memcpy(*ppBuf, pbReturn, cbReturn);
  1284. }
  1285. else
  1286. {
  1287. return (SCARD_E_NO_MEMORY);
  1288. }
  1289. }
  1290. else
  1291. {
  1292. memcpy(pbUserBuffer, pbReturn, cbReturn);
  1293. }
  1294. }
  1295. return (SCARD_S_SUCCESS);
  1296. }
  1297. //---------------------------------------------------------------------------------------
  1298. //
  1299. // I_DecodeLongReturn
  1300. //
  1301. //---------------------------------------------------------------------------------------
  1302. LONG
  1303. I_DecodeLongReturn(
  1304. BYTE *pb,
  1305. unsigned long cb)
  1306. {
  1307. handle_t h = 0;
  1308. RPC_STATUS rpcStatus;
  1309. Long_Return LongReturn;
  1310. LONG lReturn;
  1311. rpcStatus = MesDecodeBufferHandleCreate(
  1312. (char *) pb,
  1313. cb,
  1314. &h);
  1315. if (rpcStatus != RPC_S_OK)
  1316. {
  1317. ERROR_RETURN(SCARD_E_UNEXPECTED);
  1318. }
  1319. memset(&LongReturn, 0, sizeof(LongReturn));
  1320. _TRY_(Long_Return_Decode(h, &LongReturn))
  1321. lReturn = LongReturn.ReturnCode;
  1322. _TRY_2(Long_Return_Free(h, &LongReturn))
  1323. Return:
  1324. SafeMesHandleFree(&h);
  1325. return (lReturn);
  1326. ErrorReturn:
  1327. goto Return;
  1328. }
  1329. //---------------------------------------------------------------------------------------
  1330. //
  1331. // SCardEstablishContext
  1332. //
  1333. //---------------------------------------------------------------------------------------
  1334. WINSCARDAPI LONG WINAPI
  1335. SCardEstablishContext(
  1336. IN DWORD dwScope,
  1337. IN LPCVOID pvReserved1,
  1338. IN LPCVOID pvReserved2,
  1339. OUT LPSCARDCONTEXT phContext)
  1340. {
  1341. LONG lReturn = SCARD_S_SUCCESS;
  1342. NTSTATUS Status = STATUS_SUCCESS;
  1343. RPC_STATUS rpcStatus = RPC_S_OK;
  1344. char *pbEncodedBuffer = NULL;
  1345. unsigned long cbEncodedBuffer = 0;
  1346. handle_t h = 0;
  1347. BOOL fFreeDecode = FALSE;
  1348. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  1349. EstablishContext_Call EstablishContextCall;
  1350. EstablishContext_Return EstablishContextReturn;
  1351. //
  1352. // This event is the "smart card subsystem started" event that
  1353. // winscard.dll and scredir.dll share. scredir will Reset this event
  1354. // if it gets a STATUS_CANCELLED returned from the rdpdr driver, or if it
  1355. // gets and indication that the clients scardsvr service was stopped (it
  1356. // gets these indications via SCardEstablishContext returing SCARD_E_NO_SERVICE
  1357. // or by SCardGetStatusChange returning SCARD_E_SYSTEM_CANCELLED). It
  1358. // does this so that the event goes into the unsignalled state as soon as
  1359. // possible when a disconnect or service shutdown is detected... a STATUS_CANCELLED
  1360. // returned from rdpdr happens when a disconnect takes place
  1361. //
  1362. g_hUnifiedStartedEvent = (HANDLE) pvReserved2;
  1363. //
  1364. // Validate input params and initialize the out param
  1365. //
  1366. if (phContext == NULL)
  1367. {
  1368. ERROR_RETURN(SCARD_E_INVALID_PARAMETER)
  1369. }
  1370. else
  1371. {
  1372. *phContext = NULL;
  1373. }
  1374. if ((SCARD_SCOPE_USER != dwScope)
  1375. // && (SCARD_SCOPE_TERMINAL != dwScope) // Maybe NT V5+?
  1376. && (SCARD_SCOPE_SYSTEM != dwScope))
  1377. {
  1378. ERROR_RETURN(SCARD_E_INVALID_VALUE)
  1379. }
  1380. //
  1381. // Initialize encoding handle
  1382. //
  1383. rpcStatus = MesEncodeDynBufferHandleCreate(
  1384. &pbEncodedBuffer,
  1385. &cbEncodedBuffer,
  1386. &h);
  1387. if (rpcStatus != RPC_S_OK)
  1388. {
  1389. ERROR_RETURN(SCARD_E_UNEXPECTED)
  1390. }
  1391. //
  1392. // Encode the EstablishContext params
  1393. //
  1394. EstablishContextCall.dwScope = dwScope;
  1395. _TRY_(EstablishContext_Call_Encode(h, &EstablishContextCall))
  1396. //
  1397. // Make the EstablishContext call to the client
  1398. //
  1399. Status = _SendSCardIOCTL(
  1400. SCARD_IOCTL_ESTABLISHCONTEXT,
  1401. pbEncodedBuffer,
  1402. cbEncodedBuffer,
  1403. &pOutputBuffer);
  1404. if (Status != STATUS_SUCCESS)
  1405. {
  1406. ERROR_RETURN(_MakeSCardError(Status))
  1407. }
  1408. SafeMesHandleFree(&h);
  1409. //
  1410. // Decode the return
  1411. //
  1412. rpcStatus = MesDecodeBufferHandleCreate(
  1413. (char *) pOutputBuffer->pbBytes,
  1414. pOutputBuffer->cbBytesUsed,
  1415. &h);
  1416. if (rpcStatus != RPC_S_OK)
  1417. {
  1418. ERROR_RETURN(SCARD_E_UNEXPECTED)
  1419. }
  1420. memset(&EstablishContextReturn, 0, sizeof(EstablishContextReturn));
  1421. _TRY_(EstablishContext_Return_Decode(h, &EstablishContextReturn))
  1422. fFreeDecode = TRUE;
  1423. lReturn = EstablishContextReturn.ReturnCode;
  1424. if (lReturn == SCARD_S_SUCCESS)
  1425. {
  1426. REDIR_LOCAL_SCARDCONTEXT *pRedirLocalContext = NULL;
  1427. //
  1428. // The value that represents the SCARDCONTEXT on the remote client
  1429. // machine is a variable size, so allocate memory for the struct
  1430. // that holds the variable length context size and pointer, plus
  1431. // the actual bytes for the context... but first, make sure the
  1432. // context is a reasonable size
  1433. //
  1434. if (EstablishContextReturn.Context.cbContext > MAX_SCARDCONTEXT_SIZE)
  1435. {
  1436. ERROR_RETURN(SCARD_E_UNEXPECTED)
  1437. }
  1438. pRedirLocalContext = (REDIR_LOCAL_SCARDCONTEXT *)
  1439. MIDL_user_allocate(
  1440. sizeof(REDIR_LOCAL_SCARDCONTEXT) +
  1441. EstablishContextReturn.Context.cbContext);
  1442. if (pRedirLocalContext != NULL)
  1443. {
  1444. pRedirLocalContext->Context.cbContext = EstablishContextReturn.Context.cbContext;
  1445. pRedirLocalContext->Context.pbContext = ((BYTE *) pRedirLocalContext) +
  1446. sizeof(REDIR_LOCAL_SCARDCONTEXT);
  1447. memcpy(
  1448. pRedirLocalContext->Context.pbContext,
  1449. EstablishContextReturn.Context.pbContext,
  1450. EstablishContextReturn.Context.cbContext);
  1451. pRedirLocalContext->hHeap = (HANDLE) pvReserved1;
  1452. *phContext = (SCARDCONTEXT) pRedirLocalContext;
  1453. }
  1454. else
  1455. {
  1456. lReturn = SCARD_E_NO_MEMORY;
  1457. }
  1458. }
  1459. else if ((lReturn == SCARD_E_NO_SERVICE) &&
  1460. (g_hUnifiedStartedEvent != NULL))
  1461. {
  1462. //
  1463. // This error indicates that the clients scardsvr service has been stopped,
  1464. // so reset the unified started event
  1465. //
  1466. //OutputDebugString("SCREDIR: SCardEstablishContext: resetting g_hUnifiedStartedEvent\n");
  1467. ResetEvent(g_hUnifiedStartedEvent);
  1468. _SetStartedEventToCorrectState();
  1469. }
  1470. Return:
  1471. if (fFreeDecode)
  1472. {
  1473. _TRY_2(EstablishContext_Return_Free(h, &EstablishContextReturn))
  1474. }
  1475. SafeMesHandleFree(&h);
  1476. MIDL_user_free(pbEncodedBuffer);
  1477. FreeBuffer(pOutputBuffer);
  1478. return (lReturn);
  1479. ErrorReturn:
  1480. if ((phContext != NULL) && (*phContext != NULL))
  1481. {
  1482. MIDL_user_free((void *) *phContext);
  1483. *phContext = NULL;
  1484. }
  1485. goto Return;
  1486. }
  1487. //---------------------------------------------------------------------------------------
  1488. //
  1489. // I_ContextCallWithLongReturn
  1490. //
  1491. //---------------------------------------------------------------------------------------
  1492. WINSCARDAPI LONG WINAPI
  1493. I_ContextCallWithLongReturn(
  1494. IN SCARDCONTEXT hContext,
  1495. ULONG IoControlCode)
  1496. {
  1497. LONG lReturn = SCARD_S_SUCCESS;
  1498. NTSTATUS Status = STATUS_SUCCESS;
  1499. RPC_STATUS rpcStatus = RPC_S_OK;
  1500. char *pbEncodedBuffer = NULL;
  1501. unsigned long cbEncodedBuffer = 0;
  1502. handle_t h = 0;
  1503. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  1504. Context_Call ContextCall;
  1505. if (hContext == NULL)
  1506. {
  1507. return (SCARD_E_INVALID_PARAMETER);
  1508. }
  1509. //
  1510. // Initialize encoding handle
  1511. //
  1512. rpcStatus = MesEncodeDynBufferHandleCreate(
  1513. &pbEncodedBuffer,
  1514. &cbEncodedBuffer,
  1515. &h);
  1516. if (rpcStatus != RPC_S_OK)
  1517. {
  1518. ERROR_RETURN(SCARD_E_UNEXPECTED)
  1519. }
  1520. //
  1521. // Encode the ContextCall params
  1522. //
  1523. ContextCall.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context;
  1524. _TRY_(Context_Call_Encode(h, &ContextCall))
  1525. //
  1526. // Make the IoControl call to the client
  1527. //
  1528. Status = _SendSCardIOCTL(
  1529. IoControlCode,
  1530. pbEncodedBuffer,
  1531. cbEncodedBuffer,
  1532. &pOutputBuffer);
  1533. if (Status != STATUS_SUCCESS)
  1534. {
  1535. ERROR_RETURN(_MakeSCardError(Status))
  1536. }
  1537. //
  1538. // Decode the return
  1539. //
  1540. lReturn = I_DecodeLongReturn(pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed);
  1541. Return:
  1542. SafeMesHandleFree(&h);
  1543. MIDL_user_free(pbEncodedBuffer);
  1544. FreeBuffer(pOutputBuffer);
  1545. return (lReturn);
  1546. ErrorReturn:
  1547. goto Return;
  1548. }
  1549. //---------------------------------------------------------------------------------------
  1550. //
  1551. // SCardReleaseContext
  1552. //
  1553. //---------------------------------------------------------------------------------------
  1554. WINSCARDAPI LONG WINAPI
  1555. SCardReleaseContext(
  1556. IN SCARDCONTEXT hContext)
  1557. {
  1558. LONG lReturn = SCARD_S_SUCCESS;
  1559. __try
  1560. {
  1561. if (hContext == NULL)
  1562. {
  1563. return (SCARD_E_INVALID_PARAMETER);
  1564. }
  1565. lReturn = I_ContextCallWithLongReturn(
  1566. hContext,
  1567. SCARD_IOCTL_RELEASECONTEXT);
  1568. MIDL_user_free((REDIR_LOCAL_SCARDCONTEXT *) hContext);
  1569. }
  1570. __except(EXCEPTION_EXECUTE_HANDLER)
  1571. {
  1572. return (SCARD_E_INVALID_PARAMETER);
  1573. }
  1574. return (lReturn);
  1575. }
  1576. //---------------------------------------------------------------------------------------
  1577. //
  1578. // SCardIsValidContext
  1579. //
  1580. //---------------------------------------------------------------------------------------
  1581. WINSCARDAPI LONG WINAPI
  1582. SCardIsValidContext(
  1583. IN SCARDCONTEXT hContext)
  1584. {
  1585. return (I_ContextCallWithLongReturn(
  1586. hContext,
  1587. SCARD_IOCTL_ISVALIDCONTEXT));
  1588. }
  1589. //---------------------------------------------------------------------------------------
  1590. //
  1591. // SCardListReaderGroups
  1592. //
  1593. //---------------------------------------------------------------------------------------
  1594. WINSCARDAPI LONG WINAPI
  1595. I_SCardListReaderGroups(
  1596. IN SCARDCONTEXT hContext,
  1597. OUT LPBYTE mszGroups,
  1598. IN OUT LPDWORD pcchGroups,
  1599. IN BOOL fUnicode)
  1600. {
  1601. LONG lReturn = SCARD_S_SUCCESS;
  1602. NTSTATUS Status = STATUS_SUCCESS;
  1603. RPC_STATUS rpcStatus = RPC_S_OK;
  1604. char *pbEncodedBuffer = NULL;
  1605. unsigned long cbEncodedBuffer = 0;
  1606. handle_t h = 0;
  1607. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  1608. ListReaderGroups_Call ListReaderGroupsCall;
  1609. ListReaderGroups_Return ListReaderGroupsReturn;
  1610. if (pcchGroups == NULL)
  1611. {
  1612. return (SCARD_E_INVALID_PARAMETER);
  1613. }
  1614. //
  1615. // Initialize encoding handle
  1616. //
  1617. rpcStatus = MesEncodeDynBufferHandleCreate(
  1618. &pbEncodedBuffer,
  1619. &cbEncodedBuffer,
  1620. &h);
  1621. if (rpcStatus != RPC_S_OK)
  1622. {
  1623. ERROR_RETURN(SCARD_E_UNEXPECTED)
  1624. }
  1625. //
  1626. // Encode the ListReaderGroups params
  1627. //
  1628. if (hContext != NULL)
  1629. {
  1630. ListReaderGroupsCall.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context;
  1631. }
  1632. else
  1633. {
  1634. ListReaderGroupsCall.Context.pbContext = NULL;
  1635. ListReaderGroupsCall.Context.cbContext = 0;
  1636. }
  1637. ListReaderGroupsCall.fmszGroupsIsNULL = (mszGroups == NULL);
  1638. ListReaderGroupsCall.cchGroups = *pcchGroups;
  1639. _TRY_(ListReaderGroups_Call_Encode(h, &ListReaderGroupsCall))
  1640. //
  1641. // Make the ListReaderGroups call to the client
  1642. //
  1643. Status = _SendSCardIOCTL(
  1644. fUnicode ? SCARD_IOCTL_LISTREADERGROUPSW :
  1645. SCARD_IOCTL_LISTREADERGROUPSA,
  1646. pbEncodedBuffer,
  1647. cbEncodedBuffer,
  1648. &pOutputBuffer);
  1649. if (Status != STATUS_SUCCESS)
  1650. {
  1651. ERROR_RETURN(_MakeSCardError(Status))
  1652. }
  1653. SafeMesHandleFree(&h);
  1654. //
  1655. // Decode the return
  1656. //
  1657. rpcStatus = MesDecodeBufferHandleCreate(
  1658. (char *) pOutputBuffer->pbBytes,
  1659. pOutputBuffer->cbBytesUsed,
  1660. &h);
  1661. if (rpcStatus != RPC_S_OK)
  1662. {
  1663. ERROR_RETURN(SCARD_E_UNEXPECTED)
  1664. }
  1665. memset(&ListReaderGroupsReturn, 0, sizeof(ListReaderGroupsReturn));
  1666. _TRY_(ListReaderGroups_Return_Decode(h, &ListReaderGroupsReturn))
  1667. //
  1668. // If successful, then copy the returned multi string
  1669. //
  1670. if (ListReaderGroupsReturn.ReturnCode == SCARD_S_SUCCESS)
  1671. {
  1672. lReturn = _CopyReturnToCallerBuffer(
  1673. (REDIR_LOCAL_SCARDCONTEXT *) hContext,
  1674. ListReaderGroupsReturn.msz,
  1675. ListReaderGroupsReturn.cBytes,
  1676. mszGroups,
  1677. pcchGroups,
  1678. fUnicode ? WSZ_TYPE_RETURN : SZ_TYPE_RETURN);
  1679. }
  1680. else
  1681. {
  1682. lReturn = ListReaderGroupsReturn.ReturnCode;
  1683. }
  1684. _TRY_2(ListReaderGroups_Return_Free(h, &ListReaderGroupsReturn))
  1685. Return:
  1686. SafeMesHandleFree(&h);
  1687. MIDL_user_free(pbEncodedBuffer);
  1688. FreeBuffer(pOutputBuffer);
  1689. return (lReturn);
  1690. ErrorReturn:
  1691. goto Return;
  1692. }
  1693. WINSCARDAPI LONG WINAPI
  1694. SCardListReaderGroupsA(
  1695. IN SCARDCONTEXT hContext,
  1696. OUT LPSTR mszGroups,
  1697. IN OUT LPDWORD pcchGroups)
  1698. {
  1699. return (I_SCardListReaderGroups(
  1700. hContext,
  1701. (LPBYTE) mszGroups,
  1702. pcchGroups,
  1703. FALSE));
  1704. }
  1705. WINSCARDAPI LONG WINAPI
  1706. SCardListReaderGroupsW(
  1707. IN SCARDCONTEXT hContext,
  1708. OUT LPWSTR mszGroups,
  1709. IN OUT LPDWORD pcchGroups)
  1710. {
  1711. return (I_SCardListReaderGroups(
  1712. hContext,
  1713. (LPBYTE) mszGroups,
  1714. pcchGroups,
  1715. TRUE));
  1716. }
  1717. //---------------------------------------------------------------------------------------
  1718. //
  1719. // SCardListReaders
  1720. //
  1721. //---------------------------------------------------------------------------------------
  1722. WINSCARDAPI LONG WINAPI
  1723. I_SCardListReaders(
  1724. IN SCARDCONTEXT hContext,
  1725. IN LPCBYTE mszGroups,
  1726. OUT LPBYTE mszReaders,
  1727. IN OUT LPDWORD pcchReaders,
  1728. IN BOOL fUnicode)
  1729. {
  1730. LONG lReturn = SCARD_S_SUCCESS;
  1731. NTSTATUS Status = STATUS_SUCCESS;
  1732. RPC_STATUS rpcStatus = RPC_S_OK;
  1733. char *pbEncodedBuffer = NULL;
  1734. unsigned long cbEncodedBuffer = 0;
  1735. handle_t h = 0;
  1736. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  1737. ListReaders_Call ListReadersCall;
  1738. ListReaders_Return ListReadersReturn;
  1739. if (pcchReaders == NULL)
  1740. {
  1741. return (SCARD_E_INVALID_PARAMETER);
  1742. }
  1743. //
  1744. // Initialize encoding handle
  1745. //
  1746. rpcStatus = MesEncodeDynBufferHandleCreate(
  1747. &pbEncodedBuffer,
  1748. &cbEncodedBuffer,
  1749. &h);
  1750. if (rpcStatus != RPC_S_OK)
  1751. {
  1752. ERROR_RETURN(SCARD_E_UNEXPECTED)
  1753. }
  1754. //
  1755. // Encode the ListReaders params
  1756. //
  1757. if (hContext != NULL)
  1758. {
  1759. ListReadersCall.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context;
  1760. }
  1761. else
  1762. {
  1763. ListReadersCall.Context.pbContext = NULL;
  1764. ListReadersCall.Context.cbContext = 0;
  1765. }
  1766. ListReadersCall.cBytes = fUnicode ?
  1767. _CalculateNumBytesInMultiStringW((LPCWSTR) mszGroups) :
  1768. _CalculateNumBytesInMultiStringA((LPCSTR) mszGroups);
  1769. ListReadersCall.mszGroups = mszGroups;
  1770. ListReadersCall.fmszReadersIsNULL = (mszReaders == NULL);
  1771. ListReadersCall.cchReaders = *pcchReaders;
  1772. _TRY_(ListReaders_Call_Encode(h, &ListReadersCall))
  1773. //
  1774. // Make the ListReaders call to the client
  1775. //
  1776. Status = _SendSCardIOCTL(
  1777. fUnicode ? SCARD_IOCTL_LISTREADERSW :
  1778. SCARD_IOCTL_LISTREADERSA,
  1779. pbEncodedBuffer,
  1780. cbEncodedBuffer,
  1781. &pOutputBuffer);
  1782. if (Status != STATUS_SUCCESS)
  1783. {
  1784. ERROR_RETURN(_MakeSCardError(Status))
  1785. }
  1786. SafeMesHandleFree(&h);
  1787. //
  1788. // Decode the return
  1789. //
  1790. rpcStatus = MesDecodeBufferHandleCreate(
  1791. (char *) pOutputBuffer->pbBytes,
  1792. pOutputBuffer->cbBytesUsed,
  1793. &h);
  1794. if (rpcStatus != RPC_S_OK)
  1795. {
  1796. ERROR_RETURN(SCARD_E_UNEXPECTED)
  1797. }
  1798. memset(&ListReadersReturn, 0, sizeof(ListReadersReturn));
  1799. _TRY_(ListReaders_Return_Decode(h, &ListReadersReturn))
  1800. //
  1801. // If successful, then copy the returned multi string
  1802. //
  1803. if (ListReadersReturn.ReturnCode == SCARD_S_SUCCESS)
  1804. {
  1805. lReturn = _CopyReturnToCallerBuffer(
  1806. (REDIR_LOCAL_SCARDCONTEXT *) hContext,
  1807. ListReadersReturn.msz,
  1808. ListReadersReturn.cBytes,
  1809. mszReaders,
  1810. pcchReaders,
  1811. fUnicode ? WSZ_TYPE_RETURN : SZ_TYPE_RETURN);
  1812. }
  1813. else
  1814. {
  1815. lReturn = ListReadersReturn.ReturnCode;
  1816. }
  1817. _TRY_2(ListReaders_Return_Free(h, &ListReadersReturn))
  1818. Return:
  1819. SafeMesHandleFree(&h);
  1820. MIDL_user_free(pbEncodedBuffer);
  1821. FreeBuffer(pOutputBuffer);
  1822. return (lReturn);
  1823. ErrorReturn:
  1824. goto Return;
  1825. }
  1826. WINSCARDAPI LONG WINAPI
  1827. SCardListReadersA(
  1828. IN SCARDCONTEXT hContext,
  1829. IN LPCSTR mszGroups,
  1830. OUT LPSTR mszReaders,
  1831. IN OUT LPDWORD pcchReaders)
  1832. {
  1833. return (I_SCardListReaders(
  1834. hContext,
  1835. (LPCBYTE) mszGroups,
  1836. (LPBYTE) mszReaders,
  1837. pcchReaders,
  1838. FALSE));
  1839. }
  1840. WINSCARDAPI LONG WINAPI
  1841. SCardListReadersW(
  1842. IN SCARDCONTEXT hContext,
  1843. IN LPCWSTR mszGroups,
  1844. OUT LPWSTR mszReaders,
  1845. IN OUT LPDWORD pcchReaders)
  1846. {
  1847. return (I_SCardListReaders(
  1848. hContext,
  1849. (LPCBYTE) mszGroups,
  1850. (LPBYTE) mszReaders,
  1851. pcchReaders,
  1852. TRUE));
  1853. }
  1854. //---------------------------------------------------------------------------------------
  1855. //
  1856. // I_ContextAndStringCallWithLongReturn
  1857. //
  1858. //---------------------------------------------------------------------------------------
  1859. WINSCARDAPI LONG WINAPI
  1860. I_ContextAndStringCallWithLongReturn(
  1861. IN SCARDCONTEXT hContext,
  1862. IN LPCBYTE sz,
  1863. IN BOOL fUnicode,
  1864. ULONG IoControlCode)
  1865. {
  1866. LONG lReturn = SCARD_S_SUCCESS;
  1867. NTSTATUS Status = STATUS_SUCCESS;
  1868. RPC_STATUS rpcStatus = RPC_S_OK;
  1869. char *pbEncodedBuffer = NULL;
  1870. unsigned long cbEncodedBuffer = 0;
  1871. handle_t h = 0;
  1872. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  1873. ContextAndStringA_Call ContextAndStringCallA;
  1874. ContextAndStringW_Call ContextAndStringCallW;
  1875. if (hContext == NULL)
  1876. {
  1877. return (SCARD_E_INVALID_PARAMETER);
  1878. }
  1879. else if (sz == NULL)
  1880. {
  1881. return (SCARD_E_INVALID_VALUE);
  1882. }
  1883. //
  1884. // Initialize encoding handle
  1885. //
  1886. rpcStatus = MesEncodeDynBufferHandleCreate(
  1887. &pbEncodedBuffer,
  1888. &cbEncodedBuffer,
  1889. &h);
  1890. if (rpcStatus != RPC_S_OK)
  1891. {
  1892. ERROR_RETURN(SCARD_E_UNEXPECTED)
  1893. }
  1894. //
  1895. // Encode the ContextAndString params
  1896. //
  1897. ContextAndStringCallA.Context =
  1898. ContextAndStringCallW.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context;
  1899. if (fUnicode)
  1900. {
  1901. ContextAndStringCallW.sz = (LPCWSTR) sz;
  1902. _TRY_(ContextAndStringW_Call_Encode(h, &ContextAndStringCallW))
  1903. }
  1904. else
  1905. {
  1906. ContextAndStringCallA.sz = (LPCSTR) sz;
  1907. _TRY_(ContextAndStringA_Call_Encode(h, &ContextAndStringCallA))
  1908. }
  1909. //
  1910. // Make the call to the client
  1911. //
  1912. Status = _SendSCardIOCTL(
  1913. IoControlCode,
  1914. pbEncodedBuffer,
  1915. cbEncodedBuffer,
  1916. &pOutputBuffer);
  1917. if (Status != STATUS_SUCCESS)
  1918. {
  1919. ERROR_RETURN(_MakeSCardError(Status))
  1920. }
  1921. //
  1922. // Decode the return
  1923. //
  1924. lReturn = I_DecodeLongReturn(pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed);
  1925. Return:
  1926. SafeMesHandleFree(&h);
  1927. MIDL_user_free(pbEncodedBuffer);
  1928. FreeBuffer(pOutputBuffer);
  1929. return (lReturn);
  1930. ErrorReturn:
  1931. goto Return;
  1932. }
  1933. //---------------------------------------------------------------------------------------
  1934. //
  1935. // SCardIntroduceReaderGroup
  1936. //
  1937. //---------------------------------------------------------------------------------------
  1938. WINSCARDAPI LONG WINAPI
  1939. SCardIntroduceReaderGroupA(
  1940. IN SCARDCONTEXT hContext,
  1941. IN LPCSTR szGroupName)
  1942. {
  1943. return (I_ContextAndStringCallWithLongReturn(
  1944. hContext,
  1945. (LPCBYTE) szGroupName,
  1946. FALSE,
  1947. SCARD_IOCTL_INTRODUCEREADERGROUPA));
  1948. }
  1949. WINSCARDAPI LONG WINAPI
  1950. SCardIntroduceReaderGroupW(
  1951. IN SCARDCONTEXT hContext,
  1952. IN LPCWSTR szGroupName)
  1953. {
  1954. return (I_ContextAndStringCallWithLongReturn(
  1955. hContext,
  1956. (LPCBYTE) szGroupName,
  1957. TRUE,
  1958. SCARD_IOCTL_INTRODUCEREADERGROUPW));
  1959. }
  1960. //---------------------------------------------------------------------------------------
  1961. //
  1962. // SCardForgetReaderGroup
  1963. //
  1964. //---------------------------------------------------------------------------------------
  1965. WINSCARDAPI LONG WINAPI
  1966. SCardForgetReaderGroupA(
  1967. IN SCARDCONTEXT hContext,
  1968. IN LPCSTR szGroupName)
  1969. {
  1970. return (I_ContextAndStringCallWithLongReturn(
  1971. hContext,
  1972. (LPCBYTE) szGroupName,
  1973. FALSE,
  1974. SCARD_IOCTL_FORGETREADERGROUPA));
  1975. }
  1976. WINSCARDAPI LONG WINAPI
  1977. SCardForgetReaderGroupW(
  1978. IN SCARDCONTEXT hContext,
  1979. IN LPCWSTR szGroupName)
  1980. {
  1981. return (I_ContextAndStringCallWithLongReturn(
  1982. hContext,
  1983. (LPCBYTE) szGroupName,
  1984. TRUE,
  1985. SCARD_IOCTL_FORGETREADERGROUPW));
  1986. }
  1987. //---------------------------------------------------------------------------------------
  1988. //
  1989. // I_ContextAndTwoStringCallWithLongReturn
  1990. //
  1991. //---------------------------------------------------------------------------------------
  1992. WINSCARDAPI LONG WINAPI
  1993. I_ContextAndTwoStringCallWithLongReturn(
  1994. IN SCARDCONTEXT hContext,
  1995. IN LPCBYTE sz1,
  1996. IN LPCBYTE sz2,
  1997. IN BOOL fUnicode,
  1998. ULONG IoControlCode)
  1999. {
  2000. LONG lReturn = SCARD_S_SUCCESS;
  2001. NTSTATUS Status = STATUS_SUCCESS;
  2002. RPC_STATUS rpcStatus = RPC_S_OK;
  2003. char *pbEncodedBuffer = NULL;
  2004. unsigned long cbEncodedBuffer = 0;
  2005. handle_t h = 0;
  2006. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  2007. ContextAndTwoStringA_Call ContextAndTwoStringCallA;
  2008. ContextAndTwoStringW_Call ContextAndTwoStringCallW;
  2009. if (hContext == NULL)
  2010. {
  2011. return (SCARD_E_INVALID_PARAMETER);
  2012. }
  2013. else if ((sz1 == NULL) ||
  2014. (sz2 == NULL))
  2015. {
  2016. return (SCARD_E_INVALID_VALUE);
  2017. }
  2018. //
  2019. // Initialize encoding handle
  2020. //
  2021. rpcStatus = MesEncodeDynBufferHandleCreate(
  2022. &pbEncodedBuffer,
  2023. &cbEncodedBuffer,
  2024. &h);
  2025. if (rpcStatus != RPC_S_OK)
  2026. {
  2027. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2028. }
  2029. //
  2030. // Encode the ContextAndTwoString params
  2031. //
  2032. ContextAndTwoStringCallA.Context =
  2033. ContextAndTwoStringCallW.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context;
  2034. if (fUnicode)
  2035. {
  2036. ContextAndTwoStringCallW.sz1 = (LPCWSTR) sz1;
  2037. ContextAndTwoStringCallW.sz2 = (LPCWSTR) sz2;
  2038. _TRY_(ContextAndTwoStringW_Call_Encode(h, &ContextAndTwoStringCallW))
  2039. }
  2040. else
  2041. {
  2042. ContextAndTwoStringCallA.sz1 = (LPCSTR) sz1;
  2043. ContextAndTwoStringCallA.sz2 = (LPCSTR) sz2;
  2044. _TRY_(ContextAndTwoStringA_Call_Encode(h, &ContextAndTwoStringCallA))
  2045. }
  2046. //
  2047. // Make the call to the client
  2048. //
  2049. Status = _SendSCardIOCTL(
  2050. IoControlCode,
  2051. pbEncodedBuffer,
  2052. cbEncodedBuffer,
  2053. &pOutputBuffer);
  2054. if (Status != STATUS_SUCCESS)
  2055. {
  2056. MesHandleFree(h);
  2057. ERROR_RETURN(_MakeSCardError(Status))
  2058. }
  2059. //
  2060. // Decode the return
  2061. //
  2062. lReturn = I_DecodeLongReturn(pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed);
  2063. Return:
  2064. SafeMesHandleFree(&h);
  2065. MIDL_user_free(pbEncodedBuffer);
  2066. FreeBuffer(pOutputBuffer);
  2067. return (lReturn);
  2068. ErrorReturn:
  2069. goto Return;
  2070. }
  2071. //---------------------------------------------------------------------------------------
  2072. //
  2073. // SCardIntroduceReader
  2074. //
  2075. //---------------------------------------------------------------------------------------
  2076. WINSCARDAPI LONG WINAPI
  2077. SCardIntroduceReaderA(
  2078. IN SCARDCONTEXT hContext,
  2079. IN LPCSTR szReaderName,
  2080. IN LPCSTR szDeviceName)
  2081. {
  2082. return (I_ContextAndTwoStringCallWithLongReturn(
  2083. hContext,
  2084. (LPCBYTE) szReaderName,
  2085. (LPCBYTE) szDeviceName,
  2086. FALSE,
  2087. SCARD_IOCTL_INTRODUCEREADERA));
  2088. }
  2089. WINSCARDAPI LONG WINAPI
  2090. SCardIntroduceReaderW(
  2091. IN SCARDCONTEXT hContext,
  2092. IN LPCWSTR szReaderName,
  2093. IN LPCWSTR szDeviceName)
  2094. {
  2095. return (I_ContextAndTwoStringCallWithLongReturn(
  2096. hContext,
  2097. (LPCBYTE) szReaderName,
  2098. (LPCBYTE) szDeviceName,
  2099. TRUE,
  2100. SCARD_IOCTL_INTRODUCEREADERW));
  2101. }
  2102. //---------------------------------------------------------------------------------------
  2103. //
  2104. // SCardForgetReader
  2105. //
  2106. //---------------------------------------------------------------------------------------
  2107. WINSCARDAPI LONG WINAPI
  2108. SCardForgetReaderA(
  2109. IN SCARDCONTEXT hContext,
  2110. IN LPCSTR szReaderName)
  2111. {
  2112. return (I_ContextAndStringCallWithLongReturn(
  2113. hContext,
  2114. (LPCBYTE) szReaderName,
  2115. FALSE,
  2116. SCARD_IOCTL_FORGETREADERA));
  2117. }
  2118. WINSCARDAPI LONG WINAPI
  2119. SCardForgetReaderW(
  2120. IN SCARDCONTEXT hContext,
  2121. IN LPCWSTR szReaderName)
  2122. {
  2123. return (I_ContextAndStringCallWithLongReturn(
  2124. hContext,
  2125. (LPCBYTE) szReaderName,
  2126. TRUE,
  2127. SCARD_IOCTL_FORGETREADERW));
  2128. }
  2129. //---------------------------------------------------------------------------------------
  2130. //
  2131. // SCardAddReaderToGroup
  2132. //
  2133. //---------------------------------------------------------------------------------------
  2134. WINSCARDAPI LONG WINAPI
  2135. SCardAddReaderToGroupA(
  2136. IN SCARDCONTEXT hContext,
  2137. IN LPCSTR szReaderName,
  2138. IN LPCSTR szGroupName)
  2139. {
  2140. return (I_ContextAndTwoStringCallWithLongReturn(
  2141. hContext,
  2142. (LPCBYTE) szReaderName,
  2143. (LPCBYTE) szGroupName,
  2144. FALSE,
  2145. SCARD_IOCTL_ADDREADERTOGROUPA));
  2146. }
  2147. WINSCARDAPI LONG WINAPI
  2148. SCardAddReaderToGroupW(
  2149. IN SCARDCONTEXT hContext,
  2150. IN LPCWSTR szReaderName,
  2151. IN LPCWSTR szGroupName)
  2152. {
  2153. return (I_ContextAndTwoStringCallWithLongReturn(
  2154. hContext,
  2155. (LPCBYTE) szReaderName,
  2156. (LPCBYTE) szGroupName,
  2157. TRUE,
  2158. SCARD_IOCTL_ADDREADERTOGROUPW));
  2159. }
  2160. //---------------------------------------------------------------------------------------
  2161. //
  2162. // SCardRemoveReaderFromGroup
  2163. //
  2164. //---------------------------------------------------------------------------------------
  2165. WINSCARDAPI LONG WINAPI
  2166. SCardRemoveReaderFromGroupA(
  2167. IN SCARDCONTEXT hContext,
  2168. IN LPCSTR szReaderName,
  2169. IN LPCSTR szGroupName)
  2170. {
  2171. return (I_ContextAndTwoStringCallWithLongReturn(
  2172. hContext,
  2173. (LPCBYTE) szReaderName,
  2174. (LPCBYTE) szGroupName,
  2175. FALSE,
  2176. SCARD_IOCTL_REMOVEREADERFROMGROUPA));
  2177. }
  2178. WINSCARDAPI LONG WINAPI
  2179. SCardRemoveReaderFromGroupW(
  2180. IN SCARDCONTEXT hContext,
  2181. IN LPCWSTR szReaderName,
  2182. IN LPCWSTR szGroupName)
  2183. {
  2184. return (I_ContextAndTwoStringCallWithLongReturn(
  2185. hContext,
  2186. (LPCBYTE) szReaderName,
  2187. (LPCBYTE) szGroupName,
  2188. TRUE,
  2189. SCARD_IOCTL_REMOVEREADERFROMGROUPW));
  2190. }
  2191. //---------------------------------------------------------------------------------------
  2192. //
  2193. // _AllocAndCopyReaderState*StructsForCall and _CopyReaderState*StructsForReturn
  2194. //
  2195. //---------------------------------------------------------------------------------------
  2196. LONG
  2197. _AllocAndCopyReaderStateAStructsForCall(
  2198. DWORD cReaders,
  2199. ReaderStateA **prgReaderStatesToEncodeA,
  2200. LPSCARD_READERSTATE_A rgReaderStates)
  2201. {
  2202. DWORD i;
  2203. ReaderStateA *rgAlloced;
  2204. rgAlloced = (ReaderStateA *)
  2205. MIDL_user_allocate(cReaders * sizeof(ReaderStateA));
  2206. if (rgAlloced == NULL)
  2207. {
  2208. return (SCARD_E_NO_MEMORY);
  2209. }
  2210. for (i=0; i<cReaders; i++)
  2211. {
  2212. rgAlloced[i].Common.dwCurrentState =
  2213. rgReaderStates[i].dwCurrentState;
  2214. rgAlloced[i].Common.dwEventState =
  2215. rgReaderStates[i].dwEventState;
  2216. rgAlloced[i].Common.cbAtr =
  2217. rgReaderStates[i].cbAtr;
  2218. memcpy(
  2219. rgAlloced[i].Common.rgbAtr,
  2220. rgReaderStates[i].rgbAtr,
  2221. 36);
  2222. rgAlloced[i].szReader =
  2223. rgReaderStates[i].szReader;
  2224. }
  2225. *prgReaderStatesToEncodeA = rgAlloced;
  2226. return (SCARD_S_SUCCESS);
  2227. }
  2228. LONG
  2229. _AllocAndCopyReaderStateWStructsForCall(
  2230. DWORD cReaders,
  2231. ReaderStateW **prgReaderStatesToEncodeW,
  2232. LPSCARD_READERSTATE_W rgReaderStates)
  2233. {
  2234. DWORD i;
  2235. ReaderStateW *rgAlloced;
  2236. rgAlloced = (ReaderStateW *)
  2237. MIDL_user_allocate(cReaders * sizeof(ReaderStateW));
  2238. if (rgAlloced == NULL)
  2239. {
  2240. return (SCARD_E_NO_MEMORY);
  2241. }
  2242. for (i=0; i<cReaders; i++)
  2243. {
  2244. rgAlloced[i].Common.dwCurrentState =
  2245. rgReaderStates[i].dwCurrentState;
  2246. rgAlloced[i].Common.dwEventState =
  2247. rgReaderStates[i].dwEventState;
  2248. rgAlloced[i].Common.cbAtr =
  2249. rgReaderStates[i].cbAtr;
  2250. memcpy(
  2251. rgAlloced[i].Common.rgbAtr,
  2252. rgReaderStates[i].rgbAtr,
  2253. 36);
  2254. rgAlloced[i].szReader =
  2255. rgReaderStates[i].szReader;
  2256. }
  2257. *prgReaderStatesToEncodeW = rgAlloced;
  2258. return (SCARD_S_SUCCESS);
  2259. }
  2260. void
  2261. _CopyReaderStateAStructsForReturn(
  2262. DWORD cReaders,
  2263. LPSCARD_READERSTATE_A rgReaderStates,
  2264. ReaderState_Return *rgReaderStatesReturned)
  2265. {
  2266. DWORD i;
  2267. for (i=0; i<cReaders; i++)
  2268. {
  2269. rgReaderStates[i].dwCurrentState =
  2270. rgReaderStatesReturned[i].dwCurrentState;
  2271. rgReaderStates[i].dwEventState =
  2272. rgReaderStatesReturned[i].dwEventState;
  2273. rgReaderStates[i].cbAtr =
  2274. rgReaderStatesReturned[i].cbAtr;
  2275. memcpy(
  2276. rgReaderStates[i].rgbAtr,
  2277. rgReaderStatesReturned[i].rgbAtr,
  2278. 36);
  2279. }
  2280. }
  2281. void
  2282. _CopyReaderStateWStructsForReturn(
  2283. DWORD cReaders,
  2284. LPSCARD_READERSTATE_W rgReaderStates,
  2285. ReaderState_Return *rgReaderStatesReturned)
  2286. {
  2287. DWORD i;
  2288. for (i=0; i<cReaders; i++)
  2289. {
  2290. rgReaderStates[i].dwCurrentState =
  2291. rgReaderStatesReturned[i].dwCurrentState;
  2292. rgReaderStates[i].dwEventState =
  2293. rgReaderStatesReturned[i].dwEventState;
  2294. rgReaderStates[i].cbAtr =
  2295. rgReaderStatesReturned[i].cbAtr;
  2296. memcpy(
  2297. rgReaderStates[i].rgbAtr,
  2298. rgReaderStatesReturned[i].rgbAtr,
  2299. 36);
  2300. }
  2301. }
  2302. //---------------------------------------------------------------------------------------
  2303. //
  2304. // _AllocAndCopyATRMasksForCall
  2305. //
  2306. //---------------------------------------------------------------------------------------
  2307. LONG
  2308. _AllocAndCopyATRMasksForCall(
  2309. DWORD cAtrs,
  2310. LocateCards_ATRMask **prgATRMasksToEncode,
  2311. LPSCARD_ATRMASK rgAtrMasks)
  2312. {
  2313. DWORD i;
  2314. LocateCards_ATRMask *rgAlloced;
  2315. rgAlloced = (LocateCards_ATRMask *)
  2316. MIDL_user_allocate(cAtrs * sizeof(LocateCards_ATRMask));
  2317. if (rgAlloced == NULL)
  2318. {
  2319. return (SCARD_E_NO_MEMORY);
  2320. }
  2321. for (i=0; i<cAtrs; i++)
  2322. {
  2323. rgAlloced[i].cbAtr = rgAtrMasks[i].cbAtr;
  2324. memcpy(
  2325. rgAlloced[i].rgbAtr,
  2326. rgAtrMasks[i].rgbAtr,
  2327. 36);
  2328. memcpy(
  2329. rgAlloced[i].rgbMask,
  2330. rgAtrMasks[i].rgbMask,
  2331. 36);
  2332. }
  2333. *prgATRMasksToEncode = rgAlloced;
  2334. return (SCARD_S_SUCCESS);
  2335. }
  2336. //---------------------------------------------------------------------------------------
  2337. //
  2338. // SCardLocateCardsA
  2339. //
  2340. //---------------------------------------------------------------------------------------
  2341. WINSCARDAPI LONG WINAPI
  2342. SCardLocateCardsA(
  2343. IN SCARDCONTEXT hContext,
  2344. IN LPCSTR mszCards,
  2345. IN OUT LPSCARD_READERSTATE_A rgReaderStates,
  2346. IN DWORD cReaders)
  2347. {
  2348. LONG lReturn = SCARD_S_SUCCESS;
  2349. NTSTATUS Status = STATUS_SUCCESS;
  2350. RPC_STATUS rpcStatus = RPC_S_OK;
  2351. char *pbEncodedBuffer = NULL;
  2352. unsigned long cbEncodedBuffer = 0;
  2353. handle_t h = 0;
  2354. LocateCardsA_Call LocateCardsCallA;
  2355. LocateCards_Return LocateCardsReturn;
  2356. ReaderStateA *rgReaderStatesToEncodeA = NULL;
  2357. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  2358. DWORD i;
  2359. if (hContext == NULL)
  2360. {
  2361. return (SCARD_E_INVALID_PARAMETER);
  2362. }
  2363. else if (mszCards == NULL)
  2364. {
  2365. return (SCARD_E_INVALID_VALUE);
  2366. }
  2367. //
  2368. // Initialize encoding handle
  2369. //
  2370. rpcStatus = MesEncodeDynBufferHandleCreate(
  2371. &pbEncodedBuffer,
  2372. &cbEncodedBuffer,
  2373. &h);
  2374. if (rpcStatus != RPC_S_OK)
  2375. {
  2376. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2377. }
  2378. //
  2379. // Encode the LocateCards params
  2380. //
  2381. LocateCardsCallA.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context;
  2382. LocateCardsCallA.cBytes = _CalculateNumBytesInMultiStringA(mszCards);
  2383. LocateCardsCallA.mszCards = (LPCBYTE) mszCards;
  2384. LocateCardsCallA.cReaders = cReaders;
  2385. lReturn = _AllocAndCopyReaderStateAStructsForCall(
  2386. cReaders,
  2387. &rgReaderStatesToEncodeA,
  2388. rgReaderStates);
  2389. if (lReturn != SCARD_S_SUCCESS)
  2390. {
  2391. ERROR_RETURN(SCARD_E_NO_MEMORY)
  2392. }
  2393. LocateCardsCallA.rgReaderStates = rgReaderStatesToEncodeA;
  2394. _TRY_(LocateCardsA_Call_Encode(h, &LocateCardsCallA))
  2395. //
  2396. // Make the LocateCards call to the client
  2397. //
  2398. Status = _SendSCardIOCTL(
  2399. SCARD_IOCTL_LOCATECARDSA,
  2400. pbEncodedBuffer,
  2401. cbEncodedBuffer,
  2402. &pOutputBuffer);
  2403. if (Status != STATUS_SUCCESS)
  2404. {
  2405. ERROR_RETURN(_MakeSCardError(Status))
  2406. }
  2407. SafeMesHandleFree(&h);
  2408. //
  2409. // Decode the return
  2410. //
  2411. rpcStatus = MesDecodeBufferHandleCreate(
  2412. (char *) pOutputBuffer->pbBytes,
  2413. pOutputBuffer->cbBytesUsed,
  2414. &h);
  2415. if (rpcStatus != RPC_S_OK)
  2416. {
  2417. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2418. }
  2419. memset(&LocateCardsReturn, 0 , sizeof(LocateCardsReturn));
  2420. _TRY_(LocateCards_Return_Decode(h, &LocateCardsReturn))
  2421. lReturn = LocateCardsReturn.ReturnCode;
  2422. if (lReturn == SCARD_S_SUCCESS)
  2423. {
  2424. //
  2425. // Validate return info
  2426. //
  2427. if (cReaders != LocateCardsReturn.cReaders)
  2428. {
  2429. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2430. }
  2431. _CopyReaderStateAStructsForReturn(
  2432. cReaders,
  2433. rgReaderStates,
  2434. LocateCardsReturn.rgReaderStates);
  2435. }
  2436. _TRY_2(LocateCards_Return_Free(h, &LocateCardsReturn))
  2437. Return:
  2438. SafeMesHandleFree(&h);
  2439. MIDL_user_free(pbEncodedBuffer);
  2440. MIDL_user_free(rgReaderStatesToEncodeA);
  2441. FreeBuffer(pOutputBuffer);
  2442. return (lReturn);
  2443. ErrorReturn:
  2444. goto Return;
  2445. }
  2446. //---------------------------------------------------------------------------------------
  2447. //
  2448. // SCardLocateCardsW
  2449. //
  2450. //---------------------------------------------------------------------------------------
  2451. WINSCARDAPI LONG WINAPI
  2452. SCardLocateCardsW(
  2453. IN SCARDCONTEXT hContext,
  2454. IN LPCWSTR mszCards,
  2455. IN OUT LPSCARD_READERSTATE_W rgReaderStates,
  2456. IN DWORD cReaders)
  2457. {
  2458. LONG lReturn = SCARD_S_SUCCESS;
  2459. NTSTATUS Status = STATUS_SUCCESS;
  2460. RPC_STATUS rpcStatus = RPC_S_OK;
  2461. char *pbEncodedBuffer = NULL;
  2462. unsigned long cbEncodedBuffer = 0;
  2463. handle_t h = 0;
  2464. LocateCardsW_Call LocateCardsCallW;
  2465. LocateCards_Return LocateCardsReturn;
  2466. ReaderStateW *rgReaderStatesToEncodeW = NULL;
  2467. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  2468. DWORD i;
  2469. if (hContext == NULL)
  2470. {
  2471. return (SCARD_E_INVALID_PARAMETER);
  2472. }
  2473. else if (mszCards == NULL)
  2474. {
  2475. return (SCARD_E_INVALID_VALUE);
  2476. }
  2477. //
  2478. // Initialize encoding handle
  2479. //
  2480. rpcStatus = MesEncodeDynBufferHandleCreate(
  2481. &pbEncodedBuffer,
  2482. &cbEncodedBuffer,
  2483. &h);
  2484. if (rpcStatus != RPC_S_OK)
  2485. {
  2486. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2487. }
  2488. //
  2489. // Encode the LocateCards params
  2490. //
  2491. LocateCardsCallW.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context;
  2492. LocateCardsCallW.cBytes = _CalculateNumBytesInMultiStringW(mszCards);
  2493. LocateCardsCallW.mszCards = (LPCBYTE) mszCards;
  2494. LocateCardsCallW.cReaders = cReaders;
  2495. lReturn = _AllocAndCopyReaderStateWStructsForCall(
  2496. cReaders,
  2497. &rgReaderStatesToEncodeW,
  2498. rgReaderStates);
  2499. if (lReturn != SCARD_S_SUCCESS)
  2500. {
  2501. ERROR_RETURN(SCARD_E_NO_MEMORY)
  2502. }
  2503. LocateCardsCallW.rgReaderStates = rgReaderStatesToEncodeW;
  2504. _TRY_(LocateCardsW_Call_Encode(h, &LocateCardsCallW))
  2505. //
  2506. // Make the LocateCards call to the client
  2507. //
  2508. Status = _SendSCardIOCTL(
  2509. SCARD_IOCTL_LOCATECARDSW,
  2510. pbEncodedBuffer,
  2511. cbEncodedBuffer,
  2512. &pOutputBuffer);
  2513. if (Status != STATUS_SUCCESS)
  2514. {
  2515. ERROR_RETURN(_MakeSCardError(Status))
  2516. }
  2517. SafeMesHandleFree(&h);
  2518. //
  2519. // Decode the return
  2520. //
  2521. rpcStatus = MesDecodeBufferHandleCreate(
  2522. (char *) pOutputBuffer->pbBytes,
  2523. pOutputBuffer->cbBytesUsed,
  2524. &h);
  2525. if (rpcStatus != RPC_S_OK)
  2526. {
  2527. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2528. }
  2529. memset(&LocateCardsReturn, 0, sizeof(LocateCardsReturn));
  2530. _TRY_(LocateCards_Return_Decode(h, &LocateCardsReturn))
  2531. lReturn = LocateCardsReturn.ReturnCode;
  2532. if (lReturn == SCARD_S_SUCCESS)
  2533. {
  2534. //
  2535. // Validate return info
  2536. //
  2537. if (cReaders != LocateCardsReturn.cReaders)
  2538. {
  2539. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2540. }
  2541. _CopyReaderStateWStructsForReturn(
  2542. cReaders,
  2543. rgReaderStates,
  2544. LocateCardsReturn.rgReaderStates);
  2545. }
  2546. _TRY_2(LocateCards_Return_Free(h, &LocateCardsReturn))
  2547. Return:
  2548. SafeMesHandleFree(&h);
  2549. MIDL_user_free(pbEncodedBuffer);
  2550. MIDL_user_free(rgReaderStatesToEncodeW);
  2551. FreeBuffer(pOutputBuffer);
  2552. return (lReturn);
  2553. ErrorReturn:
  2554. goto Return;
  2555. }
  2556. //---------------------------------------------------------------------------------------
  2557. //
  2558. // SCardLocateCardsByATRA
  2559. //
  2560. //---------------------------------------------------------------------------------------
  2561. WINSCARDAPI LONG WINAPI
  2562. SCardLocateCardsByATRA(
  2563. IN SCARDCONTEXT hContext,
  2564. IN LPSCARD_ATRMASK rgAtrMasks,
  2565. IN DWORD cAtrs,
  2566. IN OUT LPSCARD_READERSTATE_A rgReaderStates,
  2567. IN DWORD cReaders)
  2568. {
  2569. LONG lReturn = SCARD_S_SUCCESS;
  2570. NTSTATUS Status = STATUS_SUCCESS;
  2571. RPC_STATUS rpcStatus = RPC_S_OK;
  2572. char *pbEncodedBuffer = NULL;
  2573. unsigned long cbEncodedBuffer = 0;
  2574. handle_t h = 0;
  2575. LocateCardsByATRA_Call LocateCardsByATRA_Call;
  2576. LocateCards_ATRMask *rgATRMasksToEncode = NULL;
  2577. LocateCards_Return LocateCardsReturn;
  2578. ReaderStateA *rgReaderStatesToEncodeA = NULL;
  2579. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  2580. DWORD i;
  2581. if (hContext == NULL)
  2582. {
  2583. return (SCARD_E_INVALID_PARAMETER);
  2584. }
  2585. //
  2586. // Initialize encoding handle
  2587. //
  2588. rpcStatus = MesEncodeDynBufferHandleCreate(
  2589. &pbEncodedBuffer,
  2590. &cbEncodedBuffer,
  2591. &h);
  2592. if (rpcStatus != RPC_S_OK)
  2593. {
  2594. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2595. }
  2596. //
  2597. // Encode the LocateCards params
  2598. //
  2599. LocateCardsByATRA_Call.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context;
  2600. LocateCardsByATRA_Call.cAtrs = cAtrs;
  2601. LocateCardsByATRA_Call.cReaders = cReaders;
  2602. lReturn = _AllocAndCopyATRMasksForCall(
  2603. cAtrs,
  2604. &rgATRMasksToEncode,
  2605. rgAtrMasks);
  2606. if (lReturn != SCARD_S_SUCCESS)
  2607. {
  2608. ERROR_RETURN(SCARD_E_NO_MEMORY)
  2609. }
  2610. LocateCardsByATRA_Call.rgAtrMasks = rgATRMasksToEncode;
  2611. lReturn = _AllocAndCopyReaderStateAStructsForCall(
  2612. cReaders,
  2613. &rgReaderStatesToEncodeA,
  2614. rgReaderStates);
  2615. if (lReturn != SCARD_S_SUCCESS)
  2616. {
  2617. ERROR_RETURN(SCARD_E_NO_MEMORY)
  2618. }
  2619. LocateCardsByATRA_Call.rgReaderStates = rgReaderStatesToEncodeA;
  2620. _TRY_(LocateCardsByATRA_Call_Encode(h, &LocateCardsByATRA_Call))
  2621. //
  2622. // Make the LocateCards call to the client
  2623. //
  2624. Status = _SendSCardIOCTL(
  2625. SCARD_IOCTL_LOCATECARDSBYATRA,
  2626. pbEncodedBuffer,
  2627. cbEncodedBuffer,
  2628. &pOutputBuffer);
  2629. if (Status != STATUS_SUCCESS)
  2630. {
  2631. ERROR_RETURN(_MakeSCardError(Status))
  2632. }
  2633. SafeMesHandleFree(&h);
  2634. //
  2635. // Decode the return
  2636. //
  2637. rpcStatus = MesDecodeBufferHandleCreate(
  2638. (char *) pOutputBuffer->pbBytes,
  2639. pOutputBuffer->cbBytesUsed,
  2640. &h);
  2641. if (rpcStatus != RPC_S_OK)
  2642. {
  2643. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2644. }
  2645. memset(&LocateCardsReturn, 0 , sizeof(LocateCardsReturn));
  2646. _TRY_(LocateCards_Return_Decode(h, &LocateCardsReturn))
  2647. lReturn = LocateCardsReturn.ReturnCode;
  2648. if (lReturn == SCARD_S_SUCCESS)
  2649. {
  2650. //
  2651. // Validate return info
  2652. //
  2653. if (cReaders != LocateCardsReturn.cReaders)
  2654. {
  2655. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2656. }
  2657. _CopyReaderStateAStructsForReturn(
  2658. cReaders,
  2659. rgReaderStates,
  2660. LocateCardsReturn.rgReaderStates);
  2661. }
  2662. _TRY_2(LocateCards_Return_Free(h, &LocateCardsReturn))
  2663. Return:
  2664. SafeMesHandleFree(&h);
  2665. MIDL_user_free(pbEncodedBuffer);
  2666. MIDL_user_free(rgATRMasksToEncode);
  2667. MIDL_user_free(rgReaderStatesToEncodeA);
  2668. FreeBuffer(pOutputBuffer);
  2669. return (lReturn);
  2670. ErrorReturn:
  2671. goto Return;
  2672. }
  2673. //---------------------------------------------------------------------------------------
  2674. //
  2675. // SCardLocateCardsByATRW
  2676. //
  2677. //---------------------------------------------------------------------------------------
  2678. WINSCARDAPI LONG WINAPI
  2679. SCardLocateCardsByATRW(
  2680. IN SCARDCONTEXT hContext,
  2681. IN LPSCARD_ATRMASK rgAtrMasks,
  2682. IN DWORD cAtrs,
  2683. IN OUT LPSCARD_READERSTATE_W rgReaderStates,
  2684. IN DWORD cReaders)
  2685. {
  2686. LONG lReturn = SCARD_S_SUCCESS;
  2687. NTSTATUS Status = STATUS_SUCCESS;
  2688. RPC_STATUS rpcStatus = RPC_S_OK;
  2689. char *pbEncodedBuffer = NULL;
  2690. unsigned long cbEncodedBuffer = 0;
  2691. handle_t h = 0;
  2692. LocateCardsByATRW_Call LocateCardsByATRW_Call;
  2693. LocateCards_ATRMask *rgATRMasksToEncode = NULL;
  2694. LocateCards_Return LocateCardsReturn;
  2695. ReaderStateW *rgReaderStatesToEncodeW = NULL;
  2696. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  2697. DWORD i;
  2698. if (hContext == NULL)
  2699. {
  2700. return (SCARD_E_INVALID_PARAMETER);
  2701. }
  2702. //
  2703. // Initialize encoding handle
  2704. //
  2705. rpcStatus = MesEncodeDynBufferHandleCreate(
  2706. &pbEncodedBuffer,
  2707. &cbEncodedBuffer,
  2708. &h);
  2709. if (rpcStatus != RPC_S_OK)
  2710. {
  2711. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2712. }
  2713. //
  2714. // Encode the LocateCards params
  2715. //
  2716. LocateCardsByATRW_Call.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context;
  2717. LocateCardsByATRW_Call.cAtrs = cAtrs;
  2718. LocateCardsByATRW_Call.cReaders = cReaders;
  2719. lReturn = _AllocAndCopyATRMasksForCall(
  2720. cAtrs,
  2721. &rgATRMasksToEncode,
  2722. rgAtrMasks);
  2723. if (lReturn != SCARD_S_SUCCESS)
  2724. {
  2725. ERROR_RETURN(SCARD_E_NO_MEMORY)
  2726. }
  2727. LocateCardsByATRW_Call.rgAtrMasks = rgATRMasksToEncode;
  2728. lReturn = _AllocAndCopyReaderStateWStructsForCall(
  2729. cReaders,
  2730. &rgReaderStatesToEncodeW,
  2731. rgReaderStates);
  2732. if (lReturn != SCARD_S_SUCCESS)
  2733. {
  2734. ERROR_RETURN(SCARD_E_NO_MEMORY)
  2735. }
  2736. LocateCardsByATRW_Call.rgReaderStates = rgReaderStatesToEncodeW;
  2737. _TRY_(LocateCardsByATRW_Call_Encode(h, &LocateCardsByATRW_Call))
  2738. //
  2739. // Make the LocateCards call to the client
  2740. //
  2741. Status = _SendSCardIOCTL(
  2742. SCARD_IOCTL_LOCATECARDSBYATRW,
  2743. pbEncodedBuffer,
  2744. cbEncodedBuffer,
  2745. &pOutputBuffer);
  2746. if (Status != STATUS_SUCCESS)
  2747. {
  2748. ERROR_RETURN(_MakeSCardError(Status))
  2749. }
  2750. SafeMesHandleFree(&h);
  2751. //
  2752. // Decode the return
  2753. //
  2754. rpcStatus = MesDecodeBufferHandleCreate(
  2755. (char *) pOutputBuffer->pbBytes,
  2756. pOutputBuffer->cbBytesUsed,
  2757. &h);
  2758. if (rpcStatus != RPC_S_OK)
  2759. {
  2760. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2761. }
  2762. memset(&LocateCardsReturn, 0 , sizeof(LocateCardsReturn));
  2763. _TRY_(LocateCards_Return_Decode(h, &LocateCardsReturn))
  2764. lReturn = LocateCardsReturn.ReturnCode;
  2765. if (lReturn == SCARD_S_SUCCESS)
  2766. {
  2767. //
  2768. // Validate return info
  2769. //
  2770. if (cReaders != LocateCardsReturn.cReaders)
  2771. {
  2772. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2773. }
  2774. _CopyReaderStateWStructsForReturn(
  2775. cReaders,
  2776. rgReaderStates,
  2777. LocateCardsReturn.rgReaderStates);
  2778. }
  2779. _TRY_2(LocateCards_Return_Free(h, &LocateCardsReturn))
  2780. Return:
  2781. SafeMesHandleFree(&h);
  2782. MIDL_user_free(pbEncodedBuffer);
  2783. MIDL_user_free(rgATRMasksToEncode);
  2784. MIDL_user_free(rgReaderStatesToEncodeW);
  2785. FreeBuffer(pOutputBuffer);
  2786. return (lReturn);
  2787. ErrorReturn:
  2788. goto Return;
  2789. }
  2790. //---------------------------------------------------------------------------------------
  2791. //
  2792. // SCardGetStatusChangeA
  2793. //
  2794. //---------------------------------------------------------------------------------------
  2795. WINSCARDAPI LONG WINAPI
  2796. SCardGetStatusChangeA(
  2797. IN SCARDCONTEXT hContext,
  2798. IN DWORD dwTimeout,
  2799. IN OUT LPSCARD_READERSTATE_A rgReaderStates,
  2800. IN DWORD cReaders)
  2801. {
  2802. LONG lReturn = SCARD_S_SUCCESS;
  2803. NTSTATUS Status = STATUS_SUCCESS;
  2804. RPC_STATUS rpcStatus = RPC_S_OK;
  2805. char *pbEncodedBuffer = NULL;
  2806. unsigned long cbEncodedBuffer = 0;
  2807. handle_t h = 0;
  2808. GetStatusChangeA_Call GetStatusChangeCallA;
  2809. GetStatusChange_Return GetStatusChangeReturn;
  2810. ReaderStateA *rgReaderStatesToEncodeA = NULL;
  2811. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  2812. DWORD i;
  2813. if (hContext == NULL)
  2814. {
  2815. return (SCARD_E_INVALID_PARAMETER);
  2816. }
  2817. //
  2818. // Initialize encoding handle
  2819. //
  2820. rpcStatus = MesEncodeDynBufferHandleCreate(
  2821. &pbEncodedBuffer,
  2822. &cbEncodedBuffer,
  2823. &h);
  2824. if (rpcStatus != RPC_S_OK)
  2825. {
  2826. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2827. }
  2828. //
  2829. // Encode the LocateCards params
  2830. //
  2831. GetStatusChangeCallA.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context;
  2832. GetStatusChangeCallA.dwTimeOut = dwTimeout;
  2833. GetStatusChangeCallA.cReaders = cReaders;
  2834. lReturn = _AllocAndCopyReaderStateAStructsForCall(
  2835. cReaders,
  2836. &rgReaderStatesToEncodeA,
  2837. rgReaderStates);
  2838. if (lReturn != SCARD_S_SUCCESS)
  2839. {
  2840. ERROR_RETURN(SCARD_E_NO_MEMORY)
  2841. }
  2842. GetStatusChangeCallA.rgReaderStates = rgReaderStatesToEncodeA;
  2843. _TRY_(GetStatusChangeA_Call_Encode(h, &GetStatusChangeCallA))
  2844. //
  2845. // Make the GetStatusChange call to the client
  2846. //
  2847. Status = _SendSCardIOCTL(
  2848. SCARD_IOCTL_GETSTATUSCHANGEA,
  2849. pbEncodedBuffer,
  2850. cbEncodedBuffer,
  2851. &pOutputBuffer);
  2852. if (Status != STATUS_SUCCESS)
  2853. {
  2854. ERROR_RETURN(_MakeSCardError(Status))
  2855. }
  2856. SafeMesHandleFree(&h);
  2857. //
  2858. // Decode the return
  2859. //
  2860. rpcStatus = MesDecodeBufferHandleCreate(
  2861. (char *) pOutputBuffer->pbBytes,
  2862. pOutputBuffer->cbBytesUsed,
  2863. &h);
  2864. if (rpcStatus != RPC_S_OK)
  2865. {
  2866. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2867. }
  2868. memset(&GetStatusChangeReturn, 0, sizeof(GetStatusChangeReturn));
  2869. _TRY_(GetStatusChange_Return_Decode(h, &GetStatusChangeReturn))
  2870. lReturn = GetStatusChangeReturn.ReturnCode;
  2871. if (lReturn == SCARD_S_SUCCESS)
  2872. {
  2873. //
  2874. // Validate return info
  2875. //
  2876. if (cReaders != GetStatusChangeReturn.cReaders)
  2877. {
  2878. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2879. }
  2880. _CopyReaderStateAStructsForReturn(
  2881. cReaders,
  2882. rgReaderStates,
  2883. GetStatusChangeReturn.rgReaderStates);
  2884. }
  2885. else if ((lReturn == SCARD_E_SYSTEM_CANCELLED) &&
  2886. (g_hUnifiedStartedEvent != NULL))
  2887. {
  2888. //
  2889. // This error indicates that the clients scardsvr service has been stopped,
  2890. // so reset the unified started event
  2891. //
  2892. //OutputDebugString("SCREDIR: SCardGetStatusChangeA: resetting g_hUnifiedStartedEvent\n");
  2893. ResetEvent(g_hUnifiedStartedEvent);
  2894. _SetStartedEventToCorrectState();
  2895. }
  2896. _TRY_2(GetStatusChange_Return_Free(h, &GetStatusChangeReturn))
  2897. Return:
  2898. SafeMesHandleFree(&h);
  2899. MIDL_user_free(pbEncodedBuffer);
  2900. MIDL_user_free(rgReaderStatesToEncodeA);
  2901. FreeBuffer(pOutputBuffer);
  2902. return (lReturn);
  2903. ErrorReturn:
  2904. goto Return;
  2905. }
  2906. //---------------------------------------------------------------------------------------
  2907. //
  2908. // SCardGetStatusChangew
  2909. //
  2910. //---------------------------------------------------------------------------------------
  2911. WINSCARDAPI LONG WINAPI
  2912. SCardGetStatusChangeW(
  2913. IN SCARDCONTEXT hContext,
  2914. IN DWORD dwTimeout,
  2915. IN OUT LPSCARD_READERSTATE_W rgReaderStates,
  2916. IN DWORD cReaders)
  2917. {
  2918. LONG lReturn = SCARD_S_SUCCESS;
  2919. NTSTATUS Status = STATUS_SUCCESS;
  2920. RPC_STATUS rpcStatus = RPC_S_OK;
  2921. char *pbEncodedBuffer = NULL;
  2922. unsigned long cbEncodedBuffer = 0;
  2923. handle_t h = 0;
  2924. GetStatusChangeW_Call GetStatusChangeCallW;
  2925. GetStatusChange_Return GetStatusChangeReturn;
  2926. ReaderStateW *rgReaderStatesToEncodeW = NULL;
  2927. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  2928. DWORD i;
  2929. if (hContext == NULL)
  2930. {
  2931. return (SCARD_E_INVALID_PARAMETER);
  2932. }
  2933. //
  2934. // Initialize encoding handle
  2935. //
  2936. rpcStatus = MesEncodeDynBufferHandleCreate(
  2937. &pbEncodedBuffer,
  2938. &cbEncodedBuffer,
  2939. &h);
  2940. if (rpcStatus != RPC_S_OK)
  2941. {
  2942. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2943. }
  2944. //
  2945. // Encode the LocateCards params
  2946. //
  2947. GetStatusChangeCallW.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context;
  2948. GetStatusChangeCallW.dwTimeOut = dwTimeout;
  2949. GetStatusChangeCallW.cReaders = cReaders;
  2950. lReturn = _AllocAndCopyReaderStateWStructsForCall(
  2951. cReaders,
  2952. &rgReaderStatesToEncodeW,
  2953. rgReaderStates);
  2954. if (lReturn != SCARD_S_SUCCESS)
  2955. {
  2956. ERROR_RETURN(SCARD_E_NO_MEMORY)
  2957. }
  2958. GetStatusChangeCallW.rgReaderStates = rgReaderStatesToEncodeW;
  2959. _TRY_(GetStatusChangeW_Call_Encode(h, &GetStatusChangeCallW))
  2960. //
  2961. // Make the GetStatusChange call to the client
  2962. //
  2963. Status = _SendSCardIOCTL(
  2964. SCARD_IOCTL_GETSTATUSCHANGEW,
  2965. pbEncodedBuffer,
  2966. cbEncodedBuffer,
  2967. &pOutputBuffer);
  2968. if (Status != STATUS_SUCCESS)
  2969. {
  2970. ERROR_RETURN(_MakeSCardError(Status))
  2971. }
  2972. SafeMesHandleFree(&h);
  2973. //
  2974. // Decode the return
  2975. //
  2976. rpcStatus = MesDecodeBufferHandleCreate(
  2977. (char *) pOutputBuffer->pbBytes,
  2978. pOutputBuffer->cbBytesUsed,
  2979. &h);
  2980. if (rpcStatus != RPC_S_OK)
  2981. {
  2982. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2983. }
  2984. memset(&GetStatusChangeReturn, 0, sizeof(GetStatusChangeReturn));
  2985. _TRY_(GetStatusChange_Return_Decode(h, &GetStatusChangeReturn))
  2986. lReturn = GetStatusChangeReturn.ReturnCode;
  2987. if (lReturn == SCARD_S_SUCCESS)
  2988. {
  2989. //
  2990. // Validate return info
  2991. //
  2992. if (cReaders != GetStatusChangeReturn.cReaders)
  2993. {
  2994. ERROR_RETURN(SCARD_E_UNEXPECTED)
  2995. }
  2996. _CopyReaderStateWStructsForReturn(
  2997. cReaders,
  2998. rgReaderStates,
  2999. GetStatusChangeReturn.rgReaderStates);
  3000. }
  3001. else if ((lReturn == SCARD_E_SYSTEM_CANCELLED) &&
  3002. (g_hUnifiedStartedEvent != NULL))
  3003. {
  3004. //
  3005. // This error indicates that the clients scardsvr service has been stopped,
  3006. // so reset the unified started event
  3007. //
  3008. //OutputDebugString("SCREDIR: SCardGetStatusChangeW: resetting g_hUnifiedStartedEvent\n");
  3009. ResetEvent(g_hUnifiedStartedEvent);
  3010. _SetStartedEventToCorrectState();
  3011. }
  3012. _TRY_2(GetStatusChange_Return_Free(h, &GetStatusChangeReturn))
  3013. Return:
  3014. SafeMesHandleFree(&h);
  3015. MIDL_user_free(pbEncodedBuffer);
  3016. MIDL_user_free(rgReaderStatesToEncodeW);
  3017. FreeBuffer(pOutputBuffer);
  3018. return (lReturn);
  3019. ErrorReturn:
  3020. goto Return;
  3021. }
  3022. WINSCARDAPI LONG WINAPI
  3023. SCardCancel(
  3024. IN SCARDCONTEXT hContext)
  3025. {
  3026. return (I_ContextCallWithLongReturn(
  3027. hContext,
  3028. SCARD_IOCTL_CANCEL));
  3029. }
  3030. //---------------------------------------------------------------------------------------
  3031. //
  3032. // SCardConnect
  3033. //
  3034. //---------------------------------------------------------------------------------------
  3035. WINSCARDAPI LONG WINAPI
  3036. I_SCardConnect(
  3037. IN SCARDCONTEXT hContext,
  3038. IN LPCBYTE szReader,
  3039. IN DWORD dwShareMode,
  3040. IN DWORD dwPreferredProtocols,
  3041. OUT LPSCARDHANDLE phCard,
  3042. OUT LPDWORD pdwActiveProtocol,
  3043. IN BOOL fUnicode)
  3044. {
  3045. LONG lReturn = SCARD_S_SUCCESS;
  3046. NTSTATUS Status = STATUS_SUCCESS;
  3047. RPC_STATUS rpcStatus = RPC_S_OK;
  3048. char *pbEncodedBuffer = NULL;
  3049. unsigned long cbEncodedBuffer = 0;
  3050. handle_t h = 0;
  3051. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  3052. ConnectA_Call ConnectCallA;
  3053. ConnectW_Call ConnectCallW;
  3054. Connect_Return ConnectReturn;
  3055. if ((hContext == NULL) ||
  3056. (phCard == NULL) ||
  3057. (pdwActiveProtocol == NULL))
  3058. {
  3059. return (SCARD_E_INVALID_PARAMETER);
  3060. }
  3061. else if (szReader == NULL)
  3062. {
  3063. return (SCARD_E_INVALID_VALUE);
  3064. }
  3065. //
  3066. // Initialize encoding handle
  3067. //
  3068. rpcStatus = MesEncodeDynBufferHandleCreate(
  3069. &pbEncodedBuffer,
  3070. &cbEncodedBuffer,
  3071. &h);
  3072. if (rpcStatus != RPC_S_OK)
  3073. {
  3074. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3075. }
  3076. //
  3077. // Encode the Connect params
  3078. //
  3079. ConnectCallA.Common.Context =
  3080. ConnectCallW.Common.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context;
  3081. ConnectCallA.Common.dwShareMode =
  3082. ConnectCallW.Common.dwShareMode = dwShareMode;
  3083. ConnectCallA.Common.dwPreferredProtocols =
  3084. ConnectCallW.Common.dwPreferredProtocols = dwPreferredProtocols;
  3085. if (fUnicode)
  3086. {
  3087. ConnectCallW.szReader = (LPCWSTR) szReader;
  3088. _TRY_(ConnectW_Call_Encode(h, &ConnectCallW))
  3089. }
  3090. else
  3091. {
  3092. ConnectCallA.szReader = (LPCSTR) szReader;
  3093. _TRY_(ConnectA_Call_Encode(h, &ConnectCallA))
  3094. }
  3095. //
  3096. // Make the ListInterfaces call to the client
  3097. //
  3098. Status = _SendSCardIOCTL(
  3099. fUnicode ? SCARD_IOCTL_CONNECTW :
  3100. SCARD_IOCTL_CONNECTA,
  3101. pbEncodedBuffer,
  3102. cbEncodedBuffer,
  3103. &pOutputBuffer);
  3104. if (Status != STATUS_SUCCESS)
  3105. {
  3106. ERROR_RETURN(_MakeSCardError(Status))
  3107. }
  3108. SafeMesHandleFree(&h);
  3109. //
  3110. // Decode the return
  3111. //
  3112. rpcStatus = MesDecodeBufferHandleCreate(
  3113. (char *) pOutputBuffer->pbBytes,
  3114. pOutputBuffer->cbBytesUsed,
  3115. &h);
  3116. if (rpcStatus != RPC_S_OK)
  3117. {
  3118. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3119. }
  3120. memset(&ConnectReturn, 0, sizeof(ConnectReturn));
  3121. _TRY_(Connect_Return_Decode(h, &ConnectReturn))
  3122. lReturn = ConnectReturn.ReturnCode;
  3123. if (lReturn == SCARD_S_SUCCESS)
  3124. {
  3125. REDIR_LOCAL_SCARDHANDLE *pRedirHandle = NULL;
  3126. //
  3127. // The value that represents the SCARDHANDLE on the remote client
  3128. // machine is a variable size, so allocate memory to for the struct
  3129. // that holds the variable length handle size and pointer, plus
  3130. // the actual bytes for the handle, it also holds the context
  3131. //
  3132. if (ConnectReturn.hCard.cbHandle > MAX_SCARDHANDLE_SIZE)
  3133. {
  3134. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3135. }
  3136. pRedirHandle = (REDIR_LOCAL_SCARDHANDLE *)
  3137. MIDL_user_allocate(
  3138. sizeof(REDIR_LOCAL_SCARDHANDLE) +
  3139. ConnectReturn.hCard.cbHandle);
  3140. if (pRedirHandle != NULL)
  3141. {
  3142. pRedirHandle->pRedirContext = (REDIR_LOCAL_SCARDCONTEXT *) hContext;
  3143. pRedirHandle->Handle.Context = ((REDIR_LOCAL_SCARDCONTEXT *) hContext)->Context;
  3144. pRedirHandle->Handle.cbHandle = ConnectReturn.hCard.cbHandle;
  3145. pRedirHandle->Handle.pbHandle = ((BYTE *) pRedirHandle) +
  3146. sizeof(REDIR_LOCAL_SCARDHANDLE);
  3147. memcpy(
  3148. pRedirHandle->Handle.pbHandle,
  3149. ConnectReturn.hCard.pbHandle,
  3150. ConnectReturn.hCard.cbHandle);
  3151. *phCard = (SCARDHANDLE) pRedirHandle;
  3152. // The original Winscard API implements this parameter as
  3153. // Optional. We need to preserve that behavior.
  3154. if (NULL != pdwActiveProtocol)
  3155. *pdwActiveProtocol = ConnectReturn.dwActiveProtocol;
  3156. }
  3157. else
  3158. {
  3159. lReturn = SCARD_E_NO_MEMORY;
  3160. }
  3161. }
  3162. _TRY_2(Connect_Return_Free(h, &ConnectReturn))
  3163. Return:
  3164. SafeMesHandleFree(&h);
  3165. MIDL_user_free(pbEncodedBuffer);
  3166. FreeBuffer(pOutputBuffer);
  3167. return (lReturn);
  3168. ErrorReturn:
  3169. goto Return;
  3170. }
  3171. WINSCARDAPI LONG WINAPI
  3172. SCardConnectA(
  3173. IN SCARDCONTEXT hContext,
  3174. IN LPCSTR szReader,
  3175. IN DWORD dwShareMode,
  3176. IN DWORD dwPreferredProtocols,
  3177. OUT LPSCARDHANDLE phCard,
  3178. OUT LPDWORD pdwActiveProtocol)
  3179. {
  3180. return (I_SCardConnect(
  3181. hContext,
  3182. (LPCBYTE) szReader,
  3183. dwShareMode,
  3184. dwPreferredProtocols,
  3185. phCard,
  3186. pdwActiveProtocol,
  3187. FALSE));
  3188. }
  3189. WINSCARDAPI LONG WINAPI
  3190. SCardConnectW(
  3191. IN SCARDCONTEXT hContext,
  3192. IN LPCWSTR szReader,
  3193. IN DWORD dwShareMode,
  3194. IN DWORD dwPreferredProtocols,
  3195. OUT LPSCARDHANDLE phCard,
  3196. OUT LPDWORD pdwActiveProtocol)
  3197. {
  3198. return (I_SCardConnect(
  3199. hContext,
  3200. (LPCBYTE) szReader,
  3201. dwShareMode,
  3202. dwPreferredProtocols,
  3203. phCard,
  3204. pdwActiveProtocol,
  3205. TRUE));
  3206. }
  3207. //---------------------------------------------------------------------------------------
  3208. //
  3209. // SCardReconnect
  3210. //
  3211. //---------------------------------------------------------------------------------------
  3212. WINSCARDAPI LONG WINAPI
  3213. SCardReconnect(
  3214. IN SCARDHANDLE hCard,
  3215. IN DWORD dwShareMode,
  3216. IN DWORD dwPreferredProtocols,
  3217. IN DWORD dwInitialization,
  3218. OUT LPDWORD pdwActiveProtocol)
  3219. {
  3220. LONG lReturn = SCARD_S_SUCCESS;
  3221. NTSTATUS Status = STATUS_SUCCESS;
  3222. RPC_STATUS rpcStatus = RPC_S_OK;
  3223. char *pbEncodedBuffer = NULL;
  3224. unsigned long cbEncodedBuffer = 0;
  3225. handle_t h = 0;
  3226. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  3227. Reconnect_Call ReconnectCall;
  3228. Reconnect_Return ReconnectReturn;
  3229. if ((hCard == NULL) ||
  3230. (pdwActiveProtocol == NULL))
  3231. {
  3232. return (SCARD_E_INVALID_PARAMETER);
  3233. }
  3234. //
  3235. // Initialize encoding handle
  3236. //
  3237. rpcStatus = MesEncodeDynBufferHandleCreate(
  3238. &pbEncodedBuffer,
  3239. &cbEncodedBuffer,
  3240. &h);
  3241. if (rpcStatus != RPC_S_OK)
  3242. {
  3243. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3244. }
  3245. //
  3246. // Encode the Reconnect params
  3247. //
  3248. ReconnectCall.hCard = ((REDIR_LOCAL_SCARDHANDLE *) hCard)->Handle;
  3249. ReconnectCall.dwShareMode = dwShareMode;
  3250. ReconnectCall.dwPreferredProtocols = dwPreferredProtocols;
  3251. ReconnectCall.dwInitialization = dwInitialization;
  3252. _TRY_(Reconnect_Call_Encode(h, &ReconnectCall))
  3253. //
  3254. // Make the Reconnect call to the client
  3255. //
  3256. Status = _SendSCardIOCTL(
  3257. SCARD_IOCTL_RECONNECT,
  3258. pbEncodedBuffer,
  3259. cbEncodedBuffer,
  3260. &pOutputBuffer);
  3261. if (Status != STATUS_SUCCESS)
  3262. {
  3263. ERROR_RETURN(_MakeSCardError(Status))
  3264. }
  3265. SafeMesHandleFree(&h);
  3266. //
  3267. // Decode the return
  3268. //
  3269. rpcStatus = MesDecodeBufferHandleCreate(
  3270. (char *) pOutputBuffer->pbBytes,
  3271. pOutputBuffer->cbBytesUsed,
  3272. &h);
  3273. if (rpcStatus != RPC_S_OK)
  3274. {
  3275. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3276. }
  3277. memset(&ReconnectReturn, 0, sizeof(ReconnectReturn));
  3278. _TRY_(Reconnect_Return_Decode(h, &ReconnectReturn))
  3279. lReturn = ReconnectReturn.ReturnCode;
  3280. if (lReturn == SCARD_S_SUCCESS)
  3281. {
  3282. // The original Winscard API implements this parameter as
  3283. // Optional. We need to preserve that behavior.
  3284. if (NULL != pdwActiveProtocol)
  3285. *pdwActiveProtocol = ReconnectReturn.dwActiveProtocol;
  3286. }
  3287. _TRY_2(Reconnect_Return_Free(h, &ReconnectReturn))
  3288. Return:
  3289. SafeMesHandleFree(&h);
  3290. MIDL_user_free(pbEncodedBuffer);
  3291. FreeBuffer(pOutputBuffer);
  3292. return (lReturn);
  3293. ErrorReturn:
  3294. goto Return;
  3295. }
  3296. //---------------------------------------------------------------------------------------
  3297. //
  3298. // I_HCardAndDispositionCall
  3299. //
  3300. //---------------------------------------------------------------------------------------
  3301. WINSCARDAPI LONG WINAPI
  3302. I_HCardAndDispositionCall(
  3303. IN SCARDHANDLE hCard,
  3304. IN DWORD dwDisposition,
  3305. ULONG IoControlCode)
  3306. {
  3307. LONG lReturn = SCARD_S_SUCCESS;
  3308. NTSTATUS Status = STATUS_SUCCESS;
  3309. RPC_STATUS rpcStatus = RPC_S_OK;
  3310. char *pbEncodedBuffer = NULL;
  3311. unsigned long cbEncodedBuffer = 0;
  3312. handle_t h = 0;
  3313. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  3314. HCardAndDisposition_Call HCardAndDispositionCall;
  3315. if (hCard == NULL)
  3316. {
  3317. return (SCARD_E_INVALID_PARAMETER);
  3318. }
  3319. //
  3320. // Initialize encoding handle
  3321. //
  3322. rpcStatus = MesEncodeDynBufferHandleCreate(
  3323. &pbEncodedBuffer,
  3324. &cbEncodedBuffer,
  3325. &h);
  3326. if (rpcStatus != RPC_S_OK)
  3327. {
  3328. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3329. }
  3330. //
  3331. // Encode the Reconnect params
  3332. //
  3333. HCardAndDispositionCall.hCard = ((REDIR_LOCAL_SCARDHANDLE *) hCard)->Handle;
  3334. HCardAndDispositionCall.dwDisposition = dwDisposition;
  3335. _TRY_(HCardAndDisposition_Call_Encode(h, &HCardAndDispositionCall))
  3336. //
  3337. // Make the Reconnect call to the client
  3338. //
  3339. Status = _SendSCardIOCTL(
  3340. IoControlCode,
  3341. pbEncodedBuffer,
  3342. cbEncodedBuffer,
  3343. &pOutputBuffer);
  3344. if (Status != STATUS_SUCCESS)
  3345. {
  3346. ERROR_RETURN(_MakeSCardError(Status))
  3347. }
  3348. //
  3349. // Decode the return
  3350. //
  3351. lReturn = I_DecodeLongReturn(pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed);
  3352. Return:
  3353. SafeMesHandleFree(&h);
  3354. MIDL_user_free(pbEncodedBuffer);
  3355. FreeBuffer(pOutputBuffer);
  3356. return (lReturn);
  3357. ErrorReturn:
  3358. goto Return;
  3359. }
  3360. //---------------------------------------------------------------------------------------
  3361. //
  3362. // SCardDisconnect
  3363. //
  3364. //---------------------------------------------------------------------------------------
  3365. WINSCARDAPI LONG WINAPI
  3366. SCardDisconnect(
  3367. IN SCARDHANDLE hCard,
  3368. IN DWORD dwDisposition)
  3369. {
  3370. LONG lReturn = SCARD_S_SUCCESS;
  3371. lReturn = I_HCardAndDispositionCall(
  3372. hCard,
  3373. dwDisposition,
  3374. SCARD_IOCTL_DISCONNECT);
  3375. MIDL_user_free((REDIR_SCARDHANDLE *) hCard);
  3376. return (lReturn);
  3377. }
  3378. //---------------------------------------------------------------------------------------
  3379. //
  3380. // SCardBeginTransaction
  3381. //
  3382. //---------------------------------------------------------------------------------------
  3383. WINSCARDAPI LONG WINAPI
  3384. SCardBeginTransaction(
  3385. IN SCARDHANDLE hCard)
  3386. {
  3387. return (I_HCardAndDispositionCall(
  3388. hCard,
  3389. 0, // SCardBeginTransaction doesn't use a dispostion, so just set to 0
  3390. SCARD_IOCTL_BEGINTRANSACTION));
  3391. }
  3392. //---------------------------------------------------------------------------------------
  3393. //
  3394. // SCardEndTransaction
  3395. //
  3396. //---------------------------------------------------------------------------------------
  3397. WINSCARDAPI LONG WINAPI
  3398. SCardEndTransaction(
  3399. IN SCARDHANDLE hCard,
  3400. IN DWORD dwDisposition)
  3401. {
  3402. return (I_HCardAndDispositionCall(
  3403. hCard,
  3404. dwDisposition,
  3405. SCARD_IOCTL_ENDTRANSACTION));
  3406. }
  3407. //---------------------------------------------------------------------------------------
  3408. //
  3409. // SCardState
  3410. //
  3411. //---------------------------------------------------------------------------------------
  3412. WINSCARDAPI LONG WINAPI
  3413. SCardState(
  3414. IN SCARDHANDLE hCard,
  3415. OUT LPDWORD pdwState,
  3416. OUT LPDWORD pdwProtocol,
  3417. OUT LPBYTE pbAtr,
  3418. IN OUT LPDWORD pcbAtrLen)
  3419. {
  3420. LONG lReturn = SCARD_S_SUCCESS;
  3421. NTSTATUS Status = STATUS_SUCCESS;
  3422. RPC_STATUS rpcStatus = RPC_S_OK;
  3423. char *pbEncodedBuffer = NULL;
  3424. unsigned long cbEncodedBuffer = 0;
  3425. handle_t h = 0;
  3426. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  3427. State_Call StateCall;
  3428. State_Return StateReturn;
  3429. if (hCard == NULL)
  3430. {
  3431. return (SCARD_E_INVALID_PARAMETER);
  3432. }
  3433. //
  3434. // Initialize encoding handle
  3435. //
  3436. rpcStatus = MesEncodeDynBufferHandleCreate(
  3437. &pbEncodedBuffer,
  3438. &cbEncodedBuffer,
  3439. &h);
  3440. if (rpcStatus != RPC_S_OK)
  3441. {
  3442. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3443. }
  3444. //
  3445. // Encode the Reconnect params
  3446. //
  3447. StateCall.hCard = ((REDIR_LOCAL_SCARDHANDLE *) hCard)->Handle;
  3448. StateCall.fpbAtrIsNULL = (pbAtr == NULL);
  3449. StateCall.cbAtrLen = *pcbAtrLen;
  3450. _TRY_(State_Call_Encode(h, &StateCall))
  3451. //
  3452. // Make the Reconnect call to the client
  3453. //
  3454. Status = _SendSCardIOCTL(
  3455. SCARD_IOCTL_STATE,
  3456. pbEncodedBuffer,
  3457. cbEncodedBuffer,
  3458. &pOutputBuffer);
  3459. if (Status != STATUS_SUCCESS)
  3460. {
  3461. ERROR_RETURN(_MakeSCardError(Status))
  3462. }
  3463. SafeMesHandleFree(&h);
  3464. //
  3465. // Decode the return
  3466. //
  3467. rpcStatus = MesDecodeBufferHandleCreate(
  3468. (char *) pOutputBuffer->pbBytes,
  3469. pOutputBuffer->cbBytesUsed,
  3470. &h);
  3471. if (rpcStatus != RPC_S_OK)
  3472. {
  3473. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3474. }
  3475. memset(&StateReturn, 0, sizeof(StateReturn));
  3476. _TRY_(State_Return_Decode(h, &StateReturn))
  3477. lReturn = StateReturn.ReturnCode;
  3478. if (lReturn == SCARD_S_SUCCESS)
  3479. {
  3480. //
  3481. // The original Winscard API implements each of these
  3482. // parameters as Optional. We need to preserve that behavior.
  3483. //
  3484. if (NULL != pdwState)
  3485. *pdwState = StateReturn.dwState;
  3486. if (NULL != pdwProtocol)
  3487. *pdwProtocol = StateReturn.dwProtocol;
  3488. if (NULL != pcbAtrLen)
  3489. {
  3490. lReturn = _CopyReturnToCallerBuffer(
  3491. ((REDIR_LOCAL_SCARDHANDLE *) hCard)->pRedirContext,
  3492. StateReturn.rgAtr,
  3493. StateReturn.cbAtrLen,
  3494. pbAtr,
  3495. pcbAtrLen,
  3496. BYTE_TYPE_RETURN);
  3497. }
  3498. }
  3499. _TRY_2(State_Return_Free(h, &StateReturn))
  3500. Return:
  3501. SafeMesHandleFree(&h);
  3502. MIDL_user_free(pbEncodedBuffer);
  3503. FreeBuffer(pOutputBuffer);
  3504. return (lReturn);
  3505. ErrorReturn:
  3506. goto Return;
  3507. }
  3508. //---------------------------------------------------------------------------------------
  3509. //
  3510. // SCardStatus
  3511. //
  3512. //---------------------------------------------------------------------------------------
  3513. WINSCARDAPI LONG WINAPI
  3514. I_SCardStatus(
  3515. IN SCARDHANDLE hCard,
  3516. OUT LPBYTE mszReaderNames,
  3517. IN OUT LPDWORD pcchReaderLen,
  3518. OUT LPDWORD pdwState,
  3519. OUT LPDWORD pdwProtocol,
  3520. OUT LPBYTE pbAtr,
  3521. IN OUT LPDWORD pcbAtrLen,
  3522. IN BOOL fUnicode)
  3523. {
  3524. LONG lReturn = SCARD_S_SUCCESS;
  3525. NTSTATUS Status = STATUS_SUCCESS;
  3526. RPC_STATUS rpcStatus = RPC_S_OK;
  3527. char *pbEncodedBuffer = NULL;
  3528. unsigned long cbEncodedBuffer = 0;
  3529. handle_t h = 0;
  3530. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  3531. Status_Call StatusCall;
  3532. Status_Return StatusReturn;
  3533. if (hCard == NULL)
  3534. {
  3535. return (SCARD_E_INVALID_PARAMETER);
  3536. }
  3537. //
  3538. // Initialize encoding handle
  3539. //
  3540. rpcStatus = MesEncodeDynBufferHandleCreate(
  3541. &pbEncodedBuffer,
  3542. &cbEncodedBuffer,
  3543. &h);
  3544. if (rpcStatus != RPC_S_OK)
  3545. {
  3546. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3547. }
  3548. //
  3549. // Encode the Reconnect params
  3550. //
  3551. StatusCall.hCard = ((REDIR_LOCAL_SCARDHANDLE *) hCard)->Handle;
  3552. StatusCall.fmszReaderNamesIsNULL = (mszReaderNames == NULL);
  3553. StatusCall.cchReaderLen = *pcchReaderLen;
  3554. StatusCall.cbAtrLen = *pcbAtrLen;
  3555. _TRY_(Status_Call_Encode(h, &StatusCall))
  3556. //
  3557. // Make the Status call to the client
  3558. //
  3559. Status = _SendSCardIOCTL(
  3560. fUnicode ? SCARD_IOCTL_STATUSW :
  3561. SCARD_IOCTL_STATUSA,
  3562. pbEncodedBuffer,
  3563. cbEncodedBuffer,
  3564. &pOutputBuffer);
  3565. if (Status != STATUS_SUCCESS)
  3566. {
  3567. ERROR_RETURN(_MakeSCardError(Status))
  3568. }
  3569. SafeMesHandleFree(&h);
  3570. //
  3571. // Decode the return
  3572. //
  3573. rpcStatus = MesDecodeBufferHandleCreate(
  3574. (char *) pOutputBuffer->pbBytes,
  3575. pOutputBuffer->cbBytesUsed,
  3576. &h);
  3577. if (rpcStatus != RPC_S_OK)
  3578. {
  3579. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3580. }
  3581. memset(&StatusReturn, 0, sizeof(StatusReturn));
  3582. _TRY_(Status_Return_Decode(h, &StatusReturn))
  3583. if (StatusReturn.cbAtrLen > sizeof(StatusReturn.pbAtr))
  3584. {
  3585. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3586. }
  3587. lReturn = StatusReturn.ReturnCode;
  3588. if (lReturn == SCARD_S_SUCCESS)
  3589. {
  3590. //
  3591. // The original Winscard API implements each of these
  3592. // parameters as Optional. We need to preserve that behavior.
  3593. //
  3594. if (NULL != pcchReaderLen)
  3595. {
  3596. lReturn = _CopyReturnToCallerBuffer(
  3597. ((REDIR_LOCAL_SCARDHANDLE *) hCard)->pRedirContext,
  3598. StatusReturn.mszReaderNames,
  3599. StatusReturn.cBytes,
  3600. mszReaderNames,
  3601. pcchReaderLen,
  3602. fUnicode ? WSZ_TYPE_RETURN : SZ_TYPE_RETURN);
  3603. }
  3604. if (lReturn == SCARD_S_SUCCESS)
  3605. {
  3606. if (NULL != pdwState)
  3607. *pdwState = StatusReturn.dwState;
  3608. if (NULL != pdwProtocol)
  3609. *pdwProtocol = StatusReturn.dwProtocol;
  3610. if (NULL != pcbAtrLen)
  3611. {
  3612. if ((NULL != pbAtr) && (*pcbAtrLen >= StatusReturn.cbAtrLen))
  3613. {
  3614. memcpy(
  3615. pbAtr,
  3616. StatusReturn.pbAtr,
  3617. StatusReturn.cbAtrLen);
  3618. }
  3619. *pcbAtrLen = StatusReturn.cbAtrLen;
  3620. }
  3621. }
  3622. }
  3623. _TRY_2(Status_Return_Free(h, &StatusReturn))
  3624. Return:
  3625. SafeMesHandleFree(&h);
  3626. MIDL_user_free(pbEncodedBuffer);
  3627. FreeBuffer(pOutputBuffer);
  3628. return (lReturn);
  3629. ErrorReturn:
  3630. goto Return;
  3631. }
  3632. WINSCARDAPI LONG WINAPI
  3633. SCardStatusA(
  3634. IN SCARDHANDLE hCard,
  3635. OUT LPSTR mszReaderNames,
  3636. IN OUT LPDWORD pcchReaderLen,
  3637. OUT LPDWORD pdwState,
  3638. OUT LPDWORD pdwProtocol,
  3639. OUT LPBYTE pbAtr,
  3640. IN OUT LPDWORD pcbAtrLen)
  3641. {
  3642. return (I_SCardStatus(
  3643. hCard,
  3644. (LPBYTE) mszReaderNames,
  3645. pcchReaderLen,
  3646. pdwState,
  3647. pdwProtocol,
  3648. pbAtr,
  3649. pcbAtrLen,
  3650. FALSE));
  3651. }
  3652. WINSCARDAPI LONG WINAPI
  3653. SCardStatusW(
  3654. IN SCARDHANDLE hCard,
  3655. OUT LPWSTR mszReaderNames,
  3656. IN OUT LPDWORD pcchReaderLen,
  3657. OUT LPDWORD pdwState,
  3658. OUT LPDWORD pdwProtocol,
  3659. OUT LPBYTE pbAtr,
  3660. IN OUT LPDWORD pcbAtrLen)
  3661. {
  3662. return (I_SCardStatus(
  3663. hCard,
  3664. (LPBYTE) mszReaderNames,
  3665. pcchReaderLen,
  3666. pdwState,
  3667. pdwProtocol,
  3668. pbAtr,
  3669. pcbAtrLen,
  3670. TRUE));
  3671. }
  3672. //---------------------------------------------------------------------------------------
  3673. //
  3674. // SCardTransmit
  3675. //
  3676. //---------------------------------------------------------------------------------------
  3677. WINSCARDAPI LONG WINAPI
  3678. SCardTransmit(
  3679. IN SCARDHANDLE hCard,
  3680. IN LPCSCARD_IO_REQUEST pioSendPci,
  3681. IN LPCBYTE pbSendBuffer,
  3682. IN DWORD cbSendLength,
  3683. IN OUT LPSCARD_IO_REQUEST pioRecvPci,
  3684. OUT LPBYTE pbRecvBuffer,
  3685. IN OUT LPDWORD pcbRecvLength)
  3686. {
  3687. LONG lReturn = SCARD_S_SUCCESS;
  3688. NTSTATUS Status = STATUS_SUCCESS;
  3689. RPC_STATUS rpcStatus = RPC_S_OK;
  3690. char *pbEncodedBuffer = NULL;
  3691. unsigned long cbEncodedBuffer = 0;
  3692. handle_t h = 0;
  3693. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  3694. Transmit_Call TransmitCall;
  3695. Transmit_Return TransmitReturn;
  3696. SCardIO_Request ioRecvPci;
  3697. if (hCard == NULL)
  3698. {
  3699. return (SCARD_E_INVALID_PARAMETER);
  3700. }
  3701. //
  3702. // Initialize encoding handle
  3703. //
  3704. rpcStatus = MesEncodeDynBufferHandleCreate(
  3705. &pbEncodedBuffer,
  3706. &cbEncodedBuffer,
  3707. &h);
  3708. if (rpcStatus != RPC_S_OK)
  3709. {
  3710. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3711. }
  3712. //
  3713. // Encode the Transmit params
  3714. //
  3715. TransmitCall.hCard = ((REDIR_LOCAL_SCARDHANDLE *) hCard)->Handle;
  3716. TransmitCall.ioSendPci.dwProtocol = pioSendPci->dwProtocol;
  3717. TransmitCall.ioSendPci.cbExtraBytes = pioSendPci->cbPciLength -
  3718. sizeof(SCARD_IO_REQUEST);
  3719. if (TransmitCall.ioSendPci.cbExtraBytes != 0)
  3720. {
  3721. TransmitCall.ioSendPci.pbExtraBytes = ((BYTE *) pioSendPci) +
  3722. sizeof(SCARD_IO_REQUEST);
  3723. }
  3724. else
  3725. {
  3726. TransmitCall.ioSendPci.pbExtraBytes = NULL;
  3727. }
  3728. TransmitCall.cbSendLength = cbSendLength;
  3729. TransmitCall.pbSendBuffer = pbSendBuffer;
  3730. if (pioRecvPci != NULL)
  3731. {
  3732. TransmitCall.pioRecvPci = &ioRecvPci;
  3733. ioRecvPci.dwProtocol = pioRecvPci->dwProtocol;
  3734. ioRecvPci.cbExtraBytes = pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST);
  3735. if (ioRecvPci.cbExtraBytes != 0)
  3736. {
  3737. ioRecvPci.pbExtraBytes = ((LPBYTE) pioRecvPci) + sizeof(SCARD_IO_REQUEST);
  3738. }
  3739. else
  3740. {
  3741. ioRecvPci.pbExtraBytes = NULL;
  3742. }
  3743. }
  3744. else
  3745. {
  3746. TransmitCall.pioRecvPci = NULL;
  3747. }
  3748. TransmitCall.fpbRecvBufferIsNULL = (pbRecvBuffer == NULL);
  3749. TransmitCall.cbRecvLength = *pcbRecvLength;
  3750. _TRY_(Transmit_Call_Encode(h, &TransmitCall))
  3751. //
  3752. // Make the Status call to the client
  3753. //
  3754. Status = _SendSCardIOCTL(
  3755. SCARD_IOCTL_TRANSMIT,
  3756. pbEncodedBuffer,
  3757. cbEncodedBuffer,
  3758. &pOutputBuffer);
  3759. if (Status != STATUS_SUCCESS)
  3760. {
  3761. ERROR_RETURN(_MakeSCardError(Status))
  3762. }
  3763. SafeMesHandleFree(&h);
  3764. //
  3765. // Decode the return
  3766. //
  3767. rpcStatus = MesDecodeBufferHandleCreate(
  3768. (char *) pOutputBuffer->pbBytes,
  3769. pOutputBuffer->cbBytesUsed,
  3770. &h);
  3771. if (rpcStatus != RPC_S_OK)
  3772. {
  3773. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3774. }
  3775. memset(&TransmitReturn, 0, sizeof(TransmitReturn));
  3776. _TRY_(Transmit_Return_Decode(h, &TransmitReturn))
  3777. lReturn = TransmitReturn.ReturnCode;
  3778. if (lReturn == SCARD_S_SUCCESS)
  3779. {
  3780. if ((pioRecvPci != NULL) &&
  3781. (TransmitReturn.pioRecvPci != NULL))
  3782. {
  3783. pioRecvPci->dwProtocol = TransmitReturn.pioRecvPci->dwProtocol;
  3784. if ((TransmitReturn.pioRecvPci->cbExtraBytes != 0) &&
  3785. (TransmitReturn.pioRecvPci->cbExtraBytes <=
  3786. (pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST))))
  3787. {
  3788. memcpy(
  3789. ((LPBYTE) pioRecvPci) + sizeof(SCARD_IO_REQUEST),
  3790. TransmitReturn.pioRecvPci->pbExtraBytes,
  3791. TransmitReturn.pioRecvPci->cbExtraBytes);
  3792. }
  3793. }
  3794. lReturn = _CopyReturnToCallerBuffer(
  3795. ((REDIR_LOCAL_SCARDHANDLE *) hCard)->pRedirContext,
  3796. TransmitReturn.pbRecvBuffer,
  3797. TransmitReturn.cbRecvLength,
  3798. pbRecvBuffer,
  3799. pcbRecvLength,
  3800. BYTE_TYPE_RETURN);
  3801. }
  3802. _TRY_2(Transmit_Return_Free(h, &TransmitReturn))
  3803. Return:
  3804. SafeMesHandleFree(&h);
  3805. MIDL_user_free(pbEncodedBuffer);
  3806. FreeBuffer(pOutputBuffer);
  3807. return (lReturn);
  3808. ErrorReturn:
  3809. goto Return;
  3810. }
  3811. //---------------------------------------------------------------------------------------
  3812. //
  3813. // SCardControl
  3814. //
  3815. //---------------------------------------------------------------------------------------
  3816. WINSCARDAPI LONG WINAPI
  3817. SCardControl(
  3818. IN SCARDHANDLE hCard,
  3819. IN DWORD dwControlCode,
  3820. IN LPCVOID pvInBuffer,
  3821. IN DWORD cbInBufferSize,
  3822. OUT LPVOID pvOutBuffer,
  3823. IN DWORD cbOutBufferSize,
  3824. OUT LPDWORD pcbBytesReturned)
  3825. {
  3826. LONG lReturn = SCARD_S_SUCCESS;
  3827. NTSTATUS Status = STATUS_SUCCESS;
  3828. RPC_STATUS rpcStatus = RPC_S_OK;
  3829. char *pbEncodedBuffer = NULL;
  3830. unsigned long cbEncodedBuffer = 0;
  3831. handle_t h = 0;
  3832. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  3833. Control_Call ControlCall;
  3834. Control_Return ControlReturn;
  3835. if (hCard == NULL)
  3836. {
  3837. return (SCARD_E_INVALID_PARAMETER);
  3838. }
  3839. //
  3840. // Initialize encoding handle
  3841. //
  3842. rpcStatus = MesEncodeDynBufferHandleCreate(
  3843. &pbEncodedBuffer,
  3844. &cbEncodedBuffer,
  3845. &h);
  3846. if (rpcStatus != RPC_S_OK)
  3847. {
  3848. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3849. }
  3850. //
  3851. // Encode the Control params
  3852. //
  3853. ControlCall.hCard = ((REDIR_LOCAL_SCARDHANDLE *) hCard)->Handle;
  3854. ControlCall.dwControlCode = dwControlCode;
  3855. ControlCall.cbInBufferSize = cbInBufferSize;
  3856. ControlCall.pvInBuffer = (LPCBYTE) pvInBuffer;
  3857. ControlCall.fpvOutBufferIsNULL = (pvOutBuffer == NULL);
  3858. ControlCall.cbOutBufferSize = cbOutBufferSize;
  3859. _TRY_(Control_Call_Encode(h, &ControlCall))
  3860. //
  3861. // Make the Control call to the client
  3862. //
  3863. Status = _SendSCardIOCTL(
  3864. SCARD_IOCTL_CONTROL,
  3865. pbEncodedBuffer,
  3866. cbEncodedBuffer,
  3867. &pOutputBuffer);
  3868. if (Status != STATUS_SUCCESS)
  3869. {
  3870. ERROR_RETURN(_MakeSCardError(Status))
  3871. }
  3872. SafeMesHandleFree(&h);
  3873. //
  3874. // Decode the return
  3875. //
  3876. rpcStatus = MesDecodeBufferHandleCreate(
  3877. (char *) pOutputBuffer->pbBytes,
  3878. pOutputBuffer->cbBytesUsed,
  3879. &h);
  3880. if (rpcStatus != RPC_S_OK)
  3881. {
  3882. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3883. }
  3884. memset(&ControlReturn, 0, sizeof(ControlReturn));
  3885. _TRY_(Control_Return_Decode(h, &ControlReturn))
  3886. lReturn = ControlReturn.ReturnCode;
  3887. if (lReturn == SCARD_S_SUCCESS)
  3888. {
  3889. *pcbBytesReturned = ControlReturn.cbOutBufferSize;
  3890. lReturn = _CopyReturnToCallerBuffer(
  3891. ((REDIR_LOCAL_SCARDHANDLE *) hCard)->pRedirContext,
  3892. ControlReturn.pvOutBuffer,
  3893. ControlReturn.cbOutBufferSize,
  3894. (LPBYTE) pvOutBuffer,
  3895. pcbBytesReturned,
  3896. BYTE_TYPE_RETURN);
  3897. }
  3898. _TRY_2(Control_Return_Free(h, &ControlReturn))
  3899. Return:
  3900. SafeMesHandleFree(&h);
  3901. MIDL_user_free(pbEncodedBuffer);
  3902. FreeBuffer(pOutputBuffer);
  3903. return (lReturn);
  3904. ErrorReturn:
  3905. goto Return;
  3906. }
  3907. //---------------------------------------------------------------------------------------
  3908. //
  3909. // SCardGetAttrib
  3910. //
  3911. //---------------------------------------------------------------------------------------
  3912. WINSCARDAPI LONG WINAPI
  3913. SCardGetAttrib(
  3914. IN SCARDHANDLE hCard,
  3915. IN DWORD dwAttrId,
  3916. OUT LPBYTE pbAttr,
  3917. IN OUT LPDWORD pcbAttrLen)
  3918. {
  3919. LONG lReturn = SCARD_S_SUCCESS;
  3920. NTSTATUS Status = STATUS_SUCCESS;
  3921. RPC_STATUS rpcStatus = RPC_S_OK;
  3922. char *pbEncodedBuffer = NULL;
  3923. unsigned long cbEncodedBuffer = 0;
  3924. handle_t h = 0;
  3925. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  3926. GetAttrib_Call GetAttribCall;
  3927. GetAttrib_Return GetAttribReturn;
  3928. if (hCard == NULL)
  3929. {
  3930. return (SCARD_E_INVALID_PARAMETER);
  3931. }
  3932. //
  3933. // Initialize encoding handle
  3934. //
  3935. rpcStatus = MesEncodeDynBufferHandleCreate(
  3936. &pbEncodedBuffer,
  3937. &cbEncodedBuffer,
  3938. &h);
  3939. if (rpcStatus != RPC_S_OK)
  3940. {
  3941. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3942. }
  3943. //
  3944. // Encode the GetAttrib params
  3945. //
  3946. GetAttribCall.hCard = ((REDIR_LOCAL_SCARDHANDLE *) hCard)->Handle;
  3947. GetAttribCall.dwAttrId = dwAttrId;;
  3948. GetAttribCall.fpbAttrIsNULL = (pbAttr == NULL);
  3949. GetAttribCall.cbAttrLen = *pcbAttrLen;
  3950. _TRY_(GetAttrib_Call_Encode(h, &GetAttribCall))
  3951. //
  3952. // Make the GetAttrib call to the client
  3953. //
  3954. Status = _SendSCardIOCTL(
  3955. SCARD_IOCTL_GETATTRIB,
  3956. pbEncodedBuffer,
  3957. cbEncodedBuffer,
  3958. &pOutputBuffer);
  3959. if (Status != STATUS_SUCCESS)
  3960. {
  3961. ERROR_RETURN(_MakeSCardError(Status))
  3962. }
  3963. SafeMesHandleFree(&h);
  3964. //
  3965. // Decode the return
  3966. //
  3967. rpcStatus = MesDecodeBufferHandleCreate(
  3968. (char *) pOutputBuffer->pbBytes,
  3969. pOutputBuffer->cbBytesUsed,
  3970. &h);
  3971. if (rpcStatus != RPC_S_OK)
  3972. {
  3973. ERROR_RETURN(SCARD_E_UNEXPECTED)
  3974. }
  3975. memset(&GetAttribReturn, 0, sizeof(GetAttribReturn));
  3976. _TRY_(GetAttrib_Return_Decode(h, &GetAttribReturn))
  3977. lReturn = GetAttribReturn.ReturnCode;
  3978. if (lReturn == SCARD_S_SUCCESS)
  3979. {
  3980. lReturn = _CopyReturnToCallerBuffer(
  3981. ((REDIR_LOCAL_SCARDHANDLE *) hCard)->pRedirContext,
  3982. GetAttribReturn.pbAttr,
  3983. GetAttribReturn.cbAttrLen,
  3984. (LPBYTE) pbAttr,
  3985. pcbAttrLen,
  3986. BYTE_TYPE_RETURN);
  3987. }
  3988. _TRY_2(GetAttrib_Return_Free(h, &GetAttribReturn))
  3989. Return:
  3990. SafeMesHandleFree(&h);
  3991. MIDL_user_free(pbEncodedBuffer);
  3992. FreeBuffer(pOutputBuffer);
  3993. return (lReturn);
  3994. ErrorReturn:
  3995. goto Return;
  3996. }
  3997. //---------------------------------------------------------------------------------------
  3998. //
  3999. // SCardSetAttrib
  4000. //
  4001. //---------------------------------------------------------------------------------------
  4002. WINSCARDAPI LONG WINAPI
  4003. SCardSetAttrib(
  4004. IN SCARDHANDLE hCard,
  4005. IN DWORD dwAttrId,
  4006. IN LPCBYTE pbAttr,
  4007. IN DWORD cbAttrLen)
  4008. {
  4009. LONG lReturn = SCARD_S_SUCCESS;
  4010. NTSTATUS Status = STATUS_SUCCESS;
  4011. RPC_STATUS rpcStatus = RPC_S_OK;
  4012. char *pbEncodedBuffer = NULL;
  4013. unsigned long cbEncodedBuffer = 0;
  4014. handle_t h = 0;
  4015. BUFFER_LIST_STRUCT *pOutputBuffer = NULL;
  4016. SetAttrib_Call SetAttribCall;
  4017. if (hCard == NULL)
  4018. {
  4019. return (SCARD_E_INVALID_PARAMETER);
  4020. }
  4021. //
  4022. // Initialize encoding handle
  4023. //
  4024. rpcStatus = MesEncodeDynBufferHandleCreate(
  4025. &pbEncodedBuffer,
  4026. &cbEncodedBuffer,
  4027. &h);
  4028. if (rpcStatus != RPC_S_OK)
  4029. {
  4030. ERROR_RETURN(SCARD_E_UNEXPECTED)
  4031. }
  4032. //
  4033. // Encode the SetAttrib params
  4034. //
  4035. SetAttribCall.hCard = ((REDIR_LOCAL_SCARDHANDLE *) hCard)->Handle;
  4036. SetAttribCall.dwAttrId = dwAttrId;;
  4037. SetAttribCall.pbAttr = pbAttr;
  4038. SetAttribCall.cbAttrLen = cbAttrLen;
  4039. _TRY_(SetAttrib_Call_Encode(h, &SetAttribCall))
  4040. //
  4041. // Make the SetAttrib call to the client
  4042. //
  4043. Status = _SendSCardIOCTL(
  4044. SCARD_IOCTL_SETATTRIB,
  4045. pbEncodedBuffer,
  4046. cbEncodedBuffer,
  4047. &pOutputBuffer);
  4048. if (Status != STATUS_SUCCESS)
  4049. {
  4050. ERROR_RETURN(_MakeSCardError(Status))
  4051. }
  4052. //
  4053. // Decode the return
  4054. //
  4055. lReturn = I_DecodeLongReturn(pOutputBuffer->pbBytes, pOutputBuffer->cbBytesUsed);
  4056. Return:
  4057. SafeMesHandleFree(&h);
  4058. MIDL_user_free(pbEncodedBuffer);
  4059. FreeBuffer(pOutputBuffer);
  4060. return (lReturn);
  4061. ErrorReturn:
  4062. goto Return;
  4063. }
  4064. //---------------------------------------------------------------------------------------
  4065. //
  4066. // SCardAccessStartedEvent
  4067. //
  4068. //---------------------------------------------------------------------------------------
  4069. WINSCARDAPI HANDLE WINAPI
  4070. SCardAccessStartedEvent(void)
  4071. {
  4072. HANDLE h;
  4073. h = _GetStartedEventHandle();
  4074. if ((h == NULL) || !_SetStartedEventToCorrectState())
  4075. {
  4076. //
  4077. // Either we couldn't create the event, or we couldn't start the thread to set
  4078. // the event, so return NULL
  4079. //
  4080. return (NULL);
  4081. }
  4082. //
  4083. // Check to see if the event is already set, if not, give the thread which sets
  4084. // the event a chance to run and set the event before returning
  4085. //
  4086. if (WAIT_OBJECT_0 != WaitForSingleObject(h, 0))
  4087. {
  4088. WaitForSingleObject(h, 10);
  4089. }
  4090. //
  4091. // This API has old semantics where it just return the handle straight away
  4092. // instead of duplicating it.
  4093. //
  4094. return (h);
  4095. }
  4096. //---------------------------------------------------------------------------------------
  4097. //
  4098. // SCardReleaseStartedEvent
  4099. //
  4100. //---------------------------------------------------------------------------------------
  4101. WINSCARDAPI void WINAPI
  4102. SCardReleaseStartedEvent(void)
  4103. {
  4104. return;
  4105. }
  4106. //---------------------------------------------------------------------------------------
  4107. //
  4108. // SCardReleaseBadContext
  4109. //
  4110. //---------------------------------------------------------------------------------------
  4111. WINSCARDAPI LONG WINAPI
  4112. SCardReleaseBadContext(
  4113. IN SCARDCONTEXT hContext)
  4114. {
  4115. MIDL_user_free((REDIR_LOCAL_SCARDCONTEXT *) hContext);
  4116. return (SCARD_S_SUCCESS);
  4117. }