Source code of Windows XP (NT5)
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.

533 lines
15 KiB

  1. //Copyright (c) 1998 - 1999 Microsoft Corporation
  2. /*******************************************************************************
  3. *
  4. * helpers.cpp
  5. *
  6. * WINCFG helper functions
  7. *
  8. * copyright notice: Copyright 1994, Citrix Systems Inc.
  9. *
  10. * $Author: thanhl $ Butch Davis
  11. *
  12. * $Log: N:\NT\PRIVATE\UTILS\CITRIX\WINUTILS\WINCFG\VCS\HELPERS.CPP $
  13. *
  14. * Rev 1.17 15 Jul 1997 17:08:36 thanhl
  15. * Add support for Required PDs
  16. *
  17. * Rev 1.16 27 Jun 1997 15:58:34 butchd
  18. * Registry changes for Wds/Tds/Pds/Cds
  19. *
  20. * Rev 1.15 19 Jun 1997 19:22:16 kurtp
  21. * update
  22. *
  23. * Rev 1.14 28 Feb 1997 17:59:38 butchd
  24. * update
  25. *
  26. * Rev 1.13 24 Sep 1996 16:21:42 butchd
  27. * update
  28. *
  29. *******************************************************************************/
  30. /*
  31. * include files
  32. */
  33. #include "stdafx.h"
  34. #include "wincfg.h"
  35. #include "optdlg.h"
  36. #ifdef _DEBUG
  37. #undef THIS_FILE
  38. static char BASED_CODE THIS_FILE[] = __FILE__;
  39. #endif
  40. extern CWincfgApp *pApp;
  41. extern "C" LPCTSTR WinUtilsAppName;
  42. extern "C" HWND WinUtilsAppWindow;
  43. extern "C" HINSTANCE WinUtilsAppInstance;
  44. /*
  45. * Define global variables for command line parsing helper.
  46. */
  47. USHORT g_help = FALSE;
  48. USHORT g_RegistryOnly = FALSE;
  49. USHORT g_Add = FALSE;
  50. WDNAME g_szType = { TEXT("") };
  51. PDNAME g_szTransport = { TEXT("") };
  52. ULONG g_ulCount = 0;
  53. USHORT g_Install = FALSE; // hidden switch to let us know we're invoked by Setup
  54. USHORT g_Batch = FALSE; // TRUE if an auto-command was specified;
  55. // FALSE otherwise
  56. /*
  57. * This is the structure vector to be sent to ParseCommandLine.
  58. */
  59. TOKMAP tokenmap[] =
  60. {
  61. /*-------------------------------------------------------------------------
  62. -- Retail Switches
  63. -------------------------------------------------------------------------*/
  64. { HELP_SWITCH, TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &g_help },
  65. { REGISTRYONLY_SWITCH, TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &g_RegistryOnly },
  66. { ADD_SWITCH, TMFLAG_OPTIONAL, TMFORM_STRING, WDNAME_LENGTH, g_szType },
  67. { TRANSPORT_SWITCH, TMFLAG_OPTIONAL, TMFORM_STRING, PDNAME_LENGTH, g_szTransport },
  68. { COUNT_SWITCH, TMFLAG_OPTIONAL, TMFORM_ULONG, sizeof(ULONG), &g_ulCount },
  69. /*-------------------------------------------------------------------------
  70. -- Debug or Hidden switches
  71. -------------------------------------------------------------------------*/
  72. { INSTALL_SWITCH, TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &g_Install },
  73. /*-------------------------------------------------------------------------
  74. -- POSITIONAL PARAMETERS
  75. -------------------------------------------------------------------------*/
  76. /*-------------------------------------------------------------------------
  77. -- END OF LIST
  78. -------------------------------------------------------------------------*/
  79. { NULL, 0, 0, 0, NULL }
  80. };
  81. TOKMAP *ptm = tokenmap;
  82. ////////////////////////////////////////////////////////////////////////////////
  83. // helper functions
  84. /*******************************************************************************
  85. *
  86. * CommandLineHelper - helper function
  87. *
  88. * Parse the command line for optional parameters. This routine will also
  89. * handle the request for 'help' and invalid command line parameter.
  90. *
  91. * ENTRY:
  92. * pszCommandLine (input)
  93. * Points to command line.
  94. *
  95. * EXIT:
  96. * (BOOL) TRUE if command line was parsed sucessfully or if internal error
  97. * (command line will be ignored).
  98. * FALSE if 'help' requested or error on command line (message
  99. * will have been output).
  100. *
  101. ******************************************************************************/
  102. BOOL
  103. CommandLineHelper( LPTSTR pszCommandLine )
  104. {
  105. int rc;
  106. int argc;
  107. TCHAR **argv;
  108. TCHAR szModuleName[DIRECTORY_LENGTH+1];
  109. /*
  110. * Get command line args
  111. */
  112. GetModuleFileName( AfxGetInstanceHandle(), szModuleName,
  113. lengthof(szModuleName) );
  114. if ( setargv( szModuleName, pszCommandLine, &argc, &argv ) ) {
  115. ERROR_MESSAGE((IDP_ERROR_INTERNAL_SETARGV))
  116. goto done;
  117. }
  118. /*
  119. * Parse command line args and then free them.
  120. */
  121. rc = ParseCommandLine( (argc-1), (argv+1), ptm, 0 );
  122. freeargv( argv );
  123. /*
  124. * Check for command line errors or help requested
  125. */
  126. if ( ((rc != PARSE_FLAG_NO_ERROR) &&
  127. !(rc & PARSE_FLAG_NO_PARMS))
  128. || g_help ) {
  129. if ( rc & PARSE_FLAG_NOT_ENOUGH_MEMORY ) {
  130. ERROR_MESSAGE((IDP_ERROR_INTERNAL_PARSECOMMANDLINE))
  131. goto done;
  132. } else {
  133. CommandLineUsage();
  134. return(FALSE);
  135. }
  136. }
  137. done:
  138. /*
  139. * If a batch auto command was specified, set batch flag.
  140. */
  141. if ( (g_Add = IsTokenPresent(ptm, ADD_SWITCH)) )
  142. g_Batch = TRUE;
  143. /*
  144. * Set for registry only or full registry & winstation APIs.
  145. */
  146. pApp->m_nRegistryOnly = (int)g_RegistryOnly;
  147. /*
  148. * If add is defined and no count given, set count to 1.
  149. */
  150. if ( g_Add && (g_ulCount == 0) )
  151. g_ulCount = 1;
  152. return(TRUE);
  153. } // end CommandLineHelper
  154. /*******************************************************************************
  155. *
  156. * CommandLineUsage - helper function
  157. *
  158. * Handle the request for 'help' and invalid command line parameter.
  159. *
  160. * ENTRY:
  161. * EXIT:
  162. *
  163. ******************************************************************************/
  164. void
  165. CommandLineUsage()
  166. {
  167. COptionsDlg OPTDlg;
  168. OPTDlg.DoModal();
  169. } // end CommandLineUsage
  170. /*******************************************************************************
  171. *
  172. * QueryLoggedOnCount - helper function
  173. *
  174. * Query the specified WinStation(s) to determine how many users are
  175. * currently logged on.
  176. *
  177. * ENTRY:
  178. * pWSName (input)
  179. * Points to (root) name of WinStation to query. The query will
  180. * match this name with those present in the ICA Server, including
  181. * multi-instanced WinStations.
  182. * EXIT:
  183. * (long) # of users logged onto the specified WinStation(s).
  184. *
  185. ******************************************************************************/
  186. long
  187. QueryLoggedOnCount( PWINSTATIONNAME pWSName )
  188. {
  189. long LoggedOnCount = 0;
  190. #ifdef WINSTA
  191. ULONG Entries;
  192. PLOGONID pLogonId;
  193. TCHAR *p;
  194. CWaitCursor wait;
  195. WinStationEnumerate(SERVERNAME_CURRENT, &pLogonId, &Entries);
  196. if ( pLogonId ) {
  197. for ( ULONG i = 0; i < Entries; i++ ) {
  198. /*
  199. * Check active, connected, and shadowing WinStations, and increment
  200. * the logged on count if the specified name matches the 'root'
  201. * name of current winstation.
  202. */
  203. if ( (pLogonId[i].State == State_Active) ||
  204. (pLogonId[i].State == State_Connected) ||
  205. (pLogonId[i].State == State_Shadow) ) {
  206. if ( (p = lstrchr(pLogonId[i].WinStationName, TEXT('#'))) )
  207. *p = TEXT('\0');
  208. if ( !lstrcmpi(pWSName, pLogonId[i].WinStationName) )
  209. LoggedOnCount++;
  210. }
  211. }
  212. WinStationFreeMemory(pLogonId);
  213. }
  214. #endif // WINSTA
  215. /*
  216. * Return the logged-on count.
  217. */
  218. return(LoggedOnCount);
  219. } // end QueryLoggedOnCount
  220. /*******************************************************************************
  221. *
  222. * LBInsertInstancedName - helper function
  223. *
  224. * Insert the specified 'instanced' name into the specified list box,
  225. * using a special sort based on the 'root' name and 'instance' count.
  226. *
  227. * ENTRY:
  228. * pName (input)
  229. * Pointer to name string to insert.
  230. * pListBox (input)
  231. * Pointer to CListBox object to insert name string into.
  232. *
  233. * EXIT:
  234. * (int) List box list index of name after insertion, or error code.
  235. *
  236. ******************************************************************************/
  237. int
  238. LBInsertInstancedName( LPCTSTR pName,
  239. CListBox *pListBox )
  240. {
  241. int i, count, result;
  242. TCHAR NameRoot[64], ListRoot[64];
  243. CString ListString;
  244. long NameInstance, ListInstance;
  245. /*
  246. * Form the root and instance for this name
  247. */
  248. ParseRootAndInstance( pName, NameRoot, &NameInstance );
  249. /*
  250. * Traverse list box to perform insert.
  251. */
  252. for ( i = 0, count = pListBox->GetCount(); i < count; i++ ) {
  253. /*
  254. * Fetch current list box string.
  255. */
  256. pListBox->GetText( i, ListString );
  257. /*
  258. * Parse the root and instance of the list box string.
  259. */
  260. ParseRootAndInstance( ListString, ListRoot, &ListInstance );
  261. /*
  262. * If the list box string's root is greater than the our name string's
  263. * root, or the root strings are the same but the list instance is
  264. * greater than the name string's instance, the name string belongs
  265. * at the current instance: insert it there.
  266. */
  267. if ( ((result = lstrcmpi( ListRoot, NameRoot )) > 0) ||
  268. ((result == 0) && (ListInstance > NameInstance)) )
  269. return( pListBox->InsertString( i, pName ) );
  270. }
  271. /*
  272. * Insert this name at the end of the list.
  273. */
  274. return( pListBox->InsertString( -1, pName ) );
  275. } // end LBInsertInstancedName
  276. /*******************************************************************************
  277. *
  278. * CBInsertInstancedName - helper function
  279. *
  280. * Insert the specified 'instanced' name into the specified combo box,
  281. * using a special sort based on the 'root' name and 'instance' count.
  282. *
  283. * ENTRY:
  284. * pName (input)
  285. * Pointer to name string to insert.
  286. * pComboBox (input)
  287. * Pointer to CComboBox object to insert name string into.
  288. *
  289. * EXIT:
  290. * (int) Combo box list index of name after insertion, or error code.
  291. *
  292. ******************************************************************************/
  293. int
  294. CBInsertInstancedName( LPCTSTR pName,
  295. CComboBox *pComboBox )
  296. {
  297. int i, count, result;
  298. TCHAR NameRoot[64], ListRoot[64];
  299. CString ListString;
  300. long NameInstance, ListInstance;
  301. /*
  302. * Form the root and instance for this name
  303. */
  304. ParseRootAndInstance( pName, NameRoot, &NameInstance );
  305. /*
  306. * Traverse combo box to perform insert.
  307. */
  308. for ( i = 0, count = pComboBox->GetCount(); i < count; i++ ) {
  309. /*
  310. * Fetch current combo (list) box string.
  311. */
  312. pComboBox->GetLBText( i, ListString );
  313. /*
  314. * Parse the root and instance of the list box string.
  315. */
  316. ParseRootAndInstance( ListString, ListRoot, &ListInstance );
  317. /*
  318. * If the list box string's root is greater than the our name string's
  319. * root, or the root strings are the same but the list instance is
  320. * greater than the name string's instance, or the root strings are
  321. * the same and the instances are the same but the entire list string
  322. * is greater than the entire name string, the name string belongs
  323. * at the current list position: insert it there.
  324. */
  325. if ( ((result = lstrcmpi( ListRoot, NameRoot )) > 0) ||
  326. ((result == 0) &&
  327. (ListInstance > NameInstance)) ||
  328. ((result == 0) &&
  329. (ListInstance == NameInstance) &&
  330. (lstrcmpi(ListString, pName) > 0)) )
  331. return( pComboBox->InsertString( i, pName ) );
  332. }
  333. /*
  334. * Insert this name at the end of the list.
  335. */
  336. return( pComboBox->InsertString( -1, pName ) );
  337. } // end CBInsertInstancedName
  338. /*******************************************************************************
  339. *
  340. * ParseRootAndInstance - helper function
  341. *
  342. * Parse the 'root' string and instance count for a specified string.
  343. *
  344. * ENTRY:
  345. * pString (input)
  346. * Points to the string to parse.
  347. * pRoot (output)
  348. * Points to the buffer to store the parsed 'root' string.
  349. * pInstance (output)
  350. * Points to the int variable to store the parsed instance count.
  351. *
  352. * EXIT:
  353. * ParseRootAndInstance will parse only up to the first blank character
  354. * of the string (if a blank exists).
  355. * If the string contains no 'instance' count (no trailing digits), the
  356. * pInstance variable will contain -1. If the string consists entirely
  357. * of digits, the pInstance variable will contain the conversion of those
  358. * digits and pRoot will contain a null string.
  359. *
  360. ******************************************************************************/
  361. void
  362. ParseRootAndInstance( LPCTSTR pString,
  363. LPTSTR pRoot,
  364. long *pInstance )
  365. {
  366. LPCTSTR end, p;
  367. TCHAR szString[256];
  368. /*
  369. * Make a copy of the string and terminate at first blank (if present).
  370. */
  371. lstrncpy(szString, pString, lengthof(szString));
  372. szString[lengthof(szString)-1] = TEXT('\0');
  373. lstrtok(szString, TEXT(" "));
  374. p = &(szString[lstrlen(szString)-1]);
  375. /*
  376. * Parse the instance portion of the string.
  377. */
  378. end = p;
  379. while( (p >= szString) && islstrdigit(*p) )
  380. p--;
  381. if ( p == end ) {
  382. /*
  383. * No trailing digits: indicate no 'instance' and make the 'root'
  384. * the whole string.
  385. */
  386. *pInstance = -1;
  387. lstrcpy( pRoot, szString );
  388. } else {
  389. /*
  390. * Trailing digits found (or entire string was digits): calculate
  391. * 'instance' and copy the 'root' string (null if all digits).
  392. */
  393. end = p;
  394. *pInstance = (int)lstrtol( p+1, NULL, 10 );
  395. /*
  396. * Copy 'root' string.
  397. */
  398. for ( p = szString; p <= end; pRoot++, p++ )
  399. *pRoot = *p;
  400. /*
  401. * Terminate 'root' string.
  402. */
  403. *pRoot = TEXT('\0');
  404. }
  405. } // end ParseRootAndInstance
  406. /*******************************************************************************
  407. *
  408. * GetPdConfig - helper function
  409. *
  410. * Read the PD config structure associated with the first PD in the PdList
  411. * of the specified PD class.
  412. *
  413. * ENTRY:
  414. * pPdList (input)
  415. * Points to the Pd list for selected Wd type.
  416. * PdName (input)
  417. * Specifies the Pd name to look for.
  418. * pWSConfig (input)
  419. * Pointer to WINSTATIONCONFIG2 structure to reference for Pd[0]
  420. * framing type (if SdClass == SdFrame). Can be NULL if SdClass
  421. * != SdFrame.
  422. * pPdConfig (output)
  423. * Pointer to PDCONFIG3 structure to fill.
  424. * EXIT:
  425. * nothing
  426. *
  427. ******************************************************************************/
  428. void
  429. GetPdConfig( CObList *pPdList,
  430. LPCTSTR PdName,
  431. PWINSTATIONCONFIG2 pWSConfig,
  432. PPDCONFIG3 pPdConfig )
  433. {
  434. POSITION pos;
  435. PPDLOBJECT pObject;
  436. BOOL bFound = FALSE;
  437. /*
  438. * Traverse the PD list and obtain the specified Pd's key string for query.
  439. */
  440. for ( pos = pPdList->GetHeadPosition(); pos != NULL; ) {
  441. pObject = (PPDLOBJECT)pPdList->GetNext(pos);
  442. if ( !lstrcmp(pObject->m_PdConfig.Data.PdName, PdName ) ) {
  443. bFound = TRUE;
  444. break;
  445. }
  446. }
  447. if ( bFound )
  448. *pPdConfig = pObject->m_PdConfig;
  449. } // end GetPdConfig