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.

778 lines
21 KiB

  1. //Copyright (c) Microsoft Corporation. All rights reserved.
  2. // EnCliSvr.cpp : Implementation of CTlntSvrApp and DLL registration.
  3. #include <stdafx.h>
  4. #include <oleauto.h>
  5. #include <Debug.h>
  6. #include <KillApps.h>
  7. #include <TlntSvr.h>
  8. #include <TelntSrv.h>
  9. #include <EnumData.h>
  10. #include <EnCliSvr.h>
  11. #include <TlntUtils.h>
  12. #include <Ipc.h>
  13. #include <w4warn.h>
  14. // Don't even think about changing the two strings -- BaskarK, they NEED to be in sync with tnadmin\tnadmutl.cpp
  15. // the separators used to identify various portions of a session as well as session begin/end
  16. WCHAR *session_separator = L",";
  17. WCHAR *session_data_separator = L"\\";
  18. boolean called_by_an_admin()
  19. {
  20. static PSID administrators = NULL;
  21. boolean an_admin = false;
  22. HANDLE token;
  23. if (NULL == administrators)
  24. {
  25. SID_IDENTIFIER_AUTHORITY local_system_authority = SECURITY_NT_AUTHORITY;
  26. //Build administrators alias sid
  27. if (! AllocateAndInitializeSid(
  28. &local_system_authority,
  29. 2, /* there are only two sub-authorities */
  30. SECURITY_BUILTIN_DOMAIN_RID,
  31. DOMAIN_ALIAS_RID_ADMINS,
  32. 0,0,0,0,0,0, /* Don't care about the rest */
  33. &administrators
  34. ))
  35. {
  36. return false;
  37. }
  38. }
  39. if (OpenThreadToken(
  40. GetCurrentThread(),
  41. TOKEN_QUERY | MAXIMUM_ALLOWED,
  42. TRUE,
  43. & token
  44. ))
  45. {
  46. TOKEN_GROUPS *tg = NULL;
  47. DWORD required = 2048; // 2K should be good enough for starters
  48. DWORD error = NO_ERROR;
  49. for (;;)
  50. {
  51. tg = (TOKEN_GROUPS *) new BYTE[required];
  52. if (! tg)
  53. {
  54. break;
  55. }
  56. if (GetTokenInformation(token, TokenGroups, (LPVOID) tg, required, & required))
  57. {
  58. error = NO_ERROR;
  59. break;
  60. }
  61. else
  62. {
  63. error = GetLastError();
  64. if (ERROR_INSUFFICIENT_BUFFER != error)
  65. {
  66. break;
  67. }
  68. }
  69. delete [] tg;
  70. }
  71. if (tg && (NO_ERROR == error))
  72. {
  73. DWORD x;
  74. for (x = 0; x < tg->GroupCount; x ++)
  75. {
  76. if (EqualSid(administrators, & (tg->Groups[x].Sid)) &&
  77. (tg->Groups[x].Attributes & SE_GROUP_ENABLED) &&
  78. (!(tg->Groups[x].Attributes & SE_GROUP_USE_FOR_DENY_ONLY))
  79. )
  80. {
  81. an_admin = true;
  82. break;
  83. }
  84. }
  85. }
  86. if (tg)
  87. {
  88. delete [] tg;
  89. }
  90. CloseHandle(token);
  91. }
  92. return an_admin;
  93. }
  94. void AddSeparator( LPWSTR *pszSessionData, LPWSTR szString, INT *iSizeOfBuffer )
  95. {
  96. _chASSERT( pszSessionData );
  97. _chASSERT( szString );
  98. _chASSERT( iSizeOfBuffer );
  99. if( !szString )
  100. {
  101. szString = L"";
  102. }
  103. _chVERIFY2( *iSizeOfBuffer >= ( INT ) ( wcslen( szString ) + 1 ) );
  104. DWORD dwLen = 0;
  105. if( *iSizeOfBuffer >= ( INT )( wcslen( szString ) + 1 ) )
  106. {
  107. dwLen = wcslen( szString );
  108. wcsncpy( *pszSessionData, szString, dwLen );
  109. *pszSessionData += ( dwLen );
  110. *iSizeOfBuffer -= ( dwLen );
  111. }
  112. return;
  113. }
  114. void WCopyInt( LPWSTR *pszSessionData, INT iNum, INT *iSizeOfBuffer )
  115. {
  116. _chASSERT( pszSessionData );
  117. _chASSERT( iSizeOfBuffer );
  118. _chVERIFY2( *iSizeOfBuffer >= MAX_STRING_FROM_itow );
  119. _itow( iNum, *pszSessionData, 10 );
  120. *iSizeOfBuffer -= wcslen( *pszSessionData );
  121. *pszSessionData += wcslen( *pszSessionData );
  122. AddSeparator( pszSessionData, session_data_separator, iSizeOfBuffer );
  123. }
  124. void WCopyMbcsString( LPWSTR *pszSessionData, CHAR *szString, INT *iSizeOfBuffer )
  125. {
  126. _chASSERT( pszSessionData );
  127. _chASSERT( szString );
  128. _chASSERT( iSizeOfBuffer );
  129. if( !szString )
  130. {
  131. szString = "";
  132. }
  133. _chVERIFY2( *iSizeOfBuffer >= ( INT )( strlen( szString ) + 1 ) );
  134. DWORD dwLen = 0;
  135. dwLen = MultiByteToWideChar( GetOEMCP(), 0, szString, -1, *pszSessionData, *iSizeOfBuffer );
  136. if( dwLen > 0 )
  137. {
  138. *pszSessionData += ( dwLen - 1 );
  139. *iSizeOfBuffer -= ( dwLen - 1 );
  140. AddSeparator( pszSessionData, session_data_separator, iSizeOfBuffer );
  141. }
  142. return;
  143. }
  144. void WCopyUnicodeString( LPWSTR *pszSessionData, LPWSTR szString, INT *iSizeOfBuffer )
  145. {
  146. _chASSERT( pszSessionData );
  147. _chASSERT( szString );
  148. _chASSERT( iSizeOfBuffer );
  149. if( !szString )
  150. {
  151. szString = L"";
  152. }
  153. _chVERIFY2( *iSizeOfBuffer >= ( INT ) ( wcslen( szString ) + 1 ) );
  154. DWORD dwLen = 0;
  155. if( *iSizeOfBuffer >= ( INT )( wcslen( szString ) + 1 ) )
  156. {
  157. dwLen = wcslen( szString );
  158. wcsncpy( *pszSessionData, szString, dwLen );
  159. *pszSessionData += dwLen;
  160. *iSizeOfBuffer -= dwLen;
  161. AddSeparator( pszSessionData, session_data_separator, iSizeOfBuffer );
  162. }
  163. return;
  164. }
  165. /////////////////////////////////////////////////////////////////////////////
  166. //
  167. extern CTelnetService* g_pTelnetService;
  168. //Global variables used to pass data b/n GetSessionProcesses and EnumClients
  169. CEnumData* g_pEnumData = NULL;
  170. LONG lUniqueSessionNumber;
  171. //Global variables used to pass data b/n GetTelnetSessionProcesses and GetTelnetSessions
  172. BSTR g_szSessionData = NULL;
  173. INT g_iSizeOfBuffer = 0;
  174. #ifdef ENUM_PROCESSES
  175. void
  176. GetTelnetSessionProcesses
  177. (
  178. HANDLE hProc,
  179. DWORD dwProcessId,
  180. LPWSTR lpszProcessName
  181. )
  182. {
  183. WCopyInt( &g_szSessionData, dwProcessId, &g_iSizeOfBuffer );
  184. WCopyUnicodeString( &g_szSessionData, lpszProcessName, &g_iSizeOfBuffer );
  185. }
  186. #endif
  187. //memory is allocated by this method ( GetTelnetSessions ) and to be freed by the client( telnet admin ).
  188. //It returns data about each session as a BSTR formatted as below.
  189. //Each feild is separated by wide char ':'. Each session is separated by ','
  190. //First entry is count of sessions and only this feild is separated by comma from the rest. This is followed by,
  191. //dwPid,szDomain,szUserName,szRemoteMachine, wYear, wMonth, wDayOfWeek, wDay,
  192. //wHour, wMinute, wSecond, wMilliseconds; and pairs of process id, process name.
  193. STDMETHODIMP
  194. CEnumTelnetClientsSvr::GetTelnetSessions
  195. (
  196. BSTR *pszRetVal
  197. )
  198. {
  199. DWORD dwCount = 0;
  200. CClientInfo *pClientInfo = NULL;
  201. DWORD dwStatus = S_OK;
  202. DWORD dwLen = 0;
  203. INT iBytesToBeAllocated = 0;
  204. bool bIsDomainCopied = false;
  205. // if (! called_by_an_admin())
  206. // {
  207. // return S_FALSE;
  208. // }
  209. // DebugBreak();
  210. if( g_pTelnetService == NULL || pszRetVal == NULL )
  211. {
  212. return S_FALSE;
  213. }
  214. if( WaitForSingleObject( g_pTelnetService->m_hSyncAllClientObjAccess,
  215. WAIT_TIME ) != WAIT_OBJECT_0 )
  216. {
  217. return S_FALSE;
  218. }
  219. DWORD dwSessionsWithData = 0;
  220. DWORD dwSaveCount = 0;
  221. dwCount = client_list_Count();
  222. dwSaveCount = dwCount;
  223. while( dwCount > 0 )
  224. {
  225. pClientInfo = (CClientInfo *)client_list_Get( --dwCount );
  226. if( pClientInfo && pClientInfo->szUserName )
  227. {
  228. //Only if szUserName is non null, the object has session data.
  229. //Otherwise, still in the process of getting that info
  230. dwSessionsWithData++;
  231. }
  232. }
  233. //Restore the count
  234. dwCount = dwSaveCount;
  235. g_iSizeOfBuffer = MAX_STRING_FROM_itow;
  236. if( dwSessionsWithData > 0 )
  237. {
  238. g_iSizeOfBuffer += dwSessionsWithData * SIZE_OF_ONE_SESSION_DATA;
  239. }
  240. iBytesToBeAllocated = g_iSizeOfBuffer * sizeof( WCHAR );
  241. *pszRetVal = SysAllocStringLen( NULL, iBytesToBeAllocated );
  242. g_szSessionData = *pszRetVal;
  243. if( g_szSessionData == NULL )
  244. {
  245. dwStatus = ( DWORD )S_FALSE;
  246. goto ExitOnError;
  247. }
  248. WCopyInt( &g_szSessionData, dwSessionsWithData, &g_iSizeOfBuffer );
  249. //Remove wide null char from g_szSessionData
  250. g_iSizeOfBuffer += 1;
  251. g_szSessionData -= 1;
  252. AddSeparator( &g_szSessionData, session_separator, &g_iSizeOfBuffer );
  253. while( dwCount > 0 )
  254. {
  255. pClientInfo = (CClientInfo *)client_list_Get( --dwCount );
  256. if( pClientInfo && pClientInfo->szUserName )
  257. {
  258. WCopyInt( &g_szSessionData, pClientInfo->dwPid, &g_iSizeOfBuffer );
  259. bIsDomainCopied = false;
  260. if( strcmp( pClientInfo->szDomain, "." ) == 0 )
  261. {
  262. if( g_pTelnetService->m_szDomainName[0] )
  263. {
  264. WCopyUnicodeString( &g_szSessionData, g_pTelnetService->m_szDomainName, &g_iSizeOfBuffer );
  265. bIsDomainCopied = true;
  266. }
  267. }
  268. if( !bIsDomainCopied )
  269. {
  270. WCopyMbcsString( &g_szSessionData, pClientInfo->szDomain, &g_iSizeOfBuffer );
  271. }
  272. WCopyMbcsString( &g_szSessionData, pClientInfo->szUserName, &g_iSizeOfBuffer );
  273. WCopyMbcsString( &g_szSessionData, pClientInfo->szRemoteMachine, &g_iSizeOfBuffer );
  274. WCopyInt( &g_szSessionData, pClientInfo->lpLogonTime->wYear, &g_iSizeOfBuffer );
  275. WCopyInt( &g_szSessionData, pClientInfo->lpLogonTime->wMonth, &g_iSizeOfBuffer );
  276. WCopyInt( &g_szSessionData, pClientInfo->lpLogonTime->wDayOfWeek, &g_iSizeOfBuffer );
  277. WCopyInt( &g_szSessionData, pClientInfo->lpLogonTime->wDay, &g_iSizeOfBuffer );
  278. WCopyInt( &g_szSessionData, pClientInfo->lpLogonTime->wHour, &g_iSizeOfBuffer );
  279. WCopyInt( &g_szSessionData, pClientInfo->lpLogonTime->wMinute, &g_iSizeOfBuffer );
  280. WCopyInt( &g_szSessionData, pClientInfo->lpLogonTime->wSecond, &g_iSizeOfBuffer );
  281. WCopyInt( &g_szSessionData, pClientInfo->lpLogonTime->wMilliseconds,&g_iSizeOfBuffer );
  282. WCopyInt( &g_szSessionData, pClientInfo->m_dwIdleTime/1000, &g_iSizeOfBuffer );
  283. #ifdef ENUM_PROCESSES
  284. //g_szSessionData, g_iSizeOfBuffer needs to be global for following reason
  285. //This will add the processes to the list
  286. EnumSessionProcesses( *( pClientInfo->pAuthId ), GetTelnetSessionProcesses, TO_ENUM );
  287. #endif
  288. //To indicate end of a session: ',' indicates end of a session data
  289. AddSeparator( &g_szSessionData, session_separator, &g_iSizeOfBuffer );
  290. }
  291. }
  292. ExitOnError:
  293. _chVERIFY2( ReleaseMutex( g_pTelnetService->m_hSyncAllClientObjAccess ) );
  294. return ( dwStatus );
  295. }
  296. STDMETHODIMP
  297. CEnumTelnetClientsSvr::GetEnumClients
  298. (
  299. IEnumClients * * ppretval
  300. )
  301. {
  302. *ppretval = ( IEnumClients* ) this;
  303. ( *ppretval )->AddRef();
  304. //Initialize the Telnet Clients list
  305. if( m_pEnumeration )
  306. delete m_pEnumeration;
  307. m_pEnumeration = new CEnumData;
  308. if( !m_pEnumeration )
  309. {
  310. return (S_FALSE);
  311. }
  312. if( !EnumClients( m_pEnumeration ) )
  313. return (S_FALSE);
  314. return ( S_OK );
  315. }
  316. void
  317. GetSessionProcesses
  318. (
  319. HANDLE hProc,
  320. DWORD dwProcessId,
  321. LPWSTR lpszProcessName
  322. )
  323. {
  324. g_pEnumData->Add( lUniqueSessionNumber, dwProcessId, lpszProcessName );
  325. return;
  326. }
  327. bool
  328. CEnumTelnetClientsSvr::EnumClients
  329. (
  330. CEnumData* pEnumData
  331. )
  332. {
  333. WCHAR szUserName[ MAX_STRING_LENGTH + 1 ];
  334. WCHAR szDomain[ MAX_STRING_LENGTH + 1 ];
  335. WCHAR szPeer[ MAX_STRING_LENGTH + 1 ];
  336. DWORD dwStatus = 0;
  337. if( g_pTelnetService == NULL || pEnumData == NULL )
  338. return false;
  339. DWORD dwCount = 0;
  340. CClientInfo *pClientInfo = NULL;
  341. dwStatus = WaitForSingleObject(
  342. g_pTelnetService->m_hSyncAllClientObjAccess, WAIT_TIME );
  343. if( dwStatus != WAIT_OBJECT_0 )
  344. {
  345. return false;
  346. }
  347. if( ( dwCount = client_list_Count() ) != 0 )
  348. {
  349. while( dwCount > 0 )
  350. {
  351. pClientInfo = (CClientInfo *)client_list_Get( --dwCount );
  352. if( pClientInfo )
  353. {
  354. if( !ConvertSChartoWChar( pClientInfo->szUserName, szUserName )
  355. || !ConvertSChartoWChar( pClientInfo->szDomain, szDomain ) ||
  356. !ConvertSChartoWChar( pClientInfo->szRemoteMachine, szPeer ))
  357. {
  358. continue;
  359. }
  360. pEnumData->Add( szUserName, szDomain, szPeer,
  361. *( pClientInfo->lpLogonTime ), (LONG) pClientInfo->dwPid );
  362. //This will add the processes to the list
  363. LUID authId = *( pClientInfo->pAuthId );
  364. g_pEnumData = pEnumData;
  365. lUniqueSessionNumber = pClientInfo->dwPid;
  366. EnumSessionProcesses( authId, GetSessionProcesses, TO_ENUM );
  367. }
  368. }
  369. }
  370. _chVERIFY2( ReleaseMutex( g_pTelnetService->m_hSyncAllClientObjAccess ) );
  371. return ( true );
  372. }
  373. STDMETHODIMP
  374. CEnumTelnetClientsSvr::Next
  375. (
  376. ULONG celt,
  377. TELNET_CLIENT_INFO** rgelt,
  378. ULONG * pceltFetched
  379. )
  380. {
  381. ULONG ulNumReturned = 0;
  382. if( NULL == pceltFetched )
  383. {
  384. if( celt != 1 )
  385. return ( S_FALSE );
  386. }
  387. else
  388. *pceltFetched = 0;
  389. if( NULL == rgelt )
  390. return ( E_POINTER );
  391. typedef CEnumData::CNode* PNODE;
  392. PNODE* ppcopy = new PNODE [ celt ];
  393. if( NULL == ppcopy )
  394. {
  395. return ( S_FALSE );
  396. }
  397. ULONG total = celt;
  398. for (celt = 0; celt < total; celt ++)
  399. {
  400. ppcopy[celt] = NULL;
  401. if (m_pEnumeration->GetNext(&ppcopy[celt]))
  402. {
  403. ulNumReturned++;
  404. }
  405. else
  406. {
  407. break;
  408. }
  409. }
  410. celt = 0;
  411. while( celt < ulNumReturned )
  412. {
  413. rgelt[ celt ] =
  414. (TELNET_CLIENT_INFO*) CoTaskMemAlloc( sizeof(TELNET_CLIENT_INFO));
  415. if(! rgelt[ celt ] )
  416. {
  417. goto CLEANUP_AND_GET_OUT;
  418. }
  419. lstrcpyW( (*(rgelt[ celt ])).username, ppcopy[ celt ]->lpszUserName ); // Cleared by Prefast - Baskar
  420. lstrcpyW( (*(rgelt[ celt ])).domain, ppcopy[ celt ]->lpszDomain );
  421. lstrcpyW( (*(rgelt[ celt ])).peerhostname, ppcopy[ celt ]->lpszPeerHostName );
  422. (*(rgelt[ celt ])).logonTime = ppcopy[ celt ]->logonTime;
  423. (*(rgelt[ celt ])).uniqueId = ppcopy[ celt ]->lUniqueId;
  424. PIdNode *pPId = ppcopy[ celt ]->pProcessesHead;
  425. DWORD dwNoOfProcesses = 0;
  426. while( pPId )
  427. {
  428. dwNoOfProcesses++;
  429. pPId = pPId->pNextPId;
  430. }
  431. (*(rgelt[ celt ])).NoOfPids = dwNoOfProcesses;
  432. (*(rgelt[ celt ])).pId = ( DWORD * ) CoTaskMemAlloc ( sizeof( DWORD ) *
  433. ( dwNoOfProcesses + 10 ) );
  434. if( !(*(rgelt[ celt ])).pId )
  435. {
  436. goto CLEANUP_AND_GET_OUT;
  437. }
  438. (*(rgelt[ celt ])).processName = (WCHAR(*)[256]) CoTaskMemAlloc ( sizeof(WCHAR) * dwNoOfProcesses * 256);
  439. if( !(*(rgelt[ celt ])).processName )
  440. {
  441. goto CLEANUP_AND_GET_OUT;
  442. }
  443. INT ctr = 0;
  444. pPId = ppcopy[ celt ]->pProcessesHead;
  445. while( pPId )
  446. {
  447. (*(rgelt[ celt ])).pId[ ctr ] = pPId->dwPId;
  448. lstrcpyW( (*(rgelt[ celt ])).processName[ ctr ], pPId->lpszProcessName ); // Cleared by Prefast - Baskar
  449. ctr++;
  450. pPId = pPId->pNextPId;
  451. }
  452. (*(rgelt[ celt ])).pId[ ctr ] = ( DWORD )-1; //Indicates end of processes.
  453. celt++;
  454. }
  455. {
  456. ULONG index;
  457. for (index = 0; index < total; index ++)
  458. {
  459. if (ppcopy[index])
  460. {
  461. delete ppcopy[index];
  462. }
  463. }
  464. delete [] ppcopy;
  465. }
  466. if( pceltFetched != NULL )
  467. *pceltFetched = ulNumReturned;
  468. if( ulNumReturned == 0 )
  469. return ( S_FALSE );
  470. return ( S_OK );
  471. CLEANUP_AND_GET_OUT:
  472. {
  473. ULONG index;
  474. for (index = 0; index < total; index ++)
  475. {
  476. if (ppcopy[index])
  477. {
  478. delete ppcopy[index];
  479. }
  480. }
  481. delete [] ppcopy;
  482. for (index = 0; index < total; index ++)
  483. {
  484. CoTaskMemFree( (*(rgelt[ index ])).pId );
  485. CoTaskMemFree( (*(rgelt[ index ])).processName );
  486. CoTaskMemFree( rgelt[ index ] );
  487. }
  488. }
  489. return ( S_FALSE );
  490. }
  491. STDMETHODIMP
  492. CEnumTelnetClientsSvr::Skip
  493. (
  494. ULONG celt
  495. )
  496. {
  497. //return ( S_OK );
  498. return ( E_NOTIMPL );
  499. }
  500. STDMETHODIMP CEnumTelnetClientsSvr::Reset()
  501. {
  502. m_pEnumeration->Reset();
  503. return ( S_OK );
  504. }
  505. STDMETHODIMP CEnumTelnetClientsSvr::Clone(IEnumClients * * ppenum)
  506. {
  507. //return S_OK;
  508. return ( E_NOTIMPL );
  509. }
  510. STDMETHODIMP CEnumTelnetClientsSvr::TerminateSession( DWORD dwUniqueId )
  511. {
  512. if( g_pTelnetService == NULL )
  513. return S_FALSE;
  514. LONG dwRetStatus = S_FALSE;
  515. DWORD dwCount = 0;
  516. CClientInfo *pClientInfo = NULL;
  517. DWORD dwStatus = 0;
  518. dwStatus = WaitForSingleObject( g_pTelnetService->m_hSyncAllClientObjAccess,
  519. WAIT_TIME );
  520. if( dwStatus != WAIT_OBJECT_0 )
  521. {
  522. return S_FALSE;
  523. }
  524. if( ( dwCount = client_list_Count() ) != 0 )
  525. {
  526. while( dwCount > 0 )
  527. {
  528. pClientInfo = (CClientInfo *)client_list_Get( --dwCount );
  529. if(pClientInfo == NULL)
  530. goto Done;
  531. if( pClientInfo->dwPid == dwUniqueId )
  532. {
  533. if( AskTheSessionToQuit( pClientInfo ) )
  534. {
  535. dwRetStatus = S_OK;
  536. goto Done;
  537. }
  538. }
  539. }
  540. }
  541. Done:
  542. _chVERIFY2( ReleaseMutex( g_pTelnetService->m_hSyncAllClientObjAccess ) );
  543. return dwRetStatus;
  544. }
  545. bool CEnumTelnetClientsSvr::InformTheSession( CClientInfo *pClientInfo,
  546. WCHAR szMsg[] )
  547. {
  548. UCHAR *szMsgToSend = NULL;
  549. DWORD dwLen = 2* ( wcslen( szMsg ) + 1 );
  550. szMsgToSend = new UCHAR[ IPC_HEADER_SIZE + dwLen ];
  551. if( !szMsgToSend )
  552. {
  553. return false;
  554. }
  555. szMsgToSend[0] = OPERATOR_MESSAGE;
  556. memcpy( szMsgToSend + 1, &dwLen, sizeof( DWORD ) ); // No size info here - Attack ? Baskar
  557. memcpy( szMsgToSend + IPC_HEADER_SIZE, szMsg, dwLen );
  558. if( WriteToPipe( pClientInfo->hWritingPipe, (LPVOID) szMsgToSend,
  559. IPC_HEADER_SIZE + dwLen, &( g_pTelnetService->m_oWriteToPipe ) ) )
  560. {
  561. delete[] szMsgToSend;
  562. return true;
  563. }
  564. delete[] szMsgToSend;
  565. g_pTelnetService->StopServicingClient( pClientInfo, (BOOL)TRUE );
  566. return false;
  567. }
  568. STDMETHODIMP CEnumTelnetClientsSvr::SendMsgToASession( DWORD dwUniqueId, BSTR szMsgToBeSent )
  569. {
  570. if( !SendMsg( dwUniqueId, szMsgToBeSent ) )
  571. {
  572. return S_FALSE;
  573. }
  574. return S_OK;
  575. }
  576. bool CEnumTelnetClientsSvr::SendMsg( DWORD dwUniqueId, BSTR szMsg )
  577. {
  578. bool bRetStatus = false;
  579. DWORD dwCount = 0;
  580. CClientInfo *pClientInfo = NULL;
  581. DWORD dwStatus = 0;
  582. if( g_pTelnetService == NULL || szMsg == NULL )
  583. {
  584. return bRetStatus;
  585. }
  586. if( SysStringLen( szMsg ) <= 0 )
  587. {
  588. return bRetStatus;
  589. }
  590. dwStatus = WaitForSingleObject( g_pTelnetService->m_hSyncAllClientObjAccess, WAIT_TIME );
  591. if( dwStatus != WAIT_OBJECT_0 )
  592. {
  593. return bRetStatus;
  594. }
  595. if( ( dwCount = client_list_Count() ) != 0 )
  596. {
  597. while( dwCount > 0 && !bRetStatus )
  598. {
  599. pClientInfo = (CClientInfo *)client_list_Get( --dwCount );
  600. if(pClientInfo == NULL)
  601. goto Done;
  602. if( pClientInfo->dwPid == dwUniqueId )
  603. {
  604. if( InformTheSession( pClientInfo, szMsg ) )
  605. {
  606. bRetStatus = true;
  607. }
  608. }
  609. }
  610. }
  611. Done:
  612. _chVERIFY2( ReleaseMutex( g_pTelnetService->m_hSyncAllClientObjAccess ) );
  613. return bRetStatus;
  614. }
  615. void CEnumTelnetClientsSvr::FinalRelease()
  616. {
  617. delete m_pEnumeration;
  618. m_pEnumeration = NULL;
  619. CComObjectRootEx<CComMultiThreadModel>::FinalRelease();
  620. }
  621. bool CEnumTelnetClientsSvr::AskTheSessionToQuit( CClientInfo *pClientInfo )
  622. {
  623. bool bRetVal = false;
  624. BOOL delete_the_class = FALSE;
  625. DWORD dwRetVal = 0, dwAvail = 0, dwLeft = 0;
  626. CHAR *szBuffer = NULL;
  627. if(!PeekNamedPipe(pClientInfo->hReadingPipe,szBuffer,0,&dwRetVal,&dwAvail,&dwLeft))
  628. {
  629. dwRetVal = GetLastError();
  630. if(dwRetVal == ERROR_INVALID_HANDLE)
  631. {
  632. delete_the_class = TRUE;
  633. }
  634. }
  635. else if( WriteToPipe( pClientInfo->hWritingPipe, GO_DOWN,
  636. & ( g_pTelnetService->m_oWriteToPipe ) ) )
  637. {
  638. bRetVal = true;
  639. }
  640. g_pTelnetService->StopServicingClient( pClientInfo, delete_the_class );
  641. return bRetVal;
  642. }