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.

2424 lines
74 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. tapidb.h
  7. FILE HISTORY:
  8. */
  9. #include "stdafx.h"
  10. #include "DynamLnk.h"
  11. #include "tapidb.h"
  12. #include "security.h"
  13. #include "lm.h"
  14. #include "service.h"
  15. #include <shlwapi.h>
  16. #include <shlwapip.h>
  17. #define DEFAULT_SECURITY_PKG _T("negotiate")
  18. #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
  19. #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
  20. // internal functions
  21. BOOL IsUserAdmin(LPCTSTR pszMachine, PSID AccountSid);
  22. BOOL LookupAliasFromRid(LPWSTR TargetComputer, DWORD Rid, LPWSTR Name, PDWORD cchName);
  23. DWORD ValidateDomainAccount(IN CString Machine, IN CString UserName, IN CString Domain, OUT PSID * AccountSid);
  24. NTSTATUS ValidatePassword(IN LPCWSTR UserName, IN LPCWSTR Domain, IN LPCWSTR Password);
  25. DWORD GetCurrentUser(CString & strAccount);
  26. DEBUG_DECLARE_INSTANCE_COUNTER(CTapiInfo);
  27. DynamicDLL g_TapiDLL( _T("TAPI32.DLL"), g_apchFunctionNames );
  28. CTapiInfo::CTapiInfo()
  29. : m_hServer(NULL),
  30. m_pTapiConfig(NULL),
  31. m_pProviderList(NULL),
  32. m_pAvailProviderList(NULL),
  33. m_hReinit(NULL),
  34. m_dwApiVersion(TAPI_CURRENT_VERSION),
  35. m_hResetEvent(NULL),
  36. m_cRef(1),
  37. m_fIsLocalMachine(FALSE),
  38. m_dwCachedLineSize(0),
  39. m_dwCachedPhoneSize(0),
  40. m_fCacheDirty(0)
  41. {
  42. DEBUG_INCREMENT_INSTANCE_COUNTER(CTapiInfo);
  43. for (int i = 0; i < DEVICE_TYPE_MAX; i++)
  44. m_paDeviceInfo[i] = NULL;
  45. }
  46. CTapiInfo::~CTapiInfo()
  47. {
  48. DEBUG_DECREMENT_INSTANCE_COUNTER(CTapiInfo);
  49. CSingleLock cl(&m_csData);
  50. if (m_hServer)
  51. {
  52. Destroy();
  53. }
  54. cl.Lock();
  55. if (m_pTapiConfig)
  56. {
  57. free(m_pTapiConfig);
  58. m_pTapiConfig = NULL;
  59. }
  60. for (int i = 0; i < DEVICE_TYPE_MAX; i++)
  61. {
  62. if (m_paDeviceInfo[i])
  63. {
  64. free(m_paDeviceInfo[i]);
  65. m_paDeviceInfo[i] = NULL;
  66. }
  67. }
  68. if (m_pProviderList)
  69. {
  70. free(m_pProviderList);
  71. m_pProviderList = NULL;
  72. }
  73. if (m_pAvailProviderList)
  74. {
  75. free(m_pAvailProviderList);
  76. m_pAvailProviderList = NULL;
  77. }
  78. if (m_hResetEvent)
  79. {
  80. CloseHandle(m_hResetEvent);
  81. m_hResetEvent = NULL;
  82. }
  83. cl.Unlock();
  84. }
  85. // Although this object is not a COM Interface, we want to be able to
  86. // take advantage of recounting, so we have basic addref/release/QI support
  87. IMPLEMENT_ADDREF_RELEASE(CTapiInfo)
  88. IMPLEMENT_SIMPLE_QUERYINTERFACE(CTapiInfo, ITapiInfo)
  89. /*!--------------------------------------------------------------------------
  90. CTapiInfo::Initialize()
  91. -
  92. Author: EricDav
  93. ---------------------------------------------------------------------------*/
  94. STDMETHODIMP
  95. CTapiInfo::Initialize()
  96. {
  97. HRESULT hr = hrOK;
  98. LONG lReturn = 0;
  99. if ( !g_TapiDLL.LoadFunctionPointers() )
  100. return S_OK;
  101. if (m_hServer)
  102. {
  103. // already initialized
  104. return S_OK;
  105. }
  106. CString strLocalMachineName;
  107. DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
  108. LPTSTR pBuf = strLocalMachineName.GetBuffer(dwSize);
  109. ::GetComputerName(pBuf, &dwSize);
  110. strLocalMachineName.ReleaseBuffer();
  111. if (m_strComputerName.IsEmpty())
  112. {
  113. m_strComputerName = strLocalMachineName;
  114. m_fIsLocalMachine = TRUE;
  115. Trace1("CTapiInfo::Initialize - Using local computer %s\n", m_strComputerName);
  116. }
  117. else
  118. {
  119. m_fIsLocalMachine = (0 == m_strComputerName.CompareNoCase(strLocalMachineName)) ?
  120. TRUE : FALSE;
  121. Trace1("CTapiInfo::Initialize - Using computer %s\n", m_strComputerName);
  122. }
  123. if (m_hResetEvent == NULL)
  124. {
  125. m_hResetEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  126. if (m_hResetEvent == NULL)
  127. {
  128. return HRESULT_FROM_WIN32(GetLastError());
  129. }
  130. }
  131. lReturn = ((INITIALIZE) g_TapiDLL[TAPI_INITIALIZE])(m_strComputerName, &m_hServer, &m_dwApiVersion, &m_hResetEvent);
  132. if (lReturn != ERROR_SUCCESS)
  133. {
  134. Trace1("CTapiInfo::Initialize - Initialize failed! %lx\n", lReturn);
  135. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  136. }
  137. // check to see if the local user is an admin on the machine
  138. ::IsAdmin(m_strComputerName, NULL, NULL, &m_fIsAdmin);
  139. // get the local user name for later to compare against list of tapi admins
  140. GetCurrentUser();
  141. return hr;
  142. }
  143. /*!--------------------------------------------------------------------------
  144. CTapiInfo::Reset()
  145. -
  146. Author: EricDav
  147. ---------------------------------------------------------------------------*/
  148. STDMETHODIMP
  149. CTapiInfo::Reset()
  150. {
  151. LONG lReturn = 0;
  152. for (int i = 0; i < DEVICE_TYPE_MAX; i++)
  153. {
  154. m_IndexMgr[i].Reset();
  155. }
  156. return S_OK;
  157. }
  158. /*!--------------------------------------------------------------------------
  159. CTapiInfo::Destroy()
  160. -
  161. Author: EricDav
  162. ---------------------------------------------------------------------------*/
  163. STDMETHODIMP
  164. CTapiInfo::Destroy()
  165. {
  166. LONG lReturn = 0;
  167. HRESULT hr = S_OK;
  168. if ( !g_TapiDLL.LoadFunctionPointers() )
  169. return hr;
  170. if (m_hServer == NULL)
  171. {
  172. return hr;
  173. }
  174. lReturn = ((SHUTDOWN) g_TapiDLL[TAPI_SHUTDOWN])(m_hServer);
  175. if (lReturn != ERROR_SUCCESS)
  176. {
  177. Trace1("CTapiInfo::Destroy - Shutdown failed! %lx\n", lReturn);
  178. hr = HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  179. }
  180. m_hServer = NULL;
  181. return hr;
  182. }
  183. /*!--------------------------------------------------------------------------
  184. CTapiInfo::EnumConfigInfo
  185. -
  186. Author: EricDav
  187. ---------------------------------------------------------------------------*/
  188. STDMETHODIMP
  189. CTapiInfo::EnumConfigInfo()
  190. {
  191. CSingleLock cl(&m_csData);
  192. LONG lReturn = 0;
  193. TAPISERVERCONFIG tapiServerConfig = {0};
  194. LPTAPISERVERCONFIG pTapiServerConfig = NULL;
  195. HRESULT hr = hrOK;
  196. if ( !g_TapiDLL.LoadFunctionPointers() )
  197. return S_OK;
  198. if (m_hServer == NULL)
  199. {
  200. Trace0("CTapiInfo::GetConfigInfo - Server not initialized!\n");
  201. return E_FAIL;
  202. }
  203. COM_PROTECT_TRY
  204. {
  205. // the first call will tell us how big of a buffer we need to allocate
  206. // to hold the config info struct
  207. tapiServerConfig.dwTotalSize = sizeof(TAPISERVERCONFIG);
  208. lReturn = ((GETSERVERCONFIG) g_TapiDLL[TAPI_GET_SERVER_CONFIG])(m_hServer, &tapiServerConfig);
  209. if (lReturn != ERROR_SUCCESS)
  210. {
  211. Trace1("CTapiInfo::GetConfigInfo - 1st MMCGetServerConfig returned %x!\n", lReturn);
  212. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  213. }
  214. pTapiServerConfig = (LPTAPISERVERCONFIG) malloc(tapiServerConfig.dwNeededSize);
  215. if (NULL == pTapiServerConfig)
  216. {
  217. return E_OUTOFMEMORY;
  218. }
  219. memset(pTapiServerConfig, 0, tapiServerConfig.dwNeededSize);
  220. pTapiServerConfig->dwTotalSize = tapiServerConfig.dwNeededSize;
  221. lReturn = ((GETSERVERCONFIG) g_TapiDLL[TAPI_GET_SERVER_CONFIG])(m_hServer, pTapiServerConfig);
  222. if (lReturn != ERROR_SUCCESS)
  223. {
  224. Trace1("CTapiInfo::GetConfigInfo - 2nd MMCGetServerConfig returned %x!\n", lReturn);
  225. free(pTapiServerConfig);
  226. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  227. }
  228. cl.Lock();
  229. if (m_pTapiConfig)
  230. {
  231. free(m_pTapiConfig);
  232. }
  233. m_pTapiConfig = pTapiServerConfig;
  234. cl.Unlock();
  235. }
  236. COM_PROTECT_CATCH
  237. return hr;
  238. }
  239. /*!--------------------------------------------------------------------------
  240. CTapiInfo::GetConfigInfo
  241. -
  242. Author: EricDav
  243. ---------------------------------------------------------------------------*/
  244. STDMETHODIMP
  245. CTapiInfo::GetConfigInfo(CTapiConfigInfo * ptapiConfigInfo)
  246. {
  247. CSingleLock cl(&m_csData);
  248. cl.Lock();
  249. if (m_pTapiConfig)
  250. {
  251. TapiConfigToInternal(m_pTapiConfig, *ptapiConfigInfo);
  252. }
  253. else
  254. {
  255. return E_FAIL;
  256. }
  257. return S_OK;
  258. }
  259. /*!--------------------------------------------------------------------------
  260. CTapiInfo::SetConfigInfo
  261. -
  262. Author: EricDav
  263. ---------------------------------------------------------------------------*/
  264. STDMETHODIMP
  265. CTapiInfo::SetConfigInfo(CTapiConfigInfo * ptapiConfigInfo)
  266. {
  267. CSingleLock cl(&m_csData);
  268. LPTAPISERVERCONFIG pServerConfig = NULL;
  269. HRESULT hr = hrOK;
  270. LONG lReturn = 0;
  271. if ( !g_TapiDLL.LoadFunctionPointers() )
  272. return S_OK;
  273. if (m_hServer == NULL)
  274. {
  275. Trace0("CTapiInfo::SetConfigInfo - Server not initialized!\n");
  276. return E_FAIL;
  277. }
  278. InternalToTapiConfig(*ptapiConfigInfo, &pServerConfig);
  279. Assert(pServerConfig);
  280. if (pServerConfig)
  281. {
  282. // make the call
  283. lReturn = ((SETSERVERCONFIG) g_TapiDLL[TAPI_SET_SERVER_CONFIG])(m_hServer, pServerConfig);
  284. if (lReturn != ERROR_SUCCESS)
  285. {
  286. Trace1("CTapiInfo::SetConfigInfo - MMCSetServerConfig returned %x!\n", lReturn);
  287. free(pServerConfig);
  288. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  289. }
  290. // free up the old config struct if there was one
  291. cl.Lock();
  292. if (m_pTapiConfig)
  293. free(m_pTapiConfig);
  294. m_pTapiConfig = pServerConfig;
  295. //Bug 276787 We should clear the two write bits
  296. m_pTapiConfig->dwFlags &= ~(TAPISERVERCONFIGFLAGS_SETACCOUNT |
  297. TAPISERVERCONFIGFLAGS_SETTAPIADMINISTRATORS);
  298. cl.Unlock();
  299. }
  300. else
  301. {
  302. hr = E_OUTOFMEMORY;
  303. }
  304. return hr;
  305. }
  306. /*!--------------------------------------------------------------------------
  307. CTapiInfo::IsServer
  308. -
  309. Author: EricDav
  310. ---------------------------------------------------------------------------*/
  311. STDMETHODIMP_(BOOL)
  312. CTapiInfo::IsServer()
  313. {
  314. CSingleLock cl(&m_csData);
  315. cl.Lock();
  316. if (m_pTapiConfig)
  317. return m_pTapiConfig->dwFlags & TAPISERVERCONFIGFLAGS_ISSERVER;
  318. else if (!m_strComputerName.IsEmpty())
  319. {
  320. BOOL fIsNTS = FALSE;
  321. TFSIsNTServer(m_strComputerName, &fIsNTS);
  322. return fIsNTS;
  323. }
  324. else
  325. return FALSE; // assume workstation
  326. }
  327. /*!--------------------------------------------------------------------------
  328. CTapiInfo::IsTapiServer
  329. -
  330. Author: EricDav
  331. ---------------------------------------------------------------------------*/
  332. STDMETHODIMP_(BOOL)
  333. CTapiInfo::IsTapiServer()
  334. {
  335. CSingleLock cl(&m_csData);
  336. cl.Lock();
  337. if (m_pTapiConfig)
  338. return m_pTapiConfig->dwFlags & TAPISERVERCONFIGFLAGS_ENABLESERVER;
  339. else
  340. return FALSE; // assume not a tapi server
  341. }
  342. STDMETHODIMP
  343. CTapiInfo::SetComputerName(LPCTSTR pComputer)
  344. {
  345. m_strComputerName = pComputer;
  346. return hrOK;
  347. }
  348. STDMETHODIMP_(LPCTSTR)
  349. CTapiInfo::GetComputerName()
  350. {
  351. return m_strComputerName;
  352. }
  353. /*!--------------------------------------------------------------------------
  354. CTapiInfo::IsLocalMachine
  355. Says whether this machine is local or remote
  356. Author: NSun
  357. ---------------------------------------------------------------------------*/
  358. STDMETHODIMP_(BOOL)
  359. CTapiInfo::IsLocalMachine()
  360. {
  361. return m_fIsLocalMachine;
  362. }
  363. /*!--------------------------------------------------------------------------
  364. CTapiInfo::FHasServiceControl
  365. Says whether we the access of service control for tapisrv
  366. Author: NSun
  367. ---------------------------------------------------------------------------*/
  368. STDMETHODIMP_(BOOL)
  369. CTapiInfo::FHasServiceControl()
  370. {
  371. CSingleLock cl(&m_csData);
  372. cl.Lock();
  373. if (m_pTapiConfig)
  374. return !(m_pTapiConfig->dwFlags & TAPISERVERCONFIGFLAGS_NOSERVICECONTROL);
  375. else
  376. return FALSE; // assume workstation
  377. }
  378. STDMETHODIMP
  379. CTapiInfo::SetCachedLineBuffSize(DWORD dwLineSize)
  380. {
  381. m_dwCachedLineSize = dwLineSize;
  382. return S_OK;
  383. }
  384. STDMETHODIMP
  385. CTapiInfo::SetCachedPhoneBuffSize(DWORD dwPhoneSize)
  386. {
  387. m_dwCachedPhoneSize = dwPhoneSize;
  388. return S_OK;
  389. }
  390. STDMETHODIMP_(DWORD)
  391. CTapiInfo::GetCachedLineBuffSize()
  392. {
  393. return m_dwCachedLineSize;
  394. }
  395. STDMETHODIMP_(DWORD)
  396. CTapiInfo::GetCachedPhoneBuffSize()
  397. {
  398. return m_dwCachedPhoneSize;
  399. }
  400. STDMETHODIMP_(BOOL)
  401. CTapiInfo::IsCacheDirty()
  402. {
  403. return m_fCacheDirty;
  404. }
  405. /*!--------------------------------------------------------------------------
  406. CTapiInfo::GetProviderCount
  407. -
  408. Author: EricDav
  409. ---------------------------------------------------------------------------*/
  410. STDMETHODIMP_(int)
  411. CTapiInfo::GetProviderCount()
  412. {
  413. CSingleLock cl(&m_csData);
  414. cl.Lock();
  415. if (m_pProviderList)
  416. {
  417. return m_pProviderList->dwNumProviders;
  418. }
  419. else
  420. {
  421. return 0;
  422. }
  423. }
  424. /*!--------------------------------------------------------------------------
  425. CTapiInfo::EnumProviders
  426. -
  427. Author: EricDav
  428. ---------------------------------------------------------------------------*/
  429. STDMETHODIMP
  430. CTapiInfo::EnumProviders()
  431. {
  432. CSingleLock cl(&m_csData);
  433. LINEPROVIDERLIST tapiProviderList = {0};
  434. LPLINEPROVIDERLIST pProviderList = NULL;
  435. HRESULT hr = hrOK;
  436. LONG lReturn = 0;
  437. if ( !g_TapiDLL.LoadFunctionPointers() )
  438. return S_OK;
  439. if (m_hServer == NULL)
  440. {
  441. Trace0("CTapiInfo::GetConfigInfo - Server not initialized!\n");
  442. return E_FAIL;
  443. }
  444. COM_PROTECT_TRY
  445. {
  446. // the first call will tell us how big of a buffer we need to allocate
  447. // to hold the provider list struct
  448. tapiProviderList.dwTotalSize = sizeof(LINEPROVIDERLIST);
  449. lReturn = ((GETPROVIDERLIST) g_TapiDLL[TAPI_GET_PROVIDER_LIST])(m_hServer, &tapiProviderList);
  450. if (lReturn != ERROR_SUCCESS)
  451. {
  452. Trace1("CTapiInfo::EnumProviders - 1st MMCGetProviderList returned %x!\n", lReturn);
  453. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  454. }
  455. pProviderList = (LPLINEPROVIDERLIST) malloc(tapiProviderList.dwNeededSize);
  456. if (NULL == pProviderList)
  457. {
  458. return E_OUTOFMEMORY;
  459. }
  460. memset(pProviderList, 0, tapiProviderList.dwNeededSize);
  461. pProviderList->dwTotalSize = tapiProviderList.dwNeededSize;
  462. lReturn = ((GETPROVIDERLIST) g_TapiDLL[TAPI_GET_PROVIDER_LIST])(m_hServer, pProviderList);
  463. if (lReturn != ERROR_SUCCESS)
  464. {
  465. Trace1("CTapiInfo::EnumProviders - 2nd MMCGetProviderList returned %x!\n", lReturn);
  466. free(pProviderList);
  467. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  468. }
  469. cl.Lock();
  470. if (m_pProviderList)
  471. {
  472. free(m_pProviderList);
  473. }
  474. m_pProviderList = pProviderList;
  475. cl.Unlock();
  476. }
  477. COM_PROTECT_CATCH
  478. return hr;
  479. }
  480. /*!--------------------------------------------------------------------------
  481. CTapiInfo::GetProviderInfo
  482. -
  483. Author: EricDav
  484. ---------------------------------------------------------------------------*/
  485. STDMETHODIMP
  486. CTapiInfo::GetProviderInfo(CTapiProvider * pproviderInfo, int nIndex)
  487. {
  488. CSingleLock cl(&m_csData);
  489. cl.Lock();
  490. HRESULT hr = hrOK;
  491. LPLINEPROVIDERENTRY pProvider = NULL;
  492. if (m_pProviderList == NULL)
  493. return E_FAIL;
  494. if ((UINT) nIndex > m_pProviderList->dwNumProviders)
  495. return E_FAIL;
  496. pProvider = (LPLINEPROVIDERENTRY) ((LPBYTE) m_pProviderList + m_pProviderList->dwProviderListOffset);
  497. for (int i = 0; i < nIndex; i++)
  498. {
  499. pProvider++;
  500. }
  501. pproviderInfo->m_dwProviderID = pProvider->dwPermanentProviderID;
  502. pproviderInfo->m_strFilename = (LPCWSTR) ((LPBYTE) m_pProviderList + pProvider->dwProviderFilenameOffset);
  503. pproviderInfo->m_strName = GetProviderName(pproviderInfo->m_dwProviderID, pproviderInfo->m_strFilename, &pproviderInfo->m_dwFlags);
  504. return hr;
  505. }
  506. /*!--------------------------------------------------------------------------
  507. CTapiInfo::GetProviderInfo
  508. -
  509. Author: EricDav
  510. ---------------------------------------------------------------------------*/
  511. STDMETHODIMP
  512. CTapiInfo::GetProviderInfo(CTapiProvider * pproviderInfo, DWORD dwProviderID)
  513. {
  514. CSingleLock cl(&m_csData);
  515. cl.Lock();
  516. HRESULT hr = hrOK;
  517. LPLINEPROVIDERENTRY pProvider = NULL;
  518. if (m_pProviderList == NULL)
  519. return E_FAIL;
  520. pProvider = (LPLINEPROVIDERENTRY) ((LPBYTE) m_pProviderList + m_pProviderList->dwProviderListOffset);
  521. for (UINT i = 0; i < m_pProviderList->dwNumProviders; i++)
  522. {
  523. if (pProvider->dwPermanentProviderID == dwProviderID)
  524. break;
  525. pProvider++;
  526. }
  527. pproviderInfo->m_dwProviderID = pProvider->dwPermanentProviderID;
  528. pproviderInfo->m_strFilename = (LPCWSTR) ((LPBYTE) m_pProviderList + pProvider->dwProviderFilenameOffset);
  529. pproviderInfo->m_strName = GetProviderName(pproviderInfo->m_dwProviderID, pproviderInfo->m_strFilename, &pproviderInfo->m_dwFlags);
  530. return hr;
  531. }
  532. /*!--------------------------------------------------------------------------
  533. CTapiInfo::AddProvider
  534. -
  535. Author: EricDav
  536. ---------------------------------------------------------------------------*/
  537. STDMETHODIMP
  538. CTapiInfo::AddProvider(LPCTSTR pProviderFilename, LPDWORD pdwProviderID, HWND hWnd)
  539. {
  540. CSingleLock cl(&m_csData);
  541. cl.Lock();
  542. LONG lReturn = 0;
  543. HRESULT hr = hrOK;
  544. HWND hWndParent;
  545. if (hWnd == NULL)
  546. {
  547. hWndParent = ::FindMMCMainWindow();
  548. }
  549. else
  550. {
  551. hWndParent = hWnd;
  552. }
  553. if ( !g_TapiDLL.LoadFunctionPointers() )
  554. return S_OK;
  555. if (m_hServer == NULL)
  556. {
  557. Trace0("CTapiInfo::AddProvider - Server not initialized!\n");
  558. return E_FAIL;
  559. }
  560. lReturn = ((ADDPROVIDER) g_TapiDLL[TAPI_ADD_PROVIDER])(m_hServer, hWndParent, pProviderFilename, pdwProviderID);
  561. if (lReturn != ERROR_SUCCESS)
  562. {
  563. Trace1("CTapiInfo::AddProvider - MMCAddProvider returned %x!\n", lReturn);
  564. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  565. }
  566. return hr;
  567. }
  568. /*!--------------------------------------------------------------------------
  569. CTapiInfo::ConfigureProvider
  570. -
  571. Author: EricDav
  572. ---------------------------------------------------------------------------*/
  573. STDMETHODIMP
  574. CTapiInfo::ConfigureProvider(DWORD dwProviderID, HWND hWnd)
  575. {
  576. LONG lReturn = 0;
  577. HRESULT hr = hrOK;
  578. HWND hWndParent;
  579. if (hWnd == NULL)
  580. {
  581. hWndParent = ::FindMMCMainWindow();
  582. }
  583. else
  584. {
  585. hWndParent = hWnd;
  586. }
  587. if ( !g_TapiDLL.LoadFunctionPointers() )
  588. return S_OK;
  589. if (m_hServer == NULL)
  590. {
  591. Trace0("CTapiInfo::ConfigureProvider - Server not initialized!\n");
  592. return E_FAIL;
  593. }
  594. lReturn = ((CONFIGPROVIDER) g_TapiDLL[TAPI_CONFIG_PROVIDER])(m_hServer, hWndParent, dwProviderID);
  595. if (lReturn != ERROR_SUCCESS)
  596. {
  597. Trace1("CTapiInfo::ConfigureProvider - MMCConfigureProvider returned %x!\n", lReturn);
  598. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  599. }
  600. return hr;
  601. }
  602. /*!--------------------------------------------------------------------------
  603. CTapiInfo::RemoveProvider
  604. -
  605. Author: EricDav
  606. ---------------------------------------------------------------------------*/
  607. STDMETHODIMP
  608. CTapiInfo::RemoveProvider(DWORD dwProviderID, HWND hWnd)
  609. {
  610. LONG lReturn = 0;
  611. HRESULT hr = hrOK;
  612. HWND hWndParent;
  613. if (hWnd == NULL)
  614. {
  615. hWndParent = ::FindMMCMainWindow();
  616. }
  617. else
  618. {
  619. hWndParent = hWnd;
  620. }
  621. if ( !g_TapiDLL.LoadFunctionPointers() )
  622. return S_OK;
  623. if (m_hServer == NULL)
  624. {
  625. Trace0("CTapiInfo::RemoveProvider - Server not initialized!\n");
  626. return E_FAIL;
  627. }
  628. lReturn = ((REMOVEPROVIDER) g_TapiDLL[TAPI_REMOVE_PROVIDER])(m_hServer, hWndParent, dwProviderID);
  629. if (lReturn != ERROR_SUCCESS)
  630. {
  631. Trace1("CTapiInfo::RemoveProvider - MMCRemoveProvider returned %x!\n", lReturn);
  632. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  633. }
  634. return hr;
  635. }
  636. /*!--------------------------------------------------------------------------
  637. CTapiInfo::GetAvailableProviderCount
  638. -
  639. Author: EricDav
  640. ---------------------------------------------------------------------------*/
  641. STDMETHODIMP_(int)
  642. CTapiInfo::GetAvailableProviderCount()
  643. {
  644. CSingleLock cl(&m_csData);
  645. cl.Lock();
  646. if (m_pAvailProviderList)
  647. {
  648. return m_pAvailProviderList->dwNumProviderListEntries;
  649. }
  650. else
  651. {
  652. return 0;
  653. }
  654. }
  655. /*!--------------------------------------------------------------------------
  656. CTapiInfo::EnumAvailableProviders
  657. -
  658. Author: EricDav
  659. ---------------------------------------------------------------------------*/
  660. STDMETHODIMP
  661. CTapiInfo::EnumAvailableProviders()
  662. {
  663. CSingleLock cl(&m_csData);
  664. AVAILABLEPROVIDERLIST tapiProviderList = {0};
  665. LPAVAILABLEPROVIDERLIST pProviderList = NULL;
  666. HRESULT hr = hrOK;
  667. LONG lReturn = 0;
  668. if ( !g_TapiDLL.LoadFunctionPointers() )
  669. return S_OK;
  670. if (m_hServer == NULL)
  671. {
  672. Trace0("CTapiInfo::GetConfigInfo - Server not initialized!\n");
  673. return E_FAIL;
  674. }
  675. COM_PROTECT_TRY
  676. {
  677. // the first call will tell us how big of a buffer we need to allocate
  678. // to hold the provider list struct
  679. tapiProviderList.dwTotalSize = sizeof(LINEPROVIDERLIST);
  680. lReturn = ((GETAVAILABLEPROVIDERS) g_TapiDLL[TAPI_GET_AVAILABLE_PROVIDERS])(m_hServer, &tapiProviderList);
  681. if (lReturn != ERROR_SUCCESS)
  682. {
  683. Trace1("CTapiInfo::EnumProviders - 1st MMCGetAvailableProviders returned %x!\n", lReturn);
  684. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  685. }
  686. pProviderList = (LPAVAILABLEPROVIDERLIST) malloc(tapiProviderList.dwNeededSize);
  687. memset(pProviderList, 0, tapiProviderList.dwNeededSize);
  688. pProviderList->dwTotalSize = tapiProviderList.dwNeededSize;
  689. lReturn = ((GETAVAILABLEPROVIDERS) g_TapiDLL[TAPI_GET_AVAILABLE_PROVIDERS])(m_hServer, pProviderList);
  690. if (lReturn != ERROR_SUCCESS)
  691. {
  692. Trace1("CTapiInfo::EnumProviders - 2nd MMCGetAvailableProviders returned %x!\n", lReturn);
  693. free(pProviderList);
  694. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  695. }
  696. cl.Lock();
  697. if (m_pAvailProviderList)
  698. {
  699. free(m_pAvailProviderList);
  700. }
  701. m_pAvailProviderList = pProviderList;
  702. cl.Unlock();
  703. }
  704. COM_PROTECT_CATCH
  705. return hr;
  706. }
  707. /*!--------------------------------------------------------------------------
  708. CTapiInfo::GetAvailableProviderInfo
  709. -
  710. Author: EricDav
  711. ---------------------------------------------------------------------------*/
  712. STDMETHODIMP
  713. CTapiInfo::GetAvailableProviderInfo(CTapiProvider * pproviderInfo, int nIndex)
  714. {
  715. CSingleLock cl(&m_csData);
  716. cl.Lock();
  717. HRESULT hr = hrOK;
  718. LPAVAILABLEPROVIDERENTRY pProvider = NULL;
  719. if (m_pAvailProviderList == NULL)
  720. return E_FAIL;
  721. if ((UINT) nIndex > m_pAvailProviderList->dwNumProviderListEntries)
  722. return E_FAIL;
  723. pProvider = (LPAVAILABLEPROVIDERENTRY) ((LPBYTE) m_pAvailProviderList + m_pAvailProviderList->dwProviderListOffset);
  724. for (int i = 0; i < nIndex; i++)
  725. {
  726. pProvider++;
  727. }
  728. // available providers do not have ProviderIDs until they are installed
  729. pproviderInfo->m_dwProviderID = 0;
  730. pproviderInfo->m_dwFlags = pProvider->dwOptions;
  731. pproviderInfo->m_strName = (LPCWSTR) ((LPBYTE) m_pAvailProviderList + pProvider->dwFriendlyNameOffset);
  732. pproviderInfo->m_strFilename = (LPCWSTR) ((LPBYTE) m_pAvailProviderList + pProvider->dwFileNameOffset);
  733. return hr;
  734. }
  735. /*!--------------------------------------------------------------------------
  736. CTapiInfo::EnumDevices
  737. -
  738. Author: EricDav
  739. ---------------------------------------------------------------------------*/
  740. STDMETHODIMP
  741. CTapiInfo::EnumDevices(DEVICE_TYPE deviceType)
  742. {
  743. CSingleLock cl(&m_csData);
  744. LONG lReturn = 0;
  745. HRESULT hr = hrOK;
  746. LPDEVICEINFOLIST pDeviceInfoList = NULL;
  747. if ( !g_TapiDLL.LoadFunctionPointers() )
  748. return S_OK;
  749. if (m_hServer == NULL)
  750. {
  751. Trace0("CTapiInfo::EnumDevices - Server not initialized!\n");
  752. return E_FAIL;
  753. }
  754. // the first call will tell us how big of a buffer we need to allocate
  755. // to hold the provider list struct
  756. COM_PROTECT_TRY
  757. {
  758. // Fix bug 381469
  759. // First allocate the cached size of memory to get line info
  760. DWORD dwCachedSize = (DEVICE_LINE == deviceType) ? m_dwCachedLineSize : m_dwCachedPhoneSize;
  761. if (dwCachedSize < sizeof(DEVICEINFOLIST))
  762. {
  763. //if we didn't have the cached size, then use the default size
  764. dwCachedSize = TAPI_DEFAULT_DEVICE_BUFF_SIZE;
  765. m_fCacheDirty = TRUE;
  766. }
  767. DWORD dwTotalSize = dwCachedSize + DEVICEINFO_GROW_SIZE;
  768. pDeviceInfoList = (LPDEVICEINFOLIST) malloc(dwTotalSize);
  769. if (NULL == pDeviceInfoList)
  770. {
  771. return E_OUTOFMEMORY;
  772. }
  773. memset(pDeviceInfoList, 0, dwTotalSize);
  774. pDeviceInfoList->dwTotalSize = dwTotalSize;
  775. switch (deviceType)
  776. {
  777. case DEVICE_LINE:
  778. lReturn = ((GETLINEINFO) g_TapiDLL[TAPI_GET_LINE_INFO])(m_hServer, pDeviceInfoList);
  779. break;
  780. case DEVICE_PHONE:
  781. lReturn = ((GETPHONEINFO) g_TapiDLL[TAPI_GET_PHONE_INFO])(m_hServer, pDeviceInfoList);
  782. break;
  783. }
  784. if (lReturn != ERROR_SUCCESS)
  785. {
  786. Trace1("CTapiInfo::EnumDevices - 1st MMCGetDeviceInfo returned %x!\n", lReturn);
  787. free (pDeviceInfoList);
  788. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  789. }
  790. if (pDeviceInfoList->dwNeededSize > pDeviceInfoList->dwTotalSize)
  791. {
  792. // the cached size is too small, now allocate the buffer and call again to the the info
  793. DWORD dwNeededSize = pDeviceInfoList->dwNeededSize;
  794. free (pDeviceInfoList);
  795. dwNeededSize += DEVICEINFO_GROW_SIZE;
  796. pDeviceInfoList = (LPDEVICEINFOLIST) malloc(dwNeededSize);
  797. memset(pDeviceInfoList, 0, dwNeededSize);
  798. pDeviceInfoList->dwTotalSize = dwNeededSize;
  799. switch (deviceType)
  800. {
  801. case DEVICE_LINE:
  802. lReturn = ((GETLINEINFO) g_TapiDLL[TAPI_GET_LINE_INFO])(m_hServer, pDeviceInfoList);
  803. break;
  804. case DEVICE_PHONE:
  805. lReturn = ((GETPHONEINFO) g_TapiDLL[TAPI_GET_PHONE_INFO])(m_hServer, pDeviceInfoList);
  806. break;
  807. }
  808. if (lReturn != ERROR_SUCCESS)
  809. {
  810. Trace1("CTapiInfo::EnumDevices - 2nd MMCGetDeviceInfo returned %x!\n", lReturn);
  811. free(pDeviceInfoList);
  812. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  813. }
  814. }
  815. //update the cache
  816. if (DEVICE_LINE == deviceType && m_dwCachedLineSize != pDeviceInfoList->dwNeededSize)
  817. {
  818. m_dwCachedLineSize = pDeviceInfoList->dwNeededSize;
  819. m_fCacheDirty = TRUE;
  820. }
  821. else if (DEVICE_PHONE == deviceType && m_dwCachedPhoneSize != pDeviceInfoList->dwNeededSize)
  822. {
  823. m_dwCachedPhoneSize = pDeviceInfoList->dwNeededSize;
  824. m_fCacheDirty = TRUE;
  825. }
  826. cl.Lock();
  827. if (m_paDeviceInfo[deviceType])
  828. {
  829. free (m_paDeviceInfo[deviceType]);
  830. }
  831. m_paDeviceInfo[deviceType] = pDeviceInfoList;
  832. // build our index list for sorting
  833. if (pDeviceInfoList->dwNumDeviceInfoEntries)
  834. {
  835. LPDEVICEINFO pDevice = NULL;
  836. pDevice = (LPDEVICEINFO) ((LPBYTE) pDeviceInfoList + pDeviceInfoList->dwDeviceInfoOffset);
  837. // now add all of the devices to our index
  838. for (int i = 0; i < GetTotalDeviceCount(deviceType); i++)
  839. {
  840. // walk the list of device info structs and add to the index mgr
  841. m_IndexMgr[deviceType].AddHDevice(pDevice->dwProviderID, (HDEVICE) pDevice, TRUE);
  842. pDevice++;
  843. }
  844. }
  845. cl.Unlock();
  846. }
  847. COM_PROTECT_CATCH
  848. return hr;
  849. }
  850. /*!--------------------------------------------------------------------------
  851. CTapiInfo::GetTotalDeviceCount
  852. -
  853. Author: EricDav
  854. ---------------------------------------------------------------------------*/
  855. STDMETHODIMP_(int)
  856. CTapiInfo::GetTotalDeviceCount(DEVICE_TYPE deviceType)
  857. {
  858. CSingleLock cl(&m_csData);
  859. cl.Lock();
  860. if (m_paDeviceInfo[deviceType])
  861. {
  862. return m_paDeviceInfo[deviceType]->dwNumDeviceInfoEntries;
  863. }
  864. else
  865. {
  866. return 0;
  867. }
  868. }
  869. /*!--------------------------------------------------------------------------
  870. CTapiInfo::GetDeviceCount
  871. -
  872. Author: EricDav
  873. ---------------------------------------------------------------------------*/
  874. STDMETHODIMP_(int)
  875. CTapiInfo::GetDeviceCount(DEVICE_TYPE deviceType, DWORD dwProviderID)
  876. {
  877. m_IndexMgr[deviceType].SetCurrentProvider(dwProviderID);
  878. return m_IndexMgr[deviceType].GetCurrentCount();
  879. }
  880. /*!--------------------------------------------------------------------------
  881. CTapiInfo::GetDeviceInfo
  882. -
  883. Author: EricDav
  884. ---------------------------------------------------------------------------*/
  885. STDMETHODIMP
  886. CTapiInfo::GetDeviceInfo(DEVICE_TYPE deviceType, CTapiDevice * ptapiDevice, DWORD dwProviderID, int nIndex)
  887. {
  888. CSingleLock cl(&m_csData);
  889. cl.Lock();
  890. LPDEVICEINFO pDevice = NULL;
  891. HDEVICE hdevice = NULL;
  892. HRESULT hr = hrOK;
  893. if (m_paDeviceInfo[deviceType] == NULL)
  894. return E_FAIL;
  895. if ((UINT) nIndex > m_paDeviceInfo[deviceType]->dwNumDeviceInfoEntries)
  896. return E_INVALIDARG;
  897. hr = m_IndexMgr[deviceType].GetHDevice(dwProviderID, nIndex, &hdevice);
  898. if (FAILED(hr))
  899. return hr;
  900. pDevice = (LPDEVICEINFO) hdevice;
  901. if (pDevice == NULL)
  902. return E_FAIL;
  903. TapiDeviceToInternal(deviceType, pDevice, *ptapiDevice);
  904. return hr;
  905. }
  906. /*!--------------------------------------------------------------------------
  907. CTapiInfo::SetDeviceInfo
  908. Sets the device info on a TAPI server. First builds a deviceinfolist
  909. struct to user for the SetDeviceInfo call then updates the internal
  910. device info list.
  911. Author: EricDav
  912. ---------------------------------------------------------------------------*/
  913. STDMETHODIMP
  914. CTapiInfo::SetDeviceInfo(DEVICE_TYPE deviceType, CTapiDevice * ptapiDevice)
  915. {
  916. CSingleLock cl(&m_csData);
  917. cl.Lock();
  918. HRESULT hr = hrOK;
  919. LONG lReturn = 0;
  920. LPDEVICEINFOLIST pDeviceInfoList = NULL, pNewDeviceInfoList;
  921. LPDEVICEINFO pDeviceInfo = NULL;
  922. int i;
  923. if ( !g_TapiDLL.LoadFunctionPointers() )
  924. return S_OK;
  925. if (m_hServer == NULL)
  926. {
  927. Trace0("CTapiInfo::EnumDevices - Server not initialized!\n");
  928. return E_FAIL;
  929. }
  930. InternalToTapiDevice(*ptapiDevice, &pDeviceInfoList);
  931. Assert(pDeviceInfoList);
  932. if (!pDeviceInfoList)
  933. return E_OUTOFMEMORY;
  934. // make the call...
  935. switch (deviceType)
  936. {
  937. case DEVICE_LINE:
  938. lReturn = ((SETLINEINFO) g_TapiDLL[TAPI_SET_LINE_INFO])(m_hServer, pDeviceInfoList);
  939. break;
  940. case DEVICE_PHONE:
  941. lReturn = ((SETPHONEINFO) g_TapiDLL[TAPI_SET_PHONE_INFO])(m_hServer, pDeviceInfoList);
  942. break;
  943. }
  944. if (lReturn != ERROR_SUCCESS)
  945. {
  946. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  947. }
  948. // finally, update our internal struct to reflect the changes
  949. Assert(m_paDeviceInfo[deviceType]);
  950. pDeviceInfo = (LPDEVICEINFO) ((LPBYTE) pDeviceInfoList + pDeviceInfoList->dwDeviceInfoOffset);
  951. // find the device in the list
  952. LPDEVICEINFO pDevice = NULL;
  953. pDevice = (LPDEVICEINFO) ((LPBYTE) m_paDeviceInfo[deviceType] + m_paDeviceInfo[deviceType]->dwDeviceInfoOffset);
  954. for (i = 0; i < GetTotalDeviceCount(deviceType); i++)
  955. {
  956. // walk the list of device info structs and add to the index mgr
  957. if (pDevice->dwPermanentDeviceID == ptapiDevice->m_dwPermanentID)
  958. {
  959. // update the device info here. First check to make sure we have enough room to grow
  960. if (m_paDeviceInfo[deviceType]->dwTotalSize < (m_paDeviceInfo[deviceType]->dwUsedSize + pDeviceInfo->dwDomainUserNamesSize + pDeviceInfo->dwFriendlyUserNamesSize))
  961. {
  962. // we've run out of room. Realloc a bigger piece
  963. pNewDeviceInfoList = (LPDEVICEINFOLIST) realloc(m_paDeviceInfo[deviceType], m_paDeviceInfo[deviceType]->dwTotalSize + DEVICEINFO_GROW_SIZE);
  964. if (pNewDeviceInfoList == NULL)
  965. {
  966. free(pDeviceInfoList);
  967. return E_OUTOFMEMORY;
  968. }
  969. else
  970. {
  971. m_paDeviceInfo[deviceType] = pNewDeviceInfoList;
  972. }
  973. // Update the dwTotalSize
  974. m_paDeviceInfo[deviceType]->dwTotalSize = m_paDeviceInfo[deviceType]->dwTotalSize + DEVICEINFO_GROW_SIZE;
  975. }
  976. // update the sizes
  977. pDevice->dwDomainUserNamesSize = pDeviceInfo->dwDomainUserNamesSize;
  978. pDevice->dwFriendlyUserNamesSize = pDeviceInfo->dwFriendlyUserNamesSize;
  979. // update the new domain name info
  980. pDevice->dwDomainUserNamesOffset = m_paDeviceInfo[deviceType]->dwUsedSize;
  981. memcpy(((LPBYTE) m_paDeviceInfo[deviceType] + pDevice->dwDomainUserNamesOffset),
  982. ((LPBYTE) pDeviceInfoList + pDeviceInfo->dwDomainUserNamesOffset),
  983. pDeviceInfo->dwDomainUserNamesSize);
  984. // update the new friendly name info
  985. pDevice->dwFriendlyUserNamesOffset = m_paDeviceInfo[deviceType]->dwUsedSize + pDevice->dwDomainUserNamesSize;
  986. memcpy(((LPBYTE) m_paDeviceInfo[deviceType] + pDevice->dwFriendlyUserNamesOffset),
  987. ((LPBYTE) pDeviceInfoList + pDeviceInfo->dwFriendlyUserNamesOffset),
  988. pDeviceInfo->dwFriendlyUserNamesOffset);
  989. m_paDeviceInfo[deviceType]->dwUsedSize += (pDevice->dwDomainUserNamesSize + pDevice->dwFriendlyUserNamesSize);
  990. }
  991. pDevice++;
  992. }
  993. free(pDeviceInfoList);
  994. return hr;
  995. }
  996. /*!--------------------------------------------------------------------------
  997. CTapiInfo::SortDeviceInfo
  998. -
  999. Author: EricDav
  1000. ---------------------------------------------------------------------------*/
  1001. STDMETHODIMP
  1002. CTapiInfo::SortDeviceInfo(DEVICE_TYPE deviceType, DWORD dwProviderID, INDEX_TYPE indexType, DWORD dwSortOptions)
  1003. {
  1004. CSingleLock cl(&m_csData);
  1005. cl.Lock();
  1006. HRESULT hr = hrOK;
  1007. if (m_paDeviceInfo[deviceType])
  1008. m_IndexMgr[deviceType].Sort(dwProviderID, indexType, dwSortOptions, (LPBYTE) m_paDeviceInfo[deviceType]);
  1009. return hr;
  1010. }
  1011. /*!--------------------------------------------------------------------------
  1012. CTapiInfo::GetDeviceStatus
  1013. -
  1014. Author: EricDav
  1015. ---------------------------------------------------------------------------*/
  1016. STDMETHODIMP
  1017. CTapiInfo::GetDeviceStatus(DEVICE_TYPE deviceType, CString * pstrStatus, DWORD dwProviderID, int nIndex, HWND hWnd)
  1018. {
  1019. CSingleLock cl(&m_csData);
  1020. HRESULT hr = hrOK;
  1021. LPDEVICEINFO pDevice = NULL;
  1022. HDEVICE hdevice;
  1023. LONG lReturn = 0;
  1024. BYTE data[256] = {0};
  1025. LPVARSTRING pVarStatus = (LPVARSTRING) &data[0];
  1026. int nHash;
  1027. CString strStatus;
  1028. CString strData;
  1029. HWND hWndParent;
  1030. if (hWnd == NULL)
  1031. {
  1032. hWndParent = ::FindMMCMainWindow();
  1033. }
  1034. else
  1035. {
  1036. hWndParent = hWnd;
  1037. }
  1038. if ( !g_TapiDLL.LoadFunctionPointers() )
  1039. return S_OK;
  1040. if (m_hServer == NULL)
  1041. {
  1042. Trace0("CTapiInfo::EnumDevices - Server not initialized!\n");
  1043. return E_FAIL;
  1044. }
  1045. cl.Lock();
  1046. hr = m_IndexMgr[deviceType].GetHDevice(dwProviderID, nIndex, &hdevice);
  1047. if (FAILED(hr))
  1048. return hr;
  1049. pDevice = (LPDEVICEINFO) hdevice;
  1050. if (pDevice == NULL)
  1051. return E_FAIL;
  1052. // try to get the string
  1053. pVarStatus->dwTotalSize = sizeof(data);
  1054. switch (deviceType)
  1055. {
  1056. case DEVICE_LINE:
  1057. lReturn = ((GETLINESTATUS) g_TapiDLL[TAPI_GET_LINE_STATUS])(m_hServer,
  1058. hWndParent,
  1059. 0,
  1060. pDevice->dwProviderID,
  1061. pDevice->dwPermanentDeviceID,
  1062. pVarStatus);
  1063. break;
  1064. case DEVICE_PHONE:
  1065. lReturn = ((GETLINESTATUS) g_TapiDLL[TAPI_GET_PHONE_STATUS])(m_hServer,
  1066. hWndParent,
  1067. 0,
  1068. pDevice->dwProviderID,
  1069. pDevice->dwPermanentDeviceID,
  1070. pVarStatus);
  1071. break;
  1072. }
  1073. if (lReturn != ERROR_SUCCESS)
  1074. {
  1075. Trace1("CTapiInfo::GetDeviceStatus - 1st call to GetDeviceStatus returned %x!\n", lReturn);
  1076. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  1077. }
  1078. if (pVarStatus->dwNeededSize > pVarStatus->dwTotalSize)
  1079. {
  1080. // buffer not big enough, try again.
  1081. pVarStatus = (LPVARSTRING) alloca(pVarStatus->dwNeededSize);
  1082. memset(pVarStatus, 0, pVarStatus->dwNeededSize);
  1083. pVarStatus->dwTotalSize = pVarStatus->dwNeededSize;
  1084. switch (deviceType)
  1085. {
  1086. case DEVICE_LINE:
  1087. lReturn = ((GETLINESTATUS) g_TapiDLL[TAPI_GET_LINE_STATUS])(m_hServer,
  1088. hWndParent,
  1089. 0,
  1090. pDevice->dwProviderID,
  1091. pDevice->dwPermanentDeviceID,
  1092. pVarStatus);
  1093. break;
  1094. case DEVICE_PHONE:
  1095. lReturn = ((GETLINESTATUS) g_TapiDLL[TAPI_GET_PHONE_STATUS])(m_hServer,
  1096. hWndParent,
  1097. 0,
  1098. pDevice->dwProviderID,
  1099. pDevice->dwPermanentDeviceID,
  1100. pVarStatus);
  1101. break;
  1102. }
  1103. if (lReturn != ERROR_SUCCESS)
  1104. {
  1105. Trace1("CTapiInfo::GetDeviceStatus - 2nd call to GetDeviceStatus returned %x!\n", lReturn);
  1106. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  1107. }
  1108. }
  1109. cl.Unlock();
  1110. // now see if the string exists in our table. If so, return a pointer to that,
  1111. // otherwise add and return a pointer to our table.
  1112. strStatus = (LPCTSTR) ((LPBYTE) pVarStatus + pVarStatus->dwStringOffset);
  1113. if (!m_mapStatusStrings.Lookup(strStatus, strData))
  1114. {
  1115. Trace1("CTapiInfo::GetDeviceStatus - Entry for %s added.\n", strStatus);
  1116. strData = strStatus;
  1117. m_mapStatusStrings.SetAt(strStatus, strData);
  1118. }
  1119. else
  1120. {
  1121. // entry is already in our map
  1122. }
  1123. *pstrStatus = strData;
  1124. return hr;
  1125. }
  1126. /*!--------------------------------------------------------------------------
  1127. Internal functions
  1128. ---------------------------------------------------------------------------*/
  1129. /*!--------------------------------------------------------------------------
  1130. CTapiInfo::TapiConfigToInternal
  1131. -
  1132. Author: EricDav
  1133. ---------------------------------------------------------------------------*/
  1134. void
  1135. CTapiInfo::TapiConfigToInternal(LPTAPISERVERCONFIG pTapiConfig, CTapiConfigInfo & tapiConfigInfo)
  1136. {
  1137. HRESULT hr = hrOK;
  1138. UINT uAdminLength = (pTapiConfig->dwAdministratorsSize != 0) ? pTapiConfig->dwAdministratorsSize - sizeof(WCHAR) : 0;
  1139. UINT uAdminOffset = 0;
  1140. CUserInfo userTemp;
  1141. COM_PROTECT_TRY
  1142. {
  1143. if (pTapiConfig->dwDomainNameSize)
  1144. tapiConfigInfo.m_strDomainName = (LPCTSTR) ((LPBYTE) pTapiConfig + pTapiConfig->dwDomainNameOffset);
  1145. if (pTapiConfig->dwUserNameSize)
  1146. tapiConfigInfo.m_strUserName = (LPCTSTR) ((LPBYTE) pTapiConfig + pTapiConfig->dwUserNameOffset);
  1147. if (pTapiConfig->dwPasswordSize)
  1148. tapiConfigInfo.m_strPassword = (LPCTSTR) ((LPBYTE) pTapiConfig + pTapiConfig->dwPasswordOffset);
  1149. // add all of the administrators from the list
  1150. while (uAdminOffset < uAdminLength)
  1151. {
  1152. userTemp.m_strName = (LPCTSTR) ((LPBYTE) pTapiConfig + pTapiConfig->dwAdministratorsOffset + uAdminOffset);
  1153. if (!userTemp.m_strName.IsEmpty())
  1154. {
  1155. int nIndex = (int)tapiConfigInfo.m_arrayAdministrators.Add(userTemp);
  1156. }
  1157. uAdminOffset += (userTemp.m_strName.GetLength() + 1) * sizeof(TCHAR);
  1158. }
  1159. tapiConfigInfo.m_dwFlags = pTapiConfig->dwFlags;
  1160. }
  1161. COM_PROTECT_CATCH
  1162. }
  1163. /*!--------------------------------------------------------------------------
  1164. CTapiInfo::InternalToTapiConfig
  1165. -
  1166. Author: EricDav
  1167. ---------------------------------------------------------------------------*/
  1168. void
  1169. CTapiInfo::InternalToTapiConfig(CTapiConfigInfo & tapiConfigInfo, LPTAPISERVERCONFIG * ppTapiConfig)
  1170. {
  1171. LPTAPISERVERCONFIG pTapiConfig = NULL;
  1172. HRESULT hr = hrOK;
  1173. UINT uSize = sizeof(TAPISERVERCONFIG);
  1174. UINT uDomainNameSize = 0;
  1175. UINT uUserNameSize = 0;
  1176. UINT uPasswordSize = 0;
  1177. UINT uAdministratorsSize = 0;
  1178. UINT uAdminOffset = 0;
  1179. int i;
  1180. COM_PROTECT_TRY
  1181. {
  1182. *ppTapiConfig = NULL;
  1183. // calculate the size of the struct we will need
  1184. uDomainNameSize = (tapiConfigInfo.m_strDomainName.GetLength() + 1) * sizeof(WCHAR);
  1185. uUserNameSize = (tapiConfigInfo.m_strUserName.GetLength() + 1) * sizeof(WCHAR);
  1186. uPasswordSize = (tapiConfigInfo.m_strPassword.GetLength() + 1) * sizeof(WCHAR);
  1187. for (i = 0; i < tapiConfigInfo.m_arrayAdministrators.GetSize(); i++)
  1188. {
  1189. uAdministratorsSize += (tapiConfigInfo.m_arrayAdministrators[i].m_strName.GetLength() + 1) * sizeof(WCHAR);
  1190. }
  1191. // for the extra null terminator
  1192. if (uAdministratorsSize > 0)
  1193. uAdministratorsSize += sizeof(WCHAR);
  1194. else
  1195. // if there are no names then we need two null terminators
  1196. uAdministratorsSize += 2 * sizeof(WCHAR);
  1197. uSize += uDomainNameSize + uUserNameSize + uPasswordSize + uAdministratorsSize;
  1198. pTapiConfig = (LPTAPISERVERCONFIG) malloc(uSize);
  1199. if (NULL == pTapiConfig)
  1200. {
  1201. return;
  1202. }
  1203. ZeroMemory(pTapiConfig, uSize);
  1204. // fill in the structure
  1205. pTapiConfig->dwTotalSize = uSize;
  1206. pTapiConfig->dwNeededSize = uSize;
  1207. pTapiConfig->dwUsedSize = uSize;
  1208. pTapiConfig->dwFlags = tapiConfigInfo.m_dwFlags;
  1209. pTapiConfig->dwDomainNameSize = uDomainNameSize;
  1210. pTapiConfig->dwDomainNameOffset = sizeof(TAPISERVERCONFIG);
  1211. memcpy( ((LPBYTE) pTapiConfig + pTapiConfig->dwDomainNameOffset),
  1212. (LPCTSTR) tapiConfigInfo.m_strDomainName,
  1213. uDomainNameSize );
  1214. pTapiConfig->dwUserNameSize = uUserNameSize;
  1215. pTapiConfig->dwUserNameOffset = sizeof(TAPISERVERCONFIG) + uDomainNameSize;
  1216. memcpy( ((LPBYTE) pTapiConfig + pTapiConfig->dwUserNameOffset),
  1217. (LPCTSTR) tapiConfigInfo.m_strUserName,
  1218. uUserNameSize );
  1219. pTapiConfig->dwPasswordSize = uPasswordSize;
  1220. pTapiConfig->dwPasswordOffset = sizeof(TAPISERVERCONFIG) + uDomainNameSize + uUserNameSize;
  1221. memcpy( ((LPBYTE) pTapiConfig + pTapiConfig->dwPasswordOffset),
  1222. (LPCTSTR) tapiConfigInfo.m_strPassword,
  1223. uPasswordSize );
  1224. pTapiConfig->dwAdministratorsSize = uAdministratorsSize;
  1225. pTapiConfig->dwAdministratorsOffset = sizeof(TAPISERVERCONFIG) + uDomainNameSize + uUserNameSize + uPasswordSize;
  1226. if (uAdministratorsSize > 0)
  1227. {
  1228. for (i = 0; i < tapiConfigInfo.m_arrayAdministrators.GetSize(); i++)
  1229. {
  1230. memcpy( ((LPBYTE) pTapiConfig + pTapiConfig->dwAdministratorsOffset + uAdminOffset),
  1231. (LPCTSTR) tapiConfigInfo.m_arrayAdministrators[i].m_strName,
  1232. (tapiConfigInfo.m_arrayAdministrators[i].m_strName.GetLength() + 1) * sizeof(WCHAR) );
  1233. uAdminOffset += (tapiConfigInfo.m_arrayAdministrators[i].m_strName.GetLength() + 1) * sizeof(WCHAR);
  1234. }
  1235. }
  1236. *ppTapiConfig = pTapiConfig;
  1237. }
  1238. COM_PROTECT_CATCH
  1239. }
  1240. /*!--------------------------------------------------------------------------
  1241. CTapiInfo::TapiDeviceToInternal
  1242. -
  1243. Author: EricDav
  1244. ---------------------------------------------------------------------------*/
  1245. void
  1246. CTapiInfo::TapiDeviceToInternal(DEVICE_TYPE deviceType, LPDEVICEINFO pTapiDeviceInfo, CTapiDevice & tapiDevice)
  1247. {
  1248. HRESULT hr = hrOK;
  1249. UINT uCurSize = 0;
  1250. UINT uCurOffset = 0;
  1251. CUserInfo userTemp;
  1252. int nCount = 0;
  1253. COM_PROTECT_TRY
  1254. {
  1255. tapiDevice.m_dwPermanentID = pTapiDeviceInfo->dwPermanentDeviceID;
  1256. tapiDevice.m_dwProviderID = pTapiDeviceInfo->dwProviderID;
  1257. if (pTapiDeviceInfo->dwDeviceNameSize > 0)
  1258. {
  1259. DWORD cch = pTapiDeviceInfo->dwDeviceNameSize / sizeof(TCHAR) + 1;
  1260. LPTSTR sz = tapiDevice.m_strName.GetBufferSetLength (cch);
  1261. LPTSTR pLastChar = sz + cch - 1;
  1262. memcpy (
  1263. sz,
  1264. (LPBYTE) m_paDeviceInfo[deviceType] + pTapiDeviceInfo->dwDeviceNameOffset,
  1265. pTapiDeviceInfo->dwDeviceNameSize
  1266. );
  1267. // append NULL;
  1268. *pLastChar = _T('\0');
  1269. }
  1270. else
  1271. tapiDevice.m_strName.Empty();
  1272. // build a list of all of the devicess
  1273. // in the case that the string is empty then it will have 2 NULL terminators, one for the
  1274. // name and one for the overall string
  1275. if (pTapiDeviceInfo->dwAddressesSize > (2 * sizeof(WCHAR)))
  1276. {
  1277. uCurSize = pTapiDeviceInfo->dwAddressesSize - sizeof(WCHAR);
  1278. while (uCurOffset < uCurSize)
  1279. {
  1280. int nIndex = (int)tapiDevice.m_arrayAddresses.Add((LPCTSTR) ((LPBYTE) m_paDeviceInfo[deviceType] + pTapiDeviceInfo->dwAddressesOffset + uCurOffset));
  1281. uCurOffset += (tapiDevice.m_arrayAddresses[nIndex].GetLength() + 1) * sizeof(TCHAR);
  1282. }
  1283. }
  1284. // add all of the usernames from the list
  1285. // in the case that the string is empty then it will have 2 NULL terminators, one for the
  1286. // name and one for the overall string
  1287. if (pTapiDeviceInfo->dwDomainUserNamesSize > (2 * sizeof(WCHAR)))
  1288. {
  1289. uCurOffset = 0;
  1290. uCurSize = pTapiDeviceInfo->dwDomainUserNamesSize - sizeof(WCHAR);
  1291. while (uCurOffset < uCurSize)
  1292. {
  1293. userTemp.m_strName = (LPCTSTR) ((LPBYTE) m_paDeviceInfo[deviceType] + pTapiDeviceInfo->dwDomainUserNamesOffset + uCurOffset);
  1294. int nIndex = (int)tapiDevice.m_arrayUsers.Add(userTemp);
  1295. uCurOffset += (userTemp.m_strName.GetLength() + 1) * sizeof(TCHAR);
  1296. }
  1297. }
  1298. // in the case that the string is empty then it will have 2 NULL terminators, one for the
  1299. // name and one for the overall string
  1300. if (pTapiDeviceInfo->dwFriendlyUserNamesSize > (2 * sizeof(WCHAR)))
  1301. {
  1302. uCurOffset = 0;
  1303. uCurSize = pTapiDeviceInfo->dwFriendlyUserNamesSize - sizeof(WCHAR);
  1304. while (uCurOffset < uCurSize)
  1305. {
  1306. tapiDevice.m_arrayUsers[nCount].m_strFullName = (LPCTSTR) ((LPBYTE) m_paDeviceInfo[deviceType] + pTapiDeviceInfo->dwFriendlyUserNamesOffset + uCurOffset);
  1307. uCurOffset += (tapiDevice.m_arrayUsers[nCount].m_strFullName.GetLength() + 1) * sizeof(TCHAR);
  1308. nCount++;
  1309. }
  1310. }
  1311. }
  1312. COM_PROTECT_CATCH
  1313. }
  1314. /*!--------------------------------------------------------------------------
  1315. CTapiInfo::InternalToTapiDevice
  1316. Takes one tapi device internal struct and builds a TAPIDEVICEINFO
  1317. struct for it.
  1318. Author: EricDav
  1319. ---------------------------------------------------------------------------*/
  1320. void
  1321. CTapiInfo::InternalToTapiDevice(CTapiDevice & tapiDevice, LPDEVICEINFOLIST * ppTapiDeviceInfoList)
  1322. {
  1323. LPDEVICEINFO pDeviceInfo;
  1324. LPDEVICEINFOLIST pDeviceInfoList;
  1325. HRESULT hr = hrOK;
  1326. UINT uSize = 0;
  1327. int i;
  1328. COM_PROTECT_TRY
  1329. {
  1330. *ppTapiDeviceInfoList = NULL;
  1331. // first calculate the size of the buffer we need
  1332. uSize += (tapiDevice.m_strName.GetLength() + 1) * sizeof(WCHAR);
  1333. for (i = 0; i < tapiDevice.m_arrayAddresses.GetSize(); i++)
  1334. {
  1335. uSize += (tapiDevice.m_arrayAddresses[i].GetLength() + 1) * sizeof(WCHAR);
  1336. }
  1337. for (i = 0; i < tapiDevice.m_arrayUsers.GetSize(); i++)
  1338. {
  1339. uSize += (tapiDevice.m_arrayUsers[i].m_strName.GetLength() + 1) * sizeof(WCHAR);
  1340. uSize += (tapiDevice.m_arrayUsers[i].m_strFullName.GetLength() + 1) * sizeof(WCHAR);
  1341. }
  1342. // for the terminating NULLs for both addresses, domain and friendly names
  1343. uSize += 3 * sizeof(WCHAR);
  1344. uSize += sizeof(DEVICEINFO);
  1345. uSize += sizeof(DEVICEINFOLIST);
  1346. // now allocate a buffer
  1347. pDeviceInfoList = (LPDEVICEINFOLIST) malloc(uSize);
  1348. if (!pDeviceInfoList)
  1349. return;
  1350. ZeroMemory(pDeviceInfoList, uSize);
  1351. // now fill in the info
  1352. pDeviceInfoList->dwTotalSize = uSize;
  1353. pDeviceInfoList->dwNeededSize = uSize;
  1354. pDeviceInfoList->dwUsedSize = uSize;
  1355. pDeviceInfoList->dwNumDeviceInfoEntries = 1;
  1356. pDeviceInfoList->dwDeviceInfoSize = sizeof(DEVICEINFO);
  1357. pDeviceInfoList->dwDeviceInfoOffset = sizeof(DEVICEINFOLIST);
  1358. pDeviceInfo = (LPDEVICEINFO) (((LPBYTE) pDeviceInfoList) + pDeviceInfoList->dwDeviceInfoOffset);
  1359. pDeviceInfo->dwPermanentDeviceID = tapiDevice.m_dwPermanentID;
  1360. pDeviceInfo->dwProviderID = tapiDevice.m_dwProviderID;
  1361. // Device name
  1362. pDeviceInfo->dwDeviceNameSize = (tapiDevice.m_strName.GetLength() + 1) * sizeof(WCHAR);
  1363. pDeviceInfo->dwDeviceNameOffset = pDeviceInfoList->dwDeviceInfoOffset + sizeof(DEVICEINFO);
  1364. memcpy((LPBYTE) pDeviceInfoList + pDeviceInfo->dwDeviceNameOffset, (LPCTSTR) tapiDevice.m_strName, pDeviceInfo->dwDeviceNameSize);
  1365. // Device addresses
  1366. pDeviceInfo->dwAddressesOffset = pDeviceInfo->dwDeviceNameOffset + pDeviceInfo->dwDeviceNameSize;
  1367. for (i = 0; i < tapiDevice.m_arrayAddresses.GetSize(); i++)
  1368. {
  1369. memcpy(((LPBYTE) pDeviceInfoList + pDeviceInfo->dwAddressesOffset + pDeviceInfo->dwAddressesSize),
  1370. (LPCTSTR) tapiDevice.m_arrayAddresses[i],
  1371. (tapiDevice.m_arrayAddresses[i].GetLength() + 1) * sizeof(WCHAR));
  1372. pDeviceInfo->dwAddressesSize += (tapiDevice.m_arrayAddresses[i].GetLength() + 1) * sizeof(WCHAR);
  1373. }
  1374. // increment size by 1 for the extra null terminator
  1375. pDeviceInfo->dwAddressesSize += sizeof(WCHAR);
  1376. // now the user info
  1377. pDeviceInfo->dwDomainUserNamesOffset = pDeviceInfo->dwAddressesOffset + pDeviceInfo->dwAddressesSize;
  1378. for (i = 0; i < tapiDevice.m_arrayUsers.GetSize(); i++)
  1379. {
  1380. memcpy(((LPBYTE) pDeviceInfoList + pDeviceInfo->dwDomainUserNamesOffset + pDeviceInfo->dwDomainUserNamesSize),
  1381. (LPCTSTR) tapiDevice.m_arrayUsers[i].m_strName,
  1382. (tapiDevice.m_arrayUsers[i].m_strName.GetLength() + 1) * sizeof(WCHAR));
  1383. pDeviceInfo->dwDomainUserNamesSize += (tapiDevice.m_arrayUsers[i].m_strName.GetLength() + 1) * sizeof(WCHAR);
  1384. }
  1385. // increment size by 1 for the extra null terminator
  1386. pDeviceInfo->dwDomainUserNamesSize += sizeof(WCHAR);
  1387. // now the friendly names
  1388. pDeviceInfo->dwFriendlyUserNamesOffset = pDeviceInfo->dwDomainUserNamesOffset + pDeviceInfo->dwDomainUserNamesSize;
  1389. for (i = 0; i < tapiDevice.m_arrayUsers.GetSize(); i++)
  1390. {
  1391. memcpy(((LPBYTE) pDeviceInfoList + pDeviceInfo->dwFriendlyUserNamesOffset + pDeviceInfo->dwFriendlyUserNamesSize),
  1392. (LPCTSTR) tapiDevice.m_arrayUsers[i].m_strFullName,
  1393. (tapiDevice.m_arrayUsers[i].m_strFullName.GetLength() + 1) * sizeof(WCHAR));
  1394. pDeviceInfo->dwFriendlyUserNamesSize += (tapiDevice.m_arrayUsers[i].m_strFullName.GetLength() + 1) * sizeof(WCHAR);
  1395. }
  1396. // increment size by 1 for the extra null terminator
  1397. pDeviceInfo->dwFriendlyUserNamesSize += sizeof(WCHAR);
  1398. *ppTapiDeviceInfoList = pDeviceInfoList;
  1399. }
  1400. COM_PROTECT_CATCH
  1401. }
  1402. /*!--------------------------------------------------------------------------
  1403. CTapiInfo::GetProviderName
  1404. Takes a provider filename and tries to locate the friendly name.
  1405. Author: EricDav
  1406. ---------------------------------------------------------------------------*/
  1407. LPCTSTR
  1408. CTapiInfo::GetProviderName(DWORD dwProviderID, LPCTSTR pszFilename, LPDWORD pdwFlags)
  1409. {
  1410. UINT i;
  1411. if (m_pAvailProviderList)
  1412. {
  1413. LPAVAILABLEPROVIDERENTRY pProvider = NULL;
  1414. pProvider = (LPAVAILABLEPROVIDERENTRY) ((LPBYTE) m_pAvailProviderList + m_pAvailProviderList->dwProviderListOffset);
  1415. for (i = 0; i < m_pAvailProviderList->dwNumProviderListEntries; i++)
  1416. {
  1417. // walk the available provider info and see if we can find
  1418. // a friendly name
  1419. LPCTSTR pszCurFilename = (LPCWSTR) ((LPBYTE) m_pAvailProviderList + pProvider->dwFileNameOffset);
  1420. if (lstrcmpi(pszFilename, pszCurFilename) == 0)
  1421. {
  1422. // found it, return
  1423. if (pdwFlags)
  1424. *pdwFlags = pProvider->dwOptions;
  1425. return (LPCTSTR) ((LPBYTE) m_pAvailProviderList + pProvider->dwFriendlyNameOffset);
  1426. }
  1427. pProvider++;
  1428. }
  1429. }
  1430. // if we can't find a friendly name for the provider,
  1431. // then just return the filename that was passed in.
  1432. return pszFilename;
  1433. }
  1434. /*!--------------------------------------------------------------------------
  1435. CTapiInfo::IsAdmin
  1436. Says whether on not the current user is an admin on the machine
  1437. Author: EricDav
  1438. ---------------------------------------------------------------------------*/
  1439. BOOL
  1440. CTapiInfo::IsAdmin()
  1441. {
  1442. HRESULT hr = hrOK;
  1443. BOOL fIsAdmin = m_fIsAdmin;
  1444. BOOL fIsTapiAdmin = FALSE;
  1445. CTapiConfigInfo tapiConfigInfo;
  1446. DWORD dwErr = 0;
  1447. int i = 0;
  1448. CORg(GetConfigInfo(&tapiConfigInfo));
  1449. if (m_strCurrentUser.IsEmpty())
  1450. {
  1451. dwErr = GetCurrentUser();
  1452. }
  1453. if (dwErr == ERROR_SUCCESS)
  1454. {
  1455. for (i = 0; i < tapiConfigInfo.m_arrayAdministrators.GetSize(); i++)
  1456. {
  1457. if (tapiConfigInfo.m_arrayAdministrators[i].m_strName.CompareNoCase(m_strCurrentUser) == 0)
  1458. {
  1459. fIsTapiAdmin = TRUE;
  1460. break;
  1461. }
  1462. }
  1463. }
  1464. if (fIsTapiAdmin)
  1465. {
  1466. fIsAdmin = TRUE;
  1467. }
  1468. COM_PROTECT_ERROR_LABEL;
  1469. return fIsAdmin;
  1470. }
  1471. /*!--------------------------------------------------------------------------
  1472. CTapiInfo::GetCurrentUser
  1473. Get the current user
  1474. Author: EricDav
  1475. ---------------------------------------------------------------------------*/
  1476. DWORD
  1477. CTapiInfo::GetCurrentUser()
  1478. {
  1479. DWORD dwErr;
  1480. dwErr = ::GetCurrentUser(m_strCurrentUser);
  1481. return dwErr;
  1482. }
  1483. STDMETHODIMP
  1484. CTapiInfo::GetDeviceFlags (DWORD dwProviderID, DWORD dwPermanentID, DWORD * pdwFlags)
  1485. {
  1486. HRESULT hr;
  1487. DWORD dwDeviceID;
  1488. hr = ((GETDEVICEFLAGS) g_TapiDLL[TAPI_GET_DEVICE_FLAGS])(
  1489. m_hServer,
  1490. TRUE,
  1491. dwProviderID,
  1492. dwPermanentID,
  1493. pdwFlags,
  1494. &dwDeviceID
  1495. );
  1496. return hr;
  1497. }
  1498. /*!--------------------------------------------------------------------------
  1499. CreateTapiInfo
  1500. Helper to create the TapiInfo object.
  1501. Author: EricDav
  1502. ---------------------------------------------------------------------------*/
  1503. HRESULT
  1504. CreateTapiInfo(ITapiInfo ** ppTapiInfo)
  1505. {
  1506. AFX_MANAGE_STATE(AfxGetModuleState());
  1507. SPITapiInfo spTapiInfo;
  1508. ITapiInfo * pTapiInfo = NULL;
  1509. HRESULT hr = hrOK;
  1510. COM_PROTECT_TRY
  1511. {
  1512. pTapiInfo = new CTapiInfo;
  1513. // Do this so that it will get freed on error
  1514. spTapiInfo = pTapiInfo;
  1515. *ppTapiInfo = spTapiInfo.Transfer();
  1516. }
  1517. COM_PROTECT_CATCH
  1518. return hr;
  1519. }
  1520. /*!--------------------------------------------------------------------------
  1521. UnloadTapiDll
  1522. Unloads the TAPI32.DLL file. This is necessary whenever we stop the
  1523. TAPI service because the DLL keeps and internal handle to the service
  1524. and if the service goes away and comes back then it is confused.
  1525. The only way to reset that state is to unload the DLL.
  1526. Author: EricDav
  1527. ---------------------------------------------------------------------------*/
  1528. void UnloadTapiDll()
  1529. {
  1530. g_TapiDLL.Unload();
  1531. //if ( !g_TapiDLL.LoadFunctionPointers() )
  1532. // Assert("Could not reload the TAPI32 DLL!!!");
  1533. }
  1534. DWORD GetCurrentUser(CString & strAccount)
  1535. {
  1536. LPBYTE pBuf;
  1537. NET_API_STATUS status = NetWkstaUserGetInfo(NULL, 1, &pBuf);
  1538. if (status == NERR_Success)
  1539. {
  1540. strAccount.Empty();
  1541. WKSTA_USER_INFO_1 * pwkstaUserInfo = (WKSTA_USER_INFO_1 *) pBuf;
  1542. strAccount = pwkstaUserInfo->wkui1_logon_domain;
  1543. strAccount += _T("\\");
  1544. strAccount += pwkstaUserInfo->wkui1_username;
  1545. NetApiBufferFree(pBuf);
  1546. }
  1547. return (DWORD) status;
  1548. }
  1549. /*!--------------------------------------------------------------------------
  1550. IsAdmin
  1551. Connect to the remote machine as administrator with user-supplied
  1552. credentials to see if the user has admin priviledges
  1553. Returns
  1554. TRUE - the user has admin rights
  1555. FALSE - if user doesn't
  1556. Author: EricDav, KennT
  1557. ---------------------------------------------------------------------------*/
  1558. DWORD IsAdmin(LPCTSTR szMachineName, LPCTSTR szAccount, LPCTSTR szPassword, BOOL * pIsAdmin)
  1559. {
  1560. CString stAccount;
  1561. CString stDomain;
  1562. CString stUser;
  1563. CString stMachineName;
  1564. DWORD dwStatus;
  1565. BOOL fIsAdmin = FALSE;
  1566. // get the current user info
  1567. if (szAccount == NULL)
  1568. {
  1569. GetCurrentUser(stAccount);
  1570. }
  1571. else
  1572. {
  1573. stAccount = szAccount;
  1574. }
  1575. // separate the user and domain
  1576. int nPos = stAccount.Find(_T("\\"));
  1577. stDomain = stAccount.Left(nPos);
  1578. stUser = stAccount.Right(stAccount.GetLength() - nPos - 1);
  1579. // build the machine string
  1580. stMachineName = szMachineName;
  1581. if ( stMachineName.Left(2) != TEXT( "\\\\" ) )
  1582. {
  1583. stMachineName = TEXT( "\\\\" ) + stMachineName;
  1584. }
  1585. // validate the domain account and get the sid
  1586. PSID connectSid;
  1587. dwStatus = ValidateDomainAccount( stMachineName, stUser, stDomain, &connectSid );
  1588. if ( dwStatus != ERROR_SUCCESS )
  1589. {
  1590. goto Error;
  1591. }
  1592. // if a password was supplied, is it correct?
  1593. if (szPassword)
  1594. {
  1595. dwStatus = ValidatePassword( stUser, stDomain, szPassword );
  1596. if ( dwStatus != SEC_E_OK )
  1597. {
  1598. switch ( dwStatus )
  1599. {
  1600. case SEC_E_LOGON_DENIED:
  1601. dwStatus = ERROR_INVALID_PASSWORD;
  1602. break;
  1603. case SEC_E_INVALID_HANDLE:
  1604. dwStatus = ERROR_INTERNAL_ERROR;
  1605. break;
  1606. default:
  1607. dwStatus = ERROR_INTERNAL_ERROR;
  1608. break;
  1609. } // end of switch
  1610. goto Error;
  1611. } // Did ValidatePassword succeed?
  1612. }
  1613. // now check the machine to see if this account has admin access
  1614. fIsAdmin = IsUserAdmin( stMachineName, connectSid );
  1615. Error:
  1616. if (pIsAdmin)
  1617. *pIsAdmin = fIsAdmin;
  1618. return dwStatus;
  1619. }
  1620. BOOL
  1621. IsUserAdmin(LPCTSTR pszMachine,
  1622. PSID AccountSid)
  1623. /*++
  1624. Routine Description:
  1625. Determine if the specified account is a member of the local admin's group
  1626. Arguments:
  1627. AccountSid - pointer to service account Sid
  1628. Return Value:
  1629. True if member
  1630. --*/
  1631. {
  1632. NET_API_STATUS status;
  1633. DWORD count;
  1634. WCHAR adminGroupName[UNLEN+1];
  1635. WCHAR pwszMachine[MAX_COMPUTERNAME_LENGTH+1];
  1636. DWORD cchName = UNLEN;
  1637. PLOCALGROUP_MEMBERS_INFO_0 grpMemberInfo;
  1638. PLOCALGROUP_MEMBERS_INFO_0 pInfo;
  1639. DWORD entriesRead;
  1640. DWORD totalEntries;
  1641. DWORD_PTR resumeHandle = NULL;
  1642. DWORD bufferSize = 128;
  1643. BOOL foundEntry = FALSE;
  1644. // get the name of the admin's group
  1645. SHTCharToUnicode(pszMachine, pwszMachine, MAX_COMPUTERNAME_LENGTH+1);
  1646. if (!LookupAliasFromRid(pwszMachine,
  1647. DOMAIN_ALIAS_RID_ADMINS,
  1648. adminGroupName,
  1649. &cchName)) {
  1650. return(FALSE);
  1651. }
  1652. // get the Sids of the members of the admin's group
  1653. do
  1654. {
  1655. status = NetLocalGroupGetMembers(pwszMachine,
  1656. adminGroupName,
  1657. 0, // level 0 - just the Sid
  1658. (LPBYTE *)&grpMemberInfo,
  1659. bufferSize,
  1660. &entriesRead,
  1661. &totalEntries,
  1662. &resumeHandle);
  1663. bufferSize *= 2;
  1664. if ( status == ERROR_MORE_DATA )
  1665. {
  1666. // we got some of the data but I want it all; free this buffer and
  1667. // reset the context handle for the API
  1668. NetApiBufferFree( grpMemberInfo );
  1669. resumeHandle = NULL;
  1670. }
  1671. } while ( status == NERR_BufTooSmall || status == ERROR_MORE_DATA );
  1672. if ( status == NERR_Success )
  1673. {
  1674. // loop through the members of the admin group, comparing the supplied
  1675. // Sid to that of the group members' Sids
  1676. for ( count = 0, pInfo = grpMemberInfo; count < totalEntries; ++count, ++pInfo )
  1677. {
  1678. if ( EqualSid( AccountSid, pInfo->lgrmi0_sid ))
  1679. {
  1680. foundEntry = TRUE;
  1681. break;
  1682. }
  1683. }
  1684. NetApiBufferFree( grpMemberInfo );
  1685. }
  1686. return foundEntry;
  1687. }
  1688. //
  1689. //
  1690. //
  1691. BOOL
  1692. LookupAliasFromRid(
  1693. LPWSTR TargetComputer,
  1694. DWORD Rid,
  1695. LPWSTR Name,
  1696. PDWORD cchName
  1697. )
  1698. {
  1699. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  1700. SID_NAME_USE snu;
  1701. PSID pSid;
  1702. WCHAR DomainName[DNLEN+1];
  1703. DWORD cchDomainName = DNLEN;
  1704. BOOL bSuccess = FALSE;
  1705. //
  1706. // Sid is the same regardless of machine, since the well-known
  1707. // BUILTIN domain is referenced.
  1708. //
  1709. if(AllocateAndInitializeSid(&sia,
  1710. 2,
  1711. SECURITY_BUILTIN_DOMAIN_RID,
  1712. Rid,
  1713. 0, 0, 0, 0, 0, 0,
  1714. &pSid)) {
  1715. bSuccess = LookupAccountSidW(TargetComputer,
  1716. pSid,
  1717. Name,
  1718. cchName,
  1719. DomainName,
  1720. &cchDomainName,
  1721. &snu);
  1722. FreeSid(pSid);
  1723. }
  1724. return bSuccess;
  1725. } // LookupAliasFromRid
  1726. DWORD
  1727. ValidateDomainAccount(
  1728. IN CString Machine,
  1729. IN CString UserName,
  1730. IN CString Domain,
  1731. OUT PSID * AccountSid
  1732. )
  1733. /*++
  1734. Routine Description:
  1735. For the given credentials, look up the account SID for the specified
  1736. domain. As a side effect, the Sid is stored in theData->m_Sid.
  1737. Arguments:
  1738. pointers to strings that describe the user name, domain name, and password
  1739. AccountSid - address of pointer that receives the SID for this user
  1740. Return Value:
  1741. TRUE if everything validated ok.
  1742. --*/
  1743. {
  1744. DWORD dwStatus = ERROR_SUCCESS;
  1745. DWORD dwSidSize = 128;
  1746. DWORD dwDomainNameSize = 128;
  1747. LPWSTR pwszDomainName;
  1748. SID_NAME_USE SidType;
  1749. CString domainAccount;
  1750. PSID accountSid;
  1751. domainAccount = Domain + _T("\\") + UserName;
  1752. do {
  1753. // Attempt to allocate a buffer for the SID. Note that apparently in the
  1754. // absence of any error theData->m_Sid is freed only when theData goes
  1755. // out of scope.
  1756. accountSid = LocalAlloc( LMEM_FIXED, dwSidSize );
  1757. pwszDomainName = (LPWSTR) LocalAlloc( LMEM_FIXED, dwDomainNameSize * sizeof(WCHAR) );
  1758. // Was space allocated for the SID and domain name successfully?
  1759. if ( accountSid == NULL || pwszDomainName == NULL ) {
  1760. if ( accountSid != NULL ) {
  1761. LocalFree( accountSid );
  1762. }
  1763. if ( pwszDomainName != NULL ) {
  1764. LocalFree( pwszDomainName );
  1765. }
  1766. //FATALERR( IDS_ERR_NOT_ENOUGH_MEMORY, GetLastError() ); // no return
  1767. break;
  1768. }
  1769. // Attempt to Retrieve the SID and domain name. If LookupAccountName failes
  1770. // because of insufficient buffer size(s) dwSidSize and dwDomainNameSize
  1771. // will be set correctly for the next attempt.
  1772. if ( !LookupAccountName( Machine,
  1773. domainAccount,
  1774. accountSid,
  1775. &dwSidSize,
  1776. pwszDomainName,
  1777. &dwDomainNameSize,
  1778. &SidType ))
  1779. {
  1780. // free the Sid buffer and find out why we failed
  1781. LocalFree( accountSid );
  1782. dwStatus = GetLastError();
  1783. }
  1784. // domain name isn't needed at any time
  1785. LocalFree( pwszDomainName );
  1786. pwszDomainName = NULL;
  1787. } while ( dwStatus == ERROR_INSUFFICIENT_BUFFER );
  1788. if ( dwStatus == ERROR_SUCCESS ) {
  1789. *AccountSid = accountSid;
  1790. }
  1791. return dwStatus;
  1792. } // ValidateDomainAccount
  1793. NTSTATUS
  1794. ValidatePassword(
  1795. IN LPCWSTR UserName,
  1796. IN LPCWSTR Domain,
  1797. IN LPCWSTR Password
  1798. )
  1799. /*++
  1800. Routine Description:
  1801. Uses SSPI to validate the specified password
  1802. Arguments:
  1803. UserName - Supplies the user name
  1804. Domain - Supplies the user's domain
  1805. Password - Supplies the password
  1806. Return Value:
  1807. TRUE if the password is valid.
  1808. FALSE otherwise.
  1809. --*/
  1810. {
  1811. SECURITY_STATUS SecStatus;
  1812. SECURITY_STATUS AcceptStatus;
  1813. SECURITY_STATUS InitStatus;
  1814. CredHandle ClientCredHandle;
  1815. CredHandle ServerCredHandle;
  1816. BOOL ClientCredAllocated = FALSE;
  1817. BOOL ServerCredAllocated = FALSE;
  1818. CtxtHandle ClientContextHandle;
  1819. CtxtHandle ServerContextHandle;
  1820. TimeStamp Lifetime;
  1821. ULONG ContextAttributes;
  1822. PSecPkgInfo PackageInfo = NULL;
  1823. ULONG ClientFlags;
  1824. ULONG ServerFlags;
  1825. SEC_WINNT_AUTH_IDENTITY_W AuthIdentity;
  1826. SecBufferDesc NegotiateDesc;
  1827. SecBuffer NegotiateBuffer;
  1828. SecBufferDesc ChallengeDesc;
  1829. SecBuffer ChallengeBuffer;
  1830. SecBufferDesc AuthenticateDesc;
  1831. SecBuffer AuthenticateBuffer;
  1832. SecBufferDesc *pChallengeDesc = NULL;
  1833. CtxtHandle * pClientContextHandle = NULL;
  1834. CtxtHandle * pServerContextHandle = NULL;
  1835. AuthIdentity.User = (LPWSTR)UserName;
  1836. AuthIdentity.UserLength = lstrlenW(UserName);
  1837. AuthIdentity.Domain = (LPWSTR)Domain;
  1838. AuthIdentity.DomainLength = lstrlenW(Domain);
  1839. AuthIdentity.Password = (LPWSTR)Password;
  1840. AuthIdentity.PasswordLength = lstrlenW(Password);
  1841. AuthIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  1842. NegotiateBuffer.pvBuffer = NULL;
  1843. ChallengeBuffer.pvBuffer = NULL;
  1844. AuthenticateBuffer.pvBuffer = NULL;
  1845. //
  1846. // Get info about the security packages.
  1847. //
  1848. SecStatus = QuerySecurityPackageInfo( DEFAULT_SECURITY_PKG, &PackageInfo );
  1849. if ( SecStatus != STATUS_SUCCESS ) {
  1850. goto error_exit;
  1851. }
  1852. //
  1853. // Acquire a credential handle for the server side
  1854. //
  1855. SecStatus = AcquireCredentialsHandle(
  1856. NULL,
  1857. DEFAULT_SECURITY_PKG,
  1858. SECPKG_CRED_INBOUND,
  1859. NULL,
  1860. &AuthIdentity,
  1861. NULL,
  1862. NULL,
  1863. &ServerCredHandle,
  1864. &Lifetime );
  1865. if ( SecStatus != STATUS_SUCCESS ) {
  1866. goto error_exit;
  1867. }
  1868. ServerCredAllocated = TRUE;
  1869. //
  1870. // Acquire a credential handle for the client side
  1871. //
  1872. SecStatus = AcquireCredentialsHandle(
  1873. NULL, // New principal
  1874. DEFAULT_SECURITY_PKG,
  1875. SECPKG_CRED_OUTBOUND,
  1876. NULL,
  1877. &AuthIdentity,
  1878. NULL,
  1879. NULL,
  1880. &ClientCredHandle,
  1881. &Lifetime );
  1882. if ( SecStatus != STATUS_SUCCESS ) {
  1883. goto error_exit;
  1884. }
  1885. ClientCredAllocated = TRUE;
  1886. NegotiateBuffer.pvBuffer = LocalAlloc( 0, PackageInfo->cbMaxToken ); // [CHKCHK] check or allocate this earlier //
  1887. if ( NegotiateBuffer.pvBuffer == NULL ) {
  1888. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1889. goto error_exit;
  1890. }
  1891. ChallengeBuffer.pvBuffer = LocalAlloc( 0, PackageInfo->cbMaxToken ); // [CHKCHK]
  1892. if ( ChallengeBuffer.pvBuffer == NULL ) {
  1893. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1894. goto error_exit;
  1895. }
  1896. do {
  1897. //
  1898. // Get the NegotiateMessage (ClientSide)
  1899. //
  1900. NegotiateDesc.ulVersion = 0;
  1901. NegotiateDesc.cBuffers = 1;
  1902. NegotiateDesc.pBuffers = &NegotiateBuffer;
  1903. NegotiateBuffer.BufferType = SECBUFFER_TOKEN;
  1904. NegotiateBuffer.cbBuffer = PackageInfo->cbMaxToken;
  1905. ClientFlags = 0; // ISC_REQ_MUTUAL_AUTH | ISC_REQ_REPLAY_DETECT; // [CHKCHK] 0
  1906. InitStatus = InitializeSecurityContext(
  1907. &ClientCredHandle,
  1908. pClientContextHandle, // (NULL on the first pass, partially formed ctx on the next)
  1909. NULL, // [CHKCHK] szTargetName
  1910. ClientFlags,
  1911. 0, // Reserved 1
  1912. SECURITY_NATIVE_DREP,
  1913. pChallengeDesc, // (NULL on the first pass)
  1914. 0, // Reserved 2
  1915. &ClientContextHandle,
  1916. &NegotiateDesc,
  1917. &ContextAttributes,
  1918. &Lifetime );
  1919. if ( !NT_SUCCESS(InitStatus) ) {
  1920. SecStatus = InitStatus;
  1921. goto error_exit;
  1922. }
  1923. // ValidateBuffer( &NegotiateDesc ) // [CHKCHK]
  1924. pClientContextHandle = &ClientContextHandle;
  1925. //
  1926. // Get the ChallengeMessage (ServerSide)
  1927. //
  1928. NegotiateBuffer.BufferType |= SECBUFFER_READONLY;
  1929. ChallengeDesc.ulVersion = 0;
  1930. ChallengeDesc.cBuffers = 1;
  1931. ChallengeDesc.pBuffers = &ChallengeBuffer;
  1932. ChallengeBuffer.cbBuffer = PackageInfo->cbMaxToken;
  1933. ChallengeBuffer.BufferType = SECBUFFER_TOKEN;
  1934. ServerFlags = ASC_REQ_ALLOW_NON_USER_LOGONS; // ASC_REQ_EXTENDED_ERROR; [CHKCHK]
  1935. AcceptStatus = AcceptSecurityContext(
  1936. &ServerCredHandle,
  1937. pServerContextHandle, // (NULL on the first pass)
  1938. &NegotiateDesc,
  1939. ServerFlags,
  1940. SECURITY_NATIVE_DREP,
  1941. &ServerContextHandle,
  1942. &ChallengeDesc,
  1943. &ContextAttributes,
  1944. &Lifetime );
  1945. if ( !NT_SUCCESS(AcceptStatus) ) {
  1946. SecStatus = AcceptStatus;
  1947. goto error_exit;
  1948. }
  1949. // ValidateBuffer( &NegotiateDesc ) // [CHKCHK]
  1950. pChallengeDesc = &ChallengeDesc;
  1951. pServerContextHandle = &ServerContextHandle;
  1952. } while ( AcceptStatus == SEC_I_CONTINUE_NEEDED ); // || InitStatus == SEC_I_CONTINUE_NEEDED );
  1953. error_exit:
  1954. if (ServerCredAllocated) {
  1955. FreeCredentialsHandle( &ServerCredHandle );
  1956. }
  1957. if (ClientCredAllocated) {
  1958. FreeCredentialsHandle( &ClientCredHandle );
  1959. }
  1960. //
  1961. // Final Cleanup
  1962. //
  1963. if ( NegotiateBuffer.pvBuffer != NULL ) {
  1964. (VOID) LocalFree( NegotiateBuffer.pvBuffer );
  1965. }
  1966. if ( ChallengeBuffer.pvBuffer != NULL ) {
  1967. (VOID) LocalFree( ChallengeBuffer.pvBuffer );
  1968. }
  1969. if ( AuthenticateBuffer.pvBuffer != NULL ) {
  1970. (VOID) LocalFree( AuthenticateBuffer.pvBuffer );
  1971. }
  1972. return(SecStatus);
  1973. } // ValidatePassword