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.

2195 lines
77 KiB

  1. //-------------------------------------------------------------------
  2. // Copyright (c) 1999-2000 Microsoft Corporation
  3. //
  4. // tnadminutils.cpp
  5. //
  6. // Vikram/Manoj Jain/Srivatsan K/Harendra
  7. //
  8. // Functions to do administration of telnet daemon.
  9. // (May-2000)
  10. //-------------------------------------------------------------------
  11. #include "telnet.h"
  12. #include "common.h"
  13. #include "resource.h" //resource.h should be before any other .h file that has resource ids.
  14. #include "admutils.h"
  15. #include <stdio.h>
  16. #include <conio.h>
  17. #include <tchar.h>
  18. #include <shlwapi.h>
  19. #include <wbemidl.h>
  20. #include <wchar.h>
  21. #include <windns.h>
  22. #include <winnlsp.h>
  23. #include "tnadminy.h"
  24. //this file has utility functions to set authentication...
  25. #include "tlntsvr.h"
  26. #define L_TELNETSERVER_TEXT "tlntsvr"
  27. #define MAX_VALUE_MAXCONN 2147483647
  28. //Global variables
  29. wchar_t* g_arCLASSname[ _MAX_CLASS_NAMES_ ];
  30. //array to store the different class object paths
  31. HKEY g_arCLASShkey[_MAX_CLASS_NAMES_];
  32. HKEY g_hkeyHKLM=NULL;
  33. int g_arNUM_PROPNAME[_MAX_PROPS_];
  34. WCHAR g_szMsg[MAX_BUFFER_SIZE] = {0} ;
  35. HMODULE g_hResource;
  36. HANDLE g_stdout;
  37. extern HMODULE g_hXPResource;
  38. BOOL g_fWhistler = FALSE;
  39. // Don't even think about changing the two strings -- BaskarK, they NEED to be in sync with tlntsvr\enclisvr.cpp
  40. // the separators used to identify various portions of a session as well as session begin/end
  41. WCHAR *session_separator = L",";
  42. WCHAR *session_data_separator = L"\\";
  43. extern BSTR bstrLogin;
  44. extern BSTR bstrPasswd;
  45. extern BSTR bstrNameSpc;
  46. extern SERVICE_STATUS g_hServiceStatus;
  47. //wchar_t *g_szCName=NULL; (See the comment in the PrintSettings() function
  48. //all three files extern
  49. #ifdef __cplusplus
  50. extern "C" {
  51. #endif
  52. extern long int g_nConfigOptions;
  53. extern int g_nError; //Error indicator, initialsed to no error.:-)
  54. extern wchar_t* g_arVALOF[_MAX_PROPS_];
  55. extern int g_nPrimaryOption;
  56. //option indicator.
  57. extern int g_nTimeoutFlag; //o means in hh:mm:ss 1 means ss format.
  58. extern int g_nSesid;
  59. extern BSTR g_bstrMessage;
  60. extern ConfigProperty g_arPROP[_MAX_PROPS_][_MAX_NUMOF_PROPNAMES_];
  61. extern int g_nAuditOff;
  62. extern int g_nAuditOn;
  63. extern int g_nSecOff;
  64. extern int g_nSecOn;
  65. #ifdef __cplusplus
  66. }
  67. #endif
  68. IManageTelnetSessions* g_pIManageTelnetSessions = NULL;
  69. // Pointer to the Session Manager Interface;-)
  70. int g_nNumofSessions=0;
  71. wchar_t** g_ppwzSessionInfo=NULL;
  72. //will be allocated in ListUsers.An array of session infosize=g_nNumofSessions.
  73. // The following function is a replica of SafeCoInitialize() from Commfunc library
  74. // Please check with the header of function there.
  75. // Why a local copy? We are not checking in the comm func library sources
  76. // for Whistler - hence we can not link to that library for telnet.
  77. HRESULT Telnet_SafeCoInitializeEx()
  78. {
  79. HRESULT hCoIni = S_OK;
  80. // Initialize the COM library on this thread.
  81. hCoIni = CoInitializeEx( NULL, COINIT_MULTITHREADED );
  82. if(S_OK!=hCoIni)
  83. {
  84. if (S_FALSE == hCoIni)
  85. {
  86. // The COM library is already initialized on this thread
  87. // This is not an error as we already have what
  88. // we are asking for.
  89. // But this code should never get executed - Safe programming
  90. }
  91. else
  92. return hCoIni;
  93. }
  94. return S_OK;
  95. }
  96. // The following two functions are copied from commfunc.cpp. Any change made in
  97. // these functions in commfunc.cpp should be copied here.
  98. // This function calls LoadLibrary() after framing the complete path of the dll.
  99. // Arguments:
  100. // wzEnvVar [IN] : Environment Variable which needs to be expanded.
  101. // wzSubDir [IN] : Sub directory under which the dll is located. This will
  102. // concatenated to the expanded env var. This field can
  103. // be null. You should not specify "\" here.
  104. // wzDllName [IN] : Name of the DLL to be loaded in widechars
  105. // pdwRetVal [OUT]: Pointer to a DWord to hold the return value.
  106. //
  107. // Return Value:
  108. // On success returns handle to the library.
  109. // On failure returns NULL;
  110. // Notes: Please check the pdwRetVal parameter incase this function returns NULL
  111. //
  112. // Possible values for dwRetVal:
  113. //
  114. // =============================================================
  115. // | ERROR_SUCCESS Successful loading of library. |
  116. // | ERROR_INSUFFICIENT_BUFFER If the buffer is not sufficient to hold the |
  117. // | dll name. |
  118. // | ERROR_ENVVAR_NOT_FOUND If the environment variable is not found. |
  119. // | ERROR_INVALID_DATA If the environment variable is absent. |
  120. // | GetLastError() If LoadLibrary() fails. |
  121. // =============================================================
  122. //
  123. HMODULE TnSafeLoadLibraryViaEnvVarW(WCHAR *wzEnvVar, WCHAR* wzSubDir, WCHAR *wzDllName, DWORD* pdwRetVal)
  124. {
  125. HMODULE hLibrary = NULL;
  126. WCHAR wzDllPath[3*MAX_PATH+1] = {0};
  127. DWORD dwNoOfCharsUsed = 0;
  128. // Validate the input.
  129. if (NULL == pdwRetVal)
  130. goto Abort;
  131. if( (NULL == wzEnvVar) || (0==wcscmp(wzEnvVar,L"")) || (NULL == wzDllName) || (0==wcscmp(wzDllName,L"")))
  132. {
  133. *pdwRetVal=ERROR_INVALID_DATA;
  134. goto Abort;
  135. }
  136. *pdwRetVal = ERROR_SUCCESS;
  137. dwNoOfCharsUsed=GetEnvironmentVariableW(wzEnvVar, wzDllPath, ARRAYSIZE(wzDllPath)-1);
  138. if(0!=dwNoOfCharsUsed)
  139. {
  140. // Add the last '\' if absent
  141. if(wzDllPath[dwNoOfCharsUsed-1]!=L'\\')
  142. {
  143. wzDllPath[dwNoOfCharsUsed]=L'\\';
  144. dwNoOfCharsUsed++;
  145. // Check for buffer overflow.
  146. if(dwNoOfCharsUsed > ARRAYSIZE(wzDllPath)-1)
  147. {
  148. *pdwRetVal = ERROR_INSUFFICIENT_BUFFER;
  149. goto Abort;
  150. }
  151. }
  152. // If SubDir is present, frame the path as %EnvVar%SubDir\DllName
  153. // else %EnvVar%DllName
  154. if(NULL!=wzSubDir)
  155. {
  156. if(_snwprintf(wzDllPath+dwNoOfCharsUsed,
  157. ARRAYSIZE(wzDllPath)-dwNoOfCharsUsed-1,
  158. L"%s\\%s",
  159. wzSubDir,
  160. wzDllName) < 0)
  161. {
  162. // _snwprintf failed
  163. *pdwRetVal = ERROR_INSUFFICIENT_BUFFER;
  164. goto Abort;
  165. }
  166. }
  167. else
  168. {
  169. wcsncpy(wzDllPath+dwNoOfCharsUsed, wzDllName, ARRAYSIZE(wzDllPath)-dwNoOfCharsUsed-1);
  170. }
  171. // ensuring null termination
  172. wzDllPath[ARRAYSIZE(wzDllPath)-1]=L'\0';
  173. }
  174. else
  175. {
  176. // The system could not find the environment variable.
  177. *pdwRetVal = ERROR_ENVVAR_NOT_FOUND;
  178. goto Abort;
  179. }
  180. // Load the library
  181. hLibrary = LoadLibraryExW(wzDllPath,NULL,LOAD_LIBRARY_AS_DATAFILE);
  182. if(NULL == hLibrary)
  183. *pdwRetVal = GetLastError();
  184. Abort:
  185. return hLibrary;
  186. }
  187. // This function calls ZeroMemory() and makes sure that this call is not optimized
  188. // out by the compiler.
  189. // Arguments:
  190. // Destination [IN] : Pointer to the starting address of the block of memory
  191. // to fill with zeros
  192. // cbLength [IN] : Size, in bytes, of the block of memory to fill with zeros.
  193. // Return Value:
  194. // void function.
  195. // Author: srivatsk
  196. void TnSfuZeroMemory(PVOID Destination, SIZE_T cbLength)
  197. {
  198. ZeroMemory(Destination, cbLength);
  199. *(volatile char*)Destination; // this is dummy statement to prevent optimization
  200. // Why *(volatile char*)Destination? To make sure that the compiler doesn't optimize
  201. // away the ZeroMemory() call thinking that we are not going
  202. // to access this memory anymore :)
  203. return;
  204. }
  205. // The following two functions are copied from allutils.cpp. Any change made in
  206. // these functions in allutils.cpp should be copied here.
  207. // This function loads the resource dll "Cladmin.dll" from %SFUDIR%\common
  208. // and stores the handle in global variable g_hResource.
  209. // Add code here to take care of loading resources for non-english locales.
  210. // This function has been changed to load XPSP1RES.DLL in case it is present.
  211. // This is only tlntadmn.exe specific change and should not be copied back to
  212. // allutils.cpp. If present, XPSP1RES.DLL will be present in %SystemRoot%\System32
  213. DWORD TnLoadResourceDll()
  214. {
  215. //Load the Strings library "cladmin.dll".
  216. // if not found, it should get the English resources from the exe.
  217. DWORD dwRetVal = ERROR_SUCCESS;
  218. OSVERSIONINFOEX osvi = { 0 };
  219. g_hXPResource = NULL;
  220. // No need to check for the dwRetVal field of SafeLoadSystemLibrary; As incase of
  221. // failure, we will default to English resources from the exe.
  222. // We need to add check here while taking care of non-english locales.
  223. if (NULL == g_hResource)
  224. {
  225. g_hResource = GetModuleHandle(NULL);
  226. }
  227. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  228. if ( !GetVersionEx((OSVERSIONINFO *) &osvi ) )
  229. {
  230. //OSVERSIONINFOEX is supported from NT4 SP6 on. So GetVerEx() should succeed.
  231. goto Done;
  232. }
  233. //Load XPSPxRes.dll only if OS is XP and Service pack is x where 'x' is service pack number
  234. //e.g. 1 in case of XPSP1
  235. if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.wProductType == VER_NT_WORKSTATION && osvi.wServicePackMajor > 0)
  236. {
  237. //OS is Windows XP.
  238. g_hXPResource = LoadLibraryExW(L"xpsp1res.dll",NULL,LOAD_LIBRARY_AS_DATAFILE);
  239. }
  240. //no need to see if the the LoadLibrary failed. It will succeed only on XPSP1 in which case,
  241. //some resources may need to be loaded from the dll.
  242. Done:
  243. return ERROR_SUCCESS;
  244. }
  245. // This function is used to clear the passwd and should be called once you no
  246. // longer require the passwd field. This function also frees the memory and makes
  247. // it null so that nobody else call make use of it in the future.
  248. // Zeroing the memory is done by calling SfuZeroMemory() which makes sure
  249. // that ZeroMemory() call is not optimized away by the compiler.
  250. void TnClearPasswd()
  251. {
  252. if(g_arVALOF[_p_PASSWD_])
  253. {
  254. TnSfuZeroMemory(g_arVALOF[_p_PASSWD_], wcslen(g_arVALOF[_p_PASSWD_])*sizeof(WCHAR));
  255. free(g_arVALOF[_p_PASSWD_]);
  256. g_arVALOF[_p_PASSWD_]=NULL;
  257. }
  258. }
  259. /* --
  260. int Initialize(void) function initialises the class-object-paths,
  261. and also property class dependency.
  262. Then gets a handle to WbemLocator,
  263. Connects to the server and gets a handle to WbemServices
  264. with proper authentication.
  265. Note that: if the passed in namespace is null then, it defaults to
  266. "root\\sfuadmin"
  267. --*/
  268. int Initialize(void)
  269. {
  270. int i;
  271. for(i=0;i<_MAX_CLASS_NAMES_;i++)
  272. {
  273. g_arCLASShkey[i]=NULL;
  274. g_arCLASSname[i]=NULL;
  275. }
  276. int j;
  277. for(i=0;i<_MAX_PROPS_;i++)
  278. { for(j=0;j<_MAX_NUMOF_PROPNAMES_;j++)
  279. {
  280. g_arPROP[i][j].fDontput=0;
  281. g_arPROP[i][j].propname=NULL;
  282. }
  283. g_arVALOF[i]=NULL;
  284. g_arNUM_PROPNAME[i]=0;
  285. }
  286. //Load the Strings library "cladmin.dll".
  287. // if not found, it should get the English resources from the exe.
  288. DWORD dwRetVal = TnLoadResourceDll();
  289. if(ERROR_SUCCESS!=dwRetVal)
  290. {
  291. return dwRetVal;
  292. }
  293. HRESULT hCoIni = Telnet_SafeCoInitializeEx();
  294. if (S_OK!=hCoIni)
  295. // Oops! This function can not return hResult :( and so returning -1 to indicate
  296. // error. but unfortunately none of the callers are using the return value of this
  297. // function.
  298. return -1;
  299. g_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
  300. // Set the flag so that we call CoUnint...()
  301. g_fCoInitSuccess = TRUE;
  302. //Default values can be set over here.
  303. g_nConfigOptions=0;
  304. //Defining the class object paths for tnadmin....
  305. g_arCLASSname[0]=L"SOFTWARE\\Microsoft\\TelnetServer\\1.0";
  306. g_arCLASSname[1]=L"SOFTWARE\\Microsoft\\TelnetServer\\1.0\\ReadConfig";
  307. g_arCLASSname[2]=L"SOFTWARE\\Microsoft\\Services For Unix\\AppsInstalled\\Telnet Server";
  308. //Assigning different properties to their respective classes...
  309. g_arPROP[_p_CTRLAKEYMAP_][0].classname=0;
  310. g_arPROP[_p_TIMEOUT_][0].classname=0;
  311. g_arPROP[_p_MAXCONN_][0].classname=0;
  312. g_arPROP[_p_PORT_][0].classname=0;
  313. g_arPROP[_p_MAXFAIL_][0].classname=0;
  314. g_arPROP[_p_KILLALL_][0].classname=0;
  315. g_arPROP[_p_MODE_][0].classname=0;
  316. g_arPROP[_p_AUDITLOCATION_][0].classname=0;
  317. g_arPROP[_p_SEC_][0].classname=0;
  318. g_arPROP[_p_DOM_][0].classname=0;
  319. g_arPROP[_p_AUDIT_][0].classname=0;
  320. g_arPROP[_p_TIMEOUTACTIVE_][0].classname=0;
  321. g_arPROP[_p_FNAME_][0].classname=0;
  322. g_arPROP[_p_FSIZE_][0].classname=0;
  323. g_arPROP[_p_DEFAULTS_][0].classname=1;
  324. g_arPROP[_p_INSTALLPATH_][0].classname=2;
  325. //these two come from Active X, so will take care separately..
  326. //CLASSOF_AR[_p_SESSID_]=;
  327. //CLASSOF_AR[_p_STATE_]=;
  328. //giving properties number of names they are actually associated with....
  329. g_arNUM_PROPNAME[_p_CTRLAKEYMAP_]=1;
  330. g_arNUM_PROPNAME[_p_TIMEOUT_]=2;
  331. g_arNUM_PROPNAME[_p_MAXCONN_]=1;
  332. g_arNUM_PROPNAME[_p_PORT_]=1;
  333. g_arNUM_PROPNAME[_p_MAXFAIL_]=1;
  334. g_arNUM_PROPNAME[_p_KILLALL_]=1;
  335. g_arNUM_PROPNAME[_p_MODE_]=1;
  336. g_arNUM_PROPNAME[_p_AUDITLOCATION_]=2;
  337. g_arNUM_PROPNAME[_p_SEC_]=1;
  338. g_arNUM_PROPNAME[_p_DOM_]=1;
  339. g_arNUM_PROPNAME[_p_AUDIT_]=3;
  340. g_arNUM_PROPNAME[_p_TIMEOUTACTIVE_]=2;
  341. g_arNUM_PROPNAME[_p_FNAME_]=1;
  342. g_arNUM_PROPNAME[_p_FSIZE_]=1;
  343. g_arNUM_PROPNAME[_p_DEFAULTS_]=1;
  344. g_arNUM_PROPNAME[_p_INSTALLPATH_]=1;//not used
  345. //giving properties their actual property_names as in the registry....
  346. g_arPROP[_p_CTRLAKEYMAP_][0].propname=L"AltKeyMapping";
  347. g_arPROP[_p_TIMEOUT_][0].propname=L"IdleSessionTimeout";
  348. g_arPROP[_p_TIMEOUT_][1].propname=L"IdleSessionTimeoutBkup";
  349. g_arPROP[_p_MAXCONN_][0].propname=L"MaxConnections";
  350. g_arPROP[_p_PORT_][0].propname=L"TelnetPort";
  351. g_arPROP[_p_MAXFAIL_][0].propname=L"MaxFailedLogins";
  352. g_arPROP[_p_KILLALL_][0].propname=L"DisconnectKillAllApps";
  353. g_arPROP[_p_MODE_][0].propname=L"ModeOfOperation";
  354. g_arPROP[_p_AUDITLOCATION_][0].propname=L"EventLoggingEnabled";
  355. g_arPROP[_p_AUDITLOCATION_][1].propname=L"LogToFile";
  356. g_arPROP[_p_SEC_][0].propname=L"SecurityMechanism";
  357. g_arPROP[_p_DOM_][0].propname=L"DefaultDomain";
  358. g_arPROP[_p_AUDIT_][0].propname=L"LogAdminAttempts";
  359. g_arPROP[_p_AUDIT_][1].propname=L"LogNonAdminAttempts";
  360. g_arPROP[_p_AUDIT_][2].propname=L"LogFailures";
  361. g_arPROP[_p_TIMEOUTACTIVE_][0].propname=L"IdleSessionTimeout";
  362. g_arPROP[_p_TIMEOUTACTIVE_][1].propname=L"IdleSessionTimeoutBkup";
  363. g_arPROP[_p_FNAME_][0].propname=L"LogFile";
  364. g_arPROP[_p_FSIZE_][0].propname=L"LogFileSize";
  365. g_arPROP[_p_DEFAULTS_][0].propname=L"Defaults";
  366. g_arPROP[_p_INSTALLPATH_][0].propname=L"InstallPath";//not used
  367. //giving the properties their type.
  368. V_VT(&g_arPROP[_p_CTRLAKEYMAP_][0].var)=VT_I4;
  369. V_VT(&g_arPROP[_p_TIMEOUT_][0].var)=VT_I4;
  370. V_VT(&g_arPROP[_p_TIMEOUT_][1].var)=VT_I4;
  371. V_VT(&g_arPROP[_p_MAXCONN_][0].var)=VT_I4;
  372. V_VT(&g_arPROP[_p_PORT_][0].var)=VT_I4;
  373. V_VT(&g_arPROP[_p_MAXFAIL_][0].var)=VT_I4;
  374. V_VT(&g_arPROP[_p_KILLALL_][0].var)=VT_I4;
  375. V_VT(&g_arPROP[_p_MODE_][0].var)=VT_I4;
  376. V_VT(&g_arPROP[_p_AUDITLOCATION_][0].var)=VT_I4;
  377. V_VT(&g_arPROP[_p_AUDITLOCATION_][1].var)=VT_I4;
  378. V_VT(&g_arPROP[_p_SEC_][0].var)=VT_I4;
  379. V_VT(&g_arPROP[_p_DOM_][0].var)=VT_BSTR;
  380. V_VT(&g_arPROP[_p_AUDIT_][0].var)=VT_I4;
  381. V_VT(&g_arPROP[_p_AUDIT_][1].var)=VT_I4;
  382. V_VT(&g_arPROP[_p_AUDIT_][2].var)=VT_I4;
  383. V_VT(&g_arPROP[_p_TIMEOUTACTIVE_][0].var)=VT_I4;
  384. V_VT(&g_arPROP[_p_TIMEOUTACTIVE_][1].var)=VT_I4;
  385. V_VT(&g_arPROP[_p_FNAME_][0].var)=VT_BSTR;
  386. V_VT(&g_arPROP[_p_FSIZE_][0].var)=VT_I4;
  387. V_VT(&g_arPROP[_p_DEFAULTS_][0].var)=VT_I4;
  388. V_VT(&g_arPROP[_p_INSTALLPATH_][0].var)=VT_BSTR;
  389. return 0;
  390. }
  391. /*--
  392. DoTnadmindoes the actual work corresponding the command line,
  393. Depending upon the option given.
  394. --*/
  395. HRESULT DoTnadmin(void)
  396. {
  397. int nProperty,nj;
  398. SCODE sc;
  399. SCODE hRes;
  400. SetThreadUILanguage(0);
  401. if(g_nError)
  402. return E_FAIL;
  403. if(_HELP==g_nPrimaryOption)
  404. {
  405. #ifdef WHISTLER_BUILD
  406. PrintMessageEx(g_stdout,IDR_NEW_TELNET_USAGE,TEXT("\nUsage: tlntadmn [computer name] [common_options] start | stop | pause | continue | -s | -k | -m | config config_options \n\tUse 'all' for all sessions.\n\t-s sessionid List information about the session.\n\t-k sessionid\t Terminate a session. \n\t-m sessionid\t Send message to a session. \n\n\tconfig\t Configure telnet server parameters.\n\ncommon_options are:\n\t-u user\t Identity of the user whose credentials are to be used\n\t-p password\t Password of the user\n\nconfig_options are:\n\tdom = domain\t Set the default domain for user names\n\tctrlakeymap = yes|no\t Set the mapping of the ALT key\n\ttimeout = hh:mm:ss\t Set the Idle Session Timeout\n\ttimeoutactive = yes|no Enable idle session timeout.\n\tmaxfail = attempts\t Set the maximum number of login failure attempts\n\tbefore disconnecting.\n\tmaxconn = connections\t Set the maximum number of connections.\n\tport = number\t Set the telnet port.\n\tsec = [+/-]NTLM [+/-]passwd\n\t Set the authentication mechanism\n\tmode = console|stream\t Specify the mode of operation.\n"));
  407. #else
  408. PrintMessageEx(g_stdout,IDR_NEW_TELNET_USAGE,TEXT("\nUsage: tnadmin [computer name] [common_options] start | stop | pause | continue | -s | -k | -m | config config_options \n\tUse 'all' for all sessions.\n\t-s sessionid List information about the session.\n\t-k sessionid\t Terminate a session. \n\t-m sessionid\t Send message to a session. \n\n\tconfig\t Configure telnet server parameters.\n\ncommon_options are:\n\t-u user\t Identity of the user whose credentials are to be used\n\t-p password\t Password of the user\n\nconfig_options are:\n\tdom = domain\t Set the default domain for user names\n\tctrlakeymap = yes|no\t Set the mapping of the ALT key\n\ttimeout = hh:mm:ss\t Set the Idle Session Timeout\n\ttimeoutactive = yes|no Enable idle session timeout.\n\tmaxfail = attempts\t Set the maximum number of login failure attempts\n\tbefore disconnecting.\n\tmaxconn = connections\t Set the maximum number of connections.\n\tport = number\t Set the telnet port.\n\tsec = [+/-]NTLM [+/-]passwd\n\t Set the authentication mechanism\n\tmode = console|stream\t Specify the mode of operation.\n"));
  409. #endif
  410. hRes = S_OK;
  411. return hRes;
  412. }
  413. //remote execution
  414. if(NULL!=g_arVALOF[_p_CNAME_]&&(0==_wcsicmp(g_arVALOF[_p_CNAME_],L"localhost")||0==_wcsicmp(g_arVALOF[_p_CNAME_],L"\\\\localhost")))
  415. {
  416. free(g_arVALOF[_p_CNAME_]);
  417. g_arVALOF[_p_CNAME_]=NULL;
  418. // g_szCName=NULL; Not used any more
  419. }
  420. if(FAILED(hRes=CheckForPassword())) //Get password if not specified
  421. return hRes;
  422. //Checking if the telnet server exists
  423. if(FAILED(sc=(DoNetUseAdd(g_arVALOF[_p_USER_],g_arVALOF[_p_PASSWD_],g_arVALOF[_p_CNAME_]))))
  424. return sc;
  425. // We don't have to keep the password anymore except while handling sessions
  426. // related options.
  427. if((g_nPrimaryOption!=_S)&&(g_nPrimaryOption!=_K)&&(g_nPrimaryOption!=_M))
  428. {
  429. TnClearPasswd();
  430. }
  431. if(FAILED(hRes=(GetConnection(g_arVALOF[_p_CNAME_]))))
  432. goto End;
  433. if(FAILED(hRes = IsWhistlerTheOS(&g_fWhistler)))
  434. goto End;
  435. // If the telnet server is not of Whistler and SFU, then it would be from Win2K
  436. // We do not support remote administration for this. So need to special case ...
  437. if(FALSE == g_fWhistler)
  438. {
  439. if(FAILED(hRes=GetClassEx(_p_INSTALLPATH_, 0, false, MAXIMUM_ALLOWED)))
  440. {
  441. ShowError(IDR_INVALID_TELNET_SERVER_VERSION);
  442. hRes = E_FAIL;
  443. goto End;
  444. }
  445. else
  446. {
  447. if(g_arCLASShkey[g_arPROP[_p_INSTALLPATH_][0].classname] != NULL &&
  448. RegCloseKey(g_arCLASShkey[g_arPROP[_p_INSTALLPATH_][0].classname]) != ERROR_SUCCESS)
  449. {
  450. hRes = GetLastError();
  451. goto End;
  452. }
  453. g_arCLASShkey[g_arPROP[_p_INSTALLPATH_][0].classname] = NULL;
  454. }
  455. }
  456. if(FALSE == g_fWhistler)
  457. if(S_OK!=(hRes=GetSerHandle(L"tlntsvr",GENERIC_READ,SERVICE_QUERY_STATUS,FALSE))||S_OK!=(hRes=CloseHandles()))
  458. goto End;
  459. switch (g_nPrimaryOption)
  460. {
  461. case _START :
  462. hRes=StartSfuService(L"tlntsvr");
  463. break;
  464. case _STOP :
  465. hRes=ControlSfuService(L"tlntsvr",SERVICE_CONTROL_STOP);
  466. break;
  467. case _PAUSE :
  468. hRes=ControlSfuService(L"tlntsvr",SERVICE_CONTROL_PAUSE);
  469. break;
  470. case _CONTINUE:
  471. hRes=ControlSfuService(L"tlntsvr",SERVICE_CONTROL_CONTINUE);
  472. break;
  473. case _S :
  474. ShowSession();
  475. break;
  476. case _K :
  477. TerminateSession();
  478. break;
  479. case _M :
  480. MessageSession();
  481. break;
  482. case _CONFIG:
  483. if(g_nConfigOptions)
  484. {
  485. g_nConfigOptions=SetBit(g_nConfigOptions,_p_DEFAULTS_);
  486. for(nProperty=0;nProperty<_MAX_PROPS_;nProperty++)
  487. {if(GetBit(g_nConfigOptions,nProperty))
  488. {
  489. for(nj=0;nj<g_arNUM_PROPNAME[nProperty];nj++)
  490. {
  491. if(FAILED(hRes=GetClass(nProperty,nj)))
  492. goto End;
  493. if(FAILED(hRes=GetCorrectVariant(nProperty,nj,&g_arPROP[nProperty][nj].var)))
  494. goto End;
  495. }
  496. }
  497. }
  498. if(g_nError)
  499. break;
  500. for(nProperty=0;nProperty<_MAX_PROPS_;nProperty++)
  501. if(GetBit(g_nConfigOptions,nProperty))
  502. {
  503. for(nj=0;nj<g_arNUM_PROPNAME[nProperty];nj++)
  504. if(FAILED(hRes=PutProperty(nProperty,nj,&g_arPROP[nProperty][nj].var)))
  505. goto End;
  506. }
  507. if(FAILED(hRes=PutClasses()))
  508. goto End;
  509. PrintMessage(g_stdout,IDR_SETTINGS_UPDATED);
  510. break;
  511. }
  512. default :
  513. for(nProperty=0;nProperty<_MAX_PROPS_;nProperty++)
  514. {
  515. if(nProperty==_p_INSTALLPATH_)
  516. continue;
  517. for(nj=0;nj<g_arNUM_PROPNAME[nProperty];nj++)
  518. {
  519. if(FAILED(hRes=GetClass(nProperty,nj)))
  520. goto End;
  521. if(FAILED(hRes=GetProperty(nProperty,nj,&g_arPROP[nProperty][nj].var)))
  522. goto End;
  523. }
  524. }
  525. if(FAILED(hRes=PutClasses()))
  526. goto End;
  527. if(FAILED(hRes=QuerySfuService(L"tlntsvr")))
  528. goto End;
  529. hRes=PrintSettings();
  530. break;
  531. }
  532. End:
  533. (void)DoNetUseDel(g_arVALOF[_p_CNAME_]);
  534. return hRes;
  535. }
  536. /*--
  537. The function GetCorrectVariant makes a variant out of the wchar_t * of
  538. the value of each option and returns the variant
  539. this function is called by DoTnadmin(), to get the correct variants
  540. and they are put using PutProperty() function.
  541. This function also performs checks as to if the input is valid or not.
  542. such as : if the input is in valid range or not, etc.
  543. Note that Variant is malloced here, so has to be freed once used.
  544. --*/
  545. HRESULT GetCorrectVariant(int nProperty,int nPropattrib, VARIANT* pvarVal)
  546. {
  547. VARIANT vVar={0};
  548. HRESULT hRes=ERROR_SUCCESS;
  549. int fValid=0;
  550. WCHAR sztempDomain[_MAX_PATH];
  551. switch (nProperty)
  552. {
  553. case _p_CTRLAKEYMAP_ :
  554. case _p_KILLALL_ :
  555. V_VT(pvarVal)=VT_I4;
  556. if(_wcsicmp(g_arVALOF[nProperty],L"yes")>=0)
  557. V_I4(pvarVal)=1;
  558. else
  559. V_I4(pvarVal)=0;
  560. break;
  561. case _p_MAXCONN_ :
  562. V_VT(pvarVal)=VT_I4;
  563. V_I4(pvarVal)=_wtoi(g_arVALOF[nProperty]);
  564. // Why checking for MaxInt? We are anyway checking it for <0?
  565. // Answer: _wtoi() function may end up giving us a positive number
  566. // whose value is < MAXINT when we give a very long input.
  567. // Hence checking for MaxINT leaves us in the safe side.
  568. if(FAILED(hRes=CheckForMaxInt(g_arVALOF[nProperty],IDR_MAXCONN_VALUES)))
  569. break;
  570. // We have decided to allow as many connections as possible on Whistler
  571. // too making it no different than Win2K
  572. /* if(!IsMaxConnChangeAllowed()) //Checking for Whistler and SFU not installed.
  573. { //We allow him to make it 1 or 0
  574. if((V_I4(pvarVal)>2) || (V_I4(pvarVal)<0)) //less than zero for cases where the integer value is greater than 2147483647
  575. {
  576. ShowError(IDR_MAXCONN_VALUES_WHISTLER);
  577. break;
  578. }
  579. }*/
  580. if((V_I4(pvarVal)<0) || (V_I4(pvarVal)>MAX_VALUE_MAXCONN)) //Incase the value exceeds the maximum limit that an integer can store
  581. { //then it is converted as a negative number
  582. ShowError(IDR_MAXCONN_VALUES);
  583. break;
  584. }
  585. break;
  586. case _p_PORT_ :
  587. V_VT(pvarVal)=VT_I4;
  588. V_I4(pvarVal)=_wtoi(g_arVALOF[nProperty]) ;
  589. if(FAILED(hRes=CheckForMaxInt(g_arVALOF[nProperty],IDR_TELNETPORT_VALUES)))
  590. break;
  591. if((V_I4(pvarVal)>1023)||(V_I4(pvarVal)<=0))
  592. ShowError(IDR_TELNETPORT_VALUES);
  593. break;
  594. case _p_MAXFAIL_ :
  595. V_VT(pvarVal)=VT_I4;
  596. V_I4(pvarVal)=_wtoi(g_arVALOF[nProperty]) ;
  597. if(FAILED(hRes=CheckForMaxInt(g_arVALOF[nProperty],IDR_MAXFAIL_VALUES)))
  598. break;
  599. if((V_I4(pvarVal)>100)||(V_I4(pvarVal)<=0))
  600. ShowError(IDR_MAXFAIL_VALUES);
  601. break;
  602. case _p_FSIZE_ :
  603. V_VT(pvarVal)=VT_I4;
  604. hRes=GetProperty(_p_FNAME_,0,&vVar);
  605. if(FAILED(hRes))
  606. return hRes;
  607. // The first check in the following condition (V_BSTR(&vVar)==NULL) is added to avoid
  608. // deferencing of NULL pointer in _wcsicmp(). But this can NEVER be null as we check
  609. // for the error case in GetProperty() - added to get rid of Prefix issue
  610. if(((V_BSTR(&vVar)==NULL) || (_wcsicmp(V_BSTR(&vVar),L"")==NULL)) && ((wchar_t*)V_BSTR(&g_arPROP[_p_FNAME_][0].var)==NULL))
  611. {
  612. ShowError(IDR_NOFILENAME);
  613. break;
  614. }
  615. V_I4(pvarVal)=_wtoi(g_arVALOF[nProperty]);
  616. if(FAILED(hRes=CheckForMaxInt(g_arVALOF[nProperty],IDR_FILESIZE_VALUES)))
  617. break;
  618. if((V_I4(pvarVal)<0)||(V_I4(pvarVal)>4096))
  619. ShowError(IDR_FILESIZE_VALUES);
  620. break;
  621. case _p_MODE_ :
  622. V_VT(pvarVal)=VT_I4;
  623. if(_wcsicmp(g_arVALOF[nProperty],L"stream")<0)
  624. //Since console<stream.
  625. V_I4(pvarVal)=1;
  626. else
  627. V_I4(pvarVal)=2;
  628. break;
  629. case _p_AUDITLOCATION_ :
  630. V_VT(pvarVal)=VT_I4;
  631. if(nPropattrib==0)
  632. if(_wcsicmp(g_arVALOF[nProperty],L"file")<0)
  633. V_I4(pvarVal)=1;
  634. else
  635. V_I4(pvarVal)=0;
  636. else
  637. if(_wcsicmp(g_arVALOF[nProperty],L"eventlog")<0||_wcsicmp(g_arVALOF[nProperty],L"file")>=0)
  638. V_I4(pvarVal)=1;
  639. else
  640. V_I4(pvarVal)=0;
  641. break;
  642. #if 0 // This option has been removed
  643. case _p_FNAME_ :
  644. {
  645. wchar_t* wzFile=(wchar_t*)malloc(3*sizeof(wchar_t));
  646. if(wzFile==NULL)
  647. return E_OUTOFMEMORY;
  648. wzFile[0]=g_arVALOF[_p_FNAME_][0];
  649. if((wzFile[1]=g_arVALOF[_p_FNAME_][1])!=L':'||(wzFile[2]=g_arVALOF[_p_FNAME_][2])!=L'\\')
  650. {ShowError(IDR_ERROR_DRIVE_NOT_SPECIFIED);free(wzFile);break;}
  651. //file[3]=g_arVALOF[_p_FNAME_][3];
  652. wzFile[3]=L'\0';
  653. if(DRIVE_FIXED!=GetDriveType(wzFile))
  654. ShowError(IDR_ERROR_DRIVE_NOT_EXIST);
  655. free(wzFile);
  656. wchar_t* wzFileName=_wcsdup(g_arVALOF[_p_FNAME_]);
  657. if(FAILED(hRes=CreateFileIfNotExist(wzFileName)))
  658. {
  659. free(wzFileName);
  660. return hRes;
  661. }
  662. free(wzFileName);
  663. }
  664. #endif
  665. case _p_DOM_ :
  666. if( nProperty==_p_DOM_ )
  667. {
  668. if(wcsncmp(g_arVALOF[nProperty],SLASH_SLASH,2)==0)
  669. {
  670. ShowError(IDR_INVALID_NTDOMAIN);
  671. break;
  672. }
  673. if(FAILED(hRes=IsValidDomain(g_arVALOF[nProperty],&fValid)))
  674. return hRes;
  675. if(fValid == 0)
  676. {
  677. // try again with '\\' at the beginning - don't modify the original function that returns
  678. // the local machine name with '\\' appended to it
  679. wcscpy(sztempDomain,SLASH_SLASH);
  680. wcsncat(sztempDomain,g_arVALOF[nProperty],_MAX_PATH -sizeof(SLASH_SLASH)-sizeof(WCHAR));
  681. if(FAILED(hRes=IsValidDomain(sztempDomain,&fValid)))
  682. return hRes;
  683. }
  684. if(fValid==0)
  685. {
  686. ShowError(IDR_INVALID_NTDOMAIN);
  687. break;
  688. }
  689. }
  690. V_VT(pvarVal)=VT_BSTR;
  691. V_BSTR(pvarVal)=SysAllocString(g_arVALOF[nProperty]);
  692. break;
  693. case _p_AUDIT_ :
  694. V_VT(pvarVal)=VT_I4;
  695. if(nPropattrib==0)
  696. if(GetBit(g_nAuditOff,ADMIN_BIT))
  697. V_I4(pvarVal)=0;
  698. else if(GetBit(g_nAuditOn,ADMIN_BIT))
  699. V_I4(pvarVal)=1;
  700. else
  701. g_arPROP[_p_AUDIT_][0].fDontput=1;
  702. else if(nPropattrib==1)
  703. if(GetBit(g_nAuditOff,USER_BIT))
  704. V_I4(pvarVal)=0;
  705. else if(GetBit(g_nAuditOn,USER_BIT))
  706. V_I4(pvarVal)=1;
  707. else
  708. g_arPROP[_p_AUDIT_][1].fDontput=1;
  709. else
  710. if(GetBit(g_nAuditOff,FAIL_BIT))
  711. V_I4(pvarVal)=0;
  712. else if(GetBit(g_nAuditOn,FAIL_BIT))
  713. V_I4(pvarVal)=1;
  714. else
  715. g_arPROP[_p_AUDIT_][2].fDontput=1;
  716. break;
  717. case _p_TIMEOUTACTIVE_ :
  718. if(nPropattrib==1) // Do not meddle with the backup property.
  719. {g_arPROP[_p_TIMEOUTACTIVE_][nPropattrib].fDontput=1;break;}
  720. V_VT(pvarVal)=VT_I4;
  721. if(0==_wcsicmp(g_arVALOF[nProperty],L"yes"))
  722. {
  723. if(FAILED(hRes=GetProperty(_p_TIMEOUTACTIVE_,1,&vVar)))
  724. return hRes;
  725. V_I4(pvarVal)=V_I4(&vVar);
  726. }
  727. else
  728. V_I4(pvarVal)=-1;
  729. break;
  730. case _p_TIMEOUT_: //By this time timeoutactive is already set or put.
  731. if(GetBit(g_nConfigOptions,_p_TIMEOUTACTIVE_)&&(_wcsicmp(g_arVALOF[_p_TIMEOUTACTIVE_],L"yes")<0))
  732. {
  733. g_arPROP[_p_TIMEOUT_][nPropattrib].fDontput=1;
  734. ShowError(IDR_TIMEOUTACTIVE_TIMEOUT_MUTUAL_EXCLUSION);
  735. return E_FAIL;//Check this return Value
  736. }
  737. V_VT(pvarVal)=VT_I4;
  738. if(g_nTimeoutFlag)
  739. {
  740. V_I4(pvarVal)=_wtoi(g_arVALOF[nProperty]);
  741. }
  742. else
  743. {
  744. if(CheckForInt(nProperty))
  745. {
  746. int nSeconds;
  747. if(0==nPropattrib)
  748. {
  749. ConvertintoSeconds(nProperty,&nSeconds);
  750. V_I4(pvarVal)=nSeconds;
  751. }
  752. // Now that we have destroyed whatever value we had in the global
  753. // variable by the use of wcstok, we need to copy from the already
  754. // computed value
  755. else //incase nPropattrib is 1
  756. V_I4(pvarVal)=V_I4(& g_arPROP[nProperty][0].var);
  757. }
  758. }
  759. if(V_I4(pvarVal)>60*60*2400||V_I4(pvarVal)<=0)
  760. {
  761. ShowError(IDR_TIMEOUT_INTEGER_VALUES);
  762. hRes=E_FAIL;
  763. }
  764. break;
  765. case _p_SEC_ :
  766. V_VT(pvarVal)=VT_I4;
  767. if(FAILED(hRes=GetProperty(_p_SEC_,0,&vVar)))
  768. return hRes;
  769. if(GetBit(g_nSecOn,PASSWD_BIT))//+passwd
  770. if(GetBit(g_nSecOn,NTLM_BIT)) //+ntlm
  771. V_I4(pvarVal)=6;
  772. else if(GetBit(g_nSecOff,NTLM_BIT)) //-ntlm
  773. V_I4(pvarVal)=4;
  774. else
  775. {
  776. if(V_I4(&vVar)!=2)
  777. g_arPROP[nProperty][nPropattrib].fDontput=1;
  778. else
  779. V_I4(pvarVal)=6;
  780. }
  781. else if(GetBit(g_nSecOff,PASSWD_BIT)) //-passwd
  782. if(GetBit(g_nSecOn,NTLM_BIT)) //+ntlm
  783. V_I4(pvarVal)=2;
  784. else if(GetBit(g_nSecOff,NTLM_BIT)) //-ntlm
  785. {
  786. ShowError(IDR_NO_AUTHENTICATION_MECHANISM);
  787. g_arPROP[nProperty][nPropattrib].fDontput=1;
  788. }
  789. else
  790. {
  791. if(V_I4(&vVar)==4)
  792. {
  793. ShowError(IDR_NO_AUTHENTICATION_MECHANISM);
  794. g_arPROP[nProperty][nPropattrib].fDontput=1;
  795. }
  796. else if(V_I4(&vVar)==2)
  797. g_arPROP[_p_SEC_][nPropattrib].fDontput=1;
  798. else
  799. V_I4(pvarVal)=2;
  800. }
  801. else
  802. if(GetBit(g_nSecOn,NTLM_BIT)) //+ntlm
  803. {
  804. if(V_I4(&vVar)!=4)
  805. g_arPROP[nProperty][nPropattrib].fDontput=1;
  806. else
  807. V_I4(pvarVal)=6;
  808. }
  809. else if(GetBit(g_nSecOff,NTLM_BIT)) //-ntlm
  810. {
  811. if(V_I4(&vVar)==2)
  812. {
  813. ShowError(IDR_NO_AUTHENTICATION_MECHANISM);
  814. g_arPROP[nProperty][nPropattrib].fDontput=1;
  815. }
  816. else if(V_I4(&vVar)==4)
  817. g_arPROP[_p_SEC_][nPropattrib].fDontput=1;
  818. else
  819. V_I4(pvarVal)=4;
  820. }
  821. else
  822. {
  823. ShowError(IDR_NO_AUTHENTICATION_MECHANISM);
  824. g_arPROP[nProperty][nPropattrib].fDontput=1;
  825. }
  826. break;
  827. case _p_DEFAULTS_ :
  828. if(nPropattrib==0)
  829. {
  830. if(FAILED(hRes=GetProperty(nProperty,0, &vVar)))
  831. {
  832. g_nError=1;
  833. //error occurred in getting the value.
  834. //error in notification
  835. break;
  836. }
  837. V_I4(pvarVal)=((V_I4(&vVar)>0) ? 0 : 1);
  838. }
  839. else
  840. g_arPROP[nProperty][nPropattrib].fDontput=1;
  841. break;
  842. case _p_CNAME_ :
  843. case _p_INSTALLPATH_ :
  844. default :
  845. g_arPROP[nProperty][nPropattrib].fDontput=1;
  846. break;
  847. }
  848. return hRes;
  849. }
  850. /*--
  851. PrintSettings Gets the present values int the registry corresponding to the
  852. tnadmin and prints it out.
  853. --*/
  854. HRESULT PrintSettings(void)
  855. {
  856. int nLen=0, temp_count;
  857. int nCheck=0;
  858. WCHAR wzDomain[DNS_MAX_NAME_BUFFER_LENGTH];
  859. WCHAR szTemp[MAX_BUFFER_SIZE] = { 0 };
  860. nLen=LoadString(g_hResource,IDR_MACHINE_SETTINGS, szTemp, MAX_BUFFER_SIZE );
  861. if(0 == nLen) return GetLastError();
  862. _putws(L"\n");
  863. _snwprintf(g_szMsg, MAX_BUFFER_SIZE -1, szTemp,(NULL == g_arVALOF[_p_CNAME_]) ? L"localhost" : g_arVALOF[_p_CNAME_]);
  864. MyWriteConsole(g_stdout, g_szMsg, wcslen(g_szMsg));
  865. // The following line(commented out) is used when we had g_szCName to
  866. // store the computer name as g_arVALOF[_p_CNAME_] stores the same in
  867. // the IP address format.
  868. // But we decided not to go for it as it will lead to serious perf issues
  869. nLen = 0;
  870. nCheck=LoadString(g_hResource, IDR_ALT_KEY_MAPPING, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen);
  871. if(nCheck==0) return GetLastError();
  872. nLen += nCheck;
  873. // check whether we have room left in the buffer.
  874. if (nLen >= ARRAYSIZE(g_szMsg))
  875. {
  876. return ERROR_INSUFFICIENT_BUFFER;
  877. }
  878. //ctrlakeymap
  879. if(V_I4(&g_arPROP[_p_CTRLAKEYMAP_][0].var))
  880. {
  881. nCheck=TnLoadString(IDR_YES, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("\tYES\n"));
  882. if(nCheck==0) return GetLastError();
  883. nLen += nCheck;
  884. // check whether we have room left in the buffer.
  885. if (nLen >= ARRAYSIZE(g_szMsg))
  886. {
  887. return ERROR_INSUFFICIENT_BUFFER;
  888. }
  889. }
  890. else
  891. {
  892. nCheck=TnLoadString(IDR_NO, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("\tYES\n"));
  893. if(nCheck==0) return GetLastError();
  894. nLen += nCheck;
  895. // check whether we have room left in the buffer.
  896. if (nLen >= ARRAYSIZE(g_szMsg))
  897. {
  898. return ERROR_INSUFFICIENT_BUFFER;
  899. }
  900. }
  901. //timeout
  902. nCheck=LoadString(g_hResource, IDR_IDLE_SESSION_TIMEOUT, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen);
  903. if(nCheck==0) return GetLastError();
  904. nLen += nCheck;
  905. // check whether we have room left in the buffer.
  906. if (nLen >= ARRAYSIZE(g_szMsg))
  907. {
  908. return ERROR_INSUFFICIENT_BUFFER;
  909. }
  910. if(V_I4(&g_arPROP[_p_TIMEOUT_][0].var)==-1)
  911. {
  912. nCheck=TnLoadString(IDR_MAPPING_NOT_ON, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("\tNot On\n"));
  913. if(nCheck==0) return GetLastError();
  914. nLen += nCheck;
  915. // check whether we have room left in the buffer.
  916. if (nLen >= ARRAYSIZE(g_szMsg))
  917. {
  918. return ERROR_INSUFFICIENT_BUFFER;
  919. }
  920. }
  921. else
  922. {
  923. int nTime=V_I4(&g_arPROP[_p_TIMEOUT_][0].var);
  924. int nQuotient=nTime/3600;
  925. nTime=nTime-nQuotient*3600;
  926. if(nQuotient)
  927. {
  928. temp_count = _snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L"\t%d ",nQuotient);
  929. if (temp_count < 0) {
  930. return ERROR_INSUFFICIENT_BUFFER;
  931. }
  932. nLen += temp_count;
  933. nCheck=TnLoadString(IDR_TIME_HOURS, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("hours"));
  934. if(nCheck==0) return GetLastError();
  935. nLen += nCheck;
  936. // check whether we have room left in the buffer.
  937. if (nLen >= ARRAYSIZE(g_szMsg))
  938. {
  939. return ERROR_INSUFFICIENT_BUFFER;
  940. }
  941. nQuotient=nTime/60;
  942. nTime=nTime-nQuotient*60;
  943. if(nQuotient)
  944. {
  945. temp_count = _snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L" %d ",nQuotient);
  946. if (temp_count < 0) {
  947. return ERROR_INSUFFICIENT_BUFFER;
  948. }
  949. nLen += temp_count;
  950. nCheck=TnLoadString(IDR_TIME_MINUTES, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("minutes"));
  951. if(nCheck==0) return GetLastError();
  952. nLen += nCheck;
  953. // check whether we have room left in the buffer.
  954. if (nLen >= ARRAYSIZE(g_szMsg))
  955. {
  956. return ERROR_INSUFFICIENT_BUFFER;
  957. }
  958. temp_count = _snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L" %d ",nTime);
  959. if (temp_count < 0) {
  960. return ERROR_INSUFFICIENT_BUFFER;
  961. }
  962. nLen += temp_count;
  963. nCheck=TnLoadString(IDR_TIME_SECONDS, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("seconds\n"));
  964. if(nCheck==0) return GetLastError();
  965. nLen += nCheck;
  966. // check whether we have room left in the buffer.
  967. if (nLen >= ARRAYSIZE(g_szMsg))
  968. {
  969. return ERROR_INSUFFICIENT_BUFFER;
  970. }
  971. }
  972. else if(nTime)
  973. {
  974. temp_count = _snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L" %d ",nTime);
  975. if (temp_count < 0) {
  976. return ERROR_INSUFFICIENT_BUFFER;
  977. }
  978. nLen += temp_count;
  979. nCheck=TnLoadString(IDR_TIME_SECONDS, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("seconds\n"));
  980. if(nCheck==0) return GetLastError();
  981. nLen += nCheck;
  982. // check whether we have room left in the buffer.
  983. if (nLen >= ARRAYSIZE(g_szMsg))
  984. {
  985. return ERROR_INSUFFICIENT_BUFFER;
  986. }
  987. }
  988. else
  989. {
  990. wcsncpy(g_szMsg+nLen, L"\n", ARRAYSIZE(g_szMsg)-nLen-1);
  991. g_szMsg[ARRAYSIZE(g_szMsg)-1]=L'\0';
  992. nLen += 1; // for L"\n"
  993. if (nLen >= ARRAYSIZE(g_szMsg))
  994. return ERROR_INSUFFICIENT_BUFFER;
  995. }
  996. }
  997. else if(nTime)
  998. {
  999. nQuotient=nTime/60;
  1000. nTime=nTime-nQuotient*60;
  1001. if(nQuotient)
  1002. {
  1003. temp_count = _snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L"\t%d ",nQuotient);
  1004. if (temp_count < 0) {
  1005. return ERROR_INSUFFICIENT_BUFFER;
  1006. }
  1007. nLen += temp_count;
  1008. nCheck = TnLoadString(IDR_TIME_MINUTES, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("minutes"));
  1009. if(nCheck==0) return GetLastError();
  1010. nLen += nCheck;
  1011. // check whether we have room left in the buffer.
  1012. if (nLen >= ARRAYSIZE(g_szMsg))
  1013. {
  1014. return ERROR_INSUFFICIENT_BUFFER;
  1015. }
  1016. temp_count = _snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L" %d ",nTime);
  1017. if (temp_count < 0) {
  1018. return ERROR_INSUFFICIENT_BUFFER;
  1019. }
  1020. nLen += temp_count;
  1021. nCheck = TnLoadString(IDR_TIME_SECONDS, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("seconds\n"));
  1022. if(nCheck==0) return GetLastError();
  1023. nLen += nCheck;
  1024. // check whether we have room left in the buffer.
  1025. if (nLen >= ARRAYSIZE(g_szMsg))
  1026. {
  1027. return ERROR_INSUFFICIENT_BUFFER;
  1028. }
  1029. }
  1030. else
  1031. {
  1032. temp_count = _snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1, L"\t%d ",nTime);
  1033. if (temp_count < 0) {
  1034. return ERROR_INSUFFICIENT_BUFFER;
  1035. }
  1036. nLen += temp_count;
  1037. nCheck = TnLoadString(IDR_TIME_SECONDS, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("seconds\n"));
  1038. if(nCheck==0) return GetLastError();
  1039. nLen += nCheck;
  1040. // check whether we have room left in the buffer.
  1041. if (nLen >= ARRAYSIZE(g_szMsg))
  1042. {
  1043. return ERROR_INSUFFICIENT_BUFFER;
  1044. }
  1045. }
  1046. }
  1047. else
  1048. {
  1049. wcsncpy(g_szMsg+nLen, L"\t0 ", ARRAYSIZE(g_szMsg)-nLen-1);
  1050. g_szMsg[ARRAYSIZE(g_szMsg)-1]=L'\0';
  1051. nLen += wcslen(L"\t0 ");
  1052. if (nLen >= ARRAYSIZE(g_szMsg)) {
  1053. return ERROR_INSUFFICIENT_BUFFER;
  1054. }
  1055. nCheck = TnLoadString(IDR_TIME_SECONDS, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("seconds\n"));
  1056. if(nCheck==0) return GetLastError();
  1057. nLen += nCheck;
  1058. // check whether we have room left in the buffer.
  1059. if (nLen >= ARRAYSIZE(g_szMsg))
  1060. {
  1061. return ERROR_INSUFFICIENT_BUFFER;
  1062. }
  1063. }
  1064. }
  1065. //maxconnections
  1066. nCheck = LoadString(g_hResource, IDR_MAX_CONNECTIONS, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen);
  1067. if(nCheck==0) return GetLastError();
  1068. nLen += nCheck;
  1069. // check whether we have room left in the buffer.
  1070. if (nLen >= ARRAYSIZE(g_szMsg))
  1071. {
  1072. return ERROR_INSUFFICIENT_BUFFER;
  1073. }
  1074. temp_count = _snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L"\t%d\n",V_I4(&g_arPROP[_p_MAXCONN_][0].var));
  1075. if (temp_count < 0) {
  1076. return ERROR_INSUFFICIENT_BUFFER;
  1077. }
  1078. nLen += temp_count;
  1079. //port
  1080. nCheck = LoadString(g_hResource, IDR_TELNET_PORT, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen);
  1081. if(nCheck==0) return GetLastError();
  1082. nLen += nCheck;
  1083. // check whether we have room left in the buffer.
  1084. if (nLen >= ARRAYSIZE(g_szMsg))
  1085. {
  1086. return ERROR_INSUFFICIENT_BUFFER;
  1087. }
  1088. temp_count = _snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L"\t%d\n",V_I4(&g_arPROP[_p_PORT_][0].var));
  1089. if (temp_count < 0) {
  1090. return ERROR_INSUFFICIENT_BUFFER;
  1091. }
  1092. nLen += temp_count;
  1093. //maxfail
  1094. nCheck = LoadString(g_hResource, IDR_MAX_FAILED_LOGIN_ATTEMPTS, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen);
  1095. if(nCheck==0) return GetLastError();
  1096. nLen += nCheck;
  1097. // check whether we have room left in the buffer.
  1098. if (nLen >= ARRAYSIZE(g_szMsg))
  1099. {
  1100. return ERROR_INSUFFICIENT_BUFFER;
  1101. }
  1102. temp_count = _snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L"\t%d\n",V_I4(&g_arPROP[_p_MAXFAIL_][0].var));
  1103. if (temp_count < 0) {
  1104. return ERROR_INSUFFICIENT_BUFFER;
  1105. }
  1106. nLen += temp_count;
  1107. //kill on disconnect
  1108. nCheck = LoadString(g_hResource, IDR_END_TASKS_ON_DISCONNECT, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen);
  1109. if(nCheck==0) return GetLastError();
  1110. nLen += nCheck;
  1111. // check whether we have room left in the buffer.
  1112. if (nLen >= ARRAYSIZE(g_szMsg))
  1113. {
  1114. return ERROR_INSUFFICIENT_BUFFER;
  1115. }
  1116. if(V_I4(&g_arPROP[_p_KILLALL_][0].var)==1)
  1117. {
  1118. nCheck = TnLoadString(IDR_YES, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("\tYES\n"));
  1119. if(nCheck==0) return GetLastError();
  1120. nLen += nCheck;
  1121. // check whether we have room left in the buffer.
  1122. if (nLen >= ARRAYSIZE(g_szMsg))
  1123. {
  1124. return ERROR_INSUFFICIENT_BUFFER;
  1125. }
  1126. }
  1127. else
  1128. {
  1129. nCheck = TnLoadString(IDR_NO, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("\tNO\n"));
  1130. if(nCheck==0) return GetLastError();
  1131. nLen += nCheck;
  1132. // check whether we have room left in the buffer.
  1133. if (nLen >= ARRAYSIZE(g_szMsg))
  1134. {
  1135. return ERROR_INSUFFICIENT_BUFFER;
  1136. }
  1137. }
  1138. //mode
  1139. nCheck = LoadString(g_hResource, IDR_MODE_OF_OPERATION, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen);
  1140. if(nCheck==0) return GetLastError();
  1141. nLen += nCheck;
  1142. // check whether we have room left in the buffer.
  1143. if (nLen >= ARRAYSIZE(g_szMsg))
  1144. {
  1145. return ERROR_INSUFFICIENT_BUFFER;
  1146. }
  1147. temp_count = _snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1, L"\t%s\n",(V_I4(&g_arPROP[_p_MODE_][0].var)==1) ? L"Console" : L"Stream");
  1148. if (temp_count < 0) {
  1149. return ERROR_INSUFFICIENT_BUFFER;
  1150. }
  1151. nLen += temp_count;
  1152. MyWriteConsole(g_stdout,g_szMsg,wcslen(g_szMsg));
  1153. //sec
  1154. nLen=0;
  1155. nLen = LoadString(g_hResource,IDR_AUTHENTICATION_MECHANISM, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen);
  1156. if(0 == nLen) return GetLastError();
  1157. // check whether we have room left in the buffer.
  1158. if (nLen >= ARRAYSIZE(g_szMsg))
  1159. {
  1160. return ERROR_INSUFFICIENT_BUFFER;
  1161. }
  1162. switch(V_I4(&g_arPROP[_p_SEC_][0].var))
  1163. {
  1164. case 2 :
  1165. wcsncpy(g_szMsg+nLen, L"\tNTLM\n", ARRAYSIZE(g_szMsg)-nLen-1);
  1166. g_szMsg[ARRAYSIZE(g_szMsg)-1]=L'\0';
  1167. nLen += wcslen(L"\tNTLM\n");
  1168. if (nLen >= ARRAYSIZE(g_szMsg)) {
  1169. return ERROR_INSUFFICIENT_BUFFER;
  1170. }
  1171. break;
  1172. case 4 :
  1173. wcsncpy(g_szMsg+nLen, L"\tPassword\n", ARRAYSIZE(g_szMsg)-nLen-1);
  1174. g_szMsg[ARRAYSIZE(g_szMsg)-1]=L'\0';
  1175. nLen += wcslen(L"\tPassword\n");
  1176. if (nLen >= ARRAYSIZE(g_szMsg)) {
  1177. return ERROR_INSUFFICIENT_BUFFER;
  1178. }
  1179. break;
  1180. default :
  1181. wcsncpy(g_szMsg+nLen, L"\tNTLM, Password\n", ARRAYSIZE(g_szMsg)-nLen-1);
  1182. g_szMsg[ARRAYSIZE(g_szMsg)-1]=L'\0';
  1183. nLen += wcslen(L"\tNTLM, Password\n");
  1184. if (nLen >= ARRAYSIZE(g_szMsg)) {
  1185. return ERROR_INSUFFICIENT_BUFFER;
  1186. }
  1187. break;
  1188. }
  1189. //default domain
  1190. nCheck=LoadString(g_hResource, IDR_DEFAULT_DOMAIN, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen);
  1191. if(nCheck==0) return GetLastError();
  1192. nLen += nCheck;
  1193. // check whether we have room left in the buffer.
  1194. if (nLen >= ARRAYSIZE(g_szMsg))
  1195. {
  1196. return ERROR_INSUFFICIENT_BUFFER;
  1197. }
  1198. if(NULL==wcscmp(V_BSTR(&g_arPROP[_p_DOM_][0].var), L"."))
  1199. {
  1200. if(setDefaultDomainToLocaldomain(wzDomain))
  1201. {
  1202. temp_count = _snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1, L"\t%s\n",wzDomain);
  1203. if (temp_count < 0) {
  1204. return ERROR_INSUFFICIENT_BUFFER;
  1205. }
  1206. nLen += temp_count;
  1207. }
  1208. else
  1209. {
  1210. temp_count = _snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1, L"\t%s\n",V_BSTR(&g_arPROP[_p_DOM_][0].var));
  1211. if (temp_count < 0) {
  1212. return ERROR_INSUFFICIENT_BUFFER;
  1213. }
  1214. nLen += temp_count;
  1215. }
  1216. }
  1217. else
  1218. {
  1219. temp_count = _snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L"\t%s\n",V_BSTR(&g_arPROP[_p_DOM_][0].var));
  1220. if (temp_count < 0) {
  1221. return ERROR_INSUFFICIENT_BUFFER;
  1222. }
  1223. nLen += temp_count;
  1224. }
  1225. //state of the service
  1226. nCheck = LoadString(g_hResource, IDR_STATE, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen);
  1227. if(nCheck==0) return GetLastError();
  1228. nLen += nCheck;
  1229. // check whether we have room left in the buffer.
  1230. if (nLen >= ARRAYSIZE(g_szMsg))
  1231. {
  1232. return ERROR_INSUFFICIENT_BUFFER;
  1233. }
  1234. switch(g_hServiceStatus.dwCurrentState)
  1235. {
  1236. case SERVICE_STOPPED :
  1237. nCheck = TnLoadString(IDR_STATUS_STOPPED, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("\tStopped\n"));
  1238. if(nCheck==0) return GetLastError();
  1239. break;
  1240. case SERVICE_RUNNING :
  1241. nCheck = TnLoadString(IDR_STATUS_RUNNING, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("\tRunning\n"));
  1242. if(nCheck==0) return GetLastError();
  1243. break;
  1244. case SERVICE_PAUSED :
  1245. nCheck = TnLoadString(IDR_STATUS_PAUSED, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("\tPaused\n"));
  1246. if(nCheck==0) return GetLastError();
  1247. break;
  1248. case SERVICE_START_PENDING:
  1249. nCheck = TnLoadString(IDR_STATUS_START_PENDING, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("\tStart Pending\n"));
  1250. if(nCheck==0) return GetLastError();
  1251. break;
  1252. case SERVICE_STOP_PENDING :
  1253. nCheck = TnLoadString(IDR_STATUS_STOP_PENDING, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("\tStop Pending\n"));
  1254. if(nCheck==0) return GetLastError();
  1255. break;
  1256. case SERVICE_CONTINUE_PENDING:
  1257. nCheck = TnLoadString(IDR_STATUS_CONTINUE_PENDING, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("\tContinue Pending\n"));
  1258. if(nCheck==0) return GetLastError();
  1259. break;
  1260. case SERVICE_PAUSE_PENDING:
  1261. nCheck = TnLoadString(IDR_STATUS_PAUSE_PENDING, g_szMsg+nLen, MAX_BUFFER_SIZE-nLen,_T("\tPause Pending\n"));
  1262. if(nCheck==0) return GetLastError();
  1263. break;
  1264. default :
  1265. nCheck = 0;
  1266. break;
  1267. }
  1268. nLen += nCheck;
  1269. MyWriteConsole(g_stdout,g_szMsg,wcslen(g_szMsg));
  1270. return S_OK;
  1271. }
  1272. /*--
  1273. SesidInit() functions gets the handle to the session
  1274. manager interface.
  1275. --*/
  1276. #define FOUR_K 4096
  1277. HRESULT SesidInit()
  1278. {
  1279. HRESULT hr = S_OK;
  1280. COSERVERINFO serverInfo = { 0 };
  1281. MULTI_QI qi = {&IID_IManageTelnetSessions, NULL, S_OK};
  1282. CLSCTX server_type_for_com = CLSCTX_LOCAL_SERVER;
  1283. COAUTHINFO com_auth_info = { 0 };
  1284. COAUTHIDENTITY com_auth_identity = { 0 };
  1285. wchar_t full_user_name[FOUR_K + 1] = { 0 }; // hack for now
  1286. if (g_arVALOF[_p_CNAME_]) // a remote box has been specified
  1287. {
  1288. server_type_for_com = CLSCTX_REMOTE_SERVER;
  1289. serverInfo.pwszName = g_arVALOF[_p_CNAME_];
  1290. // printf("BASKAR: Remote Machine name added\n");
  1291. }
  1292. if (g_arVALOF[_p_USER_]) // A user name has been specified, so go with it
  1293. {
  1294. wchar_t *delimited;
  1295. wcsncpy(full_user_name, g_arVALOF[_p_USER_], FOUR_K);
  1296. delimited = StrStrIW(full_user_name, L"\\");
  1297. if (delimited)
  1298. {
  1299. *delimited = L'\0';
  1300. delimited ++;
  1301. com_auth_identity.Domain = full_user_name;
  1302. com_auth_identity.User = delimited;
  1303. // printf("BASKAR: Domain\\User name added\n");
  1304. }
  1305. else
  1306. {
  1307. com_auth_identity.User = full_user_name;
  1308. // printf("BASKAR: Just User name added\n");
  1309. }
  1310. com_auth_identity.UserLength = lstrlenW(com_auth_identity.User);
  1311. if (com_auth_identity.Domain)
  1312. {
  1313. com_auth_identity.DomainLength = lstrlenW(com_auth_identity.Domain);
  1314. }
  1315. if (g_arVALOF[_p_PASSWD_])
  1316. {
  1317. com_auth_identity.Password = g_arVALOF[_p_PASSWD_];
  1318. com_auth_identity.PasswordLength = lstrlenW(com_auth_identity.Password);
  1319. // printf("BASKAR: Password added\n");
  1320. }
  1321. com_auth_identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  1322. com_auth_info.dwAuthnSvc = RPC_C_AUTHN_WINNT;
  1323. com_auth_info.dwAuthzSvc = RPC_C_AUTHZ_NONE;
  1324. com_auth_info.pwszServerPrincName = NULL;
  1325. com_auth_info.dwAuthnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
  1326. com_auth_info.dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
  1327. com_auth_info.pAuthIdentityData = &com_auth_identity;
  1328. com_auth_info.dwCapabilities = EOAC_NONE;
  1329. serverInfo.pAuthInfo = &com_auth_info;
  1330. // printf("BASKAR: Auth Info added\n");
  1331. }
  1332. // No need to worry about the CoInitialize() as we have done that in Initialize()
  1333. // function.
  1334. hr = CoCreateInstanceEx(
  1335. CLSID_EnumTelnetClientsSvr,
  1336. NULL,
  1337. server_type_for_com,
  1338. &serverInfo,
  1339. 1,
  1340. &qi
  1341. );
  1342. // We no longer require password - clear it
  1343. TnClearPasswd();
  1344. if( SUCCEEDED(hr) && SUCCEEDED(qi.hr) )
  1345. {
  1346. // if (g_arVALOF[_p_USER_])
  1347. // {
  1348. // hr = CoSetProxyBlanket(
  1349. // (IUnknown*)qi.pItf, // This is the proxy interface
  1350. // com_auth_info.dwAuthnSvc,
  1351. // com_auth_info.dwAuthzSvc,
  1352. // com_auth_info.pwszServerPrincName,
  1353. // com_auth_info.dwAuthnLevel,
  1354. // com_auth_info.dwImpersonationLevel,
  1355. // &com_auth_identity,
  1356. // com_auth_info.dwCapabilities
  1357. // );
  1358. // }
  1359. // Now get the interface
  1360. g_pIManageTelnetSessions = ( IManageTelnetSessions* )qi.pItf;
  1361. }
  1362. else
  1363. {
  1364. g_pIManageTelnetSessions= NULL;
  1365. if (hr == E_ACCESSDENIED)
  1366. {
  1367. ShowError(IDS_E_CANNOT_MANAGE_TELNETSERVER);
  1368. }
  1369. else
  1370. {
  1371. ShowError(IDS_E_CANNOT_CONTACT_TELNETSERVER);
  1372. }
  1373. hr = E_FAIL;
  1374. }
  1375. return hr;
  1376. }
  1377. #undef FOUR_K
  1378. /*--
  1379. This function gets a handle to session manager interface
  1380. using sesidinit and also gets all the sessions into an array.
  1381. --*/
  1382. HRESULT ListUsers()
  1383. {
  1384. BSTR bstrSessionInfo;
  1385. HRESULT hRes=S_OK;
  1386. wchar_t *wzAllSession;
  1387. //List Users gets all the session Info into this BSTR.
  1388. if(g_pIManageTelnetSessions == NULL )
  1389. {
  1390. if(FAILED(hRes=SesidInit()))
  1391. return hRes;
  1392. }
  1393. // DebugBreak();
  1394. if(g_pIManageTelnetSessions == NULL )
  1395. {
  1396. // Still you didn't get the interface handle
  1397. // what else can we do? In case of any error in getting the handle, we would
  1398. // have printed the error message in SesidInit(). So just bail out here.
  1399. // This code path should never get executed.
  1400. return S_FALSE;
  1401. }
  1402. hRes =g_pIManageTelnetSessions->GetTelnetSessions(&bstrSessionInfo);
  1403. if( FAILED( hRes ) || (NULL == bstrSessionInfo))
  1404. {
  1405. _tprintf( TEXT("Error: GetEnumClients(): 0x%x\n"), hRes );
  1406. //Load a String here.
  1407. return hRes;
  1408. }
  1409. wzAllSession=(wchar_t *)bstrSessionInfo;
  1410. //parsing the bstrSessionInfo into each session and placing it into the
  1411. //global array g_ppwzSessionInfo for other functions to use it.
  1412. g_nNumofSessions=_wtoi(wcstok(wzAllSession,session_separator));
  1413. if(!g_nNumofSessions)
  1414. {
  1415. return hRes;
  1416. }
  1417. if((g_ppwzSessionInfo=(wchar_t**)malloc(g_nNumofSessions*sizeof(wchar_t*)))==NULL)
  1418. {
  1419. ShowError(IDS_E_OUTOFMEMORY);//BB
  1420. return E_OUTOFMEMORY;
  1421. }
  1422. for(int i=0;i<g_nNumofSessions;i++)
  1423. {
  1424. g_ppwzSessionInfo[i]=wcstok(NULL,session_separator);
  1425. }
  1426. return hRes;
  1427. }
  1428. /*--
  1429. TerminateSession terminates all sessions or given sessionid's session.
  1430. --*/
  1431. HRESULT TerminateSession(void )
  1432. {
  1433. HRESULT hRes=S_OK;int i;
  1434. if(FAILED(hRes=ListUsers()))
  1435. goto End;
  1436. if(g_nNumofSessions==0)
  1437. {
  1438. if(LoadString(g_hResource,IDR_NO_ACTIVE_SESSION,g_szMsg,MAX_BUFFER_SIZE)==0)
  1439. return GetLastError();
  1440. MyWriteConsole(g_stdout,g_szMsg,wcslen(g_szMsg));
  1441. return S_OK;
  1442. }
  1443. if(g_nSesid!=-1&&CheckSessionID()==0)
  1444. { ShowError(IDR_INVALID_SESSION);
  1445. return S_OK;
  1446. }
  1447. for(i=0;i<g_nNumofSessions;i++)
  1448. {
  1449. wchar_t* wzId=wcstok(g_ppwzSessionInfo[i],session_data_separator);
  1450. if(g_nSesid!=-1)
  1451. if(g_nSesid!=_wtoi(wzId))
  1452. continue;
  1453. hRes= g_pIManageTelnetSessions->TerminateSession(_wtoi(wzId));
  1454. }
  1455. if( FAILED( hRes ) )
  1456. {
  1457. _tprintf( TEXT("Error: GetEnumClients(): 0x%x\n"), hRes );
  1458. //Load a String here.
  1459. return E_FAIL;
  1460. }
  1461. End:
  1462. return hRes;
  1463. }
  1464. /*--
  1465. This function gets a handle to session manager interface
  1466. using sesidinit and list users and sends message to the
  1467. corresponding sessions.
  1468. --*/
  1469. HRESULT MessageSession(void)
  1470. {
  1471. HRESULT hRes=S_OK;
  1472. int i=0;
  1473. if(FAILED(hRes=ListUsers()))
  1474. goto End;
  1475. if(g_nNumofSessions==0)
  1476. {
  1477. if(LoadString(g_hResource,IDR_NO_ACTIVE_SESSION,g_szMsg,MAX_BUFFER_SIZE)==0)
  1478. return GetLastError();
  1479. MyWriteConsole(g_stdout,g_szMsg,wcslen(g_szMsg));
  1480. return S_OK;
  1481. }
  1482. if(g_nSesid!=-1&&CheckSessionID()==0)
  1483. {
  1484. ShowError(IDR_INVALID_SESSION);
  1485. return S_OK;
  1486. }
  1487. if(g_nSesid!=-1)
  1488. hRes = g_pIManageTelnetSessions->SendMsgToASession(g_nSesid,g_bstrMessage);
  1489. else
  1490. {
  1491. for(i=0;i<g_nNumofSessions;i++)
  1492. {
  1493. wchar_t* wzId=wcstok(g_ppwzSessionInfo[i],session_data_separator);
  1494. if(g_nSesid!=-1)
  1495. if(g_nSesid!=_wtoi(wzId))
  1496. continue;
  1497. hRes= g_pIManageTelnetSessions->SendMsgToASession(_wtoi(wzId),g_bstrMessage);
  1498. }
  1499. }
  1500. if( FAILED( hRes ) )
  1501. {
  1502. _tprintf( TEXT("Error: GetEnumClients(): 0x%x\n"), hRes );
  1503. //Load a String here.
  1504. return E_FAIL;
  1505. }
  1506. if(0==LoadString(g_hResource,IDR_MESSAGE_SENT,g_szMsg,MAX_BUFFER_SIZE))
  1507. return GetLastError();
  1508. MyWriteConsole(g_stdout,g_szMsg,wcslen(g_szMsg));
  1509. End:
  1510. return hRes;
  1511. }
  1512. /*--
  1513. This function gets a handle to session manager interface
  1514. using sesidinit and list users and shows all the corresponding sessions.
  1515. --*/
  1516. HRESULT ShowSession(void)
  1517. {
  1518. HRESULT hRes=S_OK;
  1519. int nLen=0, temp_count;
  1520. int nCheck=0,i;
  1521. if(FAILED(hRes=ListUsers()))
  1522. goto Error;
  1523. if(g_nNumofSessions==0)
  1524. {
  1525. if(LoadString(g_hResource,IDR_NO_ACTIVE_SESSION,g_szMsg,MAX_BUFFER_SIZE)==0)
  1526. return GetLastError();
  1527. MyWriteConsole(g_stdout,g_szMsg,wcslen(g_szMsg));
  1528. return S_OK;
  1529. }
  1530. if(g_nSesid!=-1&&CheckSessionID()==0)
  1531. { ShowError(IDR_INVALID_SESSION);
  1532. return S_OK;
  1533. }
  1534. temp_count = _snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L"\n%d",g_nNumofSessions);
  1535. if (temp_count < 0) {
  1536. return E_FAIL;
  1537. }
  1538. nLen += temp_count;
  1539. nCheck = LoadString(g_hResource,IDR_TELNET_SESSIONS,g_szMsg+nLen,MAX_BUFFER_SIZE-nLen);
  1540. if (nCheck == 0) {
  1541. return E_FAIL;
  1542. }
  1543. nLen += nCheck;
  1544. MyWriteConsole(g_stdout,g_szMsg,wcslen(g_szMsg));
  1545. // The following buffers are used to get the strings and print. They can not exceed Max_Path
  1546. WCHAR szMsg1[MAX_PATH+1];
  1547. WCHAR szMsg2[MAX_PATH+1];
  1548. WCHAR szMsg3[MAX_PATH+1];
  1549. WCHAR szMsg4[MAX_PATH+1];
  1550. WCHAR szMsg5[MAX_PATH+1];
  1551. WCHAR szTemp[MAX_BUFFER_SIZE] = { 0 };
  1552. if(LoadString(g_hResource,IDR_DOMAIN,szMsg1, ARRAYSIZE(szMsg1)-1)==0)
  1553. return E_FAIL;
  1554. if(LoadString(g_hResource,IDR_USERNAME,szMsg2,ARRAYSIZE(szMsg2)-1)==0)
  1555. return E_FAIL;
  1556. if(LoadString(g_hResource,IDR_CLIENT,szMsg3,ARRAYSIZE(szMsg3)-1)==0)
  1557. return E_FAIL;
  1558. if(LoadString(g_hResource,IDR_LOGONDATE,szMsg4,ARRAYSIZE(szMsg4)-1)==0)
  1559. return E_FAIL;
  1560. //IDR_LOGONDATE itself contains the IDR_LOGONTIME also
  1561. // if(LoadString(g_hResource,IDR_LOGONTIME,szMsg5,ARRAYSIZE(szMsg5)-1)==0)
  1562. // return E_FAIL;
  1563. if(LoadString(g_hResource,IDR_IDLETIME,szMsg5,ARRAYSIZE(szMsg5)-1)==0)
  1564. return E_FAIL;
  1565. /*
  1566. Getting some problem with this LoadString and swprintf interleaving here...hence the above
  1567. brute force approach.
  1568. nLen+=LoadString(g_hResource,IDR_DOMAIN,szMsg+nLen,MAX_BUFFER_SIZE-nLen);
  1569. nLen+=_snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L"%s",",");
  1570. nLen+=LoadString(g_hResource,IDR_USERNAME,szMsg+nLen,MAX_BUFFER_SIZE-nLen);
  1571. nLen+=_snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L"%s",L",");
  1572. nLen+=LoadString(g_hResource,IDR_CLIENT,szMsg+nLen,MAX_BUFFER_SIZE-nLen);
  1573. nLen+=_snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L",");
  1574. nLen+=LoadString(g_hResource,IDR_LOGONDATE,szMsg+nLen,MAX_BUFFER_SIZE-nLen);
  1575. nLen+=_snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L",");
  1576. nLen+=LoadString(g_hResource,IDR_LOGONTIME,szMsg+nLen,MAX_BUFFER_SIZE-nLen);
  1577. nLen+=_snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L",");
  1578. nLen+=LoadString(g_hResource,IDR_IDLETIME,szMsg+nLen,MAX_BUFFER_SIZE-nLen);
  1579. _putws(szMsg);
  1580. */
  1581. //Stores the Formatted headed in the g_szMsg
  1582. formatShowSessionsDisplay();
  1583. _snwprintf(szTemp,MAX_BUFFER_SIZE-1,g_szMsg,L"ID",szMsg1,szMsg2,szMsg3,szMsg4,szMsg5);
  1584. MyWriteConsole(g_stdout,szTemp,wcslen(szTemp));
  1585. nLen = _snwprintf(szTemp,MAX_BUFFER_SIZE-1,g_szMsg,L" ",L" ",L" ",L" ",L" ",L"(hh:mm:ss)");
  1586. MyWriteConsole(g_stdout,szTemp,wcslen(szTemp));
  1587. for(i=1;i<nLen;i++)
  1588. putwchar(L'-');
  1589. nLen=0;
  1590. for(i=0;i<g_nNumofSessions;i++)
  1591. {
  1592. wchar_t* wzId=wcstok(g_ppwzSessionInfo[i],session_data_separator);
  1593. if(g_nSesid!=-1)
  1594. if(g_nSesid!=_wtoi(wzId))
  1595. continue;
  1596. wchar_t* wzDomain=wcstok(NULL,session_data_separator);
  1597. wchar_t* wzUser=wcstok(NULL,session_data_separator);
  1598. wchar_t* wzClient=wcstok(NULL,session_data_separator);
  1599. if (NULL == wzDomain)
  1600. {
  1601. wzDomain = L"";
  1602. }
  1603. if (NULL == wzUser)
  1604. {
  1605. wzUser = L"";
  1606. }
  1607. if (NULL == wzClient)
  1608. {
  1609. wzClient = L"";
  1610. }
  1611. wchar_t* wzYear=wcstok(NULL,session_data_separator);
  1612. wchar_t* wzMonth=wcstok(NULL,session_data_separator);
  1613. wchar_t* wzDayOfWeek=wcstok(NULL,session_data_separator);
  1614. wchar_t* wzDay=wcstok(NULL,session_data_separator);
  1615. wchar_t* wzHour=wcstok(NULL,session_data_separator);
  1616. wchar_t* wzMinute=wcstok(NULL,session_data_separator);
  1617. wchar_t* wzSecond=wcstok(NULL,session_data_separator);
  1618. BSTR wzLocalDate;
  1619. if(FAILED(hRes=ConvertUTCtoLocal(wzYear,wzMonth,wzDayOfWeek,wzDay,wzHour,wzMinute,wzSecond,& wzLocalDate)))
  1620. goto Error;
  1621. wchar_t* wzIdleTimeInSeconds=wcstok(NULL,session_data_separator); //There is a constant that not required and hence that is skipped
  1622. wzIdleTimeInSeconds=wcstok(NULL,session_data_separator);//Getting the Idle time in seconds
  1623. wchar_t wzIdleTime[MAX_PATH + 1]; // To store time. CAN NOT EXCEED MAX_PATH
  1624. wzHour=_itow(_wtoi(wzIdleTimeInSeconds)/3600,wzHour,10);
  1625. int RemSeconds=_wtoi(wzIdleTimeInSeconds)%3600;
  1626. wchar_t local_minute[3];
  1627. wchar_t local_second[3];
  1628. wzMinute=(wchar_t*) local_minute;
  1629. wzSecond=(wchar_t*) local_second;
  1630. wzMinute=_itow(RemSeconds/60,wzMinute,10);
  1631. RemSeconds=_wtoi(wzIdleTimeInSeconds)%60;
  1632. wzSecond=_itow(RemSeconds,wzSecond,10);
  1633. if(1==wcslen(wzMinute)) //Add one more zero, if it is of single digit
  1634. {
  1635. wcscat(wzMinute,L"0"); //append at the last and reverse it
  1636. wzMinute=_wcsrev(wzMinute);
  1637. }
  1638. if(1==wcslen(wzSecond))
  1639. {
  1640. wcscat(wzSecond,L"0");
  1641. wzSecond=_wcsrev(wzSecond);
  1642. }
  1643. _snwprintf(wzIdleTime, ARRAYSIZE(wzIdleTime)-1, L"%s:%s:%s", wzHour, wzMinute, wzSecond);
  1644. wzIdleTime[ARRAYSIZE(wzIdleTime)-1] = L'\0'; // ensure NULL termination
  1645. putwchar(L'\n');
  1646. _snwprintf(szTemp,MAX_BUFFER_SIZE-1,g_szMsg,wzId,wzDomain,wzUser,wzClient,wzLocalDate,wzIdleTime);
  1647. MyWriteConsole(g_stdout,szTemp,wcslen(szTemp));
  1648. //free the memory allotted
  1649. if (wzLocalDate) SysFreeString(wzLocalDate);
  1650. }
  1651. Error:
  1652. return hRes;
  1653. }
  1654. /*--
  1655. CheckSessionID checks if the given session-Id is valid or not.
  1656. Should be called only when Session id is given by the user.
  1657. --*/
  1658. int CheckSessionID(void)
  1659. {
  1660. for(int i=0;i<g_nNumofSessions;i++)
  1661. {
  1662. wchar_t* wzStr=_wcsdup(g_ppwzSessionInfo[i]);
  1663. int wzID=_wtoi(wcstok(wzStr,session_data_separator));
  1664. if(g_nSesid==wzID)
  1665. return 1;
  1666. free(wzStr);
  1667. }
  1668. return 0;
  1669. }
  1670. /*--
  1671. To free any allocated memories.
  1672. --*/
  1673. void Quit(void)
  1674. {
  1675. if(g_bstrMessage)
  1676. SysFreeString(g_bstrMessage);
  1677. if(bstrLogin)
  1678. SysFreeString(bstrLogin);
  1679. if(bstrPasswd)
  1680. SysFreeString(bstrPasswd);
  1681. if(bstrNameSpc)
  1682. SysFreeString(bstrPasswd);
  1683. for(int i=0;i<_MAX_PROPS_;i++)
  1684. if(g_arVALOF[i])
  1685. free(g_arVALOF[i]);
  1686. if(V_BSTR(&g_arPROP[_p_DOM_][0].var))
  1687. SysFreeString(V_BSTR(&g_arPROP[_p_DOM_][0].var));
  1688. if(V_BSTR(&g_arPROP[_p_FNAME_][0].var))
  1689. SysFreeString(V_BSTR(&g_arPROP[_p_FNAME_][0].var));
  1690. if(g_hResource)
  1691. FreeLibrary(g_hResource);
  1692. if(g_hXPResource)
  1693. FreeLibrary(g_hXPResource);
  1694. if(g_fCoInitSuccess)
  1695. CoUninitialize();
  1696. }
  1697. HRESULT ConvertUTCtoLocal(WCHAR *wzUTCYear, WCHAR *wzUTCMonth, WCHAR *wzUTCDayOfWeek, WCHAR *wzUTCDay, WCHAR *wzUTCHour, WCHAR *wzUTCMinute, WCHAR *wzUTCSecond, BSTR * bLocalDate)
  1698. {
  1699. HRESULT hRes=S_OK;
  1700. SYSTEMTIME UniversalTime = { 0 },
  1701. LocalTime = { 0 };
  1702. DATE dtCurrent = { 0 };
  1703. DWORD dwFlags = VAR_VALIDDATE;
  1704. UDATE uSysDate = { 0 }; //local time
  1705. *bLocalDate = NULL;
  1706. UniversalTime.wYear = (WORD)_wtoi(wzUTCYear);
  1707. UniversalTime.wMonth = (WORD)_wtoi(wzUTCMonth);
  1708. UniversalTime.wDayOfWeek = (WORD)_wtoi(wzUTCDayOfWeek);
  1709. UniversalTime.wDay = (WORD)_wtoi(wzUTCDay);
  1710. UniversalTime.wDay = (WORD)_wtoi(wzUTCDay);
  1711. UniversalTime.wMinute = (WORD)_wtoi(wzUTCMinute);
  1712. UniversalTime.wHour = (WORD)_wtoi(wzUTCHour);
  1713. UniversalTime.wSecond = (WORD)_wtoi(wzUTCSecond);
  1714. UniversalTime.wMilliseconds = 0;
  1715. SystemTimeToTzSpecificLocalTime(NULL,&UniversalTime,&LocalTime);
  1716. memcpy(&uSysDate.st,&LocalTime,sizeof(SYSTEMTIME));
  1717. hRes = VarDateFromUdate( &uSysDate, dwFlags, &dtCurrent );
  1718. if(SUCCEEDED(hRes))
  1719. {
  1720. hRes=VarBstrFromDate( dtCurrent,
  1721. MAKELCID( MAKELANGID( LANG_NEUTRAL, SUBLANG_SYS_DEFAULT ), SORT_DEFAULT ),
  1722. LOCALE_NOUSEROVERRIDE, bLocalDate);
  1723. }
  1724. return hRes;
  1725. }
  1726. //This function is to notify whether the user is allowed to change the maximum number of connections that could be established
  1727. //on the Telnet Server. It is to be noted that the user is not allowed to change the maximum number of connections to more than
  1728. //two(2 is default) if he is using Whistler and SFU is not installed.
  1729. // Commented out this function, as no more use it.
  1730. // WE HAVE DECIDED TO MAKE THE BEHAVIOR SIMILAR TO WIN2K AND NO DIFFERENT
  1731. // SO NO SPL. CHECK REQUIRED FOR WHISTLER (WINDOWS XP)
  1732. /*int IsMaxConnChangeAllowed()
  1733. {
  1734. BOOL fAllow=TRUE;
  1735. if(IsWhistlerTheOS())
  1736. if(!IsSFUInstalled())
  1737. fAllow=FALSE;
  1738. return fAllow;
  1739. }*/
  1740. HRESULT IsWhistlerTheOS(BOOL *fWhistler)
  1741. {
  1742. HKEY hReg=NULL;
  1743. DWORD nSize = 256;
  1744. DWORD nType=REG_SZ;
  1745. TCHAR szDataBuffer[256];
  1746. HRESULT hRes = S_OK;
  1747. *fWhistler = FALSE;
  1748. if(NULL==g_hkeyHKLM)
  1749. {
  1750. // Connect to the registry if not already done
  1751. if(FAILED(hRes = GetConnection(g_arVALOF[_p_CNAME_])))
  1752. goto End;
  1753. }
  1754. if(ERROR_SUCCESS==(hRes=RegOpenKeyEx(g_hkeyHKLM,
  1755. _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"),
  1756. 0,
  1757. KEY_QUERY_VALUE,
  1758. &hReg)))
  1759. if(ERROR_SUCCESS == (hRes=RegQueryValueEx(hReg,
  1760. _T("CurrentBuildNumber"),
  1761. NULL,
  1762. &nType,
  1763. (LPBYTE)szDataBuffer,
  1764. &nSize)))
  1765. {
  1766. if(wcscmp(szDataBuffer,L"2195")>0)
  1767. *fWhistler=TRUE;
  1768. }
  1769. // Print the error message.
  1770. if(FAILED(hRes))
  1771. PrintFormattedErrorMessage(LONG(hRes));
  1772. if(hReg)
  1773. RegCloseKey(hReg);
  1774. End:
  1775. return hRes;
  1776. }
  1777. BOOL IsSFUInstalled()
  1778. {
  1779. HKEY hRegistry=NULL;
  1780. HKEY hHive=NULL;
  1781. DWORD nSize;
  1782. char *szDataBuffer;
  1783. BOOL fSFU=FALSE;
  1784. if(ERROR_SUCCESS == RegConnectRegistry(g_arVALOF[_p_CNAME_],
  1785. HKEY_LOCAL_MACHINE,
  1786. &hRegistry))
  1787. {
  1788. if(ERROR_SUCCESS== RegOpenKeyEx(hRegistry,
  1789. _T("SOFTWARE\\Microsoft\\Services For UNIX"),
  1790. 0,
  1791. KEY_READ,
  1792. &hHive))
  1793. fSFU=TRUE;
  1794. }
  1795. if(hHive)
  1796. RegCloseKey(hHive);
  1797. if(hRegistry)
  1798. RegCloseKey(hRegistry);
  1799. return fSFU;
  1800. }
  1801. //This is only for the display and this will not change the current registry value;
  1802. //The value in the registry is retained. (Which is ".")
  1803. BOOL setDefaultDomainToLocaldomain(WCHAR wzDomain[])
  1804. {
  1805. if(S_OK!=GetDomainHostedByThisMc(wzDomain))
  1806. return FALSE;
  1807. return TRUE;
  1808. }
  1809. void formatShowSessionsDisplay()
  1810. {
  1811. int i,temp_count;
  1812. int nLen=0;
  1813. wchar_t* ppwzSessionInfo=NULL;
  1814. unsigned int nMaxDomainFieldLength=0;
  1815. unsigned int nMaxUserFieldLength=0;
  1816. unsigned int nMaxClientFieldLength=0;
  1817. for(i=0;i<g_nNumofSessions;i++)
  1818. {
  1819. ppwzSessionInfo=_wcsdup(g_ppwzSessionInfo[i]);
  1820. wcstok(ppwzSessionInfo,session_data_separator);
  1821. WCHAR* wzDomain=wcstok(NULL,session_data_separator);
  1822. WCHAR* wzUser=wcstok(NULL,session_data_separator);
  1823. WCHAR* wzClient=wcstok(NULL,session_data_separator);
  1824. /*
  1825. For some strange reason wcstok on : returns NULL if there us an empty string between ::
  1826. so any of the above tokens could be NULL
  1827. */
  1828. if (wzDomain && (nMaxDomainFieldLength < wcslen(wzDomain)))
  1829. {
  1830. nMaxDomainFieldLength=wcslen(wzDomain);
  1831. }
  1832. if (wzUser && (nMaxUserFieldLength < wcslen(wzUser)))
  1833. {
  1834. nMaxUserFieldLength=wcslen(wzUser);
  1835. }
  1836. if (wzClient && (nMaxClientFieldLength < wcslen(wzClient)))
  1837. {
  1838. nMaxClientFieldLength=wcslen(wzClient);
  1839. }
  1840. free(ppwzSessionInfo);
  1841. }
  1842. nMaxDomainFieldLength+=2; //adding 2 for spaces (arbit)
  1843. nMaxUserFieldLength+=2;
  1844. nMaxClientFieldLength+=2;
  1845. /// "\n%-3s%-11s%-14s%-11s%-11s%-11s%-4s\n"
  1846. /// id domain user client logondate time idletime
  1847. /// Hard code to 11 and 14 so that they have a good look
  1848. if(nMaxDomainFieldLength < 11)
  1849. nMaxDomainFieldLength=11;
  1850. if(nMaxUserFieldLength < 14)
  1851. nMaxUserFieldLength=14;
  1852. if(nMaxClientFieldLength < 11)
  1853. nMaxClientFieldLength=11;
  1854. _putws(L"\n");
  1855. nLen=wcslen(wcscpy(g_szMsg,L"%-6s"));
  1856. temp_count = _snwprintf(g_szMsg+nLen, MAX_BUFFER_SIZE-nLen-1,L"%%-%ds%%-%ds%%-%ds",nMaxDomainFieldLength,nMaxUserFieldLength,nMaxClientFieldLength);
  1857. if (temp_count < 0) {
  1858. return;
  1859. }
  1860. nLen += temp_count;
  1861. wcscpy(g_szMsg+nLen,L"%-22s%-4s\n");
  1862. //IDR_SESSION_HEADER_FORMAT
  1863. }
  1864. //The function queries the registry and returns whether the OS belongs to ServerClass.
  1865. BOOL IsServerClass()
  1866. {
  1867. HKEY hReg=NULL;
  1868. DWORD nSize = 256;
  1869. DWORD nType=REG_SZ;
  1870. TCHAR szDataBuffer[256];
  1871. LONG LError;
  1872. BOOL fServerClass=FALSE;
  1873. if(ERROR_SUCCESS== RegOpenKeyEx(g_hkeyHKLM,
  1874. _T("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"),
  1875. 0,
  1876. KEY_QUERY_VALUE,
  1877. &hReg))
  1878. if(ERROR_SUCCESS == (LError=RegQueryValueEx(hReg,
  1879. _T("ProductType"),
  1880. NULL,
  1881. &nType,
  1882. (LPBYTE)szDataBuffer,
  1883. &nSize)))
  1884. {
  1885. if((NULL==_wcsicmp(szDataBuffer,L"ServerNT")) || (NULL == _wcsicmp(szDataBuffer,L"LanmanNT")))
  1886. fServerClass=TRUE;
  1887. }
  1888. if(hReg)
  1889. RegCloseKey(hReg);
  1890. return fServerClass;
  1891. }