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.

1436 lines
36 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: CONTABLE.CPP
  4. //
  5. // Module: CMCONTBL.LIB
  6. //
  7. // Synopsis: Implements the CM connection table (CConnectionTable). The connection
  8. // table is a list of active conenctions stored in a (memory only) memory
  9. // mapped file, and shared by the various CM components in order to
  10. // manage CM connections.
  11. //
  12. // Copyright (c) 1998-1999 Microsoft Corporation
  13. //
  14. // Author: nickball Created 02/02/98
  15. //
  16. //+----------------------------------------------------------------------------
  17. #include <windows.h>
  18. #include "contable.h"
  19. #include "cmdebug.h"
  20. #include "cmutil.h"
  21. #include "uapi.h"
  22. #include "setacl.h"
  23. #if 0
  24. #include "DumpSecInfo.cpp"
  25. #endif
  26. #define CONN_TABLE_NAME TEXT("CmConnectionTable")
  27. #define CONN_TABLE_OPEN TEXT("CmConnectionOpen")
  28. #define CONN_TABLE_NAME_WIN2K_ABOVE TEXT("Global\\CmConnectionTable")
  29. #define CONN_TABLE_OPEN_WIN2K_ABOVE TEXT("Global\\CmConnectionOpen")
  30. static const int MAX_LOCK_WAIT = 1000; // wait timeout in milliseconds
  31. //
  32. // Constructor and destructor
  33. //
  34. CConnectionTable::CConnectionTable()
  35. {
  36. CMTRACE(TEXT("CConnectionTable::CConnectionTable()"));
  37. //
  38. // Initialize our data members
  39. //
  40. m_hMap = NULL;
  41. m_pConnTable = NULL;
  42. m_fLocked = FALSE;
  43. m_hEvent = NULL;
  44. }
  45. CConnectionTable::~CConnectionTable()
  46. {
  47. CMTRACE(TEXT("CConnectionTable::~CConnectionTable()"));
  48. //
  49. // Data should have been cleaned up in Close, etc. Double-Check
  50. //
  51. MYDBGASSERT(NULL == m_pConnTable);
  52. MYDBGASSERT(NULL == m_hMap);
  53. MYDBGASSERT(FALSE == m_fLocked);
  54. MYDBGASSERT(NULL == m_hEvent);
  55. //
  56. // Release handles and pointers
  57. //
  58. if (m_pConnTable)
  59. {
  60. MYVERIFY(NULL != UnmapViewOfFile(m_pConnTable));
  61. m_pConnTable = NULL;
  62. }
  63. if (m_hMap)
  64. {
  65. MYVERIFY(NULL != CloseHandle(m_hMap));
  66. m_hMap = NULL;
  67. }
  68. if (m_hEvent)
  69. {
  70. MYVERIFY(NULL != CloseHandle(m_hEvent));
  71. m_hEvent = NULL;
  72. }
  73. }
  74. //+----------------------------------------------------------------------------
  75. //
  76. // Function: CConnectionTable::LockTable
  77. //
  78. // Synopsis: Sets the internal lock on the table. Should be called internally
  79. // prior to any table access.
  80. //
  81. // Arguments: None
  82. //
  83. // Returns: HRESULT - Failure code or S_OK
  84. //
  85. // History: nickball Created 2/2/98
  86. //
  87. //+----------------------------------------------------------------------------
  88. HRESULT CConnectionTable::LockTable()
  89. {
  90. MYDBGASSERT(m_pConnTable);
  91. MYDBGASSERT(m_hMap);
  92. MYDBGASSERT(m_hEvent);
  93. CMTRACE(TEXT("CConnectionTable::LockTable()"));
  94. HRESULT hrRet = S_OK;
  95. //
  96. // Validate our current state
  97. //
  98. if (NULL == m_hEvent)
  99. {
  100. MYDBGASSERT(FALSE);
  101. return E_ACCESSDENIED;
  102. }
  103. //
  104. // Wait for the open event to be signaled
  105. //
  106. DWORD dwWait = WaitForSingleObject(m_hEvent, MAX_LOCK_WAIT);
  107. //
  108. // If our records indicate that we are already locked at this point
  109. // then something is wrong within the class implementation
  110. //
  111. MYDBGASSERT(FALSE == m_fLocked); // no double locks please
  112. if (TRUE == m_fLocked)
  113. {
  114. SetEvent(m_hEvent); // cleat the signal that we just set by clearing the wait
  115. return E_ACCESSDENIED;
  116. }
  117. //
  118. // Check the
  119. //
  120. if (WAIT_FAILED == dwWait)
  121. {
  122. MYDBGASSERT(FALSE);
  123. hrRet = GetLastError();
  124. return HRESULT_FROM_WIN32(hrRet);
  125. }
  126. //
  127. // If not signaled, bail
  128. //
  129. MYDBGASSERT(WAIT_OBJECT_0 == dwWait);
  130. if (WAIT_OBJECT_0 != dwWait)
  131. {
  132. if (WAIT_TIMEOUT == dwWait)
  133. {
  134. hrRet = HRESULT_FROM_WIN32(ERROR_TIMEOUT);
  135. }
  136. else
  137. {
  138. hrRet = E_ACCESSDENIED;
  139. }
  140. }
  141. else
  142. {
  143. //
  144. // The event is signaled automatically by virtue of the
  145. // fact that we cleared the wait on the event. Its locked.
  146. //
  147. m_fLocked = TRUE;
  148. }
  149. return hrRet;
  150. }
  151. //+----------------------------------------------------------------------------
  152. //
  153. // Function: CConnectionTable::UnlockTable
  154. //
  155. // Synopsis: Clears the internal lock on the table. Should be cleared
  156. // following any access to the table.
  157. //
  158. // Arguments: None
  159. //
  160. // Returns: HRESULT - Failure code or S_OK
  161. //
  162. // History: nickball Created 2/2/98
  163. //
  164. //+----------------------------------------------------------------------------
  165. HRESULT CConnectionTable::UnlockTable()
  166. {
  167. MYDBGASSERT(m_pConnTable);
  168. MYDBGASSERT(m_hMap);
  169. MYDBGASSERT(m_hEvent);
  170. MYDBGASSERT(TRUE == m_fLocked);
  171. CMTRACE(TEXT("CConnectionTable::UnlockTable()"));
  172. HRESULT hrRet = S_OK;
  173. //
  174. // Validate our current state
  175. //
  176. if (FALSE == m_fLocked || NULL == m_hEvent)
  177. {
  178. return E_ACCESSDENIED;
  179. }
  180. //
  181. // Signal the open event, allowing access
  182. //
  183. if (SetEvent(m_hEvent))
  184. {
  185. m_fLocked = FALSE;
  186. }
  187. else
  188. {
  189. MYDBGASSERT(FALSE);
  190. hrRet = GetLastError();
  191. hrRet = HRESULT_FROM_WIN32(hrRet);
  192. }
  193. return hrRet;
  194. }
  195. //+----------------------------------------------------------------------------
  196. //
  197. // Function: CConnectionTable::FindEntry - pszEntry
  198. //
  199. // Synopsis: Determines the ID (index) of an entry in the table. Table should
  200. // be locked before making this call.
  201. //
  202. // Arguments: LPCTSTR pszEntry - Ptr to the name of the entry we are seeking.
  203. // LPINT piID - Ptr to buffer for ID (index) of connection
  204. //
  205. // Returns: HRESULT - Failure code, or S_OK if piID filled.
  206. //
  207. // History: nickball Created 2/2/98
  208. //
  209. //+----------------------------------------------------------------------------
  210. HRESULT CConnectionTable::FindEntry(LPCTSTR pszEntry, LPINT piID)
  211. {
  212. MYDBGASSERT(m_pConnTable);
  213. MYDBGASSERT(m_hMap);
  214. MYDBGASSERT(pszEntry);
  215. MYDBGASSERT(piID);
  216. MYDBGASSERT(TRUE == m_fLocked);
  217. CMTRACE1(TEXT("CConnectionTable::FindEntry(%s)"), pszEntry);
  218. if (FALSE == m_fLocked || NULL == m_pConnTable)
  219. {
  220. return E_ACCESSDENIED;
  221. }
  222. if (NULL == pszEntry || NULL == piID)
  223. {
  224. return E_POINTER;
  225. }
  226. if (0 == pszEntry[0])
  227. {
  228. return E_INVALIDARG;
  229. }
  230. //
  231. // Look for the entry
  232. //
  233. for (int i = 0; i < MAX_CM_CONNECTIONS; i++)
  234. {
  235. //
  236. // Name compare for a match
  237. //
  238. if (0 == lstrcmpU(pszEntry, m_pConnTable->Connections[i].szEntry))
  239. {
  240. MYDBGASSERT(m_pConnTable->Connections[i].dwUsage);
  241. MYDBGASSERT(m_pConnTable->Connections[i].CmState);
  242. *piID = i;
  243. return S_OK;
  244. }
  245. }
  246. return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  247. }
  248. //+----------------------------------------------------------------------------
  249. //
  250. // Function: CConnectionTable::FindEntry - hRasConn
  251. //
  252. // Synopsis: Determines the ID (index) of an entry in the table. Table should
  253. // be locked before making this call.
  254. //
  255. // Arguments: HRASCONN hRasConn - Tunnel or dial handle of the entry we are seeking.
  256. // LPINT piID - Ptr to buffer for ID (index) of connection
  257. //
  258. // Returns: HRESULT - Failure code, or S_OK if piID filled.
  259. //
  260. // History: nickball Created 2/2/98
  261. //
  262. //+----------------------------------------------------------------------------
  263. HRESULT CConnectionTable::FindEntry(HRASCONN hRasConn, LPINT piID)
  264. {
  265. MYDBGASSERT(m_pConnTable);
  266. MYDBGASSERT(m_hMap);
  267. MYDBGASSERT(hRasConn);
  268. MYDBGASSERT(piID);
  269. MYDBGASSERT(TRUE == m_fLocked);
  270. CMTRACE1(TEXT("CConnectionTable::FindEntry(%u)"), (DWORD_PTR) hRasConn);
  271. if (FALSE == m_fLocked || NULL == m_pConnTable)
  272. {
  273. return E_ACCESSDENIED;
  274. }
  275. if (NULL == piID)
  276. {
  277. return E_POINTER;
  278. }
  279. if (NULL == hRasConn)
  280. {
  281. return E_INVALIDARG;
  282. }
  283. //
  284. // Look for the entry
  285. //
  286. for (int i = 0; i < MAX_CM_CONNECTIONS; i++)
  287. {
  288. //
  289. // Compare for either handle for a match
  290. //
  291. if (hRasConn == m_pConnTable->Connections[i].hDial ||
  292. hRasConn == m_pConnTable->Connections[i].hTunnel)
  293. {
  294. MYDBGASSERT(m_pConnTable->Connections[i].dwUsage);
  295. MYDBGASSERT(m_pConnTable->Connections[i].CmState);
  296. *piID = i;
  297. return S_OK;
  298. }
  299. }
  300. return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  301. }
  302. //+----------------------------------------------------------------------------
  303. //
  304. // Function: CConnectionTable::FindUnused
  305. //
  306. // Synopsis: Determines the ID (index) of the first unused entry in the table.
  307. // Table should be locked before making this call.
  308. //
  309. // Arguments: LPINT piID - Ptr to buffer for ID (index) of connection
  310. //
  311. // Returns: HRESULT - Failure code, or S_OK if piID filled.
  312. //
  313. // History: nickball Created 2/2/98
  314. //
  315. //+----------------------------------------------------------------------------
  316. HRESULT CConnectionTable::FindUnused(LPINT piID)
  317. {
  318. MYDBGASSERT(m_pConnTable);
  319. MYDBGASSERT(m_hMap);
  320. MYDBGASSERT(piID);
  321. MYDBGASSERT(TRUE == m_fLocked);
  322. CMTRACE(TEXT("CConnectionTable::FindUnused()"));
  323. if (FALSE == m_fLocked || NULL == m_pConnTable)
  324. {
  325. return E_ACCESSDENIED;
  326. }
  327. if (NULL == piID)
  328. {
  329. return E_POINTER;
  330. }
  331. //
  332. // Look for an unused slot
  333. //
  334. for (int i = 0; i < MAX_CM_CONNECTIONS; i++)
  335. {
  336. if (0 == m_pConnTable->Connections[i].dwUsage)
  337. {
  338. MYDBGASSERT(CM_DISCONNECTED == m_pConnTable->Connections[i].CmState);
  339. *piID = i;
  340. return S_OK;
  341. }
  342. }
  343. return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  344. }
  345. //+----------------------------------------------------------------------------
  346. //
  347. // Function: Create
  348. //
  349. // Synopsis: Creates a new table. This function will fail if the table already exists.
  350. // The table should be released by calling Close.
  351. //
  352. // Arguments: None
  353. //
  354. // Returns: HRESULT - Failure code or S_OK
  355. //
  356. // History: nickball Created 2/2/98
  357. //
  358. //+----------------------------------------------------------------------------
  359. HRESULT CConnectionTable::Create()
  360. {
  361. MYDBGASSERT(NULL == m_hMap);
  362. MYDBGASSERT(NULL == m_pConnTable);
  363. MYDBGASSERT(FALSE == m_fLocked);
  364. CMTRACE(TEXT("CConnectionTable::Create()"));
  365. if (m_hMap || m_pConnTable)
  366. {
  367. return E_ACCESSDENIED;
  368. }
  369. SECURITY_ATTRIBUTES sa;
  370. PACL pAcl = NULL;
  371. // Initialize a default Security attributes, giving world permissions,
  372. // this is basically prevent Semaphores and other named objects from
  373. // being created because of default acls given by winlogon when perfmon
  374. // is being used remotely.
  375. sa.bInheritHandle = FALSE;
  376. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  377. sa.lpSecurityDescriptor = CmMalloc(sizeof(SECURITY_DESCRIPTOR));
  378. if ( !sa.lpSecurityDescriptor )
  379. {
  380. return E_OUTOFMEMORY;
  381. }
  382. if ( !InitializeSecurityDescriptor(sa.lpSecurityDescriptor,SECURITY_DESCRIPTOR_REVISION) )
  383. {
  384. return HRESULT_FROM_WIN32(GetLastError());
  385. }
  386. if (OS_NT)
  387. {
  388. if (FALSE == SetAclPerms(&pAcl))
  389. {
  390. return HRESULT_FROM_WIN32(GetLastError());
  391. }
  392. }
  393. if (FALSE == SetSecurityDescriptorDacl(sa.lpSecurityDescriptor, TRUE, pAcl, FALSE))
  394. {
  395. return HRESULT_FROM_WIN32(GetLastError());
  396. }
  397. //
  398. // Now use this 'sa' for the mapped file as well as the event (below)
  399. //
  400. if (OS_NT5)
  401. {
  402. m_hMap = CreateFileMappingU(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE,
  403. 0, sizeof(CM_CONNECTION_TABLE), CONN_TABLE_NAME_WIN2K_ABOVE);
  404. if (m_hMap)
  405. {
  406. CMTRACE1(TEXT("CreateFileMapping - create succeeded %s"), CONN_TABLE_NAME_WIN2K_ABOVE);
  407. }
  408. else
  409. {
  410. CMTRACE1(TEXT("CreateFileMapping - create failed %s"), CONN_TABLE_NAME_WIN2K_ABOVE);
  411. }
  412. }
  413. else
  414. {
  415. m_hMap = CreateFileMappingU(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE,
  416. 0, sizeof(CM_CONNECTION_TABLE), CONN_TABLE_NAME);
  417. if (m_hMap)
  418. {
  419. CMTRACE1(TEXT("CreateFileMapping - create succeeded %s"), CONN_TABLE_NAME);
  420. }
  421. else
  422. {
  423. CMTRACE1(TEXT("CreateFileMapping - create failed %s"), CONN_TABLE_NAME);
  424. }
  425. }
  426. DWORD dwRet = ERROR_SUCCESS;
  427. if (NULL == m_hMap)
  428. {
  429. dwRet = GetLastError();
  430. if (dwRet == ERROR_ALREADY_EXISTS)
  431. {
  432. if (m_hMap)
  433. {
  434. MYVERIFY(NULL != CloseHandle(m_hMap));
  435. m_hMap = NULL;
  436. }
  437. }
  438. else
  439. {
  440. CMTRACE1(TEXT("CreateFileMapping failed with error %d"), dwRet);
  441. MYDBGASSERT(FALSE);
  442. }
  443. }
  444. else
  445. {
  446. #if 0 // DBG
  447. DumpAclInfo(m_hMap);
  448. #endif
  449. //
  450. // File mapping created successfully, map a view of it
  451. //
  452. m_pConnTable = (LPCM_CONNECTION_TABLE) MapViewOfFile(m_hMap,
  453. FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
  454. if (NULL == m_pConnTable)
  455. {
  456. dwRet = GetLastError();
  457. MYVERIFY(NULL != CloseHandle(m_hMap));
  458. m_hMap = NULL;
  459. }
  460. else
  461. {
  462. //
  463. // Success, make sure mapping is empty becuase we are paranoid
  464. //
  465. ZeroMemory(m_pConnTable, sizeof(CM_CONNECTION_TABLE));
  466. //
  467. // Create the named event to be used for locking the file
  468. // Note: We use auto-reset.
  469. //
  470. if (OS_NT5)
  471. {
  472. m_hEvent = CreateEventU(&sa, FALSE, TRUE, CONN_TABLE_OPEN_WIN2K_ABOVE);
  473. if (m_hEvent)
  474. {
  475. CMTRACE1(TEXT("CreateEventU - succeeded - %s"), CONN_TABLE_OPEN_WIN2K_ABOVE);
  476. }
  477. else
  478. {
  479. CMTRACE1(TEXT("CreateEventU - failed - %s"), CONN_TABLE_OPEN_WIN2K_ABOVE);
  480. }
  481. }
  482. else
  483. {
  484. m_hEvent = CreateEventU(&sa, FALSE, TRUE, CONN_TABLE_OPEN);
  485. if (m_hEvent)
  486. {
  487. CMTRACE1(TEXT("CreateEventU - succeeded - %s"), CONN_TABLE_OPEN);
  488. }
  489. else
  490. {
  491. CMTRACE1(TEXT("CreateEventU - failed - %s"), CONN_TABLE_OPEN);
  492. }
  493. }
  494. if (NULL == m_hEvent)
  495. {
  496. MYDBGASSERT(FALSE);
  497. dwRet = GetLastError();
  498. m_hEvent = NULL;
  499. }
  500. }
  501. }
  502. CmFree(sa.lpSecurityDescriptor);
  503. if (pAcl)
  504. {
  505. LocalFree(pAcl);
  506. }
  507. return HRESULT_FROM_WIN32(dwRet);
  508. }
  509. //+----------------------------------------------------------------------------
  510. //
  511. // Function: CConnectionTable::Open
  512. //
  513. // Synopsis: Opens an existing table. This function will fail if no table exists.
  514. // The table should be released by calling Close.
  515. //
  516. // Arguments: None
  517. //
  518. // Returns: HRESULT - Failure code on S_OK
  519. //
  520. // History: nickball Created 2/2/98
  521. //
  522. //+----------------------------------------------------------------------------
  523. HRESULT CConnectionTable::Open()
  524. {
  525. MYDBGASSERT(NULL == m_hMap);
  526. MYDBGASSERT(NULL == m_pConnTable);
  527. MYDBGASSERT(FALSE == m_fLocked);
  528. CMTRACE(TEXT("CConnectionTable::Open()"));
  529. if (m_hMap || m_pConnTable)
  530. {
  531. CMTRACE(TEXT("CConnectionTable::Open() - E_ACCESSDENIED"));
  532. return E_ACCESSDENIED;
  533. }
  534. LRESULT lRet = ERROR_SUCCESS;
  535. //
  536. // Open the file mapping
  537. //
  538. if (OS_NT5)
  539. {
  540. m_hMap = OpenFileMappingU(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, CONN_TABLE_NAME_WIN2K_ABOVE);
  541. }
  542. else
  543. {
  544. m_hMap = OpenFileMappingU(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, CONN_TABLE_NAME);
  545. }
  546. if (NULL == m_hMap)
  547. {
  548. lRet = GetLastError();
  549. CMTRACE1(TEXT("CConnectionTable::Open() - OpenFileMappingU fails. GLE = 0x%x"), lRet);
  550. }
  551. else
  552. {
  553. //
  554. // File mapping opened successfully, map a view of it.
  555. //
  556. m_pConnTable = (LPCM_CONNECTION_TABLE) MapViewOfFile(m_hMap,
  557. FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
  558. MYDBGASSERT(m_pConnTable);
  559. if (NULL == m_pConnTable)
  560. {
  561. MYVERIFY(NULL != CloseHandle(m_hMap));
  562. m_hMap = NULL;
  563. lRet = GetLastError();
  564. CMTRACE1(TEXT("CConnectionTable::Open() - MapViewOfFile fails. GLE = 0x%x"), lRet);
  565. }
  566. else
  567. {
  568. //
  569. // Open the named event used for locking the file
  570. //
  571. if (OS_NT5)
  572. {
  573. m_hEvent = OpenEventU(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,
  574. NULL, CONN_TABLE_OPEN_WIN2K_ABOVE);
  575. }
  576. else
  577. {
  578. m_hEvent = OpenEventU(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,
  579. NULL, CONN_TABLE_OPEN);
  580. }
  581. if (NULL == m_hEvent)
  582. {
  583. MYDBGASSERT(FALSE);
  584. lRet = GetLastError();
  585. CMTRACE1(TEXT("CConnectionTable::Open() - OpenEventU fails. GLE = 0x%x"), lRet);
  586. }
  587. }
  588. }
  589. return HRESULT_FROM_WIN32(lRet);
  590. }
  591. //+----------------------------------------------------------------------------
  592. //
  593. // Function: CConnectionTable::Close
  594. //
  595. // Synopsis: Closes an opened table. This function will fail if the table is
  596. // not open.
  597. //
  598. // Arguments: None
  599. //
  600. // Returns: HRESULT - Failure code or S_OK
  601. //
  602. // History: nickball Created 2/2/98
  603. //
  604. //+----------------------------------------------------------------------------
  605. HRESULT CConnectionTable::Close()
  606. {
  607. MYDBGASSERT(m_pConnTable);
  608. MYDBGASSERT(m_hMap);
  609. MYDBGASSERT(FALSE == m_fLocked);
  610. CMTRACE(TEXT("CConnectionTable::Close()"));
  611. if (m_pConnTable)
  612. {
  613. MYVERIFY(NULL != UnmapViewOfFile(m_pConnTable));
  614. m_pConnTable = NULL;
  615. }
  616. if (m_hMap)
  617. {
  618. MYVERIFY(NULL != CloseHandle(m_hMap));
  619. m_hMap = NULL;
  620. }
  621. if (m_hEvent)
  622. {
  623. MYVERIFY(NULL != CloseHandle(m_hEvent));
  624. m_hEvent = NULL;
  625. }
  626. return S_OK;
  627. }
  628. //+----------------------------------------------------------------------------
  629. //
  630. // Function: CConnectionTable::AddEntry
  631. //
  632. // Synopsis: Creates a new entry in the table with the specified name. Adding
  633. // an entry implies that the connection is being attempted, so the
  634. // connection state is set to CM_CONNECTING. If an entry for the
  635. // connection already exists, the usage count is incremented.
  636. //
  637. // Arguments: LPCTSTR pszEntry - The name of connection for which we're creating an entry.
  638. // BOOL fAllUser - The All User attribute of the profile
  639. //
  640. // Returns: HRESULT - Failure code or S_OK
  641. //
  642. // History: nickball Created 2/2/98
  643. //
  644. //+----------------------------------------------------------------------------
  645. HRESULT CConnectionTable::AddEntry(LPCTSTR pszEntry, BOOL fAllUser)
  646. {
  647. MYDBGASSERT(m_pConnTable);
  648. MYDBGASSERT(m_hMap);
  649. MYDBGASSERT(pszEntry);
  650. CMTRACE1(TEXT("CConnectionTable::AddEntry(%s)"), pszEntry);
  651. if (NULL == pszEntry)
  652. {
  653. return E_POINTER;
  654. }
  655. if (0 == pszEntry[0])
  656. {
  657. return E_INVALIDARG;
  658. }
  659. if (NULL == m_pConnTable)
  660. {
  661. return E_ACCESSDENIED;
  662. }
  663. HRESULT hrRet = LockTable();
  664. if (FAILED(hrRet))
  665. {
  666. return hrRet;
  667. }
  668. //
  669. // See if we already have an entry by this name
  670. //
  671. int iID = -1;
  672. hrRet = FindEntry(pszEntry, &iID);
  673. if (SUCCEEDED(hrRet))
  674. {
  675. //
  676. // We do, bump the usage count.
  677. //
  678. MYDBGASSERT(iID >= 0 && iID < MAX_CM_CONNECTIONS);
  679. //
  680. // Don't bump ref count when reconnecting the same connection.
  681. //
  682. if (m_pConnTable->Connections[iID].CmState != CM_RECONNECTPROMPT)
  683. {
  684. m_pConnTable->Connections[iID].dwUsage += 1;
  685. }
  686. //
  687. // Unless this entry is already connected, make sure
  688. // its now in the connecting state. This allows us
  689. // to preserve the usage count across prompt reconnect
  690. // events.
  691. //
  692. if (m_pConnTable->Connections[iID].CmState != CM_CONNECTED)
  693. {
  694. m_pConnTable->Connections[iID].CmState = CM_CONNECTING;
  695. }
  696. MYDBGASSERT(m_pConnTable->Connections[iID].dwUsage < 1000); // Sanity check
  697. }
  698. else
  699. {
  700. if (HRESULT_CODE(hrRet) == ERROR_NOT_FOUND)
  701. {
  702. //
  703. // Its a new entry, find the first unused slot
  704. //
  705. hrRet = FindUnused(&iID);
  706. MYDBGASSERT(SUCCEEDED(hrRet));
  707. if (SUCCEEDED(hrRet))
  708. {
  709. MYDBGASSERT(iID >= 0 && iID < MAX_CM_CONNECTIONS);
  710. ZeroMemory(&m_pConnTable->Connections[iID], sizeof(CM_CONNECTION));
  711. //
  712. // Set usage count, state and name
  713. //
  714. m_pConnTable->Connections[iID].dwUsage = 1;
  715. m_pConnTable->Connections[iID].CmState = CM_CONNECTING;
  716. lstrcpyU(m_pConnTable->Connections[iID].szEntry, pszEntry);
  717. m_pConnTable->Connections[iID].fAllUser = fAllUser;
  718. }
  719. }
  720. }
  721. MYVERIFY(SUCCEEDED(UnlockTable()));
  722. return hrRet;
  723. }
  724. //+----------------------------------------------------------------------------
  725. //
  726. // Function: CConnectionTable::RemoveEntry
  727. //
  728. // Synopsis: Decrements the usage count for the specified connection. If the
  729. // usage count falls to 0 the entire entry is cleared.
  730. //
  731. // Arguments: LPCTSTR pszEntry - The name of the entry to be removed
  732. //
  733. // Returns: HRESULT - Failure code or S_OK
  734. //
  735. // Note: If the entry does not exists the request fails.
  736. //
  737. // History: nickball Created 2/2/98
  738. //
  739. //+----------------------------------------------------------------------------
  740. HRESULT CConnectionTable::RemoveEntry(LPCTSTR pszEntry)
  741. {
  742. MYDBGASSERT(m_pConnTable);
  743. MYDBGASSERT(m_hMap);
  744. MYDBGASSERT(pszEntry);
  745. CMTRACE1(TEXT("CConnectionTable::RemoveEntry(%s)"), pszEntry);
  746. if (NULL == pszEntry)
  747. {
  748. return E_POINTER;
  749. }
  750. if (0 == pszEntry[0])
  751. {
  752. return E_INVALIDARG;
  753. }
  754. if (NULL == m_pConnTable)
  755. {
  756. return E_ACCESSDENIED;
  757. }
  758. //
  759. // Lock the table and locate the entry
  760. //
  761. HRESULT hrRet = LockTable();
  762. if (FAILED(hrRet))
  763. {
  764. return hrRet;
  765. }
  766. int iID = -1;
  767. hrRet = FindEntry(pszEntry, &iID);
  768. if (SUCCEEDED(hrRet))
  769. {
  770. MYDBGASSERT(iID >= 0 && iID < MAX_CM_CONNECTIONS);
  771. if (m_pConnTable->Connections[iID].dwUsage == 1)
  772. {
  773. ZeroMemory(&m_pConnTable->Connections[iID], sizeof(CM_CONNECTION));
  774. }
  775. else
  776. {
  777. m_pConnTable->Connections[iID].dwUsage -= 1;
  778. MYDBGASSERT(m_pConnTable->Connections[iID].dwUsage != 0xFFFFFFFF);
  779. }
  780. }
  781. MYVERIFY(SUCCEEDED(UnlockTable()));
  782. return hrRet;
  783. }
  784. //+----------------------------------------------------------------------------
  785. //
  786. // Function: CConnectionTable::GetMonitorWnd
  787. //
  788. // Synopsis: Simple accessor to retrieve the hwnd of the CM Connection
  789. // Monitor from the table.
  790. //
  791. // Arguments: phWnd - Ptr to buffer to receive hWnd
  792. //
  793. // Returns: Failure code or S_OK
  794. //
  795. // History: nickball Created 2/2/98
  796. //
  797. //+----------------------------------------------------------------------------
  798. HRESULT CConnectionTable::GetMonitorWnd(HWND *phWnd)
  799. {
  800. MYDBGASSERT(m_pConnTable);
  801. MYDBGASSERT(m_hMap);
  802. CMTRACE(TEXT("CConnectionTable::GetMonitorWnd()"));
  803. if (NULL == m_pConnTable)
  804. {
  805. return E_ACCESSDENIED;
  806. }
  807. if (NULL == phWnd)
  808. {
  809. return E_POINTER;
  810. }
  811. //
  812. // Lock the table and retrieve the HWND
  813. //
  814. HRESULT hrRet = LockTable();
  815. if (FAILED(hrRet))
  816. {
  817. return hrRet;
  818. }
  819. *phWnd = m_pConnTable->hwndCmMon;
  820. MYVERIFY(SUCCEEDED(UnlockTable()));
  821. return S_OK;
  822. }
  823. //+----------------------------------------------------------------------------
  824. //
  825. // Function: CConnectionTable::SetMonitorWnd
  826. //
  827. // Synopsis: Simple assignment method for setting the CMMON HWND in the table
  828. // .
  829. // Arguments: HWND hwndMonitor - The HWND of CMMON
  830. //
  831. // Returns: HRESULT - Failure code or S_OK
  832. //
  833. // Note: hwndMonitor CAN be NULL. It is possible CMMON is unloaded, but
  834. // the table statys in memory
  835. // History: nickball Created 2/2/98
  836. // fengsun 2/20/98 change to allow NULL phwndMonitor
  837. //
  838. //+----------------------------------------------------------------------------
  839. HRESULT CConnectionTable::SetMonitorWnd(HWND hwndMonitor)
  840. {
  841. MYDBGASSERT(m_pConnTable);
  842. MYDBGASSERT(m_hMap);
  843. CMTRACE(TEXT("CConnectionTable::SetMonitorWnd()"));
  844. if (NULL == m_pConnTable)
  845. {
  846. return E_ACCESSDENIED;
  847. }
  848. //
  849. // Lock the table and set the HWND
  850. //
  851. HRESULT hrRet = LockTable();
  852. if (FAILED(hrRet))
  853. {
  854. return hrRet;
  855. }
  856. m_pConnTable->hwndCmMon = hwndMonitor;
  857. MYVERIFY(SUCCEEDED(UnlockTable()));
  858. return S_OK;
  859. }
  860. //+----------------------------------------------------------------------------
  861. //
  862. // Function: CConnectionTable::GetEntry - pszEntry
  863. //
  864. // Synopsis: Retrieves a copy the data for the specified connection based on
  865. // the entry name provided.
  866. //
  867. // Arguments: LPCTSTR pszEntry - The name of the connection
  868. // LPCM_CONNECTION pConnection - Ptr to a CM_CONNECTION sturct to be filled
  869. //
  870. // Returns: HRESULT - Failure Code or S_OK.
  871. //
  872. // Note: A NULL ptr may be passed for pConnection, if the existence of the
  873. // entry is the only information required.
  874. //
  875. // History: nickball Created 2/2/98
  876. //
  877. //+----------------------------------------------------------------------------
  878. HRESULT CConnectionTable::GetEntry(LPCTSTR pszEntry,
  879. LPCM_CONNECTION pConnection)
  880. {
  881. MYDBGASSERT(m_pConnTable);
  882. MYDBGASSERT(m_hMap);
  883. MYDBGASSERT(pszEntry);
  884. CMTRACE1(TEXT("CConnectionTable::GetEntry(%s)"), pszEntry);
  885. if (NULL == m_pConnTable)
  886. {
  887. return E_ACCESSDENIED;
  888. }
  889. if (NULL == pszEntry)
  890. {
  891. return E_POINTER;
  892. }
  893. if (0 == pszEntry[0])
  894. {
  895. return E_INVALIDARG;
  896. }
  897. //
  898. // Lock the table and retrieve the entry
  899. //
  900. HRESULT hrRet = LockTable();
  901. if (FAILED(hrRet))
  902. {
  903. return hrRet;
  904. }
  905. int iID = -1;
  906. hrRet = FindEntry(pszEntry, &iID);
  907. if (SUCCEEDED(hrRet))
  908. {
  909. MYDBGASSERT(iID >= 0 && iID < MAX_CM_CONNECTIONS);
  910. //
  911. // If a buffer was given fill it.
  912. //
  913. if (pConnection)
  914. {
  915. memcpy(pConnection, &m_pConnTable->Connections[iID], sizeof(CM_CONNECTION));
  916. }
  917. }
  918. MYVERIFY(SUCCEEDED(UnlockTable()));
  919. return hrRet;
  920. }
  921. //+----------------------------------------------------------------------------
  922. //
  923. // Function: CConnectionTable::GetEntry - hRasConn
  924. //
  925. // Synopsis: Retrieves a copy the data for the specified connection based on the
  926. // Ras handle provided
  927. //
  928. // Arguments: HRASCONN hRasConn - Either the tunnel or dial handle of the connection
  929. // LPCM_CONNECTION pConnection - Ptr to a CM_CONNECTION sturct to be filled
  930. //
  931. // Returns: HRESULT - Failure Code or S_OK.
  932. //
  933. // Note: A NULL ptr may be passed for pConnection, if the existence of the
  934. // entry is the only information required.
  935. //
  936. // History: nickball Created 2/2/98
  937. //
  938. //+----------------------------------------------------------------------------
  939. HRESULT CConnectionTable::GetEntry(HRASCONN hRasConn,
  940. LPCM_CONNECTION pConnection)
  941. {
  942. MYDBGASSERT(m_pConnTable);
  943. MYDBGASSERT(m_hMap);
  944. MYDBGASSERT(hRasConn);
  945. CMTRACE1(TEXT("CConnectionTable::GetEntry(%u)"), (DWORD_PTR) hRasConn);
  946. if (NULL == m_pConnTable)
  947. {
  948. return E_ACCESSDENIED;
  949. }
  950. if (NULL == hRasConn)
  951. {
  952. return E_INVALIDARG;
  953. }
  954. //
  955. // Lock the table and retrieve the entry
  956. //
  957. HRESULT hrRet = LockTable();
  958. if (FAILED(hrRet))
  959. {
  960. return hrRet;
  961. }
  962. int iID = -1;
  963. hrRet = FindEntry(hRasConn, &iID);
  964. if (SUCCEEDED(hrRet))
  965. {
  966. MYDBGASSERT(iID >= 0 && iID < MAX_CM_CONNECTIONS);
  967. //
  968. // If a buffer was given fill it.
  969. //
  970. if (pConnection)
  971. {
  972. memcpy(pConnection, &m_pConnTable->Connections[iID], sizeof(CM_CONNECTION));
  973. }
  974. }
  975. MYVERIFY(SUCCEEDED(UnlockTable()));
  976. return hrRet;
  977. }
  978. //+----------------------------------------------------------------------------
  979. //
  980. // Function: CConnectionTable::SetConnected
  981. //
  982. // Synopsis: Sets the connection to CM_CONNECTED indicating that a connection
  983. // has been established. The caller must provide either the hDial or
  984. // the hTunnel parameter or both in order for the function to succeed.
  985. //
  986. // Arguments: LPCTSTR pszEntry - The name of the connection.
  987. // HRASCONN hDial - A Dial-up connection handle.
  988. // HRASCONN hTunnel - A tunnel connection handle.
  989. //
  990. // Returns: HRESULT - Failure code or S_OK.
  991. //
  992. // History: nickball Created 2/2/98
  993. //
  994. //+----------------------------------------------------------------------------
  995. HRESULT CConnectionTable::SetConnected(LPCTSTR pszEntry,
  996. HRASCONN hDial,
  997. HRASCONN hTunnel)
  998. {
  999. MYDBGASSERT(m_pConnTable);
  1000. MYDBGASSERT(m_hMap);
  1001. MYDBGASSERT(pszEntry);
  1002. CMTRACE1(TEXT("CConnectionTable::SetConnected(%s)"), pszEntry);
  1003. if (NULL == m_pConnTable)
  1004. {
  1005. return E_ACCESSDENIED;
  1006. }
  1007. if (NULL == pszEntry)
  1008. {
  1009. return E_POINTER;
  1010. }
  1011. if (0 == pszEntry[0] || (NULL == hDial && NULL == hTunnel))
  1012. {
  1013. return E_INVALIDARG;
  1014. }
  1015. //
  1016. // Lock the table and retrieve the entry
  1017. //
  1018. HRESULT hrRet = LockTable();
  1019. if (FAILED(hrRet))
  1020. {
  1021. return hrRet;
  1022. }
  1023. int iID = -1;
  1024. hrRet = FindEntry(pszEntry, &iID);
  1025. MYDBGASSERT(SUCCEEDED(hrRet));
  1026. if (SUCCEEDED(hrRet))
  1027. {
  1028. //
  1029. // Found, set the state and Ras handles
  1030. //
  1031. MYDBGASSERT(iID >= 0 && iID < MAX_CM_CONNECTIONS);
  1032. MYDBGASSERT(m_pConnTable->Connections[iID].CmState != CM_CONNECTED);
  1033. m_pConnTable->Connections[iID].CmState = CM_CONNECTED;
  1034. m_pConnTable->Connections[iID].hDial = hDial;
  1035. m_pConnTable->Connections[iID].hTunnel = hTunnel;
  1036. }
  1037. MYVERIFY(SUCCEEDED(UnlockTable()));
  1038. return hrRet;
  1039. }
  1040. //+----------------------------------------------------------------------------
  1041. //
  1042. // Function: CConnectionTable::SetDisconnecting
  1043. //
  1044. // Synopsis: Set the state of the connection to CM_DISCONNECTING
  1045. //
  1046. // Arguments: LPCTSTR pszEntry - The name of the connection to be set.
  1047. //
  1048. // Returns: HRESULT - Failure code or S_OK
  1049. //
  1050. // History: nickball Created 2/2/98
  1051. //
  1052. //+----------------------------------------------------------------------------
  1053. HRESULT CConnectionTable::SetDisconnecting(LPCTSTR pszEntry)
  1054. {
  1055. MYDBGASSERT(m_pConnTable);
  1056. MYDBGASSERT(m_hMap);
  1057. MYDBGASSERT(pszEntry);
  1058. CMTRACE1(TEXT("CConnectionTable::Disconnecting(%s)"), pszEntry);
  1059. if (NULL == m_pConnTable)
  1060. {
  1061. return E_ACCESSDENIED;
  1062. }
  1063. if (NULL == pszEntry)
  1064. {
  1065. return E_POINTER;
  1066. }
  1067. if (0 == pszEntry[0])
  1068. {
  1069. return E_INVALIDARG;
  1070. }
  1071. //
  1072. // Lock the table and retrieve the entry
  1073. //
  1074. HRESULT hrRet = LockTable();
  1075. if (FAILED(hrRet))
  1076. {
  1077. return hrRet;
  1078. }
  1079. int iID = -1;
  1080. hrRet = FindEntry(pszEntry, &iID);
  1081. //MYDBGASSERT(SUCCEEDED(hrRet));
  1082. if (SUCCEEDED(hrRet))
  1083. {
  1084. //
  1085. // Found, set the state
  1086. //
  1087. MYDBGASSERT(iID >= 0 && iID < MAX_CM_CONNECTIONS);
  1088. m_pConnTable->Connections[iID].CmState = CM_DISCONNECTING;
  1089. }
  1090. MYVERIFY(SUCCEEDED(UnlockTable()));
  1091. return hrRet;
  1092. }
  1093. //+----------------------------------------------------------------------------
  1094. //
  1095. // Function: SetPrompting
  1096. //
  1097. // Synopsis: Set the state of the connection to CM_RECONNECTPROMPT
  1098. //
  1099. // Arguments: LPCTSTR pszEntry - The name of the connection to be set.
  1100. //
  1101. // Returns: HRESULT - Failure code or S_OK
  1102. //
  1103. // History: nickball Created 2/2/98
  1104. //
  1105. //+----------------------------------------------------------------------------
  1106. HRESULT CConnectionTable::SetPrompting(LPCTSTR pszEntry)
  1107. {
  1108. MYDBGASSERT(m_pConnTable);
  1109. MYDBGASSERT(m_hMap);
  1110. MYDBGASSERT(pszEntry);
  1111. CMTRACE1(TEXT("CConnectionTable::SetPrompting(%s)"), pszEntry);
  1112. if (NULL == m_pConnTable)
  1113. {
  1114. return E_ACCESSDENIED;
  1115. }
  1116. if (NULL == pszEntry)
  1117. {
  1118. return E_POINTER;
  1119. }
  1120. if (0 == pszEntry[0])
  1121. {
  1122. return E_INVALIDARG;
  1123. }
  1124. //
  1125. // Lock the table and retrieve the entry
  1126. //
  1127. HRESULT hrRet = LockTable();
  1128. if (FAILED(hrRet))
  1129. {
  1130. return hrRet;
  1131. }
  1132. int iID = -1;
  1133. hrRet = FindEntry(pszEntry, &iID);
  1134. //MYDBGASSERT(SUCCEEDED(hrRet));
  1135. if (SUCCEEDED(hrRet))
  1136. {
  1137. //
  1138. // Found, set the state
  1139. //
  1140. MYDBGASSERT(iID >= 0 && iID < MAX_CM_CONNECTIONS);
  1141. m_pConnTable->Connections[iID].CmState = CM_RECONNECTPROMPT;
  1142. }
  1143. MYVERIFY(SUCCEEDED(UnlockTable()));
  1144. return hrRet;
  1145. }
  1146. //+----------------------------------------------------------------------------
  1147. //
  1148. // Function: CConnectionTable::ClearEntry
  1149. //
  1150. // Synopsis: Clears the specified entry regardless of the usage count.
  1151. //
  1152. // Arguments: LPCTSTR pszEntry - The name of the entry to be cleared.
  1153. //
  1154. // Returns: HRESULT - Failure code or S_OK
  1155. //
  1156. // History: nickball Created 2/2/98
  1157. //
  1158. //+----------------------------------------------------------------------------
  1159. HRESULT CConnectionTable::ClearEntry(LPCTSTR pszEntry)
  1160. {
  1161. MYDBGASSERT(m_pConnTable);
  1162. MYDBGASSERT(m_hMap);
  1163. MYDBGASSERT(pszEntry);
  1164. CMTRACE1(TEXT("CConnectionTable::ClearEntry(%s)"), pszEntry);
  1165. if (NULL == m_pConnTable)
  1166. {
  1167. return E_ACCESSDENIED;
  1168. }
  1169. if (NULL == pszEntry)
  1170. {
  1171. return E_POINTER;
  1172. }
  1173. if (0 == pszEntry[0])
  1174. {
  1175. return E_INVALIDARG;
  1176. }
  1177. //
  1178. // Lock the table and retrieve the entry
  1179. //
  1180. HRESULT hrRet = LockTable();
  1181. if (FAILED(hrRet))
  1182. {
  1183. return hrRet;
  1184. }
  1185. int iID = -1;
  1186. hrRet = FindEntry(pszEntry, &iID);
  1187. if (SUCCEEDED(hrRet))
  1188. {
  1189. //
  1190. // Found, clear it
  1191. //
  1192. MYDBGASSERT(iID >= 0 && iID < MAX_CM_CONNECTIONS);
  1193. ZeroMemory(&m_pConnTable->Connections[iID], sizeof(CM_CONNECTION));
  1194. }
  1195. MYVERIFY(SUCCEEDED(UnlockTable()));
  1196. return hrRet;
  1197. }