//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1999 - 1999 // // File: chPinDlg.cpp // //-------------------------------------------------------------------------- // chPinDlg.cpp : implementation file // #include "stdafx.h" #include #include #include #include "chPin.h" #include "chPinDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif static UINT AFX_CDECL WorkThread(LPVOID); static DWORD CSPType(IN LPCTSTR szProvider); ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CChangePinDlg dialog CChangePinDlg::CChangePinDlg(CWnd* pParent /*=NULL*/) : CDialog(CChangePinDlg::IDD, pParent) { //{{AFX_DATA_INIT(CChangePinDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CChangePinDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CChangePinDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CChangePinDlg, CDialog) //{{AFX_MSG_MAP(CChangePinDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_MESSAGE(APP_ALLDONE, OnAllDone) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CChangePinDlg message handlers BOOL CChangePinDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here m_pThread = AfxBeginThread(WorkThread, this); return TRUE; // return TRUE unless you set the focus to a control } void CChangePinDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CChangePinDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CChangePinDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } static UINT AFX_CDECL WorkThread( LPVOID pv) { static TCHAR szReader[MAX_PATH]; static TCHAR szCard[MAX_PATH]; static TCHAR szProvider[MAX_PATH]; static BYTE pbSignature[(1024 / 8) + (4 * sizeof(DWORD))]; CChangePinDlg *pDlg = (CChangePinDlg *)pv; OPENCARDNAME_EX ocn; OPENCARD_SEARCH_CRITERIA ocsc; SCARDCONTEXT hCtx = NULL; HCRYPTPROV hProv = NULL; HCRYPTKEY hKey = NULL; HCRYPTHASH hHash = NULL; DWORD dwSts, dwLen, dwKeyType; DWORD dwProvType; BOOL fSts; CString szFqcn; dwSts = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &hCtx); if (SCARD_S_SUCCESS != dwSts) goto ErrorExit; ZeroMemory(&ocsc, sizeof(ocsc)); ocsc.dwStructSize = sizeof(ocsc); // LPSTR lpstrGroupNames; // OPTIONAL reader groups to include in // DWORD nMaxGroupNames; // search. NULL defaults to // // SCard$DefaultReaders // LPCGUID rgguidInterfaces; // OPTIONAL requested interfaces // DWORD cguidInterfaces; // supported by card's SSP // LPSTR lpstrCardNames; // OPTIONAL requested card names; all cards w/ // DWORD nMaxCardNames; // matching ATRs will be accepted // LPOCNCHKPROC lpfnCheck; // OPTIONAL if NULL no user check will be performed. // LPOCNCONNPROCA lpfnConnect; // OPTIONAL if lpfnConnect is provided, // LPOCNDSCPROC lpfnDisconnect; // lpfnDisconnect must also be set. // LPVOID pvUserData; // OPTIONAL parameter to callbacks // DWORD dwShareMode; // OPTIONAL must be set if lpfnCheck is not null // DWORD dwPreferredProtocols; // OPTIONAL ZeroMemory(&ocn, sizeof(ocn)); ocn.dwStructSize = sizeof(ocn); ocn.hSCardContext = hCtx; ocn.hwndOwner = pDlg->m_hWnd; ocn.dwFlags = SC_DLG_FORCE_UI; ocn.lpstrTitle = TEXT("Change PIN Card Selection"); ocn.lpstrSearchDesc = TEXT("Select the Smart Card who's PIN is to be changed."); // HICON hIcon; // OPTIONAL 32x32 icon for your brand insignia ocn.pOpenCardSearchCriteria = &ocsc; // LPOCNCONNPROCA lpfnConnect; // OPTIONAL - performed on successful selection // LPVOID pvUserData; // OPTIONAL parameter to lpfnConnect // DWORD dwShareMode; // OPTIONAL - if lpfnConnect is NULL, dwShareMode and // DWORD dwPreferredProtocols; // OPTIONAL dwPreferredProtocols will be used to // // connect to the selected card ocn.lpstrRdr = szReader; ocn.nMaxRdr = sizeof(szReader) / sizeof(TCHAR); ocn.lpstrCard = szCard; ocn.nMaxCard = sizeof(szCard) / sizeof(TCHAR); // DWORD dwActiveProtocol; // [OUT] set only if dwShareMode not NULL // SCARDHANDLE hCardHandle; // [OUT] set if a card connection was indicated dwSts = SCardUIDlgSelectCard(&ocn); if (NULL != ocn.hCardHandle) dwSts = SCardDisconnect(ocn.hCardHandle, SCARD_LEAVE_CARD); if (SCARD_S_SUCCESS != dwSts) goto ErrorExit; // // The user has selected a card. Translate that into a CSP. // dwLen = sizeof(szProvider) / sizeof(TCHAR); dwSts = SCardGetCardTypeProviderName( hCtx, szCard, SCARD_PROVIDER_CSP, szProvider, &dwLen); if (SCARD_S_SUCCESS != dwSts) goto ErrorExit; dwSts = SCardReleaseContext(hCtx); hCtx = NULL; if (SCARD_S_SUCCESS != dwSts) goto ErrorExit; dwProvType = CSPType(szProvider); if (0 == dwProvType) { dwSts = NTE_PROV_TYPE_ENTRY_BAD; goto ErrorExit; } szFqcn = TEXT("\\\\.\\"); szFqcn += szReader; // // Activate a Key on the card. // fSts = CryptAcquireContext(&hProv, szFqcn, szProvider, dwProvType, 0); if (!fSts) { dwSts = GetLastError(); goto ErrorExit; } for (dwKeyType = AT_KEYEXCHANGE; dwKeyType <= AT_SIGNATURE; dwKeyType += 1) { fSts = CryptGetUserKey(hProv, dwKeyType, &hKey); if (fSts) break; } if (!fSts) { dwSts = GetLastError(); goto ErrorExit; } // // Use the CSP to force a PIN prompt. // fSts = CryptCreateHash(hProv, CALG_SHA, NULL, 0, &hHash); if (!fSts) { dwSts = GetLastError(); goto ErrorExit; } fSts = CryptHashData(hHash, (LPBYTE)szProvider, sizeof(szProvider), 0); if (!fSts) { dwSts = GetLastError(); goto ErrorExit; } dwLen = sizeof(pbSignature); fSts = CryptSignHash(hHash, dwKeyType, NULL, 0, pbSignature, &dwLen); // // All done. Clean up and notify the main thread that we're done. // ErrorExit: if (NULL != hHash) CryptDestroyHash(hHash); if (NULL != hKey) CryptDestroyKey(hKey); if (NULL != hProv) CryptReleaseContext(hProv, 0); if (NULL != hCtx) SCardReleaseContext(hCtx); if (SCARD_S_SUCCESS != dwSts) AfxMessageBox(ErrorString(dwSts), MB_ICONEXCLAMATION | MB_OK); pDlg->PostMessage(APP_ALLDONE); return 0; } /*++ CSPType: This function converts a CSP Name to a CSP Type. Arguments: szProvider supplies the name of the CSP. Return Value: The CSP type of the given CSP, or zero if no such CSP can be found. Author: Doug Barlow (dbarlow) 1/14/1999 --*/ static DWORD CSPType( IN LPCTSTR szProvider) { LONG nSts; HKEY hList = NULL; HKEY hProv = NULL; DWORD dwProvType, dwValType, dwValLen; nSts = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider"), 0, KEY_READ, &hList); if (ERROR_SUCCESS != nSts) goto ErrorExit; nSts = RegOpenKeyEx( hList, szProvider, 0, KEY_READ, &hProv); if (ERROR_SUCCESS != nSts) goto ErrorExit; dwValLen = sizeof(DWORD); dwProvType = 0; // Assumes little endian. nSts = RegQueryValueEx( hProv, TEXT("Type"), 0, &dwValType, (LPBYTE)&dwProvType, &dwValLen); if (ERROR_SUCCESS != nSts) goto ErrorExit; RegCloseKey(hProv); RegCloseKey(hList); return dwProvType; ErrorExit: if (NULL != hProv) RegCloseKey(hProv); if (NULL != hList) RegCloseKey(hList); return 0; } LRESULT CChangePinDlg::OnAllDone( WPARAM wParam, LPARAM lParam) { WaitForSingleObject(m_pThread->m_hThread, INFINITE); CDialog::OnOK(); return 0; }