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.

2428 lines
76 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. if (NULL == pDeviceInfoList)
  798. {
  799. return E_OUTOFMEMORY;
  800. }
  801. memset(pDeviceInfoList, 0, dwNeededSize);
  802. pDeviceInfoList->dwTotalSize = dwNeededSize;
  803. switch (deviceType)
  804. {
  805. case DEVICE_LINE:
  806. lReturn = ((GETLINEINFO) g_TapiDLL[TAPI_GET_LINE_INFO])(m_hServer, pDeviceInfoList);
  807. break;
  808. case DEVICE_PHONE:
  809. lReturn = ((GETPHONEINFO) g_TapiDLL[TAPI_GET_PHONE_INFO])(m_hServer, pDeviceInfoList);
  810. break;
  811. }
  812. if (lReturn != ERROR_SUCCESS)
  813. {
  814. Trace1("CTapiInfo::EnumDevices - 2nd MMCGetDeviceInfo returned %x!\n", lReturn);
  815. free(pDeviceInfoList);
  816. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  817. }
  818. }
  819. //update the cache
  820. if (DEVICE_LINE == deviceType && m_dwCachedLineSize != pDeviceInfoList->dwNeededSize)
  821. {
  822. m_dwCachedLineSize = pDeviceInfoList->dwNeededSize;
  823. m_fCacheDirty = TRUE;
  824. }
  825. else if (DEVICE_PHONE == deviceType && m_dwCachedPhoneSize != pDeviceInfoList->dwNeededSize)
  826. {
  827. m_dwCachedPhoneSize = pDeviceInfoList->dwNeededSize;
  828. m_fCacheDirty = TRUE;
  829. }
  830. cl.Lock();
  831. if (m_paDeviceInfo[deviceType])
  832. {
  833. free (m_paDeviceInfo[deviceType]);
  834. }
  835. m_paDeviceInfo[deviceType] = pDeviceInfoList;
  836. // build our index list for sorting
  837. if (pDeviceInfoList->dwNumDeviceInfoEntries)
  838. {
  839. LPDEVICEINFO pDevice = NULL;
  840. pDevice = (LPDEVICEINFO) ((LPBYTE) pDeviceInfoList + pDeviceInfoList->dwDeviceInfoOffset);
  841. // now add all of the devices to our index
  842. for (int i = 0; i < GetTotalDeviceCount(deviceType); i++)
  843. {
  844. // walk the list of device info structs and add to the index mgr
  845. m_IndexMgr[deviceType].AddHDevice(pDevice->dwProviderID, (HDEVICE) pDevice, TRUE);
  846. pDevice++;
  847. }
  848. }
  849. cl.Unlock();
  850. }
  851. COM_PROTECT_CATCH
  852. return hr;
  853. }
  854. /*!--------------------------------------------------------------------------
  855. CTapiInfo::GetTotalDeviceCount
  856. -
  857. Author: EricDav
  858. ---------------------------------------------------------------------------*/
  859. STDMETHODIMP_(int)
  860. CTapiInfo::GetTotalDeviceCount(DEVICE_TYPE deviceType)
  861. {
  862. CSingleLock cl(&m_csData);
  863. cl.Lock();
  864. if (m_paDeviceInfo[deviceType])
  865. {
  866. return m_paDeviceInfo[deviceType]->dwNumDeviceInfoEntries;
  867. }
  868. else
  869. {
  870. return 0;
  871. }
  872. }
  873. /*!--------------------------------------------------------------------------
  874. CTapiInfo::GetDeviceCount
  875. -
  876. Author: EricDav
  877. ---------------------------------------------------------------------------*/
  878. STDMETHODIMP_(int)
  879. CTapiInfo::GetDeviceCount(DEVICE_TYPE deviceType, DWORD dwProviderID)
  880. {
  881. m_IndexMgr[deviceType].SetCurrentProvider(dwProviderID);
  882. return m_IndexMgr[deviceType].GetCurrentCount();
  883. }
  884. /*!--------------------------------------------------------------------------
  885. CTapiInfo::GetDeviceInfo
  886. -
  887. Author: EricDav
  888. ---------------------------------------------------------------------------*/
  889. STDMETHODIMP
  890. CTapiInfo::GetDeviceInfo(DEVICE_TYPE deviceType, CTapiDevice * ptapiDevice, DWORD dwProviderID, int nIndex)
  891. {
  892. CSingleLock cl(&m_csData);
  893. cl.Lock();
  894. LPDEVICEINFO pDevice = NULL;
  895. HDEVICE hdevice = NULL;
  896. HRESULT hr = hrOK;
  897. if (m_paDeviceInfo[deviceType] == NULL)
  898. return E_FAIL;
  899. if ((UINT) nIndex > m_paDeviceInfo[deviceType]->dwNumDeviceInfoEntries)
  900. return E_INVALIDARG;
  901. hr = m_IndexMgr[deviceType].GetHDevice(dwProviderID, nIndex, &hdevice);
  902. if (FAILED(hr))
  903. return hr;
  904. pDevice = (LPDEVICEINFO) hdevice;
  905. if (pDevice == NULL)
  906. return E_FAIL;
  907. TapiDeviceToInternal(deviceType, pDevice, *ptapiDevice);
  908. return hr;
  909. }
  910. /*!--------------------------------------------------------------------------
  911. CTapiInfo::SetDeviceInfo
  912. Sets the device info on a TAPI server. First builds a deviceinfolist
  913. struct to user for the SetDeviceInfo call then updates the internal
  914. device info list.
  915. Author: EricDav
  916. ---------------------------------------------------------------------------*/
  917. STDMETHODIMP
  918. CTapiInfo::SetDeviceInfo(DEVICE_TYPE deviceType, CTapiDevice * ptapiDevice)
  919. {
  920. CSingleLock cl(&m_csData);
  921. cl.Lock();
  922. HRESULT hr = hrOK;
  923. LONG lReturn = 0;
  924. LPDEVICEINFOLIST pDeviceInfoList = NULL, pNewDeviceInfoList;
  925. LPDEVICEINFO pDeviceInfo = NULL;
  926. int i;
  927. if ( !g_TapiDLL.LoadFunctionPointers() )
  928. return S_OK;
  929. if (m_hServer == NULL)
  930. {
  931. Trace0("CTapiInfo::EnumDevices - Server not initialized!\n");
  932. return E_FAIL;
  933. }
  934. InternalToTapiDevice(*ptapiDevice, &pDeviceInfoList);
  935. Assert(pDeviceInfoList);
  936. if (!pDeviceInfoList)
  937. return E_OUTOFMEMORY;
  938. // make the call...
  939. switch (deviceType)
  940. {
  941. case DEVICE_LINE:
  942. lReturn = ((SETLINEINFO) g_TapiDLL[TAPI_SET_LINE_INFO])(m_hServer, pDeviceInfoList);
  943. break;
  944. case DEVICE_PHONE:
  945. lReturn = ((SETPHONEINFO) g_TapiDLL[TAPI_SET_PHONE_INFO])(m_hServer, pDeviceInfoList);
  946. break;
  947. }
  948. if (lReturn != ERROR_SUCCESS)
  949. {
  950. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  951. }
  952. // finally, update our internal struct to reflect the changes
  953. Assert(m_paDeviceInfo[deviceType]);
  954. pDeviceInfo = (LPDEVICEINFO) ((LPBYTE) pDeviceInfoList + pDeviceInfoList->dwDeviceInfoOffset);
  955. // find the device in the list
  956. LPDEVICEINFO pDevice = NULL;
  957. pDevice = (LPDEVICEINFO) ((LPBYTE) m_paDeviceInfo[deviceType] + m_paDeviceInfo[deviceType]->dwDeviceInfoOffset);
  958. for (i = 0; i < GetTotalDeviceCount(deviceType); i++)
  959. {
  960. // walk the list of device info structs and add to the index mgr
  961. if (pDevice->dwPermanentDeviceID == ptapiDevice->m_dwPermanentID)
  962. {
  963. // update the device info here. First check to make sure we have enough room to grow
  964. if (m_paDeviceInfo[deviceType]->dwTotalSize < (m_paDeviceInfo[deviceType]->dwUsedSize + pDeviceInfo->dwDomainUserNamesSize + pDeviceInfo->dwFriendlyUserNamesSize))
  965. {
  966. // we've run out of room. Realloc a bigger piece
  967. pNewDeviceInfoList = (LPDEVICEINFOLIST) realloc(m_paDeviceInfo[deviceType], m_paDeviceInfo[deviceType]->dwTotalSize + DEVICEINFO_GROW_SIZE);
  968. if (pNewDeviceInfoList == NULL)
  969. {
  970. free(pDeviceInfoList);
  971. return E_OUTOFMEMORY;
  972. }
  973. else
  974. {
  975. m_paDeviceInfo[deviceType] = pNewDeviceInfoList;
  976. }
  977. // Update the dwTotalSize
  978. m_paDeviceInfo[deviceType]->dwTotalSize = m_paDeviceInfo[deviceType]->dwTotalSize + DEVICEINFO_GROW_SIZE;
  979. }
  980. // update the sizes
  981. pDevice->dwDomainUserNamesSize = pDeviceInfo->dwDomainUserNamesSize;
  982. pDevice->dwFriendlyUserNamesSize = pDeviceInfo->dwFriendlyUserNamesSize;
  983. // update the new domain name info
  984. pDevice->dwDomainUserNamesOffset = m_paDeviceInfo[deviceType]->dwUsedSize;
  985. memcpy(((LPBYTE) m_paDeviceInfo[deviceType] + pDevice->dwDomainUserNamesOffset),
  986. ((LPBYTE) pDeviceInfoList + pDeviceInfo->dwDomainUserNamesOffset),
  987. pDeviceInfo->dwDomainUserNamesSize);
  988. // update the new friendly name info
  989. pDevice->dwFriendlyUserNamesOffset = m_paDeviceInfo[deviceType]->dwUsedSize + pDevice->dwDomainUserNamesSize;
  990. memcpy(((LPBYTE) m_paDeviceInfo[deviceType] + pDevice->dwFriendlyUserNamesOffset),
  991. ((LPBYTE) pDeviceInfoList + pDeviceInfo->dwFriendlyUserNamesOffset),
  992. pDeviceInfo->dwFriendlyUserNamesOffset);
  993. m_paDeviceInfo[deviceType]->dwUsedSize += (pDevice->dwDomainUserNamesSize + pDevice->dwFriendlyUserNamesSize);
  994. }
  995. pDevice++;
  996. }
  997. free(pDeviceInfoList);
  998. return hr;
  999. }
  1000. /*!--------------------------------------------------------------------------
  1001. CTapiInfo::SortDeviceInfo
  1002. -
  1003. Author: EricDav
  1004. ---------------------------------------------------------------------------*/
  1005. STDMETHODIMP
  1006. CTapiInfo::SortDeviceInfo(DEVICE_TYPE deviceType, DWORD dwProviderID, INDEX_TYPE indexType, DWORD dwSortOptions)
  1007. {
  1008. CSingleLock cl(&m_csData);
  1009. cl.Lock();
  1010. HRESULT hr = hrOK;
  1011. if (m_paDeviceInfo[deviceType])
  1012. m_IndexMgr[deviceType].Sort(dwProviderID, indexType, dwSortOptions, (LPBYTE) m_paDeviceInfo[deviceType]);
  1013. return hr;
  1014. }
  1015. /*!--------------------------------------------------------------------------
  1016. CTapiInfo::GetDeviceStatus
  1017. -
  1018. Author: EricDav
  1019. ---------------------------------------------------------------------------*/
  1020. STDMETHODIMP
  1021. CTapiInfo::GetDeviceStatus(DEVICE_TYPE deviceType, CString * pstrStatus, DWORD dwProviderID, int nIndex, HWND hWnd)
  1022. {
  1023. CSingleLock cl(&m_csData);
  1024. HRESULT hr = hrOK;
  1025. LPDEVICEINFO pDevice = NULL;
  1026. HDEVICE hdevice;
  1027. LONG lReturn = 0;
  1028. BYTE data[256] = {0};
  1029. LPVARSTRING pVarStatus = (LPVARSTRING) &data[0];
  1030. int nHash;
  1031. CString strStatus;
  1032. CString strData;
  1033. HWND hWndParent;
  1034. if (hWnd == NULL)
  1035. {
  1036. hWndParent = ::FindMMCMainWindow();
  1037. }
  1038. else
  1039. {
  1040. hWndParent = hWnd;
  1041. }
  1042. if ( !g_TapiDLL.LoadFunctionPointers() )
  1043. return S_OK;
  1044. if (m_hServer == NULL)
  1045. {
  1046. Trace0("CTapiInfo::EnumDevices - Server not initialized!\n");
  1047. return E_FAIL;
  1048. }
  1049. cl.Lock();
  1050. hr = m_IndexMgr[deviceType].GetHDevice(dwProviderID, nIndex, &hdevice);
  1051. if (FAILED(hr))
  1052. return hr;
  1053. pDevice = (LPDEVICEINFO) hdevice;
  1054. if (pDevice == NULL)
  1055. return E_FAIL;
  1056. // try to get the string
  1057. pVarStatus->dwTotalSize = sizeof(data);
  1058. switch (deviceType)
  1059. {
  1060. case DEVICE_LINE:
  1061. lReturn = ((GETLINESTATUS) g_TapiDLL[TAPI_GET_LINE_STATUS])(m_hServer,
  1062. hWndParent,
  1063. 0,
  1064. pDevice->dwProviderID,
  1065. pDevice->dwPermanentDeviceID,
  1066. pVarStatus);
  1067. break;
  1068. case DEVICE_PHONE:
  1069. lReturn = ((GETLINESTATUS) g_TapiDLL[TAPI_GET_PHONE_STATUS])(m_hServer,
  1070. hWndParent,
  1071. 0,
  1072. pDevice->dwProviderID,
  1073. pDevice->dwPermanentDeviceID,
  1074. pVarStatus);
  1075. break;
  1076. }
  1077. if (lReturn != ERROR_SUCCESS)
  1078. {
  1079. Trace1("CTapiInfo::GetDeviceStatus - 1st call to GetDeviceStatus returned %x!\n", lReturn);
  1080. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  1081. }
  1082. if (pVarStatus->dwNeededSize > pVarStatus->dwTotalSize)
  1083. {
  1084. // buffer not big enough, try again.
  1085. pVarStatus = (LPVARSTRING) alloca(pVarStatus->dwNeededSize);
  1086. memset(pVarStatus, 0, pVarStatus->dwNeededSize);
  1087. pVarStatus->dwTotalSize = pVarStatus->dwNeededSize;
  1088. switch (deviceType)
  1089. {
  1090. case DEVICE_LINE:
  1091. lReturn = ((GETLINESTATUS) g_TapiDLL[TAPI_GET_LINE_STATUS])(m_hServer,
  1092. hWndParent,
  1093. 0,
  1094. pDevice->dwProviderID,
  1095. pDevice->dwPermanentDeviceID,
  1096. pVarStatus);
  1097. break;
  1098. case DEVICE_PHONE:
  1099. lReturn = ((GETLINESTATUS) g_TapiDLL[TAPI_GET_PHONE_STATUS])(m_hServer,
  1100. hWndParent,
  1101. 0,
  1102. pDevice->dwProviderID,
  1103. pDevice->dwPermanentDeviceID,
  1104. pVarStatus);
  1105. break;
  1106. }
  1107. if (lReturn != ERROR_SUCCESS)
  1108. {
  1109. Trace1("CTapiInfo::GetDeviceStatus - 2nd call to GetDeviceStatus returned %x!\n", lReturn);
  1110. return HRESULT_FROM_WIN32(TAPIERROR_FORMATMESSAGE(lReturn));
  1111. }
  1112. }
  1113. cl.Unlock();
  1114. // now see if the string exists in our table. If so, return a pointer to that,
  1115. // otherwise add and return a pointer to our table.
  1116. strStatus = (LPCTSTR) ((LPBYTE) pVarStatus + pVarStatus->dwStringOffset);
  1117. if (!m_mapStatusStrings.Lookup(strStatus, strData))
  1118. {
  1119. Trace1("CTapiInfo::GetDeviceStatus - Entry for %s added.\n", strStatus);
  1120. strData = strStatus;
  1121. m_mapStatusStrings.SetAt(strStatus, strData);
  1122. }
  1123. else
  1124. {
  1125. // entry is already in our map
  1126. }
  1127. *pstrStatus = strData;
  1128. return hr;
  1129. }
  1130. /*!--------------------------------------------------------------------------
  1131. Internal functions
  1132. ---------------------------------------------------------------------------*/
  1133. /*!--------------------------------------------------------------------------
  1134. CTapiInfo::TapiConfigToInternal
  1135. -
  1136. Author: EricDav
  1137. ---------------------------------------------------------------------------*/
  1138. void
  1139. CTapiInfo::TapiConfigToInternal(LPTAPISERVERCONFIG pTapiConfig, CTapiConfigInfo & tapiConfigInfo)
  1140. {
  1141. HRESULT hr = hrOK;
  1142. UINT uAdminLength = (pTapiConfig->dwAdministratorsSize != 0) ? pTapiConfig->dwAdministratorsSize - sizeof(WCHAR) : 0;
  1143. UINT uAdminOffset = 0;
  1144. CUserInfo userTemp;
  1145. COM_PROTECT_TRY
  1146. {
  1147. if (pTapiConfig->dwDomainNameSize)
  1148. tapiConfigInfo.m_strDomainName = (LPCTSTR) ((LPBYTE) pTapiConfig + pTapiConfig->dwDomainNameOffset);
  1149. if (pTapiConfig->dwUserNameSize)
  1150. tapiConfigInfo.m_strUserName = (LPCTSTR) ((LPBYTE) pTapiConfig + pTapiConfig->dwUserNameOffset);
  1151. if (pTapiConfig->dwPasswordSize)
  1152. tapiConfigInfo.m_strPassword = (LPCTSTR) ((LPBYTE) pTapiConfig + pTapiConfig->dwPasswordOffset);
  1153. // add all of the administrators from the list
  1154. while (uAdminOffset < uAdminLength)
  1155. {
  1156. userTemp.m_strName = (LPCTSTR) ((LPBYTE) pTapiConfig + pTapiConfig->dwAdministratorsOffset + uAdminOffset);
  1157. if (!userTemp.m_strName.IsEmpty())
  1158. {
  1159. int nIndex = (int)tapiConfigInfo.m_arrayAdministrators.Add(userTemp);
  1160. }
  1161. uAdminOffset += (userTemp.m_strName.GetLength() + 1) * sizeof(TCHAR);
  1162. }
  1163. tapiConfigInfo.m_dwFlags = pTapiConfig->dwFlags;
  1164. }
  1165. COM_PROTECT_CATCH
  1166. }
  1167. /*!--------------------------------------------------------------------------
  1168. CTapiInfo::InternalToTapiConfig
  1169. -
  1170. Author: EricDav
  1171. ---------------------------------------------------------------------------*/
  1172. void
  1173. CTapiInfo::InternalToTapiConfig(CTapiConfigInfo & tapiConfigInfo, LPTAPISERVERCONFIG * ppTapiConfig)
  1174. {
  1175. LPTAPISERVERCONFIG pTapiConfig = NULL;
  1176. HRESULT hr = hrOK;
  1177. UINT uSize = sizeof(TAPISERVERCONFIG);
  1178. UINT uDomainNameSize = 0;
  1179. UINT uUserNameSize = 0;
  1180. UINT uPasswordSize = 0;
  1181. UINT uAdministratorsSize = 0;
  1182. UINT uAdminOffset = 0;
  1183. int i;
  1184. COM_PROTECT_TRY
  1185. {
  1186. *ppTapiConfig = NULL;
  1187. // calculate the size of the struct we will need
  1188. uDomainNameSize = (tapiConfigInfo.m_strDomainName.GetLength() + 1) * sizeof(WCHAR);
  1189. uUserNameSize = (tapiConfigInfo.m_strUserName.GetLength() + 1) * sizeof(WCHAR);
  1190. uPasswordSize = (tapiConfigInfo.m_strPassword.GetLength() + 1) * sizeof(WCHAR);
  1191. for (i = 0; i < tapiConfigInfo.m_arrayAdministrators.GetSize(); i++)
  1192. {
  1193. uAdministratorsSize += (tapiConfigInfo.m_arrayAdministrators[i].m_strName.GetLength() + 1) * sizeof(WCHAR);
  1194. }
  1195. // for the extra null terminator
  1196. if (uAdministratorsSize > 0)
  1197. uAdministratorsSize += sizeof(WCHAR);
  1198. else
  1199. // if there are no names then we need two null terminators
  1200. uAdministratorsSize += 2 * sizeof(WCHAR);
  1201. uSize += uDomainNameSize + uUserNameSize + uPasswordSize + uAdministratorsSize;
  1202. pTapiConfig = (LPTAPISERVERCONFIG) malloc(uSize);
  1203. if (NULL == pTapiConfig)
  1204. {
  1205. return;
  1206. }
  1207. ZeroMemory(pTapiConfig, uSize);
  1208. // fill in the structure
  1209. pTapiConfig->dwTotalSize = uSize;
  1210. pTapiConfig->dwNeededSize = uSize;
  1211. pTapiConfig->dwUsedSize = uSize;
  1212. pTapiConfig->dwFlags = tapiConfigInfo.m_dwFlags;
  1213. pTapiConfig->dwDomainNameSize = uDomainNameSize;
  1214. pTapiConfig->dwDomainNameOffset = sizeof(TAPISERVERCONFIG);
  1215. memcpy( ((LPBYTE) pTapiConfig + pTapiConfig->dwDomainNameOffset),
  1216. (LPCTSTR) tapiConfigInfo.m_strDomainName,
  1217. uDomainNameSize );
  1218. pTapiConfig->dwUserNameSize = uUserNameSize;
  1219. pTapiConfig->dwUserNameOffset = sizeof(TAPISERVERCONFIG) + uDomainNameSize;
  1220. memcpy( ((LPBYTE) pTapiConfig + pTapiConfig->dwUserNameOffset),
  1221. (LPCTSTR) tapiConfigInfo.m_strUserName,
  1222. uUserNameSize );
  1223. pTapiConfig->dwPasswordSize = uPasswordSize;
  1224. pTapiConfig->dwPasswordOffset = sizeof(TAPISERVERCONFIG) + uDomainNameSize + uUserNameSize;
  1225. memcpy( ((LPBYTE) pTapiConfig + pTapiConfig->dwPasswordOffset),
  1226. (LPCTSTR) tapiConfigInfo.m_strPassword,
  1227. uPasswordSize );
  1228. pTapiConfig->dwAdministratorsSize = uAdministratorsSize;
  1229. pTapiConfig->dwAdministratorsOffset = sizeof(TAPISERVERCONFIG) + uDomainNameSize + uUserNameSize + uPasswordSize;
  1230. if (uAdministratorsSize > 0)
  1231. {
  1232. for (i = 0; i < tapiConfigInfo.m_arrayAdministrators.GetSize(); i++)
  1233. {
  1234. memcpy( ((LPBYTE) pTapiConfig + pTapiConfig->dwAdministratorsOffset + uAdminOffset),
  1235. (LPCTSTR) tapiConfigInfo.m_arrayAdministrators[i].m_strName,
  1236. (tapiConfigInfo.m_arrayAdministrators[i].m_strName.GetLength() + 1) * sizeof(WCHAR) );
  1237. uAdminOffset += (tapiConfigInfo.m_arrayAdministrators[i].m_strName.GetLength() + 1) * sizeof(WCHAR);
  1238. }
  1239. }
  1240. *ppTapiConfig = pTapiConfig;
  1241. }
  1242. COM_PROTECT_CATCH
  1243. }
  1244. /*!--------------------------------------------------------------------------
  1245. CTapiInfo::TapiDeviceToInternal
  1246. -
  1247. Author: EricDav
  1248. ---------------------------------------------------------------------------*/
  1249. void
  1250. CTapiInfo::TapiDeviceToInternal(DEVICE_TYPE deviceType, LPDEVICEINFO pTapiDeviceInfo, CTapiDevice & tapiDevice)
  1251. {
  1252. HRESULT hr = hrOK;
  1253. UINT uCurSize = 0;
  1254. UINT uCurOffset = 0;
  1255. CUserInfo userTemp;
  1256. int nCount = 0;
  1257. COM_PROTECT_TRY
  1258. {
  1259. tapiDevice.m_dwPermanentID = pTapiDeviceInfo->dwPermanentDeviceID;
  1260. tapiDevice.m_dwProviderID = pTapiDeviceInfo->dwProviderID;
  1261. if (pTapiDeviceInfo->dwDeviceNameSize > 0)
  1262. {
  1263. DWORD cch = pTapiDeviceInfo->dwDeviceNameSize / sizeof(TCHAR) + 1;
  1264. LPTSTR sz = tapiDevice.m_strName.GetBufferSetLength (cch);
  1265. LPTSTR pLastChar = sz + cch - 1;
  1266. memcpy (
  1267. sz,
  1268. (LPBYTE) m_paDeviceInfo[deviceType] + pTapiDeviceInfo->dwDeviceNameOffset,
  1269. pTapiDeviceInfo->dwDeviceNameSize
  1270. );
  1271. // append NULL;
  1272. *pLastChar = _T('\0');
  1273. }
  1274. else
  1275. tapiDevice.m_strName.Empty();
  1276. // build a list of all of the devicess
  1277. // in the case that the string is empty then it will have 2 NULL terminators, one for the
  1278. // name and one for the overall string
  1279. if (pTapiDeviceInfo->dwAddressesSize > (2 * sizeof(WCHAR)))
  1280. {
  1281. uCurSize = pTapiDeviceInfo->dwAddressesSize - sizeof(WCHAR);
  1282. while (uCurOffset < uCurSize)
  1283. {
  1284. int nIndex = (int)tapiDevice.m_arrayAddresses.Add((LPCTSTR) ((LPBYTE) m_paDeviceInfo[deviceType] + pTapiDeviceInfo->dwAddressesOffset + uCurOffset));
  1285. uCurOffset += (tapiDevice.m_arrayAddresses[nIndex].GetLength() + 1) * sizeof(TCHAR);
  1286. }
  1287. }
  1288. // add all of the usernames from the list
  1289. // in the case that the string is empty then it will have 2 NULL terminators, one for the
  1290. // name and one for the overall string
  1291. if (pTapiDeviceInfo->dwDomainUserNamesSize > (2 * sizeof(WCHAR)))
  1292. {
  1293. uCurOffset = 0;
  1294. uCurSize = pTapiDeviceInfo->dwDomainUserNamesSize - sizeof(WCHAR);
  1295. while (uCurOffset < uCurSize)
  1296. {
  1297. userTemp.m_strName = (LPCTSTR) ((LPBYTE) m_paDeviceInfo[deviceType] + pTapiDeviceInfo->dwDomainUserNamesOffset + uCurOffset);
  1298. int nIndex = (int)tapiDevice.m_arrayUsers.Add(userTemp);
  1299. uCurOffset += (userTemp.m_strName.GetLength() + 1) * sizeof(TCHAR);
  1300. }
  1301. }
  1302. // in the case that the string is empty then it will have 2 NULL terminators, one for the
  1303. // name and one for the overall string
  1304. if (pTapiDeviceInfo->dwFriendlyUserNamesSize > (2 * sizeof(WCHAR)))
  1305. {
  1306. uCurOffset = 0;
  1307. uCurSize = pTapiDeviceInfo->dwFriendlyUserNamesSize - sizeof(WCHAR);
  1308. while (uCurOffset < uCurSize)
  1309. {
  1310. tapiDevice.m_arrayUsers[nCount].m_strFullName = (LPCTSTR) ((LPBYTE) m_paDeviceInfo[deviceType] + pTapiDeviceInfo->dwFriendlyUserNamesOffset + uCurOffset);
  1311. uCurOffset += (tapiDevice.m_arrayUsers[nCount].m_strFullName.GetLength() + 1) * sizeof(TCHAR);
  1312. nCount++;
  1313. }
  1314. }
  1315. }
  1316. COM_PROTECT_CATCH
  1317. }
  1318. /*!--------------------------------------------------------------------------
  1319. CTapiInfo::InternalToTapiDevice
  1320. Takes one tapi device internal struct and builds a TAPIDEVICEINFO
  1321. struct for it.
  1322. Author: EricDav
  1323. ---------------------------------------------------------------------------*/
  1324. void
  1325. CTapiInfo::InternalToTapiDevice(CTapiDevice & tapiDevice, LPDEVICEINFOLIST * ppTapiDeviceInfoList)
  1326. {
  1327. LPDEVICEINFO pDeviceInfo;
  1328. LPDEVICEINFOLIST pDeviceInfoList;
  1329. HRESULT hr = hrOK;
  1330. UINT uSize = 0;
  1331. int i;
  1332. COM_PROTECT_TRY
  1333. {
  1334. *ppTapiDeviceInfoList = NULL;
  1335. // first calculate the size of the buffer we need
  1336. uSize += (tapiDevice.m_strName.GetLength() + 1) * sizeof(WCHAR);
  1337. for (i = 0; i < tapiDevice.m_arrayAddresses.GetSize(); i++)
  1338. {
  1339. uSize += (tapiDevice.m_arrayAddresses[i].GetLength() + 1) * sizeof(WCHAR);
  1340. }
  1341. for (i = 0; i < tapiDevice.m_arrayUsers.GetSize(); i++)
  1342. {
  1343. uSize += (tapiDevice.m_arrayUsers[i].m_strName.GetLength() + 1) * sizeof(WCHAR);
  1344. uSize += (tapiDevice.m_arrayUsers[i].m_strFullName.GetLength() + 1) * sizeof(WCHAR);
  1345. }
  1346. // for the terminating NULLs for both addresses, domain and friendly names
  1347. uSize += 3 * sizeof(WCHAR);
  1348. uSize += sizeof(DEVICEINFO);
  1349. uSize += sizeof(DEVICEINFOLIST);
  1350. // now allocate a buffer
  1351. pDeviceInfoList = (LPDEVICEINFOLIST) malloc(uSize);
  1352. if (!pDeviceInfoList)
  1353. return;
  1354. ZeroMemory(pDeviceInfoList, uSize);
  1355. // now fill in the info
  1356. pDeviceInfoList->dwTotalSize = uSize;
  1357. pDeviceInfoList->dwNeededSize = uSize;
  1358. pDeviceInfoList->dwUsedSize = uSize;
  1359. pDeviceInfoList->dwNumDeviceInfoEntries = 1;
  1360. pDeviceInfoList->dwDeviceInfoSize = sizeof(DEVICEINFO);
  1361. pDeviceInfoList->dwDeviceInfoOffset = sizeof(DEVICEINFOLIST);
  1362. pDeviceInfo = (LPDEVICEINFO) (((LPBYTE) pDeviceInfoList) + pDeviceInfoList->dwDeviceInfoOffset);
  1363. pDeviceInfo->dwPermanentDeviceID = tapiDevice.m_dwPermanentID;
  1364. pDeviceInfo->dwProviderID = tapiDevice.m_dwProviderID;
  1365. // Device name
  1366. pDeviceInfo->dwDeviceNameSize = (tapiDevice.m_strName.GetLength() + 1) * sizeof(WCHAR);
  1367. pDeviceInfo->dwDeviceNameOffset = pDeviceInfoList->dwDeviceInfoOffset + sizeof(DEVICEINFO);
  1368. memcpy((LPBYTE) pDeviceInfoList + pDeviceInfo->dwDeviceNameOffset, (LPCTSTR) tapiDevice.m_strName, pDeviceInfo->dwDeviceNameSize);
  1369. // Device addresses
  1370. pDeviceInfo->dwAddressesOffset = pDeviceInfo->dwDeviceNameOffset + pDeviceInfo->dwDeviceNameSize;
  1371. for (i = 0; i < tapiDevice.m_arrayAddresses.GetSize(); i++)
  1372. {
  1373. memcpy(((LPBYTE) pDeviceInfoList + pDeviceInfo->dwAddressesOffset + pDeviceInfo->dwAddressesSize),
  1374. (LPCTSTR) tapiDevice.m_arrayAddresses[i],
  1375. (tapiDevice.m_arrayAddresses[i].GetLength() + 1) * sizeof(WCHAR));
  1376. pDeviceInfo->dwAddressesSize += (tapiDevice.m_arrayAddresses[i].GetLength() + 1) * sizeof(WCHAR);
  1377. }
  1378. // increment size by 1 for the extra null terminator
  1379. pDeviceInfo->dwAddressesSize += sizeof(WCHAR);
  1380. // now the user info
  1381. pDeviceInfo->dwDomainUserNamesOffset = pDeviceInfo->dwAddressesOffset + pDeviceInfo->dwAddressesSize;
  1382. for (i = 0; i < tapiDevice.m_arrayUsers.GetSize(); i++)
  1383. {
  1384. memcpy(((LPBYTE) pDeviceInfoList + pDeviceInfo->dwDomainUserNamesOffset + pDeviceInfo->dwDomainUserNamesSize),
  1385. (LPCTSTR) tapiDevice.m_arrayUsers[i].m_strName,
  1386. (tapiDevice.m_arrayUsers[i].m_strName.GetLength() + 1) * sizeof(WCHAR));
  1387. pDeviceInfo->dwDomainUserNamesSize += (tapiDevice.m_arrayUsers[i].m_strName.GetLength() + 1) * sizeof(WCHAR);
  1388. }
  1389. // increment size by 1 for the extra null terminator
  1390. pDeviceInfo->dwDomainUserNamesSize += sizeof(WCHAR);
  1391. // now the friendly names
  1392. pDeviceInfo->dwFriendlyUserNamesOffset = pDeviceInfo->dwDomainUserNamesOffset + pDeviceInfo->dwDomainUserNamesSize;
  1393. for (i = 0; i < tapiDevice.m_arrayUsers.GetSize(); i++)
  1394. {
  1395. memcpy(((LPBYTE) pDeviceInfoList + pDeviceInfo->dwFriendlyUserNamesOffset + pDeviceInfo->dwFriendlyUserNamesSize),
  1396. (LPCTSTR) tapiDevice.m_arrayUsers[i].m_strFullName,
  1397. (tapiDevice.m_arrayUsers[i].m_strFullName.GetLength() + 1) * sizeof(WCHAR));
  1398. pDeviceInfo->dwFriendlyUserNamesSize += (tapiDevice.m_arrayUsers[i].m_strFullName.GetLength() + 1) * sizeof(WCHAR);
  1399. }
  1400. // increment size by 1 for the extra null terminator
  1401. pDeviceInfo->dwFriendlyUserNamesSize += sizeof(WCHAR);
  1402. *ppTapiDeviceInfoList = pDeviceInfoList;
  1403. }
  1404. COM_PROTECT_CATCH
  1405. }
  1406. /*!--------------------------------------------------------------------------
  1407. CTapiInfo::GetProviderName
  1408. Takes a provider filename and tries to locate the friendly name.
  1409. Author: EricDav
  1410. ---------------------------------------------------------------------------*/
  1411. LPCTSTR
  1412. CTapiInfo::GetProviderName(DWORD dwProviderID, LPCTSTR pszFilename, LPDWORD pdwFlags)
  1413. {
  1414. UINT i;
  1415. if (m_pAvailProviderList)
  1416. {
  1417. LPAVAILABLEPROVIDERENTRY pProvider = NULL;
  1418. pProvider = (LPAVAILABLEPROVIDERENTRY) ((LPBYTE) m_pAvailProviderList + m_pAvailProviderList->dwProviderListOffset);
  1419. for (i = 0; i < m_pAvailProviderList->dwNumProviderListEntries; i++)
  1420. {
  1421. // walk the available provider info and see if we can find
  1422. // a friendly name
  1423. LPCTSTR pszCurFilename = (LPCWSTR) ((LPBYTE) m_pAvailProviderList + pProvider->dwFileNameOffset);
  1424. if (lstrcmpi(pszFilename, pszCurFilename) == 0)
  1425. {
  1426. // found it, return
  1427. if (pdwFlags)
  1428. *pdwFlags = pProvider->dwOptions;
  1429. return (LPCTSTR) ((LPBYTE) m_pAvailProviderList + pProvider->dwFriendlyNameOffset);
  1430. }
  1431. pProvider++;
  1432. }
  1433. }
  1434. // if we can't find a friendly name for the provider,
  1435. // then just return the filename that was passed in.
  1436. return pszFilename;
  1437. }
  1438. /*!--------------------------------------------------------------------------
  1439. CTapiInfo::IsAdmin
  1440. Says whether on not the current user is an admin on the machine
  1441. Author: EricDav
  1442. ---------------------------------------------------------------------------*/
  1443. BOOL
  1444. CTapiInfo::IsAdmin()
  1445. {
  1446. HRESULT hr = hrOK;
  1447. BOOL fIsAdmin = m_fIsAdmin;
  1448. BOOL fIsTapiAdmin = FALSE;
  1449. CTapiConfigInfo tapiConfigInfo;
  1450. DWORD dwErr = 0;
  1451. int i = 0;
  1452. CORg(GetConfigInfo(&tapiConfigInfo));
  1453. if (m_strCurrentUser.IsEmpty())
  1454. {
  1455. dwErr = GetCurrentUser();
  1456. }
  1457. if (dwErr == ERROR_SUCCESS)
  1458. {
  1459. for (i = 0; i < tapiConfigInfo.m_arrayAdministrators.GetSize(); i++)
  1460. {
  1461. if (tapiConfigInfo.m_arrayAdministrators[i].m_strName.CompareNoCase(m_strCurrentUser) == 0)
  1462. {
  1463. fIsTapiAdmin = TRUE;
  1464. break;
  1465. }
  1466. }
  1467. }
  1468. if (fIsTapiAdmin)
  1469. {
  1470. fIsAdmin = TRUE;
  1471. }
  1472. COM_PROTECT_ERROR_LABEL;
  1473. return fIsAdmin;
  1474. }
  1475. /*!--------------------------------------------------------------------------
  1476. CTapiInfo::GetCurrentUser
  1477. Get the current user
  1478. Author: EricDav
  1479. ---------------------------------------------------------------------------*/
  1480. DWORD
  1481. CTapiInfo::GetCurrentUser()
  1482. {
  1483. DWORD dwErr;
  1484. dwErr = ::GetCurrentUser(m_strCurrentUser);
  1485. return dwErr;
  1486. }
  1487. STDMETHODIMP
  1488. CTapiInfo::GetDeviceFlags (DWORD dwProviderID, DWORD dwPermanentID, DWORD * pdwFlags)
  1489. {
  1490. HRESULT hr;
  1491. DWORD dwDeviceID;
  1492. hr = ((GETDEVICEFLAGS) g_TapiDLL[TAPI_GET_DEVICE_FLAGS])(
  1493. m_hServer,
  1494. TRUE,
  1495. dwProviderID,
  1496. dwPermanentID,
  1497. pdwFlags,
  1498. &dwDeviceID
  1499. );
  1500. return hr;
  1501. }
  1502. /*!--------------------------------------------------------------------------
  1503. CreateTapiInfo
  1504. Helper to create the TapiInfo object.
  1505. Author: EricDav
  1506. ---------------------------------------------------------------------------*/
  1507. HRESULT
  1508. CreateTapiInfo(ITapiInfo ** ppTapiInfo)
  1509. {
  1510. AFX_MANAGE_STATE(AfxGetModuleState());
  1511. SPITapiInfo spTapiInfo;
  1512. ITapiInfo * pTapiInfo = NULL;
  1513. HRESULT hr = hrOK;
  1514. COM_PROTECT_TRY
  1515. {
  1516. pTapiInfo = new CTapiInfo;
  1517. // Do this so that it will get freed on error
  1518. spTapiInfo = pTapiInfo;
  1519. *ppTapiInfo = spTapiInfo.Transfer();
  1520. }
  1521. COM_PROTECT_CATCH
  1522. return hr;
  1523. }
  1524. /*!--------------------------------------------------------------------------
  1525. UnloadTapiDll
  1526. Unloads the TAPI32.DLL file. This is necessary whenever we stop the
  1527. TAPI service because the DLL keeps and internal handle to the service
  1528. and if the service goes away and comes back then it is confused.
  1529. The only way to reset that state is to unload the DLL.
  1530. Author: EricDav
  1531. ---------------------------------------------------------------------------*/
  1532. void UnloadTapiDll()
  1533. {
  1534. g_TapiDLL.Unload();
  1535. //if ( !g_TapiDLL.LoadFunctionPointers() )
  1536. // Assert("Could not reload the TAPI32 DLL!!!");
  1537. }
  1538. DWORD GetCurrentUser(CString & strAccount)
  1539. {
  1540. LPBYTE pBuf;
  1541. NET_API_STATUS status = NetWkstaUserGetInfo(NULL, 1, &pBuf);
  1542. if (status == NERR_Success)
  1543. {
  1544. strAccount.Empty();
  1545. WKSTA_USER_INFO_1 * pwkstaUserInfo = (WKSTA_USER_INFO_1 *) pBuf;
  1546. strAccount = pwkstaUserInfo->wkui1_logon_domain;
  1547. strAccount += _T("\\");
  1548. strAccount += pwkstaUserInfo->wkui1_username;
  1549. NetApiBufferFree(pBuf);
  1550. }
  1551. return (DWORD) status;
  1552. }
  1553. /*!--------------------------------------------------------------------------
  1554. IsAdmin
  1555. Connect to the remote machine as administrator with user-supplied
  1556. credentials to see if the user has admin priviledges
  1557. Returns
  1558. TRUE - the user has admin rights
  1559. FALSE - if user doesn't
  1560. Author: EricDav, KennT
  1561. ---------------------------------------------------------------------------*/
  1562. DWORD IsAdmin(LPCTSTR szMachineName, LPCTSTR szAccount, LPCTSTR szPassword, BOOL * pIsAdmin)
  1563. {
  1564. CString stAccount;
  1565. CString stDomain;
  1566. CString stUser;
  1567. CString stMachineName;
  1568. DWORD dwStatus;
  1569. BOOL fIsAdmin = FALSE;
  1570. // get the current user info
  1571. if (szAccount == NULL)
  1572. {
  1573. GetCurrentUser(stAccount);
  1574. }
  1575. else
  1576. {
  1577. stAccount = szAccount;
  1578. }
  1579. // separate the user and domain
  1580. int nPos = stAccount.Find(_T("\\"));
  1581. stDomain = stAccount.Left(nPos);
  1582. stUser = stAccount.Right(stAccount.GetLength() - nPos - 1);
  1583. // build the machine string
  1584. stMachineName = szMachineName;
  1585. if ( stMachineName.Left(2) != TEXT( "\\\\" ) )
  1586. {
  1587. stMachineName = TEXT( "\\\\" ) + stMachineName;
  1588. }
  1589. // validate the domain account and get the sid
  1590. PSID connectSid;
  1591. dwStatus = ValidateDomainAccount( stMachineName, stUser, stDomain, &connectSid );
  1592. if ( dwStatus != ERROR_SUCCESS )
  1593. {
  1594. goto Error;
  1595. }
  1596. // if a password was supplied, is it correct?
  1597. if (szPassword)
  1598. {
  1599. dwStatus = ValidatePassword( stUser, stDomain, szPassword );
  1600. if ( dwStatus != SEC_E_OK )
  1601. {
  1602. switch ( dwStatus )
  1603. {
  1604. case SEC_E_LOGON_DENIED:
  1605. dwStatus = ERROR_INVALID_PASSWORD;
  1606. break;
  1607. case SEC_E_INVALID_HANDLE:
  1608. dwStatus = ERROR_INTERNAL_ERROR;
  1609. break;
  1610. default:
  1611. dwStatus = ERROR_INTERNAL_ERROR;
  1612. break;
  1613. } // end of switch
  1614. goto Error;
  1615. } // Did ValidatePassword succeed?
  1616. }
  1617. // now check the machine to see if this account has admin access
  1618. fIsAdmin = IsUserAdmin( stMachineName, connectSid );
  1619. Error:
  1620. if (pIsAdmin)
  1621. *pIsAdmin = fIsAdmin;
  1622. return dwStatus;
  1623. }
  1624. BOOL
  1625. IsUserAdmin(LPCTSTR pszMachine,
  1626. PSID AccountSid)
  1627. /*++
  1628. Routine Description:
  1629. Determine if the specified account is a member of the local admin's group
  1630. Arguments:
  1631. AccountSid - pointer to service account Sid
  1632. Return Value:
  1633. True if member
  1634. --*/
  1635. {
  1636. NET_API_STATUS status;
  1637. DWORD count;
  1638. WCHAR adminGroupName[UNLEN+1];
  1639. WCHAR pwszMachine[MAX_COMPUTERNAME_LENGTH+3]; // pszMachine comes as \\<computer-name>
  1640. DWORD cchName = UNLEN;
  1641. PLOCALGROUP_MEMBERS_INFO_0 grpMemberInfo;
  1642. PLOCALGROUP_MEMBERS_INFO_0 pInfo;
  1643. DWORD entriesRead;
  1644. DWORD totalEntries;
  1645. DWORD_PTR resumeHandle = NULL;
  1646. DWORD bufferSize = 128;
  1647. BOOL foundEntry = FALSE;
  1648. // get the name of the admin's group
  1649. SHTCharToUnicode(pszMachine, pwszMachine, MAX_COMPUTERNAME_LENGTH+3);
  1650. if (!LookupAliasFromRid(pwszMachine,
  1651. DOMAIN_ALIAS_RID_ADMINS,
  1652. adminGroupName,
  1653. &cchName)) {
  1654. return(FALSE);
  1655. }
  1656. // get the Sids of the members of the admin's group
  1657. do
  1658. {
  1659. status = NetLocalGroupGetMembers(pwszMachine,
  1660. adminGroupName,
  1661. 0, // level 0 - just the Sid
  1662. (LPBYTE *)&grpMemberInfo,
  1663. bufferSize,
  1664. &entriesRead,
  1665. &totalEntries,
  1666. &resumeHandle);
  1667. bufferSize *= 2;
  1668. if ( status == ERROR_MORE_DATA )
  1669. {
  1670. // we got some of the data but I want it all; free this buffer and
  1671. // reset the context handle for the API
  1672. NetApiBufferFree( grpMemberInfo );
  1673. resumeHandle = NULL;
  1674. }
  1675. } while ( status == NERR_BufTooSmall || status == ERROR_MORE_DATA );
  1676. if ( status == NERR_Success )
  1677. {
  1678. // loop through the members of the admin group, comparing the supplied
  1679. // Sid to that of the group members' Sids
  1680. for ( count = 0, pInfo = grpMemberInfo; count < totalEntries; ++count, ++pInfo )
  1681. {
  1682. if ( EqualSid( AccountSid, pInfo->lgrmi0_sid ))
  1683. {
  1684. foundEntry = TRUE;
  1685. break;
  1686. }
  1687. }
  1688. NetApiBufferFree( grpMemberInfo );
  1689. }
  1690. return foundEntry;
  1691. }
  1692. //
  1693. //
  1694. //
  1695. BOOL
  1696. LookupAliasFromRid(
  1697. LPWSTR TargetComputer,
  1698. DWORD Rid,
  1699. LPWSTR Name,
  1700. PDWORD cchName
  1701. )
  1702. {
  1703. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  1704. SID_NAME_USE snu;
  1705. PSID pSid;
  1706. WCHAR DomainName[DNLEN+1];
  1707. DWORD cchDomainName = DNLEN;
  1708. BOOL bSuccess = FALSE;
  1709. //
  1710. // Sid is the same regardless of machine, since the well-known
  1711. // BUILTIN domain is referenced.
  1712. //
  1713. if(AllocateAndInitializeSid(&sia,
  1714. 2,
  1715. SECURITY_BUILTIN_DOMAIN_RID,
  1716. Rid,
  1717. 0, 0, 0, 0, 0, 0,
  1718. &pSid)) {
  1719. bSuccess = LookupAccountSidW(TargetComputer,
  1720. pSid,
  1721. Name,
  1722. cchName,
  1723. DomainName,
  1724. &cchDomainName,
  1725. &snu);
  1726. FreeSid(pSid);
  1727. }
  1728. return bSuccess;
  1729. } // LookupAliasFromRid
  1730. DWORD
  1731. ValidateDomainAccount(
  1732. IN CString Machine,
  1733. IN CString UserName,
  1734. IN CString Domain,
  1735. OUT PSID * AccountSid
  1736. )
  1737. /*++
  1738. Routine Description:
  1739. For the given credentials, look up the account SID for the specified
  1740. domain. As a side effect, the Sid is stored in theData->m_Sid.
  1741. Arguments:
  1742. pointers to strings that describe the user name, domain name, and password
  1743. AccountSid - address of pointer that receives the SID for this user
  1744. Return Value:
  1745. TRUE if everything validated ok.
  1746. --*/
  1747. {
  1748. DWORD dwStatus = ERROR_SUCCESS;
  1749. DWORD dwSidSize = 128;
  1750. DWORD dwDomainNameSize = 128;
  1751. LPWSTR pwszDomainName;
  1752. SID_NAME_USE SidType;
  1753. CString domainAccount;
  1754. PSID accountSid;
  1755. domainAccount = Domain + _T("\\") + UserName;
  1756. do {
  1757. // Attempt to allocate a buffer for the SID. Note that apparently in the
  1758. // absence of any error theData->m_Sid is freed only when theData goes
  1759. // out of scope.
  1760. accountSid = LocalAlloc( LMEM_FIXED, dwSidSize );
  1761. pwszDomainName = (LPWSTR) LocalAlloc( LMEM_FIXED, dwDomainNameSize * sizeof(WCHAR) );
  1762. // Was space allocated for the SID and domain name successfully?
  1763. if ( accountSid == NULL || pwszDomainName == NULL ) {
  1764. if ( accountSid != NULL ) {
  1765. LocalFree( accountSid );
  1766. }
  1767. if ( pwszDomainName != NULL ) {
  1768. LocalFree( pwszDomainName );
  1769. }
  1770. //FATALERR( IDS_ERR_NOT_ENOUGH_MEMORY, GetLastError() ); // no return
  1771. break;
  1772. }
  1773. // Attempt to Retrieve the SID and domain name. If LookupAccountName failes
  1774. // because of insufficient buffer size(s) dwSidSize and dwDomainNameSize
  1775. // will be set correctly for the next attempt.
  1776. if ( !LookupAccountName( Machine,
  1777. domainAccount,
  1778. accountSid,
  1779. &dwSidSize,
  1780. pwszDomainName,
  1781. &dwDomainNameSize,
  1782. &SidType ))
  1783. {
  1784. // free the Sid buffer and find out why we failed
  1785. LocalFree( accountSid );
  1786. dwStatus = GetLastError();
  1787. }
  1788. // domain name isn't needed at any time
  1789. LocalFree( pwszDomainName );
  1790. pwszDomainName = NULL;
  1791. } while ( dwStatus == ERROR_INSUFFICIENT_BUFFER );
  1792. if ( dwStatus == ERROR_SUCCESS ) {
  1793. *AccountSid = accountSid;
  1794. }
  1795. return dwStatus;
  1796. } // ValidateDomainAccount
  1797. NTSTATUS
  1798. ValidatePassword(
  1799. IN LPCWSTR UserName,
  1800. IN LPCWSTR Domain,
  1801. IN LPCWSTR Password
  1802. )
  1803. /*++
  1804. Routine Description:
  1805. Uses SSPI to validate the specified password
  1806. Arguments:
  1807. UserName - Supplies the user name
  1808. Domain - Supplies the user's domain
  1809. Password - Supplies the password
  1810. Return Value:
  1811. TRUE if the password is valid.
  1812. FALSE otherwise.
  1813. --*/
  1814. {
  1815. SECURITY_STATUS SecStatus;
  1816. SECURITY_STATUS AcceptStatus;
  1817. SECURITY_STATUS InitStatus;
  1818. CredHandle ClientCredHandle;
  1819. CredHandle ServerCredHandle;
  1820. BOOL ClientCredAllocated = FALSE;
  1821. BOOL ServerCredAllocated = FALSE;
  1822. CtxtHandle ClientContextHandle;
  1823. CtxtHandle ServerContextHandle;
  1824. TimeStamp Lifetime;
  1825. ULONG ContextAttributes;
  1826. PSecPkgInfo PackageInfo = NULL;
  1827. ULONG ClientFlags;
  1828. ULONG ServerFlags;
  1829. SEC_WINNT_AUTH_IDENTITY_W AuthIdentity;
  1830. SecBufferDesc NegotiateDesc;
  1831. SecBuffer NegotiateBuffer;
  1832. SecBufferDesc ChallengeDesc;
  1833. SecBuffer ChallengeBuffer;
  1834. SecBufferDesc AuthenticateDesc;
  1835. SecBuffer AuthenticateBuffer;
  1836. SecBufferDesc *pChallengeDesc = NULL;
  1837. CtxtHandle * pClientContextHandle = NULL;
  1838. CtxtHandle * pServerContextHandle = NULL;
  1839. AuthIdentity.User = (LPWSTR)UserName;
  1840. AuthIdentity.UserLength = lstrlenW(UserName);
  1841. AuthIdentity.Domain = (LPWSTR)Domain;
  1842. AuthIdentity.DomainLength = lstrlenW(Domain);
  1843. AuthIdentity.Password = (LPWSTR)Password;
  1844. AuthIdentity.PasswordLength = lstrlenW(Password);
  1845. AuthIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  1846. NegotiateBuffer.pvBuffer = NULL;
  1847. ChallengeBuffer.pvBuffer = NULL;
  1848. AuthenticateBuffer.pvBuffer = NULL;
  1849. //
  1850. // Get info about the security packages.
  1851. //
  1852. SecStatus = QuerySecurityPackageInfo( DEFAULT_SECURITY_PKG, &PackageInfo );
  1853. if ( SecStatus != STATUS_SUCCESS ) {
  1854. goto error_exit;
  1855. }
  1856. //
  1857. // Acquire a credential handle for the server side
  1858. //
  1859. SecStatus = AcquireCredentialsHandle(
  1860. NULL,
  1861. DEFAULT_SECURITY_PKG,
  1862. SECPKG_CRED_INBOUND,
  1863. NULL,
  1864. &AuthIdentity,
  1865. NULL,
  1866. NULL,
  1867. &ServerCredHandle,
  1868. &Lifetime );
  1869. if ( SecStatus != STATUS_SUCCESS ) {
  1870. goto error_exit;
  1871. }
  1872. ServerCredAllocated = TRUE;
  1873. //
  1874. // Acquire a credential handle for the client side
  1875. //
  1876. SecStatus = AcquireCredentialsHandle(
  1877. NULL, // New principal
  1878. DEFAULT_SECURITY_PKG,
  1879. SECPKG_CRED_OUTBOUND,
  1880. NULL,
  1881. &AuthIdentity,
  1882. NULL,
  1883. NULL,
  1884. &ClientCredHandle,
  1885. &Lifetime );
  1886. if ( SecStatus != STATUS_SUCCESS ) {
  1887. goto error_exit;
  1888. }
  1889. ClientCredAllocated = TRUE;
  1890. NegotiateBuffer.pvBuffer = LocalAlloc( 0, PackageInfo->cbMaxToken ); // [CHKCHK] check or allocate this earlier //
  1891. if ( NegotiateBuffer.pvBuffer == NULL ) {
  1892. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1893. goto error_exit;
  1894. }
  1895. ChallengeBuffer.pvBuffer = LocalAlloc( 0, PackageInfo->cbMaxToken ); // [CHKCHK]
  1896. if ( ChallengeBuffer.pvBuffer == NULL ) {
  1897. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1898. goto error_exit;
  1899. }
  1900. do {
  1901. //
  1902. // Get the NegotiateMessage (ClientSide)
  1903. //
  1904. NegotiateDesc.ulVersion = 0;
  1905. NegotiateDesc.cBuffers = 1;
  1906. NegotiateDesc.pBuffers = &NegotiateBuffer;
  1907. NegotiateBuffer.BufferType = SECBUFFER_TOKEN;
  1908. NegotiateBuffer.cbBuffer = PackageInfo->cbMaxToken;
  1909. ClientFlags = 0; // ISC_REQ_MUTUAL_AUTH | ISC_REQ_REPLAY_DETECT; // [CHKCHK] 0
  1910. InitStatus = InitializeSecurityContext(
  1911. &ClientCredHandle,
  1912. pClientContextHandle, // (NULL on the first pass, partially formed ctx on the next)
  1913. NULL, // [CHKCHK] szTargetName
  1914. ClientFlags,
  1915. 0, // Reserved 1
  1916. SECURITY_NATIVE_DREP,
  1917. pChallengeDesc, // (NULL on the first pass)
  1918. 0, // Reserved 2
  1919. &ClientContextHandle,
  1920. &NegotiateDesc,
  1921. &ContextAttributes,
  1922. &Lifetime );
  1923. if ( !NT_SUCCESS(InitStatus) ) {
  1924. SecStatus = InitStatus;
  1925. goto error_exit;
  1926. }
  1927. // ValidateBuffer( &NegotiateDesc ) // [CHKCHK]
  1928. pClientContextHandle = &ClientContextHandle;
  1929. //
  1930. // Get the ChallengeMessage (ServerSide)
  1931. //
  1932. NegotiateBuffer.BufferType |= SECBUFFER_READONLY;
  1933. ChallengeDesc.ulVersion = 0;
  1934. ChallengeDesc.cBuffers = 1;
  1935. ChallengeDesc.pBuffers = &ChallengeBuffer;
  1936. ChallengeBuffer.cbBuffer = PackageInfo->cbMaxToken;
  1937. ChallengeBuffer.BufferType = SECBUFFER_TOKEN;
  1938. ServerFlags = ASC_REQ_ALLOW_NON_USER_LOGONS; // ASC_REQ_EXTENDED_ERROR; [CHKCHK]
  1939. AcceptStatus = AcceptSecurityContext(
  1940. &ServerCredHandle,
  1941. pServerContextHandle, // (NULL on the first pass)
  1942. &NegotiateDesc,
  1943. ServerFlags,
  1944. SECURITY_NATIVE_DREP,
  1945. &ServerContextHandle,
  1946. &ChallengeDesc,
  1947. &ContextAttributes,
  1948. &Lifetime );
  1949. if ( !NT_SUCCESS(AcceptStatus) ) {
  1950. SecStatus = AcceptStatus;
  1951. goto error_exit;
  1952. }
  1953. // ValidateBuffer( &NegotiateDesc ) // [CHKCHK]
  1954. pChallengeDesc = &ChallengeDesc;
  1955. pServerContextHandle = &ServerContextHandle;
  1956. } while ( AcceptStatus == SEC_I_CONTINUE_NEEDED ); // || InitStatus == SEC_I_CONTINUE_NEEDED );
  1957. error_exit:
  1958. if (ServerCredAllocated) {
  1959. FreeCredentialsHandle( &ServerCredHandle );
  1960. }
  1961. if (ClientCredAllocated) {
  1962. FreeCredentialsHandle( &ClientCredHandle );
  1963. }
  1964. //
  1965. // Final Cleanup
  1966. //
  1967. if ( NegotiateBuffer.pvBuffer != NULL ) {
  1968. (VOID) LocalFree( NegotiateBuffer.pvBuffer );
  1969. }
  1970. if ( ChallengeBuffer.pvBuffer != NULL ) {
  1971. (VOID) LocalFree( ChallengeBuffer.pvBuffer );
  1972. }
  1973. if ( AuthenticateBuffer.pvBuffer != NULL ) {
  1974. (VOID) LocalFree( AuthenticateBuffer.pvBuffer );
  1975. }
  1976. return(SecStatus);
  1977. } // ValidatePassword