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.

1568 lines
44 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. if (m_szAllCountryPairs)
  475. {
  476. GlobalFree(m_szAllCountryPairs);
  477. }
  478. if (m_pLineCountryList)
  479. {
  480. GlobalFree(m_pLineCountryList);
  481. }
  482. if (m_rgNameLookUp)
  483. {
  484. GlobalFree(m_rgNameLookUp);
  485. }
  486. if (m_pTC)
  487. {
  488. GlobalFree(m_pTC);
  489. }
  490. }
  491. const WCHAR gszInternationalSec[] = L"intl";
  492. const WCHAR gszCountryEntry[] = L"iCountry";
  493. STDMETHODIMP CTapiLocationInfo::InitTapiInfo(BOOL* pbRetVal)
  494. {
  495. HRESULT hr = ERROR_SUCCESS;
  496. DWORD cDevices =0;
  497. DWORD dwCurDev = 0;
  498. DWORD dwAPI = 0;
  499. LONG lrc = 0;
  500. LINEEXTENSIONID leid;
  501. LPVOID pv = NULL;
  502. DWORD dwCurLoc = 0;
  503. WCHAR szCountryCode[8];
  504. WCHAR szIniFile[MAX_PATH*2] = SZ_EMPTY;
  505. if (0 != m_dwCountryID)
  506. {
  507. // TAPI already initialized, don't do it again.
  508. *pbRetVal = m_bTapiAvailable;
  509. goto InitTapiInfoExit;
  510. }
  511. m_hLineApp=NULL;
  512. // Assume Failure
  513. *pbRetVal = FALSE;
  514. if (m_pTC)
  515. {
  516. GlobalFree(m_pTC);
  517. m_pTC = NULL;
  518. }
  519. m_bTapiAvailable = TRUE;
  520. hr = tapiGetLocationInfo(szCountryCode, m_szAreaCode);
  521. if (hr)
  522. {
  523. HKEY hKey = 0;
  524. m_bTapiAvailable = FALSE;
  525. // GetLocation failed. Normally we show the TAPI mini dialog which
  526. // has no cancel option, and the user is forced to enter info and hit OK.
  527. // In OOBE, we have to mimic this dialog in html, so here we will
  528. // give user country list, and default phone system
  529. // This code taken from dial.c in tapi32.dll
  530. m_dwCountryID = (DWORD)GetProfileInt( gszInternationalSec,
  531. gszCountryEntry,
  532. 1 );
  533. // create necessary tapi keys
  534. *pbRetVal = TRUE; // Getting here means everything worked
  535. HRESULT hr = RegCreateKey(HKEY_LOCAL_MACHINE, TAPI_PATH_LOC0, &hKey);
  536. if (hr != ERROR_SUCCESS)
  537. {
  538. *pbRetVal = FALSE;
  539. }
  540. else
  541. {
  542. RegSetValueEx(hKey, TAPI_CALLWAIT, 0, REG_SZ, (LPBYTE)NULL_SZ, BYTES_REQUIRED_BY_SZ(NULL_SZ) );
  543. HINSTANCE hInst = GetModuleHandle(L"msobmain.dll");
  544. WCHAR szTapiNewLoc[MAX_PATH];
  545. LoadString(hInst, IDS_TAPI_NEWLOC, szTapiNewLoc, MAX_CHARS_IN_BUFFER(szTapiNewLoc));
  546. RegSetValueEx(hKey, TAPI_NAME, 0, REG_SZ, (LPBYTE)szTapiNewLoc, BYTES_REQUIRED_BY_SZ(szTapiNewLoc) );
  547. RegCloseKey(hKey);
  548. }
  549. if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, TAPI_PATH_LOCATIONS, &hKey))
  550. {
  551. DWORD dwVal;
  552. DWORD dwSize = sizeof(dwVal);
  553. dwVal = 0;
  554. hr = RegSetValueEx(hKey, TAPI_CURRENTID, 0, REG_DWORD, (LPBYTE)&dwVal, sizeof(DWORD));
  555. RegQueryValueEx(hKey, TAPI_NUMENTRIES, 0, NULL, (LPBYTE)&dwVal, &dwSize);
  556. dwVal++; //bump the entry count up
  557. RegSetValueEx(hKey, TAPI_NUMENTRIES, 0, REG_DWORD, (LPBYTE)&dwVal, sizeof(DWORD));
  558. RegCloseKey(hKey);
  559. }
  560. *pbRetVal = FALSE;
  561. }
  562. else
  563. {
  564. DWORD dwFlag = REG_DWORD;
  565. DWORD dwSize = sizeof(dwFlag);
  566. DWORD dwType = 0;
  567. if (S_OK != GetTapiReg(TAPI_COUNTRY, &dwType, (LPBYTE)&dwFlag, &dwSize))
  568. {
  569. m_bTapiAvailable = FALSE;
  570. goto InitTapiInfoExit;
  571. }
  572. // Get CountryID from TAPI
  573. m_hLineApp = NULL;
  574. // Get the handle to the line app
  575. lineInitialize(&m_hLineApp, NULL, LineCallback, NULL, &cDevices);
  576. if (!m_hLineApp)
  577. {
  578. goto InitTapiInfoExit;
  579. }
  580. if (cDevices)
  581. {
  582. // Get the TAPI API version
  583. //
  584. dwCurDev = 0;
  585. dwAPI = 0;
  586. lrc = -1;
  587. while (lrc && dwCurDev < cDevices)
  588. {
  589. // NOTE: device ID's are 0 based
  590. ZeroMemory(&leid, sizeof(leid));
  591. lrc = lineNegotiateAPIVersion(m_hLineApp, dwCurDev,0x00010004,0x00010004,&dwAPI,&leid);
  592. dwCurDev++;
  593. }
  594. if (lrc)
  595. {
  596. // TAPI and us can't agree on anything so nevermind...
  597. goto InitTapiInfoExit;
  598. }
  599. // Find the CountryID in the translate cap structure
  600. m_pTC = (LINETRANSLATECAPS *)GlobalAlloc(GPTR, sizeof(LINETRANSLATECAPS));
  601. if (!m_pTC)
  602. {
  603. // we are in real trouble here, get out!
  604. hr = ERROR_NOT_ENOUGH_MEMORY;
  605. goto InitTapiInfoExit;
  606. }
  607. // Get the needed size
  608. m_pTC->dwTotalSize = sizeof(LINETRANSLATECAPS);
  609. lrc = lineGetTranslateCaps(m_hLineApp, dwAPI,m_pTC);
  610. if(lrc)
  611. {
  612. goto InitTapiInfoExit;
  613. }
  614. pv = GlobalAlloc(GPTR, ((size_t)m_pTC->dwNeededSize));
  615. if (!pv)
  616. {
  617. hr = ERROR_NOT_ENOUGH_MEMORY;
  618. goto InitTapiInfoExit;
  619. }
  620. ((LINETRANSLATECAPS*)pv)->dwTotalSize = m_pTC->dwNeededSize;
  621. m_pTC = (LINETRANSLATECAPS*)pv;
  622. pv = NULL;
  623. lrc = lineGetTranslateCaps(m_hLineApp, dwAPI,m_pTC);
  624. if(lrc)
  625. {
  626. goto InitTapiInfoExit;
  627. }
  628. // sanity check
  629. // Assert(m_pTC->dwLocationListOffset);
  630. // We have the Number of TAPI locations, so save it now
  631. m_wNumTapiLocations = (WORD)m_pTC->dwNumLocations;
  632. // Loop through the locations to find the correct country code
  633. m_plle = LPLINELOCATIONENTRY (PBYTE(m_pTC) + m_pTC->dwLocationListOffset);
  634. for (dwCurLoc = 0; dwCurLoc < m_pTC->dwNumLocations; dwCurLoc++)
  635. {
  636. if (m_pTC->dwCurrentLocationID == m_plle->dwPermanentLocationID)
  637. {
  638. m_dwCountryID = m_plle->dwCountryID;
  639. m_dwCurrLoc = dwCurLoc;
  640. break; // for loop
  641. }
  642. m_plle++;
  643. }
  644. // If we could not find it in the above loop, default to US
  645. if (!m_dwCountryID)
  646. {
  647. m_dwCountryID = 1;
  648. goto InitTapiInfoExit;
  649. }
  650. }
  651. *pbRetVal = TRUE; // Getting here means everything worked
  652. }
  653. // Settings in INI_SETTINGS_FILENAME should initialize or override the
  654. // system's Tapi configuration.
  655. if (GetCanonicalizedPath(szIniFile, INI_SETTINGS_FILENAME))
  656. {
  657. //
  658. // [Options]
  659. // Tonepulse = 0 for pulse, 1 for tone
  660. // Areacode = {string}
  661. // OutsideLine = {string}
  662. // DisableCallWaiting = {string}
  663. //
  664. LONG lTonDialing = (BOOL) GetPrivateProfileInt(OPTIONS_SECTION,
  665. TONEPULSE,
  666. -1,
  667. szIniFile);
  668. if (lTonDialing != -1)
  669. {
  670. PutPhoneSystem(lTonDialing);
  671. }
  672. if (GetPrivateProfileString(OPTIONS_SECTION,
  673. AREACODE,
  674. L"\0",
  675. m_szAreaCode,
  676. MAX_CHARS_IN_BUFFER(m_szAreaCode),
  677. szIniFile))
  678. {
  679. PutbstrAreaCode(SysAllocString(m_szAreaCode));
  680. }
  681. if (GetPrivateProfileString(OPTIONS_SECTION,
  682. OUTSIDELINE,
  683. L"\0",
  684. m_szDialOut,
  685. MAX_CHARS_IN_BUFFER(m_szDialOut),
  686. szIniFile))
  687. {
  688. PutOutsideDial(SysAllocString(m_szDialOut));
  689. }
  690. if (GetPrivateProfileString(OPTIONS_SECTION,
  691. DISABLECALLWAITING,
  692. L"\0",
  693. m_szCallWaiting,
  694. MAX_CHARS_IN_BUFFER(m_szCallWaiting),
  695. szIniFile))
  696. {
  697. PutCallWaiting(SysAllocString(m_szCallWaiting));
  698. }
  699. }
  700. InitTapiInfoExit:
  701. // if we can't figure it out because TAPI is messed up just default to
  702. // the US. The user will still have the chance to pick the right answer.
  703. if (!m_dwCountryID) {
  704. m_dwCountryID = 1;
  705. }
  706. if (m_hLineApp)
  707. {
  708. lineShutdown(m_hLineApp);
  709. m_hLineApp = NULL;
  710. }
  711. m_lNumOfCountry = 0;
  712. GetNumCountries(&m_lNumOfCountry);
  713. return S_OK;
  714. }
  715. STDMETHODIMP CTapiLocationInfo::GetlCountryIndex(long * plVal)
  716. {
  717. *plVal = m_dwComboCountryIndex;
  718. return S_OK;
  719. }
  720. STDMETHODIMP CTapiLocationInfo::SetlCountryIndex(long lVal)
  721. {
  722. HRESULT hr = E_FAIL;
  723. // Write to registry
  724. if (lVal < m_lNumOfCountry && lVal > -1)
  725. {
  726. m_bTapiCountrySet = TRUE;
  727. m_dwCountryID = m_rgNameLookUp[lVal].pLCE->dwCountryID;
  728. m_dwCountrycode = m_rgNameLookUp[lVal].pLCE->dwCountryCode;
  729. m_dwComboCountryIndex = lVal;
  730. hr = SetTapiReg(TAPI_COUNTRY, REG_DWORD, (LPBYTE)&m_rgNameLookUp[lVal].pLCE->dwCountryID, sizeof(DWORD) );
  731. }
  732. if (SUCCEEDED(hr))
  733. {
  734. m_bCheckModemCountry = TRUE;
  735. }
  736. return hr;
  737. }
  738. STDMETHODIMP CTapiLocationInfo::GetCountryID(DWORD* dwCountryID)
  739. {
  740. MYASSERT( m_dwCountryID );
  741. *dwCountryID = m_dwCountryID;
  742. return S_OK;
  743. }
  744. STDMETHODIMP CTapiLocationInfo::GetCountryCode(DWORD* dwCountryCode)
  745. {
  746. *dwCountryCode = m_dwCountrycode;
  747. return S_OK;
  748. }
  749. STDMETHODIMP CTapiLocationInfo::GetNumCountries(long *plNumOfCountry)
  750. {
  751. USES_CONVERSION;
  752. LPLINECOUNTRYLIST pLineCountryTemp = NULL;
  753. LPLINECOUNTRYENTRY pLCETemp;
  754. DWORD idx;
  755. DWORD dwCurLID = 0;
  756. HINSTANCE hTapi32Dll = NULL;
  757. FARPROC fp;
  758. BOOL bBookLoaded = FALSE;
  759. HRESULT hr = S_OK;
  760. if (NULL == plNumOfCountry)
  761. goto GetNumCountriesExit;
  762. // Avoid returning rubbish
  763. //
  764. *plNumOfCountry = 0;
  765. if (m_lNumOfCountry != 0)
  766. {
  767. *plNumOfCountry = m_lNumOfCountry;
  768. goto GetNumCountriesExit;
  769. }
  770. hTapi32Dll = LoadLibrary(L"tapi32.dll");
  771. if (hTapi32Dll)
  772. {
  773. fp = GetProcAddress(hTapi32Dll, "lineGetCountryW");
  774. if (!fp)
  775. {
  776. hr = GetLastError();
  777. goto GetNumCountriesExit;
  778. }
  779. // Get TAPI country list
  780. if (m_pLineCountryList)
  781. GlobalFree(m_pLineCountryList);
  782. m_pLineCountryList = (LPLINECOUNTRYLIST)GlobalAlloc(GPTR, sizeof(LINECOUNTRYLIST));
  783. if (!m_pLineCountryList)
  784. {
  785. hr = S_FALSE;
  786. goto GetNumCountriesExit;
  787. }
  788. m_pLineCountryList->dwTotalSize = sizeof(LINECOUNTRYLIST);
  789. idx = ((LINEGETCOUNTRY)fp)(0, 0x10003,m_pLineCountryList);
  790. if (idx && idx != LINEERR_STRUCTURETOOSMALL)
  791. {
  792. hr = S_FALSE;
  793. goto GetNumCountriesExit;
  794. }
  795. // Assert(m_pLineCountryList->dwNeededSize);
  796. pLineCountryTemp = (LPLINECOUNTRYLIST)GlobalAlloc(GPTR,
  797. (size_t)m_pLineCountryList->dwNeededSize);
  798. if (!pLineCountryTemp)
  799. {
  800. hr = S_FALSE;
  801. goto GetNumCountriesExit;
  802. }
  803. pLineCountryTemp->dwTotalSize = m_pLineCountryList->dwNeededSize;
  804. GlobalFree(m_pLineCountryList);
  805. m_pLineCountryList = pLineCountryTemp;
  806. pLineCountryTemp = NULL;
  807. if (((LINEGETCOUNTRY)fp)(0, 0x10003,m_pLineCountryList))
  808. {
  809. hr = S_FALSE;
  810. goto GetNumCountriesExit;
  811. }
  812. // look up array
  813. pLCETemp = (LPLINECOUNTRYENTRY)((DWORD_PTR)m_pLineCountryList +
  814. m_pLineCountryList->dwCountryListOffset);
  815. if(m_rgNameLookUp)
  816. GlobalFree(m_rgNameLookUp);
  817. m_rgNameLookUp = (LPCNTRYNAMELOOKUPELEMENT)GlobalAlloc(GPTR,
  818. (int)(sizeof(CNTRYNAMELOOKUPELEMENT) * m_pLineCountryList->dwNumCountries));
  819. if (!m_rgNameLookUp)
  820. {
  821. hr = S_FALSE;
  822. goto GetNumCountriesExit;
  823. }
  824. CNTRYNAMELOOKUPELEMENT CntryNameLUElement = {NULL, 0, NULL};
  825. CNTRYNAMELOOKUPELEMENT cnleUS = {NULL, 0, NULL};
  826. DWORD cbAllCountryPairs = 0;
  827. for (idx=0;idx<m_pLineCountryList->dwNumCountries;idx++)
  828. {
  829. m_rgNameLookUp[idx].psCountryName = (LPWSTR)((LPBYTE)m_pLineCountryList + (DWORD)pLCETemp[idx].dwCountryNameOffset);
  830. m_rgNameLookUp[idx].dwNameSize = pLCETemp[idx].dwCountryNameSize;
  831. m_rgNameLookUp[idx].pLCE = &pLCETemp[idx];
  832. #if 0
  833. TRACE2(L"GetNumCountries:%d:%s",
  834. m_rgNameLookUp[idx].pLCE->dwCountryID,
  835. m_rgNameLookUp[idx].psCountryName
  836. );
  837. #endif
  838. // Include space for NUL at end of unicode string
  839. //
  840. cbAllCountryPairs += m_rgNameLookUp[idx].dwNameSize + 2;
  841. // If TAPI is not available, we set the default to US
  842. if ( m_rgNameLookUp[idx].pLCE->dwCountryID == m_dwCountryID)
  843. {
  844. // Set the index to our default country in combo box
  845. m_dwComboCountryIndex = idx;
  846. m_dwCountrycode = m_rgNameLookUp[idx].pLCE->dwCountryCode;
  847. if (m_rgNameLookUp[idx].psCountryName)
  848. {
  849. m_bstrDefaultCountry = SysAllocString(m_rgNameLookUp[idx].psCountryName);
  850. }
  851. memcpy(&CntryNameLUElement, &m_rgNameLookUp[idx], sizeof(CNTRYNAMELOOKUPELEMENT));
  852. }
  853. else if (m_rgNameLookUp[idx].pLCE->dwCountryID == 1)
  854. {
  855. // Save the US info away in case we don't find the default
  856. memcpy(&cnleUS, &m_rgNameLookUp[idx], sizeof(CNTRYNAMELOOKUPELEMENT));
  857. }
  858. }
  859. // If we didn't find the default country, we're going to blow up.
  860. if (CntryNameLUElement.psCountryName == NULL)
  861. {
  862. TRACE1(L"Warning: Couldn't find country id %d. Defaulting to US.", m_dwCountryID);
  863. memcpy(&CntryNameLUElement, &cnleUS, sizeof(CNTRYNAMELOOKUPELEMENT));
  864. m_dwCountryID = 1;
  865. }
  866. MYASSERT( CntryNameLUElement.psCountryName );
  867. qsort(m_rgNameLookUp, (int)m_pLineCountryList->dwNumCountries,sizeof(CNTRYNAMELOOKUPELEMENT),
  868. CompareCntryNameLookUpElements);
  869. LPCNTRYNAMELOOKUPELEMENT pResult = (LPCNTRYNAMELOOKUPELEMENT)bsearch(&CntryNameLUElement, m_rgNameLookUp, (int)m_pLineCountryList->dwNumCountries,sizeof(CNTRYNAMELOOKUPELEMENT),
  870. CompareCntryNameLookUpElements);
  871. m_dwComboCountryIndex = (DWORD)((DWORD_PTR)pResult - (DWORD_PTR)m_rgNameLookUp) / sizeof(CNTRYNAMELOOKUPELEMENT);
  872. if (m_dwComboCountryIndex > m_pLineCountryList->dwNumCountries)
  873. m_dwComboCountryIndex = 0;
  874. *plNumOfCountry = m_pLineCountryList->dwNumCountries;
  875. m_lNumOfCountry = m_pLineCountryList->dwNumCountries;
  876. // Create the SELECT tag for the html so it can get all the country names in one shot.
  877. if (m_szAllCountryPairs)
  878. GlobalFree(m_szAllCountryPairs);
  879. // BUGBUG: Does this calculation account for country name strings??
  880. cbAllCountryPairs += m_lNumOfCountry * sizeof(szOptionTag) + 1;
  881. m_szAllCountryPairs = (WCHAR *)GlobalAlloc(GPTR, cbAllCountryPairs );
  882. if (m_szAllCountryPairs)
  883. {
  884. WCHAR szBuffer[MAX_PATH];
  885. for (idx=0; idx < (DWORD)m_lNumOfCountry; idx++)
  886. {
  887. wsprintf(szBuffer, szOptionTag, m_rgNameLookUp[idx].psCountryName);
  888. lstrcat(m_szAllCountryPairs, szBuffer);
  889. }
  890. }
  891. }
  892. GetNumCountriesExit:
  893. if (hTapi32Dll)
  894. {
  895. FreeLibrary(hTapi32Dll);
  896. hTapi32Dll = NULL;
  897. }
  898. return hr;
  899. }
  900. STDMETHODIMP CTapiLocationInfo::GetAllCountryName(BSTR* pbstrAllCountryName)
  901. {
  902. if (pbstrAllCountryName == NULL)
  903. {
  904. return E_POINTER;
  905. }
  906. // Avoid returning rubbish
  907. //
  908. *pbstrAllCountryName = NULL;
  909. if (m_lNumOfCountry && pbstrAllCountryName && m_szAllCountryPairs)
  910. {
  911. *pbstrAllCountryName = SysAllocString(m_szAllCountryPairs);
  912. return S_OK;
  913. }
  914. return E_FAIL;
  915. }
  916. STDMETHODIMP CTapiLocationInfo::GetCountryName(long lCountryIndex, BSTR* pszCountryName)
  917. {
  918. USES_CONVERSION;
  919. if (lCountryIndex < m_lNumOfCountry && lCountryIndex >= 0)
  920. {
  921. *pszCountryName = SysAllocString(m_rgNameLookUp[lCountryIndex].psCountryName);
  922. return S_OK;
  923. }
  924. return E_FAIL;
  925. }
  926. STDMETHODIMP CTapiLocationInfo::GetDefaultCountry(long* lCountryIndex)
  927. {
  928. if (lCountryIndex)
  929. *lCountryIndex = m_dwComboCountryIndex;
  930. return S_OK;
  931. }
  932. STDMETHODIMP CTapiLocationInfo::PutCountry(long lCountryIndex)
  933. {
  934. return E_NOTIMPL;
  935. }
  936. STDMETHODIMP CTapiLocationInfo::GetbstrAreaCode(BSTR * pbstrAreaCode)
  937. {
  938. HRESULT hr = S_OK;
  939. DWORD dwType = REG_SZ;
  940. DWORD dwSize = sizeof(m_szAreaCode);
  941. BSTR bstrTmp = NULL;
  942. if (pbstrAreaCode == NULL)
  943. {
  944. hr = E_POINTER;
  945. goto GetbstrAreaCodeExit;
  946. }
  947. // Avoid returning rubbish
  948. //
  949. *pbstrAreaCode = NULL;
  950. // Allocate default return value
  951. //
  952. hr = GetTapiReg(TAPI_AREACODE, &dwType, (LPBYTE)m_szAreaCode, &dwSize);
  953. if (SUCCEEDED(hr))
  954. {
  955. bstrTmp = SysAllocString(m_szAreaCode);
  956. }
  957. else
  958. {
  959. bstrTmp = SysAllocString(SZ_EMPTY);
  960. }
  961. // A valid string can be returned (though it may be empty) so we've
  962. // succeeded.
  963. //
  964. hr = S_OK;
  965. GetbstrAreaCodeExit:
  966. if (SUCCEEDED(hr))
  967. {
  968. *pbstrAreaCode = bstrTmp;
  969. bstrTmp = NULL;
  970. }
  971. return hr;
  972. }
  973. STDMETHODIMP CTapiLocationInfo::PutbstrAreaCode(BSTR bstrAreaCode)
  974. {
  975. LPWSTR szAreaCode = (NULL != bstrAreaCode) ? bstrAreaCode : SZ_EMPTY;
  976. DWORD dwSize = BYTES_REQUIRED_BY_SZ(szAreaCode);
  977. SetTapiReg(TAPI_AREACODE, REG_SZ, (LPBYTE)szAreaCode, dwSize);
  978. return S_OK;
  979. }
  980. STDMETHODIMP CTapiLocationInfo::IsAreaCodeRequired(long lVal, BOOL *pbVal)
  981. {
  982. LPWSTR szAreaCodeRule = NULL;
  983. LPWSTR szLongDistanceRule = NULL;
  984. if (!pbVal)
  985. return E_POINTER;
  986. *pbVal = FALSE;
  987. if (lVal < m_lNumOfCountry && lVal > -1 && m_pLineCountryList)
  988. {
  989. szAreaCodeRule = (LPWSTR)m_pLineCountryList + m_rgNameLookUp[lVal].pLCE->dwSameAreaRuleOffset;
  990. szLongDistanceRule = (LPWSTR)m_pLineCountryList + m_rgNameLookUp[lVal].pLCE->dwLongDistanceRuleOffset;
  991. if (szAreaCodeRule && szLongDistanceRule)
  992. {
  993. *pbVal = (NULL != StrChr(szAreaCodeRule, L'F')) || (NULL != StrChr(szLongDistanceRule, 'F'));
  994. }
  995. }
  996. return S_OK;
  997. }
  998. STDMETHODIMP CTapiLocationInfo::GetOutsideDial(BSTR * pbstrOutside)
  999. {
  1000. DWORD dwType = REG_SZ;
  1001. DWORD dwSize = sizeof(m_szDialOut);
  1002. HRESULT hr = S_OK;
  1003. BSTR bstrTmp = NULL;
  1004. if (pbstrOutside == NULL)
  1005. {
  1006. hr = E_POINTER;
  1007. goto GetOutsideDialExit;
  1008. }
  1009. // Avoid returning rubbish in case of error
  1010. //
  1011. *pbstrOutside = NULL;
  1012. // Allocate empty string for default return string
  1013. //
  1014. bstrTmp = SysAllocString(SZ_EMPTY);
  1015. if (NULL == bstrTmp)
  1016. {
  1017. hr = E_OUTOFMEMORY;
  1018. goto GetOutsideDialExit;
  1019. }
  1020. hr = GetTapiReg(TAPI_OUTSIDE, &dwType, (LPBYTE)m_szDialOut, &dwSize);
  1021. if FAILED(hr)
  1022. {
  1023. goto GetOutsideDialExit;
  1024. }
  1025. if (! SysReAllocString(&bstrTmp, m_szDialOut))
  1026. {
  1027. hr = E_OUTOFMEMORY;
  1028. goto GetOutsideDialExit;
  1029. }
  1030. GetOutsideDialExit:
  1031. if (SUCCEEDED(hr))
  1032. {
  1033. *pbstrOutside = bstrTmp;
  1034. }
  1035. else
  1036. {
  1037. if (NULL != bstrTmp)
  1038. {
  1039. SysFreeString(bstrTmp);
  1040. }
  1041. }
  1042. bstrTmp = NULL;
  1043. return hr;
  1044. }
  1045. STDMETHODIMP CTapiLocationInfo::PutOutsideDial(BSTR bstrOutside)
  1046. {
  1047. // Is the bstr null-terminated??
  1048. assert(lstrlen(bstrOutside) <= SysStringLen(bstrOutside));
  1049. // If no string is passed in, default to empty string
  1050. //
  1051. lstrcpyn(
  1052. m_szDialOut,
  1053. (NULL != bstrOutside) ? bstrOutside : SZ_EMPTY,
  1054. MAX_CHARS_IN_BUFFER(m_szDialOut));
  1055. DWORD dwSize = BYTES_REQUIRED_BY_SZ(m_szDialOut);
  1056. HRESULT hr = SetTapiReg(TAPI_OUTSIDE, REG_SZ, (LPBYTE)m_szDialOut, dwSize);
  1057. if (SUCCEEDED(hr))
  1058. {
  1059. hr = SetTapiReg(TAPI_LONGDIST, REG_SZ, (LPBYTE)m_szDialOut, dwSize);
  1060. }
  1061. return hr;
  1062. }
  1063. STDMETHODIMP CTapiLocationInfo::GetPhoneSystem(long* plTone)
  1064. {
  1065. DWORD dwFlag = REG_DWORD;
  1066. DWORD dwSize = sizeof(dwFlag);
  1067. DWORD dwType = 0;
  1068. if (NULL == plTone)
  1069. return E_FAIL;
  1070. *plTone = 1;
  1071. if (S_OK == GetTapiReg(TAPI_FLAG, &dwType, (LPBYTE)&dwFlag, &dwSize))
  1072. {
  1073. *plTone = dwFlag & 0x01;
  1074. }
  1075. return S_OK;
  1076. }
  1077. STDMETHODIMP CTapiLocationInfo::PutPhoneSystem(long lTone)
  1078. {
  1079. DWORD dwFlag = REG_DWORD;
  1080. DWORD dwSize = sizeof(dwFlag);
  1081. DWORD dwType = 0;
  1082. if (S_OK != GetTapiReg(TAPI_FLAG, &dwType, (LPBYTE)&dwFlag, &dwSize))
  1083. {
  1084. dwFlag = 0;
  1085. }
  1086. if (lTone)
  1087. dwFlag |= 0x01;
  1088. else
  1089. dwFlag &= (~0x01);
  1090. return SetTapiReg(TAPI_FLAG, REG_DWORD, (LPBYTE)&dwFlag, sizeof(DWORD) );
  1091. }
  1092. STDMETHODIMP CTapiLocationInfo::GetCallWaiting(BSTR* pbstrCallWaiting)
  1093. {
  1094. DWORD dwFlag = 0;
  1095. DWORD dwSize = sizeof(dwFlag);
  1096. DWORD dwType = REG_DWORD;
  1097. HRESULT hr = S_OK;
  1098. BSTR bstrTmp = NULL;
  1099. if (NULL == pbstrCallWaiting)
  1100. {
  1101. hr = E_POINTER;
  1102. goto GetCallWaitingExit;
  1103. }
  1104. // Avoid returning rubbish in case of error
  1105. //
  1106. *pbstrCallWaiting = NULL;
  1107. // Allocate empty string for default return string
  1108. //
  1109. bstrTmp = SysAllocString(SZ_EMPTY);
  1110. if (NULL == bstrTmp)
  1111. {
  1112. hr = E_OUTOFMEMORY;
  1113. goto GetCallWaitingExit;
  1114. }
  1115. if (S_OK == GetTapiReg(TAPI_FLAG, &dwType, (LPBYTE)&dwFlag, &dwSize))
  1116. {
  1117. // If call waiting is not enabled, return default string
  1118. if (!(dwFlag & 0x04))
  1119. {
  1120. goto GetCallWaitingExit;
  1121. }
  1122. }
  1123. dwType = REG_SZ;
  1124. dwSize = sizeof(m_szCallWaiting);
  1125. hr = GetTapiReg(TAPI_CALLWAIT, &dwType, (LPBYTE)m_szCallWaiting, &dwSize);
  1126. if (FAILED(hr))
  1127. {
  1128. goto GetCallWaitingExit;
  1129. }
  1130. // Replace the default string with the retrieved string
  1131. //
  1132. if (! SysReAllocString(&bstrTmp, m_szCallWaiting))
  1133. {
  1134. hr = E_OUTOFMEMORY;
  1135. goto GetCallWaitingExit;
  1136. }
  1137. GetCallWaitingExit:
  1138. if (SUCCEEDED(hr))
  1139. {
  1140. *pbstrCallWaiting = bstrTmp;
  1141. bstrTmp = NULL;
  1142. }
  1143. else
  1144. {
  1145. if (NULL != bstrTmp)
  1146. {
  1147. SysFreeString(bstrTmp);
  1148. }
  1149. }
  1150. return hr;
  1151. }
  1152. STDMETHODIMP CTapiLocationInfo::PutCallWaiting(BSTR bstrCallWaiting)
  1153. {
  1154. DWORD dwFlag = 0;
  1155. DWORD dwSize = sizeof(dwFlag);
  1156. DWORD dwType = REG_DWORD;
  1157. HRESULT hr = S_OK;
  1158. // Is the BSTR null-terminated?
  1159. assert(lstrlen(bstrCallWaiting) <= SysStringLen(bstrCallWaiting));
  1160. if (bstrCallWaiting == NULL || SysStringLen(bstrCallWaiting) == 0)
  1161. {
  1162. if (S_OK == GetTapiReg(TAPI_FLAG, &dwType, (LPBYTE)&dwFlag, &dwSize))
  1163. {
  1164. dwFlag &= (~0x04);
  1165. hr = SetTapiReg(TAPI_FLAG, REG_DWORD, (LPBYTE)&dwFlag, sizeof(DWORD) );
  1166. }
  1167. }
  1168. else
  1169. {
  1170. if (S_OK == GetTapiReg(TAPI_FLAG, &dwType, (LPBYTE)&dwFlag, &dwSize))
  1171. {
  1172. dwFlag |= 0x04;
  1173. }
  1174. else
  1175. {
  1176. // Value doesn't exist yet
  1177. //
  1178. dwFlag = (DWORD)0x04;
  1179. }
  1180. dwSize = BYTES_REQUIRED_BY_SZ(bstrCallWaiting);
  1181. hr = SetTapiReg(TAPI_CALLWAIT, REG_SZ, (LPBYTE)bstrCallWaiting, dwSize);
  1182. if (SUCCEEDED(hr))
  1183. {
  1184. hr = SetTapiReg(TAPI_FLAG, REG_DWORD, (LPBYTE)&dwFlag, sizeof(DWORD) );
  1185. }
  1186. }
  1187. return hr;
  1188. }
  1189. void CTapiLocationInfo::DeleteTapiInfo()
  1190. {
  1191. HKEY hKey;
  1192. DWORD dwRun = 0;
  1193. if (!m_bTapiCountrySet && !m_bTapiAvailable)
  1194. {
  1195. // We need to remove the tapi data.
  1196. //
  1197. RegDeleteKey(HKEY_LOCAL_MACHINE, TAPI_PATH_LOC0);
  1198. if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TAPI_PATH_LOCATIONS, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS )
  1199. {
  1200. RegDeleteValue(hKey, TAPI_NUMENTRIES);
  1201. RegDeleteValue(hKey, TAPI_CURRENTID);
  1202. RegDeleteValue(hKey, TAPI_NEXTID);
  1203. RegCloseKey(hKey);
  1204. }
  1205. // Now pretend that we didn't create these entries so we don't clean up twice
  1206. // (2nd instance case)
  1207. m_bTapiCountrySet = TRUE;
  1208. }
  1209. }
  1210. STDMETHODIMP CTapiLocationInfo::TapiServiceRunning(BOOL *pbRet)
  1211. {
  1212. SC_HANDLE sc_handle;
  1213. SC_HANDLE sc_service;
  1214. SERVICE_STATUS service_status;
  1215. TRACE(L"TapiServiceRunning");
  1216. *pbRet = FALSE;
  1217. sc_handle = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
  1218. if (sc_handle)
  1219. {
  1220. TRACE(L"OpenSCManager succeeded");
  1221. sc_service = OpenService(sc_handle, TEXT("TAPISRV"), SERVICE_QUERY_STATUS);
  1222. if (sc_service)
  1223. {
  1224. TRACE(L"OpenService succeeded");
  1225. if (QueryServiceStatus(sc_service, &service_status ))
  1226. {
  1227. *pbRet = (service_status.dwCurrentState == SERVICE_RUNNING);
  1228. }
  1229. else
  1230. {
  1231. TRACE1(L"QueryServiceStatus failed with %lx", GetLastError());
  1232. }
  1233. CloseServiceHandle(sc_service);
  1234. }
  1235. else
  1236. {
  1237. TRACE1(L"OpenService failed. GetLastError()=%lx",GetLastError());
  1238. }
  1239. CloseServiceHandle(sc_handle);
  1240. }
  1241. return S_OK;
  1242. }
  1243. void CTapiLocationInfo::CheckModemCountry()
  1244. /*++
  1245. Routine description:
  1246. This is soft modem workaround provided by unimodem team. It should be called
  1247. before dialing when the TAPI country code is changed in OOBE. Also, it
  1248. should be called during OEM install only, as GUI mode setup handles TAPI
  1249. configuration for upgrade and clean install.
  1250. The problem we have is that:
  1251. 1. Some vendors set the GCI code incorrectly based on the TAPI location
  1252. key (which is a bad thing L)
  1253. 2. Some modems do not conform to GCI
  1254. 3. Some modems do not correctly accept AT+GCI commands.
  1255. (+GCI is Modems AT commands for setting country)
  1256. The conformance check ensures the GCI value is properly sync
  1257. with the TAPI location. It disables GCI if the modem does not conform
  1258. to the GCI spec.
  1259. Note:
  1260. This function can take as long as 15 seconds. We should make sure the UI
  1261. doesn't appear to hang during the call.
  1262. --*/
  1263. {
  1264. typedef void (*COUNTRYRUNONCE)();
  1265. if (m_bCheckModemCountry)
  1266. {
  1267. TCHAR szIniFile[MAX_PATH];
  1268. if (GetCanonicalizedPath(szIniFile, INI_SETTINGS_FILENAME))
  1269. {
  1270. UINT bCheckModem = GetPrivateProfileInt(
  1271. OPTIONS_SECTION,
  1272. CHECK_MODEMGCI,
  1273. 0,
  1274. szIniFile);
  1275. if (bCheckModem)
  1276. {
  1277. HMODULE hLib;
  1278. hLib=LoadLibrary(TEXT("modemui.dll"));
  1279. if (hLib != NULL)
  1280. {
  1281. COUNTRYRUNONCE Proc;
  1282. Proc=(COUNTRYRUNONCE)GetProcAddress(hLib,"CountryRunOnce");
  1283. if (Proc != NULL)
  1284. {
  1285. TRACE(L"Start modemui!CountryRunOnce");
  1286. Proc();
  1287. TRACE(L"End modemui!CountryRunOnce");
  1288. }
  1289. FreeLibrary(hLib);
  1290. }
  1291. }
  1292. }
  1293. m_bCheckModemCountry = FALSE;
  1294. }
  1295. }