1591 lines
43 KiB
C++
1591 lines
43 KiB
C++
/****************************************************************************
|
|
|
|
Copyright (c) 1998-1999 Microsoft Corporation
|
|
|
|
Module Name: card.cpp
|
|
|
|
Abstract: Calling Card Object implementation
|
|
|
|
Author: noela - 09/11/98
|
|
|
|
Notes:
|
|
|
|
|
|
Rev History:
|
|
|
|
****************************************************************************/
|
|
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
|
|
#if WINNT
|
|
#else
|
|
#include <help.h>
|
|
#endif
|
|
|
|
#include <tchar.h>
|
|
#include <prsht.h>
|
|
#include <stdlib.h>
|
|
#include "tapi.h"
|
|
#include "tspi.h"
|
|
#include "utils.h"
|
|
#include "cplResource.h"
|
|
#include "client.h"
|
|
#include "clntprivate.h"
|
|
#include "card.h"
|
|
#include "location.h"
|
|
#include <shlwapi.h>
|
|
#include <shlwapip.h>
|
|
#include "rules.h"
|
|
|
|
#include "tregupr2.h"
|
|
|
|
#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
|
|
|
|
#ifdef DBG
|
|
#define assert(condition) if(condition);else \
|
|
{ DebugAssertFailure (__FILE__, __LINE__, #condition); }
|
|
|
|
static void DebugAssertFailure (LPCSTR file, DWORD line, LPCSTR condition);
|
|
|
|
#else
|
|
|
|
#define assert(condition)
|
|
|
|
#endif
|
|
|
|
|
|
#define CLIENT_FREE(x) \
|
|
if (x) { ClientFree(x); (x)=NULL;} else;
|
|
|
|
#define TRACE_DWERROR() LOG((TL_ERROR, "Error %x at line %d in file %hs", dwError, __LINE__, __FILE__))
|
|
#define TRACE_HRESULT() LOG((TL_ERROR, "Error %x at line %d in file %hs", Result, __LINE__, __FILE__))
|
|
|
|
#define EXIT_IF_DWERROR() \
|
|
if(dwError !=ERROR_SUCCESS) \
|
|
{ \
|
|
TRACE_DWERROR(); \
|
|
goto forced_exit; \
|
|
}
|
|
|
|
#define EXIT_IF_FAILED() \
|
|
if(FAILED(Result)) \
|
|
{ \
|
|
TRACE_HRESULT(); \
|
|
goto forced_exit; \
|
|
}
|
|
|
|
|
|
#define MAX_NUMBER_LEN 15
|
|
|
|
|
|
|
|
const TCHAR gszCardsPath[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Cards");
|
|
const TCHAR gszTelephonyPath[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Telephony");
|
|
|
|
const TCHAR gszCardW[] = TEXT("Card");
|
|
const TCHAR gszCardNameW[] = TEXT("Name");
|
|
const TCHAR gszLocalRuleW[] = TEXT("LocalRule");
|
|
const TCHAR gszLDRuleW[] = TEXT("LDRule");
|
|
const TCHAR gszInternationalRuleW[] = TEXT("InternationalRule");
|
|
const TCHAR gszLocalAccessNumberW[] = TEXT("LocalAccessNumber");
|
|
const TCHAR gszLDAccessNumberW[] = TEXT("LDAccessNumber");
|
|
const TCHAR gszInternationalAccessNumberW[] = TEXT("InternationalAccessNumber");
|
|
const TCHAR gszAccountNumberW[] = TEXT("AccountNumber");
|
|
const TCHAR gszPinW[] = TEXT("Pin");
|
|
|
|
const TCHAR gszFlags[] = TEXT("Flags");
|
|
const TCHAR gszCard[] = TEXT("Card");
|
|
const TCHAR gszCards[] = TEXT("Cards");
|
|
const TCHAR gszNextID[] = TEXT("NextID");
|
|
const TCHAR gszCardListVersion[] = TEXT("CardListVersion");
|
|
|
|
const TCHAR gszResourceLibrary[] = TEXT("TAPIUI.DLL");
|
|
|
|
const TCHAR gszSystemSetupPath[] = TEXT("System\\Setup");
|
|
const TCHAR gszSystemSetupInProgress[] = TEXT("SystemSetupInProgress");
|
|
|
|
static BOOL ValidValue(PWSTR);
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCard
|
|
Method : Constructor
|
|
|
|
****************************************************************************/
|
|
CCallingCard::CCallingCard()
|
|
{
|
|
m_dwCardID = 0;
|
|
m_pszCardName = NULL;;
|
|
|
|
m_pszPIN = NULL;
|
|
m_pszEncryptedPIN = NULL;
|
|
m_pszAccountNumber = NULL;
|
|
|
|
m_pszLocalAccessNumber = NULL;
|
|
m_pszLongDistanceAccessNumber = NULL;
|
|
m_pszInternationalAccessNumber = NULL;
|
|
|
|
m_pszCardPath = NULL;
|
|
m_hCard = NULL;
|
|
|
|
m_bDirty = FALSE;
|
|
m_bDeleted = FALSE;
|
|
|
|
m_dwFlags = 0; // by default
|
|
|
|
m_dwCryptInitResult = TapiCryptInitialize();
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCard
|
|
Method : Destructor
|
|
|
|
****************************************************************************/
|
|
CCallingCard::~CCallingCard()
|
|
{
|
|
CleanUp();
|
|
|
|
TapiCryptUninitialize();
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCard
|
|
Method : CleanUp
|
|
|
|
Clean up memory allocations
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
void CCallingCard::CleanUp(void)
|
|
{
|
|
CLIENT_FREE(m_pszCardName);
|
|
CLIENT_FREE(m_pszPIN);
|
|
CLIENT_FREE(m_pszEncryptedPIN);
|
|
CLIENT_FREE(m_pszAccountNumber);
|
|
CLIENT_FREE(m_pszLocalAccessNumber);
|
|
CLIENT_FREE(m_pszLongDistanceAccessNumber);
|
|
CLIENT_FREE(m_pszInternationalAccessNumber);
|
|
|
|
CLIENT_FREE(m_Rules.m_pszInternationalRule);
|
|
CLIENT_FREE(m_Rules.m_pszLongDistanceRule);
|
|
CLIENT_FREE(m_Rules.m_pszLocalRule);
|
|
|
|
CLIENT_FREE(m_pszCardPath);
|
|
CloseCardKey();
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCard
|
|
Method : Initialize - external parameters
|
|
|
|
Only for new calling cards (not present in registry)
|
|
|
|
****************************************************************************/
|
|
HRESULT CCallingCard::Initialize
|
|
(
|
|
DWORD dwCardID,
|
|
PWSTR pszCardName,
|
|
DWORD dwFlags,
|
|
PWSTR pszPIN,
|
|
PWSTR pszAccountNumber,
|
|
PWSTR pszInternationalRule,
|
|
PWSTR pszLongDistanceRule,
|
|
PWSTR pszLocalRule,
|
|
PWSTR pszInternationalAccessNumber,
|
|
PWSTR pszLongDistanceAccessNumber,
|
|
PWSTR pszLocalAccessNumber
|
|
)
|
|
{
|
|
HRESULT Result = S_OK;
|
|
|
|
#define CALLING_CARD_INIT(param) \
|
|
m_##param = ClientAllocString(param); \
|
|
if(m_##param == NULL) \
|
|
{ \
|
|
LOG((TL_ERROR, "Initialize create m_%s failed", _T(#param))); \
|
|
CleanUp(); \
|
|
return E_OUTOFMEMORY; \
|
|
}
|
|
|
|
CALLING_CARD_INIT(pszCardName)
|
|
CALLING_CARD_INIT(pszPIN)
|
|
CALLING_CARD_INIT(pszAccountNumber)
|
|
CALLING_CARD_INIT(pszInternationalAccessNumber)
|
|
CALLING_CARD_INIT(pszLongDistanceAccessNumber)
|
|
CALLING_CARD_INIT(pszLocalAccessNumber)
|
|
|
|
#undef CALLING_CARD_INIT
|
|
|
|
//////////////////////////////////////////////////
|
|
// copy the set of three Rules
|
|
//
|
|
Result = m_Rules.Initialize( pszInternationalRule,
|
|
pszLongDistanceRule,
|
|
pszLocalRule );
|
|
if(FAILED(Result))
|
|
{
|
|
LOG((TL_ERROR, "Initialize create m_Rules failed" ));
|
|
CleanUp();
|
|
return Result;
|
|
}
|
|
|
|
m_dwCardID = dwCardID;
|
|
m_dwFlags = dwFlags;
|
|
|
|
m_bDirty = TRUE;
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCard
|
|
Method : Initialize - from registry
|
|
|
|
|
|
****************************************************************************/
|
|
HRESULT CCallingCard::Initialize
|
|
(
|
|
DWORD dwCardID
|
|
)
|
|
{
|
|
|
|
DWORD dwError;
|
|
DWORD dwType;
|
|
DWORD dwLength;
|
|
|
|
m_dwCardID = dwCardID;
|
|
|
|
// open the registry key
|
|
dwError = OpenCardKey(FALSE);
|
|
|
|
if(dwError != ERROR_SUCCESS)
|
|
{
|
|
// If the key does not exist, it will be created at the first save
|
|
if(dwError==ERROR_FILE_NOT_FOUND)
|
|
{
|
|
m_bDirty = TRUE;
|
|
}
|
|
return(HRESULT_FROM_WIN32(dwError));
|
|
}
|
|
|
|
#define READ_CARD_VAL(Member, Name) \
|
|
dwError = ReadOneStringValue(&##Member, Name); \
|
|
if(dwError != ERROR_SUCCESS) \
|
|
{ \
|
|
TRACE_DWERROR(); \
|
|
CleanUp(); \
|
|
return HRESULT_FROM_WIN32(dwError); \
|
|
}
|
|
|
|
READ_CARD_VAL(m_pszCardName, gszCardNameW);
|
|
READ_CARD_VAL(m_pszEncryptedPIN, gszPinW);
|
|
// READ_CARD_VAL(m_pszPIN, gszPinW);
|
|
READ_CARD_VAL(m_pszAccountNumber, gszAccountNumberW);
|
|
READ_CARD_VAL(m_pszLocalAccessNumber, gszLocalAccessNumberW);
|
|
READ_CARD_VAL(m_pszLongDistanceAccessNumber, gszLDAccessNumberW);
|
|
READ_CARD_VAL(m_pszInternationalAccessNumber, gszInternationalAccessNumberW);
|
|
READ_CARD_VAL(m_Rules.m_pszLocalRule, gszLocalRuleW);
|
|
READ_CARD_VAL(m_Rules.m_pszLongDistanceRule, gszLDRuleW);
|
|
READ_CARD_VAL(m_Rules.m_pszInternationalRule, gszInternationalRuleW);
|
|
|
|
#undef READ_CARD_VAL
|
|
|
|
// Decrypt the PIN number
|
|
dwError = DecryptPIN();
|
|
if(dwError != ERROR_SUCCESS)
|
|
{
|
|
TRACE_DWERROR();
|
|
CleanUp();
|
|
return HRESULT_FACILITY(dwError)==0 ? HRESULT_FROM_WIN32(dwError) : dwError;
|
|
}
|
|
|
|
dwLength = sizeof(m_dwFlags);
|
|
dwError = RegQueryValueEx ( m_hCard,
|
|
gszFlags,
|
|
NULL,
|
|
&dwType,
|
|
(PBYTE)&m_dwFlags,
|
|
&dwLength
|
|
);
|
|
|
|
if(dwError != ERROR_SUCCESS)
|
|
{
|
|
TRACE_DWERROR();
|
|
CleanUp();
|
|
return HRESULT_FROM_WIN32(dwError);
|
|
}
|
|
|
|
CloseCardKey();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCard
|
|
Method : SaveToRegistry
|
|
|
|
|
|
****************************************************************************/
|
|
|
|
HRESULT CCallingCard::SaveToRegistry(void)
|
|
{
|
|
DWORD dwError;
|
|
|
|
if(!m_bDirty)
|
|
// nothing to save
|
|
return S_OK;
|
|
//open/create the registry key
|
|
dwError = OpenCardKey(TRUE);
|
|
if(dwError != ERROR_SUCCESS)
|
|
return HRESULT_FROM_WIN32(dwError);
|
|
|
|
assert(m_hCard);
|
|
assert(m_pszCardPath);
|
|
|
|
if(m_bDeleted)
|
|
{
|
|
CloseCardKey();
|
|
|
|
dwError = RegDeleteKey (HKEY_CURRENT_USER,
|
|
m_pszCardPath);
|
|
|
|
if(dwError != ERROR_SUCCESS)
|
|
return HRESULT_FROM_WIN32(dwError);
|
|
|
|
m_bDirty = FALSE;
|
|
|
|
return S_OK;
|
|
}
|
|
// Encrypt the PIN number
|
|
dwError = EncryptPIN();
|
|
if(dwError != ERROR_SUCCESS)
|
|
{
|
|
TRACE_DWERROR();
|
|
return HRESULT_FACILITY(dwError)==0 ? HRESULT_FROM_WIN32(dwError) : dwError;
|
|
}
|
|
|
|
// Save !
|
|
|
|
#define CARD_SAVE_STRING(Member, Name) \
|
|
dwError = TAPIRegSetValueExW( m_hCard, \
|
|
Name, \
|
|
0, \
|
|
REG_SZ, \
|
|
(PBYTE) Member, \
|
|
(wcslen(Member)+1)*sizeof(WCHAR) \
|
|
) ; \
|
|
if(dwError != ERROR_SUCCESS) \
|
|
{ \
|
|
TRACE_DWERROR(); \
|
|
CloseCardKey(); \
|
|
return HRESULT_FROM_WIN32(dwError); \
|
|
}
|
|
|
|
CARD_SAVE_STRING(m_pszCardName, gszCardNameW);
|
|
CARD_SAVE_STRING(m_pszEncryptedPIN, gszPinW);
|
|
CARD_SAVE_STRING(m_pszAccountNumber, gszAccountNumberW);
|
|
CARD_SAVE_STRING(m_pszLocalAccessNumber, gszLocalAccessNumberW);
|
|
CARD_SAVE_STRING(m_pszLongDistanceAccessNumber, gszLDAccessNumberW);
|
|
CARD_SAVE_STRING(m_pszInternationalAccessNumber, gszInternationalAccessNumberW);
|
|
CARD_SAVE_STRING(m_Rules.m_pszLocalRule, gszLocalRuleW);
|
|
CARD_SAVE_STRING(m_Rules.m_pszLongDistanceRule, gszLDRuleW);
|
|
CARD_SAVE_STRING(m_Rules.m_pszInternationalRule, gszInternationalRuleW);
|
|
|
|
#undef CARD_SAVE_STRING
|
|
|
|
dwError = RegSetValueEx ( m_hCard,
|
|
gszFlags,
|
|
0,
|
|
REG_DWORD,
|
|
(PBYTE)&m_dwFlags,
|
|
sizeof(m_dwFlags)
|
|
);
|
|
if(dwError != ERROR_SUCCESS)
|
|
{
|
|
TRACE_DWERROR();
|
|
CloseCardKey();
|
|
return HRESULT_FROM_WIN32(dwError);
|
|
}
|
|
|
|
m_bDirty = FALSE;
|
|
|
|
CloseCardKey();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCard
|
|
Method : MarkDeleted
|
|
|
|
Mark the card as deleted
|
|
|
|
****************************************************************************/
|
|
|
|
HRESULT CCallingCard::MarkDeleted(void)
|
|
{
|
|
m_bDirty = TRUE;
|
|
|
|
if (m_dwFlags & CARD_BUILTIN)
|
|
{
|
|
// a builtin card is only hidden, not deleted
|
|
m_dwFlags |= CARD_HIDE;
|
|
return S_OK;
|
|
}
|
|
|
|
m_bDeleted = TRUE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCard
|
|
Method : Validate
|
|
|
|
Returns 0 if the card contains complete and valid rules, or
|
|
a series of flags if the card is missing any required data.
|
|
|
|
****************************************************************************/
|
|
|
|
DWORD CCallingCard::Validate(void)
|
|
{
|
|
DWORD dwResult = 0;
|
|
|
|
// Does the card have a name?
|
|
if (!*m_pszCardName)
|
|
{
|
|
dwResult |= CCVF_NOCARDNAME;
|
|
}
|
|
|
|
// Does the card have any rules?
|
|
if (!*(m_Rules.m_pszInternationalRule) &&
|
|
!*(m_Rules.m_pszLocalRule) &&
|
|
!*(m_Rules.m_pszLongDistanceRule) )
|
|
{
|
|
dwResult |= CCVF_NOCARDRULES;
|
|
}
|
|
else
|
|
{
|
|
DWORD dwFieldsToCheck = 0;;
|
|
|
|
struct
|
|
{
|
|
PWSTR pwszRule;
|
|
DWORD dwAccesFlag;
|
|
}
|
|
aData[] =
|
|
{
|
|
{m_Rules.m_pszInternationalRule, CCVF_NOINTERNATIONALACCESSNUMBER},
|
|
{m_Rules.m_pszLocalRule, CCVF_NOLOCALACCESSNUMBER},
|
|
{m_Rules.m_pszLongDistanceRule, CCVF_NOLONGDISTANCEACCESSNUMBER},
|
|
};
|
|
|
|
// Foreach rule, is the required rule data available? We need to check
|
|
// for use of the PIN number, CardNumber, and all three access numbers.
|
|
// If any of these fields is used, then we need to verify that data has
|
|
// been entered for those fields. The data is only required if it is
|
|
// actually used in a rule.
|
|
for (int i=0; i<ARRAYSIZE(aData); i++)
|
|
{
|
|
if (StrChrW(aData[i].pwszRule, L'K'))
|
|
{
|
|
dwFieldsToCheck |= CCVF_NOCARDNUMBER;
|
|
}
|
|
if (StrChrW(aData[i].pwszRule, L'H'))
|
|
{
|
|
dwFieldsToCheck |= CCVF_NOPINNUMBER;
|
|
}
|
|
if (StrChrW(aData[i].pwszRule, L'J'))
|
|
{
|
|
dwFieldsToCheck |= aData[i].dwAccesFlag;
|
|
}
|
|
}
|
|
if (dwFieldsToCheck & CCVF_NOCARDNUMBER)
|
|
{
|
|
if (!ValidValue(m_pszAccountNumber))
|
|
{
|
|
dwResult |= CCVF_NOCARDNUMBER;
|
|
}
|
|
}
|
|
if (dwFieldsToCheck & CCVF_NOPINNUMBER)
|
|
{
|
|
if (!ValidValue(m_pszPIN))
|
|
{
|
|
dwResult |= CCVF_NOPINNUMBER;
|
|
}
|
|
}
|
|
if (dwFieldsToCheck & CCVF_NOINTERNATIONALACCESSNUMBER)
|
|
{
|
|
if (!ValidValue(m_pszInternationalAccessNumber))
|
|
{
|
|
dwResult |= CCVF_NOINTERNATIONALACCESSNUMBER;
|
|
}
|
|
}
|
|
if (dwFieldsToCheck & CCVF_NOLOCALACCESSNUMBER)
|
|
{
|
|
if (!ValidValue(m_pszLocalAccessNumber))
|
|
{
|
|
dwResult |= CCVF_NOLOCALACCESSNUMBER;
|
|
}
|
|
}
|
|
if (dwFieldsToCheck & CCVF_NOLONGDISTANCEACCESSNUMBER)
|
|
{
|
|
if (!ValidValue(m_pszLongDistanceAccessNumber))
|
|
{
|
|
dwResult |= CCVF_NOLONGDISTANCEACCESSNUMBER;
|
|
}
|
|
}
|
|
}
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCard
|
|
Method : Set##Member
|
|
|
|
****************************************************************************/
|
|
|
|
#define SET_METHOD(Member) \
|
|
HRESULT CCallingCard::Set##Member(PWSTR Value) \
|
|
{ \
|
|
PWSTR pszTemp = NULL; \
|
|
\
|
|
if(Value == NULL) \
|
|
return E_INVALIDARG; \
|
|
\
|
|
pszTemp = ClientAllocString(Value); \
|
|
if(pszTemp==NULL) \
|
|
{ \
|
|
return E_OUTOFMEMORY; \
|
|
} \
|
|
\
|
|
CLIENT_FREE(m_psz##Member); \
|
|
m_psz##Member = pszTemp; \
|
|
\
|
|
m_bDirty = TRUE; \
|
|
\
|
|
return S_OK; \
|
|
}
|
|
|
|
SET_METHOD(CardName);
|
|
SET_METHOD(PIN);
|
|
SET_METHOD(AccountNumber);
|
|
SET_METHOD(InternationalAccessNumber);
|
|
SET_METHOD(LongDistanceAccessNumber);
|
|
SET_METHOD(LocalAccessNumber);
|
|
|
|
#define m_pszInternationalRule m_Rules.m_pszInternationalRule
|
|
#define m_pszLongDistanceRule m_Rules.m_pszLongDistanceRule
|
|
#define m_pszLocalRule m_Rules.m_pszLocalRule
|
|
|
|
SET_METHOD(InternationalRule);
|
|
SET_METHOD(LongDistanceRule);
|
|
SET_METHOD(LocalRule);
|
|
|
|
#undef m_pszInternationalRule
|
|
#undef m_pszLongDistanceRule
|
|
#undef m_pszLocalRule
|
|
|
|
#undef SET_METHOD
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCard
|
|
Method : OpenCardKey
|
|
|
|
Opens the registry key for the card
|
|
|
|
****************************************************************************/
|
|
|
|
DWORD CCallingCard::OpenCardKey(BOOL bWrite)
|
|
{
|
|
DWORD dwDisp;
|
|
DWORD dwError;
|
|
|
|
if(m_pszCardPath==NULL)
|
|
{
|
|
DWORD dwLength;
|
|
|
|
// Absolute path: Software.....Cards\CardX
|
|
dwLength = ARRAYSIZE(gszCardsPath)+ARRAYSIZE(gszCard)+MAX_NUMBER_LEN;
|
|
|
|
m_pszCardPath = (PTSTR)ClientAlloc(dwLength*sizeof(TCHAR));
|
|
if (m_pszCardPath==NULL)
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
wsprintf(m_pszCardPath, TEXT("%s\\%s%d"), gszCardsPath, gszCard, m_dwCardID);
|
|
}
|
|
|
|
if(bWrite)
|
|
{
|
|
// Creates the key if it does not exist
|
|
dwError = RegCreateKeyEx ( HKEY_CURRENT_USER,
|
|
m_pszCardPath,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_QUERY_VALUE | KEY_SET_VALUE,
|
|
NULL,
|
|
&m_hCard,
|
|
&dwDisp
|
|
);
|
|
}
|
|
else
|
|
{
|
|
dwError = RegOpenKeyEx( HKEY_CURRENT_USER,
|
|
m_pszCardPath,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&m_hCard
|
|
);
|
|
}
|
|
return dwError;
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCard
|
|
Method : CloseCardKey
|
|
|
|
Opens the registry key for the card
|
|
|
|
****************************************************************************/
|
|
|
|
DWORD CCallingCard::CloseCardKey(void)
|
|
{
|
|
if(m_hCard)
|
|
{
|
|
RegCloseKey(m_hCard);
|
|
m_hCard = NULL;
|
|
}
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCard
|
|
Method : ReadOneStringValue
|
|
|
|
Read and allocates a string value
|
|
|
|
****************************************************************************/
|
|
|
|
DWORD CCallingCard::ReadOneStringValue(PWSTR *pMember, const TCHAR *pszName)
|
|
{
|
|
DWORD dwError;
|
|
DWORD dwLength;
|
|
DWORD dwType;
|
|
PTSTR pszBuffer;
|
|
|
|
assert(m_hCard);
|
|
assert(pMember);
|
|
assert(pszName);
|
|
|
|
// find the length needed
|
|
dwError = RegQueryValueEx ( m_hCard,
|
|
pszName,
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwLength
|
|
);
|
|
if (dwError != ERROR_SUCCESS)
|
|
return dwError;
|
|
if (dwType != REG_SZ)
|
|
return ERROR_INVALID_DATA;
|
|
|
|
pszBuffer = (PTSTR)ClientAlloc(dwLength);
|
|
if (pszBuffer == NULL)
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
dwError = RegQueryValueEx ( m_hCard,
|
|
pszName,
|
|
NULL,
|
|
&dwType,
|
|
(PBYTE)(pszBuffer),
|
|
&dwLength
|
|
);
|
|
if(dwError != ERROR_SUCCESS)
|
|
{
|
|
ClientFree(pszBuffer);
|
|
return dwError;
|
|
}
|
|
|
|
// convert the required bytes for the TCHAR string into the number of characters in the string.
|
|
dwLength = dwLength / sizeof(TCHAR);
|
|
*pMember = (PWSTR)ClientAlloc( dwLength * sizeof(WCHAR) );
|
|
if ( NULL == *pMember )
|
|
{
|
|
ClientFree(pszBuffer);
|
|
return ERROR_OUTOFMEMORY;
|
|
}
|
|
SHTCharToUnicode(pszBuffer, *pMember, dwLength);
|
|
|
|
ClientFree(pszBuffer);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCard
|
|
Method : EncryptPIN
|
|
|
|
Encrypts the PIN
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
DWORD CCallingCard::EncryptPIN(void)
|
|
{
|
|
DWORD dwError;
|
|
DWORD dwLength;
|
|
PWSTR pszTemp = NULL;
|
|
|
|
// free any existing encrypted string
|
|
CLIENT_FREE(m_pszEncryptedPIN);
|
|
|
|
dwError = TapiEncrypt(m_pszPIN, m_dwCardID, NULL, &dwLength);
|
|
if(dwError != ERROR_SUCCESS)
|
|
{
|
|
LOG((TL_ERROR, "EncryptPIN: TapiEncrypt (1) failed"));
|
|
return dwError;
|
|
}
|
|
|
|
pszTemp = (PWSTR)ClientAlloc(dwLength*sizeof(WCHAR));
|
|
if(pszTemp==NULL)
|
|
{
|
|
return ERROR_OUTOFMEMORY;
|
|
}
|
|
|
|
dwError = TapiEncrypt(m_pszPIN, m_dwCardID, pszTemp, &dwLength);
|
|
if(dwError != ERROR_SUCCESS)
|
|
{
|
|
LOG((TL_ERROR, "EncryptPIN: TapiEncrypt (2) failed"));
|
|
ClientFree(pszTemp);
|
|
return dwError;
|
|
}
|
|
|
|
m_pszEncryptedPIN = pszTemp;
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCard
|
|
Method : DecryptPIN
|
|
|
|
Decrypts the PIN
|
|
|
|
****************************************************************************/
|
|
|
|
DWORD CCallingCard::DecryptPIN(void)
|
|
{
|
|
DWORD dwError;
|
|
DWORD dwLength;
|
|
PWSTR pszTemp = NULL;
|
|
|
|
// free any existing string
|
|
CLIENT_FREE(m_pszPIN);
|
|
|
|
dwError = TapiDecrypt(m_pszEncryptedPIN, m_dwCardID, NULL, &dwLength);
|
|
if(dwError != ERROR_SUCCESS)
|
|
{
|
|
LOG((TL_ERROR, "DecryptPIN: TapiDecrypt (1) failed"));
|
|
return dwError;
|
|
}
|
|
|
|
pszTemp = (PWSTR)ClientAlloc(dwLength*sizeof(WCHAR));
|
|
if(pszTemp==NULL)
|
|
{
|
|
return ERROR_OUTOFMEMORY;
|
|
}
|
|
|
|
dwError = TapiDecrypt(m_pszEncryptedPIN, m_dwCardID, pszTemp, &dwLength);
|
|
if(dwError != ERROR_SUCCESS)
|
|
{
|
|
LOG((TL_ERROR, "DecryptPIN: TapiDecrypt (2) failed"));
|
|
// return a NULL PIN
|
|
*pszTemp = L'\0';
|
|
dwError = ERROR_SUCCESS;
|
|
}
|
|
|
|
m_pszPIN = pszTemp;
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCards
|
|
Method : Constructor
|
|
|
|
****************************************************************************/
|
|
|
|
CCallingCards::CCallingCards()
|
|
{
|
|
m_dwNumEntries = 0;
|
|
m_dwNextID = 0;
|
|
|
|
m_hCards = NULL;
|
|
|
|
m_hEnumNode = m_CallingCardList.head();
|
|
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCards
|
|
Method : Destructor
|
|
|
|
****************************************************************************/
|
|
|
|
CCallingCards::~CCallingCards()
|
|
{
|
|
CCallingCardNode *node;
|
|
|
|
node = m_CallingCardList.head();
|
|
|
|
while( !node->beyond_tail() )
|
|
{
|
|
delete node->value();
|
|
node = node->next();
|
|
}
|
|
m_CallingCardList.flush();
|
|
|
|
|
|
node = m_DeletedCallingCardList.head();
|
|
|
|
while( !node->beyond_tail() )
|
|
{
|
|
delete node->value();
|
|
node = node->next();
|
|
}
|
|
m_DeletedCallingCardList.flush();
|
|
|
|
if(m_hCards)
|
|
RegCloseKey(m_hCards);
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCards
|
|
Method : Initialize
|
|
|
|
Checks the presence of the Cards key. If not present, it creates
|
|
and populates it from string resources.
|
|
Verify the format of the registry config. If it is the old
|
|
one, it converts it to the new one.
|
|
Reads the cards from registry
|
|
|
|
****************************************************************************/
|
|
|
|
HRESULT CCallingCards::Initialize(void)
|
|
{
|
|
DWORD dwError;
|
|
DWORD dwDisp;
|
|
BOOL bNewCards = FALSE;
|
|
DWORD dwIndex;
|
|
DWORD dwLength;
|
|
DWORD dwType;
|
|
CCallingCard *pCard = NULL;
|
|
HRESULT Result = S_OK;
|
|
BOOL bNeedToConvert = FALSE;
|
|
BOOL bNeedToGenerateDefault = FALSE;
|
|
|
|
// Test the presence of the Cards key
|
|
dwError = RegOpenKeyEx( HKEY_CURRENT_USER,
|
|
gszCardsPath,
|
|
0,
|
|
KEY_READ,
|
|
&m_hCards
|
|
);
|
|
if(dwError==ERROR_SUCCESS)
|
|
{
|
|
// Read the NextID value
|
|
dwLength = sizeof(m_dwNextID);
|
|
dwError = RegQueryValueEx ( m_hCards,
|
|
gszNextID,
|
|
NULL,
|
|
&dwType,
|
|
(PBYTE)&m_dwNextID,
|
|
&dwLength
|
|
);
|
|
if(dwError==ERROR_SUCCESS)
|
|
{
|
|
if(dwType == REG_DWORD)
|
|
{
|
|
// Test the registry format and upgrade if necessary
|
|
if(IsCardListInOldFormat(m_hCards))
|
|
{
|
|
bNeedToConvert = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_INVALID_DATA;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(dwError != ERROR_SUCCESS)
|
|
bNeedToGenerateDefault = TRUE;
|
|
|
|
if(bNeedToGenerateDefault || bNeedToConvert)
|
|
{
|
|
// If the Cards key is missing or it has bad info, so we create a fresh, default set of cards.
|
|
// If the cards key is in the old format, it have to be converted.
|
|
// There's an excepted case, though: during the system setup no cards should be created or converted.
|
|
// So detect setup case first:
|
|
//
|
|
//
|
|
|
|
HKEY hSetupKey;
|
|
DWORD dwSetupValue;
|
|
|
|
// close the cards key handle
|
|
if(m_hCards)
|
|
{
|
|
RegCloseKey(m_hCards);
|
|
m_hCards = NULL;
|
|
}
|
|
|
|
dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
gszSystemSetupPath,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hSetupKey
|
|
);
|
|
if(dwError == ERROR_SUCCESS)
|
|
{
|
|
dwLength = sizeof(dwSetupValue);
|
|
dwSetupValue = 0;
|
|
|
|
dwError = RegQueryValueEx( hSetupKey,
|
|
gszSystemSetupInProgress,
|
|
NULL,
|
|
&dwType,
|
|
(PBYTE)&dwSetupValue,
|
|
&dwLength
|
|
);
|
|
RegCloseKey(hSetupKey);
|
|
|
|
if(dwError == ERROR_SUCCESS && dwType == REG_DWORD)
|
|
{
|
|
if(dwSetupValue == 1)
|
|
{
|
|
// Setup time !
|
|
dwError = ERROR_SUCCESS;
|
|
goto forced_exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(dwError != ERROR_SUCCESS)
|
|
{
|
|
// Hmm, cannot open the key or read the value...
|
|
TRACE_DWERROR();
|
|
}
|
|
|
|
if(bNeedToConvert)
|
|
{
|
|
dwError = ConvertCallingCards(HKEY_CURRENT_USER);
|
|
if(dwError!=ERROR_SUCCESS)
|
|
{
|
|
// fallback to default cards
|
|
bNeedToGenerateDefault = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
if(bNeedToGenerateDefault)
|
|
{
|
|
dwError = CreateFreshCards();
|
|
EXIT_IF_DWERROR();
|
|
}
|
|
|
|
// Reopen Cards key
|
|
dwError = RegOpenKeyEx( HKEY_CURRENT_USER,
|
|
gszCardsPath,
|
|
0,
|
|
KEY_READ,
|
|
&m_hCards
|
|
);
|
|
EXIT_IF_DWERROR();
|
|
|
|
// ReRead the NextID value
|
|
dwLength = sizeof(m_dwNextID);
|
|
dwError = RegQueryValueEx ( m_hCards,
|
|
gszNextID,
|
|
NULL,
|
|
&dwType,
|
|
(PBYTE)&m_dwNextID,
|
|
&dwLength
|
|
);
|
|
EXIT_IF_DWERROR();
|
|
|
|
}
|
|
|
|
// Read all entries
|
|
dwIndex = 0;
|
|
while(TRUE)
|
|
{
|
|
TCHAR szKeyName[ARRAYSIZE(gszCard)+MAX_NUMBER_LEN];
|
|
DWORD dwKeyLength;
|
|
DWORD dwCardID;
|
|
|
|
// Enumerate next entry
|
|
dwKeyLength = sizeof(szKeyName)/sizeof(TCHAR);
|
|
dwError = RegEnumKeyEx (m_hCards,
|
|
dwIndex,
|
|
szKeyName,
|
|
&dwKeyLength,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if(dwError == ERROR_NO_MORE_ITEMS)
|
|
{
|
|
m_dwNumEntries = dwIndex;
|
|
dwError = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
EXIT_IF_DWERROR();
|
|
|
|
// Create a CCallingCard object
|
|
dwCardID = StrToInt(szKeyName+ARRAYSIZE(gszCard)-1);
|
|
pCard = new CCallingCard;
|
|
if(pCard != NULL)
|
|
{
|
|
|
|
// Read the card information from registry
|
|
Result = pCard->Initialize(dwCardID);
|
|
if(SUCCEEDED(Result))
|
|
{
|
|
// Add it to the list
|
|
m_CallingCardList.tail()->insert_after(pCard);
|
|
}
|
|
else
|
|
{
|
|
LOG((TL_ERROR, "Error %x reading card %d", Result, dwCardID));
|
|
delete pCard;
|
|
pCard=NULL;
|
|
}
|
|
}
|
|
|
|
dwIndex++;
|
|
}
|
|
|
|
forced_exit:
|
|
|
|
if(m_hCards)
|
|
{
|
|
RegCloseKey(m_hCards);
|
|
m_hCards = NULL;
|
|
}
|
|
|
|
if(dwError != ERROR_SUCCESS)
|
|
Result = HRESULT_FROM_WIN32(dwError);
|
|
|
|
return Result;
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCards
|
|
Method : RemoveCard
|
|
|
|
****************************************************************************/
|
|
void CCallingCards::RemoveCard(CCallingCard *pCard)
|
|
{
|
|
CCallingCardNode *node = m_CallingCardList.head();
|
|
|
|
while( !node->beyond_tail() )
|
|
{
|
|
if ( pCard == node->value() )
|
|
{
|
|
InternalDeleteCard(node);
|
|
return;
|
|
}
|
|
node = node->next();
|
|
}
|
|
assert(FALSE);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCards
|
|
Method : RemoveCard
|
|
|
|
****************************************************************************/
|
|
void CCallingCards::RemoveCard(DWORD dwID)
|
|
{
|
|
CCallingCardNode *node = m_CallingCardList.head();
|
|
|
|
while( !node->beyond_tail() )
|
|
{
|
|
if ( dwID == (node->value())->GetCardID() )
|
|
{
|
|
InternalDeleteCard(node);
|
|
return;
|
|
}
|
|
node = node->next();
|
|
}
|
|
assert(FALSE);
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCards
|
|
Method : GetCallingCard
|
|
|
|
****************************************************************************/
|
|
CCallingCard * CCallingCards::GetCallingCard(DWORD dwID)
|
|
{
|
|
CCallingCardNode *node = m_CallingCardList.head();
|
|
|
|
while( !node->beyond_tail() )
|
|
{
|
|
if ( dwID == (node->value())->GetCardID() )
|
|
{
|
|
return node->value();
|
|
}
|
|
node = node->next();
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCards
|
|
Method : SaveToRegistry
|
|
|
|
|
|
****************************************************************************/
|
|
HRESULT CCallingCards::SaveToRegistry(void)
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
HRESULT Result = S_OK;
|
|
CCallingCardNode *node;
|
|
|
|
// Open the Cards key
|
|
dwError = RegOpenKeyEx (HKEY_CURRENT_USER,
|
|
gszCardsPath,
|
|
0,
|
|
KEY_SET_VALUE,
|
|
&m_hCards);
|
|
EXIT_IF_DWERROR();
|
|
|
|
//first - save the next ID
|
|
dwError = RegSetValueEx ( m_hCards,
|
|
gszNextID,
|
|
0,
|
|
REG_DWORD,
|
|
(PBYTE)&m_dwNextID,
|
|
sizeof(m_dwNextID)
|
|
);
|
|
EXIT_IF_DWERROR();
|
|
|
|
// save all cards (from both lists)
|
|
node = m_CallingCardList.head();
|
|
while( !node->beyond_tail() )
|
|
{
|
|
Result = node->value()->SaveToRegistry();
|
|
EXIT_IF_FAILED();
|
|
|
|
node = node->next();
|
|
}
|
|
|
|
node = m_DeletedCallingCardList.head();
|
|
while( !node->beyond_tail() )
|
|
{
|
|
Result = node->value()->SaveToRegistry();
|
|
EXIT_IF_FAILED();
|
|
|
|
node = node->next();
|
|
}
|
|
|
|
|
|
forced_exit:
|
|
|
|
if(m_hCards)
|
|
{
|
|
RegCloseKey(m_hCards);
|
|
m_hCards = NULL;
|
|
}
|
|
|
|
if(dwError != ERROR_SUCCESS)
|
|
Result = HRESULT_FROM_WIN32(dwError);
|
|
|
|
return Result;
|
|
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCards
|
|
Method : Reset
|
|
|
|
|
|
****************************************************************************/
|
|
HRESULT CCallingCards::Reset(BOOL bInclHidden)
|
|
{
|
|
m_hEnumNode = m_CallingCardList.head();
|
|
m_bEnumInclHidden = bInclHidden;
|
|
return S_OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCards
|
|
Method : Next
|
|
|
|
|
|
****************************************************************************/
|
|
HRESULT CCallingCards::Next(DWORD NrElem, CCallingCard **ppCard, DWORD *pNrElemFetched)
|
|
{
|
|
|
|
DWORD dwIndex = 0;
|
|
|
|
if(pNrElemFetched == NULL && NrElem != 1)
|
|
return E_INVALIDARG;
|
|
if(ppCard==NULL)
|
|
return E_INVALIDARG;
|
|
|
|
while( !m_hEnumNode->beyond_tail() && dwIndex<NrElem )
|
|
{
|
|
CCallingCard *pCard;
|
|
|
|
pCard = m_hEnumNode->value();
|
|
|
|
if(m_bEnumInclHidden || !pCard->IsMarkedHidden())
|
|
{
|
|
*ppCard++ = pCard;
|
|
dwIndex++;
|
|
}
|
|
|
|
m_hEnumNode = m_hEnumNode->next();
|
|
}
|
|
|
|
if(pNrElemFetched!=NULL)
|
|
*pNrElemFetched = dwIndex;
|
|
|
|
return dwIndex<NrElem ? S_FALSE : S_OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCards
|
|
Method : Skip
|
|
|
|
|
|
****************************************************************************/
|
|
HRESULT CCallingCards::Skip(DWORD NrElem)
|
|
{
|
|
|
|
DWORD dwIndex = 0;
|
|
|
|
while( !m_hEnumNode->beyond_tail() && dwIndex<NrElem )
|
|
{
|
|
|
|
if(m_bEnumInclHidden || !m_hEnumNode->value()->IsMarkedHidden())
|
|
{
|
|
dwIndex++;
|
|
}
|
|
|
|
m_hEnumNode = m_hEnumNode->next();
|
|
}
|
|
|
|
return dwIndex<NrElem ? S_FALSE : S_OK;
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCards
|
|
Method : CreateFreshCards
|
|
|
|
|
|
****************************************************************************/
|
|
|
|
DWORD CCallingCards::CreateFreshCards(void)
|
|
{
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
HRESULT Result = S_OK;
|
|
HKEY hTelephony = NULL;
|
|
HINSTANCE hTapiui = NULL;
|
|
int iNrChars;
|
|
DWORD dwNumCards;
|
|
DWORD dwDisp;
|
|
DWORD dwIndex;
|
|
DWORD dwValue;
|
|
|
|
WCHAR wBuffer[512];
|
|
PWSTR pTemp;
|
|
|
|
CCallingCard *pCard = NULL;
|
|
|
|
// Open/Create the Telephony key
|
|
dwError = RegCreateKeyEx( HKEY_CURRENT_USER,
|
|
gszTelephonyPath,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE,
|
|
NULL,
|
|
&hTelephony,
|
|
&dwDisp
|
|
);
|
|
EXIT_IF_DWERROR();
|
|
|
|
// Delete any existing tree
|
|
RegDeleteKeyRecursive( hTelephony, gszCards);
|
|
|
|
// Open/Create the Cards key
|
|
dwError = RegCreateKeyEx( hTelephony,
|
|
gszCards,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_SET_VALUE | KEY_READ,
|
|
NULL,
|
|
&m_hCards,
|
|
&dwDisp
|
|
);
|
|
EXIT_IF_DWERROR();
|
|
|
|
// Write the version
|
|
dwValue = TAPI_CARD_LIST_VERSION;
|
|
dwError = RegSetValueEx ( m_hCards,
|
|
gszCardListVersion,
|
|
0,
|
|
REG_DWORD,
|
|
(PBYTE)&dwValue,
|
|
sizeof(dwValue)
|
|
);
|
|
EXIT_IF_DWERROR();
|
|
|
|
// Load the TAPIUI.DLL resource library
|
|
hTapiui = LoadLibrary(gszResourceLibrary);
|
|
if(hTapiui==NULL)
|
|
dwError = GetLastError();
|
|
EXIT_IF_DWERROR();
|
|
|
|
// Load the number of cards. Use wBuffer as a temporary space
|
|
assert( MAX_NUMBER_LEN <= ARRAYSIZE(wBuffer) );
|
|
iNrChars = LoadString( hTapiui, RC_CARD_ID_BASE, (PTSTR)wBuffer, MAX_NUMBER_LEN);
|
|
if(iNrChars==0)
|
|
dwError = GetLastError();
|
|
EXIT_IF_DWERROR();
|
|
|
|
dwNumCards = StrToInt( (PTSTR)wBuffer );
|
|
|
|
//Read cards from string resources and write them to registry
|
|
for(dwIndex = 0; dwIndex<dwNumCards; dwIndex++)
|
|
{
|
|
PWSTR pszName;
|
|
PWSTR pszPin;
|
|
PWSTR pszLocalRule;
|
|
PWSTR pszLDRule;
|
|
PWSTR pszInternationalRule;
|
|
PWSTR pszAccountNumber;
|
|
PWSTR pszLocalAccessNumber;
|
|
PWSTR pszLDAccessNumber;
|
|
PWSTR pszInternationalAccessNumber;
|
|
DWORD dwFlags;
|
|
|
|
// read the card description
|
|
iNrChars = TAPILoadStringW( hTapiui,
|
|
RC_CARD_ID_BASE + dwIndex + 1,
|
|
wBuffer,
|
|
ARRAYSIZE(wBuffer)
|
|
);
|
|
if(iNrChars==0)
|
|
dwError = GetLastError();
|
|
EXIT_IF_DWERROR();
|
|
|
|
// tokenize it
|
|
#define TOKENIZE(Pointer) \
|
|
Pointer = (wcschr(pTemp+1, L'"'))+1; \
|
|
pTemp = wcschr(Pointer, L'"'); \
|
|
*pTemp = L'\0';
|
|
|
|
pTemp = wBuffer-1;
|
|
|
|
TOKENIZE(pszName);
|
|
TOKENIZE(pszPin);
|
|
TOKENIZE(pszLocalRule);
|
|
TOKENIZE(pszLDRule);
|
|
TOKENIZE(pszInternationalRule);
|
|
TOKENIZE(pszAccountNumber);
|
|
TOKENIZE(pszLocalAccessNumber);
|
|
TOKENIZE(pszLDAccessNumber);
|
|
TOKENIZE(pszInternationalAccessNumber);
|
|
|
|
#undef TOKENIZE
|
|
// don't forget the flags
|
|
dwFlags = _wtoi(pTemp+2);
|
|
|
|
// create the card object
|
|
pCard = new CCallingCard();
|
|
if(pCard==NULL)
|
|
dwError = ERROR_OUTOFMEMORY;
|
|
EXIT_IF_DWERROR();
|
|
|
|
Result = pCard->Initialize( dwIndex,
|
|
pszName,
|
|
dwFlags,
|
|
pszPin,
|
|
pszAccountNumber,
|
|
pszInternationalRule,
|
|
pszLDRule,
|
|
pszLocalRule,
|
|
pszInternationalAccessNumber,
|
|
pszLDAccessNumber,
|
|
pszLocalAccessNumber
|
|
);
|
|
EXIT_IF_FAILED();
|
|
|
|
// save it
|
|
Result = pCard->SaveToRegistry();
|
|
|
|
EXIT_IF_FAILED();
|
|
|
|
delete pCard;
|
|
pCard = NULL;
|
|
}
|
|
|
|
// Write NextID value
|
|
dwError = RegSetValueEx ( m_hCards,
|
|
gszNextID,
|
|
0,
|
|
REG_DWORD,
|
|
(PBYTE)&dwNumCards,
|
|
sizeof(dwNumCards)
|
|
);
|
|
EXIT_IF_DWERROR();
|
|
|
|
|
|
forced_exit:
|
|
|
|
if(hTelephony)
|
|
RegCloseKey(hTelephony);
|
|
if(m_hCards)
|
|
{
|
|
RegCloseKey(m_hCards);
|
|
m_hCards = NULL;
|
|
}
|
|
if(pCard)
|
|
delete pCard;
|
|
if(hTapiui)
|
|
FreeLibrary(hTapiui);
|
|
|
|
if(FAILED(Result))
|
|
dwError = HRESULT_CODE(Result);
|
|
|
|
return dwError;
|
|
}
|
|
|
|
/****************************************************************************
|
|
|
|
Class : CCallingCards
|
|
Method : InternalDeleteCard
|
|
|
|
|
|
****************************************************************************/
|
|
|
|
void CCallingCards::InternalDeleteCard(CCallingCardNode *pNode)
|
|
{
|
|
|
|
CCallingCard *pCard = pNode->value();
|
|
|
|
pCard->MarkDeleted();
|
|
|
|
if(!pCard->IsMarkedHidden())
|
|
{
|
|
pNode->remove();
|
|
m_dwNumEntries--;
|
|
m_DeletedCallingCardList.tail()->insert_after(pCard);
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Helpers
|
|
|
|
****************************************************************************/
|
|
|
|
BOOL ValidValue(PWSTR pwszString)
|
|
{
|
|
// An empty string or with spaces only is not valid
|
|
WCHAR const * pwcCrt = pwszString;
|
|
while(*pwcCrt)
|
|
if(*pwcCrt++ != L' ')
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef DBG
|
|
|
|
static void DebugAssertFailure (LPCSTR file, DWORD line, LPCSTR condition)
|
|
{
|
|
DbgPrt (0, TEXT("%hs(%d) : Assertion failed, condition: %hs\n"), file, line, condition);
|
|
|
|
DebugBreak();
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|