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.

3600 lines
105 KiB

  1. /****************************************************************************
  2. Copyright (c) 1995-1999 Microsoft Corporation
  3. Module Name: dial.cpp
  4. ****************************************************************************/
  5. #include <windows.h>
  6. #include <windowsx.h>
  7. #if WINNT
  8. #else
  9. #include <help.h>
  10. #endif
  11. #include "tchar.h"
  12. #include "prsht.h"
  13. #include "stdlib.h"
  14. #include "tapi.h"
  15. #include "tspi.h"
  16. #include "client.h"
  17. #include "clntprivate.h"
  18. #include "card.h"
  19. #include "location.h"
  20. #include "rules.h"
  21. #include "countrygroup.h"
  22. #include <shlwapi.h>
  23. #include <shlwapip.h> // from private\inc
  24. #undef lineGetTranslateCaps
  25. #undef lineSetTollList
  26. #undef lineTranslateAddress
  27. #undef tapiGetLocationInfo
  28. #undef lineGetCountry
  29. #undef lineTranslateDialog
  30. // moved here from loc_comn.h
  31. #define MAXLEN_NAME 96
  32. #ifdef __cplusplus
  33. extern "C"{
  34. #endif
  35. BOOL gbTranslateSimple = FALSE;
  36. BOOL gbTranslateSilent = FALSE;
  37. TCHAR gszTelephonyKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Telephony");
  38. TCHAR gszRegKeyNTServer[] = TEXT("System\\CurrentControlSet\\Control\\ProductOptions");
  39. TCHAR gszLocation[] = TEXT("Location");
  40. TCHAR gszLocations[] = TEXT("Locations");
  41. const TCHAR gszNullString[] = TEXT("");
  42. TCHAR gszNumEntries[] = TEXT("NumEntries");
  43. TCHAR gszCurrentID[] = TEXT("CurrentID");
  44. TCHAR gszNextID[] = TEXT("NextID");
  45. TCHAR gszID[] = TEXT("ID");
  46. TCHAR gszFlags[] = TEXT("Flags");
  47. TCHAR gszCallingCard[] = TEXT("CallingCard");
  48. TCHAR gszCards[] = TEXT("Cards");
  49. TCHAR gszCard[] = TEXT("Card");
  50. #ifdef __cplusplus
  51. }
  52. #endif
  53. LONG CreateCurrentLocationObject(CLocation **pLocation,
  54. HLINEAPP hLineApp,
  55. DWORD dwDeviceID,
  56. DWORD dwAPIVersion,
  57. DWORD dwOptions);
  58. HRESULT ReadLocations( PLOCATIONLIST *ppLocationList,
  59. HLINEAPP hLineApp,
  60. DWORD dwDeviceID,
  61. DWORD dwAPIVersion,
  62. DWORD dwOptions
  63. );
  64. LONG PASCAL ReadCountries( LPLINECOUNTRYLIST *ppLCL,
  65. UINT nCountryID,
  66. DWORD dwDestCountryID
  67. );
  68. LONG BreakupCanonicalW( PWSTR pAddressIn,
  69. PWSTR *pCountry,
  70. PWSTR *pCity,
  71. PWSTR *pSubscriber
  72. );
  73. static LONG GetTranslateCapsCommon(
  74. HLINEAPP hLineApp,
  75. DWORD dwAPIVersion,
  76. LPLINETRANSLATECAPS lpTranslateCaps,
  77. BOOL bUnicode
  78. );
  79. static void LayDownTollList(CLocation *pLocation,
  80. PBYTE pBuffer,
  81. PBYTE *ppCurrentIndex,
  82. PDWORD pPair,
  83. BOOL bUnicode,
  84. PBYTE pFirstByteAfter
  85. );
  86. static void LayDownString( PCWSTR pInString,
  87. PBYTE pBuffer,
  88. PBYTE *ppCurrentIndex,
  89. PDWORD pPair,
  90. BOOL bUnicode,
  91. PBYTE pFirstByteAfter
  92. );
  93. static PWSTR CopyStringWithExpandJAndK(PWSTR pszRule, PWSTR pszAccessNr, PWSTR pszAccountNr);
  94. static BOOL IsATollListAreaCodeRule(CAreaCodeRule *pRule, PWSTR pszLocationAreaCode);
  95. static BOOL FindTollPrefixInLocation(CLocation *pLocation,
  96. PWSTR pPrefix,
  97. CAreaCodeRule **ppRule,
  98. PWSTR *ppWhere);
  99. static PWSTR FindPrefixInMultiSZ(PWSTR pPrefixList, PWSTR pPrefix);
  100. LONG PASCAL WriteLocations( PLOCATIONLIST pLocationList,
  101. DWORD dwChangedFlags
  102. );
  103. extern "C" char * PASCAL
  104. MapResultCodeToText(
  105. LONG lResult,
  106. char *pszResult
  107. );
  108. LONG
  109. PASCAL
  110. IsThisAPIVersionInvalid(
  111. DWORD dwAPIVersion
  112. )
  113. {
  114. switch (dwAPIVersion)
  115. {
  116. case TAPI_VERSION3_1:
  117. case TAPI_VERSION3_0:
  118. case TAPI_VERSION2_2:
  119. case TAPI_VERSION2_1:
  120. case TAPI_VERSION2_0:
  121. case TAPI_VERSION1_4:
  122. case TAPI_VERSION1_0:
  123. return 0;
  124. default:
  125. break;
  126. }
  127. return LINEERR_INCOMPATIBLEAPIVERSION;
  128. }
  129. //***************************************************************************
  130. //
  131. // TAPI API Interfaces
  132. //
  133. //***************************************************************************
  134. //***************************************************************************
  135. LONG
  136. WINAPI
  137. lineTranslateDialogA(
  138. HLINEAPP hLineApp,
  139. DWORD dwDeviceID,
  140. DWORD dwAPIVersion,
  141. HWND hwndOwner,
  142. LPCSTR lpszAddressIn
  143. )
  144. {
  145. PWSTR szAddressInW = NULL;
  146. LONG lResult;
  147. LOG((TL_TRACE, "Entering lineTranslateDialogA"));
  148. LOG((TL_INFO, " hLineApp=x%lx", hLineApp));
  149. LOG((TL_INFO, " dwAPIVersion=0x%08lx", dwAPIVersion));
  150. LOG((TL_INFO, " hwndOwner=x%p", hwndOwner));
  151. LOG((TL_INFO, " lpszAddressIn=x%p", lpszAddressIn));
  152. if ( lpszAddressIn )
  153. {
  154. if ( IsBadStringPtrA(lpszAddressIn, 512) )
  155. {
  156. LOG((TL_ERROR, "Bad string pointer passed to lineTranslateDialog"));
  157. return LINEERR_INVALPOINTER;
  158. }
  159. else
  160. {
  161. szAddressInW = MultiToWide( lpszAddressIn );
  162. }
  163. }
  164. //
  165. // Win9x ?
  166. //
  167. #ifndef _WIN64
  168. if ((GetVersion() & 0x80000000) &&
  169. (0xffff0000 == ((DWORD) hwndOwner & 0xffff0000)))
  170. {
  171. //
  172. // Yeah. It don't play no ffff.
  173. //
  174. hwndOwner = (HWND) ( (DWORD)hwndOwner & 0x0000ffff );
  175. }
  176. #endif
  177. lResult = lineTranslateDialogW(
  178. hLineApp,
  179. dwDeviceID,
  180. dwAPIVersion,
  181. hwndOwner,
  182. szAddressInW
  183. );
  184. if ( szAddressInW )
  185. {
  186. ClientFree( szAddressInW );
  187. }
  188. return lResult;
  189. }
  190. //***************************************************************************
  191. LONG
  192. WINAPI
  193. lineTranslateDialog(
  194. HLINEAPP hLineApp,
  195. DWORD dwDeviceID,
  196. DWORD dwAPIVersion,
  197. HWND hwndOwner,
  198. LPCSTR lpszAddressIn
  199. )
  200. {
  201. return lineTranslateDialogA(
  202. hLineApp,
  203. dwDeviceID,
  204. dwAPIVersion,
  205. hwndOwner,
  206. lpszAddressIn
  207. );
  208. }
  209. extern "C" LONG WINAPI internalConfig( HWND hwndParent, PCWSTR pwsz, INT iTab, DWORD dwAPIVersion );
  210. //***************************************************************************
  211. LONG
  212. WINAPI
  213. lineTranslateDialogW(
  214. HLINEAPP hLineApp,
  215. DWORD dwDeviceID,
  216. DWORD dwAPIVersion,
  217. HWND hwndOwner,
  218. LPCWSTR lpszAddressIn
  219. )
  220. {
  221. PLOCATIONLIST pLocTest = NULL;
  222. LONG lResult = 0;
  223. LOG((TL_TRACE, "Entering lineTranslateDialogW"));
  224. LOG((TL_INFO, " hLineApp=x%lx", hLineApp));
  225. LOG((TL_INFO, " dwAPIVersion=0x%08lx", dwAPIVersion));
  226. LOG((TL_INFO, " hwndOwner=x%p", hwndOwner));
  227. LOG((TL_INFO, " lpszAddressIn=x%p", lpszAddressIn));
  228. // stuff that the old lineTranslateDialog did so I'm just copying it:
  229. lResult = IsThisAPIVersionInvalid( dwAPIVersion );
  230. if ( lResult )
  231. {
  232. LOG((TL_ERROR, "Bad dwAPIVersion - 0x%08lx", dwAPIVersion));
  233. return lResult;
  234. }
  235. if ( lpszAddressIn && TAPIIsBadStringPtrW(lpszAddressIn, (UINT)-1) )
  236. {
  237. LOG((TL_ERROR, "Bad lpszAddressIn pointer (0x%p)", lpszAddressIn));
  238. return LINEERR_INVALPOINTER;
  239. }
  240. if (hwndOwner && !IsWindow (hwndOwner))
  241. {
  242. LOG((TL_ERROR, " hwndOwner is bogus"));
  243. return LINEERR_INVALPARAM;
  244. }
  245. // Let TAPISRV test the params for us
  246. lResult = ReadLocations(&pLocTest,
  247. hLineApp,
  248. dwDeviceID,
  249. dwAPIVersion,
  250. CHECKPARMS_DWHLINEAPP|
  251. CHECKPARMS_DWDEVICEID|
  252. CHECKPARMS_DWAPIVERSION|
  253. CHECKPARMS_ONLY);
  254. if (pLocTest != NULL)
  255. {
  256. ClientFree( pLocTest);
  257. }
  258. if (lResult != ERROR_SUCCESS)
  259. {
  260. return lResult;
  261. }
  262. return internalConfig(hwndOwner, lpszAddressIn, -1, dwAPIVersion);
  263. }
  264. //***************************************************************************
  265. LONG
  266. WINAPI
  267. lineGetTranslateCaps(
  268. HLINEAPP hLineApp,
  269. DWORD dwAPIVersion,
  270. LPLINETRANSLATECAPS lpTranslateCaps
  271. )
  272. {
  273. LONG lResult;
  274. lResult = lineGetTranslateCapsA(
  275. hLineApp,
  276. dwAPIVersion,
  277. lpTranslateCaps
  278. );
  279. //
  280. // Some 1.x apps like Applink (as of version 7.5b) don't call
  281. // lineTranslateDialog when they get a LINEERR_INIFILECORRUPT
  282. // result back from the request (spec says they should call
  283. // lineTranslateDialog), so we do that here for them, otherwise
  284. // some (like Applink) blow up
  285. //
  286. // While it's kind of ugly & intrusive, this is a less awkward
  287. // fix than placing a bogus location entry in the registry &
  288. // setting an Inited flag == 0 like tapi 1.x does
  289. //
  290. // There are cases in which this hack can break the caller (ex. MSWORKS)
  291. // The gbDisableGetTranslateCapsHack flag set to TRUE prevents the hack to be applied
  292. // See bug 306143
  293. if (lResult == LINEERR_INIFILECORRUPT && !gbDisableGetTranslateCapsHack)
  294. {
  295. lineTranslateDialog(
  296. hLineApp,
  297. 0,
  298. dwAPIVersion,
  299. GetActiveWindow(),
  300. NULL
  301. );
  302. lResult = lineGetTranslateCapsA(
  303. hLineApp,
  304. dwAPIVersion,
  305. lpTranslateCaps
  306. );
  307. }
  308. return lResult;
  309. }
  310. //***************************************************************************
  311. LONG
  312. WINAPI
  313. lineGetTranslateCapsA(
  314. HLINEAPP hLineApp,
  315. DWORD dwAPIVersion,
  316. LPLINETRANSLATECAPS lpTranslateCaps
  317. )
  318. {
  319. LONG lResult = 0;
  320. LOG((TL_TRACE, "Entering lineGetTranslateCapsA"));
  321. LOG((TL_INFO, " hLineApp=x%lx", hLineApp));
  322. LOG((TL_INFO, " dwAPIVersion=0x%08lx", dwAPIVersion));
  323. LOG((TL_INFO, " lpTranslateCaps=x%p", lpTranslateCaps));
  324. lResult = GetTranslateCapsCommon(hLineApp, dwAPIVersion, lpTranslateCaps, FALSE);
  325. #if DBG
  326. {
  327. char szResult[32];
  328. LOG((TL_TRACE,
  329. "lineGetTranslateCapsA: result = %hs",
  330. MapResultCodeToText (lResult, szResult)
  331. ));
  332. }
  333. #else
  334. LOG((TL_TRACE,
  335. "lineGetTranslateCapsA: result = x%x",
  336. lResult
  337. ));
  338. #endif
  339. return lResult;
  340. }
  341. //***************************************************************************
  342. LONG
  343. WINAPI
  344. lineGetTranslateCapsW(
  345. HLINEAPP hLineApp,
  346. DWORD dwAPIVersion,
  347. LPLINETRANSLATECAPS lpTranslateCaps
  348. )
  349. {
  350. LONG lResult = 0;
  351. LOG((TL_TRACE, "Entering lineGetTranslateCapsW"));
  352. LOG((TL_INFO, " hLineApp=x%lx", hLineApp));
  353. LOG((TL_INFO, " dwAPIVersion=0x%08lx", dwAPIVersion));
  354. LOG((TL_INFO, " lpTranslateCaps=x%p", lpTranslateCaps));
  355. lResult = GetTranslateCapsCommon( hLineApp,
  356. dwAPIVersion,
  357. lpTranslateCaps,
  358. TRUE);
  359. #if DBG
  360. {
  361. char szResult[32];
  362. LOG((TL_TRACE,
  363. "lineGetTranslateCapsW: result = %hs",
  364. MapResultCodeToText (lResult, szResult)
  365. ));
  366. }
  367. #else
  368. LOG((TL_TRACE,
  369. "lineGetTranslateCapsW: result = x%x",
  370. lResult
  371. ));
  372. #endif
  373. return lResult;
  374. }
  375. //***************************************************************************
  376. LONG
  377. WINAPI
  378. lineTranslateAddressA(
  379. HLINEAPP hLineApp,
  380. DWORD dwDeviceID,
  381. DWORD dwAPIVersion,
  382. LPCSTR lpszAddressIn,
  383. DWORD dwCard,
  384. DWORD dwTranslateOptions,
  385. LPLINETRANSLATEOUTPUT lpTranslateOutput
  386. )
  387. {
  388. WCHAR szTempStringW[512];
  389. LONG lResult;
  390. if ( IsBadStringPtrA(lpszAddressIn, 512) )
  391. {
  392. LOG((TL_ERROR,
  393. "Invalid pszAddressIn pointer passed into lineTranslateAddress"
  394. ));
  395. return LINEERR_INVALPOINTER;
  396. }
  397. MultiByteToWideChar(
  398. GetACP(),
  399. MB_PRECOMPOSED,
  400. lpszAddressIn,
  401. -1,
  402. szTempStringW,
  403. 512
  404. );
  405. lResult = lineTranslateAddressW(
  406. hLineApp,
  407. dwDeviceID,
  408. dwAPIVersion,
  409. szTempStringW,
  410. dwCard,
  411. dwTranslateOptions,
  412. lpTranslateOutput
  413. );
  414. if ( 0 == lResult )
  415. {
  416. WideStringToNotSoWideString(
  417. (LPBYTE)lpTranslateOutput,
  418. &lpTranslateOutput->dwDialableStringSize
  419. );
  420. WideStringToNotSoWideString(
  421. (LPBYTE)lpTranslateOutput,
  422. &lpTranslateOutput->dwDisplayableStringSize
  423. );
  424. }
  425. return lResult;
  426. }
  427. LONG
  428. WINAPI
  429. lineTranslateAddress(
  430. HLINEAPP hLineApp,
  431. DWORD dwDeviceID,
  432. DWORD dwAPIVersion,
  433. LPCSTR lpszAddressIn,
  434. DWORD dwCard,
  435. DWORD dwTranslateOptions,
  436. LPLINETRANSLATEOUTPUT lpTranslateOutput
  437. )
  438. {
  439. LONG lResult;
  440. lResult = lineTranslateAddressA(
  441. hLineApp,
  442. dwDeviceID,
  443. dwAPIVersion,
  444. lpszAddressIn,
  445. dwCard,
  446. dwTranslateOptions,
  447. lpTranslateOutput
  448. );
  449. //
  450. // Some 1.x apps like Applink (as of version 7.5b) don't call
  451. // lineTranslateDialog when they get a LINEERR_INIFILECORRUPT
  452. // result back from the request (spec says they should call
  453. // lineTranslateDialog), so we do that here for them, otherwise
  454. // some (like Applink) blow up
  455. //
  456. // While it's kind of ugly & intrusive, this is a less awkward
  457. // fix than placing a bogus location entry in the registry &
  458. // setting an Inited flag == 0 like tapi 1.x does
  459. //
  460. if (lResult == LINEERR_INIFILECORRUPT)
  461. {
  462. lineTranslateDialog(
  463. hLineApp,
  464. 0,
  465. dwAPIVersion,
  466. GetActiveWindow(),
  467. NULL
  468. );
  469. lResult = lineTranslateAddressA(
  470. hLineApp,
  471. dwDeviceID,
  472. dwAPIVersion,
  473. lpszAddressIn,
  474. dwCard,
  475. dwTranslateOptions,
  476. lpTranslateOutput
  477. );
  478. }
  479. return lResult;
  480. }
  481. //***************************************************************************
  482. LONG
  483. WINAPI
  484. lineTranslateAddressW(
  485. HLINEAPP hLineApp,
  486. DWORD dwDeviceID,
  487. DWORD dwAPIVersion,
  488. LPCWSTR lpszAddressIn,
  489. DWORD dwCard,
  490. DWORD dwTranslateOptions,
  491. LPLINETRANSLATEOUTPUT lpTranslateOutput
  492. )
  493. {
  494. CLocation * pLocation = NULL;
  495. CCallingCard * pCallingCard = NULL;
  496. DWORD dwTranslateResults;
  497. DWORD dwDestCountryCode;
  498. PWSTR pszDialableString = NULL;
  499. PWSTR pszDisplayableString = NULL;
  500. LONG lResult = 0;
  501. HRESULT hr=S_OK;
  502. DWORD dwCardToUse = 0;
  503. DWORD dwDialableSize;
  504. DWORD dwDisplayableSize;
  505. DWORD dwNeededSize;
  506. LOG((TL_TRACE, "Entering lineTranslateAddress"));
  507. lResult = IsThisAPIVersionInvalid( dwAPIVersion );
  508. if ( lResult )
  509. {
  510. LOG((TL_ERROR, "Bad dwAPIVersion - 0x%08lx", dwAPIVersion));
  511. return lResult;
  512. }
  513. if ( TAPIIsBadStringPtrW(lpszAddressIn,256) )
  514. {
  515. LOG((TL_ERROR, "Invalid pointer - lpszAddressInW"));
  516. lResult = LINEERR_INVALPOINTER;
  517. return lResult;
  518. }
  519. if ( dwTranslateOptions &
  520. ~(LINETRANSLATEOPTION_CARDOVERRIDE |
  521. LINETRANSLATEOPTION_CANCELCALLWAITING |
  522. LINETRANSLATEOPTION_FORCELOCAL |
  523. LINETRANSLATEOPTION_FORCELD) )
  524. {
  525. LOG((TL_ERROR, " Invalid dwTranslateOptions (unknown flag set)"));
  526. lResult = LINEERR_INVALPARAM;
  527. return lResult;
  528. }
  529. if ( ( dwTranslateOptions & ( LINETRANSLATEOPTION_FORCELOCAL |
  530. LINETRANSLATEOPTION_FORCELD) )
  531. ==
  532. ( LINETRANSLATEOPTION_FORCELOCAL |
  533. LINETRANSLATEOPTION_FORCELD)
  534. )
  535. {
  536. LOG((TL_ERROR, " Invalid dwTranslateOptions (both FORCELOCAL & FORCELD set!)"));
  537. lResult = LINEERR_INVALPARAM;
  538. return lResult;
  539. }
  540. //
  541. // Is the structure at least a minimum size?
  542. //
  543. if (IsBadWritePtr(lpTranslateOutput, sizeof(LINETRANSLATEOUTPUT)))
  544. {
  545. LOG((TL_ERROR, " Leaving lineTranslateAddress INVALIDPOINTER"));
  546. lResult = LINEERR_INVALPOINTER;
  547. return lResult;
  548. }
  549. if (lpTranslateOutput->dwTotalSize < sizeof(LINETRANSLATEOUTPUT))
  550. {
  551. LOG((TL_ERROR, " Leaving lineTranslateAddress STRUCTURETOOSMALL"));
  552. lResult = LINEERR_STRUCTURETOOSMALL;
  553. return lResult;
  554. }
  555. if (IsBadWritePtr(lpTranslateOutput, lpTranslateOutput->dwTotalSize) )
  556. {
  557. LOG((TL_ERROR,
  558. " Leaving lineTranslateAddress lpTanslateOutput->dwTotalSize bad"
  559. ));
  560. lResult = LINEERR_INVALPOINTER;
  561. return lResult;
  562. }
  563. //
  564. // Should we let some bad stuff slide?
  565. //
  566. if ( dwAPIVersion < 0x00020000 )
  567. {
  568. hLineApp = NULL;
  569. }
  570. lResult = CreateCurrentLocationObject(&pLocation,
  571. hLineApp,
  572. dwDeviceID,
  573. dwAPIVersion,
  574. CHECKPARMS_DWHLINEAPP|
  575. CHECKPARMS_DWDEVICEID|
  576. CHECKPARMS_DWAPIVERSION);
  577. if(FAILED(lResult))
  578. {
  579. //lResult = lResult==E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_OPERATIONFAILED;
  580. return lResult;
  581. }
  582. if ( dwTranslateOptions & LINETRANSLATEOPTION_CARDOVERRIDE)
  583. {
  584. dwCardToUse = dwCard;
  585. }
  586. else
  587. {
  588. if(pLocation->HasCallingCard() )
  589. {
  590. dwCardToUse = pLocation->GetPreferredCardID();
  591. }
  592. }
  593. if (dwCardToUse != 0)
  594. {
  595. pCallingCard = new CCallingCard;
  596. if(pCallingCard)
  597. {
  598. if( FAILED(pCallingCard->Initialize(dwCardToUse)) )
  599. {
  600. delete pCallingCard;
  601. delete pLocation;
  602. lResult = LINEERR_INVALCARD;
  603. return lResult;
  604. }
  605. }
  606. }
  607. lResult = pLocation->TranslateAddress((PWSTR)lpszAddressIn,
  608. pCallingCard,
  609. dwTranslateOptions,
  610. &dwTranslateResults,
  611. &dwDestCountryCode,
  612. &pszDialableString,
  613. &pszDisplayableString
  614. );
  615. if (lResult == 0)
  616. {
  617. dwDialableSize = sizeof(WCHAR) * (lstrlenW(pszDialableString) + 1);
  618. dwDisplayableSize = sizeof(WCHAR) * (lstrlenW(pszDisplayableString) + 1);
  619. dwNeededSize = dwDialableSize +
  620. dwDisplayableSize +
  621. 3 + // For potential alignment problem
  622. sizeof(LINETRANSLATEOUTPUT);
  623. lpTranslateOutput->dwNeededSize = dwNeededSize;
  624. lpTranslateOutput->dwCurrentCountry = pLocation->GetCountryID();
  625. lpTranslateOutput->dwDestCountry = dwDestCountryCode; // country code, not the ID !!
  626. if (dwNeededSize <= lpTranslateOutput->dwTotalSize)
  627. {
  628. lpTranslateOutput->dwUsedSize = dwNeededSize;
  629. lpTranslateOutput->dwDialableStringSize = dwDialableSize;
  630. lpTranslateOutput->dwDialableStringOffset =
  631. sizeof(LINETRANSLATEOUTPUT);
  632. lpTranslateOutput->dwDisplayableStringSize = dwDisplayableSize;
  633. lpTranslateOutput->dwDisplayableStringOffset =
  634. sizeof(LINETRANSLATEOUTPUT) + dwDialableSize;
  635. // lpTranslateOutput->dwDisplayableStringOffset =
  636. // (sizeof(LINETRANSLATEOUTPUT) + dwDialableSize
  637. // + 3) & 0xfffffffc;
  638. lpTranslateOutput->dwTranslateResults = dwTranslateResults;
  639. wcscpy ((WCHAR *)(lpTranslateOutput + 1), pszDialableString);
  640. //
  641. // Be ultra paranoid and make sure the string is DWORD aligned
  642. //
  643. wcscpy(
  644. (LPWSTR)(((LPBYTE)(lpTranslateOutput + 1) +
  645. dwDialableSize)),
  646. // + 3 ) & 0xfffffffc)
  647. pszDisplayableString
  648. );
  649. }
  650. else
  651. {
  652. lpTranslateOutput->dwUsedSize = sizeof(LINETRANSLATEOUTPUT);
  653. lpTranslateOutput->dwTranslateResults =
  654. lpTranslateOutput->dwDialableStringSize =
  655. lpTranslateOutput->dwDialableStringOffset =
  656. lpTranslateOutput->dwDisplayableStringSize =
  657. lpTranslateOutput->dwDisplayableStringOffset = 0;
  658. }
  659. }
  660. //cleanup:
  661. if ( pszDisplayableString )
  662. {
  663. ClientFree( pszDisplayableString );
  664. }
  665. if ( pszDialableString )
  666. {
  667. ClientFree( pszDialableString );
  668. }
  669. if (pLocation != NULL)
  670. {
  671. delete pLocation;
  672. }
  673. if (pCallingCard != NULL)
  674. {
  675. delete pCallingCard;
  676. }
  677. /*
  678. //
  679. // If success & there's an LCR hook for this function then call it
  680. // & allow it to override our results if it wants to
  681. //
  682. if (lResult == 0 &&
  683. IsLeastCostRoutingEnabled() &&
  684. pfnLineTranslateAddressWLCR)
  685. {
  686. lResult = (*pfnLineTranslateAddressWLCR)(
  687. hLineApp,
  688. dwDeviceID,
  689. dwAPIVersion,
  690. lpszAddressIn,
  691. dwCard,
  692. dwTranslateOptions,
  693. lpTranslateOutput
  694. );
  695. }
  696. */
  697. return (lResult);
  698. }
  699. //***************************************************************************
  700. LONG
  701. WINAPI
  702. lineSetCurrentLocation(
  703. HLINEAPP hLineApp,
  704. DWORD dwLocationID
  705. )
  706. {
  707. UINT n;
  708. PUINT pnStuff;
  709. PLOCATIONLIST pLocationList;
  710. PLOCATION pEntry;
  711. LONG lResult = 0;
  712. HRESULT hr;
  713. DWORD dwCurrentLocationID = 0;
  714. DWORD dwNumEntries = 0;
  715. DWORD dwCount = 0;
  716. LOG((TL_TRACE,
  717. "lineSetCurrentLocation: enter, hApp=x%x, dwLoc=x%x",
  718. hLineApp,
  719. dwLocationID
  720. ));
  721. // Let TAPISRV test the params for us
  722. hr = ReadLocations(&pLocationList,
  723. hLineApp,
  724. 0,
  725. 0,
  726. CHECKPARMS_DWHLINEAPP
  727. );
  728. if SUCCEEDED( hr)
  729. {
  730. // current location
  731. dwCurrentLocationID = pLocationList->dwCurrentLocationID;
  732. //
  733. // If (specified loc == current loc) then simply return SUCCESS.
  734. //
  735. // Ran into a problem with the Equis (Reuters) DownLoader app in
  736. // which it would call this func, we'd pass the info to tapisrv,
  737. // tapisrv would send a LINE_LINEDEVSTATE\TRANSLATECHANGE msg,
  738. // and the app would respond by doing a lineSetCurrentLocation
  739. // again, effectively winding up in an infinite loop. Fyi, tapi
  740. // 1.x did not send a DEVSTATE\TRANSLATECHANGE msg if the
  741. // specified locationID == the current location ID.
  742. //
  743. if (dwLocationID == dwCurrentLocationID)
  744. {
  745. lResult = 0;
  746. }
  747. else
  748. {
  749. hr = E_FAIL; // fail if we don't find the requested loc
  750. // Find position of 1st LOCATION structure in the LOCATIONLIST structure
  751. pEntry = (PLOCATION) ((BYTE*)(pLocationList) + pLocationList->dwLocationListOffset );
  752. // Number of locations ?
  753. dwNumEntries = pLocationList->dwNumLocationsInList;
  754. // Find the current location
  755. for (dwCount = 0; dwCount < dwNumEntries ; dwCount++)
  756. {
  757. if(pEntry->dwPermanentLocationID == dwLocationID)
  758. {
  759. hr = S_OK;
  760. break;
  761. }
  762. // Try next location in list
  763. //pEntry++;
  764. pEntry = (PLOCATION) ((BYTE*)(pEntry) + pEntry->dwUsedSize);
  765. }
  766. if SUCCEEDED( hr)
  767. {
  768. LOG((TL_INFO, "lineSetCurrentLocation - reqired location found %d",
  769. dwCurrentLocationID));
  770. // write new value
  771. // finished with TAPI memory block so release
  772. if ( pLocationList != NULL )
  773. ClientFree( pLocationList );
  774. // Allocate the memory buffer;
  775. pLocationList = (PLOCATIONLIST) ClientAlloc( sizeof(LOCATIONLIST) );
  776. if (pLocationList != NULL)
  777. {
  778. // buffer size
  779. pLocationList->dwTotalSize = sizeof(LOCATIONLIST);
  780. pLocationList->dwNeededSize = sizeof(LOCATIONLIST);
  781. pLocationList->dwUsedSize = sizeof(LOCATIONLIST);
  782. pLocationList->dwCurrentLocationID = dwLocationID;
  783. pLocationList->dwNumLocationsAvailable = 0;
  784. pLocationList->dwNumLocationsInList = 0;
  785. pLocationList->dwLocationListSize = 0;
  786. pLocationList->dwLocationListOffset = 0;
  787. WriteLocations( pLocationList, CHANGEDFLAGS_CURLOCATIONCHANGED);
  788. }
  789. }
  790. else
  791. {
  792. LOG((TL_ERROR, "lineSetCurrentLocation - required location not found "));
  793. lResult = LINEERR_INVALLOCATION;
  794. }
  795. }
  796. }
  797. else
  798. {
  799. lResult = hr;
  800. }
  801. // finished with TAPI memory block so release
  802. if ( pLocationList != NULL )
  803. ClientFree( pLocationList );
  804. LOG((TL_TRACE, "Leaving lineSetCurrentLocation"));
  805. return lResult;
  806. }
  807. //***************************************************************************
  808. LONG
  809. WINAPI
  810. lineSetTollList(
  811. HLINEAPP hLineApp,
  812. DWORD dwDeviceID,
  813. LPCSTR lpszAddressIn,
  814. DWORD dwTollListOption
  815. )
  816. {
  817. return lineSetTollListA(
  818. hLineApp,
  819. dwDeviceID,
  820. lpszAddressIn,
  821. dwTollListOption
  822. );
  823. }
  824. //***************************************************************************
  825. LONG
  826. WINAPI
  827. lineSetTollListA(
  828. HLINEAPP hLineApp,
  829. DWORD dwDeviceID,
  830. LPCSTR lpszAddressIn,
  831. DWORD dwTollListOption
  832. )
  833. {
  834. WCHAR szAddressInW[512];
  835. if ( IsBadStringPtrA(lpszAddressIn, 512) )
  836. {
  837. LOG((TL_ERROR, "Bad string pointer passed to lineSetTollListA"));
  838. return LINEERR_INVALPOINTER;
  839. }
  840. MultiByteToWideChar(
  841. GetACP(),
  842. MB_PRECOMPOSED,
  843. lpszAddressIn,
  844. -1,
  845. szAddressInW,
  846. 512
  847. );
  848. return lineSetTollListW(
  849. hLineApp,
  850. dwDeviceID,
  851. szAddressInW,
  852. dwTollListOption
  853. );
  854. }
  855. //***************************************************************************
  856. LONG
  857. WINAPI
  858. lineSetTollListW(
  859. HLINEAPP hLineApp,
  860. DWORD dwDeviceID,
  861. PCWSTR pszAddressIn,
  862. DWORD dwTollListOption
  863. )
  864. {
  865. PWSTR pAddressIn = NULL;
  866. PWSTR pAreaCode;
  867. PWSTR pCountryCode;
  868. PWSTR pSubscriber;
  869. CLocation *pLocation = NULL;
  870. BOOL bPrefixPresent;
  871. CAreaCodeRule *pRule = NULL;
  872. PWSTR pWhere = NULL;
  873. LONG lResult;
  874. // Test the parameters
  875. if ((dwTollListOption != LINETOLLLISTOPTION_ADD) &&
  876. (dwTollListOption != LINETOLLLISTOPTION_REMOVE))
  877. {
  878. LOG((TL_ERROR, "Bad dwTollListOption in lineSetTollListW"));
  879. return LINEERR_INVALPARAM;
  880. }
  881. if ( TAPIIsBadStringPtrW(pszAddressIn, 256) )
  882. {
  883. LOG((TL_ERROR, "Bad pszAddressIn (0x%p)in lineSetTollListW", pszAddressIn));
  884. return LINEERR_INVALPOINTER;
  885. }
  886. //
  887. // Now, do we have a canonical number to deal with ?
  888. //
  889. if ( *pszAddressIn != L'+' ) // Check the first char
  890. {
  891. //
  892. // Nope, not canonical
  893. //
  894. LOG((TL_ERROR, "Address not canonical in lineSetTollListW"));
  895. return LINEERR_INVALADDRESS;
  896. }
  897. // Alloc a copy of the string
  898. pAddressIn = ClientAllocString((PWSTR)pszAddressIn);
  899. if ( !pAddressIn )
  900. {
  901. LOG((TL_ERROR, "Memory allocation failed"));
  902. return LINEERR_NOMEM;
  903. }
  904. // separate the string components
  905. lResult = BreakupCanonicalW(pAddressIn + 1,
  906. &pCountryCode,
  907. &pAreaCode,
  908. &pSubscriber
  909. );
  910. if(lResult)
  911. {
  912. goto forced_exit;
  913. }
  914. // test the prefix validity.
  915. // assuming 3 digits..
  916. if(! (iswdigit(pSubscriber[0]) &&
  917. iswdigit(pSubscriber[1]) &&
  918. iswdigit(pSubscriber[2]) &&
  919. pSubscriber[3] ))
  920. {
  921. LOG((TL_ERROR, "lineSetTollListW: The prefix is not valid"));
  922. lResult = LINEERR_INVALADDRESS;
  923. goto forced_exit;
  924. }
  925. // get the current location object
  926. lResult = CreateCurrentLocationObject(&pLocation,
  927. hLineApp,
  928. dwDeviceID,
  929. 0,
  930. CHECKPARMS_DWHLINEAPP|
  931. CHECKPARMS_DWDEVICEID);
  932. if(FAILED(lResult))
  933. {
  934. //lResult = lResult==E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_OPERATIONFAILED;
  935. goto forced_exit;
  936. }
  937. // are the number and the current location with country code 1 ?
  938. // is this number in the same area code ?
  939. if(pLocation->GetCountryCode() != 1 ||
  940. pCountryCode[0] != L'1' ||
  941. pCountryCode[1] != L'\0' ||
  942. wcscmp(pLocation->GetAreaCode(), pAreaCode) !=0 )
  943. {
  944. lResult = 0;
  945. goto forced_exit;
  946. }
  947. // terminate the 3 digit prefix
  948. pSubscriber[3] = L'\0';
  949. pSubscriber[4] = L'\0';
  950. // is there the prefix in any location toll rules ?
  951. bPrefixPresent = FindTollPrefixInLocation( pLocation,
  952. pSubscriber,
  953. &pRule,
  954. &pWhere);
  955. if(dwTollListOption == LINETOLLLISTOPTION_ADD)
  956. {
  957. // add toll prefix
  958. if(bPrefixPresent)
  959. {
  960. ;// Do nothing
  961. lResult = 0;
  962. }
  963. else
  964. {
  965. // if we have already a toll rule, try to add the prefix to it
  966. if(pRule)
  967. {
  968. PWSTR pList;
  969. DWORD dwSize = pRule->GetPrefixListSize();
  970. // alloc a bigger list
  971. pList = (PWSTR)ClientAlloc(dwSize + 4*sizeof(WCHAR));
  972. if(pList==NULL)
  973. {
  974. lResult = LINEERR_NOMEM;
  975. goto forced_exit;
  976. }
  977. // copy the old one
  978. memcpy((PBYTE)pList, (PBYTE)pRule->GetPrefixList(), dwSize);
  979. // add our prefix
  980. memcpy((PBYTE)pList + dwSize-sizeof(WCHAR), (PBYTE)pSubscriber, 5*sizeof(WCHAR));
  981. // set the new list
  982. lResult = pRule->SetPrefixList(pList, dwSize + 4*sizeof(WCHAR));
  983. ClientFree(pList);
  984. if(FAILED(lResult))
  985. {
  986. lResult = lResult==E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_OPERATIONFAILED;
  987. goto forced_exit;
  988. }
  989. }
  990. // else a new rule must be created
  991. else
  992. {
  993. pRule = new CAreaCodeRule();
  994. if(pRule == NULL)
  995. {
  996. lResult = LINEERR_NOMEM;
  997. goto forced_exit;
  998. }
  999. lResult = pRule->Initialize( pAreaCode,
  1000. L"1",
  1001. RULE_DIALNUMBER | RULE_DIALAREACODE,
  1002. pSubscriber,
  1003. 5*sizeof(WCHAR)
  1004. );
  1005. if(FAILED(lResult))
  1006. {
  1007. delete pRule;
  1008. lResult = lResult==E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_OPERATIONFAILED;
  1009. goto forced_exit;
  1010. }
  1011. // add the rule to the location
  1012. pLocation->AddRule(pRule);
  1013. }
  1014. }
  1015. }
  1016. else
  1017. {
  1018. // delete the toll prefix
  1019. if(bPrefixPresent)
  1020. {
  1021. DWORD dwSize = pRule->GetPrefixListSize();
  1022. // we have at least a toll rule present. If our prefix is the only one in that rule,
  1023. // delete the entire rule
  1024. if(dwSize<=5*sizeof(WCHAR))
  1025. {
  1026. // Delete the rule
  1027. pLocation->RemoveRule(pRule);
  1028. lResult = 0;
  1029. }
  1030. else
  1031. {
  1032. PWSTR pList;
  1033. PWSTR pOld;
  1034. DWORD dwHeadSize;
  1035. DWORD dwTailSize;
  1036. pList = (PWSTR)ClientAlloc(dwSize - 4*sizeof(WCHAR));
  1037. if(pList==NULL)
  1038. {
  1039. lResult = LINEERR_NOMEM;
  1040. goto forced_exit;
  1041. }
  1042. pOld = pRule->GetPrefixList();
  1043. dwHeadSize = (DWORD)((PBYTE)pWhere - (PBYTE)pOld);
  1044. dwTailSize = dwSize - dwHeadSize - 4*sizeof(WCHAR);
  1045. // copy the first part of the old list
  1046. memcpy((PBYTE)pList, (PBYTE)pOld, dwHeadSize);
  1047. // copy the rest of the list
  1048. memcpy((PBYTE)pList+dwHeadSize, (PBYTE)pWhere + 4*sizeof(WCHAR), dwTailSize);
  1049. // set the new list
  1050. lResult = pRule->SetPrefixList(pList, dwSize - 4*sizeof(WCHAR));
  1051. ClientFree(pList);
  1052. if(FAILED(lResult))
  1053. {
  1054. lResult = lResult==E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_OPERATIONFAILED;
  1055. goto forced_exit;
  1056. }
  1057. }
  1058. }
  1059. else
  1060. {
  1061. // prefix not present. Do nothing.
  1062. lResult = 0;
  1063. }
  1064. }
  1065. // Save
  1066. lResult = pLocation->WriteToRegistry();
  1067. if(FAILED(lResult))
  1068. {
  1069. lResult = lResult==E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_OPERATIONFAILED;
  1070. goto forced_exit;
  1071. }
  1072. forced_exit:
  1073. if(pLocation)
  1074. delete pLocation;
  1075. if(pAddressIn)
  1076. ClientFree(pAddressIn);
  1077. return lResult;
  1078. }
  1079. //***************************************************************************
  1080. LONG
  1081. WINAPI
  1082. tapiGetLocationInfoW(
  1083. LPWSTR lpszCountryCode,
  1084. LPWSTR lpszCityCode
  1085. )
  1086. {
  1087. CLocation * pLocation;
  1088. LONG lResult = 0;
  1089. WCHAR * p;
  1090. WCHAR * q;
  1091. DWORD i;
  1092. if (IsBadWritePtr( lpszCountryCode, 16) )
  1093. {
  1094. LOG((TL_ERROR,
  1095. "tapiGetLocationInfoW: lpszCountryCode is not a valid, 8-byte pointer"
  1096. ));
  1097. return TAPIERR_REQUESTFAILED;
  1098. }
  1099. if (IsBadWritePtr( lpszCityCode, 16) )
  1100. {
  1101. LOG((TL_ERROR,
  1102. "tapiGetLocationInfoW: lpszCityCode is not a valid, 8-byte pointer"
  1103. ));
  1104. return TAPIERR_REQUESTFAILED;
  1105. }
  1106. lResult = CreateCurrentLocationObject(&pLocation,0,0,0,0);
  1107. if(FAILED(lResult))
  1108. {
  1109. return TAPIERR_REQUESTFAILED;
  1110. }
  1111. TCHAR szTempChar[8];
  1112. wsprintf(
  1113. szTempChar,
  1114. TEXT("%d"),
  1115. pLocation->GetCountryCode()
  1116. );
  1117. SHTCharToUnicode(szTempChar, lpszCountryCode, 8);
  1118. //
  1119. // Make sure not to return > (7 chars + NULL char)
  1120. //
  1121. p = (WCHAR *) lpszCityCode;
  1122. q = (WCHAR *) pLocation->GetAreaCode();
  1123. for (i = 0; (i < 7) && ((p[i] = q[i]) != L'\0'); i++);
  1124. p[7] = L'\0';
  1125. delete pLocation;
  1126. return 0;
  1127. }
  1128. //***************************************************************************
  1129. LONG
  1130. WINAPI
  1131. tapiGetLocationInfoA(
  1132. LPSTR lpszCountryCode,
  1133. LPSTR lpszCityCode
  1134. )
  1135. {
  1136. WCHAR szCountryCodeW[8];
  1137. WCHAR szCityCodeW[8];
  1138. LONG lResult;
  1139. LOG((TL_TRACE, "Entering tapiGetLocationInfoA"));
  1140. LOG((TL_INFO, " lpszCountryCode=%p", lpszCountryCode ));
  1141. LOG((TL_INFO, " lpszCityCode=%p", lpszCityCode ));
  1142. if (IsBadWritePtr( lpszCountryCode, 8) )
  1143. {
  1144. LOG((TL_ERROR, "tapiGetLocationInfo: lpszCountryCode is not a valid, 8-byte pointer"));
  1145. return TAPIERR_REQUESTFAILED;
  1146. }
  1147. if (IsBadWritePtr( lpszCityCode, 8) )
  1148. {
  1149. LOG((TL_ERROR, "tapiGetLocationInfo: lpszCityCode is not a valid, 8-byte pointer"));
  1150. return TAPIERR_REQUESTFAILED;
  1151. }
  1152. lResult = tapiGetLocationInfoW(
  1153. szCountryCodeW,
  1154. szCityCodeW
  1155. );
  1156. if ( 0 == lResult )
  1157. {
  1158. WideCharToMultiByte(
  1159. GetACP(),
  1160. 0,
  1161. szCountryCodeW,
  1162. -1,
  1163. lpszCountryCode,
  1164. 8,
  1165. NULL,
  1166. NULL
  1167. );
  1168. WideCharToMultiByte(
  1169. GetACP(),
  1170. 0,
  1171. szCityCodeW,
  1172. -1,
  1173. lpszCityCode,
  1174. 8,
  1175. NULL,
  1176. NULL
  1177. );
  1178. }
  1179. return lResult;
  1180. }
  1181. //***************************************************************************
  1182. LONG
  1183. WINAPI
  1184. tapiGetLocationInfo(
  1185. LPSTR lpszCountryCode,
  1186. LPSTR lpszCityCode
  1187. )
  1188. {
  1189. return tapiGetLocationInfoA(
  1190. lpszCountryCode,
  1191. lpszCityCode
  1192. );
  1193. }
  1194. //***************************************************************************
  1195. //
  1196. // RAS Private Interfaces
  1197. //
  1198. //***************************************************************************
  1199. #ifndef NORASPRIVATES
  1200. //***************************************************************************
  1201. LOCATION*
  1202. LocationFromID(
  1203. IN LOCATION* pLocs,
  1204. IN UINT cLocs,
  1205. IN DWORD dwID )
  1206. {
  1207. return NULL;
  1208. }
  1209. //***************************************************************************
  1210. LOCATION*
  1211. LocationFromName(
  1212. IN LOCATION* pLocs,
  1213. IN UINT cLocs,
  1214. IN WCHAR* pszName )
  1215. {
  1216. return NULL;
  1217. }
  1218. //***************************************************************************
  1219. //
  1220. // internalCreateDefLocation
  1221. //
  1222. // This API is created to be used by OOBE team internally.
  1223. // It expectes a LOCATIONLIST with at least one LOCATION
  1224. // specified in it. and pLocation->dwCurrentLocationID needs to
  1225. // match dwPermanentLocationID of at least one of the location
  1226. // entries specified in the location list.
  1227. //
  1228. extern "C"
  1229. HRESULT APIENTRY
  1230. internalCreateDefLocation(
  1231. PLOCATIONLIST pLocationList
  1232. )
  1233. {
  1234. HRESULT hr = S_OK;
  1235. DWORD dw;
  1236. PLOCATION pEntry;
  1237. // Basic parameter check
  1238. if (pLocationList == NULL ||
  1239. pLocationList->dwNumLocationsInList < 1 ||
  1240. pLocationList->dwUsedSize == 0 ||
  1241. pLocationList->dwUsedSize > pLocationList->dwTotalSize ||
  1242. pLocationList->dwTotalSize <
  1243. sizeof(LOCATIONLIST) + sizeof(LOCATION) ||
  1244. pLocationList->dwLocationListSize < sizeof(LOCATION)
  1245. )
  1246. {
  1247. hr = E_INVALIDARG;
  1248. goto ExitHere;
  1249. }
  1250. // Check the validity of the dwCurrentLocationID
  1251. pEntry = (PLOCATION)((LPBYTE)pLocationList +
  1252. pLocationList->dwLocationListOffset);
  1253. for (dw = 0; dw < pLocationList->dwNumLocationsInList; ++dw)
  1254. {
  1255. if (pEntry->dwPermanentLocationID ==
  1256. pLocationList->dwCurrentLocationID)
  1257. {
  1258. break;
  1259. }
  1260. pEntry = (PLOCATION)((LPBYTE)pEntry + pEntry->dwUsedSize);
  1261. }
  1262. if (dw >= pLocationList->dwNumLocationsInList)
  1263. {
  1264. hr = E_INVALIDARG;
  1265. goto ExitHere;
  1266. }
  1267. hr = (HRESULT) WriteLocations (
  1268. pLocationList,
  1269. CHANGEDFLAGS_CURLOCATIONCHANGED
  1270. );
  1271. ExitHere:
  1272. return hr;
  1273. }
  1274. extern "C"
  1275. DWORD APIENTRY
  1276. internalNewLocationW(
  1277. IN WCHAR* pszName )
  1278. {
  1279. LONG lResult = 0;
  1280. CLocation *pLocation = NULL;
  1281. CLocation *pNewLocation = NULL;
  1282. CAreaCodeRule *pAreaCodeRule = NULL;
  1283. CAreaCodeRule *pNewRule = NULL;
  1284. // Validate
  1285. if (!pszName || lstrlenW( pszName ) > MAXLEN_NAME)
  1286. return LINEERR_INVALPARAM;
  1287. // Read the current location
  1288. lResult = CreateCurrentLocationObject(&pLocation,0,0,0,0);
  1289. if(FAILED(lResult))
  1290. {
  1291. //lResult = lResult==E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_OPERATIONFAILED;
  1292. return lResult;
  1293. }
  1294. // Create the new object
  1295. pNewLocation = new CLocation();
  1296. if(pNewLocation==NULL)
  1297. {
  1298. delete pLocation;
  1299. LOG((TL_ERROR, "Cannot allocate a CLocation object"));
  1300. return LINEERR_NOMEM;
  1301. }
  1302. // Clone the location (w/o the ID)
  1303. lResult = pNewLocation->Initialize( pszName,
  1304. pLocation->GetAreaCode(),
  1305. pLocation->GetLongDistanceCarrierCode(),
  1306. pLocation->GetInternationalCarrierCode(),
  1307. pLocation->GetLongDistanceAccessCode(),
  1308. pLocation->GetLocalAccessCode(),
  1309. pLocation->GetDisableCallWaitingCode(),
  1310. 0,
  1311. pLocation->GetCountryID(),
  1312. pLocation->GetPreferredCardID(),
  1313. (pLocation->HasCallingCard() ? LOCATION_USECALLINGCARD : 0) |
  1314. (pLocation->HasCallWaiting() ? LOCATION_HASCALLWAITING : 0) |
  1315. (pLocation->HasToneDialing() ? LOCATION_USETONEDIALING : 0) ,
  1316. FALSE);
  1317. if(FAILED(lResult))
  1318. {
  1319. delete pLocation;
  1320. delete pNewLocation;
  1321. lResult = lResult==E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_OPERATIONFAILED;
  1322. return lResult;
  1323. }
  1324. // Set the ID
  1325. lResult = pNewLocation->NewID();
  1326. if(FAILED(lResult))
  1327. {
  1328. delete pLocation;
  1329. delete pNewLocation;
  1330. lResult = lResult==E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_OPERATIONFAILED;
  1331. return lResult;
  1332. }
  1333. // Copy the area code rules
  1334. pLocation->ResetRules();
  1335. while(S_OK == pLocation->NextRule(1, &pAreaCodeRule, NULL))
  1336. {
  1337. pNewRule = new CAreaCodeRule;
  1338. pNewRule->Initialize(pAreaCodeRule->GetAreaCode(),
  1339. pAreaCodeRule->GetNumberToDial(),
  1340. pAreaCodeRule->GetOptions(),
  1341. pAreaCodeRule->GetPrefixList(),
  1342. pAreaCodeRule->GetPrefixListSize()
  1343. );
  1344. pNewLocation->AddRule(pNewRule);
  1345. }
  1346. // Save the new location
  1347. lResult = pNewLocation->WriteToRegistry();
  1348. if(FAILED(lResult))
  1349. {
  1350. delete pLocation;
  1351. delete pNewLocation;
  1352. lResult = lResult==E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_OPERATIONFAILED;
  1353. return lResult;
  1354. }
  1355. delete pLocation;
  1356. delete pNewLocation;
  1357. return 0;
  1358. }
  1359. //***************************************************************************
  1360. extern "C"
  1361. DWORD APIENTRY
  1362. internalRemoveLocation(
  1363. IN DWORD dwID )
  1364. {
  1365. CLocations *pLocationList = NULL;
  1366. DWORD dwCurID;
  1367. HRESULT Result;
  1368. LOG((TL_TRACE, "Entering internalRemoveLocation"));
  1369. LOG((TL_INFO, " dwID=0x%d", dwID));
  1370. // Read the location list
  1371. pLocationList = new CLocations();
  1372. if(pLocationList==NULL)
  1373. {
  1374. LOG((TL_ERROR, "Cannot allocate a CLocations object"));
  1375. return LINEERR_NOMEM;
  1376. }
  1377. Result = pLocationList->Initialize();
  1378. if(FAILED(Result))
  1379. {
  1380. delete pLocationList;
  1381. LOG((TL_ERROR, "CLocations.Initialize() failed - HRESULT=0x%08lx", Result));
  1382. return Result == E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_INIFILECORRUPT;
  1383. }
  1384. // Cannot delete the last location
  1385. if(pLocationList->GetNumLocations() <2)
  1386. {
  1387. delete pLocationList;
  1388. return LINEERR_INVALPARAM;
  1389. }
  1390. // If we're deleting the current location make the first location the
  1391. // current location, or if we're deleting the first the second.
  1392. dwCurID = pLocationList->GetCurrentLocationID();
  1393. if(dwCurID==dwID)
  1394. {
  1395. CLocation *pLocation;
  1396. // find the first location
  1397. pLocationList->Reset();
  1398. pLocationList->Next(1, &pLocation, NULL);
  1399. // are we deleting the first
  1400. if(pLocation->GetLocationID()==dwID)
  1401. // try the second
  1402. pLocationList->Next(1, &pLocation, NULL);
  1403. // change the current location
  1404. pLocationList->SetCurrentLocationID(pLocation->GetLocationID());
  1405. }
  1406. // Delete the location
  1407. pLocationList->Remove(dwID);
  1408. // Save
  1409. Result = pLocationList->SaveToRegistry();
  1410. if(FAILED(Result))
  1411. {
  1412. delete pLocationList;
  1413. LOG((TL_ERROR, "CLocations.SaveToRegistry() failed - HRESULT=0x%08lx", Result));
  1414. return Result == E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_OPERATIONFAILED;
  1415. }
  1416. delete pLocationList;
  1417. return 0;
  1418. }
  1419. //***************************************************************************
  1420. extern "C"
  1421. DWORD APIENTRY
  1422. internalRenameLocationW(
  1423. IN WCHAR* pszOldName,
  1424. IN WCHAR* pszNewName )
  1425. {
  1426. CLocations *pLocationList;
  1427. CLocation *pLocation;
  1428. HRESULT Result;
  1429. DWORD dwError;
  1430. // Test the arguments
  1431. if(!pszOldName || !pszNewName || wcslen(pszNewName) > MAXLEN_NAME)
  1432. return LINEERR_INVALPARAM;
  1433. // Read the locations
  1434. pLocationList = new CLocations();
  1435. if(pLocationList==NULL)
  1436. {
  1437. LOG((TL_ERROR, "Cannot allocate a CLocations object"));
  1438. return LINEERR_NOMEM;
  1439. }
  1440. Result = pLocationList->Initialize();
  1441. if(FAILED(Result))
  1442. {
  1443. delete pLocationList;
  1444. LOG((TL_ERROR, "CLocations.Initialize() failed - HRESULT=0x%08lx", Result));
  1445. return Result == E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_INIFILECORRUPT;
  1446. }
  1447. // find the specified location
  1448. dwError = LINEERR_INVALPARAM; // skeptical approach
  1449. pLocationList->Reset();
  1450. while(pLocationList->Next(1, &pLocation, NULL)==S_OK)
  1451. {
  1452. if(wcscmp(pLocation->GetName(), pszOldName)==0)
  1453. {
  1454. // found it, change it
  1455. Result = pLocation->SetName(pszNewName);
  1456. if(FAILED(Result))
  1457. {
  1458. delete pLocationList;
  1459. LOG((TL_ERROR, "CLocations.SetName(Name) failed - HRESULT=0x%08lx", Result));
  1460. return Result == E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_OPERATIONFAILED;
  1461. }
  1462. // save
  1463. Result = pLocationList->SaveToRegistry();
  1464. if(FAILED(Result))
  1465. {
  1466. delete pLocationList;
  1467. LOG((TL_ERROR, "CLocations.SetName(Name) failed - HRESULT=0x%08lx", Result));
  1468. return Result == E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_OPERATIONFAILED;
  1469. }
  1470. dwError = 0;
  1471. break;
  1472. }
  1473. }
  1474. delete pLocationList;
  1475. return dwError;
  1476. }
  1477. #endif // !NORASPRIVATES
  1478. //***************************************************************************
  1479. //
  1480. // Helper functions
  1481. //
  1482. //***************************************************************************
  1483. LONG BreakupCanonicalW( PWSTR pAddressIn,
  1484. PWSTR *pCountry,
  1485. PWSTR *pCity,
  1486. PWSTR *pSubscriber
  1487. )
  1488. {
  1489. LONG lResult = 0;
  1490. PWSTR pCountryEnd;
  1491. PWSTR pAreaEnd;
  1492. //
  1493. // Get past any (illegal) leading spaces
  1494. //
  1495. while ( *pAddressIn == L' ' )
  1496. {
  1497. pAddressIn++;
  1498. }
  1499. //
  1500. // Leading zeros are very bad. Don't allow them.
  1501. // We're now at the first non-space. Better not be a '0'.
  1502. //
  1503. if ( *pAddressIn == L'0' )
  1504. {
  1505. //
  1506. // There are leading zeros!
  1507. //
  1508. LOG((TL_ERROR, " Canonical numbers are not allowed to have leading zeros"));
  1509. lResult = LINEERR_INVALADDRESS;
  1510. goto cleanup;
  1511. }
  1512. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1513. //
  1514. // Parse the canonical number into its component pieces
  1515. //
  1516. //
  1517. // Do country first
  1518. //
  1519. *pCountry = pAddressIn;
  1520. // At least one digit must be present
  1521. if(!(iswdigit(*pAddressIn)))
  1522. {
  1523. LOG((TL_ERROR, " Canonical numbers must have a valid country code"));
  1524. lResult = LINEERR_INVALADDRESS;
  1525. goto cleanup;
  1526. }
  1527. //
  1528. // Now get to past this
  1529. //
  1530. while (iswdigit(*pAddressIn) )
  1531. {
  1532. pAddressIn++;
  1533. }
  1534. // Save the end of the country code
  1535. pCountryEnd = pAddressIn;
  1536. //
  1537. // We hit something that's not a digit...
  1538. // There must be only one space here, but we allow any number of spaces (including none)
  1539. //
  1540. while (*pAddressIn == L' ')
  1541. {
  1542. pAddressIn++;
  1543. }
  1544. // Test the area code delimiter
  1545. if ( *pAddressIn == L'(')
  1546. {
  1547. pAddressIn++;
  1548. // Skip any illegal spaces
  1549. while (*pAddressIn == L' ')
  1550. {
  1551. pAddressIn++;
  1552. }
  1553. /*
  1554. // At least one digit must be present
  1555. if(!(iswdigit(*pAddressIn)))
  1556. {
  1557. LOG((TL_ERROR, TEXT(" Canonical numbers must have a valid area code between ()")));
  1558. lResult = LINEERR_INVALADDRESS;
  1559. goto cleanup;
  1560. }
  1561. */
  1562. //
  1563. // This must be the beginning of the area code
  1564. //
  1565. *pCity = pAddressIn;
  1566. //
  1567. // Now get to past this
  1568. //
  1569. while (iswdigit(*pAddressIn) )
  1570. {
  1571. pAddressIn++;
  1572. }
  1573. // Save the end pointer
  1574. pAreaEnd = pAddressIn;
  1575. // Skip any illegal spaces
  1576. while (*pAddressIn == L' ')
  1577. {
  1578. pAddressIn++;
  1579. }
  1580. if(*pAddressIn != L')')
  1581. {
  1582. LOG((TL_ERROR, " Canonical numbers must have a ')' after the area code"));
  1583. lResult = LINEERR_INVALADDRESS;
  1584. goto cleanup;
  1585. }
  1586. pAddressIn++;
  1587. *pAreaEnd = L'\0';
  1588. // Return the same NULL string for an empty area code
  1589. if(*pCity == pAreaEnd)
  1590. *pCity = NULL;
  1591. }
  1592. else
  1593. {
  1594. // there's no area code
  1595. *pCity = NULL;
  1596. }
  1597. // Skip spaces
  1598. while (*pAddressIn == L' ')
  1599. {
  1600. pAddressIn++;
  1601. }
  1602. *pCountryEnd = L'\0';
  1603. //
  1604. // Nothing left to do but put the icing on the cake
  1605. //
  1606. *pSubscriber = pAddressIn;
  1607. if (
  1608. TAPIIsBadStringPtrW( *pSubscriber, 512 )
  1609. ||
  1610. lstrlenW( *pSubscriber ) == 0
  1611. )
  1612. {
  1613. //
  1614. // Obviously not canonical
  1615. //
  1616. LOG((TL_ERROR, " Canonical numbers must have a subscriber number"));
  1617. lResult = LINEERR_INVALADDRESS;
  1618. goto cleanup;
  1619. }
  1620. cleanup:
  1621. return lResult;
  1622. }
  1623. static void LayDownString( PCWSTR pInString,
  1624. PBYTE pBuffer,
  1625. PBYTE *ppCurrentIndex,
  1626. PDWORD pPair, // this is the Len & Offset pair
  1627. BOOL bUnicode,
  1628. PBYTE pFirstByteAfter
  1629. )
  1630. {
  1631. #define LDS_FAST_BUF_SIZE 48
  1632. DWORD dwLength;
  1633. PSTR pTempString = NULL;
  1634. char achFastBuf[LDS_FAST_BUF_SIZE];
  1635. if(bUnicode)
  1636. {
  1637. dwLength = (lstrlenW( pInString ) + 1)*sizeof(WCHAR);
  1638. }
  1639. else
  1640. {
  1641. dwLength = WideCharToMultiByte(
  1642. GetACP(),
  1643. 0,
  1644. pInString,
  1645. -1,
  1646. NULL,
  1647. 0,
  1648. NULL,
  1649. NULL
  1650. );
  1651. if (dwLength == 0)
  1652. {
  1653. return;
  1654. }
  1655. }
  1656. // Make sure we're starting on some boundary
  1657. //
  1658. *ppCurrentIndex = (PBYTE) (((ULONG_PTR)( *ppCurrentIndex + TALIGN_COUNT)) & (~TALIGN_COUNT));
  1659. if(*ppCurrentIndex + dwLength <= pFirstByteAfter)
  1660. {
  1661. pPair[0] = dwLength;
  1662. pPair[1] = (DWORD)(*ppCurrentIndex - pBuffer);
  1663. if(bUnicode)
  1664. {
  1665. wcscpy( (PWSTR)*ppCurrentIndex, pInString );
  1666. }
  1667. else
  1668. {
  1669. //
  1670. // Get some space in which to convert Unicode to local
  1671. //
  1672. pTempString = (dwLength > LDS_FAST_BUF_SIZE ?
  1673. (PSTR)ClientAlloc (dwLength) : (PSTR) achFastBuf);
  1674. if ( !pTempString )
  1675. {
  1676. pPair[0] = 0;
  1677. pPair[1] = 0;
  1678. return;
  1679. }
  1680. WideCharToMultiByte(
  1681. GetACP(),
  1682. 0,
  1683. pInString,
  1684. -1,
  1685. pTempString,
  1686. dwLength,
  1687. NULL,
  1688. NULL
  1689. );
  1690. lstrcpyA( (PSTR)*ppCurrentIndex, pTempString );
  1691. if (pTempString != (PSTR) achFastBuf)
  1692. {
  1693. ClientFree (pTempString);
  1694. }
  1695. }
  1696. }
  1697. *ppCurrentIndex += dwLength;
  1698. }
  1699. static PWSTR CopyStringWithExpandJAndK(PWSTR pszRule, PWSTR pszAccessNr, PWSTR pszAccountNr)
  1700. {
  1701. DWORD dwLength=0;
  1702. PWSTR pResult = NULL;
  1703. PWCHAR pCrt, pOut;
  1704. WCHAR c;
  1705. DWORD dwAccessNrLen, dwAccountNrLen;
  1706. dwAccessNrLen = wcslen(pszAccessNr);
  1707. dwAccountNrLen = wcslen(pszAccountNr);
  1708. // Find the space to alloc
  1709. pCrt = pszRule;
  1710. while(*pCrt)
  1711. {
  1712. c = *pCrt++;
  1713. if(c == L'J' || c == L'j')
  1714. {
  1715. dwLength += dwAccessNrLen;
  1716. }
  1717. else if (c == L'K' || c == L'k')
  1718. {
  1719. dwLength += dwAccountNrLen;
  1720. }
  1721. else
  1722. dwLength++;
  1723. }
  1724. // WCHARs and NULL term
  1725. dwLength = (dwLength+1)*sizeof(WCHAR);
  1726. // Alloc
  1727. pResult = (PWSTR)ClientAlloc(dwLength); // allocates zeroed memory
  1728. if(pResult == NULL)
  1729. return NULL;
  1730. // Create result
  1731. pCrt = pszRule;
  1732. pOut = pResult;
  1733. while(*pCrt)
  1734. {
  1735. c = *pCrt++;
  1736. if(c == L'J' || c == L'j')
  1737. {
  1738. wcscat(pOut, pszAccessNr);
  1739. pOut += dwAccessNrLen;
  1740. }
  1741. else if (c == L'K' || c == L'k')
  1742. {
  1743. wcscat(pOut, pszAccountNr);
  1744. pOut += dwAccountNrLen;
  1745. }
  1746. else
  1747. *pOut++ = c;
  1748. }
  1749. return pResult;
  1750. }
  1751. static void LayDownTollList(CLocation *pLocation,
  1752. PBYTE pBuffer,
  1753. PBYTE *ppCurrentIndex,
  1754. PDWORD pPair,
  1755. BOOL bUnicode,
  1756. PBYTE pFirstByteAfter
  1757. )
  1758. {
  1759. DWORD dwLength;
  1760. DWORD dwTotalLength;
  1761. DWORD dwListLength;
  1762. PBYTE pDest;
  1763. AreaCodeRulePtrNode *pNode;
  1764. PWSTR pszLocationAreaCode;
  1765. DWORD dwCountryCode;
  1766. BOOL bFirst;
  1767. CAreaCodeRule *pRule;
  1768. DWORD dwIndex;
  1769. pszLocationAreaCode = pLocation->GetAreaCode();
  1770. dwCountryCode = pLocation->GetCountryCode();
  1771. // Make sure we're starting on some boundary
  1772. //
  1773. *ppCurrentIndex = (PBYTE) (((ULONG_PTR)( *ppCurrentIndex + TALIGN_COUNT )) & (~TALIGN_COUNT));
  1774. // Save the destination pointer
  1775. pDest = *ppCurrentIndex;
  1776. bFirst = TRUE;
  1777. dwTotalLength = 0;
  1778. // Only for US, Canada, Antigua etc.
  1779. if(pLocation->GetCountryCode() == 1)
  1780. {
  1781. // Find all rules which could be considered toll rules
  1782. pNode = pLocation->m_AreaCodeRuleList.head();
  1783. while( !pNode->beyond_tail() )
  1784. {
  1785. pRule = pNode->value();
  1786. if( IsATollListAreaCodeRule(pRule, pszLocationAreaCode))
  1787. {
  1788. // Get the size of the prefixes, in bytes
  1789. dwListLength = pRule->GetPrefixListSize();
  1790. if(bUnicode)
  1791. {
  1792. WCHAR *pCrt;
  1793. WCHAR *pOut;
  1794. // we strip the last two nulls
  1795. dwLength = dwListLength - 2*sizeof(WCHAR);
  1796. // if this is not the first rule, a comma should be added
  1797. if(!bFirst)
  1798. dwLength += sizeof(WCHAR);
  1799. dwTotalLength += dwLength;
  1800. // we have to convert the single nulls in commas
  1801. if(*ppCurrentIndex + dwLength <= pFirstByteAfter)
  1802. {
  1803. if(!bFirst)
  1804. {
  1805. *(WCHAR *)(*ppCurrentIndex) = L',';
  1806. *ppCurrentIndex += sizeof(WCHAR);
  1807. }
  1808. pCrt = pRule->GetPrefixList();
  1809. dwListLength /= sizeof(WCHAR);
  1810. dwListLength--;
  1811. dwListLength--;
  1812. // now dwListLength is the length in characters without the two ending nulls
  1813. // replace nulls with commas
  1814. for (dwIndex =0; dwIndex<dwListLength; dwIndex++)
  1815. {
  1816. if(*pCrt)
  1817. *(WCHAR *)(*ppCurrentIndex) = *pCrt;
  1818. else
  1819. *(WCHAR *)(*ppCurrentIndex) = L',';
  1820. pCrt++;
  1821. *ppCurrentIndex += sizeof(WCHAR);
  1822. }
  1823. }
  1824. }
  1825. else
  1826. {
  1827. WCHAR *pList;
  1828. dwListLength /= sizeof(WCHAR);
  1829. dwListLength--;
  1830. dwListLength--;
  1831. // now dwListLength is the length in characters without the two ending nulls
  1832. // Length needed
  1833. pList = pRule->GetPrefixList();
  1834. dwLength = WideCharToMultiByte(
  1835. GetACP(),
  1836. 0,
  1837. pList,
  1838. dwListLength,
  1839. NULL,
  1840. 0,
  1841. NULL,
  1842. NULL
  1843. );
  1844. // if this is not the first rule, a comma should be added
  1845. if(!bFirst)
  1846. dwLength+=sizeof(CHAR);
  1847. dwTotalLength += dwLength;
  1848. if(*ppCurrentIndex + dwLength <= pFirstByteAfter)
  1849. {
  1850. if(!bFirst)
  1851. {
  1852. *(CHAR *)(*ppCurrentIndex) = ',';
  1853. *ppCurrentIndex += sizeof(CHAR);
  1854. dwLength-=sizeof(CHAR); // temporary - the conversion and the null filling routines
  1855. // should'nt take into account the space for the separating comma
  1856. }
  1857. // convert
  1858. WideCharToMultiByte(GetACP(),
  1859. 0,
  1860. pList,
  1861. dwListLength,
  1862. (PSTR)(*ppCurrentIndex),
  1863. dwLength,
  1864. NULL,
  1865. NULL
  1866. );
  1867. // Replace inplace the nulls with commas
  1868. for (dwIndex =0; dwIndex<dwLength; dwIndex++)
  1869. {
  1870. if(*(CHAR *)(*ppCurrentIndex)=='\0')
  1871. *(CHAR *)(*ppCurrentIndex) = ',';
  1872. *ppCurrentIndex += sizeof(CHAR);
  1873. }
  1874. if(!bFirst)
  1875. dwLength+=sizeof(CHAR); // restore
  1876. }
  1877. }
  1878. bFirst = FALSE;
  1879. }
  1880. pNode = pNode->next();
  1881. }
  1882. }
  1883. // space for a terminating NULL
  1884. dwLength = bUnicode ? sizeof(WCHAR) : 1;
  1885. dwTotalLength += dwLength;
  1886. if(*ppCurrentIndex + dwLength <= pFirstByteAfter)
  1887. {
  1888. if(bUnicode)
  1889. *(WCHAR *)(*ppCurrentIndex) = L'\0';
  1890. else
  1891. *(CHAR *)(*ppCurrentIndex) = '\0';
  1892. *ppCurrentIndex += dwLength;
  1893. pPair[0] = (DWORD)(*ppCurrentIndex - pDest);
  1894. pPair[1] = (DWORD)(pDest - pBuffer);
  1895. }
  1896. // Update the current pointer whatever the buffer size is
  1897. *ppCurrentIndex = pDest + dwTotalLength;
  1898. }
  1899. static LONG
  1900. GetTranslateCapsCommon(
  1901. HLINEAPP hLineApp,
  1902. DWORD dwAPIVersion,
  1903. LPLINETRANSLATECAPS lpTranslateCaps,
  1904. BOOL bUnicode
  1905. )
  1906. {
  1907. LONG lResult = 0; // good for HRESULTs too
  1908. CLocations *pLocationList = NULL;
  1909. CCallingCards *pCardList = NULL;
  1910. DWORD dwNumLocations;
  1911. DWORD dwNumCards;
  1912. DWORD dwLenChar;
  1913. CCallingCard *pCard = NULL;
  1914. CLocation *pLocation;
  1915. DWORD dwTotalSize;
  1916. DWORD dwFinalSize;
  1917. DWORD dwLocationsSize;
  1918. DWORD dwLocationsStart;
  1919. DWORD dwCardsSize;
  1920. DWORD dwCardsStart;
  1921. DWORD dwCurrentLocationID;
  1922. DWORD dwPreferredCardID;
  1923. DWORD dwTempCardID;
  1924. BOOL bOldTapi;
  1925. BOOL bBufferTooSmall;
  1926. LINELOCATIONENTRY *pLineLocationEntry;
  1927. LINECARDENTRY *pLineCardEntry;
  1928. PBYTE pCurrentIndex;
  1929. PBYTE pCurrentIndexSave;
  1930. PBYTE pFirstByteAfter;
  1931. DWORD dwLocEntryLength;
  1932. DWORD dwCardEntryLength;
  1933. DWORD dwIndex;
  1934. DWORD dwAlignOffset;
  1935. PLOCATIONLIST pLocTest;
  1936. lResult = IsThisAPIVersionInvalid( dwAPIVersion );
  1937. if ( lResult )
  1938. {
  1939. LOG((TL_ERROR, "Bad dwAPIVersion - 0x%08lx", dwAPIVersion));
  1940. return lResult;
  1941. }
  1942. if ( IsBadWritePtr(lpTranslateCaps, sizeof(DWORD)*3) )
  1943. {
  1944. LOG((TL_ERROR, "lpTranslateCaps not a valid pointer"));
  1945. return LINEERR_INVALPOINTER;
  1946. }
  1947. if ( IsBadWritePtr(lpTranslateCaps, lpTranslateCaps->dwTotalSize) )
  1948. {
  1949. LOG((TL_ERROR, "lpTranslateCaps not a valid pointer (dwTotalSize)"));
  1950. return LINEERR_INVALPOINTER;
  1951. }
  1952. LOG((TL_INFO, "lpTranslateCaps->dwTotalSize = %d",lpTranslateCaps->dwTotalSize));
  1953. if ( lpTranslateCaps->dwTotalSize < sizeof(LINETRANSLATECAPS))
  1954. {
  1955. LOG((TL_ERROR, "Not even enough room for the fixed portion"));
  1956. return LINEERR_STRUCTURETOOSMALL;
  1957. }
  1958. // Let TAPISRV test the params for us
  1959. lResult = ReadLocations(&pLocTest,
  1960. hLineApp,
  1961. 0,
  1962. dwAPIVersion,
  1963. CHECKPARMS_DWHLINEAPP|
  1964. CHECKPARMS_DWAPIVERSION|
  1965. CHECKPARMS_ONLY);
  1966. if (pLocTest != NULL)
  1967. {
  1968. ClientFree( pLocTest);
  1969. }
  1970. if (lResult != ERROR_SUCCESS)
  1971. {
  1972. return lResult;
  1973. }
  1974. // Read the location list
  1975. pLocationList = new CLocations();
  1976. if(pLocationList==NULL)
  1977. {
  1978. LOG((TL_ERROR, "Cannot allocate a CLocations object"));
  1979. return LINEERR_NOMEM;
  1980. }
  1981. lResult = pLocationList->Initialize();
  1982. if(lResult != ERROR_SUCCESS)
  1983. {
  1984. delete pLocationList;
  1985. LOG((TL_ERROR, "CLocations.Initialize() failed - HRESULT=0x%08lx", lResult));
  1986. return lResult == E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_INIFILECORRUPT;
  1987. }
  1988. // Read the calling card list
  1989. pCardList = new CCallingCards();
  1990. if(pCardList==NULL)
  1991. {
  1992. delete pLocationList;
  1993. LOG((TL_ERROR, "Cannot allocate a CCallingCards object"));
  1994. return LINEERR_NOMEM;
  1995. }
  1996. lResult = pCardList->Initialize();
  1997. if(lResult != ERROR_SUCCESS)
  1998. {
  1999. delete pCardList;
  2000. delete pLocationList;
  2001. LOG((TL_ERROR, "CCallingCards.Initialize() failed - HRESULT=0x%08lx", lResult));
  2002. return lResult == E_OUTOFMEMORY ? LINEERR_NOMEM : LINEERR_OPERATIONFAILED;
  2003. }
  2004. // The char length in bytes depends on bUnicode
  2005. dwLenChar = bUnicode ? sizeof(WCHAR) : sizeof(CHAR);
  2006. // The structures for TAPI<=1.3 ar smaller
  2007. bOldTapi = (dwAPIVersion<0x00010004);
  2008. dwLocEntryLength = (DWORD)(bOldTapi ? 7*sizeof(DWORD) : sizeof(LINELOCATIONENTRY));
  2009. dwCardEntryLength = (DWORD)(bOldTapi ? 3*sizeof(DWORD) : sizeof(LINECARDENTRY));
  2010. dwNumLocations = pLocationList->GetNumLocations();
  2011. dwNumCards = pCardList->GetNumCards();
  2012. dwCurrentLocationID = pLocationList->GetCurrentLocationID();
  2013. dwPreferredCardID = 0;
  2014. // Size provided by the caller
  2015. dwTotalSize = lpTranslateCaps->dwTotalSize;
  2016. // First byte after the buffer provided by the caller
  2017. pFirstByteAfter = (PBYTE)lpTranslateCaps + dwTotalSize;
  2018. bBufferTooSmall = FALSE;
  2019. dwLocationsStart = sizeof(LINETRANSLATECAPS);
  2020. // The size of the locations part
  2021. dwLocationsSize = dwNumLocations * dwLocEntryLength;
  2022. // The strings included in locations are stored after the array of LINELOCATIONENTRY structures
  2023. pCurrentIndex = ((PBYTE)lpTranslateCaps)+
  2024. dwLocationsStart +
  2025. dwLocationsSize;
  2026. // do the first pointer alignment here. This initial offset will help at the end
  2027. pCurrentIndexSave = pCurrentIndex;
  2028. pCurrentIndex = (PBYTE) (((ULONG_PTR)( pCurrentIndex + TALIGN_COUNT )) & (~TALIGN_COUNT));
  2029. dwAlignOffset = (DWORD)(pCurrentIndex - pCurrentIndexSave);
  2030. // Test the space for the array
  2031. if(pCurrentIndex > pFirstByteAfter)
  2032. bBufferTooSmall = TRUE;
  2033. // First, process the locations
  2034. pLocationList->Reset();
  2035. dwIndex = 0;
  2036. while(S_OK==pLocationList->Next(1, &pLocation, NULL))
  2037. {
  2038. pLineLocationEntry = (LINELOCATIONENTRY *)(((PBYTE)lpTranslateCaps)+dwLocationsStart+dwIndex*dwLocEntryLength);
  2039. // string values
  2040. LayDownString( pLocation->GetName(),
  2041. (PBYTE)lpTranslateCaps,
  2042. &pCurrentIndex,
  2043. &pLineLocationEntry->dwLocationNameSize,
  2044. bUnicode,
  2045. pFirstByteAfter
  2046. );
  2047. LayDownString( pLocation->GetAreaCode(),
  2048. (PBYTE)lpTranslateCaps,
  2049. &pCurrentIndex,
  2050. &pLineLocationEntry->dwCityCodeSize,
  2051. bUnicode,
  2052. pFirstByteAfter
  2053. );
  2054. if(!bOldTapi)
  2055. {
  2056. LayDownString( pLocation->GetLocalAccessCode(),
  2057. (PBYTE)lpTranslateCaps,
  2058. &pCurrentIndex,
  2059. &pLineLocationEntry->dwLocalAccessCodeSize,
  2060. bUnicode,
  2061. pFirstByteAfter
  2062. );
  2063. LayDownString( pLocation->GetLongDistanceAccessCode(),
  2064. (PBYTE)lpTranslateCaps,
  2065. &pCurrentIndex,
  2066. &pLineLocationEntry->dwLongDistanceAccessCodeSize,
  2067. bUnicode,
  2068. pFirstByteAfter
  2069. );
  2070. // Toll list
  2071. LayDownTollList(pLocation,
  2072. (PBYTE)lpTranslateCaps,
  2073. &pCurrentIndex,
  2074. &pLineLocationEntry->dwTollPrefixListSize,
  2075. bUnicode,
  2076. pFirstByteAfter
  2077. );
  2078. LayDownString( pLocation->GetDisableCallWaitingCode(),
  2079. (PBYTE)lpTranslateCaps,
  2080. &pCurrentIndex,
  2081. &pLineLocationEntry->dwCancelCallWaitingSize,
  2082. bUnicode,
  2083. pFirstByteAfter
  2084. );
  2085. }
  2086. if(pLocation->HasCallingCard())
  2087. {
  2088. dwTempCardID = pLocation->GetPreferredCardID();
  2089. // Extract the preferred calling card if current location
  2090. if(pLocation->GetLocationID() == dwCurrentLocationID)
  2091. dwPreferredCardID = dwTempCardID;
  2092. }
  2093. else
  2094. dwTempCardID =0;
  2095. //Other non string values
  2096. if(!bBufferTooSmall)
  2097. {
  2098. pLineLocationEntry->dwPermanentLocationID = pLocation->GetLocationID();
  2099. pLineLocationEntry->dwPreferredCardID = dwTempCardID;
  2100. pLineLocationEntry->dwCountryCode = pLocation->GetCountryCode();
  2101. if(!bOldTapi)
  2102. {
  2103. pLineLocationEntry->dwCountryID = pLocation->GetCountryID();
  2104. pLineLocationEntry->dwOptions = pLocation->HasToneDialing() ? 0 : LINELOCATIONOPTION_PULSEDIAL;
  2105. }
  2106. }
  2107. dwIndex++;
  2108. }
  2109. // Align the pointer
  2110. pCurrentIndex = (PBYTE) (((ULONG_PTR)( pCurrentIndex + TALIGN_COUNT )) & (~TALIGN_COUNT));
  2111. // Process the cards
  2112. dwCardsStart = (DWORD)(pCurrentIndex - ((PBYTE)lpTranslateCaps));
  2113. // The size of the cards part
  2114. dwCardsSize = dwCardEntryLength * dwNumCards;
  2115. pCurrentIndex += dwCardsSize;
  2116. // Test the space for the array
  2117. if(pCurrentIndex > pFirstByteAfter)
  2118. bBufferTooSmall = TRUE;
  2119. // including the hidden cards
  2120. pCardList->Reset(TRUE);
  2121. dwIndex = 0;
  2122. while(S_OK==pCardList->Next(1, &pCard, NULL))
  2123. {
  2124. PWSTR pszTemp = NULL;
  2125. pLineCardEntry = (LINECARDENTRY *)(((PBYTE)lpTranslateCaps)+dwCardsStart+dwIndex*dwCardEntryLength);
  2126. // String values
  2127. LayDownString( pCard->GetCardName(),
  2128. (PBYTE)lpTranslateCaps,
  2129. &pCurrentIndex,
  2130. &pLineCardEntry->dwCardNameSize,
  2131. bUnicode,
  2132. pFirstByteAfter
  2133. );
  2134. if(!bOldTapi)
  2135. {
  2136. // Convert rules to old format (w/o J and K spec)
  2137. pszTemp = CopyStringWithExpandJAndK(pCard->GetLocalRule(),
  2138. pCard->GetLocalAccessNumber(),
  2139. pCard->GetAccountNumber());
  2140. if(pszTemp==NULL)
  2141. {
  2142. delete pCardList;
  2143. delete pLocationList;
  2144. LOG((TL_ERROR, "CopyStringWithExpandJAndK failed to allocate memory"));
  2145. return LINEERR_NOMEM;
  2146. }
  2147. LayDownString( pszTemp,
  2148. (PBYTE)lpTranslateCaps,
  2149. &pCurrentIndex,
  2150. &pLineCardEntry->dwSameAreaRuleSize,
  2151. bUnicode,
  2152. pFirstByteAfter
  2153. );
  2154. ClientFree(pszTemp);
  2155. LOG((TL_INFO, "About to do CopyStringWithExpandJAndK"));
  2156. pszTemp = CopyStringWithExpandJAndK( pCard->GetLongDistanceRule(),
  2157. pCard->GetLongDistanceAccessNumber(),
  2158. pCard->GetAccountNumber() );
  2159. LOG((TL_INFO, "Did CopyStringWithExpandJAndK"));
  2160. if(pszTemp==NULL)
  2161. {
  2162. delete pCardList;
  2163. delete pLocationList;
  2164. LOG((TL_ERROR, "CopyStringWithExpandJAndK failed to allocate memory"));
  2165. return LINEERR_NOMEM;
  2166. }
  2167. LayDownString( pszTemp,
  2168. (PBYTE)lpTranslateCaps,
  2169. &pCurrentIndex,
  2170. &pLineCardEntry->dwLongDistanceRuleSize,
  2171. bUnicode,
  2172. pFirstByteAfter
  2173. );
  2174. ClientFree(pszTemp);
  2175. pszTemp = CopyStringWithExpandJAndK(pCard->GetInternationalRule(),
  2176. pCard->GetInternationalAccessNumber(),
  2177. pCard->GetAccountNumber());
  2178. if(pszTemp==NULL)
  2179. {
  2180. delete pCardList;
  2181. delete pLocationList;
  2182. LOG((TL_ERROR, "CopyStringWithExpandJAndK failed to allocate memory"));
  2183. return LINEERR_NOMEM;
  2184. }
  2185. LayDownString( pszTemp,
  2186. (PBYTE)lpTranslateCaps,
  2187. &pCurrentIndex,
  2188. &pLineCardEntry->dwInternationalRuleSize,
  2189. bUnicode,
  2190. pFirstByteAfter
  2191. );
  2192. ClientFree(pszTemp);
  2193. }
  2194. // Other non-string fields
  2195. if(!bBufferTooSmall)
  2196. {
  2197. pLineCardEntry->dwPermanentCardID = pCard->GetCardID();
  2198. if(!bOldTapi)
  2199. {
  2200. pLineCardEntry->dwCardNumberDigits = wcslen(pCard->GetPIN());
  2201. pLineCardEntry->dwOptions = (pCard->IsMarkedPermanent() ? LINECARDOPTION_PREDEFINED : 0)
  2202. | (pCard->IsMarkedHidden() ? LINECARDOPTION_HIDDEN : 0);
  2203. }
  2204. }
  2205. dwIndex++;
  2206. }
  2207. dwFinalSize = (DWORD)(pCurrentIndex - (PBYTE)lpTranslateCaps);
  2208. // Uhh, the goal is to have the same needed size whatever the alignment of the lpTranslateCaps is..
  2209. // A nongoal is to provide similar returned content (in terms of alignments, pads etc) for
  2210. // different alignment of lpTranslateCaps
  2211. //
  2212. dwFinalSize += (TALIGN_COUNT - dwAlignOffset);
  2213. if(dwFinalSize>dwTotalSize)
  2214. {
  2215. lpTranslateCaps->dwUsedSize = sizeof (LINETRANSLATECAPS);
  2216. // Fix for alignment problems
  2217. lpTranslateCaps->dwNeededSize = dwFinalSize;
  2218. ZeroMemory(
  2219. &lpTranslateCaps->dwNumLocations,
  2220. dwTotalSize - 3 * sizeof (DWORD)
  2221. );
  2222. lpTranslateCaps->dwCurrentLocationID = dwCurrentLocationID;
  2223. lpTranslateCaps->dwCurrentPreferredCardID = dwPreferredCardID;
  2224. LOG((TL_ERROR, "Buffer too small"));
  2225. LOG((TL_ERROR, "lpTranslateCaps->dwTotalSize = %d",lpTranslateCaps->dwTotalSize));
  2226. LOG((TL_ERROR, "lpTranslateCaps->dwNeededSize = %d",lpTranslateCaps->dwNeededSize));
  2227. }
  2228. else
  2229. {
  2230. lpTranslateCaps->dwUsedSize = dwFinalSize;
  2231. lpTranslateCaps->dwNeededSize = dwFinalSize;
  2232. lpTranslateCaps->dwNumLocations = dwNumLocations;
  2233. lpTranslateCaps->dwNumCards = dwNumCards;
  2234. lpTranslateCaps->dwCurrentLocationID = dwCurrentLocationID;
  2235. lpTranslateCaps->dwLocationListOffset = dwLocationsStart;
  2236. lpTranslateCaps->dwLocationListSize = dwLocationsSize;
  2237. lpTranslateCaps->dwCardListOffset = dwCardsStart;
  2238. lpTranslateCaps->dwCardListSize = dwCardsSize;
  2239. lpTranslateCaps->dwCurrentPreferredCardID = dwPreferredCardID;
  2240. LOG((TL_INFO, "Buffer OK"));
  2241. LOG((TL_INFO, "lpTranslateCaps->dwTotalSize = %d",lpTranslateCaps->dwTotalSize));
  2242. LOG((TL_INFO, "lpTranslateCaps->dwNeededSize = %d",lpTranslateCaps->dwNeededSize));
  2243. }
  2244. delete pCardList;
  2245. delete pLocationList;
  2246. return 0;
  2247. }
  2248. static BOOL FindTollPrefixInLocation(CLocation *pLocation,
  2249. PWSTR pPrefix,
  2250. CAreaCodeRule **ppRule,
  2251. PWSTR *ppWhere)
  2252. {
  2253. BOOL bPrefixFound = FALSE;
  2254. AreaCodeRulePtrNode *pNode;
  2255. CAreaCodeRule *pCrtRule = NULL;
  2256. PWSTR pLocationAreaCode;
  2257. PWSTR pWhere;
  2258. pLocationAreaCode = pLocation->GetAreaCode();
  2259. // Enumerate the area code rules
  2260. // If a rule is appropriate for a toll list, we search the prefix
  2261. pNode = pLocation->m_AreaCodeRuleList.head();
  2262. while( !pNode->beyond_tail() )
  2263. {
  2264. pCrtRule = pNode->value();
  2265. if(IsATollListAreaCodeRule(pCrtRule, pLocationAreaCode))
  2266. {
  2267. // Set this even we don't find the prefix.
  2268. // The caller could be interested in the presence of toll rules
  2269. *ppRule = pCrtRule;
  2270. // Try to find the prefix
  2271. pWhere = FindPrefixInMultiSZ(pCrtRule->GetPrefixList(), pPrefix);
  2272. if(pWhere)
  2273. {
  2274. *ppWhere = pWhere;
  2275. return TRUE;
  2276. }
  2277. }
  2278. pNode = pNode->next();
  2279. }
  2280. return FALSE;
  2281. }
  2282. static BOOL IsATollListAreaCodeRule(CAreaCodeRule *pRule, PWSTR pszLocationAreaCode)
  2283. {
  2284. // conditions for toll rules:
  2285. //
  2286. // location.Country code == 1 (to be tested outside) AND
  2287. // Area Code to dial == Current Area Code AND
  2288. // NumberToDial == 1 AND
  2289. // BeforeDialingDialNumberToDial == TRUE AND
  2290. // BeforeDialingDialAreaCode == TRUE AND
  2291. // IncludeAllPrefixesForThisAreaCode == FALSE
  2292. return pRule->HasDialNumber()
  2293. && !pRule->HasAppliesToAllPrefixes()
  2294. && pRule->HasDialAreaCode()
  2295. && 0==wcscmp(pszLocationAreaCode, pRule->GetAreaCode())
  2296. && 0==wcscmp(pRule->GetNumberToDial(), L"1")
  2297. ;
  2298. }
  2299. static PWSTR FindPrefixInMultiSZ(PWSTR pPrefixList, PWSTR pPrefix)
  2300. {
  2301. PWSTR pCrt;
  2302. PWSTR pListCrt;
  2303. PWSTR pStart;
  2304. pListCrt = pPrefixList;
  2305. while(TRUE)
  2306. {
  2307. pCrt = pPrefix;
  2308. pStart = pListCrt;
  2309. while(*pCrt == *pListCrt)
  2310. {
  2311. if(!*pCrt)
  2312. // found
  2313. return pStart;
  2314. pCrt++;
  2315. pListCrt++;
  2316. }
  2317. while(*pListCrt++);
  2318. if(!*pListCrt)
  2319. // not found
  2320. return NULL;
  2321. }
  2322. }
  2323. /****************************************************************************
  2324. Function : CreateCurrentLocationObject
  2325. ****************************************************************************/
  2326. LONG CreateCurrentLocationObject(CLocation **pLocation,
  2327. HLINEAPP hLineApp,
  2328. DWORD dwDeviceID,
  2329. DWORD dwAPIVersion,
  2330. DWORD dwOptions)
  2331. {
  2332. PLOCATIONLIST pLocationList = NULL;
  2333. PLOCATION pEntry = NULL;
  2334. PWSTR pszLocationName = NULL;
  2335. PWSTR pszAreaCode = NULL;
  2336. PWSTR pszLongDistanceCarrierCode = NULL;
  2337. PWSTR pszInternationalCarrierCode = NULL;
  2338. PWSTR pszLocalAccessCode = NULL;
  2339. PWSTR pszLongDistanceAccessCode = NULL;
  2340. PWSTR pszCancelCallWaitingCode = NULL;
  2341. DWORD dwPermanentLocationID = 0;
  2342. CLocation * pNewLocation = NULL;
  2343. PAREACODERULE pAreaCodeRuleEntry = NULL;
  2344. PWSTR pszNumberToDial = NULL;
  2345. PWSTR pszzPrefixesList = NULL;
  2346. DWORD dwNumRules = 0;
  2347. CAreaCodeRule * pAreaCodeRule = NULL;
  2348. DWORD dwCount = 0;
  2349. DWORD dwNumEntries = 0;
  2350. DWORD dwCurrentLocationID = 0;
  2351. HRESULT hr;
  2352. // Let TAPISRV test the params for us
  2353. hr = ReadLocations(&pLocationList,
  2354. hLineApp,
  2355. dwDeviceID,
  2356. dwAPIVersion,
  2357. dwOptions
  2358. );
  2359. if SUCCEEDED( hr)
  2360. {
  2361. hr = E_FAIL; // fail if we don't find the current loc
  2362. // current location
  2363. dwCurrentLocationID = pLocationList->dwCurrentLocationID;
  2364. // Find position of 1st LOCATION structure in the LOCATIONLIST structure
  2365. pEntry = (PLOCATION) ((BYTE*)(pLocationList) + pLocationList->dwLocationListOffset );
  2366. // Number of locations ?
  2367. dwNumEntries = pLocationList->dwNumLocationsInList;
  2368. // Find the current location
  2369. for (dwCount = 0; dwCount < dwNumEntries ; dwCount++)
  2370. {
  2371. if(pEntry->dwPermanentLocationID == dwCurrentLocationID)
  2372. {
  2373. hr = S_OK;
  2374. break;
  2375. }
  2376. // Try next location in list
  2377. //pEntry++;
  2378. pEntry = (PLOCATION) ((BYTE*)(pEntry) + pEntry->dwUsedSize);
  2379. }
  2380. if SUCCEEDED( hr)
  2381. {
  2382. LOG((TL_INFO, "CreateCurrentLocationObject - current location found %d",
  2383. dwCurrentLocationID));
  2384. // Pull Location Info out of LOCATION structure
  2385. pszLocationName = (PWSTR) ((BYTE*)(pEntry)
  2386. + pEntry->dwLocationNameOffset);
  2387. pszAreaCode = (PWSTR) ((BYTE*)(pEntry)
  2388. + pEntry->dwAreaCodeOffset);
  2389. pszLongDistanceCarrierCode= (PWSTR) ((BYTE*)(pEntry)
  2390. + pEntry->dwLongDistanceCarrierCodeOffset);
  2391. pszInternationalCarrierCode= (PWSTR) ((BYTE*)(pEntry)
  2392. + pEntry->dwInternationalCarrierCodeOffset);
  2393. pszLocalAccessCode = (PWSTR) ((BYTE*)(pEntry)
  2394. + pEntry->dwLocalAccessCodeOffset);
  2395. pszLongDistanceAccessCode = (PWSTR) ((BYTE*)(pEntry)
  2396. + pEntry->dwLongDistanceAccessCodeOffset);
  2397. pszCancelCallWaitingCode = (PWSTR) ((BYTE*)(pEntry)
  2398. + pEntry->dwCancelCallWaitingOffset);
  2399. // create our new Location Object
  2400. pNewLocation = new CLocation;
  2401. if (pNewLocation)
  2402. {
  2403. // initialize the new Location Object
  2404. hr = pNewLocation->Initialize(
  2405. pszLocationName,
  2406. pszAreaCode,
  2407. pszLongDistanceCarrierCode,
  2408. pszInternationalCarrierCode,
  2409. pszLongDistanceAccessCode,
  2410. pszLocalAccessCode,
  2411. pszCancelCallWaitingCode ,
  2412. pEntry->dwPermanentLocationID,
  2413. pEntry->dwCountryID,
  2414. pEntry->dwPreferredCardID,
  2415. pEntry->dwOptions
  2416. );
  2417. if( SUCCEEDED(hr) )
  2418. {
  2419. // Find position of 1st AREACODERULE structure in the LOCATIONLIST structure
  2420. pAreaCodeRuleEntry = (PAREACODERULE) ((BYTE*)(pEntry)
  2421. + pEntry->dwAreaCodeRulesListOffset );
  2422. dwNumRules = pEntry->dwNumAreaCodeRules;
  2423. for (dwCount = 0; dwCount != dwNumRules; dwCount++)
  2424. {
  2425. // Pull Rule Info out of AREACODERULE structure
  2426. pszAreaCode = (PWSTR) ((BYTE*)(pEntry)
  2427. + pAreaCodeRuleEntry->dwAreaCodeOffset);
  2428. pszNumberToDial = (PWSTR) ((BYTE*)(pEntry)
  2429. + pAreaCodeRuleEntry->dwNumberToDialOffset);
  2430. pszzPrefixesList = (PWSTR) ((BYTE*)(pEntry)
  2431. + pAreaCodeRuleEntry->dwPrefixesListOffset);
  2432. // create our new AreaCodeRule Object
  2433. pAreaCodeRule = new CAreaCodeRule;
  2434. if (pAreaCodeRule)
  2435. {
  2436. // initialize the new AreaCodeRule Object
  2437. hr = pAreaCodeRule->Initialize ( pszAreaCode,
  2438. pszNumberToDial,
  2439. pAreaCodeRuleEntry->dwOptions,
  2440. pszzPrefixesList,
  2441. pAreaCodeRuleEntry->dwPrefixesListSize
  2442. );
  2443. if( SUCCEEDED(hr) )
  2444. {
  2445. pNewLocation->AddRule(pAreaCodeRule);
  2446. }
  2447. else // rule initialization failed
  2448. {
  2449. delete pAreaCodeRule;
  2450. LOG((TL_ERROR, "CreateCurrentLocationObject - rule create failed"));
  2451. }
  2452. }
  2453. else // new CAreaCodeRule failed
  2454. {
  2455. LOG((TL_ERROR, "CreateCurrentLocationObject - rule create failed"));
  2456. }
  2457. // Try next rule in list
  2458. pAreaCodeRuleEntry++;
  2459. }
  2460. }
  2461. else // location initialize failed
  2462. {
  2463. delete pNewLocation;
  2464. pNewLocation = NULL;
  2465. LOG((TL_ERROR, "CreateCurrentLocationObject - location create failed"));
  2466. hr =LINEERR_OPERATIONFAILED;
  2467. // hr = E_FAIL;
  2468. }
  2469. }
  2470. else // new CLocation failed
  2471. {
  2472. LOG((TL_ERROR, "CreateCurrentLocationObject - location create failed"));
  2473. hr = LINEERR_NOMEM;
  2474. //hr = E_OUTOFMEMORY;
  2475. }
  2476. }
  2477. else
  2478. {
  2479. LOG((TL_ERROR, "CreateCurrentLocationObject - current location not found"));
  2480. hr =LINEERR_OPERATIONFAILED;
  2481. //hr = E_FAIL;
  2482. }
  2483. }
  2484. else // ReadLocations failed
  2485. {
  2486. LOG((TL_ERROR, "CreateCurrentLocationObject - ReadLocation create failed"));
  2487. // hr = E_FAIL;
  2488. }
  2489. // finished with TAPI memory block so release
  2490. if ( pLocationList != NULL )
  2491. ClientFree( pLocationList );
  2492. *pLocation = pNewLocation;
  2493. return hr;
  2494. }
  2495. /****************************************************************************
  2496. Function : CreateCountryObject
  2497. ****************************************************************************/
  2498. HRESULT CreateCountryObject(DWORD dwCountryID, CCountry **ppCountry)
  2499. {
  2500. LPLINECOUNTRYLIST_INTERNAL pCountryList = NULL;
  2501. LPLINECOUNTRYENTRY_INTERNAL pEntry = NULL;
  2502. PWSTR pszCountryName = NULL;
  2503. PWSTR pszInternationalRule = NULL;
  2504. PWSTR pszLongDistanceRule = NULL;
  2505. PWSTR pszLocalRule = NULL;
  2506. CCountry * pCountry = NULL;
  2507. DWORD dwCount = 0;
  2508. DWORD dwNumEntries = 0;
  2509. LONG lResult;
  2510. HRESULT hr;
  2511. lResult = ReadCountriesAndGroups( &pCountryList, dwCountryID, 0);
  2512. if (lResult == 0)
  2513. {
  2514. // Find position of 1st LINECOUNTRYENTRY structure in the LINECOUNTRYLIST structure
  2515. pEntry = (LPLINECOUNTRYENTRY_INTERNAL) ((BYTE*)(pCountryList) + pCountryList->dwCountryListOffset );
  2516. // Pull Country Info out of LINECOUNTRYENTRY structure
  2517. pszCountryName = (PWSTR) ((BYTE*)(pCountryList)
  2518. + pEntry->dwCountryNameOffset);
  2519. pszInternationalRule = (PWSTR) ((BYTE*)(pCountryList)
  2520. + pEntry->dwInternationalRuleOffset);
  2521. pszLongDistanceRule = (PWSTR) ((BYTE*)(pCountryList)
  2522. + pEntry->dwLongDistanceRuleOffset);
  2523. pszLocalRule = (PWSTR) ((BYTE*)(pCountryList)
  2524. + pEntry->dwSameAreaRuleOffset);
  2525. // create our new CCountry Object
  2526. pCountry = new CCountry;
  2527. if (pCountry)
  2528. {
  2529. // initialize the new CCountry Object
  2530. hr = pCountry->Initialize(pEntry->dwCountryID,
  2531. pEntry->dwCountryCode,
  2532. pEntry->dwCountryGroup,
  2533. pszCountryName,
  2534. pszInternationalRule,
  2535. pszLongDistanceRule,
  2536. pszLocalRule
  2537. );
  2538. if( SUCCEEDED(hr) )
  2539. {
  2540. *ppCountry = pCountry;
  2541. }
  2542. else // country initialization failed
  2543. {
  2544. delete pCountry;
  2545. LOG((TL_ERROR, "CreateCountryObject - country create failed"));
  2546. }
  2547. }
  2548. else // new CCountry failed
  2549. {
  2550. LOG((TL_ERROR, "CreateCountryObject - country create failed"));
  2551. }
  2552. }
  2553. else // ReadLocations failed
  2554. {
  2555. LOG((TL_ERROR, "CreateCountryObject - ReadCountries failed"));
  2556. hr = E_FAIL;
  2557. }
  2558. // finished with TAPI memory block so release
  2559. if ( pCountryList != NULL )
  2560. {
  2561. ClientFree( pCountryList );
  2562. }
  2563. return hr;
  2564. }
  2565. /****************************************************************************
  2566. Function : ReadLocations
  2567. ****************************************************************************/
  2568. HRESULT ReadLocations( PLOCATIONLIST *ppLocationList,
  2569. HLINEAPP hLineApp,
  2570. DWORD dwDeviceID,
  2571. DWORD dwAPIVersion,
  2572. DWORD dwOptions
  2573. )
  2574. {
  2575. HRESULT hr = S_OK;
  2576. long lResult;
  2577. DWORD dwSize = sizeof(LOCATIONLIST) + 500;
  2578. *ppLocationList = (PLOCATIONLIST) ClientAlloc( dwSize );
  2579. if (NULL == *ppLocationList)
  2580. {
  2581. return E_OUTOFMEMORY;
  2582. }
  2583. (*ppLocationList)->dwTotalSize = dwSize;
  2584. FUNC_ARGS funcArgs =
  2585. {
  2586. MAKELONG (LINE_FUNC | SYNC | 5, tReadLocations),
  2587. {
  2588. (ULONG_PTR)hLineApp,
  2589. (ULONG_PTR)dwDeviceID,
  2590. (ULONG_PTR)dwAPIVersion,
  2591. (ULONG_PTR)dwOptions,
  2592. (ULONG_PTR)*ppLocationList // (DWORD) pLocationSpace
  2593. },
  2594. {
  2595. hXxxApp_NULLOK,
  2596. Dword,
  2597. Dword,
  2598. Dword,
  2599. lpGet_Struct
  2600. }
  2601. };
  2602. while (TRUE)
  2603. {
  2604. lResult = (DOFUNC (&funcArgs, "TReadLocations"));
  2605. if ((lResult == 0) && ((*ppLocationList)->dwNeededSize > (*ppLocationList)->dwTotalSize))
  2606. {
  2607. // Didn't Work , adjust buffer size & try again
  2608. LOG((TL_ERROR, "ReadLocations failed - buffer too small"));
  2609. dwSize = (*ppLocationList)->dwNeededSize;
  2610. ClientFree( *ppLocationList );
  2611. *ppLocationList = (PLOCATIONLIST) ClientAlloc( dwSize );
  2612. if (*ppLocationList == NULL)
  2613. {
  2614. LOG((TL_ERROR, "ReadLocations failed - repeat ClientAlloc failed"));
  2615. hr = E_OUTOFMEMORY;
  2616. break;
  2617. }
  2618. else
  2619. {
  2620. (*ppLocationList)->dwTotalSize = dwSize;
  2621. funcArgs.Args[4] = (ULONG_PTR)*ppLocationList;
  2622. }
  2623. }
  2624. else
  2625. {
  2626. hr = (HRESULT)lResult;
  2627. break;
  2628. }
  2629. } // end while(TRUE)
  2630. return hr;
  2631. }
  2632. /****************************************************************************
  2633. Function : WriteLocations
  2634. ****************************************************************************/
  2635. LONG PASCAL WriteLocations( PLOCATIONLIST pLocationList,
  2636. DWORD dwChangedFlags
  2637. )
  2638. {
  2639. PSTR pString;
  2640. UINT n;
  2641. LONG lResult;
  2642. FUNC_ARGS funcArgs =
  2643. {
  2644. MAKELONG (LINE_FUNC | SYNC | 4, tWriteLocations),
  2645. {
  2646. (ULONG_PTR)pLocationList->dwNumLocationsInList,
  2647. (ULONG_PTR)dwChangedFlags,
  2648. (ULONG_PTR)pLocationList->dwCurrentLocationID,
  2649. (ULONG_PTR)pLocationList
  2650. },
  2651. {
  2652. Dword,
  2653. Dword,
  2654. Dword,
  2655. lpSet_Struct
  2656. }
  2657. };
  2658. lResult = (DOFUNC (&funcArgs, "TWriteLocations"));
  2659. return lResult;
  2660. }
  2661. /****************************************************************************
  2662. Function : ReadCountries
  2663. ****************************************************************************/
  2664. LONG PASCAL ReadCountries( LPLINECOUNTRYLIST *ppLCL,
  2665. UINT nCountryID,
  2666. DWORD dwDestCountryID
  2667. )
  2668. {
  2669. LONG lTapiResult;
  2670. UINT nBufSize = 0x8000; //Start with a buffer of 16K
  2671. UINT n;
  2672. LPLINECOUNTRYLIST pNewLCL;
  2673. FUNC_ARGS funcArgs =
  2674. {
  2675. MAKELONG (LINE_FUNC | SYNC | 4, lGetCountry),
  2676. {
  2677. 0,
  2678. TAPI_VERSION_CURRENT,
  2679. (ULONG_PTR)dwDestCountryID,
  2680. 0
  2681. },
  2682. {
  2683. Dword,
  2684. Dword,
  2685. Dword,
  2686. lpGet_Struct
  2687. }
  2688. };
  2689. //
  2690. // Try until success or the buffer is huge
  2691. //
  2692. for ( lTapiResult = 1, n = 0;
  2693. lTapiResult && (n < 5);
  2694. n++ )
  2695. {
  2696. pNewLCL = (LPLINECOUNTRYLIST)ClientAlloc( nBufSize );
  2697. if(!pNewLCL)
  2698. return LINEERR_NOMEM;
  2699. pNewLCL->dwTotalSize = nBufSize;
  2700. //
  2701. // Put new values in structure for TAPISRV
  2702. //
  2703. funcArgs.Args[0] = (ULONG_PTR)nCountryID;
  2704. funcArgs.Args[3] = (ULONG_PTR)pNewLCL;
  2705. //
  2706. // Call TAPISRV to get the country list
  2707. //
  2708. lTapiResult = DOFUNC (&funcArgs, "lineGetCountry");
  2709. //
  2710. // If the call succeeded, but the buffer was too small, or if the
  2711. // call failed, do it again...
  2712. //
  2713. if (
  2714. (lTapiResult == LINEERR_STRUCTURETOOSMALL)
  2715. ||
  2716. (pNewLCL->dwNeededSize > nBufSize)
  2717. )
  2718. {
  2719. //
  2720. // Complain to anyone who'll listen that this should be tuned
  2721. // to start with a larger buffer so we don't have to do this multiple
  2722. // times....
  2723. //
  2724. LOG((TL_ERROR, " TUNING PROBLEM: We're about to call lineGetCountry()"));
  2725. LOG((TL_ERROR, " _again_ because the buffer wasn't big enough"));
  2726. LOG((TL_ERROR, " the last time. FIX THIS!!! (0x%lx)", nBufSize));
  2727. lTapiResult = 1; // Force error condition if size was bad...
  2728. nBufSize += 0x4000; // Try a bit bigger
  2729. ClientFree( pNewLCL );
  2730. }
  2731. else
  2732. {
  2733. //
  2734. // We didn't work for some other reason
  2735. //
  2736. break;
  2737. }
  2738. }
  2739. *ppLCL = pNewLCL;
  2740. return lTapiResult;
  2741. }
  2742. /****************************************************************************
  2743. Function : ReadCountriesAndGroups
  2744. ****************************************************************************/
  2745. LONG PASCAL ReadCountriesAndGroups( LPLINECOUNTRYLIST_INTERNAL *ppLCL,
  2746. UINT nCountryID,
  2747. DWORD dwDestCountryID
  2748. )
  2749. {
  2750. LPLINECOUNTRYLIST_INTERNAL pLCL = NULL;
  2751. LPLINECOUNTRYENTRY_INTERNAL pLCountry;
  2752. LONG lResult;
  2753. LPDWORD pCountryIDs;
  2754. FUNC_ARGS funcArgs =
  2755. {
  2756. MAKELONG (LINE_FUNC | SYNC | 4, lGetCountryGroup),
  2757. {
  2758. (ULONG_PTR) 0,
  2759. (ULONG_PTR) 0,
  2760. (ULONG_PTR) 0,
  2761. (ULONG_PTR) 0
  2762. },
  2763. {
  2764. lpSet_SizeToFollow,
  2765. Size,
  2766. lpGet_SizeToFollow,
  2767. Size
  2768. }
  2769. };
  2770. //
  2771. // read the countries
  2772. //
  2773. lResult = ReadCountries( (LPLINECOUNTRYLIST *)&pLCL, nCountryID, dwDestCountryID );
  2774. if (lResult)
  2775. {
  2776. LOG((TL_ERROR, "ReadCountriesAndGroups: ReadCountries failed with %d", lResult));
  2777. return lResult;
  2778. }
  2779. //
  2780. // create the array of country IDs
  2781. //
  2782. pCountryIDs = (LPDWORD)ClientAlloc( sizeof(DWORD) * pLCL->dwNumCountries );
  2783. if(!pCountryIDs)
  2784. {
  2785. ClientFree( pLCL );
  2786. return LINEERR_NOMEM;
  2787. }
  2788. pLCountry = (LPLINECOUNTRYENTRY_INTERNAL) ((LPBYTE)pLCL + pLCL->dwCountryListOffset);
  2789. for( DWORD dwIdx = 0; dwIdx < pLCL->dwNumCountries; dwIdx++, pLCountry++ )
  2790. {
  2791. *(pCountryIDs + dwIdx) = pLCountry->dwCountryID;
  2792. }
  2793. funcArgs.Args[0] = funcArgs.Args[2] = (ULONG_PTR)pCountryIDs;
  2794. funcArgs.Args[1] = funcArgs.Args[3] = (ULONG_PTR)(sizeof(DWORD) * pLCL->dwNumCountries);
  2795. //
  2796. // Call TAPISRV to get the country groups
  2797. // At return pCountryIDs will have the country groups
  2798. //
  2799. lResult = DOFUNC (&funcArgs, "lineGetCountryGroups");
  2800. if (lResult)
  2801. {
  2802. LOG((TL_TRACE, "ReadCountriesAndGroups: lineGetCountryGroups failed with %d", lResult));
  2803. //
  2804. // consider all the country groups undefined (0)
  2805. //
  2806. memset( pCountryIDs, 0, sizeof(DWORD) * pLCL->dwNumCountries );
  2807. lResult = ERROR_SUCCESS;
  2808. }
  2809. pLCountry = (LPLINECOUNTRYENTRY_INTERNAL) ((LPBYTE)pLCL + pLCL->dwCountryListOffset);
  2810. for( DWORD dwIdx = 0; dwIdx < pLCL->dwNumCountries; dwIdx++, pLCountry++ )
  2811. {
  2812. pLCountry->dwCountryGroup = *(pCountryIDs + dwIdx);
  2813. }
  2814. *ppLCL = pLCL;
  2815. ClientFree( pCountryIDs );
  2816. return lResult;
  2817. }
  2818. //***************************************************************************
  2819. // Returns LONG_DISTANCE_CARRIER_MANDATORY if rule contains an 'L' or 'l'
  2820. // (ie long distance carrier code - mandatory),
  2821. // Returns LONG_DISTANCE_CARRIER_OPTIONAL if rule contains an 'N' or 'n'
  2822. // (ie long distance carrier code - optional),
  2823. // Returns LONG_DISTANCE_CARRIER_NONE if rule contains neither
  2824. //
  2825. int IsLongDistanceCarrierCodeRule(LPWSTR lpRule)
  2826. {
  2827. WCHAR c;
  2828. while ((c = *lpRule++) != '\0')
  2829. {
  2830. if (c == 'L' || c == 'l') return LONG_DISTANCE_CARRIER_MANDATORY;
  2831. if (c == 'N' || c == 'n') return LONG_DISTANCE_CARRIER_OPTIONAL;
  2832. }
  2833. return LONG_DISTANCE_CARRIER_NONE;
  2834. }
  2835. //***************************************************************************
  2836. // Returns INTERNATIONAL_CARRIER_MANDATORY if rule contains an 'M' or 'm'
  2837. // (ie international carrier code - mandatory),
  2838. // Returns INTERNATIONAL_CARRIER_OPTIONAL if rule contains an 'S' or 's'
  2839. // (ie international carrier code - optional),
  2840. // Returns INTERNATIONAL_CARRIER_NONE if rule contains neither
  2841. //
  2842. int IsInternationalCarrierCodeRule(LPWSTR lpRule)
  2843. {
  2844. WCHAR c;
  2845. while ((c = *lpRule++) != '\0')
  2846. {
  2847. if (c == 'M' || c == 'm') return INTERNATIONAL_CARRIER_MANDATORY;
  2848. if (c == 'S' || c == 's') return INTERNATIONAL_CARRIER_OPTIONAL;
  2849. }
  2850. return INTERNATIONAL_CARRIER_NONE;
  2851. }
  2852. //***************************************************************************
  2853. //***************************************************************************
  2854. //***************************************************************************
  2855. // Returns CITY_MANDATORY if rule contains an F (ie city code mandatory),
  2856. // Returns CITY_OPTIONAL if rule contains an I (ie city code optional)
  2857. // Returns CITY_NONE if rule contains neither
  2858. //
  2859. int IsCityRule(LPWSTR lpRule)
  2860. {
  2861. WCHAR c;
  2862. while ((c = *lpRule++) != '\0')
  2863. {
  2864. if (c == 'F') return CITY_MANDATORY;
  2865. if (c == 'I') return CITY_OPTIONAL;
  2866. }
  2867. return CITY_NONE;
  2868. }
  2869. // Initializes/uninitializes the defined node pools based on the templates from list.h
  2870. //
  2871. void ListNodePoolsInitialize(void)
  2872. {
  2873. NodePool<CCallingCard *>::initialize();
  2874. NodePool<CCountry *>::initialize();
  2875. NodePool<CLocation *>::initialize();
  2876. NodePool<CAreaCodeRule*>::initialize();
  2877. }
  2878. void ListNodePoolsUninitialize(void)
  2879. {
  2880. NodePool<CCallingCard *>::uninitialize();
  2881. NodePool<CCountry *>::uninitialize();
  2882. NodePool<CLocation *>::uninitialize();
  2883. NodePool<CAreaCodeRule*>::uninitialize();
  2884. }