windows-nt/Source/XPSP1/NT/shell/osshell/regwiz/phbooklib/phbk.cpp
2020-09-26 16:20:57 +08:00

1308 lines
34 KiB
C++

// ############################################################################
// Phone book APIs
#include "pch.hpp"
#include <tchar.h>
#include "phbk.h"
#include "misc.h"
#include "phbkrc.h"
#include "suapi.h"
#define ReadVerifyPhoneBookDW(x) if (!ReadPhoneBookDW(&(x),pcCSVFile)) \
{ AssertSz(0,"Invalid DWORD in phone book"); \
goto ReadError; }
#define ReadVerifyPhoneBookW(x) if (!ReadPhoneBookW(&(x),pcCSVFile)) \
{ AssertSz(0,"Invalid DWORD in phone book"); \
goto ReadError; }
#define ReadVerifyPhoneBookB(x) if (!ReadPhoneBookB(&(x),pcCSVFile)) \
{ AssertSz(0,"Invalid DWORD in phone book"); \
goto ReadError; }
#define ReadVerifyPhoneBookSZ(x,y) if (!ReadPhoneBookSZ(&x[0],y+sizeof('\0'),pcCSVFile)) \
{ AssertSz(0,"Invalid DWORD in phone book"); \
goto ReadError; }
#define CHANGE_BUFFER_SIZE 50
#define TEMP_PHONE_BOOK_PREFIX "PBH"
#define ERROR_USERBACK 32766
#define ERROR_USERCANCEL 32767
char szTempBuffer[TEMP_BUFFER_LENGTH];
char szTempFileName[MAX_PATH];
#ifdef __cplusplus
extern "C" {
#endif
HWND g_hWndMain;
#ifdef __cplusplus
}
#endif
static void GetAbsolutePath( LPTSTR input, LPTSTR output, DWORD chOut)
{
if(_tcschr(input,_T('%')) == NULL) {
_tcsncpy(output, input, chOut);
return ;
}
if(input[0] == _T('%'))
{
LPTSTR token = _tcstok(input,_T("%"));
if(token != NULL)
{
LPTSTR sztemp;
sztemp = getenv( token );
if(sztemp != NULL)
{
_tcsncpy(output, sztemp, chOut);
}
token = _tcstok(NULL,_T("\0"));
if(token != NULL)
{
_tcsncat(output, token, chOut - _tcslen(output));
}
}
}
else
{
LPTSTR token = _tcstok(input,_T("%"));
if(token != NULL)
{
_tcsncpy(output, token, chOut);
token = _tcstok(NULL,_T("%"));
if(token != NULL)
{
LPTSTR sztemp;
sztemp = getenv( token );
if(sztemp != NULL)
{
_tcsncat(output, sztemp, chOut - _tcslen(output));
}
token = _tcstok(NULL,_T("\0"));
if(token != NULL)
{
_tcsncat(output, token, chOut - _tcslen(output));
}
}
}
}
GetAbsolutePath(output, output, chOut);
}
// ############################################################################
CPhoneBook::CPhoneBook()
{
HINSTANCE hInst = NULL;
LONG lrc;
// HANDLE hKey;
LONG regStatus;
char uszRegKey[]="SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\ICWCONN1.EXE";
char uszR[ ]= "Path";
DWORD dwInfoSize ;
HKEY hKey;
DWORD dwType;
DWORD dwSize;
CHAR szData[MAX_PATH+1];
CHAR czTemp[256];
m_rgPhoneBookEntry = NULL;
m_hPhoneBookEntry = NULL;
m_cPhoneBookEntries =0;
m_rgLineCountryEntry=NULL;
m_rgState=NULL;
m_cStates=0;
m_rgIDLookUp = NULL;
m_rgNameLookUp = NULL;
m_pLineCountryList = NULL;
ZeroMemory(&m_szINFFile[0],MAX_PATH);
ZeroMemory(&m_szINFCode[0],MAX_INFCODE);
ZeroMemory(&m_szPhoneBook[0],MAX_PATH);
ZeroMemory(&m_szICWDirectoryPath,MAX_PATH);
regStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
uszRegKey,0,KEY_READ ,&hKey);
if (regStatus == ERROR_SUCCESS) {
// Get The Path
dwInfoSize = MAX_PATH;
RegQueryValueEx(hKey,uszR,NULL,0,(LPBYTE) czTemp,
&dwInfoSize);
GetAbsolutePath(czTemp,m_szICWDirectoryPath, MAX_PATH-1);
size_t sLen = strlen(m_szICWDirectoryPath);
m_szICWDirectoryPath[sLen-1] = '\0';
}
else {
MessageBox(NULL,"Error Accessing PAth ","SearchPath",MB_OK);
// Error
}
#if !defined(WIN16)
if (VER_PLATFORM_WIN32_NT == DWGetWin32Platform())
{
m_bScriptingAvailable = TRUE;
}
else
{
//
// Verify scripting by checking for smmscrpt.dll in RemoteAccess registry key
//
if (1111 <= DWGetWin32BuildNumber())
{
m_bScriptingAvailable = TRUE;
}
else
{
m_bScriptingAvailable = FALSE;
hKey = NULL;
lrc=RegOpenKey(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\Services\\RemoteAccess\\Authentication\\SMM_FILES\\PPP",&hKey);
if (ERROR_SUCCESS == lrc)
{
dwSize = MAX_PATH;
lrc = RegQueryValueEx(hKey,"Path",0,&dwType,(LPBYTE)szData,&dwSize);
if (ERROR_SUCCESS == lrc)
{
if (0 == lstrcmpi(szData,"smmscrpt.dll"))
m_bScriptingAvailable = TRUE;
}
}
if (hKey)
RegCloseKey(hKey);
hKey = NULL;
}
//
// Verify that the DLL can be loaded
//
if (m_bScriptingAvailable)
{
hInst = LoadLibrary("smmscrpt.dll");
if (hInst)
FreeLibrary(hInst);
else
m_bScriptingAvailable = FALSE;
hInst = NULL;
}
}
#endif // WIN16
}
// ############################################################################
CPhoneBook::~CPhoneBook()
{
#ifdef WIN16
if (m_rgPhoneBookEntry)
GlobalFree(m_rgPhoneBookEntry);
#else
if (m_hPhoneBookEntry)
GlobalUnlock(m_hPhoneBookEntry);
if (m_hPhoneBookEntry)
GlobalFree(m_hPhoneBookEntry);
#endif
if (m_pLineCountryList)
GlobalFree(m_pLineCountryList);
if (m_rgIDLookUp)
GlobalFree(m_rgIDLookUp);
if (m_rgNameLookUp)
GlobalFree(m_rgNameLookUp);
if (m_rgState)
GlobalFree(m_rgState);
}
// ############################################################################
BOOL CPhoneBook::ReadPhoneBookDW(DWORD far *pdw, CCSVFile far *pcCSVFile)
{
if (!pcCSVFile->ReadToken(szTempBuffer,TEMP_BUFFER_LENGTH))
return FALSE;
return (FSz2Dw(szTempBuffer,pdw));
}
// ############################################################################
BOOL CPhoneBook::ReadPhoneBookW(WORD far *pw, CCSVFile far *pcCSVFile)
{
if (!pcCSVFile->ReadToken(szTempBuffer,TEMP_BUFFER_LENGTH))
return FALSE;
return (FSz2W(szTempBuffer,pw));
}
// ############################################################################
BOOL CPhoneBook::ReadPhoneBookB(BYTE far *pb, CCSVFile far *pcCSVFile)
{
if (!pcCSVFile->ReadToken(szTempBuffer,TEMP_BUFFER_LENGTH))
return FALSE;
return (FSz2B(szTempBuffer,pb));
}
// ############################################################################
BOOL CPhoneBook::ReadPhoneBookSZ(LPSTR psz, DWORD dwSize, CCSVFile far *pcCSVFile)
{
if (!pcCSVFile->ReadToken(psz,dwSize))
return FALSE;
return TRUE;
}
// ############################################################################
BOOL CPhoneBook::FixUpFromRealloc(PACCESSENTRY paeOld, PACCESSENTRY paeNew)
{
BOOL bRC = FALSE;
LONG_PTR lDiff = 0;
DWORD idx = 0;
//
// No starting value or no move, therefore no fix-ups needed
//
if ((0 == paeOld) || (paeNew == paeOld))
{
bRC = TRUE;
goto FixUpFromReallocExit;
}
Assert(paeNew);
Assert(((LONG_PTR)paeOld) > 0); // if these address look like negative numbers
Assert(((LONG_PTR)paeNew) > 0); // I'm not sure the code would handle them
lDiff = (LONG_PTR)paeOld - (LONG_PTR)paeNew;
//
// fix up STATES
//
for (idx = 0; idx < m_cStates; idx++)
{
if (m_rgState[idx].paeFirst)
m_rgState[idx].paeFirst = (PACCESSENTRY )((LONG_PTR)m_rgState[idx].paeFirst - lDiff);
}
//
// fix up ID look up array
//
for (idx = 0; idx < m_pLineCountryList->dwNumCountries ; idx++)
{
if (m_rgIDLookUp[idx].pFirstAE)
m_rgIDLookUp[idx].pFirstAE = (PACCESSENTRY )((LONG_PTR)m_rgIDLookUp[idx].pFirstAE - lDiff);
}
bRC = TRUE;
FixUpFromReallocExit:
return bRC;
}
/*
long WINAPI lineGetCountry(unsigned long x,unsigned long y,struct linecountrylist_tag *z)
{
return 0;
}
*/
// ############################################################################
HRESULT CPhoneBook::Init(LPCSTR pszISPCode)
{
LPLINECOUNTRYLIST pLineCountryTemp = NULL;
HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
DWORD dwLastState = 0;
DWORD dwLastCountry = 0;
DWORD dwSizeAllocated;
PACCESSENTRY pCurAccessEntry;
PACCESSENTRY pAETemp;
LPLINECOUNTRYENTRY pLCETemp;
DWORD idx;
LPSTR pszTemp;
CCSVFile far *pcCSVFile=NULL;
LPSTATE ps,psLast; //faster to use pointers.
int iTestSK;
// Get TAPI country list
m_pLineCountryList = (LPLINECOUNTRYLIST)GlobalAlloc(GPTR,sizeof(LINECOUNTRYLIST));
if (!m_pLineCountryList)
goto InitExit;
m_pLineCountryList->dwTotalSize = sizeof(LINECOUNTRYLIST);
#if defined(WIN16)
idx = (DWORD) IETapiGetCountry(0, m_pLineCountryList);
#else
idx = lineGetCountry(0,0x10003,m_pLineCountryList);
#endif
if (idx && idx != LINEERR_STRUCTURETOOSMALL)
goto InitExit;
Assert(m_pLineCountryList->dwNeededSize);
pLineCountryTemp = (LPLINECOUNTRYLIST)GlobalAlloc(GPTR,
(size_t)m_pLineCountryList->dwNeededSize);
if (!pLineCountryTemp)
goto InitExit;
pLineCountryTemp->dwTotalSize = m_pLineCountryList->dwNeededSize;
GlobalFree(m_pLineCountryList);
m_pLineCountryList = pLineCountryTemp;
pLineCountryTemp = NULL;
#if defined(WIN16)
if (IETapiGetCountry(0, m_pLineCountryList))
#else
if (lineGetCountry(0,0x10003,m_pLineCountryList))
#endif
goto InitExit;
//#endif // WIN16
// Load Look Up arrays
#ifdef DEBUG
m_rgIDLookUp = (LPIDLOOKUPELEMENT)GlobalAlloc(GPTR,
(int)(sizeof(IDLOOKUPELEMENT)*m_pLineCountryList->dwNumCountries+5));
#else
m_rgIDLookUp = (LPIDLOOKUPELEMENT)GlobalAlloc(GPTR,
(int)(sizeof(IDLOOKUPELEMENT)*m_pLineCountryList->dwNumCountries));
#endif
if (!m_rgIDLookUp) goto InitExit;
pLCETemp = (LPLINECOUNTRYENTRY)((DWORD_PTR)m_pLineCountryList +
m_pLineCountryList->dwCountryListOffset);
for (idx=0;idx<m_pLineCountryList->dwNumCountries;idx++)
{
m_rgIDLookUp[idx].dwID = pLCETemp[idx].dwCountryID;
m_rgIDLookUp[idx].pLCE = &pLCETemp[idx];
}
qsort(m_rgIDLookUp,(int)m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),
CompareIDLookUpElements);
m_rgNameLookUp = (LPCNTRYNAMELOOKUPELEMENT)GlobalAlloc(GPTR,
(int)(sizeof(CNTRYNAMELOOKUPELEMENT) * m_pLineCountryList->dwNumCountries));
if (!m_rgNameLookUp) goto InitExit;
for (idx=0;idx<m_pLineCountryList->dwNumCountries;idx++)
{
m_rgNameLookUp[idx].psCountryName = (LPSTR)((LPBYTE)m_pLineCountryList + (DWORD)pLCETemp[idx].dwCountryNameOffset);
m_rgNameLookUp[idx].dwNameSize = pLCETemp[idx].dwCountryNameSize;
m_rgNameLookUp[idx].pLCE = &pLCETemp[idx];
}
qsort(m_rgNameLookUp,(int)m_pLineCountryList->dwNumCountries,sizeof(CNTRYNAMELOOKUPELEMENT),
CompareCntryNameLookUpElements);
// Load States
if (!SearchPath(NULL,STATE_FILENAME,NULL,TEMP_BUFFER_LENGTH,szTempBuffer,&pszTemp))
{
if(m_szICWDirectoryPath){
// Try with c:\\ProgramFile\\ICW-INTERNET\\......
if(! SearchPath(m_szICWDirectoryPath,
STATE_FILENAME,NULL,TEMP_BUFFER_LENGTH,szTempBuffer,&pszTemp)) {
AssertSz(0,"STATE.ICW not found");
hr = ERROR_FILE_NOT_FOUND;
goto InitExit;
}else {
; // OK Th e file is found
iTestSK=0;
}
}
else {
AssertSz(0,"STATE.ICW not found");
hr = ERROR_FILE_NOT_FOUND;
goto InitExit;
}
}
pcCSVFile = new CCSVFile;
if (!pcCSVFile) goto InitExit;
if (!pcCSVFile->Open(szTempBuffer))
{
AssertSz(0,"Can not open STATE.ICW");
delete pcCSVFile;
pcCSVFile = NULL;
goto InitExit;
}
// first token in state file is the number of states
if (!pcCSVFile->ReadToken(szTempBuffer,TEMP_BUFFER_LENGTH))
goto InitExit;
if (!FSz2Dw(szTempBuffer,&m_cStates))
{
AssertSz(0,"STATE.ICW count is invalid");
goto InitExit;
}
m_rgState = (LPSTATE)GlobalAlloc(GPTR,(int)(sizeof(STATE)*m_cStates));
if (!m_rgState)
goto InitExit;
for (ps = m_rgState, psLast = &m_rgState[m_cStates - 1]; ps <= psLast;++ps)
{
pcCSVFile->ReadToken(ps->szStateName,cbStateName);
}
pcCSVFile->Close();
// Locate ISP's INF file
if (!SearchPath(NULL,(LPCTSTR) pszISPCode,INF_SUFFIX,MAX_PATH,
m_szINFFile,&pszTemp))
{
wsprintf(szTempBuffer,"Can not find:%s%s (%d)",pszISPCode,INF_SUFFIX,GetLastError());
if(m_szICWDirectoryPath) {
if(!SearchPath(m_szICWDirectoryPath,(LPCTSTR) pszISPCode,INF_SUFFIX,MAX_PATH,
m_szINFFile,&pszTemp)) {
AssertSz(0,szTempBuffer);
hr = ERROR_FILE_NOT_FOUND;
goto InitExit;
//
}else {
iTestSK++;
}
}else {
AssertSz(0,szTempBuffer);
hr = ERROR_FILE_NOT_FOUND;
goto InitExit;
}
}
//Load Phone Book
if (!GetPrivateProfileString(INF_APP_NAME,INF_PHONE_BOOK,INF_DEFAULT,
szTempBuffer,TEMP_BUFFER_LENGTH,m_szINFFile))
{
AssertSz(0,"PhoneBookFile not specified in INF file");
hr = ERROR_FILE_NOT_FOUND;
goto InitExit;
}
#ifdef DEBUG
if (!lstrcmp(szTempBuffer,INF_DEFAULT))
{
wsprintf(szTempBuffer, "%s value not found in ISP file", INF_PHONE_BOOK);
AssertSz(0,szTempBuffer);
}
#endif
if (!SearchPath(NULL,szTempBuffer,NULL,MAX_PATH,m_szPhoneBook,&pszTemp))
{
if(m_szICWDirectoryPath){
if (!SearchPath(m_szICWDirectoryPath,szTempBuffer,NULL,MAX_PATH,m_szPhoneBook,&pszTemp)){
AssertSz(0,"ISP phone book not found");
hr = ERROR_FILE_NOT_FOUND;
goto InitExit;
}else {
;; // OK file Found
iTestSK++;
}
}else {
AssertSz(0,"ISP phone book not found");
hr = ERROR_FILE_NOT_FOUND;
goto InitExit;
}
}
if (!pcCSVFile->Open(m_szPhoneBook))
{
AssertSz(0,"Can not open phone book");
hr = GetLastError();
goto InitExit;
}
dwSizeAllocated = 0;
do {
Assert (dwSizeAllocated >= m_cPhoneBookEntries);
// check that sufficient memory is allocated
if (m_rgPhoneBookEntry)
{
if (dwSizeAllocated == m_cPhoneBookEntries)
{
//
// we need more memory
//
// AssertSz(0,"Out of memory originally allocated for phone book.\r\n");
// goto InitExit;
pAETemp = m_rgPhoneBookEntry;
#ifdef WIN16
dwSizeAllocated += PHONE_ENTRY_ALLOC_SIZE;
m_rgPhoneBookEntry = (PACCESSENTRY)GlobalReAlloc(m_rgPhoneBookEntry,
(int)(dwSizeAllocated * sizeof(ACCESSENTRY)),GHND);
if (NULL == m_rgPhoneBookEntry)
goto InitExit;
#else
// UNLOCK
Assert(m_hPhoneBookEntry);
if (FALSE == GlobalUnlock(m_hPhoneBookEntry))
{
if (NO_ERROR != GetLastError())
goto InitExit;
}
// REALLOC
dwSizeAllocated += PHONE_ENTRY_ALLOC_SIZE;
m_hPhoneBookEntry = GlobalReAlloc(m_hPhoneBookEntry,
(int)(dwSizeAllocated * sizeof(ACCESSENTRY)),GHND);
if (NULL == m_hPhoneBookEntry)
goto InitExit;
// LOCK
m_rgPhoneBookEntry = (PACCESSENTRY)GlobalLock(m_hPhoneBookEntry);
if (NULL == m_rgPhoneBookEntry)
goto InitExit;
#endif
FixUpFromRealloc(pAETemp, m_rgPhoneBookEntry);
Dprintf("Grow phone book to %d entries\n",dwSizeAllocated);
pCurAccessEntry = (PACCESSENTRY)((LONG_PTR)pCurAccessEntry -
((LONG_PTR)pAETemp - (LONG_PTR)(m_rgPhoneBookEntry)));
}
}
else
{
//
// Initialization for the first time through
//
// ALLOC
#ifdef WIN16
m_rgPhoneBookEntry = (PACCESSENTRY)GlobalAlloc(GHND,sizeof(ACCESSENTRY) * PHONE_ENTRY_ALLOC_SIZE);
if(NULL == m_rgPhoneBookEntry)
goto InitExit;
#else
m_hPhoneBookEntry = GlobalAlloc(GHND,sizeof(ACCESSENTRY) * PHONE_ENTRY_ALLOC_SIZE);
if(NULL == m_hPhoneBookEntry)
goto InitExit;
// LOCK
m_rgPhoneBookEntry = (PACCESSENTRY)GlobalLock(m_hPhoneBookEntry);
if(NULL == m_rgPhoneBookEntry)
goto InitExit;
#endif
dwSizeAllocated = PHONE_ENTRY_ALLOC_SIZE;
pCurAccessEntry = m_rgPhoneBookEntry;
}
// Read a line from the phonebook
hr = ReadOneLine(pCurAccessEntry,pcCSVFile);
if (hr == ERROR_NO_MORE_ITEMS)
{
break;
}
else if (hr != ERROR_SUCCESS)
{
goto InitExit;
}
hr = ERROR_NOT_ENOUGH_MEMORY;
// Check to see if this is the first phone number for a given country
if (pCurAccessEntry->dwCountryID != dwLastCountry)
{
LPIDLOOKUPELEMENT lpIDLookupElement;
// NOTE: Not sure about the first parameter here.
lpIDLookupElement = (LPIDLOOKUPELEMENT)bsearch(&pCurAccessEntry->dwCountryID,
m_rgIDLookUp,(int)m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),
CompareIDLookUpElements);
if (!lpIDLookupElement)
{
// bad country ID, but we can't assert here
Dprintf("Bad country ID in phone book %d\n",pCurAccessEntry->dwCountryID);
continue;
}
else
{
// for a given country ID this is the first phone number
lpIDLookupElement->pFirstAE = pCurAccessEntry;
dwLastCountry = pCurAccessEntry->dwCountryID;
}
}
// Check to see if this is the first phone number for a given state
if (pCurAccessEntry->wStateID && (pCurAccessEntry->wStateID != dwLastState))
{
idx = pCurAccessEntry->wStateID - 1;
m_rgState[idx].dwCountryID = pCurAccessEntry->dwCountryID;
m_rgState[idx].paeFirst = pCurAccessEntry;
dwLastState = pCurAccessEntry->wStateID;
}
pCurAccessEntry++;
m_cPhoneBookEntries++;
} while (TRUE);
// Trim the phone book for unused memory
Assert(m_rgPhoneBookEntry && m_cPhoneBookEntries);
pAETemp = m_rgPhoneBookEntry;
#ifdef WIN16
m_rgPhoneBookEntry = (PACCESSENTRY)GlobalReAlloc(m_rgPhoneBookEntry,(int)(m_cPhoneBookEntries * sizeof(ACCESSENTRY)),GHND);
if (!m_rgPhoneBookEntry) goto InitExit;
#else
// UNLOCK
Assert(m_hPhoneBookEntry);
if (FALSE != GlobalUnlock(m_hPhoneBookEntry))
{
if (NO_ERROR != GetLastError())
goto InitExit;
}
// REALLOC
m_hPhoneBookEntry = GlobalReAlloc(m_hPhoneBookEntry,(int)(m_cPhoneBookEntries * sizeof(ACCESSENTRY)),GHND);
if (NULL == m_hPhoneBookEntry)
goto InitExit;
// LOCK
m_rgPhoneBookEntry = (PACCESSENTRY)GlobalLock(m_hPhoneBookEntry);
if (NULL == m_rgPhoneBookEntry)
goto InitExit;
#endif
FixUpFromRealloc(pAETemp, m_rgPhoneBookEntry);
hr = ERROR_SUCCESS;
InitExit:
// If something failed release everything
if (hr != ERROR_SUCCESS)
{
#ifdef WIN16
GlobalFree(m_rgPhoneBookEntry);
#else
GlobalUnlock(m_hPhoneBookEntry);
GlobalFree(m_hPhoneBookEntry);
#endif
GlobalFree(m_pLineCountryList);
GlobalFree(m_rgIDLookUp);
GlobalFree(m_rgNameLookUp);
GlobalFree(m_rgState);
m_cPhoneBookEntries = 0 ;
m_cStates = 0;
m_pLineCountryList = NULL;
m_rgPhoneBookEntry = NULL;
m_hPhoneBookEntry = NULL;
m_rgIDLookUp=NULL;
m_rgNameLookUp=NULL;
m_rgState=NULL;
}
if (pcCSVFile)
{
pcCSVFile->Close();
delete pcCSVFile;
}
return hr;
}
// ############################################################################
HRESULT CPhoneBook::Merge(LPCSTR pszChangeFile)
{
CCSVFile far *pcCSVFile;
ACCESSENTRY aeChange;
LPIDXLOOKUPELEMENT rgIdxLookUp;
LPIDXLOOKUPELEMENT pCurIdxLookUp;
DWORD dwAllocated;
DWORD dwUsed;
DWORD dwOriginalSize;
HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
DWORD dwIdx;
#if !defined(WIN16)
HANDLE hTemp;
HANDLE hIdxLookUp;
#else
// Normandy 11746
LPVOID rgTemp; // 16-bit only
#endif
DWORD cch, cchWritten;
HANDLE hFile;
// Pad the phonebook for new entries.
dwAllocated = m_cPhoneBookEntries + CHANGE_BUFFER_SIZE;
#ifdef WIN16
Assert(m_rgPhoneBookEntry);
rgTemp = GlobalReAlloc(m_rgPhoneBookEntry, (int)(sizeof(ACCESSENTRY) * dwAllocated),GHND);
Assert(rgTemp);
if (!rgTemp) goto MergeExit;
m_rgPhoneBookEntry = (PACCESSENTRY)rgTemp;
#else
Assert(m_hPhoneBookEntry);
GlobalUnlock(m_hPhoneBookEntry);
hTemp = (HANDLE)GlobalReAlloc(m_hPhoneBookEntry, sizeof(ACCESSENTRY) * dwAllocated,GHND);
Assert(hTemp);
if (!hTemp)
goto MergeExit;
m_rgPhoneBookEntry = (PACCESSENTRY)GlobalLock(m_hPhoneBookEntry);
if (!m_rgPhoneBookEntry)
goto MergeExit;
#endif
// Create index to loaded phone book, sorted by index
#ifdef WIN16
rgIdxLookUp = (LPIDXLOOKUPELEMENT)GlobalAlloc(GHND,(int)(sizeof(IDXLOOKUPELEMENT) * dwAllocated));
#else
hIdxLookUp = (HANDLE)GlobalAlloc(GHND,sizeof(IDXLOOKUPELEMENT) * dwAllocated);
rgIdxLookUp = (LPIDXLOOKUPELEMENT)GlobalLock(hIdxLookUp);
#endif
Assert(rgIdxLookUp);
if (!rgIdxLookUp)
goto MergeExit;
for (dwIdx = 0; dwIdx < m_cPhoneBookEntries; dwIdx++)
{
rgIdxLookUp[dwIdx].dwIndex = rgIdxLookUp[dwIdx].pAE->dwIndex;
rgIdxLookUp[dwIdx].pAE = &m_rgPhoneBookEntry[dwIdx];
}
dwUsed = m_cPhoneBookEntries;
dwOriginalSize = m_cPhoneBookEntries;
qsort(rgIdxLookUp,(int)dwOriginalSize,sizeof(IDXLOOKUPELEMENT),CompareIdxLookUpElements);
// Load changes to phone book
pcCSVFile = new CCSVFile;
Assert(pcCSVFile);
if (!pcCSVFile)
goto MergeExit;
if (!pcCSVFile->Open(pszChangeFile))
goto MergeExit;
do {
// Read a change record
ZeroMemory(&aeChange,sizeof(ACCESSENTRY));
hr = ReadOneLine(&aeChange, pcCSVFile);
if(hr == ERROR_NO_MORE_ITEMS)
{
break; // no more enteries
}
else if (hr =! ERROR_SUCCESS)
{
goto MergeExit;
}
hr = ERROR_NOT_ENOUGH_MEMORY;
// Determine if this is a delete or add record
if (aeChange.szAccessNumber[0] == '0' && aeChange.szAccessNumber[1] == '\0')
{
// This is a delete record, find matching record
// NOTE: we only search the numbers that existed before the change file,
// because they are the only ones that are sorted.
pCurIdxLookUp = (LPIDXLOOKUPELEMENT)bsearch(&aeChange,rgIdxLookUp,(int)dwOriginalSize,
sizeof(IDXLOOKUPELEMENT),CompareIdxLookUpElements);
AssertSz(pCurIdxLookUp,"Attempting to delete a record that does not exist. The change file and phone book versions do not match.");
if (pCurIdxLookUp)
pCurIdxLookUp->pAE = NULL; //Create a dead entry in the look up table
m_cPhoneBookEntries--;
}
else
{
// This is an add entry
m_cPhoneBookEntries++;
dwUsed++;
// Make sure we have enough room
if (m_cPhoneBookEntries > dwAllocated)
{
// Grow phone book
dwAllocated += CHANGE_BUFFER_SIZE;
#ifdef WIN16
Assert(m_rgPhoneBookEntry);
rgTemp = GlobalReAlloc(m_rgPhoneBookEntry,(int)(sizeof(ACCESSENTRY)*dwAllocated),GHND);
Assert(rgTemp);
if (!rgTemp)
goto MergeExit;
m_rgPhoneBookEntry = (PACCESSENTRY)rgTemp;
// Grow look up index
Assert(rgIdxLookUp);
rgTemp = GlobalReAlloc(rgIdxLookUp,(int)(sizeof(IDXLOOKUPELEMENT)*dwAllocated),GHND);
Assert(rgTemp);
if (!rgTemp)
goto MergeExit;
rgIdxLookUp = (LPIDXLOOKUPELEMENT)rgTemp;
#else
Assert(m_hPhoneBookEntry);
GlobalUnlock(m_hPhoneBookEntry);
hTemp = (HANDLE)GlobalReAlloc(m_hPhoneBookEntry,sizeof(ACCESSENTRY)*dwAllocated,GHND);
Assert(hTemp);
if (!hTemp)
goto MergeExit;
m_hPhoneBookEntry = hTemp;
m_rgPhoneBookEntry = (PACCESSENTRY)GlobalLock(m_hPhoneBookEntry);
Assert(m_rgPhoneBookEntry);
if (!m_rgPhoneBookEntry)
goto MergeExit;
// Grow look up index
Assert(hIdxLookUp);
GlobalUnlock(hIdxLookUp);
hTemp = (HANDLE)GlobalReAlloc(hIdxLookUp,sizeof(IDXLOOKUPELEMENT)*dwAllocated,GHND);
Assert(hTemp);
if (!hTemp)
goto MergeExit;
hIdxLookUp = hTemp;
rgIdxLookUp = (LPIDXLOOKUPELEMENT)GlobalLock(hIdxLookUp);
Assert(rgIdxLookUp);
if (!rgIdxLookUp)
goto MergeExit;
#endif
}
//Add entry to the end of the phonebook and to end of look up index
CopyMemory(&m_rgPhoneBookEntry[m_cPhoneBookEntries],&aeChange,sizeof(ACCESSENTRY));
rgIdxLookUp[m_cPhoneBookEntries].dwIndex = m_rgPhoneBookEntry[m_cPhoneBookEntries].dwIndex;
rgIdxLookUp[m_cPhoneBookEntries].pAE = &m_rgPhoneBookEntry[m_cPhoneBookEntries];
// NOTE: because the entry is added to the end of the list, we can't add
// and delete entries in the same change file.
}
} while (TRUE);
// resort the IDXLookUp index to reflect the correct order of enteries
// for the phonebook file, including all of the entries to be deleted.
qsort(rgIdxLookUp,(int)dwUsed,sizeof(IDXLOOKUPELEMENT),CompareIdxLookUpElementsFileOrder);
// Build a new phonebook file
#ifdef WIN16
GetTempFileName(0, TEMP_PHONE_BOOK_PREFIX, 0, szTempFileName);
#else
if (!GetTempPath(TEMP_BUFFER_LENGTH,szTempBuffer))
goto MergeExit;
if (!GetTempFileName(szTempBuffer,TEMP_PHONE_BOOK_PREFIX,0,szTempFileName))
goto MergeExit;
#endif
hFile = CreateFile(szTempFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
FILE_FLAG_WRITE_THROUGH,0);
if (hFile == INVALID_HANDLE_VALUE)
goto MergeExit;
for (dwIdx = 0; dwIdx < m_cPhoneBookEntries; dwIdx++)
{
cch = wsprintf(szTempBuffer, "%lu,%lu,%lu,%s,%s,%s,%lu,%lu,%lu,%lu,%s\r\n",
rgIdxLookUp[dwIdx].pAE->dwIndex,
rgIdxLookUp[dwIdx].pAE->dwCountryID,
DWORD(rgIdxLookUp[dwIdx].pAE->wStateID),
rgIdxLookUp[dwIdx].pAE->szCity,
rgIdxLookUp[dwIdx].pAE->szAreaCode,
rgIdxLookUp[dwIdx].pAE->szAccessNumber,
rgIdxLookUp[dwIdx].pAE->dwConnectSpeedMin,
rgIdxLookUp[dwIdx].pAE->dwConnectSpeedMax,
DWORD(rgIdxLookUp[dwIdx].pAE->bFlipFactor),
DWORD(rgIdxLookUp[dwIdx].pAE->fType),
rgIdxLookUp[dwIdx].pAE->szDataCenter);
if (!WriteFile(hFile,szTempBuffer,cch,&cchWritten,NULL))
{
// something went wrong, get rid of the temporary file
CloseHandle(hFile);
DeleteFile(szTempFileName);
hr = GetLastError();
goto MergeExit;
}
Assert(cch == cchWritten);
}
CloseHandle(hFile);
hFile = NULL;
// Move new phone book over old
if (!MoveFileEx(szTempFileName,m_szPhoneBook,MOVEFILE_REPLACE_EXISTING))
{
hr = GetLastError();
goto MergeExit;
}
// discard the phonebook in memory
#ifndef WIN16
Assert(m_hPhoneBookEntry);
GlobalUnlock(m_hPhoneBookEntry);
#endif
m_rgPhoneBookEntry = NULL;
m_cPhoneBookEntries = 0;
GlobalFree(m_pLineCountryList);
GlobalFree(m_rgIDLookUp);
GlobalFree(m_rgNameLookUp);
GlobalFree(m_rgState);
m_cStates = 0;
lstrcpy(szTempBuffer,m_szINFCode);
m_szINFFile[0] = '\0';
m_szPhoneBook[0] = '\0';
m_szINFCode[0] = '\0';
// Reload it (and rebuild look up arrays)
hr = Init(szTempBuffer);
MergeExit:
if (hr != ERROR_SUCCESS)
{
GlobalFree(rgIdxLookUp);
if (pcCSVFile) delete pcCSVFile;
CloseHandle(hFile);
}
return hr;
}
// ############################################################################
HRESULT CPhoneBook::ReadOneLine(PACCESSENTRY lpAccessEntry, CCSVFile far *pcCSVFile)
{
HRESULT hr = ERROR_SUCCESS;
#if !defined(WIN16)
ReadOneLineStart:
#endif //WIN16
if (!ReadPhoneBookDW(&lpAccessEntry->dwIndex,pcCSVFile))
{
hr = ERROR_NO_MORE_ITEMS; // no more enteries
goto ReadExit;
}
ReadVerifyPhoneBookDW(lpAccessEntry->dwCountryID);
ReadVerifyPhoneBookW(lpAccessEntry->wStateID);
ReadVerifyPhoneBookSZ(lpAccessEntry->szCity,cbCity);
ReadVerifyPhoneBookSZ(lpAccessEntry->szAreaCode,cbAreaCode);
// NOTE: 0 is a valid area code and ,, is a valid entry for an area code
if (!FSz2Dw(lpAccessEntry->szAreaCode,&lpAccessEntry->dwAreaCode))
lpAccessEntry->dwAreaCode = NO_AREA_CODE;
ReadVerifyPhoneBookSZ(lpAccessEntry->szAccessNumber,cbAccessNumber);
ReadVerifyPhoneBookDW(lpAccessEntry->dwConnectSpeedMin);
ReadVerifyPhoneBookDW(lpAccessEntry->dwConnectSpeedMax);
ReadVerifyPhoneBookB(lpAccessEntry->bFlipFactor);
ReadVerifyPhoneBookDW(lpAccessEntry->fType);
ReadVerifyPhoneBookSZ(lpAccessEntry->szDataCenter,cbDataCenter);
#if !defined(WIN16)
//
// If scripting is not available and the phonebook entry has a dun file other than
// icwip.dun, then ignore the entry and read the one after that.
//
if (!m_bScriptingAvailable)
{
if (0 != lstrcmpi(lpAccessEntry->szDataCenter,"icwip.dun"))
{
ZeroMemory(lpAccessEntry,sizeof(ACCESSENTRY));
goto ReadOneLineStart;
}
}
#endif //WIN16
ReadExit:
return hr;
ReadError:
hr = ERROR_INVALID_DATA;
goto ReadExit;
}
// ############################################################################
HRESULT CPhoneBook::Suggest(PSUGGESTINFO pSuggest)
{
WORD wNumFound = 0;
HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
// Validate parameters
Assert(pSuggest);
Assert(pSuggest->wNumber);
if (wNumFound == pSuggest->wNumber)
goto SuggestExit;
LPIDLOOKUPELEMENT pCurLookUp;
PACCESSENTRY lpAccessEntry;
//REVIEW: double check this
pCurLookUp = (LPIDLOOKUPELEMENT)bsearch(&pSuggest->dwCountryID,m_rgIDLookUp,
(int)m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),
CompareIDLookUpElements);
// Check for invalid country
if (!pCurLookUp)
goto SuggestExit;
// Check if there are any phone numbers for this country
if (!pCurLookUp->pFirstAE) goto SuggestExit;
lpAccessEntry = pCurLookUp->pFirstAE;
do {
// check for the right area code
if (lpAccessEntry->dwAreaCode == pSuggest->wAreaCode)
{
// check for the right type of number
if ((lpAccessEntry->fType & pSuggest->bMask) == pSuggest->fType)
{
pSuggest->rgpAccessEntry[wNumFound] = lpAccessEntry;
wNumFound++;
}
}
lpAccessEntry++;
} while ((lpAccessEntry <= &m_rgPhoneBookEntry[m_cPhoneBookEntries-1]) &&
(wNumFound < pSuggest->wNumber) &&
(lpAccessEntry->dwCountryID == pSuggest->dwCountryID));
// if we couldn't find enough numnbers, try something else
// 10/15/96 jmazner ported fixes below from core\client\phbk
// Do this only if area code is not 0 - Bug #9349 (VetriV)
// if ((pSuggest->wAreaCode != 0) && (wNumFound < pSuggest->wNumber))
// No, there are some places (Finland? ChrisK knows) where 0 is a legit area code -- jmazner
if (wNumFound < pSuggest->wNumber)
{
lpAccessEntry = pCurLookUp->pFirstAE;
// Note: we are now only looking for Nationwide phone numbers (state = 0)
// 8/13/96 jmazner MOS Normandy #4597
// We want nationwide toll-free numbers to display last, so for this pass,
// only consider numbers that are _not_ toll free (fType bit #1 = 0)
// Tweak pSuggest->bMask to let through the toll/charge bit
pSuggest->bMask |= MASK_TOLLFREE_BIT;
// Tweak pSuggest->ftype to be charge
pSuggest->fType &= TYPE_SET_TOLL;
do {
// 8/13/96 jmazner MOS Normandy #4598
// If this entry's area code matches pSuggest->wAreaCode, then we already
// have included it in the previous pass, so don't duplicate it again here.
if ((lpAccessEntry->fType & pSuggest->bMask) == pSuggest->fType &&
lpAccessEntry->wStateID == 0 &&
lpAccessEntry->dwAreaCode != pSuggest->wAreaCode)
{
pSuggest->rgpAccessEntry[wNumFound] = lpAccessEntry;
wNumFound++;
}
lpAccessEntry++;
} while ((lpAccessEntry <= &m_rgPhoneBookEntry[m_cPhoneBookEntries-1]) &&
(wNumFound < pSuggest->wNumber) &&
(lpAccessEntry->dwCountryID == pSuggest->dwCountryID) &&
(lpAccessEntry->wStateID == 0) );
}
// 8/13/96 jmazner MOS Normandy #4597
// if we STILL couldn't find enough numnbers, widen the search to include tollfree #s
if (wNumFound < pSuggest->wNumber)
{
lpAccessEntry = pCurLookUp->pFirstAE;
// Tweak pSuggest->bMask to let through the toll/charge bit
// REDUNDANT? If we made it to this point, we _should_ have done this above...
// Better safe than sorry!
Assert(pSuggest->bMask & MASK_TOLLFREE_BIT);
pSuggest->bMask |= MASK_TOLLFREE_BIT;
// Tweak pSuggest->ftype to be tollfree
pSuggest->fType |= TYPE_SET_TOLLFREE;
do {
// 8/13/96 jmazner MOS Normandy #4598
// If this entry's area code matches pSuggest->wAreaCode, then we already
// have included it in the first pass, so don't include it here.
// Any entry that made it in in the 2nd pass will definitely not make it in here
// (because of tollfree bit), so no need to worry about dups from there.
if ((lpAccessEntry->fType & pSuggest->bMask) == pSuggest->fType &&
lpAccessEntry->wStateID == 0 &&
lpAccessEntry->dwAreaCode != pSuggest->wAreaCode)
{
pSuggest->rgpAccessEntry[wNumFound] = lpAccessEntry;
wNumFound++;
}
lpAccessEntry++;
} while ((lpAccessEntry <= &m_rgPhoneBookEntry[m_cPhoneBookEntries-1]) &&
(wNumFound < pSuggest->wNumber) &&
(lpAccessEntry->dwCountryID == pSuggest->dwCountryID) &&
(lpAccessEntry->wStateID == 0) );
}
hr = ERROR_SUCCESS;
SuggestExit:
pSuggest->wNumber = wNumFound;
return hr;
}
// ############################################################################
HRESULT CPhoneBook::GetCanonical (PACCESSENTRY pAE, LPSTR psOut)
{
HRESULT hr = ERROR_SUCCESS;
LPIDLOOKUPELEMENT pIDLookUp;
pIDLookUp = (LPIDLOOKUPELEMENT)bsearch(&pAE->dwCountryID,m_rgIDLookUp,
(int)m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),CompareIdxLookUpElements);
if (!pIDLookUp)
{
hr = ERROR_INVALID_PARAMETER;
} else {
SzCanonicalFromAE (psOut, pAE, pIDLookUp->pLCE);
}
return hr;
}
// ############################################################################
DllExportH PhoneBookLoad(LPCSTR pszISPCode, DWORD_PTR far *pdwPhoneID)
{
HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
CPhoneBook far *pcPhoneBook;
if (!g_hInstDll)
g_hInstDll = GetModuleHandle(NULL);
// validate parameters
Assert(pszISPCode && *pszISPCode && pdwPhoneID);
*pdwPhoneID = NULL;
// allocate phone book
pcPhoneBook = new CPhoneBook;
// initialize phone book
if (pcPhoneBook)
hr = pcPhoneBook->Init(pszISPCode);
// in case of failure
if (hr && pcPhoneBook)
{
delete pcPhoneBook;
} else {
*pdwPhoneID = (DWORD_PTR)pcPhoneBook;
}
#if defined(WIN16)
if (!hr)
BMP_RegisterClass(g_hInstDll);
#endif
return hr;
}
// ############################################################################
DllExportH PhoneBookUnload(DWORD_PTR dwPhoneID)
{
Assert(dwPhoneID);
if (dwPhoneID)
{
#if defined(WIN16)
BMP_DestroyClass(g_hInstDll);
#endif
// Release contents
delete (CPhoneBook far*)dwPhoneID;
}
return ERROR_SUCCESS;
}
// ############################################################################
DllExportH PhoneBookMergeChanges(DWORD_PTR dwPhoneID, LPCSTR pszChangeFile)
{
return ((CPhoneBook far*)dwPhoneID)->Merge(pszChangeFile);
}
// ############################################################################
DllExportH PhoneBookSuggestNumbers(DWORD_PTR dwPhoneID, PSUGGESTINFO lpSuggestInfo)
{
HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
// get suggested numbers
lpSuggestInfo->rgpAccessEntry = (PACCESSENTRY *)GlobalAlloc(GPTR,sizeof(PACCESSENTRY) * lpSuggestInfo->wNumber);
if (lpSuggestInfo->rgpAccessEntry)
{
hr = ((CPhoneBook far *)dwPhoneID)->Suggest(lpSuggestInfo);
}
return hr;
}
// ############################################################################
DllExportH PhoneBookGetCanonical (DWORD_PTR dwPhoneID, PACCESSENTRY pAE, LPSTR psOut)
{
return ((CPhoneBook far*)dwPhoneID)->GetCanonical(pAE,psOut);
}
// ############################################################################
DllExportH PhoneBookDisplaySignUpNumbers (DWORD_PTR dwPhoneID,
LPSTR far *ppszPhoneNumbers,
LPSTR far *ppszDunFiles,
WORD far *pwPhoneNumbers,
DWORD far *pdwCountry,
WORD far *pwRegion,
BYTE fType,
BYTE bMask,
HWND hwndParent,
DWORD dwFlags)
{
INT_PTR hr;
AssertSz(ppszPhoneNumbers && pwPhoneNumbers && pdwCountry &&pwRegion,"invalid parameters");
//CAccessNumDlg *pcDlg;
CSelectNumDlg far *pcDlg;
pcDlg = new CSelectNumDlg;
if (!pcDlg)
{
hr = GetLastError();
goto DisplayExit;
}
// Initialize information for dialog
//
pcDlg->m_dwPhoneBook = dwPhoneID;
pcDlg->m_dwCountryID = *pdwCountry;
pcDlg->m_wRegion = *pwRegion;
pcDlg->m_fType = fType;
pcDlg->m_bMask = bMask;
pcDlg->m_dwFlags = dwFlags;
// invoke the dialog
//
// BUG: NOT THREAD SAFE!!
g_hWndMain = hwndParent;
hr = DialogBoxParam(g_hInstDll,MAKEINTRESOURCE(IDD_SELECTNUMBER),
g_hWndMain,PhbkGenericDlgProc,(LPARAM)pcDlg);
g_hWndMain = NULL;
if (hr == IDC_CMDNEXT)
{
*pwRegion = pcDlg->m_wRegion;
*pdwCountry = pcDlg->m_dwCountryID;
Assert (ppszPhoneNumbers[0] && ppszDunFiles[0]);
lstrcpy(ppszPhoneNumbers[0],&pcDlg->m_szPhoneNumber[0]);
lstrcpy(ppszDunFiles[0],&pcDlg->m_szDunFile[0]);
hr = ERROR_SUCCESS;
}
else if (hr == IDC_CMDBACK)
hr = ERROR_USERBACK;
else
hr = ERROR_USERCANCEL;
// hr == -1;
DisplayExit:
if (pcDlg) delete pcDlg;
return (HRESULT) hr;
}