/*++ Copyright (C) Microsoft Corporation, 1996 - 1999 Module Name: SCardDlg Abstract: This file contains the outline implementation of the DLL exports for the Smartcard Common Dialogs Author: Chris Dudley 2/27/1997 Environment: Win32, C++ w/Exceptions, MFC Revision History: Amanda Matlosz 07/09/1998 incorporated new select card, get pin and change pin dlgs. Notes: --*/ ///////////////////////////////////////////////////////////////////////////// // // Includes // #include "stdafx.h" #include #include "resource.h" #include "miscdef.h" #include "SCDlg.h" #include "ScSearch.h" #include "ScInsDlg.h" #include "chngpdlg.h" #include "ScUIDlg.h" // will someday be just #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // Forward Decls -- Helper functions defined @ eof void MString2CommaList(CString& str, LPWSTR szmString); void MString2CommaList(CString& str, LPSTR szmString); ///////////////////////////////////////////////////////////////////////////// // CSCardDlgApp BEGIN_MESSAGE_MAP(CSCardDlgApp, CWinApp) //{{AFX_MSG_MAP(CSCardDlgApp) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG_MAP END_MESSAGE_MAP() /*++ CSCardDlgApp: Construction. Arguments: Return Value: Author: Chris Dudley 2/27/1997 --*/ CSCardDlgApp::CSCardDlgApp() { } ///////////////////////////////////////////////////////////////////////////// // // The one CSCardDlgApp object // CSCardDlgApp theApp; /*++ InitInstance: Override for the instance initializaion. Arguments: None Return Value: TRUE on success; FALSE otherwise resulting in DLL NOT be loaded. Author: Chris Dudley 2/27/1997 --*/ BOOL CSCardDlgApp::InitInstance() { BOOL fResult = FALSE; // Disable all DLL notifications...Force exported API entry point. fResult = DisableThreadLibraryCalls(m_hInstance); _ASSERTE(fResult); // DisableThreadLibraryCalls failed; can't init dll return fResult; } ///////////////////////////////////////////////////////////////////////////// // // Exported APIs from the DLL // /*++ GetOpenCardName: This is the SDK v1.0 entry point routine to open the common dialog box. It has been retained for backwards compatibility; it is now a wrapper call for GetOpenCardNameEx(). Arguments: pOCNA - Pointer to an ANSI open card name structure. -or- pOCNW - Popinter to a UNICODE open card name structure Return Value: A LONG value indicating the status of the requested action. Please see the Smartcard header files for additional information. Author: Chris Dudley 2/27/1997 --*/ LONG WINAPI GetOpenCardNameA(LPOPENCARDNAMEA pOCNA) { // Setup the correct module state information AFX_MANAGE_STATE(AfxGetStaticModuleState()); USES_CONVERSION; // Locals LONG lReturn = SCARD_S_SUCCESS; OPENCARDNAMEA_EX openCardNameEx; OPENCARD_SEARCH_CRITERIAA openCardSearchCriteria; try { // Check Params if (NULL == pOCNA) { throw (LONG)SCARD_E_INVALID_VALUE; } if (pOCNA->dwStructSize != sizeof(OPENCARDNAMEA)) { throw (LONG)SCARD_E_INVALID_VALUE; } // Translate the OPENCARDNAME struct to OPENCARDNAME_EX ZeroMemory((PVOID)&openCardNameEx, sizeof(openCardNameEx)); openCardNameEx.dwStructSize = sizeof(openCardNameEx); openCardNameEx.hwndOwner = pOCNA->hwndOwner; openCardNameEx.hSCardContext = pOCNA->hSCardContext; openCardNameEx.lpstrTitle = pOCNA->lpstrTitle; openCardNameEx.dwFlags = pOCNA->dwFlags; openCardNameEx.lpstrRdr = pOCNA->lpstrRdr; openCardNameEx.nMaxRdr = pOCNA->nMaxRdr; openCardNameEx.lpstrCard = pOCNA->lpstrCard; openCardNameEx.nMaxCard = pOCNA->nMaxCard; openCardNameEx.lpfnConnect = pOCNA->lpfnConnect; openCardNameEx.pvUserData = pOCNA->pvUserData; openCardNameEx.dwShareMode = pOCNA->dwShareMode; openCardNameEx.dwPreferredProtocols = pOCNA->dwPreferredProtocols; // Build a OPENCARD_SEARCH_CRITERIA struct ZeroMemory((PVOID)&openCardSearchCriteria, sizeof(openCardSearchCriteria)); openCardSearchCriteria.dwStructSize = sizeof(openCardSearchCriteria); openCardSearchCriteria.lpstrGroupNames = pOCNA->lpstrGroupNames; openCardSearchCriteria.nMaxGroupNames = pOCNA->nMaxGroupNames; openCardSearchCriteria.rgguidInterfaces = pOCNA->rgguidInterfaces; openCardSearchCriteria.cguidInterfaces = pOCNA->cguidInterfaces; openCardSearchCriteria.lpstrCardNames = pOCNA->lpstrCardNames; openCardSearchCriteria.nMaxCardNames = pOCNA->nMaxCardNames; openCardSearchCriteria.lpfnCheck = pOCNA->lpfnCheck; openCardSearchCriteria.lpfnConnect = pOCNA->lpfnConnect; openCardSearchCriteria.lpfnDisconnect = pOCNA->lpfnDisconnect; openCardSearchCriteria.pvUserData = pOCNA->pvUserData; openCardSearchCriteria.dwShareMode = pOCNA->dwShareMode; openCardSearchCriteria.dwPreferredProtocols = pOCNA->dwPreferredProtocols; openCardNameEx.pOpenCardSearchCriteria = &openCardSearchCriteria; // Create a "search description" based on requested card names CString strPrompt; strPrompt.Empty(); if (NULL != pOCNA->lpstrCardNames) { DWORD cNames = AnsiMStringCount(pOCNA->lpstrCardNames); if (1 == cNames) { strPrompt.Format( IDS_PROMPT_ONECARD, A2W(pOCNA->lpstrCardNames)); } else if (1 < cNames) { CString strCommaList; MString2CommaList(strCommaList, pOCNA->lpstrCardNames); strPrompt.Format( IDS_PROMPT_CARDS, strCommaList); } } if (!strPrompt.IsEmpty()) { openCardNameEx.lpstrSearchDesc = (LPCSTR)W2A(strPrompt); } // Call the updated routine lReturn = SCardUIDlgSelectCardA(&openCardNameEx); // Update the (const) return values of the OPENCARDNAME struct pOCNA->nMaxRdr = openCardNameEx.nMaxRdr; pOCNA->nMaxCard = openCardNameEx.nMaxCard; pOCNA->dwActiveProtocol = openCardNameEx.dwActiveProtocol; pOCNA->hCardHandle = openCardNameEx.hCardHandle; } catch (LONG hr) { lReturn = hr; TRACE_CATCH(_T("GetOpenCardNameA"),hr); } catch (...) { lReturn = (LONG) SCARD_E_UNEXPECTED; TRACE_CATCH_UNKNOWN(_T("GetOpenCardNameA")); } return lReturn; } LONG WINAPI GetOpenCardNameW(LPOPENCARDNAMEW pOCNW) { // Setup the correct module state information AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Locals LONG lReturn = SCARD_S_SUCCESS; OPENCARDNAMEW_EX openCardNameEx; OPENCARD_SEARCH_CRITERIAW openCardSearchCriteria; try { // Check Params if (NULL == pOCNW) { throw (LONG)SCARD_E_INVALID_VALUE; } if (pOCNW->dwStructSize != sizeof(OPENCARDNAMEW)) { throw (LONG)SCARD_E_INVALID_VALUE; } // Translate the OPENCARDNAME struct to OPENCARDNAME_EX ZeroMemory((PVOID)&openCardNameEx, sizeof(openCardNameEx)); openCardNameEx.dwStructSize = sizeof(openCardNameEx); openCardNameEx.hwndOwner = pOCNW->hwndOwner; openCardNameEx.hSCardContext = pOCNW->hSCardContext; openCardNameEx.lpstrTitle = pOCNW->lpstrTitle; openCardNameEx.dwFlags = pOCNW->dwFlags; openCardNameEx.lpstrRdr = pOCNW->lpstrRdr; openCardNameEx.nMaxRdr = pOCNW->nMaxRdr; openCardNameEx.lpstrCard = pOCNW->lpstrCard; openCardNameEx.nMaxCard = pOCNW->nMaxCard; openCardNameEx.lpfnConnect = pOCNW->lpfnConnect; openCardNameEx.pvUserData = pOCNW->pvUserData; openCardNameEx.dwShareMode = pOCNW->dwShareMode; openCardNameEx.dwPreferredProtocols = pOCNW->dwPreferredProtocols; // Build a OPENCARD_SEARCH_CRITERIA struct ZeroMemory((PVOID)&openCardSearchCriteria, sizeof(openCardSearchCriteria)); openCardSearchCriteria.dwStructSize = sizeof(openCardSearchCriteria); openCardSearchCriteria.lpstrGroupNames = pOCNW->lpstrGroupNames; openCardSearchCriteria.nMaxGroupNames = pOCNW->nMaxGroupNames; openCardSearchCriteria.rgguidInterfaces = pOCNW->rgguidInterfaces; openCardSearchCriteria.cguidInterfaces = pOCNW->cguidInterfaces; openCardSearchCriteria.lpstrCardNames = pOCNW->lpstrCardNames; openCardSearchCriteria.nMaxCardNames = pOCNW->nMaxCardNames; openCardSearchCriteria.lpfnCheck = pOCNW->lpfnCheck; openCardSearchCriteria.lpfnConnect = pOCNW->lpfnConnect; openCardSearchCriteria.lpfnDisconnect = pOCNW->lpfnDisconnect; openCardSearchCriteria.pvUserData = pOCNW->pvUserData; openCardSearchCriteria.dwShareMode = pOCNW->dwShareMode; openCardSearchCriteria.dwPreferredProtocols = pOCNW->dwPreferredProtocols; openCardNameEx.pOpenCardSearchCriteria = &openCardSearchCriteria; // Create a "search description" based on requested card names CString strPrompt; strPrompt.Empty(); if (NULL != pOCNW->lpstrCardNames) { DWORD cNames = MStringCount(pOCNW->lpstrCardNames); if (1 == cNames) { strPrompt.Format( IDS_PROMPT_ONECARD, pOCNW->lpstrCardNames); } else if (1 < cNames) { CString strCommaList; MString2CommaList(strCommaList, pOCNW->lpstrCardNames); strPrompt.Format( IDS_PROMPT_CARDS, strCommaList); } } if (!strPrompt.IsEmpty()) { openCardNameEx.lpstrSearchDesc = (LPCWSTR)strPrompt; } // Call the updated routine lReturn = SCardUIDlgSelectCardW(&openCardNameEx); // Update the (const) return values of the OPENCARDNAME struct pOCNW->nMaxRdr = openCardNameEx.nMaxRdr; pOCNW->nMaxCard = openCardNameEx.nMaxCard; pOCNW->dwActiveProtocol = openCardNameEx.dwActiveProtocol; pOCNW->hCardHandle = openCardNameEx.hCardHandle; } catch (LONG hr) { lReturn = hr; TRACE_CATCH(_T("GetOpenCardNameW"),hr); } catch (...) { lReturn = (LONG) SCARD_E_UNEXPECTED; TRACE_CATCH_UNKNOWN(_T("GetOpenCardNameW")); } return lReturn; } /*++ LONG SCardDlgExtendedError: This is an old entry point for getting extended errors from the dialog. Please use the lLastError member of the OPENCARDNAME struct. Arguments: None. Return Value: None. Author: Chris Dudley 2/27/1997 --*/ LONG WINAPI SCardDlgExtendedError (void) { // Setup the correct module state information AFX_MANAGE_STATE(AfxGetStaticModuleState()); LONG lReturn = E_NOTIMPL; // NO LONGER IMPLEMENTED return lReturn; } /*++ SCardUIDlgSelectCard: This is the entry point routine to open the common dialog box, introduced in the Microsoft Smart Card SDK v1.x. Arguments: pOCNA - Pointer to an ANSI open card name (ex) structure. -or- pOCNW - Pointer to a UNICODE open card name (ex) structure. Return Value: A LONG value indicating the status of the requested action. Please see the Smartcard header files for additional information. Author: Amanda Matlosz 6/11/98 --*/ LONG WINAPI SCardUIDlgSelectCardA(LPOPENCARDNAMEA_EX pOCNA) { // Setup the correct module state information AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Locals LONG lReturn = SCARD_S_SUCCESS; CWnd wndParent; BOOL fEnableUI = FALSE; INT_PTR nResponse = IDCANCEL; int nResult = 0; DWORD dwOKCards = 0; try { // Check Params if (!CheckOCN(pOCNA)) { throw (LONG)SCARD_E_INVALID_VALUE; } // Determine names of all acceptable cards CTextMultistring mstrOKCards; ListAllOKCardNames(pOCNA, mstrOKCards); // // Do a silent search intially to determine # of suitable cards // currently available and/or connect to a card if min or no UI // lReturn = NoUISearch(pOCNA, &dwOKCards, (LPCSTR)mstrOKCards); // // If we haven't successfully selected a card and we can show UI, // raise the dialog // if (SCARD_S_SUCCESS != lReturn && !(pOCNA->dwFlags & SC_DLG_NO_UI)) { // Now we can init the common dialog wndParent.Attach(pOCNA->hwndOwner); CScInsertDlg dlgCommon(&wndParent); lReturn = dlgCommon.Initialize(pOCNA, dwOKCards, (LPCSTR)mstrOKCards); if(SCARD_S_SUCCESS != lReturn) { throw lReturn; } nResponse = dlgCommon.DoModal(); // If cancel/closed return error switch (nResponse) { case IDOK: // absolutely sure of total success! break; case IDCANCEL: lReturn = dlgCommon.m_lLastError; if (0 == lReturn) lReturn = SCARD_W_CANCELLED_BY_USER; // not SCARD_E_CANCELLED break; default: _ASSERTE(FALSE); case -1: case IDABORT: lReturn = dlgCommon.m_lLastError; if (0 == lReturn) lReturn = SCARD_F_UNKNOWN_ERROR; break; } } } catch (LONG hr) { lReturn = hr; TRACE_CATCH(_T("SCardUIDlgSelectCardA"),hr); } catch (...) { lReturn = (LONG) SCARD_E_UNEXPECTED; TRACE_CATCH_UNKNOWN(_T("SCardUIDlgSelectCardA")); } if (NULL != wndParent.m_hWnd) { wndParent.Detach(); } return lReturn; } LONG WINAPI SCardUIDlgSelectCardW(LPOPENCARDNAMEW_EX pOCNW) { // Setup the correct module state information AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Locals LONG lReturn = SCARD_S_SUCCESS; CWnd wndParent; BOOL fEnableUI = FALSE; INT_PTR nResponse = IDCANCEL; DWORD dwOKCards = 0; try { // Check Params if (!CheckOCN(pOCNW)) { throw (LONG)SCARD_E_INVALID_VALUE; } // Determine names of all acceptable cards CTextMultistring mstrOKCards; ListAllOKCardNames(pOCNW, mstrOKCards); // // Do a silent search intially to determine # of suitable cards and/or // connect to a card according to display mode (min or no UI) // lReturn = NoUISearch(pOCNW, &dwOKCards, (LPCWSTR)mstrOKCards); // // If we haven't successfully selected a card and we can show UI, // raise the dialog // if (SCARD_S_SUCCESS != lReturn && !(pOCNW->dwFlags & SC_DLG_NO_UI)) { // Now we can init the common dialog wndParent.Attach(pOCNW->hwndOwner); CScInsertDlg dlgCommon(&wndParent); // Store Pointer and open dialog lReturn = dlgCommon.Initialize(pOCNW, dwOKCards, (LPCWSTR)mstrOKCards); if (SCARD_S_SUCCESS != lReturn) { throw (lReturn); } nResponse = dlgCommon.DoModal(); // If cancel/closed return error switch (nResponse) { case IDOK: // absolutely sure of total success! break; case IDCANCEL: if (ERROR_SUCCESS == dlgCommon.m_lLastError) lReturn = SCARD_W_CANCELLED_BY_USER; else lReturn = dlgCommon.m_lLastError; break; default: _ASSERTE(FALSE); case -1: case IDABORT: lReturn = dlgCommon.m_lLastError; if (0 == lReturn) lReturn = SCARD_F_UNKNOWN_ERROR; break; } } } catch (LONG lErr) { lReturn = lErr; TRACE_CATCH(_T("SCardUIDlgSelectCardW"),lReturn); } catch (...) { lReturn = (LONG) SCARD_E_UNEXPECTED; TRACE_CATCH_UNKNOWN(_T("SCardUIDlgSelectCardW")); } if (NULL != wndParent.m_hWnd) { wndParent.Detach(); } return lReturn; } /*++ SCardUIDlgGetPIN: Arguments: Return Value: A LONG value indicating the status of the requested action. Author: Amanda Matlosz 06/18/1998 --*/ LONG WINAPI SCardUIDlgGetPINA(LPPINPROMPT pPinPrompt) { // Setup the correct module state information AFX_MANAGE_STATE(AfxGetStaticModuleState()); INT_PTR nResponse = IDCANCEL; // result of DoModal. CWnd wndParent; wndParent.Attach(pPinPrompt->hwndOwner); CGetPinDlg dlgGetPin(&wndParent); if (dlgGetPin.SetAttributes(pPinPrompt)) { nResponse = dlgGetPin.DoModal(); } if (NULL != wndParent.m_hWnd) { wndParent.Detach(); } return (LONG)nResponse; } /*++ SCardUIDlgChangePIN: Arguments: Return Value: A LONG value indicating the status of the requested action. Author: Amanda Matlosz 06/18/1998 --*/ LONG WINAPI SCardUIDlgChangePINA(LPCHANGEPIN pChangePin) { // Setup the correct module state information AFX_MANAGE_STATE(AfxGetStaticModuleState()); INT_PTR nResponse = IDCANCEL; // result of DoModal. CWnd wndParent; wndParent.Attach(pChangePin->hwndOwner); CChangePinDlg dlgChangePin(&wndParent); if (dlgChangePin.SetAttributes(pChangePin)) { nResponse = dlgChangePin.DoModal(); } if (NULL != wndParent.m_hWnd) { wndParent.Detach(); } return (LONG)nResponse; } /////////////////////////////////////////////////////////////////////////////// // Helper functions void MString2CommaList(CString& str, LPWSTR szmString) { str.Empty(); if (NULL == szmString) { return; } LPCWSTR szm = szmString; szm = FirstString(szm); str = szm; for(szm = NextString(szm); NULL != szm; szm = NextString(szm)) { str += ", "; str += szm; } } void MString2CommaList(CString& str, LPSTR szmString) { DWORD cchLength = 0; DWORD cchConverted = 0; DWORD dwSts = ERROR_SUCCESS; LPWSTR wszStr = NULL; USES_CONVERSION; str.Empty(); if (NULL == szmString) goto Ret; cchLength = MStrLen(szmString); cchConverted = MultiByteToWideChar( GetACP(), MB_PRECOMPOSED | MB_USEGLYPHCHARS, szmString, cchLength, NULL, 0); wszStr = (LPWSTR) HeapAlloc( GetProcessHeap(), 0, cchConverted * sizeof(WCHAR)); if (NULL == wszStr) goto Ret; MultiByteToWideChar( GetACP(), MB_PRECOMPOSED | MB_USEGLYPHCHARS, szmString, cchLength, wszStr, cchConverted); MString2CommaList(str, wszStr); Ret: if (wszStr) HeapFree(GetProcessHeap(), 0, wszStr); return; }