Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1575 lines
43 KiB

  1. //*********************************************************************
  2. //* Microsoft Windows **
  3. //* Copyright(c) Microsoft Corp., 1999 **
  4. //*********************************************************************
  5. //
  6. // tapiloc.CPP - Header for the implementation of CObMain
  7. //
  8. // HISTORY:
  9. //
  10. // 1/27/99 vyung Created.
  11. //
  12. #include "tapiloc.h"
  13. #include "appdefs.h"
  14. #include "dispids.h"
  15. #include "msobmain.h"
  16. #include <shlwapi.h>
  17. #include "resource.h"
  18. #include <regapix.h>
  19. DISPATCHLIST TapiExternalInterface[] =
  20. {
  21. {L"IsTAPIConfigured", DISPID_TAPI_INITTAPI },
  22. {L"get_CountryNameForIndex", DISPID_TAPI_GETCOUNTRYNAME },
  23. {L"get_CountryIndex", DISPID_TAPI_GETCOUNTRYINDEX },
  24. {L"set_CountryIndex", DISPID_TAPI_SETCOUNTRYINDEX },
  25. {L"get_NumOfCountry", DISPID_TAPI_GETNUMOFCOUNTRY },
  26. {L"get_AreaCode", DISPID_TAPI_GETAREACODE },
  27. {L"set_AreaCode", DISPID_TAPI_SETAREACODE },
  28. {L"get_DialOut", DISPID_TAPI_GETDIALOUT },
  29. {L"set_DialOut", DISPID_TAPI_SETDIALOUT },
  30. {L"get_PhoneSystem", DISPID_TAPI_GETPHONESYS },
  31. {L"set_PhoneSystem", DISPID_TAPI_SETPHONESYS },
  32. {L"get_CallWaiting", DISPID_TAPI_GETCALLWAITING },
  33. {L"set_CallWaiting", DISPID_TAPI_SETCALLWAITING },
  34. {L"get_AllCountryName", DISPID_TAPI_GETALLCNTRYNAME },
  35. {L"IsAreaCodeRequired", DISPID_TAPI_ISACODEREQUIRED },
  36. {L"get_CountryID", DISPID_TAPI_GETCOUNTRYID },
  37. {L"IsTapiServiceRunning", DISPID_TAPI_TAPISERVICERUNNING}
  38. };
  39. //+---------------------------------------------------------------------------
  40. //
  41. // Function: CompareCntryNameLookUpElements()
  42. //
  43. // Synopsis: Function to compare names used by sort
  44. //
  45. //+---------------------------------------------------------------------------
  46. int __cdecl CompareCntryNameLookUpElements(const void *e1, const void *e2)
  47. {
  48. LPCNTRYNAMELOOKUPELEMENT pCUE1 = (LPCNTRYNAMELOOKUPELEMENT)e1;
  49. LPCNTRYNAMELOOKUPELEMENT pCUE2 = (LPCNTRYNAMELOOKUPELEMENT)e2;
  50. return CompareStringW(LOCALE_USER_DEFAULT, 0,
  51. pCUE1->psCountryName, -1,
  52. pCUE2->psCountryName, -1
  53. ) - 2;
  54. }
  55. //+---------------------------------------------------------------------------
  56. //
  57. // Function: LineCallback()
  58. //
  59. // Synopsis: Call back for TAPI line
  60. //
  61. //+---------------------------------------------------------------------------
  62. void CALLBACK LineCallback(DWORD hDevice,
  63. DWORD dwMessage,
  64. DWORD_PTR dwInstance,
  65. DWORD_PTR dwParam1,
  66. DWORD_PTR dwParam2,
  67. DWORD_PTR dwParam3)
  68. {
  69. return;
  70. }
  71. //+---------------------------------------------------------------------------
  72. // Function: GetCurrentTapiLocation
  73. //
  74. // Synopsis: Open the
  75. // \HKLM\Software\Microsoft\CurrentVersion\Telephony\Locations\LocationX
  76. // where X is the id of the current location. The id is stored in
  77. // HKLM\Software\Microsoft\Windows\CurrentVersion\Telephony\Locations\CurrentID.
  78. //
  79. //+---------------------------------------------------------------------------
  80. HRESULT
  81. GetCurrentTapiLocation(
  82. LPWSTR szLocation,
  83. DWORD cbLocation
  84. )
  85. {
  86. HKEY hkey = NULL;
  87. HRESULT hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  88. TAPI_PATH_LOCATIONS,
  89. 0,
  90. KEY_QUERY_VALUE,
  91. &hkey
  92. );
  93. if (ERROR_SUCCESS == hr)
  94. {
  95. DWORD dwCurrentId = 0;
  96. DWORD cbCurrentId = sizeof(DWORD);
  97. hr = RegQueryValueEx(hkey, TAPI_CURRENTID, NULL, NULL,
  98. (LPBYTE) &dwCurrentId, &cbCurrentId);
  99. if (ERROR_SUCCESS == hr)
  100. {
  101. if (0 >= wnsprintf(szLocation, cbLocation - 1, L"%s\\%s%lu",
  102. TAPI_PATH_LOCATIONS, TAPI_LOCATION, dwCurrentId)
  103. )
  104. {
  105. hr = E_FAIL;
  106. }
  107. }
  108. RegCloseKey(hkey);
  109. }
  110. return hr;
  111. }
  112. //+---------------------------------------------------------------------------
  113. //
  114. // Function: SetTapiReg()
  115. //
  116. // Synopsis: Set TAPI REG
  117. //
  118. //+---------------------------------------------------------------------------
  119. STDMETHODIMP SetTapiReg(LPCWSTR lpValueName, DWORD dwType, const BYTE* lpByte, DWORD dwSize)
  120. {
  121. HKEY hKey = 0;
  122. // get path to the TAPI
  123. WCHAR szLocation[MAXIMUM_VALUE_NAME_LENGTH];
  124. HRESULT hr = GetCurrentTapiLocation(szLocation, MAXIMUM_VALUE_NAME_LENGTH);
  125. if (ERROR_SUCCESS == hr)
  126. {
  127. hr = RegOpenKey(HKEY_LOCAL_MACHINE, szLocation, &hKey);
  128. }
  129. if (hr != ERROR_SUCCESS)
  130. return( E_FAIL );
  131. hr = RegSetValueEx(hKey, lpValueName, 0, dwType, lpByte, dwSize );
  132. RegCloseKey(hKey);
  133. if (hr != ERROR_SUCCESS)
  134. return( E_FAIL );
  135. return S_OK;
  136. }
  137. STDMETHODIMP GetTapiReg(LPCWSTR lpValueName, DWORD* pdwType, BYTE* lpByte, DWORD* pdwSize)
  138. {
  139. HRESULT hr;
  140. HKEY hKey = 0;
  141. // get path to the TAPI
  142. WCHAR szLocation[MAXIMUM_VALUE_NAME_LENGTH];
  143. hr = GetCurrentTapiLocation(szLocation, MAXIMUM_VALUE_NAME_LENGTH);
  144. if (ERROR_SUCCESS == hr)
  145. {
  146. hr = RegOpenKey(HKEY_LOCAL_MACHINE, szLocation, &hKey);
  147. }
  148. if (hr != ERROR_SUCCESS)
  149. return( E_FAIL );
  150. hr = RegQueryValueEx(hKey, lpValueName, 0, pdwType, lpByte, pdwSize );
  151. RegCloseKey(hKey);
  152. if (hr != ERROR_SUCCESS) return( E_FAIL );
  153. return S_OK;
  154. }
  155. /////////////////////////////////////////////////////////////
  156. /////////////////////////////////////////////////////////////
  157. /////////////////////////////////////////////////////////////
  158. /////// IUnknown implementation
  159. ///////
  160. ///////
  161. /////////////////////////////////////////////////////////////
  162. // CObMain::QueryInterface
  163. STDMETHODIMP CTapiLocationInfo::QueryInterface(REFIID riid, LPVOID* ppvObj)
  164. {
  165. // must set out pointer parameters to NULL
  166. *ppvObj = NULL;
  167. if ( riid == IID_IUnknown)
  168. {
  169. AddRef();
  170. *ppvObj = (IUnknown*)this;
  171. return ResultFromScode(S_OK);
  172. }
  173. if (riid == IID_IDispatch)
  174. {
  175. AddRef();
  176. *ppvObj = (IDispatch*)this;
  177. return ResultFromScode(S_OK);
  178. }
  179. // Not a supported interface
  180. return ResultFromScode(E_NOINTERFACE);
  181. }
  182. /////////////////////////////////////////////////////////////
  183. // CTapiLocationInfo::AddRef
  184. STDMETHODIMP_(ULONG) CTapiLocationInfo::AddRef()
  185. {
  186. return ++m_cRef;
  187. }
  188. /////////////////////////////////////////////////////////////
  189. // CTapiLocationInfo::Release
  190. STDMETHODIMP_(ULONG) CTapiLocationInfo::Release()
  191. {
  192. return --m_cRef;
  193. }
  194. /////////////////////////////////////////////////////////////
  195. /////////////////////////////////////////////////////////////
  196. /////////////////////////////////////////////////////////////
  197. /////// IDispatch implementation
  198. ///////
  199. ///////
  200. /////////////////////////////////////////////////////////////
  201. // CTapiLocationInfo::GetTypeInfo
  202. STDMETHODIMP CTapiLocationInfo::GetTypeInfo(UINT, LCID, ITypeInfo**)
  203. {
  204. return E_NOTIMPL;
  205. }
  206. /////////////////////////////////////////////////////////////
  207. // CTapiLocationInfo::GetTypeInfoCount
  208. STDMETHODIMP CTapiLocationInfo::GetTypeInfoCount(UINT* pcInfo)
  209. {
  210. return E_NOTIMPL;
  211. }
  212. /////////////////////////////////////////////////////////////
  213. // CTapiLocationInfo::GetIDsOfNames
  214. STDMETHODIMP CTapiLocationInfo::GetIDsOfNames(REFIID riid,
  215. OLECHAR** rgszNames,
  216. UINT cNames,
  217. LCID lcid,
  218. DISPID* rgDispId)
  219. {
  220. HRESULT hr = DISP_E_UNKNOWNNAME;
  221. rgDispId[0] = DISPID_UNKNOWN;
  222. for (int iX = 0; iX < sizeof(TapiExternalInterface)/sizeof(DISPATCHLIST); iX ++)
  223. {
  224. if(lstrcmp(TapiExternalInterface[iX].szName, rgszNames[0]) == 0)
  225. {
  226. rgDispId[0] = TapiExternalInterface[iX].dwDispID;
  227. hr = NOERROR;
  228. break;
  229. }
  230. }
  231. // Set the disid's for the parameters
  232. if (cNames > 1)
  233. {
  234. // Set a DISPID for function parameters
  235. for (UINT i = 1; i < cNames ; i++)
  236. rgDispId[i] = DISPID_UNKNOWN;
  237. }
  238. return hr;
  239. }
  240. /////////////////////////////////////////////////////////////
  241. // CTapiLocationInfo::Invoke
  242. HRESULT CTapiLocationInfo::Invoke
  243. (
  244. DISPID dispidMember,
  245. REFIID riid,
  246. LCID lcid,
  247. WORD wFlags,
  248. DISPPARAMS* pdispparams,
  249. VARIANT* pvarResult,
  250. EXCEPINFO* pexcepinfo,
  251. UINT* puArgErr
  252. )
  253. {
  254. HRESULT hr = S_OK;
  255. switch(dispidMember)
  256. {
  257. case DISPID_TAPI_INITTAPI:
  258. {
  259. TRACE(L"DISPID_TAPI_INITTAPI\n");
  260. BOOL bRet;
  261. InitTapiInfo(&bRet);
  262. if(pvarResult)
  263. {
  264. VariantInit(pvarResult);
  265. V_VT(pvarResult) = VT_BOOL;
  266. pvarResult->boolVal = Bool2VarBool(bRet);
  267. }
  268. break;
  269. }
  270. case DISPID_TAPI_GETCOUNTRYINDEX:
  271. {
  272. TRACE(L"DISPID_TAPI_GETCOUNTRYINDEX\n");
  273. if(pvarResult)
  274. {
  275. VariantInit(pvarResult);
  276. V_VT(pvarResult) = VT_I4;
  277. GetlCountryIndex(&(pvarResult->lVal));
  278. }
  279. break;
  280. }
  281. case DISPID_TAPI_SETCOUNTRYINDEX:
  282. {
  283. TRACE(L"DISPID_TAPI_SETCOUNTRYINDEX\n");
  284. if(pdispparams && &pdispparams[0].rgvarg[0])
  285. {
  286. SetlCountryIndex(pdispparams[0].rgvarg[0].lVal);
  287. }
  288. break;
  289. }
  290. case DISPID_TAPI_GETNUMOFCOUNTRY:
  291. {
  292. TRACE(L"DISPID_TAPI_GETNUMOFCOUNTRY\n");
  293. if(pvarResult)
  294. {
  295. VariantInit(pvarResult);
  296. V_VT(pvarResult) = VT_I4;
  297. GetNumCountries(&(pvarResult->lVal));
  298. }
  299. break;
  300. }
  301. case DISPID_TAPI_GETCOUNTRYNAME:
  302. {
  303. TRACE(L"DISPID_TAPI_GETCOUNTRYNAME\n");
  304. BSTR bstrCountry;
  305. if(pdispparams && &pdispparams[0].rgvarg[0])
  306. {
  307. GetCountryName(pdispparams[0].rgvarg[0].lVal, &bstrCountry);
  308. }
  309. if(pvarResult)
  310. {
  311. VariantInit(pvarResult);
  312. V_VT(pvarResult) = VT_BSTR;
  313. pvarResult->bstrVal = bstrCountry;
  314. bstrCountry = NULL;
  315. }
  316. break;
  317. }
  318. case DISPID_TAPI_GETAREACODE:
  319. {
  320. TRACE(L"DISPID_TAPI_GETAREACODE\n");
  321. if(pvarResult)
  322. {
  323. VariantInit(pvarResult);
  324. V_VT(pvarResult) = VT_BSTR;
  325. GetbstrAreaCode(&(pvarResult->bstrVal));
  326. }
  327. break;
  328. }
  329. case DISPID_TAPI_SETAREACODE:
  330. {
  331. TRACE(L"DISPID_TAPI_SETAREACODE\n");
  332. if(pdispparams && &pdispparams[0].rgvarg[0])
  333. {
  334. PutbstrAreaCode(pdispparams[0].rgvarg[0].bstrVal);
  335. }
  336. break;
  337. }
  338. case DISPID_TAPI_GETDIALOUT:
  339. {
  340. TRACE(L"DISPID_TAPI_GETDIALOUT\n");
  341. if(pvarResult)
  342. {
  343. VariantInit(pvarResult);
  344. V_VT(pvarResult) = VT_BSTR;
  345. GetOutsideDial(&(pvarResult->bstrVal));
  346. }
  347. break;
  348. }
  349. case DISPID_TAPI_SETDIALOUT:
  350. {
  351. TRACE(L"DISPID_TAPI_SETDIALOUT\n");
  352. if(pdispparams && &pdispparams[0].rgvarg[0])
  353. {
  354. PutOutsideDial(pdispparams[0].rgvarg[0].bstrVal);
  355. }
  356. break;
  357. }
  358. case DISPID_TAPI_GETPHONESYS:
  359. {
  360. TRACE(L"DISPID_TAPI_GETPHONESYS\n");
  361. if(pvarResult)
  362. {
  363. VariantInit(pvarResult);
  364. V_VT(pvarResult) = VT_I4;
  365. GetPhoneSystem(&(pvarResult->lVal));
  366. }
  367. break;
  368. }
  369. case DISPID_TAPI_SETPHONESYS:
  370. {
  371. TRACE(L"DISPID_TAPI_SETPHONESYS\n");
  372. if(pdispparams && &pdispparams[0].rgvarg[0])
  373. {
  374. PutPhoneSystem(pdispparams[0].rgvarg[0].lVal);
  375. }
  376. break;
  377. }
  378. case DISPID_TAPI_GETCALLWAITING:
  379. {
  380. TRACE(L"DISPID_TAPI_GETCALLWAITING\n");
  381. if(pvarResult)
  382. {
  383. VariantInit(pvarResult);
  384. V_VT(pvarResult) = VT_BSTR;
  385. GetCallWaiting(&(pvarResult->bstrVal));
  386. }
  387. break;
  388. }
  389. case DISPID_TAPI_SETCALLWAITING:
  390. {
  391. TRACE(L"DISPID_TAPI_SETCALLWAITING\n");
  392. if(pdispparams && &pdispparams[0].rgvarg[0])
  393. {
  394. PutCallWaiting(pdispparams[0].rgvarg[0].bstrVal);
  395. }
  396. break;
  397. }
  398. case DISPID_TAPI_GETALLCNTRYNAME:
  399. {
  400. TRACE(L"DISPID_TAPI_GETALLCNTRYNAME\n");
  401. if(pvarResult)
  402. {
  403. VariantInit(pvarResult);
  404. V_VT(pvarResult) = VT_BSTR;
  405. GetAllCountryName(&(pvarResult->bstrVal));
  406. }
  407. break;
  408. }
  409. case DISPID_TAPI_ISACODEREQUIRED:
  410. {
  411. TRACE(L"DISPID_TAPI_ISACODEREQUIRED\n");
  412. if(pdispparams && &pdispparams[0].rgvarg[0] && pvarResult)
  413. {
  414. VariantInit(pvarResult);
  415. V_VT(pvarResult) = VT_BOOL;
  416. IsAreaCodeRequired(pdispparams[0].rgvarg[0].lVal, (BOOL*)&(pvarResult->boolVal));
  417. }
  418. break;
  419. }
  420. case DISPID_TAPI_GETCOUNTRYID:
  421. {
  422. TRACE(L"DISPID_TAPI_GETCOUNTRYID");
  423. if(pvarResult)
  424. {
  425. VariantInit(pvarResult);
  426. V_VT(pvarResult) = VT_I4;
  427. pvarResult->lVal = m_dwCountryID;
  428. TRACE1(L"... %d returned", m_dwCountryID);
  429. }
  430. break;
  431. }
  432. case DISPID_TAPI_TAPISERVICERUNNING:
  433. {
  434. TRACE(L"DISPID_TAPI_TAPISERVICERUNNING\n");
  435. BOOL bRet;
  436. TapiServiceRunning(&bRet);
  437. if(pvarResult)
  438. {
  439. VariantInit(pvarResult);
  440. V_VT(pvarResult) = VT_BOOL;
  441. pvarResult->boolVal = Bool2VarBool(bRet);
  442. }
  443. break;
  444. }
  445. default:
  446. {
  447. hr = DISP_E_MEMBERNOTFOUND;
  448. break;
  449. }
  450. }
  451. return hr;
  452. }
  453. /////////////////////////////////////////////////////////////////////////////
  454. // CTapiLocationInfo
  455. CTapiLocationInfo::CTapiLocationInfo()
  456. {
  457. m_wNumTapiLocations = 0;
  458. m_dwComboCountryIndex = 0;
  459. m_dwCountryID = 0;
  460. m_dwCurrLoc = 0;
  461. m_hLineApp = NULL;
  462. m_pLineCountryList = NULL;
  463. m_rgNameLookUp = NULL;
  464. m_pTC = NULL;
  465. m_bTapiAvailable = FALSE;
  466. m_szAreaCode [0] = L'\0';
  467. m_szDialOut [0] = L'\0';
  468. m_szAllCountryPairs = NULL;
  469. m_bTapiCountrySet = FALSE;
  470. m_bCheckModemCountry = FALSE;
  471. }
  472. CTapiLocationInfo::~CTapiLocationInfo()
  473. {
  474. //
  475. // It is possible that the country ID is set but dialing, hence the call
  476. // to CheckModemCountry, is skipped.
  477. //
  478. CheckModemCountry();
  479. if (m_szAllCountryPairs)
  480. {
  481. GlobalFree(m_szAllCountryPairs);
  482. }
  483. if (m_pLineCountryList)
  484. {
  485. GlobalFree(m_pLineCountryList);
  486. }
  487. if (m_rgNameLookUp)
  488. {
  489. GlobalFree(m_rgNameLookUp);
  490. }
  491. if (m_pTC)
  492. {
  493. GlobalFree(m_pTC);
  494. }
  495. }
  496. const WCHAR gszInternationalSec[] = L"intl";
  497. const WCHAR gszCountryEntry[] = L"iCountry";
  498. STDMETHODIMP CTapiLocationInfo::InitTapiInfo(BOOL* pbRetVal)
  499. {
  500. HRESULT hr = ERROR_SUCCESS;
  501. DWORD cDevices =0;
  502. DWORD dwCurDev = 0;
  503. DWORD dwAPI = 0;
  504. LONG lrc = 0;
  505. LINEEXTENSIONID leid;
  506. LPVOID pv = NULL;
  507. DWORD dwCurLoc = 0;
  508. WCHAR szCountryCode[8];
  509. WCHAR szIniFile[MAX_PATH*2] = SZ_EMPTY;
  510. if (0 != m_dwCountryID)
  511. {
  512. // TAPI already initialized, don't do it again.
  513. *pbRetVal = m_bTapiAvailable;
  514. goto InitTapiInfoExit;
  515. }
  516. m_hLineApp=NULL;
  517. // Assume Failure
  518. *pbRetVal = FALSE;
  519. if (m_pTC)
  520. {
  521. GlobalFree(m_pTC);
  522. m_pTC = NULL;
  523. }
  524. m_bTapiAvailable = TRUE;
  525. hr = tapiGetLocationInfo(szCountryCode, m_szAreaCode);
  526. if (hr)
  527. {
  528. HKEY hKey = 0;
  529. m_bTapiAvailable = FALSE;
  530. // GetLocation failed. Normally we show the TAPI mini dialog which
  531. // has no cancel option, and the user is forced to enter info and hit OK.
  532. // In OOBE, we have to mimic this dialog in html, so here we will
  533. // give user country list, and default phone system
  534. // This code taken from dial.c in tapi32.dll
  535. m_dwCountryID = (DWORD)GetProfileInt( gszInternationalSec,
  536. gszCountryEntry,
  537. 1 );
  538. // create necessary tapi keys
  539. *pbRetVal = TRUE; // Getting here means everything worked
  540. HRESULT hr = RegCreateKey(HKEY_LOCAL_MACHINE, TAPI_PATH_LOC0, &hKey);
  541. if (hr != ERROR_SUCCESS)
  542. {
  543. *pbRetVal = FALSE;
  544. }
  545. else
  546. {
  547. RegSetValueEx(hKey, TAPI_CALLWAIT, 0, REG_SZ, (LPBYTE)NULL_SZ, BYTES_REQUIRED_BY_SZ(NULL_SZ) );
  548. HINSTANCE hInst = GetModuleHandle(L"msobmain.dll");
  549. WCHAR szTapiNewLoc[MAX_PATH];
  550. LoadString(hInst, IDS_TAPI_NEWLOC, szTapiNewLoc, MAX_CHARS_IN_BUFFER(szTapiNewLoc));
  551. RegSetValueEx(hKey, TAPI_NAME, 0, REG_SZ, (LPBYTE)szTapiNewLoc, BYTES_REQUIRED_BY_SZ(szTapiNewLoc) );
  552. RegCloseKey(hKey);
  553. }
  554. if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, TAPI_PATH_LOCATIONS, &hKey))
  555. {
  556. DWORD dwVal;
  557. DWORD dwSize = sizeof(dwVal);
  558. dwVal = 0;
  559. hr = RegSetValueEx(hKey, TAPI_CURRENTID, 0, REG_DWORD, (LPBYTE)&dwVal, sizeof(DWORD));
  560. RegQueryValueEx(hKey, TAPI_NUMENTRIES, 0, NULL, (LPBYTE)&dwVal, &dwSize);
  561. dwVal++; //bump the entry count up
  562. RegSetValueEx(hKey, TAPI_NUMENTRIES, 0, REG_DWORD, (LPBYTE)&dwVal, sizeof(DWORD));
  563. RegCloseKey(hKey);
  564. }
  565. *pbRetVal = FALSE;
  566. }
  567. else
  568. {
  569. DWORD dwFlag = REG_DWORD;
  570. DWORD dwSize = sizeof(dwFlag);
  571. DWORD dwType = 0;
  572. if (S_OK != GetTapiReg(TAPI_COUNTRY, &dwType, (LPBYTE)&dwFlag, &dwSize))
  573. {
  574. m_bTapiAvailable = FALSE;
  575. goto InitTapiInfoExit;
  576. }
  577. // Get CountryID from TAPI
  578. m_hLineApp = NULL;
  579. // Get the handle to the line app
  580. lineInitialize(&m_hLineApp, NULL, LineCallback, NULL, &cDevices);
  581. if (!m_hLineApp)
  582. {
  583. goto InitTapiInfoExit;
  584. }
  585. if (cDevices)
  586. {
  587. // Get the TAPI API version
  588. //
  589. dwCurDev = 0;
  590. dwAPI = 0;
  591. lrc = -1;
  592. while (lrc && dwCurDev < cDevices)
  593. {
  594. // NOTE: device ID's are 0 based
  595. ZeroMemory(&leid, sizeof(leid));
  596. lrc = lineNegotiateAPIVersion(m_hLineApp, dwCurDev,0x00010004,0x00010004,&dwAPI,&leid);
  597. dwCurDev++;
  598. }
  599. if (lrc)
  600. {
  601. // TAPI and us can't agree on anything so nevermind...
  602. goto InitTapiInfoExit;
  603. }
  604. // Find the CountryID in the translate cap structure
  605. m_pTC = (LINETRANSLATECAPS *)GlobalAlloc(GPTR, sizeof(LINETRANSLATECAPS));
  606. if (!m_pTC)
  607. {
  608. // we are in real trouble here, get out!
  609. hr = ERROR_NOT_ENOUGH_MEMORY;
  610. goto InitTapiInfoExit;
  611. }
  612. // Get the needed size
  613. m_pTC->dwTotalSize = sizeof(LINETRANSLATECAPS);
  614. lrc = lineGetTranslateCaps(m_hLineApp, dwAPI,m_pTC);
  615. if(lrc)
  616. {
  617. goto InitTapiInfoExit;
  618. }
  619. pv = GlobalAlloc(GPTR, ((size_t)m_pTC->dwNeededSize));
  620. if (!pv)
  621. {
  622. hr = ERROR_NOT_ENOUGH_MEMORY;
  623. goto InitTapiInfoExit;
  624. }
  625. ((LINETRANSLATECAPS*)pv)->dwTotalSize = m_pTC->dwNeededSize;
  626. m_pTC = (LINETRANSLATECAPS*)pv;
  627. pv = NULL;
  628. lrc = lineGetTranslateCaps(m_hLineApp, dwAPI,m_pTC);
  629. if(lrc)
  630. {
  631. goto InitTapiInfoExit;
  632. }
  633. // sanity check
  634. // Assert(m_pTC->dwLocationListOffset);
  635. // We have the Number of TAPI locations, so save it now
  636. m_wNumTapiLocations = (WORD)m_pTC->dwNumLocations;
  637. // Loop through the locations to find the correct country code
  638. m_plle = LPLINELOCATIONENTRY (PBYTE(m_pTC) + m_pTC->dwLocationListOffset);
  639. for (dwCurLoc = 0; dwCurLoc < m_pTC->dwNumLocations; dwCurLoc++)
  640. {
  641. if (m_pTC->dwCurrentLocationID == m_plle->dwPermanentLocationID)
  642. {
  643. m_dwCountryID = m_plle->dwCountryID;
  644. m_dwCurrLoc = dwCurLoc;
  645. break; // for loop
  646. }
  647. m_plle++;
  648. }
  649. // If we could not find it in the above loop, default to US
  650. if (!m_dwCountryID)
  651. {
  652. m_dwCountryID = 1;
  653. goto InitTapiInfoExit;
  654. }
  655. }
  656. *pbRetVal = TRUE; // Getting here means everything worked
  657. }
  658. // Settings in INI_SETTINGS_FILENAME should initialize or override the
  659. // system's Tapi configuration.
  660. if (GetCanonicalizedPath(szIniFile, INI_SETTINGS_FILENAME))
  661. {
  662. //
  663. // [Options]
  664. // Tonepulse = 0 for pulse, 1 for tone
  665. // Areacode = {string}
  666. // OutsideLine = {string}
  667. // DisableCallWaiting = {string}
  668. //
  669. LONG lTonDialing = (BOOL) GetPrivateProfileInt(OPTIONS_SECTION,
  670. TONEPULSE,
  671. -1,
  672. szIniFile);
  673. if (lTonDialing != -1)
  674. {
  675. PutPhoneSystem(lTonDialing);
  676. }
  677. if (GetPrivateProfileString(OPTIONS_SECTION,
  678. AREACODE,
  679. L"\0",
  680. m_szAreaCode,
  681. MAX_CHARS_IN_BUFFER(m_szAreaCode),
  682. szIniFile))
  683. {
  684. PutbstrAreaCode(SysAllocString(m_szAreaCode));
  685. }
  686. if (GetPrivateProfileString(OPTIONS_SECTION,
  687. OUTSIDELINE,
  688. L"\0",
  689. m_szDialOut,
  690. MAX_CHARS_IN_BUFFER(m_szDialOut),
  691. szIniFile))
  692. {
  693. PutOutsideDial(SysAllocString(m_szDialOut));
  694. }
  695. if (GetPrivateProfileString(OPTIONS_SECTION,
  696. DISABLECALLWAITING,
  697. L"\0",
  698. m_szCallWaiting,
  699. MAX_CHARS_IN_BUFFER(m_szCallWaiting),
  700. szIniFile))
  701. {
  702. PutCallWaiting(SysAllocString(m_szCallWaiting));
  703. }
  704. }
  705. InitTapiInfoExit:
  706. // if we can't figure it out because TAPI is messed up just default to
  707. // the US. The user will still have the chance to pick the right answer.
  708. if (!m_dwCountryID) {
  709. m_dwCountryID = 1;
  710. }
  711. if (m_hLineApp)
  712. {
  713. lineShutdown(m_hLineApp);
  714. m_hLineApp = NULL;
  715. }
  716. m_lNumOfCountry = 0;
  717. GetNumCountries(&m_lNumOfCountry);
  718. return S_OK;
  719. }
  720. STDMETHODIMP CTapiLocationInfo::GetlCountryIndex(long * plVal)
  721. {
  722. *plVal = m_dwComboCountryIndex;
  723. return S_OK;
  724. }
  725. STDMETHODIMP CTapiLocationInfo::SetlCountryIndex(long lVal)
  726. {
  727. HRESULT hr = E_FAIL;
  728. // Write to registry
  729. if (lVal < m_lNumOfCountry && lVal > -1)
  730. {
  731. m_bTapiCountrySet = TRUE;
  732. m_dwCountryID = m_rgNameLookUp[lVal].pLCE->dwCountryID;
  733. m_dwCountrycode = m_rgNameLookUp[lVal].pLCE->dwCountryCode;
  734. m_dwComboCountryIndex = lVal;
  735. hr = SetTapiReg(TAPI_COUNTRY, REG_DWORD, (LPBYTE)&m_rgNameLookUp[lVal].pLCE->dwCountryID, sizeof(DWORD) );
  736. }
  737. if (SUCCEEDED(hr))
  738. {
  739. m_bCheckModemCountry = TRUE;
  740. }
  741. return hr;
  742. }
  743. STDMETHODIMP CTapiLocationInfo::GetCountryID(DWORD* dwCountryID)
  744. {
  745. MYASSERT( m_dwCountryID );
  746. *dwCountryID = m_dwCountryID;
  747. return S_OK;
  748. }
  749. STDMETHODIMP CTapiLocationInfo::GetCountryCode(DWORD* dwCountryCode)
  750. {
  751. *dwCountryCode = m_dwCountrycode;
  752. return S_OK;
  753. }
  754. STDMETHODIMP CTapiLocationInfo::GetNumCountries(long *plNumOfCountry)
  755. {
  756. USES_CONVERSION;
  757. LPLINECOUNTRYLIST pLineCountryTemp = NULL;
  758. LPLINECOUNTRYENTRY pLCETemp;
  759. DWORD idx;
  760. DWORD dwCurLID = 0;
  761. HINSTANCE hTapi32Dll = NULL;
  762. FARPROC fp;
  763. BOOL bBookLoaded = FALSE;
  764. HRESULT hr = S_OK;
  765. if (NULL == plNumOfCountry)
  766. goto GetNumCountriesExit;
  767. // Avoid returning rubbish
  768. //
  769. *plNumOfCountry = 0;
  770. if (m_lNumOfCountry != 0)
  771. {
  772. *plNumOfCountry = m_lNumOfCountry;
  773. goto GetNumCountriesExit;
  774. }
  775. hTapi32Dll = LoadLibrary(L"tapi32.dll");
  776. if (hTapi32Dll)
  777. {
  778. fp = GetProcAddress(hTapi32Dll, "lineGetCountryW");
  779. if (!fp)
  780. {
  781. hr = GetLastError();
  782. goto GetNumCountriesExit;
  783. }
  784. // Get TAPI country list
  785. if (m_pLineCountryList)
  786. GlobalFree(m_pLineCountryList);
  787. m_pLineCountryList = (LPLINECOUNTRYLIST)GlobalAlloc(GPTR, sizeof(LINECOUNTRYLIST));
  788. if (!m_pLineCountryList)
  789. {
  790. hr = S_FALSE;
  791. goto GetNumCountriesExit;
  792. }
  793. m_pLineCountryList->dwTotalSize = sizeof(LINECOUNTRYLIST);
  794. idx = ((LINEGETCOUNTRY)fp)(0, 0x10003,m_pLineCountryList);
  795. if (idx && idx != LINEERR_STRUCTURETOOSMALL)
  796. {
  797. hr = S_FALSE;
  798. goto GetNumCountriesExit;
  799. }
  800. // Assert(m_pLineCountryList->dwNeededSize);
  801. pLineCountryTemp = (LPLINECOUNTRYLIST)GlobalAlloc(GPTR,
  802. (size_t)m_pLineCountryList->dwNeededSize);
  803. if (!pLineCountryTemp)
  804. {
  805. hr = S_FALSE;
  806. goto GetNumCountriesExit;
  807. }
  808. pLineCountryTemp->dwTotalSize = m_pLineCountryList->dwNeededSize;
  809. GlobalFree(m_pLineCountryList);
  810. m_pLineCountryList = pLineCountryTemp;
  811. pLineCountryTemp = NULL;
  812. if (((LINEGETCOUNTRY)fp)(0, 0x10003,m_pLineCountryList))
  813. {
  814. hr = S_FALSE;
  815. goto GetNumCountriesExit;
  816. }
  817. // look up array
  818. pLCETemp = (LPLINECOUNTRYENTRY)((DWORD_PTR)m_pLineCountryList +
  819. m_pLineCountryList->dwCountryListOffset);
  820. if(m_rgNameLookUp)
  821. GlobalFree(m_rgNameLookUp);
  822. m_rgNameLookUp = (LPCNTRYNAMELOOKUPELEMENT)GlobalAlloc(GPTR,
  823. (int)(sizeof(CNTRYNAMELOOKUPELEMENT) * m_pLineCountryList->dwNumCountries));
  824. if (!m_rgNameLookUp)
  825. {
  826. hr = S_FALSE;
  827. goto GetNumCountriesExit;
  828. }
  829. CNTRYNAMELOOKUPELEMENT CntryNameLUElement = {NULL, 0, NULL};
  830. CNTRYNAMELOOKUPELEMENT cnleUS = {NULL, 0, NULL};
  831. DWORD cbAllCountryPairs = 0;
  832. for (idx=0;idx<m_pLineCountryList->dwNumCountries;idx++)
  833. {
  834. m_rgNameLookUp[idx].psCountryName = (LPWSTR)((LPBYTE)m_pLineCountryList + (DWORD)pLCETemp[idx].dwCountryNameOffset);
  835. m_rgNameLookUp[idx].dwNameSize = pLCETemp[idx].dwCountryNameSize;
  836. m_rgNameLookUp[idx].pLCE = &pLCETemp[idx];
  837. #if 0
  838. TRACE2(L"GetNumCountries:%d:%s",
  839. m_rgNameLookUp[idx].pLCE->dwCountryID,
  840. m_rgNameLookUp[idx].psCountryName
  841. );
  842. #endif
  843. // Include space for NUL at end of unicode string
  844. //
  845. cbAllCountryPairs += m_rgNameLookUp[idx].dwNameSize + 2;
  846. // If TAPI is not available, we set the default to US
  847. if ( m_rgNameLookUp[idx].pLCE->dwCountryID == m_dwCountryID)
  848. {
  849. // Set the index to our default country in combo box
  850. m_dwComboCountryIndex = idx;
  851. m_dwCountrycode = m_rgNameLookUp[idx].pLCE->dwCountryCode;
  852. if (m_rgNameLookUp[idx].psCountryName)
  853. {
  854. m_bstrDefaultCountry = SysAllocString(m_rgNameLookUp[idx].psCountryName);
  855. }
  856. memcpy(&CntryNameLUElement, &m_rgNameLookUp[idx], sizeof(CNTRYNAMELOOKUPELEMENT));
  857. }
  858. else if (m_rgNameLookUp[idx].pLCE->dwCountryID == 1)
  859. {
  860. // Save the US info away in case we don't find the default
  861. memcpy(&cnleUS, &m_rgNameLookUp[idx], sizeof(CNTRYNAMELOOKUPELEMENT));
  862. }
  863. }
  864. // If we didn't find the default country, we're going to blow up.
  865. if (CntryNameLUElement.psCountryName == NULL)
  866. {
  867. TRACE1(L"Warning: Couldn't find country id %d. Defaulting to US.", m_dwCountryID);
  868. memcpy(&CntryNameLUElement, &cnleUS, sizeof(CNTRYNAMELOOKUPELEMENT));
  869. m_dwCountryID = 1;
  870. }
  871. MYASSERT( CntryNameLUElement.psCountryName );
  872. qsort(m_rgNameLookUp, (int)m_pLineCountryList->dwNumCountries,sizeof(CNTRYNAMELOOKUPELEMENT),
  873. CompareCntryNameLookUpElements);
  874. LPCNTRYNAMELOOKUPELEMENT pResult = (LPCNTRYNAMELOOKUPELEMENT)bsearch(&CntryNameLUElement, m_rgNameLookUp, (int)m_pLineCountryList->dwNumCountries,sizeof(CNTRYNAMELOOKUPELEMENT),
  875. CompareCntryNameLookUpElements);
  876. m_dwComboCountryIndex = (DWORD)((DWORD_PTR)pResult - (DWORD_PTR)m_rgNameLookUp) / sizeof(CNTRYNAMELOOKUPELEMENT);
  877. if (m_dwComboCountryIndex > m_pLineCountryList->dwNumCountries)
  878. m_dwComboCountryIndex = 0;
  879. *plNumOfCountry = m_pLineCountryList->dwNumCountries;
  880. m_lNumOfCountry = m_pLineCountryList->dwNumCountries;
  881. // Create the SELECT tag for the html so it can get all the country names in one shot.
  882. if (m_szAllCountryPairs)
  883. GlobalFree(m_szAllCountryPairs);
  884. // BUGBUG: Does this calculation account for country name strings??
  885. cbAllCountryPairs += m_lNumOfCountry * sizeof(szOptionTag) + 1;
  886. m_szAllCountryPairs = (WCHAR *)GlobalAlloc(GPTR, cbAllCountryPairs );
  887. if (m_szAllCountryPairs)
  888. {
  889. WCHAR szBuffer[MAX_PATH];
  890. for (idx=0; idx < (DWORD)m_lNumOfCountry; idx++)
  891. {
  892. wsprintf(szBuffer, szOptionTag, m_rgNameLookUp[idx].psCountryName);
  893. lstrcat(m_szAllCountryPairs, szBuffer);
  894. }
  895. }
  896. }
  897. GetNumCountriesExit:
  898. if (hTapi32Dll)
  899. {
  900. FreeLibrary(hTapi32Dll);
  901. hTapi32Dll = NULL;
  902. }
  903. return hr;
  904. }
  905. STDMETHODIMP CTapiLocationInfo::GetAllCountryName(BSTR* pbstrAllCountryName)
  906. {
  907. if (pbstrAllCountryName == NULL)
  908. {
  909. return E_POINTER;
  910. }
  911. // Avoid returning rubbish
  912. //
  913. *pbstrAllCountryName = NULL;
  914. if (m_lNumOfCountry && pbstrAllCountryName && m_szAllCountryPairs)
  915. {
  916. *pbstrAllCountryName = SysAllocString(m_szAllCountryPairs);
  917. return S_OK;
  918. }
  919. return E_FAIL;
  920. }
  921. STDMETHODIMP CTapiLocationInfo::GetCountryName(long lCountryIndex, BSTR* pszCountryName)
  922. {
  923. USES_CONVERSION;
  924. if (lCountryIndex < m_lNumOfCountry && lCountryIndex >= 0)
  925. {
  926. *pszCountryName = SysAllocString(m_rgNameLookUp[lCountryIndex].psCountryName);
  927. return S_OK;
  928. }
  929. return E_FAIL;
  930. }
  931. STDMETHODIMP CTapiLocationInfo::GetDefaultCountry(long* lCountryIndex)
  932. {
  933. if (lCountryIndex)
  934. *lCountryIndex = m_dwComboCountryIndex;
  935. return S_OK;
  936. }
  937. STDMETHODIMP CTapiLocationInfo::PutCountry(long lCountryIndex)
  938. {
  939. return E_NOTIMPL;
  940. }
  941. STDMETHODIMP CTapiLocationInfo::GetbstrAreaCode(BSTR * pbstrAreaCode)
  942. {
  943. HRESULT hr = S_OK;
  944. DWORD dwType = REG_SZ;
  945. DWORD dwSize = sizeof(m_szAreaCode);
  946. BSTR bstrTmp = NULL;
  947. if (pbstrAreaCode == NULL)
  948. {
  949. hr = E_POINTER;
  950. goto GetbstrAreaCodeExit;
  951. }
  952. // Avoid returning rubbish
  953. //
  954. *pbstrAreaCode = NULL;
  955. // Allocate default return value
  956. //
  957. hr = GetTapiReg(TAPI_AREACODE, &dwType, (LPBYTE)m_szAreaCode, &dwSize);
  958. if (SUCCEEDED(hr))
  959. {
  960. bstrTmp = SysAllocString(m_szAreaCode);
  961. }
  962. else
  963. {
  964. bstrTmp = SysAllocString(SZ_EMPTY);
  965. }
  966. // A valid string can be returned (though it may be empty) so we've
  967. // succeeded.
  968. //
  969. hr = S_OK;
  970. GetbstrAreaCodeExit:
  971. if (SUCCEEDED(hr))
  972. {
  973. *pbstrAreaCode = bstrTmp;
  974. bstrTmp = NULL;
  975. }
  976. return hr;
  977. }
  978. STDMETHODIMP CTapiLocationInfo::PutbstrAreaCode(BSTR bstrAreaCode)
  979. {
  980. LPWSTR szAreaCode = (NULL != bstrAreaCode) ? bstrAreaCode : SZ_EMPTY;
  981. DWORD dwSize = BYTES_REQUIRED_BY_SZ(szAreaCode);
  982. SetTapiReg(TAPI_AREACODE, REG_SZ, (LPBYTE)szAreaCode, dwSize);
  983. return S_OK;
  984. }
  985. STDMETHODIMP CTapiLocationInfo::IsAreaCodeRequired(long lVal, BOOL *pbVal)
  986. {
  987. LPWSTR szAreaCodeRule = NULL;
  988. LPWSTR szLongDistanceRule = NULL;
  989. if (!pbVal)
  990. return E_POINTER;
  991. *pbVal = FALSE;
  992. if (lVal < m_lNumOfCountry && lVal > -1 && m_pLineCountryList)
  993. {
  994. szAreaCodeRule = (LPWSTR)m_pLineCountryList + m_rgNameLookUp[lVal].pLCE->dwSameAreaRuleOffset;
  995. szLongDistanceRule = (LPWSTR)m_pLineCountryList + m_rgNameLookUp[lVal].pLCE->dwLongDistanceRuleOffset;
  996. if (szAreaCodeRule && szLongDistanceRule)
  997. {
  998. *pbVal = (NULL != StrChr(szAreaCodeRule, L'F')) || (NULL != StrChr(szLongDistanceRule, 'F'));
  999. }
  1000. }
  1001. return S_OK;
  1002. }
  1003. STDMETHODIMP CTapiLocationInfo::GetOutsideDial(BSTR * pbstrOutside)
  1004. {
  1005. DWORD dwType = REG_SZ;
  1006. DWORD dwSize = sizeof(m_szDialOut);
  1007. HRESULT hr = S_OK;
  1008. BSTR bstrTmp = NULL;
  1009. if (pbstrOutside == NULL)
  1010. {
  1011. hr = E_POINTER;
  1012. goto GetOutsideDialExit;
  1013. }
  1014. // Avoid returning rubbish in case of error
  1015. //
  1016. *pbstrOutside = NULL;
  1017. // Allocate empty string for default return string
  1018. //
  1019. bstrTmp = SysAllocString(SZ_EMPTY);
  1020. if (NULL == bstrTmp)
  1021. {
  1022. hr = E_OUTOFMEMORY;
  1023. goto GetOutsideDialExit;
  1024. }
  1025. hr = GetTapiReg(TAPI_OUTSIDE, &dwType, (LPBYTE)m_szDialOut, &dwSize);
  1026. if FAILED(hr)
  1027. {
  1028. goto GetOutsideDialExit;
  1029. }
  1030. if (! SysReAllocString(&bstrTmp, m_szDialOut))
  1031. {
  1032. hr = E_OUTOFMEMORY;
  1033. goto GetOutsideDialExit;
  1034. }
  1035. GetOutsideDialExit:
  1036. if (SUCCEEDED(hr))
  1037. {
  1038. *pbstrOutside = bstrTmp;
  1039. }
  1040. else
  1041. {
  1042. if (NULL != bstrTmp)
  1043. {
  1044. SysFreeString(bstrTmp);
  1045. }
  1046. }
  1047. bstrTmp = NULL;
  1048. return hr;
  1049. }
  1050. STDMETHODIMP CTapiLocationInfo::PutOutsideDial(BSTR bstrOutside)
  1051. {
  1052. // Is the bstr null-terminated??
  1053. assert(lstrlen(bstrOutside) <= SysStringLen(bstrOutside));
  1054. // If no string is passed in, default to empty string
  1055. //
  1056. lstrcpyn(
  1057. m_szDialOut,
  1058. (NULL != bstrOutside) ? bstrOutside : SZ_EMPTY,
  1059. MAX_CHARS_IN_BUFFER(m_szDialOut));
  1060. DWORD dwSize = BYTES_REQUIRED_BY_SZ(m_szDialOut);
  1061. HRESULT hr = SetTapiReg(TAPI_OUTSIDE, REG_SZ, (LPBYTE)m_szDialOut, dwSize);
  1062. if (SUCCEEDED(hr))
  1063. {
  1064. hr = SetTapiReg(TAPI_LONGDIST, REG_SZ, (LPBYTE)m_szDialOut, dwSize);
  1065. }
  1066. return hr;
  1067. }
  1068. STDMETHODIMP CTapiLocationInfo::GetPhoneSystem(long* plTone)
  1069. {
  1070. DWORD dwFlag = REG_DWORD;
  1071. DWORD dwSize = sizeof(dwFlag);
  1072. DWORD dwType = 0;
  1073. if (NULL == plTone)
  1074. return E_FAIL;
  1075. *plTone = 1;
  1076. if (S_OK == GetTapiReg(TAPI_FLAG, &dwType, (LPBYTE)&dwFlag, &dwSize))
  1077. {
  1078. *plTone = dwFlag & 0x01;
  1079. }
  1080. return S_OK;
  1081. }
  1082. STDMETHODIMP CTapiLocationInfo::PutPhoneSystem(long lTone)
  1083. {
  1084. DWORD dwFlag = REG_DWORD;
  1085. DWORD dwSize = sizeof(dwFlag);
  1086. DWORD dwType = 0;
  1087. if (S_OK != GetTapiReg(TAPI_FLAG, &dwType, (LPBYTE)&dwFlag, &dwSize))
  1088. {
  1089. dwFlag = 0;
  1090. }
  1091. if (lTone)
  1092. dwFlag |= 0x01;
  1093. else
  1094. dwFlag &= (~0x01);
  1095. return SetTapiReg(TAPI_FLAG, REG_DWORD, (LPBYTE)&dwFlag, sizeof(DWORD) );
  1096. }
  1097. STDMETHODIMP CTapiLocationInfo::GetCallWaiting(BSTR* pbstrCallWaiting)
  1098. {
  1099. DWORD dwFlag = 0;
  1100. DWORD dwSize = sizeof(dwFlag);
  1101. DWORD dwType = REG_DWORD;
  1102. HRESULT hr = S_OK;
  1103. BSTR bstrTmp = NULL;
  1104. if (NULL == pbstrCallWaiting)
  1105. {
  1106. hr = E_POINTER;
  1107. goto GetCallWaitingExit;
  1108. }
  1109. // Avoid returning rubbish in case of error
  1110. //
  1111. *pbstrCallWaiting = NULL;
  1112. // Allocate empty string for default return string
  1113. //
  1114. bstrTmp = SysAllocString(SZ_EMPTY);
  1115. if (NULL == bstrTmp)
  1116. {
  1117. hr = E_OUTOFMEMORY;
  1118. goto GetCallWaitingExit;
  1119. }
  1120. if (S_OK == GetTapiReg(TAPI_FLAG, &dwType, (LPBYTE)&dwFlag, &dwSize))
  1121. {
  1122. // If call waiting is not enabled, return default string
  1123. if (!(dwFlag & 0x04))
  1124. {
  1125. goto GetCallWaitingExit;
  1126. }
  1127. }
  1128. dwType = REG_SZ;
  1129. dwSize = sizeof(m_szCallWaiting);
  1130. hr = GetTapiReg(TAPI_CALLWAIT, &dwType, (LPBYTE)m_szCallWaiting, &dwSize);
  1131. if (FAILED(hr))
  1132. {
  1133. goto GetCallWaitingExit;
  1134. }
  1135. // Replace the default string with the retrieved string
  1136. //
  1137. if (! SysReAllocString(&bstrTmp, m_szCallWaiting))
  1138. {
  1139. hr = E_OUTOFMEMORY;
  1140. goto GetCallWaitingExit;
  1141. }
  1142. GetCallWaitingExit:
  1143. if (SUCCEEDED(hr))
  1144. {
  1145. *pbstrCallWaiting = bstrTmp;
  1146. bstrTmp = NULL;
  1147. }
  1148. else
  1149. {
  1150. if (NULL != bstrTmp)
  1151. {
  1152. SysFreeString(bstrTmp);
  1153. }
  1154. }
  1155. return hr;
  1156. }
  1157. STDMETHODIMP CTapiLocationInfo::PutCallWaiting(BSTR bstrCallWaiting)
  1158. {
  1159. DWORD dwFlag = 0;
  1160. DWORD dwSize = sizeof(dwFlag);
  1161. DWORD dwType = REG_DWORD;
  1162. HRESULT hr = S_OK;
  1163. // Is the BSTR null-terminated?
  1164. assert(lstrlen(bstrCallWaiting) <= SysStringLen(bstrCallWaiting));
  1165. if (bstrCallWaiting == NULL || SysStringLen(bstrCallWaiting) == 0)
  1166. {
  1167. if (S_OK == GetTapiReg(TAPI_FLAG, &dwType, (LPBYTE)&dwFlag, &dwSize))
  1168. {
  1169. dwFlag &= (~0x04);
  1170. hr = SetTapiReg(TAPI_FLAG, REG_DWORD, (LPBYTE)&dwFlag, sizeof(DWORD) );
  1171. }
  1172. }
  1173. else
  1174. {
  1175. if (S_OK == GetTapiReg(TAPI_FLAG, &dwType, (LPBYTE)&dwFlag, &dwSize))
  1176. {
  1177. dwFlag |= 0x04;
  1178. }
  1179. else
  1180. {
  1181. // Value doesn't exist yet
  1182. //
  1183. dwFlag = (DWORD)0x04;
  1184. }
  1185. dwSize = BYTES_REQUIRED_BY_SZ(bstrCallWaiting);
  1186. hr = SetTapiReg(TAPI_CALLWAIT, REG_SZ, (LPBYTE)bstrCallWaiting, dwSize);
  1187. if (SUCCEEDED(hr))
  1188. {
  1189. hr = SetTapiReg(TAPI_FLAG, REG_DWORD, (LPBYTE)&dwFlag, sizeof(DWORD) );
  1190. }
  1191. }
  1192. return hr;
  1193. }
  1194. void CTapiLocationInfo::DeleteTapiInfo()
  1195. {
  1196. HKEY hKey;
  1197. DWORD dwRun = 0;
  1198. if (!m_bTapiCountrySet && !m_bTapiAvailable)
  1199. {
  1200. // We need to remove the tapi data.
  1201. //
  1202. RegDeleteKey(HKEY_LOCAL_MACHINE, TAPI_PATH_LOC0);
  1203. if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TAPI_PATH_LOCATIONS, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS )
  1204. {
  1205. RegDeleteValue(hKey, TAPI_NUMENTRIES);
  1206. RegDeleteValue(hKey, TAPI_CURRENTID);
  1207. RegDeleteValue(hKey, TAPI_NEXTID);
  1208. RegCloseKey(hKey);
  1209. }
  1210. // Now pretend that we didn't create these entries so we don't clean up twice
  1211. // (2nd instance case)
  1212. m_bTapiCountrySet = TRUE;
  1213. }
  1214. }
  1215. STDMETHODIMP CTapiLocationInfo::TapiServiceRunning(BOOL *pbRet)
  1216. {
  1217. SC_HANDLE sc_handle;
  1218. SC_HANDLE sc_service;
  1219. SERVICE_STATUS service_status;
  1220. TRACE(L"TapiServiceRunning");
  1221. *pbRet = FALSE;
  1222. sc_handle = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
  1223. if (sc_handle)
  1224. {
  1225. TRACE(L"OpenSCManager succeeded");
  1226. sc_service = OpenService(sc_handle, TEXT("TAPISRV"), SERVICE_QUERY_STATUS);
  1227. if (sc_service)
  1228. {
  1229. TRACE(L"OpenService succeeded");
  1230. if (QueryServiceStatus(sc_service, &service_status ))
  1231. {
  1232. *pbRet = (service_status.dwCurrentState == SERVICE_RUNNING);
  1233. }
  1234. else
  1235. {
  1236. TRACE1(L"QueryServiceStatus failed with %lx", GetLastError());
  1237. }
  1238. CloseServiceHandle(sc_service);
  1239. }
  1240. else
  1241. {
  1242. TRACE1(L"OpenService failed. GetLastError()=%lx",GetLastError());
  1243. }
  1244. CloseServiceHandle(sc_handle);
  1245. }
  1246. return S_OK;
  1247. }
  1248. void CTapiLocationInfo::CheckModemCountry()
  1249. /*++
  1250. Routine description:
  1251. This is soft modem workaround provided by unimodem team. It should be called
  1252. before dialing when the TAPI country code is changed in OOBE. Also, it
  1253. should be called during OEM install only, as GUI mode setup handles TAPI
  1254. configuration for upgrade and clean install.
  1255. The problem we have is that:
  1256. 1. Some vendors set the GCI code incorrectly based on the TAPI location
  1257. key (which is a bad thing L)
  1258. 2. Some modems do not conform to GCI
  1259. 3. Some modems do not correctly accept AT+GCI commands.
  1260. (+GCI is Modems AT commands for setting country)
  1261. The conformance check ensures the GCI value is properly sync
  1262. with the TAPI location. It disables GCI if the modem does not conform
  1263. to the GCI spec.
  1264. Note:
  1265. This function can take as long as 15 seconds. We should make sure the UI
  1266. doesn't appear to hang during the call.
  1267. --*/
  1268. {
  1269. typedef void (*COUNTRYRUNONCE)();
  1270. if (m_bCheckModemCountry)
  1271. {
  1272. TCHAR szIniFile[MAX_PATH];
  1273. if (GetCanonicalizedPath(szIniFile, INI_SETTINGS_FILENAME))
  1274. {
  1275. UINT bCheckModem = GetPrivateProfileInt(
  1276. OPTIONS_SECTION,
  1277. CHECK_MODEMGCI,
  1278. 0,
  1279. szIniFile);
  1280. if (bCheckModem)
  1281. {
  1282. HMODULE hLib;
  1283. hLib=LoadLibrary(TEXT("modemui.dll"));
  1284. if (hLib != NULL)
  1285. {
  1286. COUNTRYRUNONCE Proc;
  1287. Proc=(COUNTRYRUNONCE)GetProcAddress(hLib,"CountryRunOnce");
  1288. if (Proc != NULL)
  1289. {
  1290. TRACE(L"Start modemui!CountryRunOnce");
  1291. Proc();
  1292. TRACE(L"End modemui!CountryRunOnce");
  1293. }
  1294. FreeLibrary(hLib);
  1295. }
  1296. }
  1297. }
  1298. m_bCheckModemCountry = FALSE;
  1299. }
  1300. }