Leaked source code of windows server 2003
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.

1316 lines
36 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. HGLOBAL pTemp;
  278. LPLINECOUNTRYENTRY pLCETemp;
  279. DWORD idx;
  280. LPSTR pszTemp;
  281. CCSVFile far *pcCSVFile=NULL;
  282. LPSTATE ps,psLast; //faster to use pointers.
  283. int iTestSK;
  284. // Get TAPI country list
  285. m_pLineCountryList = (LPLINECOUNTRYLIST)GlobalAlloc(GPTR,sizeof(LINECOUNTRYLIST));
  286. if (!m_pLineCountryList)
  287. goto InitExit;
  288. m_pLineCountryList->dwTotalSize = sizeof(LINECOUNTRYLIST);
  289. #if defined(WIN16)
  290. idx = (DWORD) IETapiGetCountry(0, m_pLineCountryList);
  291. #else
  292. idx = lineGetCountry(0,0x10003,m_pLineCountryList);
  293. #endif
  294. if (idx && idx != LINEERR_STRUCTURETOOSMALL)
  295. goto InitExit;
  296. Assert(m_pLineCountryList->dwNeededSize);
  297. pLineCountryTemp = (LPLINECOUNTRYLIST)GlobalAlloc(GPTR,
  298. (size_t)m_pLineCountryList->dwNeededSize);
  299. if (!pLineCountryTemp)
  300. goto InitExit;
  301. pLineCountryTemp->dwTotalSize = m_pLineCountryList->dwNeededSize;
  302. GlobalFree(m_pLineCountryList);
  303. m_pLineCountryList = pLineCountryTemp;
  304. pLineCountryTemp = NULL;
  305. #if defined(WIN16)
  306. if (IETapiGetCountry(0, m_pLineCountryList))
  307. #else
  308. if (lineGetCountry(0,0x10003,m_pLineCountryList))
  309. #endif
  310. goto InitExit;
  311. //#endif // WIN16
  312. // Load Look Up arrays
  313. #ifdef DEBUG
  314. m_rgIDLookUp = (LPIDLOOKUPELEMENT)GlobalAlloc(GPTR,
  315. (int)(sizeof(IDLOOKUPELEMENT)*m_pLineCountryList->dwNumCountries+5));
  316. #else
  317. m_rgIDLookUp = (LPIDLOOKUPELEMENT)GlobalAlloc(GPTR,
  318. (int)(sizeof(IDLOOKUPELEMENT)*m_pLineCountryList->dwNumCountries));
  319. #endif
  320. if (!m_rgIDLookUp) goto InitExit;
  321. pLCETemp = (LPLINECOUNTRYENTRY)((DWORD_PTR)m_pLineCountryList +
  322. m_pLineCountryList->dwCountryListOffset);
  323. for (idx=0;idx<m_pLineCountryList->dwNumCountries;idx++)
  324. {
  325. m_rgIDLookUp[idx].dwID = pLCETemp[idx].dwCountryID;
  326. m_rgIDLookUp[idx].pLCE = &pLCETemp[idx];
  327. }
  328. qsort(m_rgIDLookUp,(int)m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),
  329. CompareIDLookUpElements);
  330. m_rgNameLookUp = (LPCNTRYNAMELOOKUPELEMENT)GlobalAlloc(GPTR,
  331. (int)(sizeof(CNTRYNAMELOOKUPELEMENT) * m_pLineCountryList->dwNumCountries));
  332. if (!m_rgNameLookUp) goto InitExit;
  333. for (idx=0;idx<m_pLineCountryList->dwNumCountries;idx++)
  334. {
  335. m_rgNameLookUp[idx].psCountryName = (LPSTR)((LPBYTE)m_pLineCountryList + (DWORD)pLCETemp[idx].dwCountryNameOffset);
  336. m_rgNameLookUp[idx].dwNameSize = pLCETemp[idx].dwCountryNameSize;
  337. m_rgNameLookUp[idx].pLCE = &pLCETemp[idx];
  338. }
  339. qsort(m_rgNameLookUp,(int)m_pLineCountryList->dwNumCountries,sizeof(CNTRYNAMELOOKUPELEMENT),
  340. CompareCntryNameLookUpElements);
  341. // Load States
  342. if (!SearchPath(NULL,STATE_FILENAME,NULL,TEMP_BUFFER_LENGTH,szTempBuffer,&pszTemp))
  343. {
  344. if(m_szICWDirectoryPath){
  345. // Try with c:\\ProgramFile\\ICW-INTERNET\\......
  346. if(! SearchPath(m_szICWDirectoryPath,
  347. STATE_FILENAME,NULL,TEMP_BUFFER_LENGTH,szTempBuffer,&pszTemp)) {
  348. AssertSz(0,"STATE.ICW not found");
  349. hr = ERROR_FILE_NOT_FOUND;
  350. goto InitExit;
  351. }else {
  352. ; // OK Th e file is found
  353. iTestSK=0;
  354. }
  355. }
  356. else {
  357. AssertSz(0,"STATE.ICW not found");
  358. hr = ERROR_FILE_NOT_FOUND;
  359. goto InitExit;
  360. }
  361. }
  362. pcCSVFile = new CCSVFile;
  363. if (!pcCSVFile) goto InitExit;
  364. if (!pcCSVFile->Open(szTempBuffer))
  365. {
  366. AssertSz(0,"Can not open STATE.ICW");
  367. delete pcCSVFile;
  368. pcCSVFile = NULL;
  369. goto InitExit;
  370. }
  371. // first token in state file is the number of states
  372. if (!pcCSVFile->ReadToken(szTempBuffer,TEMP_BUFFER_LENGTH))
  373. goto InitExit;
  374. if (!FSz2Dw(szTempBuffer,&m_cStates))
  375. {
  376. AssertSz(0,"STATE.ICW count is invalid");
  377. goto InitExit;
  378. }
  379. m_rgState = (LPSTATE)GlobalAlloc(GPTR,(int)(sizeof(STATE)*m_cStates));
  380. if (!m_rgState)
  381. goto InitExit;
  382. for (ps = m_rgState, psLast = &m_rgState[m_cStates - 1]; ps <= psLast;++ps)
  383. {
  384. pcCSVFile->ReadToken(ps->szStateName,cbStateName);
  385. }
  386. pcCSVFile->Close();
  387. // Locate ISP's INF file
  388. if (!SearchPath(NULL,(LPCTSTR) pszISPCode,INF_SUFFIX,MAX_PATH,
  389. m_szINFFile,&pszTemp))
  390. {
  391. wsprintf(szTempBuffer,"Can not find:%s%s (%d)",pszISPCode,INF_SUFFIX,GetLastError());
  392. if(m_szICWDirectoryPath) {
  393. if(!SearchPath(m_szICWDirectoryPath,(LPCTSTR) pszISPCode,INF_SUFFIX,MAX_PATH,
  394. m_szINFFile,&pszTemp)) {
  395. AssertSz(0,szTempBuffer);
  396. hr = ERROR_FILE_NOT_FOUND;
  397. goto InitExit;
  398. //
  399. }else {
  400. iTestSK++;
  401. }
  402. }else {
  403. AssertSz(0,szTempBuffer);
  404. hr = ERROR_FILE_NOT_FOUND;
  405. goto InitExit;
  406. }
  407. }
  408. //Load Phone Book
  409. if (!GetPrivateProfileString(INF_APP_NAME,INF_PHONE_BOOK,INF_DEFAULT,
  410. szTempBuffer,TEMP_BUFFER_LENGTH,m_szINFFile))
  411. {
  412. AssertSz(0,"PhoneBookFile not specified in INF file");
  413. hr = ERROR_FILE_NOT_FOUND;
  414. goto InitExit;
  415. }
  416. #ifdef DEBUG
  417. if (!lstrcmp(szTempBuffer,INF_DEFAULT))
  418. {
  419. wsprintf(szTempBuffer, "%s value not found in ISP file", INF_PHONE_BOOK);
  420. AssertSz(0,szTempBuffer);
  421. }
  422. #endif
  423. if (!SearchPath(NULL,szTempBuffer,NULL,MAX_PATH,m_szPhoneBook,&pszTemp))
  424. {
  425. if(m_szICWDirectoryPath){
  426. if (!SearchPath(m_szICWDirectoryPath,szTempBuffer,NULL,MAX_PATH,m_szPhoneBook,&pszTemp)){
  427. AssertSz(0,"ISP phone book not found");
  428. hr = ERROR_FILE_NOT_FOUND;
  429. goto InitExit;
  430. }else {
  431. ;; // OK file Found
  432. iTestSK++;
  433. }
  434. }else {
  435. AssertSz(0,"ISP phone book not found");
  436. hr = ERROR_FILE_NOT_FOUND;
  437. goto InitExit;
  438. }
  439. }
  440. if (!pcCSVFile->Open(m_szPhoneBook))
  441. {
  442. AssertSz(0,"Can not open phone book");
  443. hr = GetLastError();
  444. goto InitExit;
  445. }
  446. dwSizeAllocated = 0;
  447. do {
  448. Assert (dwSizeAllocated >= m_cPhoneBookEntries);
  449. // check that sufficient memory is allocated
  450. if (m_rgPhoneBookEntry)
  451. {
  452. if (dwSizeAllocated == m_cPhoneBookEntries)
  453. {
  454. //
  455. // we need more memory
  456. //
  457. // AssertSz(0,"Out of memory originally allocated for phone book.\r\n");
  458. // goto InitExit;
  459. pAETemp = m_rgPhoneBookEntry;
  460. #ifdef WIN16
  461. dwSizeAllocated += PHONE_ENTRY_ALLOC_SIZE;
  462. pTemp = GlobalReAlloc(m_rgPhoneBookEntry,
  463. (int)(dwSizeAllocated * sizeof(ACCESSENTRY)),GHND);
  464. if (NULL == pTemp)
  465. goto InitExit;
  466. else
  467. m_rgPhoneBookEntry = (PACCESSENTRY)pTemp;
  468. #else
  469. // UNLOCK
  470. Assert(m_hPhoneBookEntry);
  471. if (FALSE == GlobalUnlock(m_hPhoneBookEntry))
  472. {
  473. if (NO_ERROR != GetLastError())
  474. goto InitExit;
  475. }
  476. // REALLOC
  477. dwSizeAllocated += PHONE_ENTRY_ALLOC_SIZE;
  478. pTemp = GlobalReAlloc(m_hPhoneBookEntry,
  479. (int)(dwSizeAllocated * sizeof(ACCESSENTRY)),GHND);
  480. if (NULL == pTemp)
  481. goto InitExit;
  482. else
  483. m_hPhoneBookEntry = pTemp;
  484. // LOCK
  485. m_rgPhoneBookEntry = (PACCESSENTRY)GlobalLock(m_hPhoneBookEntry);
  486. if (NULL == m_rgPhoneBookEntry)
  487. goto InitExit;
  488. #endif
  489. FixUpFromRealloc(pAETemp, m_rgPhoneBookEntry);
  490. Dprintf("Grow phone book to %d entries\n",dwSizeAllocated);
  491. pCurAccessEntry = (PACCESSENTRY)((LONG_PTR)pCurAccessEntry -
  492. ((LONG_PTR)pAETemp - (LONG_PTR)(m_rgPhoneBookEntry)));
  493. }
  494. }
  495. else
  496. {
  497. //
  498. // Initialization for the first time through
  499. //
  500. // ALLOC
  501. #ifdef WIN16
  502. m_rgPhoneBookEntry = (PACCESSENTRY)GlobalAlloc(GHND,sizeof(ACCESSENTRY) * PHONE_ENTRY_ALLOC_SIZE);
  503. if(NULL == m_rgPhoneBookEntry)
  504. goto InitExit;
  505. #else
  506. m_hPhoneBookEntry = GlobalAlloc(GHND,sizeof(ACCESSENTRY) * PHONE_ENTRY_ALLOC_SIZE);
  507. if(NULL == m_hPhoneBookEntry)
  508. goto InitExit;
  509. // LOCK
  510. m_rgPhoneBookEntry = (PACCESSENTRY)GlobalLock(m_hPhoneBookEntry);
  511. if(NULL == m_rgPhoneBookEntry)
  512. goto InitExit;
  513. #endif
  514. dwSizeAllocated = PHONE_ENTRY_ALLOC_SIZE;
  515. pCurAccessEntry = m_rgPhoneBookEntry;
  516. }
  517. // Read a line from the phonebook
  518. hr = ReadOneLine(pCurAccessEntry,pcCSVFile);
  519. if (hr == ERROR_NO_MORE_ITEMS)
  520. {
  521. break;
  522. }
  523. else if (hr != ERROR_SUCCESS)
  524. {
  525. goto InitExit;
  526. }
  527. hr = ERROR_NOT_ENOUGH_MEMORY;
  528. // Check to see if this is the first phone number for a given country
  529. if (pCurAccessEntry->dwCountryID != dwLastCountry)
  530. {
  531. LPIDLOOKUPELEMENT lpIDLookupElement;
  532. // NOTE: Not sure about the first parameter here.
  533. lpIDLookupElement = (LPIDLOOKUPELEMENT)bsearch(&pCurAccessEntry->dwCountryID,
  534. m_rgIDLookUp,(int)m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),
  535. CompareIDLookUpElements);
  536. if (!lpIDLookupElement)
  537. {
  538. // bad country ID, but we can't assert here
  539. Dprintf("Bad country ID in phone book %d\n",pCurAccessEntry->dwCountryID);
  540. continue;
  541. }
  542. else
  543. {
  544. // for a given country ID this is the first phone number
  545. lpIDLookupElement->pFirstAE = pCurAccessEntry;
  546. dwLastCountry = pCurAccessEntry->dwCountryID;
  547. }
  548. }
  549. // Check to see if this is the first phone number for a given state
  550. if (pCurAccessEntry->wStateID && (pCurAccessEntry->wStateID != dwLastState))
  551. {
  552. idx = pCurAccessEntry->wStateID - 1;
  553. m_rgState[idx].dwCountryID = pCurAccessEntry->dwCountryID;
  554. m_rgState[idx].paeFirst = pCurAccessEntry;
  555. dwLastState = pCurAccessEntry->wStateID;
  556. }
  557. pCurAccessEntry++;
  558. m_cPhoneBookEntries++;
  559. } while (TRUE);
  560. // Trim the phone book for unused memory
  561. Assert(m_rgPhoneBookEntry && m_cPhoneBookEntries);
  562. pAETemp = m_rgPhoneBookEntry;
  563. #ifdef WIN16
  564. pTemp = GlobalReAlloc(m_rgPhoneBookEntry,(int)(m_cPhoneBookEntries * sizeof(ACCESSENTRY)),GHND);
  565. if (pTemp == NULL)
  566. goto InitExit;
  567. else
  568. m_rgPhoneBookEntry = (PACCESSENTRY)pTemp;
  569. #else
  570. // UNLOCK
  571. Assert(m_hPhoneBookEntry);
  572. if (FALSE != GlobalUnlock(m_hPhoneBookEntry))
  573. {
  574. if (NO_ERROR != GetLastError())
  575. goto InitExit;
  576. }
  577. // REALLOC
  578. pTemp = GlobalReAlloc(m_hPhoneBookEntry,(int)(m_cPhoneBookEntries * sizeof(ACCESSENTRY)),GHND);
  579. if (NULL == pTemp)
  580. goto InitExit;
  581. else
  582. m_hPhoneBookEntry = pTemp;
  583. // LOCK
  584. m_rgPhoneBookEntry = (PACCESSENTRY)GlobalLock(m_hPhoneBookEntry);
  585. if (NULL == m_rgPhoneBookEntry)
  586. goto InitExit;
  587. #endif
  588. FixUpFromRealloc(pAETemp, m_rgPhoneBookEntry);
  589. hr = ERROR_SUCCESS;
  590. InitExit:
  591. // If something failed release everything
  592. if (hr != ERROR_SUCCESS)
  593. {
  594. #ifdef WIN16
  595. GlobalFree(m_rgPhoneBookEntry);
  596. #else
  597. GlobalUnlock(m_hPhoneBookEntry);
  598. GlobalFree(m_hPhoneBookEntry);
  599. #endif
  600. GlobalFree(m_pLineCountryList);
  601. GlobalFree(m_rgIDLookUp);
  602. GlobalFree(m_rgNameLookUp);
  603. GlobalFree(m_rgState);
  604. m_cPhoneBookEntries = 0 ;
  605. m_cStates = 0;
  606. m_pLineCountryList = NULL;
  607. m_rgPhoneBookEntry = NULL;
  608. m_hPhoneBookEntry = NULL;
  609. m_rgIDLookUp=NULL;
  610. m_rgNameLookUp=NULL;
  611. m_rgState=NULL;
  612. }
  613. if (pcCSVFile)
  614. {
  615. pcCSVFile->Close();
  616. delete pcCSVFile;
  617. }
  618. return hr;
  619. }
  620. // ############################################################################
  621. HRESULT CPhoneBook::Merge(LPCSTR pszChangeFile)
  622. {
  623. CCSVFile far *pcCSVFile;
  624. ACCESSENTRY aeChange;
  625. LPIDXLOOKUPELEMENT rgIdxLookUp;
  626. LPIDXLOOKUPELEMENT pCurIdxLookUp;
  627. DWORD dwAllocated;
  628. DWORD dwUsed;
  629. DWORD dwOriginalSize;
  630. HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
  631. DWORD dwIdx;
  632. #if !defined(WIN16)
  633. HANDLE hTemp;
  634. HANDLE hIdxLookUp;
  635. #else
  636. // Normandy 11746
  637. LPVOID rgTemp; // 16-bit only
  638. #endif
  639. DWORD cch, cchWritten;
  640. HANDLE hFile;
  641. // Pad the phonebook for new entries.
  642. dwAllocated = m_cPhoneBookEntries + CHANGE_BUFFER_SIZE;
  643. #ifdef WIN16
  644. Assert(m_rgPhoneBookEntry);
  645. rgTemp = GlobalReAlloc(m_rgPhoneBookEntry, (int)(sizeof(ACCESSENTRY) * dwAllocated),GHND);
  646. Assert(rgTemp);
  647. if (!rgTemp) goto MergeExit;
  648. m_rgPhoneBookEntry = (PACCESSENTRY)rgTemp;
  649. #else
  650. Assert(m_hPhoneBookEntry);
  651. GlobalUnlock(m_hPhoneBookEntry);
  652. hTemp = (HANDLE)GlobalReAlloc(m_hPhoneBookEntry, sizeof(ACCESSENTRY) * dwAllocated,GHND);
  653. Assert(hTemp);
  654. if (!hTemp)
  655. goto MergeExit;
  656. m_rgPhoneBookEntry = (PACCESSENTRY)GlobalLock(m_hPhoneBookEntry);
  657. if (!m_rgPhoneBookEntry)
  658. goto MergeExit;
  659. #endif
  660. // Create index to loaded phone book, sorted by index
  661. #ifdef WIN16
  662. rgIdxLookUp = (LPIDXLOOKUPELEMENT)GlobalAlloc(GHND,(int)(sizeof(IDXLOOKUPELEMENT) * dwAllocated));
  663. #else
  664. hIdxLookUp = (HANDLE)GlobalAlloc(GHND,sizeof(IDXLOOKUPELEMENT) * dwAllocated);
  665. rgIdxLookUp = (LPIDXLOOKUPELEMENT)GlobalLock(hIdxLookUp);
  666. #endif
  667. Assert(rgIdxLookUp);
  668. if (!rgIdxLookUp)
  669. goto MergeExit;
  670. for (dwIdx = 0; dwIdx < m_cPhoneBookEntries; dwIdx++)
  671. {
  672. rgIdxLookUp[dwIdx].dwIndex = rgIdxLookUp[dwIdx].pAE->dwIndex;
  673. rgIdxLookUp[dwIdx].pAE = &m_rgPhoneBookEntry[dwIdx];
  674. }
  675. dwUsed = m_cPhoneBookEntries;
  676. dwOriginalSize = m_cPhoneBookEntries;
  677. qsort(rgIdxLookUp,(int)dwOriginalSize,sizeof(IDXLOOKUPELEMENT),CompareIdxLookUpElements);
  678. // Load changes to phone book
  679. pcCSVFile = new CCSVFile;
  680. Assert(pcCSVFile);
  681. if (!pcCSVFile)
  682. goto MergeExit;
  683. if (!pcCSVFile->Open(pszChangeFile))
  684. goto MergeExit;
  685. do {
  686. // Read a change record
  687. ZeroMemory(&aeChange,sizeof(ACCESSENTRY));
  688. hr = ReadOneLine(&aeChange, pcCSVFile);
  689. if (hr == ERROR_NO_MORE_ITEMS)
  690. {
  691. break; // no more enteries
  692. }
  693. else if (hr != ERROR_SUCCESS)
  694. {
  695. goto MergeExit;
  696. }
  697. hr = ERROR_NOT_ENOUGH_MEMORY;
  698. // Determine if this is a delete or add record
  699. if (aeChange.szAccessNumber[0] == '0' && aeChange.szAccessNumber[1] == '\0')
  700. {
  701. // This is a delete record, find matching record
  702. // NOTE: we only search the numbers that existed before the change file,
  703. // because they are the only ones that are sorted.
  704. pCurIdxLookUp = (LPIDXLOOKUPELEMENT)bsearch(&aeChange,rgIdxLookUp,(int)dwOriginalSize,
  705. sizeof(IDXLOOKUPELEMENT),CompareIdxLookUpElements);
  706. AssertSz(pCurIdxLookUp,"Attempting to delete a record that does not exist. The change file and phone book versions do not match.");
  707. if (pCurIdxLookUp)
  708. pCurIdxLookUp->pAE = NULL; //Create a dead entry in the look up table
  709. m_cPhoneBookEntries--;
  710. }
  711. else
  712. {
  713. // This is an add entry
  714. m_cPhoneBookEntries++;
  715. dwUsed++;
  716. // Make sure we have enough room
  717. if (m_cPhoneBookEntries > dwAllocated)
  718. {
  719. // Grow phone book
  720. dwAllocated += CHANGE_BUFFER_SIZE;
  721. #ifdef WIN16
  722. Assert(m_rgPhoneBookEntry);
  723. rgTemp = GlobalReAlloc(m_rgPhoneBookEntry,(int)(sizeof(ACCESSENTRY)*dwAllocated),GHND);
  724. Assert(rgTemp);
  725. if (!rgTemp)
  726. goto MergeExit;
  727. m_rgPhoneBookEntry = (PACCESSENTRY)rgTemp;
  728. // Grow look up index
  729. Assert(rgIdxLookUp);
  730. rgTemp = GlobalReAlloc(rgIdxLookUp,(int)(sizeof(IDXLOOKUPELEMENT)*dwAllocated),GHND);
  731. Assert(rgTemp);
  732. if (!rgTemp)
  733. goto MergeExit;
  734. rgIdxLookUp = (LPIDXLOOKUPELEMENT)rgTemp;
  735. #else
  736. Assert(m_hPhoneBookEntry);
  737. GlobalUnlock(m_hPhoneBookEntry);
  738. hTemp = (HANDLE)GlobalReAlloc(m_hPhoneBookEntry,sizeof(ACCESSENTRY)*dwAllocated,GHND);
  739. Assert(hTemp);
  740. if (!hTemp)
  741. goto MergeExit;
  742. m_hPhoneBookEntry = hTemp;
  743. m_rgPhoneBookEntry = (PACCESSENTRY)GlobalLock(m_hPhoneBookEntry);
  744. Assert(m_rgPhoneBookEntry);
  745. if (!m_rgPhoneBookEntry)
  746. goto MergeExit;
  747. // Grow look up index
  748. Assert(hIdxLookUp);
  749. GlobalUnlock(hIdxLookUp);
  750. hTemp = (HANDLE)GlobalReAlloc(hIdxLookUp,sizeof(IDXLOOKUPELEMENT)*dwAllocated,GHND);
  751. Assert(hTemp);
  752. if (!hTemp)
  753. goto MergeExit;
  754. hIdxLookUp = hTemp;
  755. rgIdxLookUp = (LPIDXLOOKUPELEMENT)GlobalLock(hIdxLookUp);
  756. Assert(rgIdxLookUp);
  757. if (!rgIdxLookUp)
  758. goto MergeExit;
  759. #endif
  760. }
  761. //Add entry to the end of the phonebook and to end of look up index
  762. CopyMemory(&m_rgPhoneBookEntry[m_cPhoneBookEntries],&aeChange,sizeof(ACCESSENTRY));
  763. rgIdxLookUp[m_cPhoneBookEntries].dwIndex = m_rgPhoneBookEntry[m_cPhoneBookEntries].dwIndex;
  764. rgIdxLookUp[m_cPhoneBookEntries].pAE = &m_rgPhoneBookEntry[m_cPhoneBookEntries];
  765. // NOTE: because the entry is added to the end of the list, we can't add
  766. // and delete entries in the same change file.
  767. }
  768. } while (TRUE);
  769. // resort the IDXLookUp index to reflect the correct order of enteries
  770. // for the phonebook file, including all of the entries to be deleted.
  771. qsort(rgIdxLookUp,(int)dwUsed,sizeof(IDXLOOKUPELEMENT),CompareIdxLookUpElementsFileOrder);
  772. // Build a new phonebook file
  773. #ifdef WIN16
  774. GetTempFileName(0, TEMP_PHONE_BOOK_PREFIX, 0, szTempFileName);
  775. #else
  776. if (!GetTempPath(TEMP_BUFFER_LENGTH,szTempBuffer))
  777. goto MergeExit;
  778. if (!GetTempFileName(szTempBuffer,TEMP_PHONE_BOOK_PREFIX,0,szTempFileName))
  779. goto MergeExit;
  780. #endif
  781. hFile = CreateFile(szTempFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
  782. FILE_FLAG_WRITE_THROUGH,0);
  783. if (hFile == INVALID_HANDLE_VALUE)
  784. goto MergeExit;
  785. for (dwIdx = 0; dwIdx < m_cPhoneBookEntries; dwIdx++)
  786. {
  787. cch = wsprintf(szTempBuffer, "%lu,%lu,%lu,%s,%s,%s,%lu,%lu,%lu,%lu,%s\r\n",
  788. rgIdxLookUp[dwIdx].pAE->dwIndex,
  789. rgIdxLookUp[dwIdx].pAE->dwCountryID,
  790. DWORD(rgIdxLookUp[dwIdx].pAE->wStateID),
  791. rgIdxLookUp[dwIdx].pAE->szCity,
  792. rgIdxLookUp[dwIdx].pAE->szAreaCode,
  793. rgIdxLookUp[dwIdx].pAE->szAccessNumber,
  794. rgIdxLookUp[dwIdx].pAE->dwConnectSpeedMin,
  795. rgIdxLookUp[dwIdx].pAE->dwConnectSpeedMax,
  796. DWORD(rgIdxLookUp[dwIdx].pAE->bFlipFactor),
  797. DWORD(rgIdxLookUp[dwIdx].pAE->fType),
  798. rgIdxLookUp[dwIdx].pAE->szDataCenter);
  799. if (!WriteFile(hFile,szTempBuffer,cch,&cchWritten,NULL))
  800. {
  801. // something went wrong, get rid of the temporary file
  802. CloseHandle(hFile);
  803. DeleteFile(szTempFileName);
  804. hr = GetLastError();
  805. goto MergeExit;
  806. }
  807. Assert(cch == cchWritten);
  808. }
  809. CloseHandle(hFile);
  810. hFile = NULL;
  811. // Move new phone book over old
  812. if (!MoveFileEx(szTempFileName,m_szPhoneBook,MOVEFILE_REPLACE_EXISTING))
  813. {
  814. hr = GetLastError();
  815. goto MergeExit;
  816. }
  817. // discard the phonebook in memory
  818. #ifndef WIN16
  819. Assert(m_hPhoneBookEntry);
  820. GlobalUnlock(m_hPhoneBookEntry);
  821. #endif
  822. m_rgPhoneBookEntry = NULL;
  823. m_cPhoneBookEntries = 0;
  824. GlobalFree(m_pLineCountryList);
  825. GlobalFree(m_rgIDLookUp);
  826. GlobalFree(m_rgNameLookUp);
  827. GlobalFree(m_rgState);
  828. m_cStates = 0;
  829. lstrcpy(szTempBuffer,m_szINFCode);
  830. m_szINFFile[0] = '\0';
  831. m_szPhoneBook[0] = '\0';
  832. m_szINFCode[0] = '\0';
  833. // Reload it (and rebuild look up arrays)
  834. hr = Init(szTempBuffer);
  835. MergeExit:
  836. if (hr != ERROR_SUCCESS)
  837. {
  838. GlobalFree(rgIdxLookUp);
  839. if (pcCSVFile) delete pcCSVFile;
  840. CloseHandle(hFile);
  841. }
  842. return hr;
  843. }
  844. // ############################################################################
  845. HRESULT CPhoneBook::ReadOneLine(PACCESSENTRY lpAccessEntry, CCSVFile far *pcCSVFile)
  846. {
  847. HRESULT hr = ERROR_SUCCESS;
  848. #if !defined(WIN16)
  849. ReadOneLineStart:
  850. #endif //WIN16
  851. if (!ReadPhoneBookDW(&lpAccessEntry->dwIndex,pcCSVFile))
  852. {
  853. hr = ERROR_NO_MORE_ITEMS; // no more enteries
  854. goto ReadExit;
  855. }
  856. ReadVerifyPhoneBookDW(lpAccessEntry->dwCountryID);
  857. ReadVerifyPhoneBookW(lpAccessEntry->wStateID);
  858. ReadVerifyPhoneBookSZ(lpAccessEntry->szCity,cbCity);
  859. ReadVerifyPhoneBookSZ(lpAccessEntry->szAreaCode,cbAreaCode);
  860. // NOTE: 0 is a valid area code and ,, is a valid entry for an area code
  861. if (!FSz2Dw(lpAccessEntry->szAreaCode,&lpAccessEntry->dwAreaCode))
  862. lpAccessEntry->dwAreaCode = NO_AREA_CODE;
  863. ReadVerifyPhoneBookSZ(lpAccessEntry->szAccessNumber,cbAccessNumber);
  864. ReadVerifyPhoneBookDW(lpAccessEntry->dwConnectSpeedMin);
  865. ReadVerifyPhoneBookDW(lpAccessEntry->dwConnectSpeedMax);
  866. ReadVerifyPhoneBookB(lpAccessEntry->bFlipFactor);
  867. ReadVerifyPhoneBookDW(lpAccessEntry->fType);
  868. ReadVerifyPhoneBookSZ(lpAccessEntry->szDataCenter,cbDataCenter);
  869. #if !defined(WIN16)
  870. //
  871. // If scripting is not available and the phonebook entry has a dun file other than
  872. // icwip.dun, then ignore the entry and read the one after that.
  873. //
  874. if (!m_bScriptingAvailable)
  875. {
  876. if (0 != lstrcmpi(lpAccessEntry->szDataCenter,"icwip.dun"))
  877. {
  878. ZeroMemory(lpAccessEntry,sizeof(ACCESSENTRY));
  879. goto ReadOneLineStart;
  880. }
  881. }
  882. #endif //WIN16
  883. ReadExit:
  884. return hr;
  885. ReadError:
  886. hr = ERROR_INVALID_DATA;
  887. goto ReadExit;
  888. }
  889. // ############################################################################
  890. HRESULT CPhoneBook::Suggest(PSUGGESTINFO pSuggest)
  891. {
  892. WORD wNumFound = 0;
  893. HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
  894. // Validate parameters
  895. Assert(pSuggest);
  896. Assert(pSuggest->wNumber);
  897. if (wNumFound == pSuggest->wNumber)
  898. goto SuggestExit;
  899. LPIDLOOKUPELEMENT pCurLookUp;
  900. PACCESSENTRY lpAccessEntry;
  901. //REVIEW: double check this
  902. pCurLookUp = (LPIDLOOKUPELEMENT)bsearch(&pSuggest->dwCountryID,m_rgIDLookUp,
  903. (int)m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),
  904. CompareIDLookUpElements);
  905. // Check for invalid country
  906. if (!pCurLookUp)
  907. goto SuggestExit;
  908. // Check if there are any phone numbers for this country
  909. if (!pCurLookUp->pFirstAE) goto SuggestExit;
  910. lpAccessEntry = pCurLookUp->pFirstAE;
  911. do {
  912. // check for the right area code
  913. if (lpAccessEntry->dwAreaCode == pSuggest->wAreaCode)
  914. {
  915. // check for the right type of number
  916. if ((lpAccessEntry->fType & pSuggest->bMask) == pSuggest->fType)
  917. {
  918. pSuggest->rgpAccessEntry[wNumFound] = lpAccessEntry;
  919. wNumFound++;
  920. }
  921. }
  922. lpAccessEntry++;
  923. } while ((lpAccessEntry <= &m_rgPhoneBookEntry[m_cPhoneBookEntries-1]) &&
  924. (wNumFound < pSuggest->wNumber) &&
  925. (lpAccessEntry->dwCountryID == pSuggest->dwCountryID));
  926. // if we couldn't find enough numnbers, try something else
  927. // 10/15/96 jmazner ported fixes below from core\client\phbk
  928. // Do this only if area code is not 0 - Bug #9349 (VetriV)
  929. // if ((pSuggest->wAreaCode != 0) && (wNumFound < pSuggest->wNumber))
  930. // No, there are some places (Finland? ChrisK knows) where 0 is a legit area code -- jmazner
  931. if (wNumFound < pSuggest->wNumber)
  932. {
  933. lpAccessEntry = pCurLookUp->pFirstAE;
  934. // Note: we are now only looking for Nationwide phone numbers (state = 0)
  935. // 8/13/96 jmazner MOS Normandy #4597
  936. // We want nationwide toll-free numbers to display last, so for this pass,
  937. // only consider numbers that are _not_ toll free (fType bit #1 = 0)
  938. // Tweak pSuggest->bMask to let through the toll/charge bit
  939. pSuggest->bMask |= MASK_TOLLFREE_BIT;
  940. // Tweak pSuggest->ftype to be charge
  941. pSuggest->fType &= TYPE_SET_TOLL;
  942. do {
  943. // 8/13/96 jmazner MOS Normandy #4598
  944. // If this entry's area code matches pSuggest->wAreaCode, then we already
  945. // have included it in the previous pass, so don't duplicate it again here.
  946. if ((lpAccessEntry->fType & pSuggest->bMask) == pSuggest->fType &&
  947. lpAccessEntry->wStateID == 0 &&
  948. lpAccessEntry->dwAreaCode != pSuggest->wAreaCode)
  949. {
  950. pSuggest->rgpAccessEntry[wNumFound] = lpAccessEntry;
  951. wNumFound++;
  952. }
  953. lpAccessEntry++;
  954. } while ((lpAccessEntry <= &m_rgPhoneBookEntry[m_cPhoneBookEntries-1]) &&
  955. (wNumFound < pSuggest->wNumber) &&
  956. (lpAccessEntry->dwCountryID == pSuggest->dwCountryID) &&
  957. (lpAccessEntry->wStateID == 0) );
  958. }
  959. // 8/13/96 jmazner MOS Normandy #4597
  960. // if we STILL couldn't find enough numnbers, widen the search to include tollfree #s
  961. if (wNumFound < pSuggest->wNumber)
  962. {
  963. lpAccessEntry = pCurLookUp->pFirstAE;
  964. // Tweak pSuggest->bMask to let through the toll/charge bit
  965. // REDUNDANT? If we made it to this point, we _should_ have done this above...
  966. // Better safe than sorry!
  967. Assert(pSuggest->bMask & MASK_TOLLFREE_BIT);
  968. pSuggest->bMask |= MASK_TOLLFREE_BIT;
  969. // Tweak pSuggest->ftype to be tollfree
  970. pSuggest->fType |= TYPE_SET_TOLLFREE;
  971. do {
  972. // 8/13/96 jmazner MOS Normandy #4598
  973. // If this entry's area code matches pSuggest->wAreaCode, then we already
  974. // have included it in the first pass, so don't include it here.
  975. // Any entry that made it in in the 2nd pass will definitely not make it in here
  976. // (because of tollfree bit), so no need to worry about dups from there.
  977. if ((lpAccessEntry->fType & pSuggest->bMask) == pSuggest->fType &&
  978. lpAccessEntry->wStateID == 0 &&
  979. lpAccessEntry->dwAreaCode != pSuggest->wAreaCode)
  980. {
  981. pSuggest->rgpAccessEntry[wNumFound] = lpAccessEntry;
  982. wNumFound++;
  983. }
  984. lpAccessEntry++;
  985. } while ((lpAccessEntry <= &m_rgPhoneBookEntry[m_cPhoneBookEntries-1]) &&
  986. (wNumFound < pSuggest->wNumber) &&
  987. (lpAccessEntry->dwCountryID == pSuggest->dwCountryID) &&
  988. (lpAccessEntry->wStateID == 0) );
  989. }
  990. hr = ERROR_SUCCESS;
  991. SuggestExit:
  992. pSuggest->wNumber = wNumFound;
  993. return hr;
  994. }
  995. // ############################################################################
  996. HRESULT CPhoneBook::GetCanonical (PACCESSENTRY pAE, LPSTR psOut)
  997. {
  998. HRESULT hr = ERROR_SUCCESS;
  999. LPIDLOOKUPELEMENT pIDLookUp;
  1000. pIDLookUp = (LPIDLOOKUPELEMENT)bsearch(&pAE->dwCountryID,m_rgIDLookUp,
  1001. (int)m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),CompareIdxLookUpElements);
  1002. if (!pIDLookUp)
  1003. {
  1004. hr = ERROR_INVALID_PARAMETER;
  1005. } else {
  1006. SzCanonicalFromAE (psOut, pAE, pIDLookUp->pLCE);
  1007. }
  1008. return hr;
  1009. }
  1010. // ############################################################################
  1011. DllExportH PhoneBookLoad(LPCSTR pszISPCode, DWORD_PTR far *pdwPhoneID)
  1012. {
  1013. HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
  1014. CPhoneBook far *pcPhoneBook;
  1015. if (!g_hInstDll)
  1016. g_hInstDll = GetModuleHandle(NULL);
  1017. // validate parameters
  1018. Assert(pszISPCode && *pszISPCode && pdwPhoneID);
  1019. *pdwPhoneID = NULL;
  1020. // allocate phone book
  1021. pcPhoneBook = new CPhoneBook;
  1022. // initialize phone book
  1023. if (pcPhoneBook)
  1024. hr = pcPhoneBook->Init(pszISPCode);
  1025. // in case of failure
  1026. if (hr && pcPhoneBook)
  1027. {
  1028. delete pcPhoneBook;
  1029. } else {
  1030. *pdwPhoneID = (DWORD_PTR)pcPhoneBook;
  1031. }
  1032. #if defined(WIN16)
  1033. if (!hr)
  1034. BMP_RegisterClass(g_hInstDll);
  1035. #endif
  1036. return hr;
  1037. }
  1038. // ############################################################################
  1039. DllExportH PhoneBookUnload(DWORD_PTR dwPhoneID)
  1040. {
  1041. Assert(dwPhoneID);
  1042. if (dwPhoneID)
  1043. {
  1044. #if defined(WIN16)
  1045. BMP_DestroyClass(g_hInstDll);
  1046. #endif
  1047. // Release contents
  1048. delete (CPhoneBook far*)dwPhoneID;
  1049. }
  1050. return ERROR_SUCCESS;
  1051. }
  1052. // ############################################################################
  1053. DllExportH PhoneBookMergeChanges(DWORD_PTR dwPhoneID, LPCSTR pszChangeFile)
  1054. {
  1055. return ((CPhoneBook far*)dwPhoneID)->Merge(pszChangeFile);
  1056. }
  1057. // ############################################################################
  1058. DllExportH PhoneBookSuggestNumbers(DWORD_PTR dwPhoneID, PSUGGESTINFO lpSuggestInfo)
  1059. {
  1060. HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
  1061. // get suggested numbers
  1062. lpSuggestInfo->rgpAccessEntry = (PACCESSENTRY *)GlobalAlloc(GPTR,sizeof(PACCESSENTRY) * lpSuggestInfo->wNumber);
  1063. if (lpSuggestInfo->rgpAccessEntry)
  1064. {
  1065. hr = ((CPhoneBook far *)dwPhoneID)->Suggest(lpSuggestInfo);
  1066. }
  1067. return hr;
  1068. }
  1069. // ############################################################################
  1070. DllExportH PhoneBookGetCanonical (DWORD_PTR dwPhoneID, PACCESSENTRY pAE, LPSTR psOut)
  1071. {
  1072. return ((CPhoneBook far*)dwPhoneID)->GetCanonical(pAE,psOut);
  1073. }
  1074. // ############################################################################
  1075. DllExportH PhoneBookDisplaySignUpNumbers (DWORD_PTR dwPhoneID,
  1076. LPSTR far *ppszPhoneNumbers,
  1077. LPSTR far *ppszDunFiles,
  1078. WORD far *pwPhoneNumbers,
  1079. DWORD far *pdwCountry,
  1080. WORD far *pwRegion,
  1081. BYTE fType,
  1082. BYTE bMask,
  1083. HWND hwndParent,
  1084. DWORD dwFlags)
  1085. {
  1086. INT_PTR hr;
  1087. AssertSz(ppszPhoneNumbers && pwPhoneNumbers && pdwCountry &&pwRegion,"invalid parameters");
  1088. //CAccessNumDlg *pcDlg;
  1089. CSelectNumDlg far *pcDlg;
  1090. pcDlg = new CSelectNumDlg;
  1091. if (!pcDlg)
  1092. {
  1093. hr = GetLastError();
  1094. goto DisplayExit;
  1095. }
  1096. // Initialize information for dialog
  1097. //
  1098. pcDlg->m_dwPhoneBook = dwPhoneID;
  1099. pcDlg->m_dwCountryID = *pdwCountry;
  1100. pcDlg->m_wRegion = *pwRegion;
  1101. pcDlg->m_fType = fType;
  1102. pcDlg->m_bMask = bMask;
  1103. pcDlg->m_dwFlags = dwFlags;
  1104. // invoke the dialog
  1105. //
  1106. // BUG: NOT THREAD SAFE!!
  1107. g_hWndMain = hwndParent;
  1108. hr = DialogBoxParam(g_hInstDll,MAKEINTRESOURCE(IDD_SELECTNUMBER),
  1109. g_hWndMain,PhbkGenericDlgProc,(LPARAM)pcDlg);
  1110. g_hWndMain = NULL;
  1111. if (hr == IDC_CMDNEXT)
  1112. {
  1113. *pwRegion = pcDlg->m_wRegion;
  1114. *pdwCountry = pcDlg->m_dwCountryID;
  1115. Assert (ppszPhoneNumbers[0] && ppszDunFiles[0]);
  1116. lstrcpy(ppszPhoneNumbers[0],&pcDlg->m_szPhoneNumber[0]);
  1117. lstrcpy(ppszDunFiles[0],&pcDlg->m_szDunFile[0]);
  1118. hr = ERROR_SUCCESS;
  1119. }
  1120. else if (hr == IDC_CMDBACK)
  1121. hr = ERROR_USERBACK;
  1122. else
  1123. hr = ERROR_USERCANCEL;
  1124. // hr == -1;
  1125. DisplayExit:
  1126. if (pcDlg) delete pcDlg;
  1127. return (HRESULT) hr;
  1128. }