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.

2294 lines
66 KiB

  1. // TlntSvr.cpp : This file contains the
  2. // Created: Feb '98
  3. // History:
  4. // Copyright (C) 1998 Microsoft Corporation
  5. // All rights reserved.
  6. // Microsoft Confidential
  7. // TlntSvr.cpp : Implementation of WinMain
  8. // Note: Proxy/Stub Information
  9. // To build a separate proxy/stub DLL,
  10. // run nmake -f TlntSvrps.mk in the project directory.
  11. #include <Stdafx.h>
  12. #include <Stdio.h>
  13. #include <stdlib.h>
  14. #include <time.h>
  15. #include <WinError.h>
  16. #include <TChar.h>
  17. #include <New.h>
  18. #include <OleAuto.h>
  19. #include <Resource.h>
  20. #include <Debug.h>
  21. #include <MsgFile.h>
  22. #include <TlntUtils.h>
  23. #include <regutil.h>
  24. #include <TlntSvr.h>
  25. #ifdef WHISTLER_BUILD
  26. #include "tlntsvr_i.c"
  27. #else
  28. #ifndef NO_PCHECK
  29. #include <PiracyCheck.h>
  30. #endif
  31. #endif
  32. #include <TelnetD.h>
  33. #include <TelntSrv.h>
  34. #include <EnumData.h>
  35. #include <EnCliSvr.h>
  36. #include "locresman.h"
  37. #include <lm.h>
  38. #include <lmaccess.h>
  39. #pragma warning(disable:4100)
  40. #define heapalloc(x) (HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, x))
  41. #define heapfree(x) (HeapFree(GetProcessHeap(), 0, x))
  42. CTelnetService* g_pTelnetService = 0;
  43. HANDLE *g_phLogFile = NULL;
  44. LPWSTR g_pszTelnetInstallPath = NULL;
  45. LPWSTR g_pszLogFile = NULL;
  46. LONG g_lMaxFileSize = 0;
  47. bool g_fIsLogFull = false;
  48. bool g_fLogToFile = false;
  49. #ifdef WHISTLER_BUILD
  50. DWORD g_dwStartType = SERVICE_DISABLED;
  51. #else
  52. DWORD g_dwStartType = SERVICE_AUTO_START;
  53. #endif
  54. HINSTANCE g_hInstRes = NULL;
  55. void LogEvent ( WORD wType, DWORD dwEventID, LPCTSTR pFormat, ... );
  56. using namespace _Utils;
  57. using CDebugLevel::TRACE_DEBUGGING;
  58. using CDebugLevel::TRACE_HANDLE;
  59. using CDebugLevel::TRACE_SOCKET;
  60. TCHAR g_szErrRegDelete[ MAX_STRING_LENGTH ];
  61. TCHAR g_szErrOpenSCM [ MAX_STRING_LENGTH ];
  62. TCHAR g_szErrOpenSvc [ MAX_STRING_LENGTH ];
  63. TCHAR g_szErrCreateSvc[ MAX_STRING_LENGTH ];
  64. TCHAR g_szErrDeleteSvc[ MAX_STRING_LENGTH ];
  65. TCHAR g_szMaxConnectionsReached[ MAX_STRING_LENGTH ];
  66. TCHAR g_szLicenseLimitReached [ MAX_STRING_LENGTH ];
  67. extern PSID localLocalSid;
  68. /////////////////////////////////////////////////////////////////////////////
  69. //
  70. LPWSTR
  71. GetDefaultLoginScriptFullPath( )
  72. {
  73. HKEY hk;
  74. DWORD dwDisp = 0;
  75. if( TnSecureRegCreateKeyEx( HKEY_LOCAL_MACHINE, REG_SERVICE_KEY, NULL, NULL,
  76. REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED , NULL, &hk, &dwDisp, 0 ) )
  77. {
  78. return NULL;
  79. }
  80. if( !GetRegistryString( hk, NULL, L"ImagePath", &g_pszTelnetInstallPath, L"",FALSE ) )
  81. {
  82. return NULL;
  83. }
  84. RegCloseKey( hk );
  85. if( !g_pszTelnetInstallPath )
  86. {
  87. //ImagePath key was not created.
  88. return NULL;
  89. }
  90. LPWSTR pLastBackSlash = wcsrchr( g_pszTelnetInstallPath, L'\\' );
  91. if( pLastBackSlash != NULL )
  92. {
  93. //Nuke the trailing "tlntsvr.exe"
  94. *pLastBackSlash = 0;
  95. }
  96. DWORD length_required = wcslen( g_pszTelnetInstallPath ) + wcslen( DEFAULT_LOGIN_SCRIPT ) + 2; // one for \ and one more for NULL in the end
  97. LPWSTR lpszDefaultLoginScriptFullPathName = new WCHAR[ length_required ];
  98. if( !lpszDefaultLoginScriptFullPathName )
  99. {
  100. return NULL;
  101. }
  102. _snwprintf(lpszDefaultLoginScriptFullPathName, length_required - 1, L"%s\\%s", g_pszTelnetInstallPath, DEFAULT_LOGIN_SCRIPT);
  103. lpszDefaultLoginScriptFullPathName[length_required-1] = 0; // When the buffer is full snwprintf could return non-null terminated string
  104. return lpszDefaultLoginScriptFullPathName;
  105. }
  106. /*Mem allocation by this function.
  107. To be deleted by the caller.
  108. It just forms the reg key as required by console.
  109. See comments for HandleJapSpecificRegKeys */
  110. bool
  111. FormTlntSessKeyForCmd( LPWSTR *lpszKey )
  112. {
  113. WCHAR szPathName[MAX_PATH + 1 ] = { 0 };
  114. WCHAR session_path[MAX_PATH*2];
  115. if( !GetModuleFileName( NULL, szPathName, MAX_PATH ) )
  116. {
  117. return ( FALSE );
  118. }
  119. //
  120. // Nuke the trailing "tlntsvr.exe"
  121. //
  122. LPTSTR pSlash = wcsrchr( szPathName, L'\\' );
  123. if( pSlash == NULL )
  124. {
  125. return ( FALSE );
  126. }
  127. else
  128. {
  129. *pSlash = L'\0';
  130. }
  131. wint_t ch = L'\\';
  132. LPTSTR pBackSlash = NULL;
  133. //
  134. // Replace all '\\' with '_' This format is required for the console to
  135. // interpret the key.
  136. //
  137. while ( 1 )
  138. {
  139. pBackSlash = wcschr( szPathName, ch );
  140. if( pBackSlash == NULL )
  141. {
  142. break;
  143. }
  144. else
  145. {
  146. *pBackSlash = L'_';
  147. }
  148. }
  149. _snwprintf(session_path, MAX_PATH*2 - 1, L"%s_tlntsess.exe", szPathName);
  150. session_path[MAX_PATH*2 - 1] = L'\0'; // snwprintf could return non-null terminated string, if the buffer size is an exact fit
  151. DWORD length_required = wcslen( REG_LOCALSERVICE_CONSOLE_KEY ) + wcslen( session_path ) + 2;
  152. *lpszKey = new WCHAR[ length_required ];
  153. if( *lpszKey == NULL )
  154. {
  155. return( FALSE );
  156. }
  157. _snwprintf(*lpszKey, length_required - 1, L"%s\\%s", REG_LOCALSERVICE_CONSOLE_KEY, session_path );
  158. (*lpszKey)[length_required - 1] = L'\0'; // snwprintf could return non-null terminated string, if the buffer size is an exact fit
  159. return ( TRUE );
  160. }
  161. //
  162. // If Japanese codepage, then we need to verify 3 registry settings for
  163. // console fonts:
  164. // HKEY_USERS\.DEFAULT\Console\FaceName :REG_SZ:�l�r �S�V�b�N
  165. // where the FaceName is "MS gothic" written in Japanese full widthKana
  166. // HKEY_USERS\.DEFAULT\Console\FontFamily:REG_DWORD:0x36
  167. // HKEY_USERS\.DEFAULT\Console\C:_SFU_Telnet_tlntsess.exe\FontFamily:REG_DWORD: 0x36
  168. // where the "C:" part is the actual path to SFU installation
  169. //
  170. //
  171. bool
  172. HandleFarEastSpecificRegKeys( void )
  173. {
  174. HKEY hk;
  175. DWORD dwFontSize = 0;
  176. const TCHAR szJAPFaceName[] = { 0xFF2D ,0xFF33 ,L' ' ,0x30B4 ,0x30B7 ,0x30C3 ,0x30AF ,L'\0' };
  177. const TCHAR szCHTFaceName[] = { 0x7D30 ,0x660E ,0x9AD4 ,L'\0'};
  178. const TCHAR szKORFaceName[] = { 0xAD74 ,0xB9BC ,0xCCB4 ,L'\0'};
  179. const TCHAR szCHSFaceName[] = { 0x65B0 ,0x5B8B ,0x4F53 ,L'\0' };
  180. TCHAR szFaceNameDef[MAX_STRING_LENGTH];
  181. DWORD dwCodePage = GetACP();
  182. DWORD dwFaceNameSize = 0;
  183. DWORD dwFontFamily = 54;
  184. DWORD dwFontWeight = 400;
  185. DWORD dwHistoryNoDup = 0;
  186. DWORD dwSize = 0;
  187. switch (dwCodePage)
  188. {
  189. case JAP_CODEPAGE:
  190. _tcscpy(szFaceNameDef, szJAPFaceName); //On JAP, set the FaceName to "MS Gothic"
  191. dwFontSize = JAP_FONTSIZE;
  192. break;
  193. case CHT_CODEPAGE:
  194. _tcscpy(szFaceNameDef, szCHTFaceName); //On CHT, set the FaceName to "MingLiU"
  195. dwFontSize = CHT_FONTSIZE;
  196. break;
  197. case KOR_CODEPAGE:
  198. _tcscpy(szFaceNameDef, szKORFaceName);//On KOR, set the FaceName to "GulimChe"
  199. dwFontSize = KOR_FONTSIZE;
  200. break;
  201. case CHS_CODEPAGE:
  202. _tcscpy(szFaceNameDef, szCHSFaceName);//On CHS, set the FaceName to "NSimSun"
  203. dwFontSize = CHS_FONTSIZE;
  204. break;
  205. default:
  206. _tcscpy(szFaceNameDef,L"\0");
  207. break;
  208. }
  209. dwFaceNameSize = ( _tcslen( szFaceNameDef ) + 1 ) * sizeof( TCHAR );
  210. if( !RegOpenKeyEx( HKEY_CURRENT_USER, REG_LOCALSERVICE_CONSOLE_KEY, 0, KEY_SET_VALUE, &hk ) )
  211. {
  212. RegSetValueEx( hk, L"FaceName", 0, REG_SZ, (LPBYTE) szFaceNameDef,
  213. dwFaceNameSize );
  214. DWORD dwVal;
  215. dwSize = sizeof( DWORD );
  216. SETREGISTRYDW( dwFontFamily, NULL, hk, L"FontFamily", dwVal,dwSize );
  217. RegCloseKey( hk );
  218. return ( TRUE );
  219. }
  220. return ( FALSE );
  221. }
  222. bool
  223. CreateRegistryEntriesIfNotPresent( void )
  224. {
  225. HKEY hk = NULL;
  226. HKEY hkDef = NULL;
  227. HKEY hkReadConf = NULL;
  228. DWORD dwCreateInitially;
  229. LPWSTR pszCreateInitially = NULL;
  230. LPWSTR lpszDefaultLoginScriptFullPathName = NULL;
  231. DWORD dwType;
  232. DWORD dwSize = sizeof( DWORD );
  233. DWORD dwValue = NULL;
  234. DWORD dwDisp = 0;
  235. DWORD dwSecurityMechanism = DEFAULT_SECURITY_MECHANISM;
  236. BOOL fFound = FALSE;
  237. if( TnSecureRegCreateKeyEx( HKEY_LOCAL_MACHINE, REG_PARAMS_KEY, NULL, NULL,
  238. REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED , NULL, &hk, &dwDisp, 0 ) )
  239. {
  240. return ( FALSE );
  241. }
  242. /*++
  243. When the telnet server is getting modified from w2k telnet, there'll be NTLM value present
  244. under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\TelnetServer\1.0
  245. This is treated as a gateway for updating the registry. Since this value is present,
  246. we are updating from win2k telnet to any upper version ( Garuda or whistler ). In that case,
  247. we need to map the data contained by this value into the corresponding data for
  248. "SecurityMechanism".
  249. If we are upgrading from win2k, the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\TelnetServer\Defaults
  250. key is deleted and created again. According to the telnet spec, all the values under this key
  251. should be overwritten by the default values. So instead of checking all values, deleting the key -
  252. which will create all the values with the defaults in them.
  253. After updating all the values, we create a new value called UpdateTo and put data '3' in that.
  254. This is defined by TELNET_LATEST_VERSION. Next version should be modifying this to the proper
  255. value.
  256. After the values are once modified, we need not go through the whole procedure again.
  257. Now the open issue here is :
  258. What if admin changes the registry value after once they are updated ?
  259. Well, no one is supposed to edit the registry. So the service would not start properly
  260. if the registry values are changed with invalid data in them.
  261. Once the UpdatedTo value is created, the registry will never be changed. Few values need to be
  262. read because some global variables are initialized with them.
  263. This is done at the end of the function.
  264. --*/
  265. if( ERROR_SUCCESS == (RegQueryValueEx( hk, L"UpdatedTo", NULL, &dwType, ( LPBYTE )(&dwValue),
  266. &dwSize )))
  267. {
  268. if(dwValue == LATEST_TELNET_VERSION )
  269. {
  270. goto Done;
  271. }
  272. }
  273. dwDisp=0;
  274. //ignore the failure... since we are immediately doing RegCreateKey(). If RegDeleteKey() fails due to
  275. //some permission problems, RegCreateKey() will also fail. In other cases, we should continue.
  276. RegDeleteKey(HKEY_LOCAL_MACHINE, REG_DEFAULTS_KEY);
  277. if( TnSecureRegCreateKeyEx( HKEY_LOCAL_MACHINE, REG_DEFAULTS_KEY, NULL, NULL,
  278. REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED , NULL, &hkDef, &dwDisp , 0 ))
  279. {
  280. return(FALSE);
  281. }
  282. if( ERROR_SUCCESS == (RegQueryValueEx( hk, L"NTLM", NULL, &dwType, ( LPBYTE )(&dwValue),
  283. &dwSize )))
  284. {
  285. fFound = TRUE;
  286. switch (dwValue)
  287. {
  288. case 0:
  289. dwValue = NO_NTLM;
  290. break;
  291. case 1:
  292. dwValue = NTLM_ELSE_OR_LOGIN;
  293. break;
  294. case 2:
  295. dwValue = NTLM_ONLY;
  296. break;
  297. default:
  298. //should never happen
  299. _TRACE(TRACE_DEBUGGING,"ERROR: NTLM contains unexpected data");
  300. return(FALSE);
  301. }
  302. dwSecurityMechanism = dwValue;
  303. if( !GetRegistryDW( hk, NULL, L"SecurityMechanism", &dwCreateInitially,
  304. dwSecurityMechanism ,fFound) )
  305. {
  306. return ( FALSE );
  307. }
  308. if(ERROR_SUCCESS != RegDeleteValue(hk,L"NTLM"))
  309. {
  310. _TRACE(TRACE_DEBUGGING,"CreateRegistryEntries : RegDelete failed");
  311. return(FALSE);
  312. }
  313. if(ERROR_SUCCESS!=RegDeleteKey(hk,L"Performance"))
  314. {
  315. _TRACE(TRACE_DEBUGGING,"CreateRegistryEntries : RegDeleteKey failed");
  316. return(FALSE);
  317. }
  318. }
  319. dwDisp = 0;
  320. if( TnSecureRegCreateKeyEx( HKEY_LOCAL_MACHINE, READ_CONFIG_KEY, NULL, NULL,
  321. REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED , NULL, &hkReadConf, &dwDisp, 0 ) )
  322. {
  323. return( FALSE );
  324. }
  325. if(!GetRegistryDWORD(hkReadConf,L"Defaults",&dwCreateInitially,1,TRUE))
  326. {
  327. return(FALSE);
  328. }
  329. RegCloseKey( hkReadConf );
  330. if( !GetRegistryDW( hk, hkDef, L"MaxConnections", &dwCreateInitially,
  331. DEFAULT_MAX_CONNECTIONS,FALSE) )
  332. {
  333. return ( FALSE );
  334. }
  335. if( !GetRegistryDW( hk, hkDef, L"TelnetPort", &dwCreateInitially,
  336. DEFAULT_TELNET_PORT,FALSE) )
  337. {
  338. return ( FALSE );
  339. }
  340. if( !GetRegistryString( hk, hkDef, L"DefaultShell", &pszCreateInitially,
  341. DEFAULT_SHELL,fFound ) )
  342. {
  343. return ( FALSE );
  344. }
  345. delete[] pszCreateInitially;
  346. pszCreateInitially = NULL;
  347. if( !GetRegistryString( hk, hkDef, L"ListenToSpecificIpAddr", &pszCreateInitially,
  348. DEFAULT_IP_ADDR,fFound ) )
  349. {
  350. return ( FALSE );
  351. }
  352. delete[] pszCreateInitially;
  353. pszCreateInitially = NULL;
  354. if( !GetRegistryString( hk, hkDef, SWITCH_TO_KEEP_SHELL_RUNNING, &pszCreateInitially,
  355. DEFAULT_SWITCH_TO_KEEP_SHELL_RUNNING,fFound ) )
  356. {
  357. return ( FALSE );
  358. }
  359. delete[] pszCreateInitially;
  360. pszCreateInitially = NULL;
  361. if( !GetRegistryString( hk, hkDef, SWITCH_FOR_ONE_TIME_USE_OF_SHELL,
  362. &pszCreateInitially,
  363. DEFAULT_SWITCH_FOR_ONE_TIME_USE_OF_SHELL,fFound ) )
  364. {
  365. return ( FALSE );
  366. }
  367. delete[] pszCreateInitially;
  368. pszCreateInitially = NULL;
  369. if( !GetRegistryString( hk, hkDef, L"DefaultDomain", &pszCreateInitially,
  370. DEFAULT_DOMAIN,FALSE) )
  371. {
  372. return ( FALSE );
  373. }
  374. delete[] pszCreateInitially;
  375. pszCreateInitially = NULL;
  376. if( !GetRegistryString( hk, NULL, L"Shell", &pszCreateInitially, L"",fFound ) )
  377. {
  378. return false;
  379. }
  380. delete[] pszCreateInitially;
  381. pszCreateInitially = NULL;
  382. if( !GetRegistryDW( hk, hkDef, L"AllowTrustedDomain", &dwCreateInitially,
  383. DEFAULT_ALLOW_TRUSTED_DOMAIN,FALSE) )
  384. {
  385. return ( FALSE );
  386. }
  387. if( !GetRegistryDW( hk, hkDef, L"MaxFailedLogins", &dwCreateInitially,
  388. DEFAULT_MAX_FAILED_LOGINS,FALSE) )
  389. {
  390. return ( FALSE );
  391. }
  392. if( !GetRegistryDW( hk, hkDef, L"SecurityMechanism", &dwCreateInitially,
  393. DEFAULT_SECURITY_MECHANISM ,FALSE) )
  394. {
  395. return ( FALSE );
  396. }
  397. if( !GetRegistryDW( hk, hkDef, L"EventLoggingEnabled", &dwCreateInitially,
  398. DEFAULT_SYSAUDITING,fFound ) )
  399. {
  400. return ( FALSE );
  401. }
  402. if( !GetRegistryDW( hk, hkDef, L"LogNonAdminAttempts", &dwCreateInitially,
  403. DEFAULT_LOGEVENTS,fFound ) )
  404. {
  405. return ( FALSE );
  406. }
  407. if( !GetRegistryDW( hk, hkDef, L"LogAdminAttempts", &dwCreateInitially,
  408. DEFAULT_LOGADMIN,fFound ) )
  409. {
  410. return ( FALSE );
  411. }
  412. if( !GetRegistryDW( hk, hkDef, L"LogFailures", &dwCreateInitially,
  413. DEFAULT_LOGFAILURES,fFound ) )
  414. {
  415. return ( FALSE );
  416. }
  417. //In SFU2.0, AltKeyMapping has 1 for TRUE and 2 for FALSE where as now we have
  418. // 1 for TRUE and 0 for FALSE. So if 'AltKeyMapping' value is found, we need to map it
  419. // to the correct data.
  420. if( ERROR_SUCCESS == (RegQueryValueEx( hk, L"AltKeyMapping", NULL, &dwType, ( LPBYTE )(&dwValue),
  421. &dwSize )))
  422. {
  423. switch (dwValue)
  424. {
  425. case 1://In sfu2.0 and Garuda, AltKeyMapping ON = 1
  426. dwValue = ALT_KEY_MAPPING_ON;
  427. break;
  428. case 2: //In SFU 2.0, AltKeyMapping off = 2. In garuda, it's 0.
  429. dwValue = ALT_KEY_MAPPING_OFF;
  430. break;
  431. default:
  432. dwValue = ALT_KEY_MAPPING_ON;
  433. _TRACE(TRACE_DEBUGGING,"ERROR: AltKeyMapping contains unexpected data");
  434. }
  435. }
  436. else
  437. {
  438. dwValue = DEFAULT_ALT_KEY_MAPPING;
  439. }
  440. if( !GetRegistryDW( hk, hkDef, L"AltKeyMapping", &dwCreateInitially,
  441. dwValue,TRUE) )
  442. {
  443. return ( FALSE );
  444. }
  445. if( !GetRegistryDW( hk, hkDef, L"IdleSessionTimeOut", &dwCreateInitially,
  446. DEFAULT_IDLE_SESSION_TIME_OUT,fFound ) )
  447. {
  448. return ( FALSE );
  449. }
  450. if( !GetRegistryDW( hk, hkDef, L"IdleSessionTimeOutBkup", &dwCreateInitially,
  451. DEFAULT_IDLE_SESSION_TIME_OUT,fFound ) )
  452. {
  453. return ( FALSE );
  454. }
  455. if( !GetRegistryDW( hk, hkDef, L"DisconnectKillAllApps", &dwCreateInitially,
  456. DEFAULT_DISCONNECT_KILLALL_APPS,fFound ) )
  457. {
  458. return ( FALSE );
  459. }
  460. if( !GetRegistryDW( hk, hkDef, L"ModeOfOperation", &dwCreateInitially,
  461. DEFAULT_MODE_OF_OPERATION,fFound ) )
  462. {
  463. return ( FALSE );
  464. }
  465. //Delete the Termcap entry. It will exist only when you are upgrading.
  466. //It will get created when the first session connects to the server.
  467. RegDeleteValue(hk,L"Termcap");
  468. if( !GetRegistryDW( hk, hkDef, L"UpdatedTo", &dwCreateInitially,
  469. LATEST_TELNET_VERSION,TRUE) )
  470. {
  471. return ( FALSE );
  472. }
  473. Done:
  474. /*++
  475. These things are needed to be done everytime at the net start because
  476. they initialize some global variables.
  477. --*/
  478. dwCreateInitially = 0;
  479. if( !GetRegistryDW( hk, hkDef, L"LogToFile", &dwCreateInitially,
  480. DEFAULT_LOGTOFILE,fFound ) )
  481. {
  482. return ( FALSE );
  483. }
  484. if( dwCreateInitially )
  485. {
  486. g_fLogToFile = true;
  487. }
  488. if( !( lpszDefaultLoginScriptFullPathName
  489. = GetDefaultLoginScriptFullPath() ) )
  490. {
  491. return ( FALSE );
  492. }
  493. if( !GetRegistryString( hk, hkDef, L"LoginScript", &pszCreateInitially,
  494. lpszDefaultLoginScriptFullPathName,FALSE) )
  495. {
  496. delete[] lpszDefaultLoginScriptFullPathName;
  497. return ( FALSE );
  498. }
  499. delete[] pszCreateInitially;
  500. pszCreateInitially = NULL;
  501. delete[] lpszDefaultLoginScriptFullPathName;
  502. if( !GetRegistryString( hk, hkDef, L"LogFile", &g_pszLogFile,
  503. DEFAULT_LOGFILE,fFound ) )
  504. {
  505. return ( FALSE );
  506. }
  507. if( !GetRegistryDW( hk, hkDef, LOGFILESIZE, (DWORD *)&g_lMaxFileSize,
  508. DEFAULT_LOGFILESIZE,fFound ) )
  509. {
  510. return ( FALSE );
  511. }
  512. RegCloseKey( hkDef );
  513. RegCloseKey( hk );
  514. return ( TRUE );
  515. }
  516. void CloseLogFile( LPWSTR *pszLogFile, HANDLE *hLogFile )
  517. {
  518. delete[] ( *pszLogFile );
  519. *pszLogFile = NULL;
  520. if( *hLogFile ) // global variable
  521. TELNET_CLOSE_HANDLE( *hLogFile );
  522. delete hLogFile;
  523. }
  524. void CloseAnyGlobalObjects()
  525. {
  526. delete[] g_pszTelnetInstallPath;
  527. CloseLogFile( &g_pszLogFile, g_phLogFile );
  528. }
  529. bool InitializeLogFile( LPWSTR szLogFile, HANDLE *hLogFile )
  530. {
  531. //open logfile handle
  532. //
  533. _chASSERT( hLogFile != NULL );
  534. _chASSERT( szLogFile != NULL );
  535. *hLogFile = NULL;
  536. LPWSTR szExpandedLogFile = NULL;
  537. if( !g_fLogToFile )
  538. {
  539. return ( TRUE );
  540. }
  541. if( wcscmp( szLogFile, L"" ) != 0 )
  542. {
  543. LONG lDistanceToMove = 0 ;
  544. if( !AllocateNExpandEnvStrings( szLogFile, &szExpandedLogFile) )
  545. {
  546. return( FALSE );
  547. }
  548. *hLogFile = CreateFile( szExpandedLogFile, GENERIC_WRITE | GENERIC_READ,
  549. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
  550. FILE_ATTRIBUTE_NORMAL, NULL );
  551. delete [] szExpandedLogFile;
  552. if( *hLogFile == INVALID_HANDLE_VALUE )
  553. {
  554. DWORD dwErr = GetLastError();
  555. *hLogFile = NULL;
  556. LogEvent( EVENTLOG_ERROR_TYPE, MSG_ERRLOGFILE, szLogFile );
  557. LogFormattedGetLastError( EVENTLOG_ERROR_TYPE, 0, dwErr );
  558. return( FALSE );
  559. }
  560. _chVERIFY2( SetFilePointer( *hLogFile, lDistanceToMove, &lDistanceToMove, FILE_END ) );
  561. }
  562. return ( TRUE );
  563. }
  564. bool InitializeGlobalObjects()
  565. {
  566. _chASSERT ( g_hInstRes );
  567. if( !CreateRegistryEntriesIfNotPresent( ) )
  568. {
  569. return ( FALSE );
  570. }
  571. DWORD dwCodePage = GetACP();
  572. if ( dwCodePage == JAP_CODEPAGE || dwCodePage == CHS_CODEPAGE ||dwCodePage == CHT_CODEPAGE || dwCodePage == KOR_CODEPAGE )
  573. {
  574. //Fareast code page
  575. if( !HandleFarEastSpecificRegKeys() )
  576. {
  577. return( FALSE );
  578. }
  579. }
  580. g_phLogFile = new HANDLE;
  581. if( !g_phLogFile )
  582. {
  583. return ( FALSE );
  584. }
  585. InitializeLogFile( g_pszLogFile, g_phLogFile );
  586. return ( TRUE );
  587. }
  588. void WriteAuditedMsgsToFile( LPSTR szString )
  589. {
  590. DWORD dwNumBytesWritten, dwMsgLength;
  591. LPSTR logStr = NULL;
  592. LPSTR logTime = NULL;
  593. UDATE uSysDate; //local time
  594. DATE dtCurrent;
  595. DWORD dwFlags = VAR_VALIDDATE;
  596. BSTR szDate = NULL;
  597. DWORD dwSize = 0;
  598. DWORD dwFileSizeLowWord = 0, dwFileSizeHighWord = 0;
  599. LARGE_INTEGER liActualSize = { 0 };
  600. GetLocalTime( &uSysDate.st );
  601. if( VarDateFromUdate( &uSysDate, dwFlags, &dtCurrent ) != S_OK )
  602. {
  603. goto AuditAbort;
  604. }
  605. if( VarBstrFromDate( dtCurrent,
  606. MAKELCID( MAKELANGID( LANG_NEUTRAL, SUBLANG_SYS_DEFAULT ), SORT_DEFAULT ),
  607. LOCALE_NOUSEROVERRIDE, &szDate ) != S_OK )
  608. {
  609. goto AuditAbort;
  610. }
  611. dwSize = WideCharToMultiByte( GetOEMCP(), 0, szDate, SysStringByteLen( szDate )/sizeof(TCHAR),
  612. NULL, 0, NULL, NULL );
  613. logTime = new CHAR[ dwSize+1 ];
  614. if( !logTime )
  615. {
  616. goto AuditAbort;
  617. }
  618. dwSize = WideCharToMultiByte( GetOEMCP(), 0, szDate, SysStringByteLen( szDate )/sizeof(TCHAR),
  619. logTime, dwSize, NULL, NULL );
  620. logTime[dwSize] = 0;
  621. dwMsgLength = strlen( szString ) + strlen( logTime ) + strlen( NEW_LINE ) + 1;
  622. logStr = new CHAR[ dwMsgLength + 1 ];
  623. if( !logStr )
  624. {
  625. goto AuditAbort;
  626. }
  627. _snprintf( logStr, dwMsgLength, "%s %s%s", szString, logTime, NEW_LINE );
  628. dwFileSizeLowWord = GetFileSize( *g_phLogFile, &dwFileSizeHighWord );
  629. if( dwFileSizeLowWord == INVALID_FILE_SIZE )
  630. {
  631. goto AuditAbort;
  632. }
  633. liActualSize.QuadPart = dwFileSizeHighWord;
  634. liActualSize.QuadPart = liActualSize.QuadPart << (sizeof( dwFileSizeHighWord ) * 8);
  635. liActualSize.QuadPart += dwFileSizeLowWord + dwMsgLength;
  636. if( liActualSize.QuadPart <= (g_lMaxFileSize * ONE_MB) )
  637. {
  638. g_fIsLogFull = false;
  639. _chVERIFY2( WriteFile( *g_phLogFile, (LPCVOID) logStr,
  640. dwMsgLength, &dwNumBytesWritten, NULL ) );
  641. }
  642. else
  643. {
  644. if( !g_fIsLogFull )
  645. {
  646. //Log event
  647. g_fIsLogFull = true;
  648. LogEvent(EVENTLOG_INFORMATION_TYPE, LOGFILE_FULL, g_pszLogFile );
  649. }
  650. }
  651. AuditAbort:
  652. SysFreeString( szDate );
  653. delete[] logTime;
  654. delete[] logStr;
  655. }
  656. BOOL GetInstalledTlntsvrPath( LPTSTR szPath, DWORD *dwSize )
  657. {
  658. HKEY hKey = NULL;
  659. BOOL bResult = FALSE;
  660. DWORD dwDisp = 0;
  661. DWORD dwType = 0;
  662. if( !szPath || !dwSize )
  663. {
  664. goto GetInstalledTlntsvrPathAbort;
  665. }
  666. if( TnSecureRegCreateKeyEx( HKEY_LOCAL_MACHINE, REG_SERVICE_KEY, NULL, NULL,
  667. REG_OPTION_NON_VOLATILE, KEY_QUERY_VALUE, NULL, &hKey, &dwDisp, 0 ) )
  668. {
  669. goto GetInstalledTlntsvrPathAbort;
  670. }
  671. if( RegQueryValueEx( hKey, L"ImagePath", NULL, &dwType, ( LPBYTE )szPath, dwSize) )
  672. {
  673. goto GetInstalledTlntsvrPathAbort;
  674. }
  675. bResult = TRUE;
  676. GetInstalledTlntsvrPathAbort:
  677. if( hKey )
  678. {
  679. RegCloseKey( hKey );
  680. }
  681. return bResult;
  682. }
  683. void Regsvr32IfNotAlreadyDone()
  684. {
  685. TCHAR szPath[MAX_PATH+1];
  686. TCHAR szInstalledTlntsvr[MAX_PATH+1];
  687. DWORD dwSize = 2* ( MAX_PATH + 1 ); //in bytes;
  688. CRegKey keyAppID;
  689. LONG lRes = 0;
  690. CRegKey key;
  691. TCHAR szValue[_MAX_PATH];
  692. DWORD dwLen = _MAX_PATH;
  693. LPTSTR szTelnetPath = NULL;
  694. LPTSTR szInstalledDll = NULL;
  695. STARTUPINFO sinfo;
  696. PROCESS_INFORMATION pinfo;
  697. WCHAR szApp[MAX_PATH+14];
  698. lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("CLSID"));
  699. if (lRes != ERROR_SUCCESS)
  700. return;
  701. lRes = key.Open( keyAppID, L"{FE9E48A2-A014-11D1-855C-00A0C944138C}" );
  702. if (lRes != ERROR_SUCCESS)
  703. return;
  704. lRes = key.QueryValue(szValue, _T("Default"), &dwLen);
  705. keyAppID.Close();
  706. key.Close();
  707. //Get the Installed service path from HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TlntSvr\ImagePath
  708. if( !GetInstalledTlntsvrPath( szInstalledTlntsvr, &dwSize ) )
  709. {
  710. return;
  711. }
  712. //path contains tlntsvr.exe at the tail
  713. //truncate at the last '\' - so *szTelnetPath will have z:\some\folder
  714. szTelnetPath = wcsrchr( szInstalledTlntsvr, L'\\' );
  715. if(szTelnetPath)
  716. *szTelnetPath = L'\0';
  717. //HKEY_CLASSES_ROOT\CLSID\{FE9E48A2-A014-11D1-855C-00A0C944138C}\InProcServer32
  718. //truncate at last '\'
  719. szInstalledDll = wcsrchr( szValue, L'\\' );
  720. if(szInstalledDll)
  721. *szInstalledDll = L'\0';
  722. if( lstrcmpi( szInstalledTlntsvr, szValue ) == 0 )
  723. {
  724. //Since both the paths match, our dll is already registered
  725. return;
  726. }
  727. _tcscpy(szPath, L"regsvr32.exe /s " );
  728. _tcscat(szPath, szInstalledTlntsvr );
  729. _tcscat(szPath, L"\\tlntsvrp.dll");
  730. SfuZeroMemory(&sinfo, sizeof(STARTUPINFO));
  731. sinfo.cb = sizeof(STARTUPINFO);
  732. if(!GetSystemDirectory(szApp,MAX_PATH))
  733. {
  734. return;
  735. }
  736. wcsncat(szApp,L"\\regsvr32.exe",13);
  737. szApp[MAX_PATH+13] = L'\0';
  738. //initiate Regsvr32 /s path\tlntsvrp.dll
  739. _TRACE(TRACE_DEBUGGING,L"Calling regsvr32 with szApp = %s and szPath = %s",szApp,szPath);
  740. if ( CreateProcess( szApp, szPath, NULL, NULL,
  741. FALSE, 0, NULL, NULL, &sinfo, &pinfo) )
  742. {
  743. // wait for the process to finish.
  744. TlntSynchronizeOn(pinfo.hProcess);
  745. TELNET_CLOSE_HANDLE(pinfo.hProcess);
  746. TELNET_CLOSE_HANDLE(pinfo.hThread);
  747. }
  748. }
  749. DWORD
  750. WINAPI
  751. TelnetServiceThread ( )
  752. {
  753. g_pTelnetService = CTelnetService::Instance();
  754. _chASSERT( g_pTelnetService != NULL );
  755. if( !g_pTelnetService )
  756. {
  757. return( FALSE );
  758. }
  759. if( !InitializeGlobalObjects() )
  760. {
  761. return ( FALSE );
  762. }
  763. _Module.SetServiceStatus(SERVICE_START_PENDING);
  764. //This is needed because W2k telnet server is registering tlntsvrp.dll of %systemdir%. Even if this fails the service can continue
  765. Regsvr32IfNotAlreadyDone();
  766. LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_STARTUP, _T("Service started"));
  767. g_pTelnetService->ListenerThread();
  768. _Module.SetServiceStatus( SERVICE_STOP_PENDING );
  769. CloseAnyGlobalObjects();
  770. delete g_pTelnetService;
  771. g_pTelnetService = NULL;
  772. return ( TRUE );
  773. }
  774. /////////////////////////////////////////////////////////////////////////////
  775. //
  776. CServiceModule _Module;
  777. BEGIN_OBJECT_MAP(ObjectMap)
  778. OBJECT_ENTRY(CLSID_EnumTelnetClientsSvr, CEnumTelnetClientsSvr)
  779. END_OBJECT_MAP()
  780. LPCTSTR
  781. FindOneOf
  782. (
  783. LPCTSTR p1,
  784. LPCTSTR p2
  785. )
  786. {
  787. while (*p1 != NULL)
  788. {
  789. LPCTSTR p = p2;
  790. while (*p != NULL)
  791. {
  792. if (*p1 == *p++)
  793. return p1+1;
  794. }
  795. p1++;
  796. }
  797. return NULL;
  798. }
  799. BOOL
  800. IsThatMe()
  801. {
  802. HKEY hk = NULL;
  803. DWORD dwType;
  804. DWORD dwSize = sizeof( DWORD );
  805. DWORD dwValue = 0;
  806. BOOL bIsThatMe = FALSE;
  807. DWORD dwDisp = 0;
  808. if( TnSecureRegCreateKeyEx( HKEY_LOCAL_MACHINE, REG_PARAMS_KEY, NULL, NULL,
  809. REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED , NULL, &hk, &dwDisp, 0 ) )
  810. {
  811. goto Done;
  812. }
  813. if( ERROR_SUCCESS == (RegQueryValueEx( hk, L"UpdatedTo", NULL, &dwType, ( LPBYTE )(&dwValue),
  814. &dwSize )))
  815. {
  816. if(dwValue == LATEST_TELNET_VERSION )
  817. {
  818. bIsThatMe = TRUE;
  819. goto Done;
  820. }
  821. }
  822. Done:
  823. if(hk)
  824. {
  825. RegCloseKey(hk);
  826. }
  827. return bIsThatMe;
  828. }
  829. BOOL
  830. SetServiceConfigToSelf( LPTSTR szServiceName )
  831. {
  832. BOOL bResult = FALSE;
  833. HKEY hKey = NULL;
  834. DWORD dwDisp = 0;
  835. WCHAR szMyName[ MAX_PATH + 1 ];
  836. DWORD dwSize = 0;
  837. LONG lRes = 0;
  838. DWORD dwCreateInitially = 0;
  839. if( !szServiceName )
  840. {
  841. goto SetServiceConfigToSelfAbort;
  842. }
  843. // Get our Path.
  844. if ( !GetModuleFileName(NULL, szMyName, MAX_PATH) )
  845. {
  846. goto SetServiceConfigToSelfAbort;
  847. }
  848. if( TnSecureRegCreateKeyEx( HKEY_LOCAL_MACHINE, REG_SERVICE_KEY, NULL, NULL,
  849. REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED , NULL, &hKey, &dwDisp, 0 ) )
  850. {
  851. goto SetServiceConfigToSelfAbort;
  852. }
  853. dwSize = ( wcslen( szMyName ) + 1 ) * 2 ;
  854. if( lRes = RegSetValueEx( hKey, L"ImagePath", NULL, REG_EXPAND_SZ, ( BYTE * ) szMyName, dwSize) )
  855. {
  856. goto SetServiceConfigToSelfAbort;
  857. }
  858. if( !GetRegistryDW( hKey, NULL, L"Start", &g_dwStartType,
  859. g_dwStartType,FALSE) )
  860. {
  861. goto SetServiceConfigToSelfAbort;
  862. }
  863. bResult = TRUE;
  864. SetServiceConfigToSelfAbort:
  865. if( hKey )
  866. {
  867. RegCloseKey( hKey );
  868. }
  869. return bResult;
  870. }
  871. /**************************
  872. * Appends the SID to current DACL of a file.
  873. * Parameters:
  874. * [in] SID to be appended
  875. * [in] Name of the file ( full path )
  876. * [in] Access Mask
  877. * Return values:
  878. * boolean to return success or failure.
  879. */
  880. BOOL AddAccessRights(PSID pSid, LPCWSTR lpszFileName, DWORD dwAccessMask) {
  881. // File SD variables.
  882. PSECURITY_DESCRIPTOR pFileSD = NULL;
  883. DWORD cbFileSD = 0;
  884. // New SD variables.
  885. PSECURITY_DESCRIPTOR pNewSD = NULL;
  886. // ACL variables.
  887. PACL pACL = NULL;
  888. BOOL fDaclPresent;
  889. BOOL fDaclDefaulted;
  890. ACL_SIZE_INFORMATION AclInfo;
  891. // New ACL variables.
  892. PACL pNewACL = NULL;
  893. DWORD cbNewACL = 0;
  894. // Temporary ACE.
  895. LPVOID pTempAce = NULL;
  896. UINT CurrentAceIndex;
  897. // Assume function will fail.
  898. BOOL fResult = FALSE;
  899. BOOL fAPISuccess;
  900. __try {
  901. //
  902. // Get security descriptor (SD) for file.
  903. //
  904. fAPISuccess = GetFileSecurity(lpszFileName,
  905. DACL_SECURITY_INFORMATION, pFileSD, 0, &cbFileSD);
  906. // API should have failed with insufficient buffer.
  907. if (fAPISuccess)
  908. __leave;
  909. else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  910. _TRACE(TRACE_DEBUGGING,L"GetFileSecurity() failed. Error %d\n",
  911. GetLastError());
  912. __leave;
  913. }
  914. pFileSD = heapalloc(cbFileSD);
  915. if (!pFileSD) {
  916. _TRACE(TRACE_DEBUGGING,L"HeapAlloc() failed. Error %d\n", GetLastError());
  917. __leave;
  918. }
  919. fAPISuccess = GetFileSecurity(lpszFileName,
  920. DACL_SECURITY_INFORMATION, pFileSD, cbFileSD, &cbFileSD);
  921. if (!fAPISuccess) {
  922. _TRACE(TRACE_DEBUGGING,L"GetFileSecurity() failed. Error %d\n",
  923. GetLastError());
  924. __leave;
  925. }
  926. //
  927. // Initialize new SD.
  928. //
  929. pNewSD = heapalloc(cbFileSD); // Should be same size as FileSD.
  930. if (!pNewSD) {
  931. _TRACE(TRACE_DEBUGGING,L"HeapAlloc() failed. Error %d\n", GetLastError());
  932. __leave;
  933. }
  934. if (!InitializeSecurityDescriptor(pNewSD,
  935. SECURITY_DESCRIPTOR_REVISION)) {
  936. _TRACE(TRACE_DEBUGGING,L"InitializeSecurityDescriptor() failed. Error %d\n",
  937. GetLastError());
  938. __leave;
  939. }
  940. //
  941. // Get DACL from SD.
  942. //
  943. if (!GetSecurityDescriptorDacl(pFileSD, &fDaclPresent, &pACL,
  944. &fDaclDefaulted)) {
  945. _TRACE(TRACE_DEBUGGING,L"GetSecurityDescriptorDacl() failed. Error %d\n",
  946. GetLastError());
  947. __leave;
  948. }
  949. //
  950. // Get size information for DACL.
  951. //
  952. AclInfo.AceCount = 0; // Assume NULL DACL.
  953. AclInfo.AclBytesFree = 0;
  954. AclInfo.AclBytesInUse = sizeof(ACL);
  955. // If not NULL DACL, gather size information from DACL.
  956. if (fDaclPresent && pACL) {
  957. if(!GetAclInformation(pACL, &AclInfo,
  958. sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) {
  959. _TRACE(TRACE_DEBUGGING,L"GetAclInformation() failed. Error %d\n",
  960. GetLastError());
  961. __leave;
  962. }
  963. }
  964. //
  965. // Compute size needed for the new ACL.
  966. //
  967. cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE)
  968. + GetLengthSid(pSid) - sizeof(DWORD);
  969. //
  970. // Allocate memory for new ACL.
  971. //
  972. pNewACL = (PACL) heapalloc(cbNewACL);
  973. if (!pNewACL) {
  974. _TRACE(TRACE_DEBUGGING,L"HeapAlloc() failed. Error %d\n", GetLastError());
  975. __leave;
  976. }
  977. //
  978. // Initialize the new ACL.
  979. //
  980. if(!InitializeAcl(pNewACL, cbNewACL, ACL_REVISION2)) {
  981. _TRACE(TRACE_DEBUGGING,L"InitializeAcl() failed. Error %d\n", GetLastError());
  982. __leave;
  983. }
  984. //
  985. // If DACL is present, copy it to a new DACL.
  986. //
  987. if (fDaclPresent) {
  988. //
  989. // Copy the file's ACEs to the new ACL.
  990. //
  991. if (AclInfo.AceCount) {
  992. //See if the ACE is present in the end.
  993. if(!GetAce(pACL,AclInfo.AceCount -1, &pTempAce))
  994. {
  995. __leave;
  996. }
  997. if(((ACE_HEADER *)pTempAce)->AceType == ACCESS_ALLOWED_ACE_TYPE &&
  998. EqualSid((PSID)&(((ACCESS_ALLOWED_ACE*)pTempAce)->SidStart),pSid))
  999. {
  1000. //ACE is already present.
  1001. goto Done;
  1002. }
  1003. for (CurrentAceIndex = 0;
  1004. CurrentAceIndex < AclInfo.AceCount;
  1005. CurrentAceIndex++) {
  1006. //
  1007. // Get an ACE.
  1008. //
  1009. if(!GetAce(pACL, CurrentAceIndex, &pTempAce)) {
  1010. _TRACE(TRACE_DEBUGGING,L"GetAce() failed. Error %d\n",
  1011. GetLastError());
  1012. __leave;
  1013. }
  1014. //Keep checking if the ACE is already present.
  1015. if(((ACE_HEADER *)pTempAce)->AceType == ACCESS_ALLOWED_ACE_TYPE &&
  1016. EqualSid((PSID)&(((ACCESS_ALLOWED_ACE*)pTempAce)->SidStart),pSid))
  1017. {
  1018. //ACE is already present.
  1019. goto Done;
  1020. }
  1021. //
  1022. // Add the ACE to the new ACL.
  1023. //
  1024. if(!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
  1025. ((PACE_HEADER) pTempAce)->AceSize)) {
  1026. _TRACE(TRACE_DEBUGGING,L"AddAce() failed. Error %d\n",
  1027. GetLastError());
  1028. __leave;
  1029. }
  1030. }
  1031. }
  1032. }
  1033. //
  1034. // Add the access-allowed ACE to the new DACL.
  1035. //
  1036. if (!AddAccessAllowedAce(pNewACL, ACL_REVISION2, dwAccessMask,
  1037. pSid)) {
  1038. _TRACE(TRACE_DEBUGGING,L"AddAccessAllowedAce() failed. Error %d\n",
  1039. GetLastError());
  1040. __leave;
  1041. }
  1042. //
  1043. // Set the new DACL to the file SD.
  1044. //
  1045. if (!SetSecurityDescriptorDacl(pNewSD, TRUE, pNewACL,
  1046. FALSE)) {
  1047. _TRACE(TRACE_DEBUGGING,L"() failed. Error %d\n", GetLastError());
  1048. __leave;
  1049. }
  1050. //
  1051. // Set the SD to the File.
  1052. //
  1053. if (!SetFileSecurity(lpszFileName, DACL_SECURITY_INFORMATION,
  1054. pNewSD)) {
  1055. _TRACE(TRACE_DEBUGGING,L"SetFileSecurity() failed. Error %d\n",
  1056. GetLastError());
  1057. __leave;
  1058. }
  1059. Done:
  1060. fResult = TRUE;
  1061. } __finally {
  1062. //
  1063. // Free allocated memory
  1064. //
  1065. if (pFileSD)
  1066. heapfree(pFileSD);
  1067. if (pNewSD)
  1068. heapfree(pNewSD);
  1069. if (pNewACL)
  1070. heapfree(pNewACL);
  1071. }
  1072. return fResult;
  1073. }
  1074. /******************************************************************
  1075. * CreateTelnetClientsGroupAndSetPermissions()
  1076. * Creates a group called TelnetClients and sets permissions on cmd.exe
  1077. * to give Read+Execute rights to TelnetClients group.
  1078. * Parameters:
  1079. * None
  1080. * Return values:
  1081. * Boolean to return success or failure.
  1082. */
  1083. BOOL CreateTelnetClientsGroupAndSetPermissions()
  1084. {
  1085. LOCALGROUP_INFO_1 giTelnetGroup;
  1086. TCHAR wzGrpi1Name[GNLEN] = { 0 };
  1087. TCHAR wzGrpi1Comment[MAXCOMMENTSZ] = { 0 };
  1088. DWORD dwCount = MAX_PATH;
  1089. BOOL bRetVal = FALSE;
  1090. NET_API_STATUS success = NERR_Success;
  1091. PSID pSidTelnetClients = NULL;
  1092. WCHAR szApp[MAX_PATH+9] = { 0 }; //for "System32_path\\cmd.exe" + NULL
  1093. wcsncpy(wzGrpi1Name,TELNETCLIENTS_GROUP_NAME, GNLEN -1);
  1094. if (! LoadString(g_hInstRes, IDS_TELNETCLIENTS_GROUP_COMMENT, wzGrpi1Comment,
  1095. sizeof(wzGrpi1Comment) / sizeof(TCHAR)))
  1096. {
  1097. _tcsncpy(wzGrpi1Comment, TEXT("Members of this group have access to Telnet Server on this system."),MAXCOMMENTSZ-1);
  1098. }
  1099. giTelnetGroup.lgrpi1_name = wzGrpi1Name;
  1100. giTelnetGroup.lgrpi1_comment = wzGrpi1Comment;
  1101. success = NetLocalGroupAdd( NULL, 1, (LPBYTE)&giTelnetGroup, NULL);
  1102. if(success != NERR_Success && success != NERR_GroupExists && success != ERROR_ALIAS_EXISTS )
  1103. {
  1104. goto ExitOnError;
  1105. }
  1106. //Get TelnetClients Sid.
  1107. {
  1108. DWORD needed_length = 0;
  1109. DWORD dwErr = 0, dwDomainLen = 0;
  1110. SID_NAME_USE sidNameUse;
  1111. TCHAR szDomain[ MAX_PATH + 1 ];
  1112. BOOL success = FALSE;
  1113. TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1 + 14] = { 0 }; //+14 for '\TelnetClients'
  1114. DWORD dwNameLen = MAX_COMPUTERNAME_LENGTH + 1;
  1115. success = GetComputerName(szComputerName, &dwNameLen);
  1116. if(success)
  1117. {
  1118. _sntprintf(szComputerName+dwNameLen,(MAX_COMPUTERNAME_LENGTH + 14) - dwNameLen,_T("\\%s"),TELNETCLIENTS_GROUP_NAME);
  1119. }
  1120. LookupAccountName( NULL, szComputerName, pSidTelnetClients, &needed_length,
  1121. szDomain, &dwDomainLen, &sidNameUse );
  1122. pSidTelnetClients = ( PSID ) new UCHAR[ needed_length ];
  1123. if(pSidTelnetClients == NULL)
  1124. {
  1125. _TRACE(TRACE_DEBUGGING,L"Allocation for pSidTelnetClients failed in CreateTelnetClientsGroupAndSetPermissions");
  1126. goto ExitOnError;
  1127. }
  1128. //Even if if allocation fails just go ahead.
  1129. success = LookupAccountName( NULL, szComputerName, pSidTelnetClients, &needed_length,
  1130. szDomain, &dwDomainLen, &sidNameUse );
  1131. if( !success )
  1132. {
  1133. _TRACE(TRACE_DEBUGGING,L"LookupAccountName failed in CreateTelnetClientsGroupAnd... with %d",GetLastError());
  1134. goto ExitOnError;
  1135. }
  1136. }
  1137. if(!GetSystemDirectory(szApp,MAX_PATH+1))
  1138. {
  1139. goto ExitOnError;
  1140. }
  1141. wcsncat(szApp,L"\\cmd.exe",8);
  1142. bRetVal = AddAccessRights(pSidTelnetClients, (LPCWSTR)szApp, FILE_EXECUTE | FILE_READ_DATA |
  1143. FILE_READ_ATTRIBUTES |
  1144. FILE_READ_EA |
  1145. STANDARD_RIGHTS_READ |
  1146. SYNCHRONIZE);
  1147. ExitOnError:
  1148. if (pSidTelnetClients)
  1149. {
  1150. delete pSidTelnetClients;
  1151. pSidTelnetClients = NULL;
  1152. }
  1153. return bRetVal;
  1154. }
  1155. HRESULT
  1156. CServiceModule::RegisterServer
  1157. (
  1158. BOOL bRegTypeLib,
  1159. BOOL bService
  1160. )
  1161. {
  1162. HRESULT hr = CoInitialize(NULL);
  1163. if (FAILED(hr))
  1164. return hr;
  1165. if( IsInstalled() )
  1166. {
  1167. if( IsThatMe() )
  1168. {
  1169. //This is needed because it is possible to call tlntsvr /Service
  1170. //multiple times from commandline
  1171. return S_OK;
  1172. }
  1173. //Set the service keys point to self
  1174. if( !SetServiceConfigToSelf( m_szServiceName ) )
  1175. {
  1176. //Let the latest version run
  1177. return S_OK;
  1178. }
  1179. else
  1180. {
  1181. //Set the service keys point to self
  1182. if( !SetServiceConfigToSelf( m_szServiceName ) )
  1183. {
  1184. if (! LoadString(g_hInstRes, IDS_ERR_CONFIG_SVC, g_szErrRegDelete,
  1185. sizeof(g_szErrRegDelete) / sizeof(g_szErrRegDelete[0])))
  1186. {
  1187. lstrcpy(g_szErrRegDelete, TEXT(""));
  1188. }
  1189. }
  1190. }
  1191. }
  1192. if(!CreateTelnetClientsGroupAndSetPermissions())
  1193. return E_FAIL;
  1194. // Add service entries
  1195. UpdateRegistryFromResource(IDR_TlntSvr, TRUE);
  1196. // Adjust the AppID for Local Server or Service
  1197. CRegKey keyAppID;
  1198. LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"));
  1199. if (lRes != ERROR_SUCCESS)
  1200. return lRes;
  1201. CRegKey key;
  1202. lRes = key.Open( keyAppID, APPID );
  1203. if (lRes != ERROR_SUCCESS)
  1204. return lRes;
  1205. key.DeleteValue(_T("LocalService"));
  1206. HKEY hk = NULL;
  1207. WCHAR szAccnt[_MAX_PATH+1];
  1208. LPWSTR pszAccount = NULL, pszPassword = NULL;
  1209. WCHAR szDomainName[_MAX_PATH+1];
  1210. DWORD dwAccntSize = _MAX_PATH, dwDomainNameSize = _MAX_PATH;
  1211. WCHAR szFullAccountName[_MAX_PATH*2 + 2] = { 0 }; // 3 for '\' and NULL.
  1212. SID_NAME_USE sid_name_use;
  1213. LPWSTR szPasswd = L"";
  1214. if(!TnInitializeStandardSids())
  1215. return FALSE;
  1216. if(!LookupAccountSid(NULL,localLocalSid,szAccnt,&dwAccntSize,szDomainName,&dwDomainNameSize,&sid_name_use))
  1217. {
  1218. // If error is ERROR_NONE_MAPPED, the account is not present.
  1219. // Probably we are running W2k or NT4.
  1220. // the service will run as local system.
  1221. if(GetLastError() != ERROR_NONE_MAPPED)
  1222. {
  1223. TnFreeStandardSids();
  1224. return E_FAIL;
  1225. }
  1226. }
  1227. else
  1228. {
  1229. _snwprintf(szFullAccountName,MAX_PATH*2+1,L"NT AUTHORITY\\LocalService");
  1230. pszAccount = szFullAccountName; // Name of the Local Service account
  1231. pszPassword = szPasswd; //Empty String
  1232. }
  1233. TnFreeStandardSids();
  1234. if (bService)
  1235. {
  1236. key.SetValue(_T("TlntSvr"), _T("LocalService"));
  1237. key.SetValue(_T("-Service -From_DCOM"), _T("ServiceParameters"));
  1238. // Create service
  1239. Install(pszAccount,pszPassword);
  1240. }
  1241. keyAppID.Close();
  1242. key.Close();
  1243. // Add object entries
  1244. hr = CComModule::RegisterServer(bRegTypeLib);
  1245. CoUninitialize();
  1246. //register the message resource
  1247. if(bService)
  1248. {
  1249. // Add event log info
  1250. CRegKey eventLog;
  1251. TCHAR local_key[_MAX_PATH];
  1252. lstrcpy( local_key, _T("SYSTEM\\CurrentControlSet\\Services\\EventLog"
  1253. _T("\\Application\\"))); // NO, BO, Baskar.
  1254. TCHAR szModule[_MAX_PATH];
  1255. GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH);
  1256. TCHAR szResModule[_MAX_PATH*2];
  1257. DWORD len = GetModuleFileName(g_hInstRes, szResModule, _MAX_PATH);
  1258. OSVERSIONINFOEX osvi = { 0 };
  1259. WCHAR szSysDir[MAX_PATH+1] = {0};
  1260. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  1261. if ( !GetVersionEx((OSVERSIONINFO *) &osvi ) )
  1262. {
  1263. //OSVERSIONINFOEX is supported from NT4 SP6 on. So GetVerEx() should succeed.
  1264. return E_FAIL;
  1265. }
  1266. //Check if the OS is XPSP, in that case, we need to append the xpspresdll name to
  1267. //eventmessagefile value in HKLM\system\...\eventlog\tlntsvr.
  1268. //The event message will first be searched in szResModule and then in xpsp1res.dll
  1269. if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.wProductType == VER_NT_WORKSTATION && osvi.wServicePackMajor > 0)
  1270. {
  1271. //OS is Windows XP.
  1272. if(!GetSystemDirectory(szSysDir,MAX_PATH+1))
  1273. {
  1274. _tcsncpy(szSysDir,L"%SYSTEMROOT%\\system32",MAX_PATH);
  1275. }
  1276. _snwprintf(szResModule+len,(_MAX_PATH*2)-len-1,L";%s\\xpsp1res.dll",szSysDir);
  1277. }
  1278. TCHAR szName[_MAX_FNAME];
  1279. _tsplitpath( szModule, NULL, NULL, szName, NULL);
  1280. lstrcat(local_key, szName); // NO overflow, Baskar
  1281. LONG result = eventLog.Create(HKEY_LOCAL_MACHINE, local_key);
  1282. if( ERROR_SUCCESS != result)
  1283. return result;
  1284. result = eventLog.SetValue(szResModule, _T("EventMessageFile"));
  1285. if(ERROR_SUCCESS != result)
  1286. return result;
  1287. DWORD dwTypes = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
  1288. EVENTLOG_INFORMATION_TYPE | EVENTLOG_AUDIT_SUCCESS |
  1289. EVENTLOG_AUDIT_FAILURE;
  1290. result = eventLog.SetValue(dwTypes, _T("TypesSupported"));
  1291. if(ERROR_SUCCESS != result)
  1292. return result;
  1293. eventLog.Close();
  1294. SC_HANDLE hService = NULL, hSCM = NULL;
  1295. TCHAR szServiceDesc[ _MAX_PATH * 2 ];
  1296. DWORD dwData = 0;
  1297. DWORD dwTag = 0;
  1298. DWORD dwDisp = 0;
  1299. if( (result = TnSecureRegCreateKeyEx( HKEY_LOCAL_MACHINE, REG_SERVICE_KEY, NULL, NULL,
  1300. REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED , NULL, &hk, &dwDisp, 0 )) == ERROR_SUCCESS )
  1301. {
  1302. LPWSTR pszCreateInitially = NULL;
  1303. if(LoadString(_Module.GetResourceInstance(),
  1304. IDS_SERVICE_DESCRIPTION,
  1305. szServiceDesc,
  1306. sizeof(szServiceDesc) / sizeof(TCHAR)))
  1307. {
  1308. if( !GetRegistryString( hk, NULL, L"Description", &pszCreateInitially,
  1309. szServiceDesc,TRUE ) )
  1310. {
  1311. RegCloseKey(hk);
  1312. return E_FAIL;
  1313. }
  1314. RegCloseKey(hk);
  1315. }
  1316. else
  1317. {
  1318. RegCloseKey(hk);
  1319. return E_FAIL;
  1320. }
  1321. }
  1322. else
  1323. {
  1324. return E_FAIL;
  1325. }
  1326. hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE |
  1327. SC_MANAGER_ENUMERATE_SERVICE | MAXIMUM_ALLOWED );
  1328. if (hSCM != NULL)
  1329. {
  1330. hService = ::OpenService(hSCM, m_szServiceName,
  1331. SERVICE_CHANGE_CONFIG );
  1332. if (hService == NULL)
  1333. {
  1334. result = E_FAIL;
  1335. ::CloseServiceHandle(hSCM);
  1336. return result;
  1337. }
  1338. if(!ChangeServiceConfig(hService,SERVICE_NO_CHANGE,SERVICE_NO_CHANGE,
  1339. SERVICE_ERROR_NORMAL,NULL,NULL,
  1340. NULL,DEFAULT_SERVICE_DEPENDENCY,
  1341. pszAccount,pszPassword,SERVICE_DISPLAY_NAME))
  1342. {
  1343. result = E_FAIL;
  1344. }
  1345. ::CloseServiceHandle(hService);
  1346. ::CloseServiceHandle(hSCM);
  1347. }
  1348. else
  1349. {
  1350. return result;
  1351. }
  1352. }
  1353. //Create HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\TelnetServer key and it's values.
  1354. if( !CreateRegistryEntriesIfNotPresent( ) )
  1355. {
  1356. return E_FAIL;
  1357. }
  1358. return hr;
  1359. }
  1360. HRESULT
  1361. CServiceModule::UnregisterServer()
  1362. {
  1363. DWORD dwError = 0;
  1364. HRESULT hr = CoInitialize(NULL);
  1365. if (FAILED(hr))
  1366. return hr;
  1367. // Remove service entries
  1368. UpdateRegistryFromResource(IDR_TlntSvr, FALSE);
  1369. // Remove service
  1370. Uninstall();
  1371. // Remove object entries
  1372. CComModule::UnregisterServer();
  1373. //This is so that reg key related to typelib gets deleted
  1374. (void)UnRegisterTypeLib(LIBID_TLNTSVRLib, 1, 0, LOCALE_NEUTRAL, SYS_WIN32); // Stop prefast from reporting an error.
  1375. //remove telnet specific registry entries
  1376. //RegDeleteKey is returning ERROR_INVALID_FUNCTION in the absence of the key
  1377. RegDeleteKey( HKEY_LOCAL_MACHINE, ( READ_CONFIG_KEY ) );
  1378. RegDeleteKey( HKEY_LOCAL_MACHINE, ( REG_PARAMS_KEY ) );
  1379. RegDeleteKey( HKEY_LOCAL_MACHINE, ( REG_DEFAULTS_KEY ) );
  1380. RegDeleteKey( HKEY_LOCAL_MACHINE, ( REG_SERVER_KEY ) );
  1381. RegDeleteKey( HKEY_CLASSES_ROOT, ( APPID ) );
  1382. RegDeleteKey( HKEY_LOCAL_MACHINE, _T( "System\\CurrentControlSet\\Services\\EventLog\\Application\\TlntSvr" ) );
  1383. LPWSTR lpszKey = NULL;
  1384. if( FormTlntSessKeyForCmd( &lpszKey ) )
  1385. {
  1386. if( ( dwError = RegDeleteKey( HKEY_USERS, lpszKey)) != ERROR_SUCCESS
  1387. && ( dwError != ERROR_INVALID_FUNCTION ) )
  1388. {
  1389. //do nothing
  1390. }
  1391. delete [] lpszKey;
  1392. }
  1393. //The following key is not created by this program. But by tlntsvr.rgs
  1394. //I couldn't delete this in any other way. So, manually deleting it
  1395. RegDeleteKey( HKEY_CLASSES_ROOT, _T( "AppID\\TlntSvr.Exe" ) );
  1396. CoUninitialize();
  1397. return S_OK;
  1398. }
  1399. void
  1400. CServiceModule::Init
  1401. (
  1402. _ATL_OBJMAP_ENTRY* p,
  1403. HINSTANCE h,
  1404. UINT nServiceNameID
  1405. )
  1406. {
  1407. CComModule::Init(p, h);
  1408. m_bService = TRUE;
  1409. if (! LoadString(h, nServiceNameID, m_szServiceName,
  1410. sizeof(m_szServiceName) / sizeof(TCHAR)))
  1411. {
  1412. lstrcpy(m_szServiceName, TEXT(""));
  1413. }
  1414. if (! LoadString(h, IDS_ERR_REG_DELETE, g_szErrRegDelete,
  1415. sizeof(g_szErrRegDelete) / sizeof(TCHAR)))
  1416. {
  1417. lstrcpy(g_szErrRegDelete, TEXT(""));
  1418. }
  1419. if (! LoadString(h, IDS_ERR_OPEN_SCM, g_szErrOpenSCM,
  1420. sizeof(g_szErrOpenSCM) / sizeof(TCHAR)))
  1421. {
  1422. lstrcpy(g_szErrOpenSCM, TEXT(""));
  1423. }
  1424. if (! LoadString(h, IDS_ERR_CREATE_SVC, g_szErrCreateSvc,
  1425. sizeof(g_szErrCreateSvc) / sizeof(TCHAR)))
  1426. {
  1427. lstrcpy(g_szErrCreateSvc, TEXT(""));
  1428. }
  1429. if (! LoadString(h, IDS_ERR_OPEN_SVC, g_szErrOpenSvc,
  1430. sizeof(g_szErrOpenSvc) / sizeof(TCHAR)))
  1431. {
  1432. lstrcpy(g_szErrOpenSvc, TEXT(""));
  1433. }
  1434. if (! LoadString(h, IDS_ERR_DELETE_SVC, g_szErrDeleteSvc,
  1435. sizeof(g_szErrDeleteSvc) / sizeof(TCHAR)))
  1436. {
  1437. lstrcpy(g_szErrDeleteSvc, TEXT(""));
  1438. }
  1439. if (! LoadString(h, IDS_MAX_CONNECTIONS_REACHED, g_szMaxConnectionsReached,
  1440. sizeof(g_szMaxConnectionsReached) / sizeof(TCHAR)))
  1441. {
  1442. lstrcpy(g_szMaxConnectionsReached, TEXT(""));
  1443. }
  1444. if (! LoadString(h, IDS_LICENSE_LIMIT_REACHED, g_szLicenseLimitReached,
  1445. sizeof(g_szLicenseLimitReached) / sizeof(TCHAR)))
  1446. {
  1447. lstrcpy(g_szLicenseLimitReached, TEXT(""));
  1448. }
  1449. // set up the initial service status
  1450. m_hServiceStatus = NULL;
  1451. m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  1452. m_status.dwCurrentState = SERVICE_STOPPED;
  1453. m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  1454. SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;
  1455. m_status.dwWin32ExitCode = 0;
  1456. m_status.dwServiceSpecificExitCode = 0;
  1457. m_status.dwCheckPoint = 0;
  1458. m_status.dwWaitHint = 0;
  1459. }
  1460. LONG
  1461. CServiceModule::Unlock()
  1462. {
  1463. LONG x = CComModule::Unlock();
  1464. // May be Telnet server has to shutdown
  1465. // if (l == 0 && !m_bService)
  1466. // PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
  1467. return x;
  1468. }
  1469. BOOL
  1470. CServiceModule::IsInstalled()
  1471. {
  1472. BOOL bResult = FALSE;
  1473. SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE |
  1474. SC_MANAGER_ENUMERATE_SERVICE | MAXIMUM_ALLOWED );
  1475. if (hSCM != NULL)
  1476. {
  1477. SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName,
  1478. SERVICE_QUERY_CONFIG);
  1479. if (hService != NULL)
  1480. {
  1481. bResult = TRUE;
  1482. ::CloseServiceHandle(hService);
  1483. }
  1484. ::CloseServiceHandle(hSCM);
  1485. }
  1486. return bResult;
  1487. }
  1488. BOOL
  1489. CServiceModule::Install(LPWSTR pszAccount, LPWSTR pszPassword)
  1490. {
  1491. if (IsInstalled())
  1492. return TRUE;
  1493. SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE |
  1494. SC_MANAGER_ENUMERATE_SERVICE | MAXIMUM_ALLOWED );
  1495. if (hSCM == NULL)
  1496. {
  1497. MessageBox(NULL, g_szErrOpenSCM, m_szServiceName, MB_OK);
  1498. return FALSE;
  1499. }
  1500. // Get the executable file path
  1501. TCHAR szFilePath[_MAX_PATH + 1] = { 0 };
  1502. ::GetModuleFileName(NULL, szFilePath, _MAX_PATH);
  1503. SC_HANDLE hService = ::CreateService(hSCM, m_szServiceName,
  1504. SERVICE_DISPLAY_NAME, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
  1505. g_dwStartType, SERVICE_ERROR_NORMAL, szFilePath, NULL, NULL,
  1506. DEFAULT_SERVICE_DEPENDENCY,pszAccount,pszPassword);
  1507. if (hService == NULL)
  1508. {
  1509. ::CloseServiceHandle(hSCM);
  1510. MessageBox(NULL, g_szErrCreateSvc, m_szServiceName, MB_OK);
  1511. return FALSE;
  1512. }
  1513. ::CloseServiceHandle(hService);
  1514. ::CloseServiceHandle(hSCM);
  1515. return TRUE;
  1516. }
  1517. BOOL
  1518. CServiceModule::Uninstall()
  1519. {
  1520. if (!IsInstalled())
  1521. return TRUE;
  1522. SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE |
  1523. SC_MANAGER_ENUMERATE_SERVICE | MAXIMUM_ALLOWED );
  1524. if (hSCM == NULL)
  1525. {
  1526. MessageBox(NULL, g_szErrOpenSCM, m_szServiceName, MB_OK);
  1527. return FALSE;
  1528. }
  1529. SC_HANDLE hService = ::OpenService(
  1530. hSCM, m_szServiceName, SERVICE_STOP | DELETE);
  1531. if (hService == NULL)
  1532. {
  1533. ::CloseServiceHandle(hSCM);
  1534. MessageBox(NULL, g_szErrOpenSvc, m_szServiceName, MB_OK);
  1535. return FALSE;
  1536. }
  1537. SERVICE_STATUS status;
  1538. ::ControlService(hService, SERVICE_CONTROL_STOP, &status);
  1539. BOOL bDelete = ::DeleteService(hService);
  1540. ::CloseServiceHandle(hService);
  1541. ::CloseServiceHandle(hSCM);
  1542. if (bDelete)
  1543. return TRUE;
  1544. MessageBox(NULL, g_szErrDeleteSvc, m_szServiceName, MB_OK);
  1545. return FALSE;
  1546. }
  1547. ////////////////////////////////////////////////////////////////////////////////
  1548. // Logging functions
  1549. void
  1550. LogEvent
  1551. (
  1552. WORD wType,
  1553. DWORD dwEventID,
  1554. LPCTSTR pFormat,
  1555. ...
  1556. )
  1557. {
  1558. #define CHARS_TO_LOG 1024
  1559. TCHAR chMsg[CHARS_TO_LOG] = { 0 };
  1560. LPTSTR lpszStrings[1] = { chMsg };
  1561. INT format_length = lstrlen(pFormat);
  1562. if (format_length < CHARS_TO_LOG)
  1563. {
  1564. va_list pArg;
  1565. va_start(pArg, pFormat);
  1566. _vsntprintf(chMsg, CHARS_TO_LOG - 1, pFormat, pArg);
  1567. va_end(pArg);
  1568. }
  1569. else
  1570. {
  1571. _sntprintf(chMsg, CHARS_TO_LOG - 1, TEXT("TLNTSVR: Too long a format string to log, Length == %d"), format_length);
  1572. }
  1573. if (_Module.m_bService)
  1574. {
  1575. LogToTlntsvrLog( _Module.m_hEventSource, wType, dwEventID,
  1576. (LPCTSTR*) &lpszStrings[0] );
  1577. }
  1578. else
  1579. {
  1580. // As we are not running as a service, just write the error to the
  1581. //console.
  1582. _putts(chMsg);
  1583. }
  1584. #undef CHARS_TO_LOG
  1585. }
  1586. ///////////////////////////////////////////////////////////////////////////////
  1587. // Service startup and registration
  1588. void
  1589. CServiceModule::Start()
  1590. {
  1591. SERVICE_TABLE_ENTRY st[] =
  1592. {
  1593. { m_szServiceName, _ServiceMain },
  1594. { NULL, NULL }
  1595. };
  1596. if (m_bService)
  1597. {
  1598. if (! ::StartServiceCtrlDispatcher(st))
  1599. {
  1600. m_bService = FALSE;
  1601. }
  1602. }
  1603. if (m_bService == FALSE)
  1604. Run();
  1605. }
  1606. void
  1607. CServiceModule::ServiceMain
  1608. (
  1609. DWORD dwArgc,
  1610. LPTSTR* lpszArgv
  1611. )
  1612. {
  1613. // DebugBreak();
  1614. // Register the control request handler
  1615. m_status.dwCurrentState = SERVICE_START_PENDING;
  1616. m_hServiceStatus = RegisterServiceCtrlHandler(m_szServiceName, _Handler);
  1617. if (m_hServiceStatus == NULL)
  1618. {
  1619. LogEvent(EVENTLOG_ERROR_TYPE, 0, _T("Handler not installed"));
  1620. return;
  1621. }
  1622. // DebugBreak();
  1623. SetServiceStatus(SERVICE_START_PENDING);
  1624. m_status.dwWin32ExitCode = S_OK;
  1625. m_status.dwCheckPoint = 0;
  1626. m_status.dwWaitHint = 0;
  1627. //
  1628. // Security bug fix: When the CLSID of telnet object is
  1629. // embedded into a web page then DCOM is starting up
  1630. // the service. To disable this from happening the fix
  1631. // we did was to put in a new command line switch in
  1632. // ServiceParameters under the HKCR\AppID\{FE9E4896-A014-11D1-855C-00A0C944138C}\ServiceParameters
  1633. // key. This switch is "-From_DCOM". This will tell us when
  1634. // IE is starting the service versus when the service
  1635. // is started via net.exe or tlntadmn.exe. If IE is starting
  1636. // the service then we immediately exit.
  1637. //
  1638. for (DWORD dwIndex =1; dwIndex < dwArgc; ++dwIndex)
  1639. {
  1640. if (!_tcsicmp(lpszArgv[dwIndex], TEXT("-From_DCOM")) ||
  1641. !_tcsicmp(lpszArgv[dwIndex], TEXT("/From_DCOM")))
  1642. {
  1643. goto ExitOnIEInstantiation;
  1644. }
  1645. }
  1646. // DebugBreak();
  1647. // When the Run function returns, the service has stopped.
  1648. Run();
  1649. LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SHUTDOWN, _T("Service stopped"));
  1650. ExitOnIEInstantiation:
  1651. DeregisterEventSource(_Module.m_hEventSource);
  1652. SetServiceStatus( SERVICE_STOPPED );
  1653. }
  1654. void
  1655. CServiceModule::Handler
  1656. (
  1657. DWORD dwOpcode
  1658. )
  1659. {
  1660. switch (dwOpcode)
  1661. {
  1662. case SERVICE_CONTROL_STOP:
  1663. g_pTelnetService->Shutdown();
  1664. SetServiceStatus(SERVICE_STOP_PENDING);
  1665. break;
  1666. case SERVICE_CONTROL_PAUSE:
  1667. SetServiceStatus(SERVICE_PAUSE_PENDING);
  1668. g_pTelnetService->Pause();
  1669. SetServiceStatus(SERVICE_PAUSED);
  1670. break;
  1671. case SERVICE_CONTROL_CONTINUE:
  1672. SetServiceStatus(SERVICE_CONTINUE_PENDING);
  1673. g_pTelnetService->Resume();
  1674. SetServiceStatus(SERVICE_RUNNING);
  1675. break;
  1676. case SERVICE_CONTROL_INTERROGATE:
  1677. break;
  1678. case SERVICE_CONTROL_SHUTDOWN:
  1679. g_pTelnetService->SystemShutdown();
  1680. break;
  1681. default:
  1682. LogEvent(EVENTLOG_WARNING_TYPE, 0, _T("Bad service request"));
  1683. break;
  1684. }
  1685. }
  1686. void
  1687. WINAPI
  1688. CServiceModule::_ServiceMain
  1689. (
  1690. DWORD dwArgc,
  1691. LPTSTR* lpszArgv
  1692. )
  1693. {
  1694. _Module.ServiceMain(dwArgc, lpszArgv);
  1695. }
  1696. void
  1697. WINAPI
  1698. CServiceModule::_Handler
  1699. (
  1700. DWORD dwOpcode
  1701. )
  1702. {
  1703. _Module.Handler(dwOpcode);
  1704. }
  1705. void
  1706. CServiceModule::SetServiceStatus
  1707. (
  1708. DWORD dwState
  1709. )
  1710. {
  1711. m_status.dwCurrentState = dwState;
  1712. ::SetServiceStatus(m_hServiceStatus, &m_status);
  1713. }
  1714. HRESULT SetSecurityForTheComObject()
  1715. {
  1716. HRESULT hr = S_FALSE;
  1717. PSID pSidAdministrators = NULL;
  1718. int aclSize = 0;
  1719. PACL newACL = NULL;
  1720. SECURITY_DESCRIPTOR sd;
  1721. {
  1722. SID_IDENTIFIER_AUTHORITY local_system_authority = SECURITY_NT_AUTHORITY;
  1723. //Build administrators alias sid
  1724. if (! AllocateAndInitializeSid(
  1725. &local_system_authority,
  1726. 2, /* there are only two sub-authorities */
  1727. SECURITY_BUILTIN_DOMAIN_RID,
  1728. DOMAIN_ALIAS_RID_ADMINS,
  1729. 0,0,0,0,0,0, /* Don't care about the rest */
  1730. &pSidAdministrators
  1731. ))
  1732. {
  1733. goto Done;
  1734. }
  1735. }
  1736. aclSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pSidAdministrators) - sizeof(DWORD);
  1737. newACL = (PACL) new BYTE[aclSize];
  1738. if (newACL == NULL)
  1739. {
  1740. goto Done;
  1741. }
  1742. if (!InitializeAcl(newACL, aclSize, ACL_REVISION))
  1743. {
  1744. goto Done;
  1745. }
  1746. if (!AddAccessAllowedAce(newACL, ACL_REVISION, (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER), pSidAdministrators))
  1747. {
  1748. goto Done;
  1749. }
  1750. if( !InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION ) )
  1751. {
  1752. goto Done;
  1753. }
  1754. if( !SetSecurityDescriptorDacl(&sd, TRUE, newACL, FALSE) )
  1755. {
  1756. goto Done;
  1757. }
  1758. if( !SetSecurityDescriptorOwner(&sd, pSidAdministrators, FALSE ) )
  1759. {
  1760. goto Done;
  1761. }
  1762. if( !SetSecurityDescriptorGroup(&sd, pSidAdministrators, FALSE) )
  1763. {
  1764. goto Done;
  1765. }
  1766. // DebugBreak();
  1767. hr = CoInitializeSecurity(
  1768. &sd,
  1769. -1, // Let COM choose it
  1770. NULL, // -do-
  1771. NULL,
  1772. RPC_C_AUTHN_LEVEL_PKT,
  1773. RPC_C_IMP_LEVEL_IMPERSONATE,
  1774. NULL,
  1775. EOAC_NONE,
  1776. NULL
  1777. );
  1778. Done:
  1779. if( pSidAdministrators != NULL )
  1780. {
  1781. FreeSid (pSidAdministrators );
  1782. }
  1783. if( newACL )
  1784. {
  1785. delete[] newACL;
  1786. }
  1787. return hr;
  1788. }
  1789. void
  1790. CServiceModule::Run()
  1791. {
  1792. HRESULT hr;
  1793. HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED );
  1794. _ASSERTE(SUCCEEDED(hRes));
  1795. if( SetSecurityForTheComObject( ) != S_OK )
  1796. {
  1797. m_status.dwWin32ExitCode = ERROR_ACCESS_DENIED;
  1798. SetServiceStatus( SERVICE_STOPPED );
  1799. //log the failure and return;
  1800. goto Done;
  1801. }
  1802. hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER,
  1803. REGCLS_MULTIPLEUSE);
  1804. _ASSERTE(SUCCEEDED(hr));
  1805. if( !TelnetServiceThread( ) )
  1806. {
  1807. m_status.dwWin32ExitCode = ERROR_INVALID_DATA;
  1808. SetServiceStatus( SERVICE_STOPPED );
  1809. }
  1810. _Module.RevokeClassObjects();
  1811. Done:
  1812. CoUninitialize();
  1813. }
  1814. int __cdecl NoMoreMemory( size_t size )
  1815. {
  1816. int NO_MORE_MEMORY = 1;
  1817. size=size;
  1818. _chASSERT(NO_MORE_MEMORY != 1);
  1819. LogEvent( EVENTLOG_ERROR_TYPE, MSG_NOMOREMEMORY, _T(" ") );
  1820. ExitProcess( 1 );
  1821. return( 0 );
  1822. }
  1823. /////////////////////////////////////////////////////////////////////////////
  1824. //
  1825. extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
  1826. HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
  1827. {
  1828. // DebugBreak();
  1829. // _set_new_handler( NoMoreMemory );
  1830. // We do not really care about the return value.
  1831. // because g_hInstRes will get the value hInstance in case of any failure
  1832. HrLoadLocalizedLibrarySFU(hInstance, L"TLNTSVRR.DLL", &g_hInstRes, NULL);
  1833. lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT
  1834. _Module.Init(ObjectMap, g_hInstRes, IDS_SERVICENAME);
  1835. _Module.m_bService = TRUE;
  1836. // Get a handle to use with ReportEvent().
  1837. _Module.m_hEventSource = RegisterEventSource(NULL, _Module.m_szServiceName);
  1838. TCHAR szTokens[] = _T("-/");
  1839. LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
  1840. while (lpszToken != NULL)
  1841. {
  1842. if (_tcsicmp(lpszToken, _T("UnregServer"))==0)
  1843. return _Module.UnregisterServer();
  1844. // Register as Local Server
  1845. if (_tcsicmp(lpszToken, _T("RegServer"))==0)
  1846. return _Module.RegisterServer(TRUE, FALSE);
  1847. // Register as Service
  1848. if (_tcsicmp(lpszToken, _T("Service"))==0)
  1849. return _Module.RegisterServer(TRUE, TRUE);
  1850. lpszToken = FindOneOf(lpszToken, szTokens);
  1851. }
  1852. OSVERSIONINFOEX osvi = { 0 };
  1853. WCHAR szSysDir[MAX_PATH+1] = {0};
  1854. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  1855. if ( !GetVersionEx((OSVERSIONINFO *) &osvi ) )
  1856. {
  1857. //OSVERSIONINFOEX is supported from NT4 SP6 on. So GetVerEx() should succeed.
  1858. return E_FAIL;
  1859. }
  1860. if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.wProductType == VER_NT_WORKSTATION && osvi.wServicePackMajor > 0)
  1861. {
  1862. //OS is Windows XP.
  1863. // Add event log info
  1864. CRegKey eventLog;
  1865. TCHAR local_key[_MAX_PATH];
  1866. lstrcpy( local_key, _T("SYSTEM\\CurrentControlSet\\Services\\EventLog"
  1867. _T("\\Application\\"))); // NO, BO, Baskar.
  1868. TCHAR szModule[_MAX_PATH + 1] = { 0 };
  1869. GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH);
  1870. TCHAR szResModule[(_MAX_PATH*2) +2];
  1871. DWORD len = GetModuleFileName(g_hInstRes, szResModule, _MAX_PATH);
  1872. //Check if the OS is XPSP, in that case, we need to append the xpspresdll name to
  1873. //eventmessagefile value in HKLM\system\...\eventlog\tlntsvr.
  1874. //The event message will first be searched in szResModule and then in xpsp1res.dll
  1875. if(!GetSystemDirectory(szSysDir,MAX_PATH+1))
  1876. {
  1877. _tcsncpy(szSysDir,L"%SYSTEMROOT%\\system32",MAX_PATH);
  1878. }
  1879. _snwprintf(szResModule+len,(_MAX_PATH*2)-len-1,L";%s\\xpsp1res.dll",szSysDir);
  1880. TCHAR szName[_MAX_FNAME];
  1881. _tsplitpath( szModule, NULL, NULL, szName, NULL);
  1882. lstrcat(local_key, szName); // NO overflow, Baskar
  1883. LONG result = eventLog.Create(HKEY_LOCAL_MACHINE, local_key);
  1884. if( ERROR_SUCCESS != result)
  1885. return result;
  1886. result = eventLog.SetValue(szResModule, _T("EventMessageFile"));
  1887. if(ERROR_SUCCESS != result)
  1888. return result;
  1889. DWORD dwTypes = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
  1890. EVENTLOG_INFORMATION_TYPE | EVENTLOG_AUDIT_SUCCESS |
  1891. EVENTLOG_AUDIT_FAILURE;
  1892. result = eventLog.SetValue(dwTypes, _T("TypesSupported"));
  1893. if(ERROR_SUCCESS != result)
  1894. return result;
  1895. eventLog.Close();
  1896. }
  1897. #ifndef NO_PCHECK
  1898. #ifndef WHISTLER_BUILD
  1899. if( ! IsLicensedCopy() )
  1900. {
  1901. LogEvent(EVENTLOG_ERROR_TYPE, MSG_LICENSEEXPIRED, _T(" "));
  1902. return 1;
  1903. }
  1904. #endif
  1905. #endif
  1906. // Are we Service or Local Server
  1907. CRegKey keyAppID;
  1908. LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"),MAXIMUM_ALLOWED);
  1909. if (lRes != ERROR_SUCCESS)
  1910. return lRes;
  1911. CRegKey key;
  1912. lRes = key.Open( keyAppID, APPID,MAXIMUM_ALLOWED );
  1913. if (lRes != ERROR_SUCCESS)
  1914. return lRes;
  1915. TCHAR szValue[_MAX_PATH];
  1916. DWORD dwLen = _MAX_PATH;
  1917. lRes = key.QueryValue(szValue, _T("LocalService"), &dwLen);
  1918. keyAppID.Close();
  1919. key.Close();
  1920. _Module.m_bService = FALSE;
  1921. if (lRes == ERROR_SUCCESS)
  1922. _Module.m_bService = TRUE;
  1923. #if _DEBUG || DBG
  1924. CDebugLogger::Init( TRACE_DEBUGGING, "C:\\temp\\TlntSvr.log" );
  1925. #endif
  1926. // DebugBreak();
  1927. _Module.Start();
  1928. #if _DEBUG || DBG
  1929. CDebugLogger::ShutDown();
  1930. #endif
  1931. // When we get here, the service has been stopped
  1932. return _Module.m_status.dwWin32ExitCode;
  1933. }