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.

1329 lines
41 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: phbk.cpp
  4. //
  5. // Module: CMPBK32.DLL
  6. //
  7. // Synopsis: Implementation of CPhoneBook
  8. //
  9. // Copyright (c) 1998-1999 Microsoft Corporation
  10. //
  11. // Author: quintinb created header 08/17/99
  12. //
  13. //+----------------------------------------------------------------------------
  14. // ############################################################################
  15. // Phone book APIs
  16. #include "cmmaster.h"
  17. const TCHAR* const c_pszInfDefault = TEXT("INF_DEFAULT");
  18. const TCHAR* const c_pszInfSuffix = TEXT(".CMS");
  19. //#define ReadVerifyPhoneBookDW(x) CMASSERTMSG(ReadPhoneBookDW(&(x),pcCSVFile),"Invalid DWORD in phone book");
  20. #define ReadVerifyPhoneBookDW(x) if (!ReadPhoneBookDW(&(x),pcCSVFile)) \
  21. { CMASSERTMSG(0,"Invalid DWORD in phone book"); \
  22. goto DataError; }
  23. #define ReadVerifyPhoneBookW(x) if (!ReadPhoneBookW(&(x),pcCSVFile)) \
  24. { CMASSERTMSG(0,"Invalid WORD in phone book"); \
  25. goto DataError; }
  26. #define ReadVerifyPhoneBookB(x) if (!ReadPhoneBookB(&(x),pcCSVFile)) \
  27. { CMASSERTMSG(0,"Invalid BYTE in phone book"); \
  28. goto DataError; }
  29. #define ReadVerifyPhoneBookSZ(x,y) if (!ReadPhoneBookSZ(&x[0],y+sizeof('\0'),pcCSVFile)) \
  30. { CMASSERTMSG(0,"Invalid STRING in phone book"); \
  31. goto DataError; }
  32. #define CHANGE_BUFFER_SIZE 50
  33. #define ERROR_USERBACK 32766
  34. #define ERROR_USERCANCEL 32767
  35. // ############################################################################
  36. void CPhoneBook::EnumNumbersByCountry(DWORD dwCountryID, PPBFS pFilter, CB_PHONEBOOK pfnNumber, DWORD_PTR dwParam)
  37. {
  38. MYDBG(("CPhoneBook::EnumNumbersByCountry"));
  39. PACCESSENTRY pAELast, pAE = NULL;
  40. PIDLOOKUPELEMENT pIDLookUp;
  41. IDLOOKUPELEMENT LookUpTarget;
  42. LookUpTarget.dwID = dwCountryID;
  43. pIDLookUp = NULL;
  44. pIDLookUp = (PIDLOOKUPELEMENT)CmBSearch(&LookUpTarget,m_rgIDLookUp,
  45. (size_t) m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),CompareIDLookUpElements);
  46. if (pIDLookUp)
  47. pAE = IdxToPAE(pIDLookUp->iFirstAE);
  48. // Fill the list for whatever AE's we found
  49. //
  50. if (pAE)
  51. {
  52. pAELast = &(m_rgPhoneBookEntry[m_cPhoneBookEntries - 1]);
  53. while (pAELast >= pAE)
  54. {
  55. if (pAE->dwCountryID == dwCountryID && pAE->wStateID == 0) {
  56. if (PhoneBookMatchFilter(pFilter,pAE->fType))
  57. {
  58. pfnNumber((unsigned int) (pAE - m_rgPhoneBookEntry),dwParam);
  59. }
  60. }
  61. pAE++;
  62. }
  63. // Select the first item
  64. //
  65. }
  66. }
  67. // ############################################################################
  68. void CPhoneBook::EnumNumbersByCountry(DWORD dwCountryID, DWORD dwMask, DWORD fType, CB_PHONEBOOK pfnNumber, DWORD_PTR dwParam)
  69. {
  70. MYDBG(("CPhoneBook::EnumNumbersByCountry"));
  71. PhoneBookFilterStruct sFilter = {1,{{dwMask,fType}}};
  72. EnumNumbersByCountry(dwCountryID,&sFilter,pfnNumber,dwParam);
  73. }
  74. // ############################################################################
  75. BOOL CPhoneBook::FHasPhoneType(PPBFS pFilter)
  76. {
  77. MYDBG(("CPhoneBook::FHasPhoneType"));
  78. PACCESSENTRY pAELast, pAE = NULL;
  79. pAE = &(m_rgPhoneBookEntry[0]); // pAE points to the first phone book entry
  80. //
  81. // Examine each entry until we find a match or exhaust the entries
  82. //
  83. if (pAE)
  84. {
  85. pAELast = &(m_rgPhoneBookEntry[m_cPhoneBookEntries - 1]);
  86. while (pAELast >= pAE)
  87. {
  88. //
  89. // See if this pop passes the specified filter
  90. //
  91. if (PhoneBookMatchFilter(pFilter, pAE->fType))
  92. {
  93. return TRUE;
  94. }
  95. pAE++;
  96. }
  97. }
  98. return FALSE;
  99. }
  100. // ############################################################################
  101. void CPhoneBook::EnumNumbersByRegion(unsigned int nRegion, DWORD dwCountryID, PPBFS pFilter, CB_PHONEBOOK pfnNumber, DWORD_PTR dwParam)
  102. {
  103. MYDBG(("CPhoneBook::EnumNumbersByRegion"));
  104. PACCESSENTRY pAELast, pAE = NULL;
  105. pAE = &m_rgPhoneBookEntry[0]; // pAE points to the first phone book entry
  106. // Fill the list for whatever AE's we found
  107. if (pAE)
  108. {
  109. pAELast = &(m_rgPhoneBookEntry[m_cPhoneBookEntries - 1]);
  110. while (pAELast >= pAE)
  111. {
  112. // choose phone number of the same region OR with region ID = 0(which means ALL regions)
  113. if (pAE->dwCountryID == dwCountryID &&
  114. ((pAE->wStateID == nRegion+1) || (pAE->wStateID == 0)))
  115. {
  116. if (PhoneBookMatchFilter(pFilter,pAE->fType))
  117. pfnNumber((unsigned int) (pAE - m_rgPhoneBookEntry), dwParam);
  118. }
  119. pAE++;
  120. }
  121. // Select the first item
  122. //
  123. }
  124. }
  125. // ############################################################################
  126. void CPhoneBook::EnumNumbersByRegion(unsigned int nRegion, DWORD dwCountryID, DWORD dwMask, DWORD fType, CB_PHONEBOOK pfnNumber, DWORD_PTR dwParam)
  127. {
  128. MYDBG(("CPhoneBook::EnumNumbersByRegion"));
  129. PhoneBookFilterStruct sFilter = {1,{{dwMask,fType}}};
  130. EnumNumbersByRegion(nRegion,dwCountryID,&sFilter,pfnNumber,dwParam);
  131. }
  132. // ############################################################################
  133. void CPhoneBook::EnumRegions(DWORD dwCountryID, PPBFS pFilter, CB_PHONEBOOK pfnRegion, DWORD_PTR dwParam)
  134. {
  135. unsigned int idx;
  136. MYDBG(("CPhoneBook::EnumRegions"));
  137. for (idx=0;idx<m_cStates;idx++)
  138. {
  139. PACCESSENTRY pAE = NULL, pAELast = NULL;
  140. pAE = &m_rgPhoneBookEntry[0];
  141. MYDBGASSERT(pAE);
  142. pAELast = &(m_rgPhoneBookEntry[m_cPhoneBookEntries - 1]);
  143. while (pAELast >= pAE)
  144. {
  145. if (pAE->dwCountryID == dwCountryID &&
  146. pAE->wStateID == idx+1)
  147. {
  148. if (PhoneBookMatchFilter(pFilter,pAE->fType))
  149. goto AddRegion;
  150. }
  151. pAE++;
  152. } // while
  153. continue; // start the next 'for' loop
  154. AddRegion:
  155. pfnRegion(idx,dwParam);
  156. }
  157. }
  158. // ############################################################################
  159. void CPhoneBook::EnumRegions(DWORD dwCountryID, DWORD dwMask, DWORD fType, CB_PHONEBOOK pfnRegion, DWORD_PTR dwParam)
  160. {
  161. MYDBG(("CPhoneBook::EnumRegions"));
  162. PhoneBookFilterStruct sFilter = {1,{{dwMask,fType}}};
  163. EnumRegions(dwCountryID,&sFilter,pfnRegion,dwParam);
  164. }
  165. // ############################################################################
  166. void CPhoneBook::EnumCountries(PPBFS pFilter, CB_PHONEBOOK pfnCountry, DWORD_PTR dwParam)
  167. {
  168. unsigned int idx;
  169. MYDBG(("CPhoneBook::EnumCountries"));
  170. for (idx=0;idx<m_pLineCountryList->dwNumCountries;idx++)
  171. {
  172. if (FHasPhoneNumbers(m_rgNameLookUp[idx].pLCE->dwCountryID,pFilter))
  173. {
  174. pfnCountry(idx,dwParam);
  175. }
  176. }
  177. }
  178. // ############################################################################
  179. void CPhoneBook::EnumCountries(DWORD dwMask, DWORD fType, CB_PHONEBOOK pfnCountry, DWORD_PTR dwParam)
  180. {
  181. MYDBG(("CPhoneBook::EnumCountries"));
  182. PhoneBookFilterStruct sFilter = {1,{{dwMask,fType}}};
  183. EnumCountries(&sFilter,pfnCountry,dwParam);
  184. }
  185. // ############################################################################
  186. BOOL CPhoneBook::FHasPhoneNumbers(DWORD dwCountryID, PPBFS pFilter)
  187. {
  188. PIDLOOKUPELEMENT pIDLookUp;
  189. IDLOOKUPELEMENT LookUpTarget;
  190. PACCESSENTRY pAE = NULL, pAELast = NULL;
  191. DWORD dwTmpCountryID;
  192. LookUpTarget.dwID = dwCountryID;
  193. pIDLookUp = NULL;
  194. pIDLookUp = (PIDLOOKUPELEMENT)CmBSearch(&LookUpTarget,m_rgIDLookUp,
  195. (size_t) m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),CompareIDLookUpElements);
  196. if (!pIDLookUp) return FALSE; // no such country
  197. pAE = IdxToPAE(pIDLookUp->iFirstAE);
  198. if (!pAE) return FALSE; // no phone numbers at all
  199. dwTmpCountryID = pAE->dwCountryID;
  200. pAELast = &(m_rgPhoneBookEntry[m_cPhoneBookEntries - 1]);
  201. while (pAELast >= pAE) {
  202. if (pAE->dwCountryID == dwTmpCountryID)
  203. {
  204. if (PhoneBookMatchFilter(pFilter,pAE->fType)) return TRUE;
  205. }
  206. pAE++;
  207. }
  208. return FALSE; // no phone numbers of the right type
  209. // return ((BOOL)(pIDLookUp->pFirstAE));
  210. }
  211. // ############################################################################
  212. BOOL CPhoneBook::FHasPhoneNumbers(DWORD dwCountryID, DWORD dwMask, DWORD fType)
  213. {
  214. MYDBG(("CPhoneBook::FHasPhoneNumbers"));
  215. PhoneBookFilterStruct sFilter = {1,{{dwMask,fType}}};
  216. return FHasPhoneNumbers(dwCountryID,&sFilter);
  217. }
  218. // ############################################################################
  219. CPhoneBook::CPhoneBook()
  220. {
  221. m_rgPhoneBookEntry = NULL;
  222. m_cPhoneBookEntries =0;
  223. m_rgLineCountryEntry=NULL;
  224. m_rgState=NULL;
  225. m_cStates=0;
  226. m_rgIDLookUp = NULL;
  227. m_rgNameLookUp = NULL;
  228. m_pLineCountryList = NULL;
  229. MYDBG(("CPhoneBook::CPhoneBook"));
  230. ZeroMemory(&m_szINFFile[0],MAX_PATH);
  231. ZeroMemory(&m_szPhoneBook[0],MAX_PATH);
  232. }
  233. // ############################################################################
  234. CPhoneBook::~CPhoneBook()
  235. {
  236. MYDBG(("CPhoneBook::~CPhoneBook"));
  237. CmFree(m_rgPhoneBookEntry);
  238. m_rgPhoneBookEntry = NULL;
  239. CmFree(m_pLineCountryList);
  240. m_pLineCountryList = NULL;
  241. CmFree(m_rgIDLookUp);
  242. m_rgIDLookUp = NULL;
  243. CmFree(m_rgNameLookUp);
  244. m_rgNameLookUp = NULL;
  245. CmFree(m_rgState);
  246. m_rgState = NULL;
  247. }
  248. // ############################################################################
  249. BOOL CPhoneBook::ReadPhoneBookDW(DWORD *pdw, CCSVFile *pcCSVFile)
  250. {
  251. char szTempBuffer[TEMP_BUFFER_LENGTH];
  252. if (!pcCSVFile->ReadToken(szTempBuffer,TEMP_BUFFER_LENGTH))
  253. return FALSE;
  254. return (FSz2Dw(szTempBuffer,pdw));
  255. }
  256. // ############################################################################
  257. BOOL CPhoneBook::ReadPhoneBookW(WORD *pw, CCSVFile *pcCSVFile)
  258. {
  259. char szTempBuffer[TEMP_BUFFER_LENGTH];
  260. if (!pcCSVFile->ReadToken(szTempBuffer,TEMP_BUFFER_LENGTH))
  261. return FALSE;
  262. return (FSz2W(szTempBuffer,pw));
  263. }
  264. // ############################################################################
  265. BOOL CPhoneBook::ReadPhoneBookB(BYTE *pb, CCSVFile *pcCSVFile)
  266. {
  267. char szTempBuffer[TEMP_BUFFER_LENGTH];
  268. if (!pcCSVFile->ReadToken(szTempBuffer,TEMP_BUFFER_LENGTH))
  269. return FALSE;
  270. return (FSz2B(szTempBuffer,pb));
  271. }
  272. // ############################################################################
  273. BOOL CPhoneBook::ReadPhoneBookSZ(LPSTR psz, DWORD dwSize, CCSVFile *pcCSVFile)
  274. {
  275. if (!pcCSVFile->ReadToken(psz,dwSize))
  276. return FALSE;
  277. return TRUE;
  278. }
  279. // ############################################################################
  280. BOOL CPhoneBook::ReadPhoneBookNL(CCSVFile *pcCSVFile)
  281. {
  282. if (!pcCSVFile->ClearNewLines())
  283. return FALSE;
  284. return TRUE;
  285. }
  286. //
  287. // Note: the new fUnicode parameter has been added so that Whistler and newer releases
  288. // take advantage of the Unicode TAPI functions where available, so that MUI works.
  289. //
  290. static LONG PBlineGetCountry(DWORD dwCountryID, DWORD dwAPIVersion, LPLINECOUNTRYLIST lpLineCountryList, BOOL fUnicode)
  291. {
  292. HINSTANCE hInst;
  293. LONG lRes;
  294. // Try to load the TAPI DLL
  295. hInst = LoadLibrary("tapi32");
  296. if (!hInst)
  297. {
  298. return (LINEERR_NOMEM);
  299. }
  300. // Get the proc address for GetCountry
  301. LONG (WINAPI *pfn)(DWORD,DWORD,LPLINECOUNTRYLIST);
  302. //
  303. // In case of non-Unicode we don't want lineGetCountryA because on Win95 the tapi32.dll
  304. // doesn't export any A functions.
  305. //
  306. pfn = (LONG (WINAPI *)(DWORD,DWORD,LPLINECOUNTRYLIST)) GetProcAddress(hInst, fUnicode ? "lineGetCountryW" : "lineGetCountry");
  307. if (!pfn)
  308. {
  309. FreeLibrary(hInst);
  310. return (LINEERR_NOMEM);
  311. }
  312. // Get the country list
  313. lRes = pfn(dwCountryID,dwAPIVersion,lpLineCountryList);
  314. FreeLibrary(hInst);
  315. return (lRes);
  316. }
  317. // ############################################################################
  318. HRESULT CPhoneBook::Init(LPCSTR pszISPCode)
  319. {
  320. char szTempBuffer[TEMP_BUFFER_LENGTH];
  321. LPLINECOUNTRYLIST pLineCountryTemp = NULL;
  322. HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
  323. DWORD dwLastState = 0;
  324. DWORD dwLastCountry = 0;
  325. DWORD dwNumAllocated;
  326. PACCESSENTRY pCurAccessEntry = NULL;
  327. LPLINECOUNTRYENTRY pLCETemp;
  328. DWORD idx;
  329. LPTSTR pszTemp;
  330. LPTSTR pszCmpDir = NULL;
  331. CCSVFile *pcCSVFile=NULL;
  332. PSTATE ps,psLast; //faster to use pointers.
  333. DWORD dwAlloc = 0;
  334. PACCESSENTRY pTempAccessEntry = NULL;
  335. MYDBG(("CPhoneBook::Init"));
  336. // Get TAPI country list
  337. m_pLineCountryList = (LPLINECOUNTRYLIST)CmMalloc(sizeof(LINECOUNTRYLIST));
  338. if (!m_pLineCountryList)
  339. {
  340. goto InitExit;
  341. }
  342. m_pLineCountryList->dwTotalSize = sizeof(LINECOUNTRYLIST);
  343. //
  344. // Note: For Whistler and newer releases, we take advantage of the Unicode TAPI
  345. // functions where available, so that MUI works. Hence the final parameter
  346. // to PBlineGetCountry, and the two different QSorts below.
  347. //
  348. // get ALL country information
  349. idx = PBlineGetCountry(0,0x10003, m_pLineCountryList, OS_NT51);
  350. if (idx && idx != LINEERR_STRUCTURETOOSMALL)
  351. {
  352. goto InitExit;
  353. }
  354. MYDBGASSERT(m_pLineCountryList->dwNeededSize);
  355. // reallocate memory for country list
  356. pLineCountryTemp = (LPLINECOUNTRYLIST)CmMalloc(m_pLineCountryList->dwNeededSize);
  357. if (!pLineCountryTemp)
  358. {
  359. goto InitExit;
  360. }
  361. pLineCountryTemp->dwTotalSize = m_pLineCountryList->dwNeededSize;
  362. CmFree(m_pLineCountryList);
  363. m_pLineCountryList = pLineCountryTemp;
  364. pLineCountryTemp = NULL;
  365. if (PBlineGetCountry(0,0x10003, m_pLineCountryList, OS_NT51))
  366. {
  367. goto InitExit;
  368. }
  369. // Load Look Up arrays
  370. // keyword: country ID,
  371. // keyvalue: pointer to the country entry in m_pLineCountryList
  372. //
  373. #ifdef DEBUG
  374. m_rgIDLookUp = (IDLOOKUPELEMENT*)CmMalloc(sizeof(IDLOOKUPELEMENT)*m_pLineCountryList->dwNumCountries+5);
  375. #else
  376. m_rgIDLookUp = (IDLOOKUPELEMENT*)CmMalloc(sizeof(IDLOOKUPELEMENT)*m_pLineCountryList->dwNumCountries);
  377. #endif
  378. if (!m_rgIDLookUp)
  379. {
  380. goto InitExit;
  381. }
  382. // pLCETemp points to the first country information entry
  383. pLCETemp = (LPLINECOUNTRYENTRY)((DWORD_PTR) m_pLineCountryList +
  384. m_pLineCountryList->dwCountryListOffset);
  385. for (idx=0;idx<m_pLineCountryList->dwNumCountries;idx++)
  386. {
  387. m_rgIDLookUp[idx].dwID = pLCETemp[idx].dwCountryID;
  388. m_rgIDLookUp[idx].pLCE = &pLCETemp[idx];
  389. }
  390. // sort the country lines
  391. CmQSort(m_rgIDLookUp, (size_t) m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),
  392. CompareIDLookUpElements);
  393. // m_rgNameLookUp: look-up list for country name
  394. // keyword: country name
  395. // keyvalue: pointer to the country entry in m_pLineCountryList
  396. m_rgNameLookUp = (CNTRYNAMELOOKUPELEMENT*)CmMalloc(sizeof(CNTRYNAMELOOKUPELEMENT) * m_pLineCountryList->dwNumCountries);
  397. if (!m_rgNameLookUp)
  398. {
  399. goto InitExit;
  400. }
  401. for (idx=0;idx<m_pLineCountryList->dwNumCountries;idx++)
  402. {
  403. m_rgNameLookUp[idx].psCountryName = (LPSTR)((DWORD_PTR)m_pLineCountryList + (DWORD)pLCETemp[idx].dwCountryNameOffset);
  404. m_rgNameLookUp[idx].dwNameSize = pLCETemp[idx].dwCountryNameSize;
  405. m_rgNameLookUp[idx].pLCE = &pLCETemp[idx];
  406. }
  407. // sort the country names
  408. if (OS_NT51)
  409. {
  410. CmQSort(m_rgNameLookUp,(size_t) m_pLineCountryList->dwNumCountries,sizeof(CNTRYNAMELOOKUPELEMENTW),
  411. CompareCntryNameLookUpElementsW);
  412. }
  413. else
  414. {
  415. CmQSort(m_rgNameLookUp,(size_t) m_pLineCountryList->dwNumCountries,sizeof(CNTRYNAMELOOKUPELEMENT),
  416. CompareCntryNameLookUpElementsA);
  417. }
  418. //
  419. // Locate ISP's INF file (aka .CMS)
  420. //
  421. if (!SearchPath(NULL, (LPCTSTR) pszISPCode, c_pszInfSuffix, MAX_PATH, m_szINFFile, &pszTemp))
  422. {
  423. wsprintf(szTempBuffer,"Can not find:%s%s (%d)",pszISPCode,c_pszInfSuffix,GetLastError());
  424. CMASSERTMSG(0,szTempBuffer);
  425. hr = ERROR_FILE_NOT_FOUND;
  426. goto InitExit;
  427. }
  428. // Load Region file, get region file name
  429. char szStateFile[sizeof(szTempBuffer)/sizeof(szTempBuffer[0])];
  430. GetPrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspRegionFile, NULL, szStateFile, sizeof(szStateFile)-1, m_szINFFile);
  431. //
  432. // Can't assume current directory, construct path to PBK directory
  433. //
  434. pszCmpDir = GetBaseDirFromCms(m_szINFFile);
  435. //
  436. // Look for the .PBR file, using CMP dir as base path for search
  437. //
  438. if (!SearchPath(pszCmpDir, szStateFile, NULL, TEMP_BUFFER_LENGTH, szTempBuffer, &pszTemp))
  439. {
  440. // CMASSERTMSG(0,"STATE.ICW not found");
  441. CMASSERTMSG(0,"region file not found");
  442. hr = ERROR_FILE_NOT_FOUND;
  443. goto InitExit;
  444. }
  445. // open region file
  446. pcCSVFile = new CCSVFile;
  447. if (!pcCSVFile)
  448. {
  449. goto InitExit;
  450. }
  451. if (!pcCSVFile->Open(szTempBuffer))
  452. {
  453. // CMASSERTMSG(0,"Can not open STATE.ICW");
  454. CMASSERTMSG(0,"Can not open region file");
  455. delete pcCSVFile;
  456. pcCSVFile = NULL;
  457. goto InitExit;
  458. }
  459. // first token in region file is the number of regions
  460. if (!pcCSVFile->ClearNewLines() || !pcCSVFile->ReadToken(szTempBuffer,TEMP_BUFFER_LENGTH))
  461. {
  462. goto InitExit;
  463. }
  464. if (!FSz2Dw(szTempBuffer,&m_cStates))
  465. {
  466. // CMASSERTMSG(0,"STATE.ICW count is invalid");
  467. CMASSERTMSG(0,"region count is invalid");
  468. goto InitExit;
  469. }
  470. // Now read in all the regions if there are any
  471. if (0 != m_cStates)
  472. {
  473. m_rgState = (PSTATE)CmMalloc(sizeof(STATE)*m_cStates);
  474. if (!m_rgState)
  475. {
  476. goto InitExit;
  477. }
  478. for (ps = m_rgState, psLast = &m_rgState[m_cStates - 1]; ps <= psLast;++ps)
  479. {
  480. if (pcCSVFile->ClearNewLines())
  481. {
  482. pcCSVFile->ReadToken(ps->szStateName,cbStateName);
  483. }
  484. }
  485. }
  486. pcCSVFile->Close();
  487. // load Phone Book Name
  488. if (!GetPrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspPbFile,c_pszInfDefault,
  489. szTempBuffer,TEMP_BUFFER_LENGTH,m_szINFFile))
  490. {
  491. CMASSERTMSG(0,"PhoneBookFile not specified in INF file");
  492. hr = ERROR_FILE_NOT_FOUND;
  493. goto InitExit;
  494. }
  495. #ifdef DEBUG
  496. if (!lstrcmp(szTempBuffer,c_pszInfDefault))
  497. {
  498. wsprintf(szTempBuffer, "%s value not found in ISP file", c_pszCmEntryIspPbFile);
  499. CMASSERTMSG(0,szTempBuffer);
  500. }
  501. #endif
  502. //
  503. // Look for the .PBK file, using CMP dir as base path for search
  504. //
  505. if (!SearchPath(pszCmpDir,szTempBuffer,NULL,MAX_PATH,m_szPhoneBook,&pszTemp))
  506. {
  507. CMASSERTMSG(0,"ISP phone book not found");
  508. hr = ERROR_FILE_NOT_FOUND;
  509. goto InitExit;
  510. }
  511. // read in phone book entries
  512. if (!pcCSVFile->Open(m_szPhoneBook))
  513. {
  514. CMASSERTMSG(0,"Can not open phone book");
  515. hr = GetLastError();
  516. goto InitExit;
  517. }
  518. dwNumAllocated = 0;
  519. do {
  520. MYDBGASSERT (dwNumAllocated >= m_cPhoneBookEntries);
  521. if (m_rgPhoneBookEntry)
  522. {
  523. // If we already have an array, make sure its big enough
  524. if (dwNumAllocated == m_cPhoneBookEntries)
  525. {
  526. // We're maxed out, allocate some more memory
  527. dwNumAllocated += PHONE_ENTRY_ALLOC_SIZE;
  528. dwAlloc = (DWORD) dwNumAllocated * sizeof(ACCESSENTRY);
  529. MYDBG(("PhoneBook::Init - Grow ReAlloc = %lu",dwAlloc));
  530. // Realloc
  531. pTempAccessEntry = (PACCESSENTRY)CmRealloc(m_rgPhoneBookEntry, dwAlloc);
  532. if (!pTempAccessEntry)
  533. {
  534. MYDBG(("PhoneBook::Init - Grow ReAlloc of %lu failed", dwAlloc));
  535. goto InitExit;
  536. }
  537. m_rgPhoneBookEntry = pTempAccessEntry;
  538. pTempAccessEntry = NULL;
  539. MYDBG(("Grow phone book to %d entries",dwNumAllocated));
  540. pCurAccessEntry = m_rgPhoneBookEntry + m_cPhoneBookEntries;
  541. }
  542. }
  543. else
  544. {
  545. // Initialization for the first time through
  546. DWORD dwSize = (DWORD) sizeof(ACCESSENTRY);
  547. dwAlloc = (DWORD) dwSize * PHONE_ENTRY_ALLOC_SIZE;
  548. MYDBG(("PhoneBook::Init - sizeof(ACCESSENTRY) = %lu",dwSize));
  549. MYDBG(("PhoneBook::Init - PHONE_ENTRY_ALLOC_SIZE = %d",PHONE_ENTRY_ALLOC_SIZE));
  550. MYDBG(("PhoneBook::Init - Initial Alloc = %lu",dwAlloc));
  551. // Allocate intial array of PHONE_ENTRY_ALLOC_SIZE items
  552. m_rgPhoneBookEntry = (PACCESSENTRY)CmMalloc(dwAlloc);
  553. if (!m_rgPhoneBookEntry)
  554. {
  555. MYDBG(("PhoneBook::Init - Initial Alloc of %lu failed",dwAlloc));
  556. goto InitExit;
  557. }
  558. dwNumAllocated = PHONE_ENTRY_ALLOC_SIZE;
  559. pCurAccessEntry = m_rgPhoneBookEntry;
  560. }
  561. //
  562. // Make sure that we have a valid pCurAccessEntry, otherwise bail out.
  563. //
  564. if (NULL == pCurAccessEntry)
  565. {
  566. CMASSERTMSG(FALSE, TEXT("PhoneBook::Init - pCurAccessEntry is NULL"));
  567. hr = ERROR_NOT_ENOUGH_MEMORY;
  568. goto InitExit;
  569. }
  570. // Read a line from the phonebook
  571. hr = ReadOneLine(pCurAccessEntry,pcCSVFile);
  572. if (hr == ERROR_NO_MORE_ITEMS)
  573. {
  574. break;
  575. }
  576. else if (hr != ERROR_SUCCESS)
  577. {
  578. MYDBG(("PhoneBook::Init - ReadOneLine failed"));
  579. goto InitExit;
  580. }
  581. hr = ERROR_NOT_ENOUGH_MEMORY;
  582. // check the first index pointer to prevent it from being overwritten
  583. // by the second appearance that's scattered around somewhere else -- added by byao
  584. if (pCurAccessEntry->dwCountryID != dwLastCountry)
  585. {
  586. PIDLOOKUPELEMENT pIDLookUpElement;
  587. // NOTE: Not sure about the first parameter here.
  588. pIDLookUpElement = (PIDLOOKUPELEMENT)CmBSearch(&pCurAccessEntry->dwCountryID,
  589. m_rgIDLookUp,(size_t) m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),
  590. CompareIDLookUpElements);
  591. if (!pIDLookUpElement)
  592. {
  593. // bad country ID, but we can't assert here
  594. MYDBG(("Bad country ID in phone book %d\n",pCurAccessEntry->dwCountryID));
  595. continue;
  596. }
  597. else
  598. {
  599. // for a given country ID this is the first phone number
  600. // don't overwrite existing index
  601. if (!pIDLookUpElement->iFirstAE)
  602. {
  603. pIDLookUpElement->iFirstAE = PAEToIdx(pCurAccessEntry);
  604. dwLastCountry = pCurAccessEntry->dwCountryID;
  605. }
  606. }
  607. }
  608. // Check to see if this is the first phone number for a given state
  609. // the code has been changed accordingly
  610. if (pCurAccessEntry->wStateID && (pCurAccessEntry->wStateID != dwLastState))
  611. {
  612. idx = pCurAccessEntry->wStateID - 1;
  613. //
  614. // don't overwrite existing index
  615. //
  616. if ((idx < m_cStates) && !m_rgState[idx].iFirst)
  617. {
  618. m_rgState[idx].dwCountryID = pCurAccessEntry->dwCountryID;
  619. m_rgState[idx].iFirst = PAEToIdx(pCurAccessEntry);
  620. }
  621. dwLastState = pCurAccessEntry->wStateID;
  622. }
  623. pCurAccessEntry++;
  624. m_cPhoneBookEntries++;
  625. } while (TRUE);
  626. MYDBG(("PhoneBook::Init - %lu Entries read",m_cPhoneBookEntries));
  627. if (m_cPhoneBookEntries == 0)
  628. {
  629. //
  630. // Phone book is empty
  631. //
  632. goto InitExit;
  633. }
  634. // Trim the phone book for unused memory
  635. dwAlloc = m_cPhoneBookEntries * sizeof(ACCESSENTRY);
  636. MYDBG(("PhoneBook::Init - Trim ReAlloc = %lu",dwAlloc));
  637. MYDBGASSERT(m_cPhoneBookEntries);
  638. // Realloc
  639. pTempAccessEntry = (PACCESSENTRY)CmRealloc(m_rgPhoneBookEntry, dwAlloc);
  640. MYDBGASSERT(pTempAccessEntry);
  641. if (!pTempAccessEntry)
  642. {
  643. MYDBG(("PhoneBook::Init - Trim ReAlloc of %lu failed",dwAlloc));
  644. goto InitExit;
  645. }
  646. m_rgPhoneBookEntry = pTempAccessEntry;
  647. pTempAccessEntry = NULL;
  648. hr = ERROR_SUCCESS;
  649. // Exit
  650. InitExit:
  651. // If something failed release everything
  652. if (hr != ERROR_SUCCESS)
  653. {
  654. CmFree(m_pLineCountryList);
  655. m_pLineCountryList = NULL;
  656. CmFree(m_rgPhoneBookEntry);
  657. m_rgPhoneBookEntry = NULL;
  658. m_cPhoneBookEntries = 0 ;
  659. CmFree(m_rgIDLookUp);
  660. m_rgIDLookUp=NULL;
  661. CmFree(m_rgNameLookUp);
  662. m_rgNameLookUp=NULL;
  663. CmFree(m_rgState);
  664. m_rgState = NULL;
  665. m_cStates = 0;
  666. }
  667. if (pcCSVFile)
  668. {
  669. pcCSVFile->Close();
  670. delete pcCSVFile;
  671. }
  672. if (pszCmpDir)
  673. {
  674. CmFree(pszCmpDir);
  675. }
  676. return hr;
  677. }
  678. // ############################################################################
  679. HRESULT CPhoneBook::Merge(LPCSTR pszChangeFile)
  680. {
  681. char szTempBuffer[TEMP_BUFFER_LENGTH];
  682. char szTempFileName[MAX_PATH];
  683. CCSVFile *pcCSVFile = NULL;
  684. ACCESSENTRY aeChange;
  685. PIDXLOOKUPELEMENT rgIdxLookUp = NULL;
  686. PIDXLOOKUPELEMENT pCurIdxLookUp;
  687. DWORD dwAllocated;
  688. DWORD dwOriginalSize;
  689. HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
  690. DWORD dwIdx;
  691. DWORD cch, cchWritten;
  692. HANDLE hFile = INVALID_HANDLE_VALUE;
  693. MYDBG(("CPhoneBook::Merge"));
  694. // We'll grow the phone book on the first add record (this minimizes the number
  695. // of places in the code where we have to grow the phone book) - so, for now,
  696. // just stay with the current size.
  697. dwAllocated = m_cPhoneBookEntries;
  698. // Create index to loaded phone book, sorted by index
  699. rgIdxLookUp = (PIDXLOOKUPELEMENT)CmMalloc(sizeof(IDXLOOKUPELEMENT) * dwAllocated);
  700. MYDBGASSERT(rgIdxLookUp);
  701. if (!rgIdxLookUp)
  702. {
  703. goto MergeExit;
  704. }
  705. for (dwIdx = 0; dwIdx < m_cPhoneBookEntries; dwIdx++)
  706. {
  707. rgIdxLookUp[dwIdx].iAE = PAEToIdx(&m_rgPhoneBookEntry[dwIdx]);
  708. rgIdxLookUp[dwIdx].dwIndex = IdxToPAE(rgIdxLookUp[dwIdx].iAE)->dwIndex;
  709. }
  710. dwOriginalSize = m_cPhoneBookEntries;
  711. CmQSort(rgIdxLookUp,(size_t) dwOriginalSize,sizeof(IDXLOOKUPELEMENT),CompareIdxLookUpElements);
  712. // Load changes to phone book
  713. pcCSVFile = new CCSVFile;
  714. MYDBGASSERT(pcCSVFile);
  715. if (!pcCSVFile)
  716. {
  717. goto MergeExit;
  718. }
  719. if (!pcCSVFile->Open(pszChangeFile))
  720. {
  721. delete pcCSVFile;
  722. pcCSVFile = NULL;
  723. goto MergeExit;
  724. }
  725. do {
  726. // Read a change record
  727. ZeroMemory(&aeChange,sizeof(ACCESSENTRY));
  728. hr = ReadOneLine(&aeChange, pcCSVFile);
  729. if (hr == ERROR_NO_MORE_ITEMS)
  730. {
  731. break; // no more enteries
  732. }
  733. else if (hr != ERROR_SUCCESS)
  734. {
  735. goto MergeExit;
  736. }
  737. hr = ERROR_NOT_ENOUGH_MEMORY;
  738. /* if (!ReadPhoneBookDW(&aeChange.dwIndex,pcCSVFile))
  739. break; // no more enteries
  740. ReadVerifyPhoneBookDW(aeChange.dwCountryID);
  741. ReadVerifyPhoneBookW(aeChange.wStateID);
  742. ReadVerifyPhoneBookSZ(aeChange.szCity,cbCity);
  743. ReadVerifyPhoneBookSZ(aeChange.szAreaCode,cbAreaCode);
  744. // NOTE: 0 is a valid area code and ,, is a valid entry for an area code
  745. if (!FSz2Dw(aeChange.szAreaCode,&aeChange.dwAreaCode))
  746. aeChange.dwAreaCode = NO_AREA_CODE;
  747. ReadVerifyPhoneBookSZ(aeChange.szAccessNumber,cbAccessNumber);
  748. ReadVerifyPhoneBookDW(aeChange.dwConnectSpeedMin);
  749. ReadVerifyPhoneBookDW(aeChange.dwConnectSpeedMax);
  750. ReadVerifyPhoneBookB(aeChange.bFlipFactor);
  751. ReadVerifyPhoneBookDW(aeChange.fType);
  752. ReadVerifyPhoneBookSZ(aeChange.szDataCenter,cbDataCenter);
  753. */
  754. pCurIdxLookUp = (PIDXLOOKUPELEMENT) CmBSearch(&aeChange,
  755. rgIdxLookUp,
  756. (size_t) dwOriginalSize,
  757. sizeof(IDXLOOKUPELEMENT),
  758. CompareIdxLookUpElements);
  759. // Determine if this is a delete, add, or merge record
  760. if (aeChange.szAccessNumber[0] == '0' && aeChange.szAccessNumber[1] == '\0')
  761. {
  762. // This is a delete record
  763. CMASSERTMSG(pCurIdxLookUp,"Attempting to delete a record that does not exist. The change file and phone book versions do not match.");
  764. if (pCurIdxLookUp)
  765. {
  766. CMASSERTMSG(IdxToPAE(pCurIdxLookUp->iAE),"Attempting to delete a record that has already been deleted.");
  767. pCurIdxLookUp->iAE = PAEToIdx(NULL); //Create a dead entry in the look up table
  768. }
  769. }
  770. else if (pCurIdxLookUp)
  771. {
  772. // This is a change record
  773. CMASSERTMSG(IdxToPAE(pCurIdxLookUp->iAE),"Attempting to change a record which has been deleted.");
  774. if (IdxToPAE(pCurIdxLookUp->iAE))
  775. {
  776. CopyMemory(IdxToPAE(pCurIdxLookUp->iAE),&aeChange,sizeof(ACCESSENTRY));
  777. }
  778. }
  779. else
  780. {
  781. // This is an add entry
  782. // Make sure we have enough room
  783. if (m_cPhoneBookEntries >= dwAllocated)
  784. {
  785. // Grow phone book
  786. dwAllocated += CHANGE_BUFFER_SIZE;
  787. DWORD dwNewAlloc = (DWORD) sizeof(ACCESSENTRY) * dwAllocated;
  788. PACCESSENTRY pTempAccessEntry = (PACCESSENTRY)CmRealloc(m_rgPhoneBookEntry, dwNewAlloc);
  789. MYDBGASSERT(pTempAccessEntry);
  790. if (!pTempAccessEntry)
  791. {
  792. MYDBG(("PhoneBook::Merge - Grow ReAlloc of %lu failed",dwNewAlloc));
  793. goto MergeExit;
  794. }
  795. m_rgPhoneBookEntry = pTempAccessEntry;
  796. pTempAccessEntry = NULL;
  797. MYDBG(("Grow phone book to %lu entries",dwAllocated));
  798. // Grow look up index
  799. MYDBGASSERT(rgIdxLookUp);
  800. PIDXLOOKUPELEMENT pTempLookupElement = (PIDXLOOKUPELEMENT)CmRealloc(rgIdxLookUp, sizeof(IDXLOOKUPELEMENT)*dwAllocated);
  801. MYDBGASSERT(pTempLookupElement);
  802. if (!pTempLookupElement)
  803. {
  804. goto MergeExit;
  805. }
  806. rgIdxLookUp = pTempLookupElement;
  807. }
  808. //Add entry to the end of the phonebook and to end of look up index
  809. CopyMemory(&m_rgPhoneBookEntry[m_cPhoneBookEntries],&aeChange,sizeof(ACCESSENTRY));
  810. rgIdxLookUp[m_cPhoneBookEntries].iAE = PAEToIdx(&m_rgPhoneBookEntry[m_cPhoneBookEntries]);
  811. rgIdxLookUp[m_cPhoneBookEntries].dwIndex = IdxToPAE(rgIdxLookUp[m_cPhoneBookEntries].iAE)->dwIndex;
  812. m_cPhoneBookEntries++;
  813. // NOTE: because the entry is added to the end of the list, we can't add
  814. // and delete entries in the same change file.
  815. }
  816. } while (TRUE);
  817. // The CompareIdxLookupElementFileOrder() function needs the iAE member to be
  818. // a PACCESSENTRY, and not an index. So we convert 'em here, and then we'll
  819. // convert 'em back later.
  820. for (dwIdx=0;dwIdx<m_cPhoneBookEntries;dwIdx++) {
  821. rgIdxLookUp[dwIdx].iAE = (LONG_PTR)IdxToPAE(rgIdxLookUp[dwIdx].iAE);
  822. }
  823. // resort the IDXLookUp index to reflect the correct order of entries
  824. // for the phonebook file, including all of the entries to be deleted.
  825. CmQSort(rgIdxLookUp,(size_t) m_cPhoneBookEntries,sizeof(IDXLOOKUPELEMENT),CompareIdxLookUpElementsFileOrder);
  826. // Now we convert 'em back.
  827. for (dwIdx=0;dwIdx<m_cPhoneBookEntries;dwIdx++) {
  828. rgIdxLookUp[dwIdx].iAE = PAEToIdx((PACCESSENTRY) rgIdxLookUp[dwIdx].iAE);
  829. }
  830. // Build a new phonebook file
  831. #if 0
  832. /*
  833. #define TEMP_PHONE_BOOK_PREFIX "PBH"
  834. if (!GetTempPath(TEMP_BUFFER_LENGTH,szTempBuffer))
  835. goto MergeExit;
  836. if (!GetTempFileName(szTempBuffer,TEMP_PHONE_BOOK_PREFIX,0,szTempFileName))
  837. goto MergeExit;
  838. hFile = CreateFile(szTempFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
  839. FILE_FLAG_WRITE_THROUGH,0);
  840. */
  841. #else
  842. for (dwIdx=0;;dwIdx++)
  843. {
  844. lstrcpy(szTempFileName,m_szPhoneBook);
  845. wsprintf(szTempFileName+lstrlen(szTempFileName),".%03u",dwIdx);
  846. hFile = CreateFile(szTempFileName,GENERIC_WRITE,0,NULL,CREATE_NEW,0,0);
  847. if ((hFile != INVALID_HANDLE_VALUE) || (GetLastError() != ERROR_FILE_EXISTS)) {
  848. break;
  849. }
  850. }
  851. #endif
  852. if (hFile == INVALID_HANDLE_VALUE)
  853. {
  854. goto MergeExit;
  855. }
  856. for (dwIdx = 0; dwIdx < m_cPhoneBookEntries; dwIdx++)
  857. {
  858. PACCESSENTRY pAE = IdxToPAE(rgIdxLookUp[dwIdx].iAE);
  859. if (pAE) {
  860. cch = wsprintf(szTempBuffer, "%lu,%lu,%lu,%s,%s,%s,%lu,%lu,%lu,%lu,%s\r\n",
  861. pAE->dwIndex,
  862. pAE->dwCountryID,
  863. (DWORD) pAE->wStateID,
  864. pAE->szCity,
  865. pAE->szAreaCode,
  866. pAE->szAccessNumber,
  867. pAE->dwConnectSpeedMin,
  868. pAE->dwConnectSpeedMax,
  869. (DWORD) pAE->bFlipFactor,
  870. (DWORD) pAE->fType,
  871. pAE->szDataCenter);
  872. if (!WriteFile(hFile,szTempBuffer,cch,&cchWritten,NULL))
  873. {
  874. // something went wrong, get rid of the temporary file
  875. hr = GetLastError();
  876. CloseHandle(hFile);
  877. hFile = INVALID_HANDLE_VALUE;
  878. DeleteFile(szTempFileName);
  879. goto MergeExit;
  880. }
  881. MYDBGASSERT(cch == cchWritten);
  882. }
  883. }
  884. CloseHandle(hFile);
  885. hFile = INVALID_HANDLE_VALUE;
  886. // Move new phone book over old
  887. if (!DeleteFile(m_szPhoneBook))
  888. {
  889. hr = GetLastError();
  890. goto MergeExit;
  891. }
  892. if (!MoveFile(szTempFileName,m_szPhoneBook))
  893. {
  894. hr = GetLastError();
  895. goto MergeExit;
  896. }
  897. // discard the phonebook in memory
  898. CmFree(m_rgPhoneBookEntry);
  899. m_rgPhoneBookEntry = NULL;
  900. m_cPhoneBookEntries = 0;
  901. CmFree(m_pLineCountryList);
  902. CmFree(m_rgIDLookUp);
  903. CmFree(m_rgNameLookUp);
  904. CmFree(m_rgState);
  905. m_pLineCountryList = NULL;
  906. m_rgIDLookUp = NULL;
  907. m_rgNameLookUp = NULL;
  908. m_rgState = NULL;
  909. m_cStates = 0;
  910. lstrcpy(szTempBuffer,m_szINFFile);
  911. m_szINFFile[0] = '\0';
  912. m_szPhoneBook[0] = '\0';
  913. // Reload it (and rebuild look up arrays)
  914. hr = Init(szTempBuffer);
  915. MergeExit:
  916. if (pcCSVFile)
  917. {
  918. pcCSVFile->Close();
  919. delete pcCSVFile;
  920. }
  921. if (hFile != INVALID_HANDLE_VALUE)
  922. {
  923. CloseHandle(hFile);
  924. }
  925. CmFree(rgIdxLookUp);
  926. return hr;
  927. }
  928. // ############################################################################
  929. HRESULT CPhoneBook::ReadOneLine(PACCESSENTRY pAccessEntry, CCSVFile *pcCSVFile)
  930. {
  931. HRESULT hr = ERROR_SUCCESS;
  932. //
  933. // Skip newlines (trailing or leading) and read first DW token
  934. // If either fail, then consider this the end of the file
  935. //
  936. if (!ReadPhoneBookNL(pcCSVFile) || !ReadPhoneBookDW(&pAccessEntry->dwIndex,pcCSVFile))
  937. {
  938. hr = ERROR_NO_MORE_ITEMS; // no more enteries
  939. MYDBG(("CPhoneBook::ReadOneLine - No More items"));
  940. goto ReadExit;
  941. }
  942. ReadVerifyPhoneBookDW(pAccessEntry->dwCountryID);
  943. ReadVerifyPhoneBookW(pAccessEntry->wStateID);
  944. ReadVerifyPhoneBookSZ(pAccessEntry->szCity,cbCity);
  945. ReadVerifyPhoneBookSZ(pAccessEntry->szAreaCode,cbAreaCode);
  946. // NOTE: 0 is a valid area code and ,, is a valid entry for an area code
  947. if (!FSz2Dw(pAccessEntry->szAreaCode,&pAccessEntry->dwAreaCode))
  948. pAccessEntry->dwAreaCode = NO_AREA_CODE;
  949. ReadVerifyPhoneBookSZ(pAccessEntry->szAccessNumber,cbAccessNumber);
  950. ReadVerifyPhoneBookDW(pAccessEntry->dwConnectSpeedMin);
  951. ReadVerifyPhoneBookDW(pAccessEntry->dwConnectSpeedMax);
  952. ReadVerifyPhoneBookB(pAccessEntry->bFlipFactor);
  953. ReadVerifyPhoneBookDW(pAccessEntry->fType);
  954. //
  955. // Attempt to read datacenter, if read fails, find out why before reacting
  956. //
  957. if (!ReadPhoneBookSZ(pAccessEntry->szDataCenter, cbDataCenter + 1, pcCSVFile))
  958. {
  959. //
  960. // If the last read was successful, then we must have some bad sz data
  961. //
  962. if (!pcCSVFile->ReadError())
  963. {
  964. CMASSERTMSG(0,"Invalid STRING in phone book");
  965. goto DataError;
  966. }
  967. }
  968. ReadExit:
  969. return hr;
  970. DataError:
  971. hr = ERROR_INVALID_DATA;
  972. goto ReadExit;
  973. }
  974. // ############################################################################
  975. HRESULT CPhoneBook::GetCanonical (PACCESSENTRY pAE, char *psOut)
  976. {
  977. HRESULT hr = ERROR_SUCCESS;
  978. PIDLOOKUPELEMENT pIDLookUp;
  979. pIDLookUp = (PIDLOOKUPELEMENT)CmBSearch(&pAE->dwCountryID,m_rgIDLookUp,
  980. (size_t) m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),CompareIdxLookUpElements);
  981. if (!pIDLookUp)
  982. {
  983. hr = ERROR_INVALID_PARAMETER;
  984. }
  985. else
  986. {
  987. if (!psOut)
  988. {
  989. hr = ERROR_INVALID_PARAMETER;
  990. }
  991. else
  992. {
  993. *psOut = 0;
  994. SzCanonicalFromAE (psOut, pAE, pIDLookUp->pLCE);
  995. }
  996. }
  997. return hr;
  998. }
  999. // ############################################################################
  1000. HRESULT CPhoneBook::GetNonCanonical (PACCESSENTRY pAE, char *psOut)
  1001. {
  1002. HRESULT hr = ERROR_SUCCESS;
  1003. PIDLOOKUPELEMENT pIDLookUp;
  1004. pIDLookUp = (PIDLOOKUPELEMENT)CmBSearch(&pAE->dwCountryID,m_rgIDLookUp,
  1005. (size_t) m_pLineCountryList->dwNumCountries,sizeof(IDLOOKUPELEMENT),CompareIdxLookUpElements);
  1006. if (!pIDLookUp)
  1007. {
  1008. hr = ERROR_INVALID_PARAMETER;
  1009. }
  1010. else
  1011. {
  1012. if (!psOut)
  1013. {
  1014. hr = ERROR_INVALID_PARAMETER;
  1015. }
  1016. else
  1017. {
  1018. *psOut = 0;
  1019. SzNonCanonicalFromAE (psOut, pAE, pIDLookUp->pLCE);
  1020. }
  1021. }
  1022. return hr;
  1023. }
  1024. // ############################################################################
  1025. DllExportH PhoneBookLoad(LPCSTR pszISPCode, DWORD_PTR *pdwPhoneID)
  1026. {
  1027. HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
  1028. CPhoneBook *pcPhoneBook;
  1029. MYDBG(("CM_PHBK_DllExport - PhoneBookLoad"));
  1030. if (!g_hInst) g_hInst = GetModuleHandleA(NULL);
  1031. // validate parameters
  1032. MYDBGASSERT(pszISPCode && *pszISPCode && pdwPhoneID);
  1033. *pdwPhoneID = NULL;
  1034. // allocate phone book
  1035. pcPhoneBook = new CPhoneBook;
  1036. // initialize phone book
  1037. if (pcPhoneBook)
  1038. hr = pcPhoneBook->Init(pszISPCode);
  1039. // in case of failure
  1040. if (hr && pcPhoneBook)
  1041. {
  1042. delete pcPhoneBook;
  1043. MYDBG(("PhoneBookLoad() - init failed"));
  1044. } else {
  1045. *pdwPhoneID = (DWORD_PTR)pcPhoneBook;
  1046. }
  1047. return hr;
  1048. }
  1049. // ############################################################################
  1050. DllExportH PhoneBookUnload(DWORD_PTR dwPhoneID)
  1051. {
  1052. MYDBG(("CM_PHBK_DllExport - PhoneBookUnload"));
  1053. MYDBGASSERT(dwPhoneID);
  1054. // Release contents
  1055. delete (CPhoneBook*)dwPhoneID;
  1056. return ERROR_SUCCESS;
  1057. }
  1058. // ############################################################################
  1059. DllExportH PhoneBookMergeChanges(DWORD_PTR dwPhoneID, LPCSTR pszChangeFile)
  1060. {
  1061. MYDBG(("CM_PHBK_DllExport - PhoneBookMergeChanges"));
  1062. return ((CPhoneBook*)dwPhoneID)->Merge(pszChangeFile);
  1063. }