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.
365 lines
9.7 KiB
365 lines
9.7 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 2000
|
|
|
|
Module Name:
|
|
|
|
pindlg.c
|
|
|
|
Abstract:
|
|
|
|
Window procedure for the PIN dialog
|
|
|
|
Notes:
|
|
|
|
<Implementation Details>
|
|
|
|
--*/
|
|
|
|
#include <windows.h>
|
|
|
|
// C RunTime Header Files
|
|
#include <stdlib.h>
|
|
#include <malloc.h>
|
|
#include <memory.h>
|
|
#include <tchar.h>
|
|
#include "resource.h"
|
|
#include "basecsp.h"
|
|
#include "pinlib.h"
|
|
#include "pindlg.h"
|
|
|
|
// Offset added to the bottom of the reference control to determine
|
|
// the bottom of the dialog
|
|
#define BORDER_OFFSET 7
|
|
|
|
/*++
|
|
|
|
PinDlgProc:
|
|
|
|
Message handler for PIN dialog box.
|
|
|
|
Arguments:
|
|
|
|
HWND hDlg handle to window
|
|
UINT message message identifier
|
|
WPARAM wParam first message parameter
|
|
LPARAM lParam second message parameter
|
|
|
|
Return Value:
|
|
|
|
TRUE if the message was processed or FALSE if it wasn't
|
|
|
|
Remarks:
|
|
|
|
<usageDetails>
|
|
|
|
--*/
|
|
INT_PTR CALLBACK PinDlgProc(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
PPIN_SHOW_GET_PIN_UI_INFO pInfo = (PPIN_SHOW_GET_PIN_UI_INFO)
|
|
GetWindowLongPtr(hDlg, GWLP_USERDATA);
|
|
int wmId, wmEvent;
|
|
DWORD cchPin = cchMAX_PIN_LENGTH;
|
|
WCHAR wszPin [cchMAX_PIN_LENGTH + 1];
|
|
DWORD cchNewPin = cchMAX_PIN_LENGTH;
|
|
WCHAR wszNewPin [cchMAX_PIN_LENGTH];
|
|
DWORD cchNewPinConfirm = cchMAX_PIN_LENGTH;
|
|
WCHAR wszNewPinConfirm [cchMAX_PIN_LENGTH];
|
|
DWORD dwSts = ERROR_SUCCESS;
|
|
PINCACHE_PINS Pins;
|
|
LPWSTR wszWrongPin = NULL;
|
|
DWORD cchWrongPin = 0;
|
|
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
|
|
// Store the caller's data - this is the buffer by which we'll return
|
|
// the user's pin.
|
|
SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR) lParam);
|
|
|
|
// The dialog shall be initially "small"
|
|
{
|
|
RECT xRefRect, xRect;
|
|
GetWindowRect(hDlg, &xRect);
|
|
GetWindowRect(GetDlgItem(hDlg, IDOK), &xRefRect);
|
|
xRect.bottom = xRefRect.bottom + BORDER_OFFSET;
|
|
MoveWindow(hDlg,
|
|
xRect.left, xRect.top,
|
|
xRect.right - xRect.left, xRect.bottom - xRect.top,
|
|
FALSE);
|
|
}
|
|
|
|
//
|
|
// Set the max input length for the various pin input fields
|
|
//
|
|
|
|
SendDlgItemMessage(
|
|
hDlg,
|
|
IDC_EDITPIN,
|
|
EM_LIMITTEXT,
|
|
cchMAX_PIN_LENGTH,
|
|
0);
|
|
|
|
SendDlgItemMessage(
|
|
hDlg,
|
|
IDC_EDITNEWPIN,
|
|
EM_LIMITTEXT,
|
|
cchMAX_PIN_LENGTH,
|
|
0);
|
|
|
|
SendDlgItemMessage(
|
|
hDlg,
|
|
IDC_EDITNEWPIN2,
|
|
EM_LIMITTEXT,
|
|
cchMAX_PIN_LENGTH,
|
|
0);
|
|
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
wmId = LOWORD(wParam);
|
|
wmEvent = HIWORD(wParam);
|
|
// Parse the menu selections:
|
|
switch (wmId)
|
|
{
|
|
case IDOK:
|
|
|
|
pInfo->dwError = ERROR_SUCCESS;
|
|
|
|
memset(&Pins, 0, sizeof(Pins));
|
|
|
|
//
|
|
// Find out what the user typed in
|
|
//
|
|
|
|
cchPin = GetDlgItemText(
|
|
hDlg,
|
|
IDC_EDITPIN,
|
|
wszPin,
|
|
cchMAX_PIN_LENGTH);
|
|
|
|
if (cchPin == 0)
|
|
goto InvalidPin;
|
|
|
|
// User entered something. See if it's a valid pin.
|
|
|
|
dwSts = PinStringToBytesW(
|
|
wszPin,
|
|
&Pins.cbCurrentPin,
|
|
&Pins.pbCurrentPin);
|
|
|
|
switch (dwSts)
|
|
{
|
|
case ERROR_SUCCESS:
|
|
// Just continue
|
|
break;
|
|
case ERROR_NOT_ENOUGH_MEMORY:
|
|
goto OutOfMemoryRet;
|
|
default:
|
|
goto InvalidPin;
|
|
}
|
|
|
|
// See if the user is requesting a pinchange
|
|
|
|
cchNewPin = GetDlgItemText(
|
|
hDlg,
|
|
IDC_EDITNEWPIN,
|
|
wszNewPin,
|
|
cchMAX_PIN_LENGTH);
|
|
|
|
if (0 != cchNewPin)
|
|
{
|
|
// See if the "confirmed" new pin matches the first new pin
|
|
|
|
cchNewPinConfirm = GetDlgItemText(
|
|
hDlg,
|
|
IDC_EDITNEWPIN2,
|
|
wszNewPinConfirm,
|
|
cchMAX_PIN_LENGTH);
|
|
|
|
if (0 != wcscmp(wszNewPin, wszNewPinConfirm))
|
|
{
|
|
// Display a warning message and let the user try again
|
|
MessageBoxEx(
|
|
hDlg,
|
|
pInfo->pStrings[StringNewPinMismatch].wszString,
|
|
pInfo->pStrings[StringPinMessageBoxTitle].wszString,
|
|
MB_OK | MB_ICONWARNING | MB_APPLMODAL,
|
|
0);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// See if the new pin is valid
|
|
dwSts = PinStringToBytesW(
|
|
wszNewPin,
|
|
&Pins.cbNewPin,
|
|
&Pins.pbNewPin);
|
|
|
|
switch (dwSts)
|
|
{
|
|
case ERROR_SUCCESS:
|
|
// Just continue
|
|
break;
|
|
case ERROR_NOT_ENOUGH_MEMORY:
|
|
goto OutOfMemoryRet;
|
|
default:
|
|
goto InvalidPin;
|
|
}
|
|
}
|
|
|
|
dwSts = pInfo->pfnVerify(
|
|
&Pins,
|
|
(PVOID) pInfo);
|
|
|
|
if (ERROR_SUCCESS != dwSts)
|
|
goto InvalidPin;
|
|
|
|
// Pin appears to be good. We're done.
|
|
|
|
// Return the appropriate validated pin to the caller
|
|
if (NULL != Pins.pbNewPin)
|
|
{
|
|
pInfo->pbPin = Pins.pbNewPin;
|
|
pInfo->cbPin = Pins.cbNewPin;
|
|
Pins.pbNewPin = NULL;
|
|
}
|
|
else
|
|
{
|
|
pInfo->pbPin = Pins.pbCurrentPin;
|
|
pInfo->cbPin = Pins.cbCurrentPin;
|
|
Pins.pbCurrentPin = NULL;
|
|
}
|
|
|
|
EndDialog(hDlg, wmId);
|
|
goto CommonRet;
|
|
|
|
case IDCANCEL:
|
|
pInfo->dwError = SCARD_W_CANCELLED_BY_USER;
|
|
|
|
EndDialog(hDlg, wmId);
|
|
return TRUE;
|
|
|
|
case IDC_BUTTONOPTIONS:
|
|
{
|
|
RECT xRefRect, xRect;
|
|
LPCTSTR lpszNewText;
|
|
HWND hWnd;
|
|
|
|
GetWindowRect(hDlg, &xRect);
|
|
GetWindowRect(GetDlgItem(hDlg, IDOK), &xRefRect);
|
|
|
|
if (xRect.bottom == xRefRect.bottom + BORDER_OFFSET)
|
|
{ // if dialog is small, make it big
|
|
GetWindowRect(GetDlgItem(hDlg, IDC_EDITNEWPIN2), &xRefRect);
|
|
// Change the button label accordingly
|
|
lpszNewText = _T("&Options <<");
|
|
}
|
|
else // otherwise shrink it
|
|
{
|
|
// Change the button label accordingly
|
|
lpszNewText = _T("&Options >>");
|
|
}
|
|
|
|
xRect.bottom = xRefRect.bottom + BORDER_OFFSET;
|
|
MoveWindow(hDlg,
|
|
xRect.left, xRect.top,
|
|
xRect.right - xRect.left, xRect.bottom - xRect.top,
|
|
TRUE);
|
|
SetDlgItemText(hDlg, IDC_BUTTONOPTIONS, lpszNewText);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
InvalidPin:
|
|
|
|
// See if valid "Attempts Remaining" info was supplied. If so, display
|
|
// it to the user.
|
|
if (((DWORD) -1) != pInfo->cAttemptsRemaining)
|
|
{
|
|
cchWrongPin =
|
|
wcslen(pInfo->pStrings[StringWrongPin].wszString) + 3 +
|
|
wcslen(pInfo->pStrings[StringPinRetries].wszString) + 3 + 2 + 1;
|
|
|
|
wszWrongPin = (LPWSTR) CspAllocH(cchWrongPin * sizeof(WCHAR));
|
|
|
|
if (NULL == wszWrongPin)
|
|
goto OutOfMemoryRet;
|
|
|
|
wsprintf(
|
|
wszWrongPin,
|
|
L"%s. %s: %02d",
|
|
pInfo->pStrings[StringWrongPin].wszString,
|
|
pInfo->pStrings[StringPinRetries].wszString,
|
|
pInfo->cAttemptsRemaining & 0x0F);
|
|
}
|
|
else
|
|
{
|
|
cchWrongPin =
|
|
wcslen(pInfo->pStrings[StringWrongPin].wszString) + 2;
|
|
|
|
wszWrongPin = (LPWSTR) CspAllocH(cchWrongPin * sizeof(WCHAR));
|
|
|
|
if (NULL == wszWrongPin)
|
|
goto OutOfMemoryRet;
|
|
|
|
wsprintf(
|
|
wszWrongPin,
|
|
L"%s.",
|
|
pInfo->pStrings[StringWrongPin].wszString);
|
|
}
|
|
|
|
// Display a warning message and let the user try again, if they'd like.
|
|
MessageBoxEx(
|
|
hDlg,
|
|
wszWrongPin,
|
|
pInfo->pStrings[StringPinMessageBoxTitle].wszString,
|
|
MB_OK | MB_ICONWARNING | MB_APPLMODAL,
|
|
0);
|
|
|
|
//
|
|
// Clear the pin edit boxes since the current pin is wrong
|
|
//
|
|
|
|
SetDlgItemText(hDlg, IDC_EDITPIN, L"");
|
|
SetDlgItemText(hDlg, IDC_EDITNEWPIN, L"");
|
|
SetDlgItemText(hDlg, IDC_EDITNEWPIN2, L"");
|
|
|
|
CommonRet:
|
|
|
|
if (NULL != wszWrongPin)
|
|
CspFreeH(wszWrongPin);
|
|
|
|
if (NULL != Pins.pbCurrentPin)
|
|
{
|
|
RtlSecureZeroMemory(Pins.pbCurrentPin, Pins.cbCurrentPin);
|
|
CspFreeH(Pins.pbCurrentPin);
|
|
}
|
|
|
|
if (NULL != Pins.pbNewPin)
|
|
{
|
|
RtlSecureZeroMemory(Pins.pbNewPin, Pins.cbNewPin);
|
|
CspFreeH(Pins.pbNewPin);
|
|
}
|
|
|
|
if (ERROR_SUCCESS != pInfo->dwError)
|
|
EndDialog(hDlg, wmId);
|
|
|
|
return TRUE;
|
|
|
|
OutOfMemoryRet:
|
|
|
|
pInfo->dwError = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto CommonRet;
|
|
}
|