Source code of Windows XP (NT5)
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.

1307 lines
34 KiB

  1. // ############################################################################
  2. // Phone book APIs
  3. #include "pch.hpp"
  4. #include <tchar.h>
  5. #include "phbk.h"
  6. #include "misc.h"
  7. #include "phbkrc.h"
  8. #include "suapi.h"
  9. #define ReadVerifyPhoneBookDW(x) if (!ReadPhoneBookDW(&(x),pcCSVFile)) \
  10. { AssertSz(0,"Invalid DWORD in phone book"); \
  11. goto ReadError; }
  12. #define ReadVerifyPhoneBookW(x) if (!ReadPhoneBookW(&(x),pcCSVFile)) \
  13. { AssertSz(0,"Invalid DWORD in phone book"); \
  14. goto ReadError; }
  15. #define ReadVerifyPhoneBookB(x) if (!ReadPhoneBookB(&(x),pcCSVFile)) \
  16. { AssertSz(0,"Invalid DWORD in phone book"); \
  17. goto ReadError; }
  18. #define ReadVerifyPhoneBookSZ(x,y) if (!ReadPhoneBookSZ(&x[0],y+sizeof('\0'),pcCSVFile)) \
  19. { AssertSz(0,"Invalid DWORD in phone book"); \
  20. goto ReadError; }
  21. #define CHANGE_BUFFER_SIZE 50
  22. #define TEMP_PHONE_BOOK_PREFIX "PBH"
  23. #define ERROR_USERBACK 32766
  24. #define ERROR_USERCANCEL 32767
  25. char szTempBuffer[TEMP_BUFFER_LENGTH];
  26. char szTempFileName[MAX_PATH];
  27. #ifdef __cplusplus
  28. extern "C" {
  29. #endif
  30. HWND g_hWndMain;
  31. #ifdef __cplusplus
  32. }
  33. #endif
  34. static void GetAbsolutePath( LPTSTR input, LPTSTR output, DWORD chOut)
  35. {
  36. if(_tcschr(input,_T('%')) == NULL) {
  37. _tcsncpy(output, input, chOut);
  38. return ;
  39. }
  40. if(input[0] == _T('%'))
  41. {
  42. LPTSTR token = _tcstok(input,_T("%"));
  43. if(token != NULL)
  44. {
  45. LPTSTR sztemp;
  46. sztemp = getenv( token );
  47. if(sztemp != NULL)
  48. {
  49. _tcsncpy(output, sztemp, chOut);
  50. }
  51. token = _tcstok(NULL,_T("\0"));
  52. if(token != NULL)
  53. {
  54. _tcsncat(output, token, chOut - _tcslen(output));
  55. }
  56. }
  57. }
  58. else
  59. {
  60. LPTSTR token = _tcstok(input,_T("%"));
  61. if(token != NULL)
  62. {
  63. _tcsncpy(output, token, chOut);
  64. token = _tcstok(NULL,_T("%"));
  65. if(token != NULL)
  66. {
  67. LPTSTR sztemp;
  68. sztemp = getenv( token );
  69. if(sztemp != NULL)
  70. {
  71. _tcsncat(output, sztemp, chOut - _tcslen(output));
  72. }
  73. token = _tcstok(NULL,_T("\0"));
  74. if(token != NULL)
  75. {
  76. _tcsncat(output, token, chOut - _tcslen(output));
  77. }
  78. }
  79. }
  80. }
  81. GetAbsolutePath(output, output, chOut);
  82. }
  83. // ############################################################################
  84. CPhoneBook::CPhoneBook()
  85. {
  86. HINSTANCE hInst = NULL;
  87. LONG lrc;
  88. // HANDLE hKey;
  89. LONG regStatus;
  90. char uszRegKey[]="SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\ICWCONN1.EXE";
  91. char uszR[ ]= "Path";
  92. DWORD dwInfoSize ;
  93. HKEY hKey;
  94. DWORD dwType;
  95. DWORD dwSize;
  96. CHAR szData[MAX_PATH+1];
  97. CHAR czTemp[256];
  98. m_rgPhoneBookEntry = NULL;
  99. m_hPhoneBookEntry = NULL;
  100. m_cPhoneBookEntries =0;
  101. m_rgLineCountryEntry=NULL;
  102. m_rgState=NULL;
  103. m_cStates=0;
  104. m_rgIDLookUp = NULL;
  105. m_rgNameLookUp = NULL;
  106. m_pLineCountryList = NULL;
  107. ZeroMemory(&m_szINFFile[0],MAX_PATH);
  108. ZeroMemory(&m_szINFCode[0],MAX_INFCODE);
  109. ZeroMemory(&m_szPhoneBook[0],MAX_PATH);
  110. ZeroMemory(&m_szICWDirectoryPath,MAX_PATH);
  111. regStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  112. uszRegKey,0,KEY_READ ,&hKey);
  113. if (regStatus == ERROR_SUCCESS) {
  114. // Get The Path
  115. dwInfoSize = MAX_PATH;
  116. RegQueryValueEx(hKey,uszR,NULL,0,(LPBYTE) czTemp,
  117. &dwInfoSize);
  118. GetAbsolutePath(czTemp,m_szICWDirectoryPath, MAX_PATH-1);
  119. size_t sLen = strlen(m_szICWDirectoryPath);
  120. m_szICWDirectoryPath[sLen-1] = '\0';
  121. }
  122. else {
  123. MessageBox(NULL,"Error Accessing PAth ","SearchPath",MB_OK);
  124. // Error
  125. }
  126. #if !defined(WIN16)
  127. if (VER_PLATFORM_WIN32_NT == DWGetWin32Platform())
  128. {
  129. m_bScriptingAvailable = TRUE;
  130. }
  131. else
  132. {
  133. //
  134. // Verify scripting by checking for smmscrpt.dll in RemoteAccess registry key
  135. //
  136. if (1111 <= DWGetWin32BuildNumber())
  137. {
  138. m_bScriptingAvailable = TRUE;
  139. }
  140. else
  141. {
  142. m_bScriptingAvailable = FALSE;
  143. hKey = NULL;
  144. lrc=RegOpenKey(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\Services\\RemoteAccess\\Authentication\\SMM_FILES\\PPP",&hKey);
  145. if (ERROR_SUCCESS == lrc)
  146. {
  147. dwSize = MAX_PATH;
  148. lrc = RegQueryValueEx(hKey,"Path",0,&dwType,(LPBYTE)szData,&dwSize);
  149. if (ERROR_SUCCESS == lrc)
  150. {
  151. if (0 == lstrcmpi(szData,"smmscrpt.dll"))
  152. m_bScriptingAvailable = TRUE;
  153. }
  154. }
  155. if (hKey)
  156. RegCloseKey(hKey);
  157. hKey = NULL;
  158. }
  159. //
  160. // Verify that the DLL can be loaded
  161. //
  162. if (m_bScriptingAvailable)
  163. {
  164. hInst = LoadLibrary("smmscrpt.dll");
  165. if (hInst)
  166. FreeLibrary(hInst);
  167. else
  168. m_bScriptingAvailable = FALSE;
  169. hInst = NULL;
  170. }
  171. }
  172. #endif // WIN16
  173. }
  174. // ############################################################################
  175. CPhoneBook::~CPhoneBook()
  176. {
  177. #ifdef WIN16
  178. if (m_rgPhoneBookEntry)
  179. GlobalFree(m_rgPhoneBookEntry);
  180. #else
  181. if (m_hPhoneBookEntry)
  182. GlobalUnlock(m_hPhoneBookEntry);
  183. if (m_hPhoneBookEntry)
  184. GlobalFree(m_hPhoneBookEntry);
  185. #endif
  186. if (m_pLineCountryList)
  187. GlobalFree(m_pLineCountryList);
  188. if (m_rgIDLookUp)
  189. GlobalFree(m_rgIDLookUp);
  190. if (m_rgNameLookUp)
  191. GlobalFree(m_rgNameLookUp);
  192. if (m_rgState)
  193. GlobalFree(m_rgState);
  194. }
  195. // ############################################################################
  196. BOOL CPhoneBook::ReadPhoneBookDW(DWORD far *pdw, CCSVFile far *pcCSVFile)
  197. {
  198. if (!pcCSVFile->ReadToken(szTempBuffer,TEMP_BUFFER_LENGTH))
  199. return FALSE;
  200. return (FSz2Dw(szTempBuffer,pdw));
  201. }
  202. // ############################################################################
  203. BOOL CPhoneBook::ReadPhoneBookW(WORD far *pw, CCSVFile far *pcCSVFile)
  204. {
  205. if (!pcCSVFile->ReadToken(szTempBuffer,TEMP_BUFFER_LENGTH))
  206. return FALSE;
  207. return (FSz2W(szTempBuffer,pw));
  208. }
  209. // ############################################################################
  210. BOOL CPhoneBook::ReadPhoneBookB(BYTE far *pb, CCSVFile far *pcCSVFile)
  211. {
  212. if (!pcCSVFile->ReadToken(szTempBuffer,TEMP_BUFFER_LENGTH))
  213. return FALSE;
  214. return (FSz2B(szTempBuffer,pb));
  215. }
  216. // ############################################################################
  217. BOOL CPhoneBook::ReadPhoneBookSZ(LPSTR psz, DWORD dwSize, CCSVFile far *pcCSVFile)
  218. {
  219. if (!pcCSVFile->ReadToken(psz,dwSize))
  220. return FALSE;
  221. return TRUE;
  222. }
  223. // ############################################################################
  224. BOOL CPhoneBook::FixUpFromRealloc(PACCESSENTRY paeOld, PACCESSENTRY paeNew)
  225. {
  226. BOOL bRC = FALSE;
  227. LONG_PTR lDiff = 0;
  228. DWORD idx = 0;
  229. //
  230. // No starting value or no move, therefore no fix-ups needed
  231. //
  232. if ((0 == paeOld) || (paeNew == paeOld))
  233. {
  234. bRC = TRUE;
  235. goto FixUpFromReallocExit;
  236. }
  237. Assert(paeNew);
  238. Assert(((LONG_PTR)paeOld) > 0); // if these address look like negative numbers
  239. Assert(((LONG_PTR)paeNew) > 0); // I'm not sure the code would handle them
  240. lDiff = (LONG_PTR)paeOld - (LONG_PTR)paeNew;
  241. //
  242. // fix up STATES
  243. //
  244. for (idx = 0; idx < m_cStates; idx++)
  245. {
  246. if (m_rgState[idx].paeFirst)
  247. m_rgState[idx].paeFirst = (PACCESSENTRY )((LONG_PTR)m_rgState[idx].paeFirst - lDiff);
  248. }
  249. //
  250. // fix up ID look up array
  251. //
  252. for (idx = 0; idx < m_pLineCountryList->dwNumCountries ; idx++)
  253. {
  254. if (m_rgIDLookUp[idx].pFirstAE)
  255. m_rgIDLookUp[idx].pFirstAE = (PACCESSENTRY )((LONG_PTR)m_rgIDLookUp[idx].pFirstAE - lDiff);
  256. }
  257. bRC = TRUE;
  258. FixUpFromReallocExit:
  259. return bRC;
  260. }
  261. /*
  262. long WINAPI lineGetCountry(unsigned long x,unsigned long y,struct linecountrylist_tag *z)
  263. {
  264. return 0;
  265. }
  266. */
  267. // ############################################################################
  268. HRESULT CPhoneBook::Init(LPCSTR pszISPCode)
  269. {
  270. LPLINECOUNTRYLIST pLineCountryTemp = NULL;
  271. HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
  272. DWORD dwLastState = 0;
  273. DWORD dwLastCountry = 0;
  274. DWORD dwSizeAllocated;
  275. PACCESSENTRY pCurAccessEntry;
  276. PACCESSENTRY pAETemp;
  277. LPLINECOUNTRYENTRY pLCETemp;
  278. DWORD idx;
  279. LPSTR pszTemp;
  280. CCSVFile far *pcCSVFile=NULL;
  281. LPSTATE ps,psLast; //faster to use pointers.
  282. int iTestSK;
  283. // Get TAPI country list
  284. m_pLineCountryList = (LPLINECOUNTRYLIST)GlobalAlloc(GPTR,sizeof(LINECOUNTRYLIST));
  285. if (!m_pLineCountryList)
  286. goto InitExit;
  287. m_pLineCountryList->dwTotalSize = sizeof(LINECOUNTRYLIST);
  288. #if defined(WIN16)
  289. idx = (DWORD) IETapiGetCountry(0, m_pLineCountryList);
  290. #else
  291. idx = lineGetCountry(0,0x10003,m_pLineCountryList);
  292. #endif
  293. if (idx && idx != LINEERR_STRUCTURETOOSMALL)
  294. goto InitExit;
  295. Assert(m_pLineCountryList->dwNeededSize);
  296. pLineCountryTemp = (LPLINECOUNTRYLIST)GlobalAlloc(GPTR,
  297. (size_t)m_pLineCountryList->dwNeededSize);
  298. if (!pLineCountryTemp)
  299. goto InitExit;
  300. pLineCountryTemp->dwTotalSize = m_pLineCountryList->dwNeededSize;
  301. GlobalFree(m_pLineCountryList);
  302. m_pLineCountryList = pLineCountryTemp;
  303. pLineCountryTemp = NULL;
  304. #if defined(WIN16)
  305. if (IETapiGetCountry(0, m_pLineCountryList))
  306. #else
  307. if (lineGetCountry(0,0x10003,m_pLineCountryList))
  308. #endif
  309. goto InitExit;
  310. //#endif // WIN16
  311. // Load Look Up arrays
  312. #ifdef DEBUG
  313. m_rgIDLookUp = (LPIDLOOKUPELEMENT)GlobalAlloc(GPTR,
  314. (int)(sizeof(IDLOOKUPELEMENT)*m_pLineCountryList->dwNumCountries+5));
  315. #else
  316. m_rgIDLookUp = (LPIDLOOKUPELEMENT)GlobalAlloc(GPTR,
  317. (int)(sizeof(IDLOOKUPELEMENT)*m_pLineCountryList->dwNumCountries));
  318. #endif
  319. if (!m_rgIDLookUp) goto InitExit;
  320. pLCETemp = (LPLINECOUNTRYENTRY)((DWORD_PTR)m_pLineCountryList +
  321. m_pLineCountryList->dwCountryListOffset);
  322. for (idx=0;idx<m_pLineCountryList->dwNumCountries;idx++)
  323. {
  324. m_rgIDLookUp[idx].dwID = pLCETemp[idx].dwCountryID;
  325. m_rgIDLookUp[idx].pLCE = &pLCETemp[idx];
  326. }
  327. qsort(m_rgIDLookUp,(int)m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),
  328. CompareIDLookUpElements);
  329. m_rgNameLookUp = (LPCNTRYNAMELOOKUPELEMENT)GlobalAlloc(GPTR,
  330. (int)(sizeof(CNTRYNAMELOOKUPELEMENT) * m_pLineCountryList->dwNumCountries));
  331. if (!m_rgNameLookUp) goto InitExit;
  332. for (idx=0;idx<m_pLineCountryList->dwNumCountries;idx++)
  333. {
  334. m_rgNameLookUp[idx].psCountryName = (LPSTR)((LPBYTE)m_pLineCountryList + (DWORD)pLCETemp[idx].dwCountryNameOffset);
  335. m_rgNameLookUp[idx].dwNameSize = pLCETemp[idx].dwCountryNameSize;
  336. m_rgNameLookUp[idx].pLCE = &pLCETemp[idx];
  337. }
  338. qsort(m_rgNameLookUp,(int)m_pLineCountryList->dwNumCountries,sizeof(CNTRYNAMELOOKUPELEMENT),
  339. CompareCntryNameLookUpElements);
  340. // Load States
  341. if (!SearchPath(NULL,STATE_FILENAME,NULL,TEMP_BUFFER_LENGTH,szTempBuffer,&pszTemp))
  342. {
  343. if(m_szICWDirectoryPath){
  344. // Try with c:\\ProgramFile\\ICW-INTERNET\\......
  345. if(! SearchPath(m_szICWDirectoryPath,
  346. STATE_FILENAME,NULL,TEMP_BUFFER_LENGTH,szTempBuffer,&pszTemp)) {
  347. AssertSz(0,"STATE.ICW not found");
  348. hr = ERROR_FILE_NOT_FOUND;
  349. goto InitExit;
  350. }else {
  351. ; // OK Th e file is found
  352. iTestSK=0;
  353. }
  354. }
  355. else {
  356. AssertSz(0,"STATE.ICW not found");
  357. hr = ERROR_FILE_NOT_FOUND;
  358. goto InitExit;
  359. }
  360. }
  361. pcCSVFile = new CCSVFile;
  362. if (!pcCSVFile) goto InitExit;
  363. if (!pcCSVFile->Open(szTempBuffer))
  364. {
  365. AssertSz(0,"Can not open STATE.ICW");
  366. delete pcCSVFile;
  367. pcCSVFile = NULL;
  368. goto InitExit;
  369. }
  370. // first token in state file is the number of states
  371. if (!pcCSVFile->ReadToken(szTempBuffer,TEMP_BUFFER_LENGTH))
  372. goto InitExit;
  373. if (!FSz2Dw(szTempBuffer,&m_cStates))
  374. {
  375. AssertSz(0,"STATE.ICW count is invalid");
  376. goto InitExit;
  377. }
  378. m_rgState = (LPSTATE)GlobalAlloc(GPTR,(int)(sizeof(STATE)*m_cStates));
  379. if (!m_rgState)
  380. goto InitExit;
  381. for (ps = m_rgState, psLast = &m_rgState[m_cStates - 1]; ps <= psLast;++ps)
  382. {
  383. pcCSVFile->ReadToken(ps->szStateName,cbStateName);
  384. }
  385. pcCSVFile->Close();
  386. // Locate ISP's INF file
  387. if (!SearchPath(NULL,(LPCTSTR) pszISPCode,INF_SUFFIX,MAX_PATH,
  388. m_szINFFile,&pszTemp))
  389. {
  390. wsprintf(szTempBuffer,"Can not find:%s%s (%d)",pszISPCode,INF_SUFFIX,GetLastError());
  391. if(m_szICWDirectoryPath) {
  392. if(!SearchPath(m_szICWDirectoryPath,(LPCTSTR) pszISPCode,INF_SUFFIX,MAX_PATH,
  393. m_szINFFile,&pszTemp)) {
  394. AssertSz(0,szTempBuffer);
  395. hr = ERROR_FILE_NOT_FOUND;
  396. goto InitExit;
  397. //
  398. }else {
  399. iTestSK++;
  400. }
  401. }else {
  402. AssertSz(0,szTempBuffer);
  403. hr = ERROR_FILE_NOT_FOUND;
  404. goto InitExit;
  405. }
  406. }
  407. //Load Phone Book
  408. if (!GetPrivateProfileString(INF_APP_NAME,INF_PHONE_BOOK,INF_DEFAULT,
  409. szTempBuffer,TEMP_BUFFER_LENGTH,m_szINFFile))
  410. {
  411. AssertSz(0,"PhoneBookFile not specified in INF file");
  412. hr = ERROR_FILE_NOT_FOUND;
  413. goto InitExit;
  414. }
  415. #ifdef DEBUG
  416. if (!lstrcmp(szTempBuffer,INF_DEFAULT))
  417. {
  418. wsprintf(szTempBuffer, "%s value not found in ISP file", INF_PHONE_BOOK);
  419. AssertSz(0,szTempBuffer);
  420. }
  421. #endif
  422. if (!SearchPath(NULL,szTempBuffer,NULL,MAX_PATH,m_szPhoneBook,&pszTemp))
  423. {
  424. if(m_szICWDirectoryPath){
  425. if (!SearchPath(m_szICWDirectoryPath,szTempBuffer,NULL,MAX_PATH,m_szPhoneBook,&pszTemp)){
  426. AssertSz(0,"ISP phone book not found");
  427. hr = ERROR_FILE_NOT_FOUND;
  428. goto InitExit;
  429. }else {
  430. ;; // OK file Found
  431. iTestSK++;
  432. }
  433. }else {
  434. AssertSz(0,"ISP phone book not found");
  435. hr = ERROR_FILE_NOT_FOUND;
  436. goto InitExit;
  437. }
  438. }
  439. if (!pcCSVFile->Open(m_szPhoneBook))
  440. {
  441. AssertSz(0,"Can not open phone book");
  442. hr = GetLastError();
  443. goto InitExit;
  444. }
  445. dwSizeAllocated = 0;
  446. do {
  447. Assert (dwSizeAllocated >= m_cPhoneBookEntries);
  448. // check that sufficient memory is allocated
  449. if (m_rgPhoneBookEntry)
  450. {
  451. if (dwSizeAllocated == m_cPhoneBookEntries)
  452. {
  453. //
  454. // we need more memory
  455. //
  456. // AssertSz(0,"Out of memory originally allocated for phone book.\r\n");
  457. // goto InitExit;
  458. pAETemp = m_rgPhoneBookEntry;
  459. #ifdef WIN16
  460. dwSizeAllocated += PHONE_ENTRY_ALLOC_SIZE;
  461. m_rgPhoneBookEntry = (PACCESSENTRY)GlobalReAlloc(m_rgPhoneBookEntry,
  462. (int)(dwSizeAllocated * sizeof(ACCESSENTRY)),GHND);
  463. if (NULL == m_rgPhoneBookEntry)
  464. goto InitExit;
  465. #else
  466. // UNLOCK
  467. Assert(m_hPhoneBookEntry);
  468. if (FALSE == GlobalUnlock(m_hPhoneBookEntry))
  469. {
  470. if (NO_ERROR != GetLastError())
  471. goto InitExit;
  472. }
  473. // REALLOC
  474. dwSizeAllocated += PHONE_ENTRY_ALLOC_SIZE;
  475. m_hPhoneBookEntry = GlobalReAlloc(m_hPhoneBookEntry,
  476. (int)(dwSizeAllocated * sizeof(ACCESSENTRY)),GHND);
  477. if (NULL == m_hPhoneBookEntry)
  478. goto InitExit;
  479. // LOCK
  480. m_rgPhoneBookEntry = (PACCESSENTRY)GlobalLock(m_hPhoneBookEntry);
  481. if (NULL == m_rgPhoneBookEntry)
  482. goto InitExit;
  483. #endif
  484. FixUpFromRealloc(pAETemp, m_rgPhoneBookEntry);
  485. Dprintf("Grow phone book to %d entries\n",dwSizeAllocated);
  486. pCurAccessEntry = (PACCESSENTRY)((LONG_PTR)pCurAccessEntry -
  487. ((LONG_PTR)pAETemp - (LONG_PTR)(m_rgPhoneBookEntry)));
  488. }
  489. }
  490. else
  491. {
  492. //
  493. // Initialization for the first time through
  494. //
  495. // ALLOC
  496. #ifdef WIN16
  497. m_rgPhoneBookEntry = (PACCESSENTRY)GlobalAlloc(GHND,sizeof(ACCESSENTRY) * PHONE_ENTRY_ALLOC_SIZE);
  498. if(NULL == m_rgPhoneBookEntry)
  499. goto InitExit;
  500. #else
  501. m_hPhoneBookEntry = GlobalAlloc(GHND,sizeof(ACCESSENTRY) * PHONE_ENTRY_ALLOC_SIZE);
  502. if(NULL == m_hPhoneBookEntry)
  503. goto InitExit;
  504. // LOCK
  505. m_rgPhoneBookEntry = (PACCESSENTRY)GlobalLock(m_hPhoneBookEntry);
  506. if(NULL == m_rgPhoneBookEntry)
  507. goto InitExit;
  508. #endif
  509. dwSizeAllocated = PHONE_ENTRY_ALLOC_SIZE;
  510. pCurAccessEntry = m_rgPhoneBookEntry;
  511. }
  512. // Read a line from the phonebook
  513. hr = ReadOneLine(pCurAccessEntry,pcCSVFile);
  514. if (hr == ERROR_NO_MORE_ITEMS)
  515. {
  516. break;
  517. }
  518. else if (hr != ERROR_SUCCESS)
  519. {
  520. goto InitExit;
  521. }
  522. hr = ERROR_NOT_ENOUGH_MEMORY;
  523. // Check to see if this is the first phone number for a given country
  524. if (pCurAccessEntry->dwCountryID != dwLastCountry)
  525. {
  526. LPIDLOOKUPELEMENT lpIDLookupElement;
  527. // NOTE: Not sure about the first parameter here.
  528. lpIDLookupElement = (LPIDLOOKUPELEMENT)bsearch(&pCurAccessEntry->dwCountryID,
  529. m_rgIDLookUp,(int)m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),
  530. CompareIDLookUpElements);
  531. if (!lpIDLookupElement)
  532. {
  533. // bad country ID, but we can't assert here
  534. Dprintf("Bad country ID in phone book %d\n",pCurAccessEntry->dwCountryID);
  535. continue;
  536. }
  537. else
  538. {
  539. // for a given country ID this is the first phone number
  540. lpIDLookupElement->pFirstAE = pCurAccessEntry;
  541. dwLastCountry = pCurAccessEntry->dwCountryID;
  542. }
  543. }
  544. // Check to see if this is the first phone number for a given state
  545. if (pCurAccessEntry->wStateID && (pCurAccessEntry->wStateID != dwLastState))
  546. {
  547. idx = pCurAccessEntry->wStateID - 1;
  548. m_rgState[idx].dwCountryID = pCurAccessEntry->dwCountryID;
  549. m_rgState[idx].paeFirst = pCurAccessEntry;
  550. dwLastState = pCurAccessEntry->wStateID;
  551. }
  552. pCurAccessEntry++;
  553. m_cPhoneBookEntries++;
  554. } while (TRUE);
  555. // Trim the phone book for unused memory
  556. Assert(m_rgPhoneBookEntry && m_cPhoneBookEntries);
  557. pAETemp = m_rgPhoneBookEntry;
  558. #ifdef WIN16
  559. m_rgPhoneBookEntry = (PACCESSENTRY)GlobalReAlloc(m_rgPhoneBookEntry,(int)(m_cPhoneBookEntries * sizeof(ACCESSENTRY)),GHND);
  560. if (!m_rgPhoneBookEntry) goto InitExit;
  561. #else
  562. // UNLOCK
  563. Assert(m_hPhoneBookEntry);
  564. if (FALSE != GlobalUnlock(m_hPhoneBookEntry))
  565. {
  566. if (NO_ERROR != GetLastError())
  567. goto InitExit;
  568. }
  569. // REALLOC
  570. m_hPhoneBookEntry = GlobalReAlloc(m_hPhoneBookEntry,(int)(m_cPhoneBookEntries * sizeof(ACCESSENTRY)),GHND);
  571. if (NULL == m_hPhoneBookEntry)
  572. goto InitExit;
  573. // LOCK
  574. m_rgPhoneBookEntry = (PACCESSENTRY)GlobalLock(m_hPhoneBookEntry);
  575. if (NULL == m_rgPhoneBookEntry)
  576. goto InitExit;
  577. #endif
  578. FixUpFromRealloc(pAETemp, m_rgPhoneBookEntry);
  579. hr = ERROR_SUCCESS;
  580. InitExit:
  581. // If something failed release everything
  582. if (hr != ERROR_SUCCESS)
  583. {
  584. #ifdef WIN16
  585. GlobalFree(m_rgPhoneBookEntry);
  586. #else
  587. GlobalUnlock(m_hPhoneBookEntry);
  588. GlobalFree(m_hPhoneBookEntry);
  589. #endif
  590. GlobalFree(m_pLineCountryList);
  591. GlobalFree(m_rgIDLookUp);
  592. GlobalFree(m_rgNameLookUp);
  593. GlobalFree(m_rgState);
  594. m_cPhoneBookEntries = 0 ;
  595. m_cStates = 0;
  596. m_pLineCountryList = NULL;
  597. m_rgPhoneBookEntry = NULL;
  598. m_hPhoneBookEntry = NULL;
  599. m_rgIDLookUp=NULL;
  600. m_rgNameLookUp=NULL;
  601. m_rgState=NULL;
  602. }
  603. if (pcCSVFile)
  604. {
  605. pcCSVFile->Close();
  606. delete pcCSVFile;
  607. }
  608. return hr;
  609. }
  610. // ############################################################################
  611. HRESULT CPhoneBook::Merge(LPCSTR pszChangeFile)
  612. {
  613. CCSVFile far *pcCSVFile;
  614. ACCESSENTRY aeChange;
  615. LPIDXLOOKUPELEMENT rgIdxLookUp;
  616. LPIDXLOOKUPELEMENT pCurIdxLookUp;
  617. DWORD dwAllocated;
  618. DWORD dwUsed;
  619. DWORD dwOriginalSize;
  620. HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
  621. DWORD dwIdx;
  622. #if !defined(WIN16)
  623. HANDLE hTemp;
  624. HANDLE hIdxLookUp;
  625. #else
  626. // Normandy 11746
  627. LPVOID rgTemp; // 16-bit only
  628. #endif
  629. DWORD cch, cchWritten;
  630. HANDLE hFile;
  631. // Pad the phonebook for new entries.
  632. dwAllocated = m_cPhoneBookEntries + CHANGE_BUFFER_SIZE;
  633. #ifdef WIN16
  634. Assert(m_rgPhoneBookEntry);
  635. rgTemp = GlobalReAlloc(m_rgPhoneBookEntry, (int)(sizeof(ACCESSENTRY) * dwAllocated),GHND);
  636. Assert(rgTemp);
  637. if (!rgTemp) goto MergeExit;
  638. m_rgPhoneBookEntry = (PACCESSENTRY)rgTemp;
  639. #else
  640. Assert(m_hPhoneBookEntry);
  641. GlobalUnlock(m_hPhoneBookEntry);
  642. hTemp = (HANDLE)GlobalReAlloc(m_hPhoneBookEntry, sizeof(ACCESSENTRY) * dwAllocated,GHND);
  643. Assert(hTemp);
  644. if (!hTemp)
  645. goto MergeExit;
  646. m_rgPhoneBookEntry = (PACCESSENTRY)GlobalLock(m_hPhoneBookEntry);
  647. if (!m_rgPhoneBookEntry)
  648. goto MergeExit;
  649. #endif
  650. // Create index to loaded phone book, sorted by index
  651. #ifdef WIN16
  652. rgIdxLookUp = (LPIDXLOOKUPELEMENT)GlobalAlloc(GHND,(int)(sizeof(IDXLOOKUPELEMENT) * dwAllocated));
  653. #else
  654. hIdxLookUp = (HANDLE)GlobalAlloc(GHND,sizeof(IDXLOOKUPELEMENT) * dwAllocated);
  655. rgIdxLookUp = (LPIDXLOOKUPELEMENT)GlobalLock(hIdxLookUp);
  656. #endif
  657. Assert(rgIdxLookUp);
  658. if (!rgIdxLookUp)
  659. goto MergeExit;
  660. for (dwIdx = 0; dwIdx < m_cPhoneBookEntries; dwIdx++)
  661. {
  662. rgIdxLookUp[dwIdx].dwIndex = rgIdxLookUp[dwIdx].pAE->dwIndex;
  663. rgIdxLookUp[dwIdx].pAE = &m_rgPhoneBookEntry[dwIdx];
  664. }
  665. dwUsed = m_cPhoneBookEntries;
  666. dwOriginalSize = m_cPhoneBookEntries;
  667. qsort(rgIdxLookUp,(int)dwOriginalSize,sizeof(IDXLOOKUPELEMENT),CompareIdxLookUpElements);
  668. // Load changes to phone book
  669. pcCSVFile = new CCSVFile;
  670. Assert(pcCSVFile);
  671. if (!pcCSVFile)
  672. goto MergeExit;
  673. if (!pcCSVFile->Open(pszChangeFile))
  674. goto MergeExit;
  675. do {
  676. // Read a change record
  677. ZeroMemory(&aeChange,sizeof(ACCESSENTRY));
  678. hr = ReadOneLine(&aeChange, pcCSVFile);
  679. if(hr == ERROR_NO_MORE_ITEMS)
  680. {
  681. break; // no more enteries
  682. }
  683. else if (hr =! ERROR_SUCCESS)
  684. {
  685. goto MergeExit;
  686. }
  687. hr = ERROR_NOT_ENOUGH_MEMORY;
  688. // Determine if this is a delete or add record
  689. if (aeChange.szAccessNumber[0] == '0' && aeChange.szAccessNumber[1] == '\0')
  690. {
  691. // This is a delete record, find matching record
  692. // NOTE: we only search the numbers that existed before the change file,
  693. // because they are the only ones that are sorted.
  694. pCurIdxLookUp = (LPIDXLOOKUPELEMENT)bsearch(&aeChange,rgIdxLookUp,(int)dwOriginalSize,
  695. sizeof(IDXLOOKUPELEMENT),CompareIdxLookUpElements);
  696. AssertSz(pCurIdxLookUp,"Attempting to delete a record that does not exist. The change file and phone book versions do not match.");
  697. if (pCurIdxLookUp)
  698. pCurIdxLookUp->pAE = NULL; //Create a dead entry in the look up table
  699. m_cPhoneBookEntries--;
  700. }
  701. else
  702. {
  703. // This is an add entry
  704. m_cPhoneBookEntries++;
  705. dwUsed++;
  706. // Make sure we have enough room
  707. if (m_cPhoneBookEntries > dwAllocated)
  708. {
  709. // Grow phone book
  710. dwAllocated += CHANGE_BUFFER_SIZE;
  711. #ifdef WIN16
  712. Assert(m_rgPhoneBookEntry);
  713. rgTemp = GlobalReAlloc(m_rgPhoneBookEntry,(int)(sizeof(ACCESSENTRY)*dwAllocated),GHND);
  714. Assert(rgTemp);
  715. if (!rgTemp)
  716. goto MergeExit;
  717. m_rgPhoneBookEntry = (PACCESSENTRY)rgTemp;
  718. // Grow look up index
  719. Assert(rgIdxLookUp);
  720. rgTemp = GlobalReAlloc(rgIdxLookUp,(int)(sizeof(IDXLOOKUPELEMENT)*dwAllocated),GHND);
  721. Assert(rgTemp);
  722. if (!rgTemp)
  723. goto MergeExit;
  724. rgIdxLookUp = (LPIDXLOOKUPELEMENT)rgTemp;
  725. #else
  726. Assert(m_hPhoneBookEntry);
  727. GlobalUnlock(m_hPhoneBookEntry);
  728. hTemp = (HANDLE)GlobalReAlloc(m_hPhoneBookEntry,sizeof(ACCESSENTRY)*dwAllocated,GHND);
  729. Assert(hTemp);
  730. if (!hTemp)
  731. goto MergeExit;
  732. m_hPhoneBookEntry = hTemp;
  733. m_rgPhoneBookEntry = (PACCESSENTRY)GlobalLock(m_hPhoneBookEntry);
  734. Assert(m_rgPhoneBookEntry);
  735. if (!m_rgPhoneBookEntry)
  736. goto MergeExit;
  737. // Grow look up index
  738. Assert(hIdxLookUp);
  739. GlobalUnlock(hIdxLookUp);
  740. hTemp = (HANDLE)GlobalReAlloc(hIdxLookUp,sizeof(IDXLOOKUPELEMENT)*dwAllocated,GHND);
  741. Assert(hTemp);
  742. if (!hTemp)
  743. goto MergeExit;
  744. hIdxLookUp = hTemp;
  745. rgIdxLookUp = (LPIDXLOOKUPELEMENT)GlobalLock(hIdxLookUp);
  746. Assert(rgIdxLookUp);
  747. if (!rgIdxLookUp)
  748. goto MergeExit;
  749. #endif
  750. }
  751. //Add entry to the end of the phonebook and to end of look up index
  752. CopyMemory(&m_rgPhoneBookEntry[m_cPhoneBookEntries],&aeChange,sizeof(ACCESSENTRY));
  753. rgIdxLookUp[m_cPhoneBookEntries].dwIndex = m_rgPhoneBookEntry[m_cPhoneBookEntries].dwIndex;
  754. rgIdxLookUp[m_cPhoneBookEntries].pAE = &m_rgPhoneBookEntry[m_cPhoneBookEntries];
  755. // NOTE: because the entry is added to the end of the list, we can't add
  756. // and delete entries in the same change file.
  757. }
  758. } while (TRUE);
  759. // resort the IDXLookUp index to reflect the correct order of enteries
  760. // for the phonebook file, including all of the entries to be deleted.
  761. qsort(rgIdxLookUp,(int)dwUsed,sizeof(IDXLOOKUPELEMENT),CompareIdxLookUpElementsFileOrder);
  762. // Build a new phonebook file
  763. #ifdef WIN16
  764. GetTempFileName(0, TEMP_PHONE_BOOK_PREFIX, 0, szTempFileName);
  765. #else
  766. if (!GetTempPath(TEMP_BUFFER_LENGTH,szTempBuffer))
  767. goto MergeExit;
  768. if (!GetTempFileName(szTempBuffer,TEMP_PHONE_BOOK_PREFIX,0,szTempFileName))
  769. goto MergeExit;
  770. #endif
  771. hFile = CreateFile(szTempFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
  772. FILE_FLAG_WRITE_THROUGH,0);
  773. if (hFile == INVALID_HANDLE_VALUE)
  774. goto MergeExit;
  775. for (dwIdx = 0; dwIdx < m_cPhoneBookEntries; dwIdx++)
  776. {
  777. cch = wsprintf(szTempBuffer, "%lu,%lu,%lu,%s,%s,%s,%lu,%lu,%lu,%lu,%s\r\n",
  778. rgIdxLookUp[dwIdx].pAE->dwIndex,
  779. rgIdxLookUp[dwIdx].pAE->dwCountryID,
  780. DWORD(rgIdxLookUp[dwIdx].pAE->wStateID),
  781. rgIdxLookUp[dwIdx].pAE->szCity,
  782. rgIdxLookUp[dwIdx].pAE->szAreaCode,
  783. rgIdxLookUp[dwIdx].pAE->szAccessNumber,
  784. rgIdxLookUp[dwIdx].pAE->dwConnectSpeedMin,
  785. rgIdxLookUp[dwIdx].pAE->dwConnectSpeedMax,
  786. DWORD(rgIdxLookUp[dwIdx].pAE->bFlipFactor),
  787. DWORD(rgIdxLookUp[dwIdx].pAE->fType),
  788. rgIdxLookUp[dwIdx].pAE->szDataCenter);
  789. if (!WriteFile(hFile,szTempBuffer,cch,&cchWritten,NULL))
  790. {
  791. // something went wrong, get rid of the temporary file
  792. CloseHandle(hFile);
  793. DeleteFile(szTempFileName);
  794. hr = GetLastError();
  795. goto MergeExit;
  796. }
  797. Assert(cch == cchWritten);
  798. }
  799. CloseHandle(hFile);
  800. hFile = NULL;
  801. // Move new phone book over old
  802. if (!MoveFileEx(szTempFileName,m_szPhoneBook,MOVEFILE_REPLACE_EXISTING))
  803. {
  804. hr = GetLastError();
  805. goto MergeExit;
  806. }
  807. // discard the phonebook in memory
  808. #ifndef WIN16
  809. Assert(m_hPhoneBookEntry);
  810. GlobalUnlock(m_hPhoneBookEntry);
  811. #endif
  812. m_rgPhoneBookEntry = NULL;
  813. m_cPhoneBookEntries = 0;
  814. GlobalFree(m_pLineCountryList);
  815. GlobalFree(m_rgIDLookUp);
  816. GlobalFree(m_rgNameLookUp);
  817. GlobalFree(m_rgState);
  818. m_cStates = 0;
  819. lstrcpy(szTempBuffer,m_szINFCode);
  820. m_szINFFile[0] = '\0';
  821. m_szPhoneBook[0] = '\0';
  822. m_szINFCode[0] = '\0';
  823. // Reload it (and rebuild look up arrays)
  824. hr = Init(szTempBuffer);
  825. MergeExit:
  826. if (hr != ERROR_SUCCESS)
  827. {
  828. GlobalFree(rgIdxLookUp);
  829. if (pcCSVFile) delete pcCSVFile;
  830. CloseHandle(hFile);
  831. }
  832. return hr;
  833. }
  834. // ############################################################################
  835. HRESULT CPhoneBook::ReadOneLine(PACCESSENTRY lpAccessEntry, CCSVFile far *pcCSVFile)
  836. {
  837. HRESULT hr = ERROR_SUCCESS;
  838. #if !defined(WIN16)
  839. ReadOneLineStart:
  840. #endif //WIN16
  841. if (!ReadPhoneBookDW(&lpAccessEntry->dwIndex,pcCSVFile))
  842. {
  843. hr = ERROR_NO_MORE_ITEMS; // no more enteries
  844. goto ReadExit;
  845. }
  846. ReadVerifyPhoneBookDW(lpAccessEntry->dwCountryID);
  847. ReadVerifyPhoneBookW(lpAccessEntry->wStateID);
  848. ReadVerifyPhoneBookSZ(lpAccessEntry->szCity,cbCity);
  849. ReadVerifyPhoneBookSZ(lpAccessEntry->szAreaCode,cbAreaCode);
  850. // NOTE: 0 is a valid area code and ,, is a valid entry for an area code
  851. if (!FSz2Dw(lpAccessEntry->szAreaCode,&lpAccessEntry->dwAreaCode))
  852. lpAccessEntry->dwAreaCode = NO_AREA_CODE;
  853. ReadVerifyPhoneBookSZ(lpAccessEntry->szAccessNumber,cbAccessNumber);
  854. ReadVerifyPhoneBookDW(lpAccessEntry->dwConnectSpeedMin);
  855. ReadVerifyPhoneBookDW(lpAccessEntry->dwConnectSpeedMax);
  856. ReadVerifyPhoneBookB(lpAccessEntry->bFlipFactor);
  857. ReadVerifyPhoneBookDW(lpAccessEntry->fType);
  858. ReadVerifyPhoneBookSZ(lpAccessEntry->szDataCenter,cbDataCenter);
  859. #if !defined(WIN16)
  860. //
  861. // If scripting is not available and the phonebook entry has a dun file other than
  862. // icwip.dun, then ignore the entry and read the one after that.
  863. //
  864. if (!m_bScriptingAvailable)
  865. {
  866. if (0 != lstrcmpi(lpAccessEntry->szDataCenter,"icwip.dun"))
  867. {
  868. ZeroMemory(lpAccessEntry,sizeof(ACCESSENTRY));
  869. goto ReadOneLineStart;
  870. }
  871. }
  872. #endif //WIN16
  873. ReadExit:
  874. return hr;
  875. ReadError:
  876. hr = ERROR_INVALID_DATA;
  877. goto ReadExit;
  878. }
  879. // ############################################################################
  880. HRESULT CPhoneBook::Suggest(PSUGGESTINFO pSuggest)
  881. {
  882. WORD wNumFound = 0;
  883. HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
  884. // Validate parameters
  885. Assert(pSuggest);
  886. Assert(pSuggest->wNumber);
  887. if (wNumFound == pSuggest->wNumber)
  888. goto SuggestExit;
  889. LPIDLOOKUPELEMENT pCurLookUp;
  890. PACCESSENTRY lpAccessEntry;
  891. //REVIEW: double check this
  892. pCurLookUp = (LPIDLOOKUPELEMENT)bsearch(&pSuggest->dwCountryID,m_rgIDLookUp,
  893. (int)m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),
  894. CompareIDLookUpElements);
  895. // Check for invalid country
  896. if (!pCurLookUp)
  897. goto SuggestExit;
  898. // Check if there are any phone numbers for this country
  899. if (!pCurLookUp->pFirstAE) goto SuggestExit;
  900. lpAccessEntry = pCurLookUp->pFirstAE;
  901. do {
  902. // check for the right area code
  903. if (lpAccessEntry->dwAreaCode == pSuggest->wAreaCode)
  904. {
  905. // check for the right type of number
  906. if ((lpAccessEntry->fType & pSuggest->bMask) == pSuggest->fType)
  907. {
  908. pSuggest->rgpAccessEntry[wNumFound] = lpAccessEntry;
  909. wNumFound++;
  910. }
  911. }
  912. lpAccessEntry++;
  913. } while ((lpAccessEntry <= &m_rgPhoneBookEntry[m_cPhoneBookEntries-1]) &&
  914. (wNumFound < pSuggest->wNumber) &&
  915. (lpAccessEntry->dwCountryID == pSuggest->dwCountryID));
  916. // if we couldn't find enough numnbers, try something else
  917. // 10/15/96 jmazner ported fixes below from core\client\phbk
  918. // Do this only if area code is not 0 - Bug #9349 (VetriV)
  919. // if ((pSuggest->wAreaCode != 0) && (wNumFound < pSuggest->wNumber))
  920. // No, there are some places (Finland? ChrisK knows) where 0 is a legit area code -- jmazner
  921. if (wNumFound < pSuggest->wNumber)
  922. {
  923. lpAccessEntry = pCurLookUp->pFirstAE;
  924. // Note: we are now only looking for Nationwide phone numbers (state = 0)
  925. // 8/13/96 jmazner MOS Normandy #4597
  926. // We want nationwide toll-free numbers to display last, so for this pass,
  927. // only consider numbers that are _not_ toll free (fType bit #1 = 0)
  928. // Tweak pSuggest->bMask to let through the toll/charge bit
  929. pSuggest->bMask |= MASK_TOLLFREE_BIT;
  930. // Tweak pSuggest->ftype to be charge
  931. pSuggest->fType &= TYPE_SET_TOLL;
  932. do {
  933. // 8/13/96 jmazner MOS Normandy #4598
  934. // If this entry's area code matches pSuggest->wAreaCode, then we already
  935. // have included it in the previous pass, so don't duplicate it again here.
  936. if ((lpAccessEntry->fType & pSuggest->bMask) == pSuggest->fType &&
  937. lpAccessEntry->wStateID == 0 &&
  938. lpAccessEntry->dwAreaCode != pSuggest->wAreaCode)
  939. {
  940. pSuggest->rgpAccessEntry[wNumFound] = lpAccessEntry;
  941. wNumFound++;
  942. }
  943. lpAccessEntry++;
  944. } while ((lpAccessEntry <= &m_rgPhoneBookEntry[m_cPhoneBookEntries-1]) &&
  945. (wNumFound < pSuggest->wNumber) &&
  946. (lpAccessEntry->dwCountryID == pSuggest->dwCountryID) &&
  947. (lpAccessEntry->wStateID == 0) );
  948. }
  949. // 8/13/96 jmazner MOS Normandy #4597
  950. // if we STILL couldn't find enough numnbers, widen the search to include tollfree #s
  951. if (wNumFound < pSuggest->wNumber)
  952. {
  953. lpAccessEntry = pCurLookUp->pFirstAE;
  954. // Tweak pSuggest->bMask to let through the toll/charge bit
  955. // REDUNDANT? If we made it to this point, we _should_ have done this above...
  956. // Better safe than sorry!
  957. Assert(pSuggest->bMask & MASK_TOLLFREE_BIT);
  958. pSuggest->bMask |= MASK_TOLLFREE_BIT;
  959. // Tweak pSuggest->ftype to be tollfree
  960. pSuggest->fType |= TYPE_SET_TOLLFREE;
  961. do {
  962. // 8/13/96 jmazner MOS Normandy #4598
  963. // If this entry's area code matches pSuggest->wAreaCode, then we already
  964. // have included it in the first pass, so don't include it here.
  965. // Any entry that made it in in the 2nd pass will definitely not make it in here
  966. // (because of tollfree bit), so no need to worry about dups from there.
  967. if ((lpAccessEntry->fType & pSuggest->bMask) == pSuggest->fType &&
  968. lpAccessEntry->wStateID == 0 &&
  969. lpAccessEntry->dwAreaCode != pSuggest->wAreaCode)
  970. {
  971. pSuggest->rgpAccessEntry[wNumFound] = lpAccessEntry;
  972. wNumFound++;
  973. }
  974. lpAccessEntry++;
  975. } while ((lpAccessEntry <= &m_rgPhoneBookEntry[m_cPhoneBookEntries-1]) &&
  976. (wNumFound < pSuggest->wNumber) &&
  977. (lpAccessEntry->dwCountryID == pSuggest->dwCountryID) &&
  978. (lpAccessEntry->wStateID == 0) );
  979. }
  980. hr = ERROR_SUCCESS;
  981. SuggestExit:
  982. pSuggest->wNumber = wNumFound;
  983. return hr;
  984. }
  985. // ############################################################################
  986. HRESULT CPhoneBook::GetCanonical (PACCESSENTRY pAE, LPSTR psOut)
  987. {
  988. HRESULT hr = ERROR_SUCCESS;
  989. LPIDLOOKUPELEMENT pIDLookUp;
  990. pIDLookUp = (LPIDLOOKUPELEMENT)bsearch(&pAE->dwCountryID,m_rgIDLookUp,
  991. (int)m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),CompareIdxLookUpElements);
  992. if (!pIDLookUp)
  993. {
  994. hr = ERROR_INVALID_PARAMETER;
  995. } else {
  996. SzCanonicalFromAE (psOut, pAE, pIDLookUp->pLCE);
  997. }
  998. return hr;
  999. }
  1000. // ############################################################################
  1001. DllExportH PhoneBookLoad(LPCSTR pszISPCode, DWORD_PTR far *pdwPhoneID)
  1002. {
  1003. HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
  1004. CPhoneBook far *pcPhoneBook;
  1005. if (!g_hInstDll)
  1006. g_hInstDll = GetModuleHandle(NULL);
  1007. // validate parameters
  1008. Assert(pszISPCode && *pszISPCode && pdwPhoneID);
  1009. *pdwPhoneID = NULL;
  1010. // allocate phone book
  1011. pcPhoneBook = new CPhoneBook;
  1012. // initialize phone book
  1013. if (pcPhoneBook)
  1014. hr = pcPhoneBook->Init(pszISPCode);
  1015. // in case of failure
  1016. if (hr && pcPhoneBook)
  1017. {
  1018. delete pcPhoneBook;
  1019. } else {
  1020. *pdwPhoneID = (DWORD_PTR)pcPhoneBook;
  1021. }
  1022. #if defined(WIN16)
  1023. if (!hr)
  1024. BMP_RegisterClass(g_hInstDll);
  1025. #endif
  1026. return hr;
  1027. }
  1028. // ############################################################################
  1029. DllExportH PhoneBookUnload(DWORD_PTR dwPhoneID)
  1030. {
  1031. Assert(dwPhoneID);
  1032. if (dwPhoneID)
  1033. {
  1034. #if defined(WIN16)
  1035. BMP_DestroyClass(g_hInstDll);
  1036. #endif
  1037. // Release contents
  1038. delete (CPhoneBook far*)dwPhoneID;
  1039. }
  1040. return ERROR_SUCCESS;
  1041. }
  1042. // ############################################################################
  1043. DllExportH PhoneBookMergeChanges(DWORD_PTR dwPhoneID, LPCSTR pszChangeFile)
  1044. {
  1045. return ((CPhoneBook far*)dwPhoneID)->Merge(pszChangeFile);
  1046. }
  1047. // ############################################################################
  1048. DllExportH PhoneBookSuggestNumbers(DWORD_PTR dwPhoneID, PSUGGESTINFO lpSuggestInfo)
  1049. {
  1050. HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
  1051. // get suggested numbers
  1052. lpSuggestInfo->rgpAccessEntry = (PACCESSENTRY *)GlobalAlloc(GPTR,sizeof(PACCESSENTRY) * lpSuggestInfo->wNumber);
  1053. if (lpSuggestInfo->rgpAccessEntry)
  1054. {
  1055. hr = ((CPhoneBook far *)dwPhoneID)->Suggest(lpSuggestInfo);
  1056. }
  1057. return hr;
  1058. }
  1059. // ############################################################################
  1060. DllExportH PhoneBookGetCanonical (DWORD_PTR dwPhoneID, PACCESSENTRY pAE, LPSTR psOut)
  1061. {
  1062. return ((CPhoneBook far*)dwPhoneID)->GetCanonical(pAE,psOut);
  1063. }
  1064. // ############################################################################
  1065. DllExportH PhoneBookDisplaySignUpNumbers (DWORD_PTR dwPhoneID,
  1066. LPSTR far *ppszPhoneNumbers,
  1067. LPSTR far *ppszDunFiles,
  1068. WORD far *pwPhoneNumbers,
  1069. DWORD far *pdwCountry,
  1070. WORD far *pwRegion,
  1071. BYTE fType,
  1072. BYTE bMask,
  1073. HWND hwndParent,
  1074. DWORD dwFlags)
  1075. {
  1076. INT_PTR hr;
  1077. AssertSz(ppszPhoneNumbers && pwPhoneNumbers && pdwCountry &&pwRegion,"invalid parameters");
  1078. //CAccessNumDlg *pcDlg;
  1079. CSelectNumDlg far *pcDlg;
  1080. pcDlg = new CSelectNumDlg;
  1081. if (!pcDlg)
  1082. {
  1083. hr = GetLastError();
  1084. goto DisplayExit;
  1085. }
  1086. // Initialize information for dialog
  1087. //
  1088. pcDlg->m_dwPhoneBook = dwPhoneID;
  1089. pcDlg->m_dwCountryID = *pdwCountry;
  1090. pcDlg->m_wRegion = *pwRegion;
  1091. pcDlg->m_fType = fType;
  1092. pcDlg->m_bMask = bMask;
  1093. pcDlg->m_dwFlags = dwFlags;
  1094. // invoke the dialog
  1095. //
  1096. // BUG: NOT THREAD SAFE!!
  1097. g_hWndMain = hwndParent;
  1098. hr = DialogBoxParam(g_hInstDll,MAKEINTRESOURCE(IDD_SELECTNUMBER),
  1099. g_hWndMain,PhbkGenericDlgProc,(LPARAM)pcDlg);
  1100. g_hWndMain = NULL;
  1101. if (hr == IDC_CMDNEXT)
  1102. {
  1103. *pwRegion = pcDlg->m_wRegion;
  1104. *pdwCountry = pcDlg->m_dwCountryID;
  1105. Assert (ppszPhoneNumbers[0] && ppszDunFiles[0]);
  1106. lstrcpy(ppszPhoneNumbers[0],&pcDlg->m_szPhoneNumber[0]);
  1107. lstrcpy(ppszDunFiles[0],&pcDlg->m_szDunFile[0]);
  1108. hr = ERROR_SUCCESS;
  1109. }
  1110. else if (hr == IDC_CMDBACK)
  1111. hr = ERROR_USERBACK;
  1112. else
  1113. hr = ERROR_USERCANCEL;
  1114. // hr == -1;
  1115. DisplayExit:
  1116. if (pcDlg) delete pcDlg;
  1117. return (HRESULT) hr;
  1118. }