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.

2882 lines
84 KiB

  1. //Copyright (c) 1998 - 1999 Microsoft Corporation
  2. /*******************************************************************************
  3. *
  4. * appsvdoc.cpp
  5. *
  6. * implementation of the CAppServerDoc class
  7. *
  8. * copyright notice: Copyright 1994, Citrix Systems Inc.
  9. *
  10. * $Author: donm $ Butch Davis
  11. *
  12. * $Log: N:\nt\private\utils\citrix\winutils\tscfg\VCS\appsvdoc.cpp $
  13. *
  14. * Rev 1.54 18 Apr 1998 15:31:08 donm
  15. * Added capability bits
  16. *
  17. * Rev 1.53 14 Feb 1998 11:23:04 donm
  18. * fixed memory leak by avoiding CDocManager::OpenDocumentFile
  19. *
  20. * Rev 1.52 31 Dec 1997 09:13:50 donm
  21. * uninitialized variable in RegistryDelete
  22. *
  23. * Rev 1.51 10 Dec 1997 15:59:14 donm
  24. * added ability to have extension DLLs
  25. *
  26. * Rev 1.50 19 Jun 1997 19:21:08 kurtp
  27. * update
  28. *
  29. * Rev 1.49 25 Mar 1997 08:59:46 butchd
  30. * update
  31. *
  32. * Rev 1.48 18 Mar 1997 15:51:18 butchd
  33. * ignore system console registry entry
  34. *
  35. * Rev 1.47 10 Mar 1997 16:58:26 butchd
  36. * update
  37. *
  38. * Rev 1.46 04 Mar 1997 09:46:46 butchd
  39. * update
  40. *
  41. * Rev 1.45 04 Mar 1997 08:35:12 butchd
  42. * update
  43. *
  44. * Rev 1.44 28 Feb 1997 17:59:22 butchd
  45. * update
  46. *
  47. * Rev 1.43 11 Dec 1996 09:50:18 butchd
  48. * update
  49. *
  50. * Rev 1.42 24 Sep 1996 16:21:18 butchd
  51. * update
  52. *
  53. *******************************************************************************/
  54. /*
  55. * include files
  56. */
  57. #include "stdafx.h"
  58. #include "wincfg.h"
  59. #include "security.h"
  60. #include "appsvdoc.h"
  61. #include "rowview.h"
  62. #include "appsvvw.h"
  63. #include "ewsdlg.h"
  64. #include <string.h>
  65. #include <hydra\regapi.h> // for WIN_ENABLEWINSTATION registry entry name
  66. #ifdef _DEBUG
  67. #undef THIS_FILE
  68. static char BASED_CODE THIS_FILE[] = __FILE__;
  69. #endif
  70. extern CWincfgApp *pApp;
  71. extern "C" LPCTSTR WinUtilsAppName;
  72. extern "C" HWND WinUtilsAppWindow;
  73. extern "C" HINSTANCE WinUtilsAppInstance;
  74. PTERMLOBJECT GetWdListObject( PWDNAME pWdName);
  75. /*
  76. * Global command line variables.
  77. */
  78. ////////////////////////////////////////////////////////////////////////////////
  79. // CWinStationListObjectHint implemetation / construction
  80. IMPLEMENT_DYNAMIC(CWinStationListObjectHint, CObject)
  81. CWinStationListObjectHint::CWinStationListObjectHint()
  82. {
  83. }
  84. ////////////////////////////////////////////////////////////////////////////////
  85. // CAppServerDoc implementation / construction, destruction
  86. IMPLEMENT_SERIAL(CAppServerDoc, CDocument, 0 /*schema*/)
  87. /*******************************************************************************
  88. *
  89. * CAppServerDoc - CAppServerDoc constructor
  90. *
  91. * ENTRY:
  92. * EXIT:
  93. *
  94. ******************************************************************************/
  95. CAppServerDoc::CAppServerDoc()
  96. : m_bReadOnly(FALSE),
  97. m_pSecurityDescriptor(NULL)
  98. {
  99. } // end CAppServerDoc::CAppServerDoc
  100. /*******************************************************************************
  101. *
  102. * ~CAppServerDoc - CAppServerDoc destructor
  103. *
  104. * ENTRY:
  105. * EXIT:
  106. *
  107. ******************************************************************************/
  108. CAppServerDoc::~CAppServerDoc()
  109. {
  110. /*
  111. * Free up all WSL objects currently in use.
  112. */
  113. DeleteWSLContents();
  114. } // end CAppServerDoc::~CAppServerDoc
  115. ////////////////////////////////////////////////////////////////////////////////
  116. // CAppServerDoc class overrides
  117. /*******************************************************************************
  118. *
  119. * OnOpenDocument - CAppServerDoc member function: CDocument class override
  120. *
  121. * Reads the specified AppServer's registry and initializes the
  122. * 'document' contents.
  123. *
  124. * ENTRY:
  125. * pszPathName (input)
  126. * Name of the AppServer to access.
  127. *
  128. * EXIT:
  129. * TRUE - sucessful initialization of 'document'.
  130. * FALSE - 'document' was not properly initialized.
  131. *
  132. ******************************************************************************/
  133. BOOL
  134. CAppServerDoc::OnNewDocument( /*LPCTSTR pszPathName*/ )
  135. {
  136. POSITION pos;
  137. /*
  138. * If this user doesn't have ALL access to the WinStation registry (ie, not
  139. * an admin), set the 'admin' flag to FALSE and 'read only' flag to TRUE
  140. * to only display the user's current WinStation in the WinStation list;
  141. * otherwise set 'admin' flag to TRUE to allow all WinStations to be
  142. * displayed, with the 'read only' state being determined from the previous
  143. * AppServer check, above.
  144. */
  145. if ( RegWinStationAccessCheck(SERVERNAME_CURRENT, KEY_ALL_ACCESS) ) {
  146. m_bAdmin = FALSE;
  147. m_bReadOnly = TRUE;
  148. } else {
  149. m_bAdmin = TRUE;
  150. }
  151. /*
  152. * Obtain the user's current WinStation information.
  153. */
  154. if ( !QueryCurrentWinStation( pApp->m_CurrentWinStation,
  155. pApp->m_CurrentUserName,
  156. &(pApp->m_CurrentLogonId),
  157. &(pApp->m_CurrentWSFlags) ) ) {
  158. STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_CURRENT, GetLastError(),
  159. IDP_ERROR_QUERYCURRENTWINSTATION ))
  160. return(FALSE);
  161. }
  162. /*
  163. * Load the WSL with registry information for this AppServer.
  164. */
  165. if ( !LoadWSL(NULL/*pszPathName*/) )
  166. return(FALSE);
  167. /*
  168. * Reset the view for this document.
  169. */
  170. ((CAppServerView *)GetNextView( pos = GetFirstViewPosition() ))->
  171. ResetView( TRUE );
  172. return ( TRUE );
  173. } // end CAppServerDoc::OnOpenDocument
  174. /*******************************************************************************
  175. *
  176. * SetTitle - CAppServerDoc member function: override
  177. *
  178. * Override default to set our title the way that we want.
  179. *
  180. * ENTRY:
  181. * lpszTitle (input)
  182. * Title to set (this is ignored).
  183. * EXIT:
  184. *
  185. ******************************************************************************/
  186. void
  187. CAppServerDoc::SetTitle( LPCTSTR lpszTitle )
  188. {
  189. /*
  190. * Set our document's title, including the READONLY (User Mode)
  191. * string if needed.
  192. */
  193. if ( m_bReadOnly ) {
  194. CString ReadOnly;
  195. ReadOnly.LoadString( IDS_READONLY );
  196. CString sz = pApp->m_szCurrentAppServer + ReadOnly;
  197. CDocument::SetTitle(sz);
  198. } else
  199. CDocument::SetTitle(pApp->m_szCurrentAppServer);
  200. } // end CAppServerDoc::SetTitle
  201. ////////////////////////////////////////////////////////////////////////////////
  202. // CAppServerDoc public operations
  203. /*******************************************************************************
  204. *
  205. * IsExitAllowed - CAppServerDoc member function: public operation
  206. *
  207. * Indicate whether or not the application can be exited, based on whether
  208. * or not there are operations pending.
  209. *
  210. * ENTRY:
  211. *
  212. * EXIT:
  213. * TRUE - no operations are pending: the application can be exited.
  214. * FALSE - operations are pending: the application cannot be exited.
  215. *
  216. ******************************************************************************/
  217. BOOL
  218. CAppServerDoc::IsExitAllowed()
  219. {
  220. return (TRUE);
  221. } // end CAppServerDoc::IsExitAllowed
  222. /*******************************************************************************
  223. *
  224. * IsAddAllowed - CAppServerDoc member function: public operation
  225. *
  226. * Indicate whether or not the WSLObject associated with the specified
  227. * list index can be referenced for adding a new WinStation.
  228. *
  229. * ENTRY:
  230. *
  231. * EXIT:
  232. * (BOOL) TRUE if the WSLObject can be referenced for add; FALSE otherwise.
  233. *
  234. ******************************************************************************/
  235. BOOL
  236. CAppServerDoc::IsAddAllowed( int nIndex )
  237. {
  238. /*
  239. * If this document is 'read only' then add is not allowed.
  240. * Otherwise, it's OK.
  241. */
  242. if ( m_bReadOnly )
  243. return(FALSE);
  244. else
  245. return(TRUE);
  246. } // end CAppServerDoc::IsAddAllowed
  247. /*******************************************************************************
  248. *
  249. * IsCopyAllowed - CAppServerDoc member function: public operation
  250. *
  251. * Indicate whether or not the WSLObject associated with the specified
  252. * list index can be copied.
  253. *
  254. * ENTRY:
  255. *
  256. * EXIT:
  257. * (BOOL) TRUE if the WSLObject can be copied; FALSE otherwise.
  258. *
  259. ******************************************************************************/
  260. BOOL
  261. CAppServerDoc::IsCopyAllowed( int nIndex )
  262. {
  263. PWSLOBJECT pWSLObject;
  264. /*
  265. * If this document is 'read only' or no items yet,
  266. * then copy is not allowed.
  267. */
  268. if ( m_bReadOnly ||
  269. !(pWSLObject = GetWSLObject(nIndex)) )
  270. return(FALSE);
  271. /*
  272. * If this WinStation is the main CONSOLE, or is not a single instance
  273. * type, we can't copy.
  274. */
  275. if ( !lstrcmpi(pWSLObject->m_WinStationName, pApp->m_szSystemConsole) ||
  276. !(pWSLObject->m_Flags & WSL_SINGLE_INST) )
  277. return(FALSE);
  278. /*
  279. * The copy is allowed.
  280. */
  281. return(TRUE);
  282. } // end CAppServerDoc::IsCopyAllowed
  283. /*******************************************************************************
  284. *
  285. * IsRenameAllowed - CAppServerDoc member function: public operation
  286. *
  287. * Indicate whether or not the WSLObject associated with the specified
  288. * list index can be renamed.
  289. *
  290. * ENTRY:
  291. *
  292. * EXIT:
  293. * (BOOL) TRUE if the WSLObject can be renamed; FALSE otherwise.
  294. *
  295. ******************************************************************************/
  296. BOOL
  297. CAppServerDoc::IsRenameAllowed( int nIndex )
  298. {
  299. PWSLOBJECT pWSLObject;
  300. /*
  301. * If this document is 'read only' or no items yet,
  302. * then rename is not allowed.
  303. */
  304. if ( m_bReadOnly ||
  305. !(pWSLObject = GetWSLObject(nIndex)) )
  306. return(FALSE);
  307. /*
  308. * If this WinStation is the main CONSOLE, we can't rename.
  309. */
  310. if ( !lstrcmpi( pWSLObject->m_WinStationName, pApp->m_szSystemConsole ) )
  311. return(FALSE);
  312. /*
  313. * The rename is allowed.
  314. */
  315. return(TRUE);
  316. } // end CAppServerDoc::IsRenameAllowed
  317. /*******************************************************************************
  318. *
  319. * IsDeleteAllowed - CAppServerDoc member function: public operation
  320. *
  321. * Indicate whether or not the WSLObject associated with the specified
  322. * list index can be deleted.
  323. *
  324. * ENTRY:
  325. *
  326. * EXIT:
  327. * (BOOL) TRUE if the WSLObject can be deleted; FALSE otherwise.
  328. *
  329. ******************************************************************************/
  330. BOOL
  331. CAppServerDoc::IsDeleteAllowed( int nIndex )
  332. {
  333. PWSLOBJECT pWSLObject;
  334. /*
  335. * If this document is 'read only' or no items yet,
  336. * then delete is not allowed.
  337. */
  338. if ( m_bReadOnly ||
  339. !(pWSLObject = GetWSLObject(nIndex)) )
  340. return(FALSE);
  341. /*
  342. * If this WinStation is the main CONSOLE, we can't delete.
  343. */
  344. if ( !lstrcmpi( pWSLObject->m_WinStationName, pApp->m_szSystemConsole ) )
  345. return(FALSE);
  346. /*
  347. * The delete is allowed.
  348. */
  349. return(TRUE);
  350. } // end CAppServerDoc::IsDeleteAllowed
  351. /*******************************************************************************
  352. *
  353. * IsEditAllowed - CAppServerDoc member function: public operation
  354. *
  355. * Indicate whether or not the WSLObject associated with the specified
  356. * list index can be edited.
  357. *
  358. * ENTRY:
  359. *
  360. * EXIT:
  361. * (BOOL) TRUE if the WSLObject can be edited; FALSE otherwise.
  362. *
  363. ******************************************************************************/
  364. BOOL
  365. CAppServerDoc::IsEditAllowed( int nIndex )
  366. {
  367. /*
  368. * If no items yet, then edit is not allowed.
  369. * Otherwise, it's OK.
  370. */
  371. if ( !GetWSLObject(nIndex) )
  372. return(FALSE);
  373. else
  374. return(TRUE);
  375. } // end CAppServerDoc::IsEditAllowed
  376. /*******************************************************************************
  377. *
  378. * IsEnableAllowed - CAppServerDoc member function: public operation
  379. *
  380. * Indicate whether or not the WinStation(s) associated with the specified
  381. * WSLObject can be enabled/disabled.
  382. *
  383. * ENTRY:
  384. * bEnable (input)
  385. * TRUE: check for enable allowed; FALSE: check for disable allowed.
  386. * EXIT:
  387. * (BOOL) TRUE if the WinStation(s) can be enabled/disabled;
  388. * FALSE otherwise.
  389. *
  390. ******************************************************************************/
  391. BOOL
  392. CAppServerDoc::IsEnableAllowed( int nIndex,
  393. BOOL bEnable )
  394. {
  395. PWSLOBJECT pWSLObject;
  396. /*
  397. * If this document is 'read only' no items yet,
  398. * then enable/disable is not allowed.
  399. */
  400. if ( m_bReadOnly ||
  401. !(pWSLObject = GetWSLObject(nIndex)) )
  402. return(FALSE);
  403. /*
  404. * If this WinStation is the main CONSOLE, we can't enable/disable.
  405. */
  406. if ( !lstrcmpi( pWSLObject->m_WinStationName, pApp->m_szSystemConsole ) )
  407. return(FALSE);
  408. /*
  409. * Make sure that the WSL is 'in sync' with the registry. Return
  410. * 'enable/disable not allowed' if error.
  411. */
  412. if ( !RefreshWSLObjectState( nIndex, pWSLObject ) )
  413. return(FALSE);
  414. /*
  415. * If this WSLObject indicates that the WinStation(s) are already enabled
  416. * and enable allow is requested, or WSLObject indicates that the
  417. * WinStation(s) are already disabled and disable allow is requested,
  418. * return FALSE (can't enable/disable).
  419. */
  420. if ( (bEnable && (pWSLObject->m_Flags & WSL_ENABLED)) ||
  421. (!bEnable && !(pWSLObject->m_Flags & WSL_ENABLED)) )
  422. return(FALSE);
  423. /*
  424. * The enable/disable is allowed.
  425. */
  426. return(TRUE);
  427. } // end CAppServerDoc::IsEnableAllowed
  428. /*******************************************************************************
  429. *
  430. * GetWSLCount - CAppServerDoc member function: public operation
  431. *
  432. * Return the number of WinStationList elements defined in this document.
  433. *
  434. * ENTRY:
  435. *
  436. * EXIT:
  437. * (int) number of WinStationsList elements present in this document.
  438. *
  439. ******************************************************************************/
  440. int
  441. CAppServerDoc::GetWSLCount()
  442. {
  443. return( m_WinStationList.GetCount() );
  444. } // end CAppServerDoc::GetWSLCount
  445. /*******************************************************************************
  446. *
  447. * GetWSLObject - CAppServerDoc member function: public operation
  448. *
  449. * Retrieves the WinStation object from the WinStationObjectList that
  450. * resides at the specified index.
  451. *
  452. * ENTRY:
  453. * nIndex (input)
  454. * WinStationObjectList index of the WinStation to retrieve.
  455. *
  456. * EXIT:
  457. * PWLSOBJECT - pointer to WinStationListObject for the indexed
  458. * WinStation. NULL if list is empty.
  459. *
  460. ******************************************************************************/
  461. PWSLOBJECT
  462. CAppServerDoc::GetWSLObject( int nIndex )
  463. {
  464. if ( !GetWSLCount() )
  465. return(NULL);
  466. else
  467. return ( (PWSLOBJECT)m_WinStationList.GetAt(
  468. m_WinStationList.FindIndex( nIndex )) );
  469. } // end CAppServerDoc::GetWSLObject
  470. /*******************************************************************************
  471. *
  472. * GetWSLIndex - CAppServerDoc member function: public operation
  473. *
  474. * Retrieves the WinStation List index of WinStation list object that
  475. * matches the specified WSName.
  476. *
  477. * ENTRY:
  478. * pWSName (input)
  479. * Points to WINSTATIONNAME to compare with list objects.
  480. *
  481. * EXIT:
  482. * int - Index of the specified WSL object in the list.
  483. * -1 if an object containing the specified WSName was not found.
  484. *
  485. ******************************************************************************/
  486. int
  487. CAppServerDoc::GetWSLIndex( PWINSTATIONNAME pWSName )
  488. {
  489. POSITION pos;
  490. int nIndex = 0;
  491. /*
  492. * Traverse the WinStationList.
  493. */
  494. for ( pos = m_WinStationList.GetHeadPosition(); pos != NULL; nIndex++ ) {
  495. PWSLOBJECT pObject = (PWSLOBJECT)m_WinStationList.GetNext(pos);
  496. /*
  497. * If this is the specified WSL object, return the current index.
  498. */
  499. if ( !lstrcmpi(pObject->m_WinStationName, pWSName) )
  500. return(nIndex);
  501. }
  502. /*
  503. * WSLObject not found in the list.
  504. */
  505. return(-1);
  506. } // end CAppServerDoc::GetWSLIndex
  507. /*******************************************************************************
  508. *
  509. * GetWSLObjectNetworkMatch - CAppServerDoc member function: public operation
  510. *
  511. * Retrieves the WinStation list object (if any) from the WinStationList
  512. * that contains the specified PdName, WdName, and LanAdapter.
  513. *
  514. * ENTRY:
  515. * PdName (input)
  516. * PdName to compare.
  517. * WdName (input)
  518. * WdName to compare.
  519. * LanAdapter (input)
  520. * LanAdapter # to compare.
  521. * EXIT:
  522. * PWLSOBJECT - pointer to WinStationList object if the PdName, WdName,
  523. * and LanAdapter all matched an existing WSL entry.
  524. * NULL if no match was found.
  525. *
  526. ******************************************************************************/
  527. PWSLOBJECT
  528. CAppServerDoc::GetWSLObjectNetworkMatch( PDNAME PdName,
  529. WDNAME WdName,
  530. ULONG LanAdapter )
  531. {
  532. POSITION pos;
  533. /*
  534. * Traverse the WinStationList.
  535. */
  536. for ( pos = m_WinStationList.GetHeadPosition(); pos != NULL; ) {
  537. PWSLOBJECT pObject = (PWSLOBJECT)m_WinStationList.GetNext(pos);
  538. /*
  539. * If PdName, WdName, and LanAdapter fields match, return this
  540. * PWSLOBJECT.
  541. */
  542. if ( !lstrcmp( pObject->m_PdName, PdName ) &&
  543. !lstrcmp( pObject->m_WdName, WdName ) &&
  544. (pObject->m_LanAdapter == LanAdapter) )
  545. return(pObject);
  546. }
  547. /*
  548. * No match found.
  549. */
  550. return(NULL);
  551. } // end CAppServerDoc::GetWSLObjectNetworkMatch
  552. /*******************************************************************************
  553. *
  554. * IsAsyncDeviceAvailable - CAppServerDoc member function: public operation
  555. *
  556. * Determines if the specified Async device is available for use in
  557. * configuring a new WinStation. Availability in this context is
  558. * determined by whether or not the device is already configured for
  559. * use in an Async WinStation.
  560. *
  561. * ENTRY:
  562. * pDeviceName (input)
  563. * Points to the Async device name (NOT decorated) to check for
  564. * availablility.
  565. * pWSName (input)
  566. * Points to WINSTATIONNAME of current WinStation being edited.
  567. *
  568. * EXIT:
  569. * TRUE if the Async device is available for use; FALSE if another
  570. * WinStation is already configured to use it.
  571. *
  572. ******************************************************************************/
  573. BOOL
  574. CAppServerDoc::IsAsyncDeviceAvailable( LPCTSTR pDeviceName,
  575. PWINSTATIONNAME pWSName )
  576. {
  577. POSITION pos;
  578. ASYNCCONFIG AsyncConfig;
  579. /*
  580. * Traverse the WinStationList.
  581. */
  582. for ( pos = m_WinStationList.GetHeadPosition(); pos != NULL; ) {
  583. PWSLOBJECT pObject = (PWSLOBJECT)m_WinStationList.GetNext(pos);
  584. /*
  585. * If this is an async WinStation, the device is the same as the
  586. * one we're checking, but this is not the current WinStation being
  587. * edited, return FALSE.
  588. */
  589. if ( pObject->m_SdClass == SdAsync ) {
  590. ParseDecoratedAsyncDeviceName( pObject->m_DeviceName, &AsyncConfig );
  591. if ( !lstrcmpi(AsyncConfig.DeviceName, pDeviceName) &&
  592. lstrcmpi(pWSName, pObject->m_WinStationName) )
  593. return(FALSE);
  594. }
  595. }
  596. /*
  597. * The Async device is not configured in any Async WinStations.
  598. */
  599. return(TRUE);
  600. } // end CAppServerDoc::IsAsyncDeviceAvailable
  601. /*******************************************************************************
  602. *
  603. * IsOemTdDeviceAvailable - CAppServerDoc member function: public operation
  604. *
  605. * Determines if the specified OEM Transport device is available for use
  606. * in configuring a new WinStation. Availability in this context is
  607. * determined by whether or not the device is already configured for
  608. * use in a WinStation for the Oem Td.
  609. *
  610. * ENTRY:
  611. * pDeviceName (input)
  612. * Points to device name to check against other WinStations of
  613. * the specified OEM Transport.
  614. * pPdName (input)
  615. * Points to PDNAME of the OEM Transport.
  616. * pWSName (input)
  617. * Points to WINSTATIONNAME of current WinStation being edited.
  618. *
  619. * EXIT:
  620. * TRUE if the OEM Transport device is available for use; FALSE if another
  621. * WinStation of the specified OEM Transport is already configured to
  622. * use it.
  623. *
  624. ******************************************************************************/
  625. BOOL
  626. CAppServerDoc::IsOemTdDeviceAvailable( LPCTSTR pDeviceName,
  627. PPDNAME pPdName,
  628. PWINSTATIONNAME pWSName )
  629. {
  630. POSITION pos;
  631. /*
  632. * Traverse the WinStationList.
  633. */
  634. for ( pos = m_WinStationList.GetHeadPosition(); pos != NULL; ) {
  635. PWSLOBJECT pObject = (PWSLOBJECT)m_WinStationList.GetNext(pos);
  636. /*
  637. * If this is a OEM Transport WinStation of the specified OEM Transport,
  638. * the device is the same as the one we're checking, but this is not the
  639. * current WinStation being edited, return FALSE.
  640. */
  641. if ( (pObject->m_SdClass == SdOemTransport) &&
  642. !lstrcmpi(pObject->m_PdName, pPdName) &&
  643. !lstrcmpi(pObject->m_DeviceName, pDeviceName) &&
  644. lstrcmpi(pWSName, pObject->m_WinStationName) ) {
  645. return(FALSE);
  646. }
  647. }
  648. /*
  649. * The OEM Transport device is not configured in any current WinStations
  650. * of the same OEM Transport.
  651. */
  652. return(TRUE);
  653. } // end CAppServerDoc::IsOemTdDeviceAvailable
  654. /*******************************************************************************
  655. *
  656. * IsWSNameUnique - CAppServerDoc member function: public operation
  657. *
  658. * Determine if the entered WinStation name is unique.
  659. *
  660. * ENTRY:
  661. * pWinStationName (input)
  662. * Points to WINSTATIONNAME to check for uniqueness.
  663. *
  664. * EXIT:
  665. * TRUE if the specified WinStation name is unique; FALSE if not.
  666. *
  667. ******************************************************************************/
  668. BOOL
  669. CAppServerDoc::IsWSNameUnique( PWINSTATIONNAME pWinStationName )
  670. {
  671. POSITION pos;
  672. WINSTATIONNAME WSRoot;
  673. PWINSTATIONNAME pWSRoot;
  674. /*
  675. * Traverse the WinStationList.
  676. */
  677. for ( pos = m_WinStationList.GetHeadPosition(); pos != NULL; ) {
  678. PWSLOBJECT pObject = (PWSLOBJECT)m_WinStationList.GetNext(pos);
  679. /*
  680. * Make sure that we only compare the 'root' names.
  681. */
  682. lstrcpy(WSRoot, pObject->m_WinStationName);
  683. pWSRoot = lstrtok(WSRoot, TEXT("#"));
  684. /*
  685. * If the roots match, return FALSE.
  686. */
  687. if ( !lstrcmpi(pWinStationName, pWSRoot) )
  688. return(FALSE);
  689. }
  690. /*
  691. * WinStation name is unique.
  692. */
  693. return(TRUE);
  694. } // end CAppServerDoc::IsWSNameUnique()
  695. /*******************************************************************************
  696. *
  697. * AddWinStation - CAppServerDoc member function: public operation
  698. *
  699. * Add a new WinStation.
  700. *
  701. * ENTRY:
  702. * WSLIndex (input)
  703. * WSL index of the currently selected WinStation, to provide some
  704. * defaults for the new WinStation.
  705. * EXIT:
  706. * (int) WSL index of the added WinStation's list item; -1 if error.
  707. *
  708. ******************************************************************************/
  709. int
  710. CAppServerDoc::AddWinStation(int WSLIndex)
  711. {
  712. LONG Status;
  713. int nIndex = -1;
  714. CEditWinStationDlg EWSDlg(this);
  715. WINSTATIONNAME WSName;
  716. PWSLOBJECT pWSLObject;
  717. LPCTSTR pszFailedCall = NULL;
  718. /*
  719. * Zero out the WinStation name and config structure.
  720. */
  721. memset(WSName, 0, sizeof(WSName));
  722. memset(&EWSDlg.m_WSConfig, 0, sizeof(WINSTATIONCONFIG2));
  723. /*
  724. * Get current WinStation object to anticipate defaults for the new
  725. * WinStation and assure that the WSL is 'in sync' with the registry.
  726. */
  727. if ( !RefreshWSLObjectState( WSLIndex,
  728. pWSLObject = GetWSLObject(WSLIndex)) )
  729. goto BadRefreshWSLObjectState;
  730. /*
  731. * Set the config structure's Pd name field to allow Edit
  732. * dialog to form default config structure contents.
  733. */
  734. EWSDlg.m_WSConfig.Create.fEnableWinStation = 1;
  735. if ( pWSLObject ) {
  736. EWSDlg.m_WSConfig.Pd[0].Create.SdClass = pWSLObject->m_SdClass;
  737. lstrcpy( EWSDlg.m_WSConfig.Pd[0].Create.PdName, pWSLObject->m_PdName );
  738. }
  739. /*
  740. * Initialize the additional dialog member variables.
  741. */
  742. EWSDlg.m_pWSName = WSName;
  743. EWSDlg.m_DlgMode = EWSDlgAdd;
  744. EWSDlg.m_pExtObject = NULL;
  745. /*
  746. * Invoke the dialog.
  747. */
  748. if ( EWSDlg.DoModal() == IDOK ) {
  749. CWaitCursor wait;
  750. /*
  751. * Add a new WSLObject to the WSL.
  752. */
  753. if ( (nIndex =
  754. InsertInWSL( WSName, &EWSDlg.m_WSConfig, EWSDlg.m_pExtObject, &pWSLObject )) == -1 )
  755. goto BadInsertInWSL;
  756. /*
  757. * Fetch the default WinStation security descriptor.
  758. */
  759. if ( (Status = GetDefaultWinStationSecurity(&m_pSecurityDescriptor))
  760. != ERROR_SUCCESS ) {
  761. pszFailedCall = pApp->m_pszGetDefaultWinStationSecurity;
  762. goto BadGetDefaultWinStationSecurity;
  763. }
  764. /*
  765. * Create the registry entry.
  766. */
  767. if((Status = RegistryCreate(WSName,
  768. TRUE,
  769. &EWSDlg.m_WSConfig,
  770. pWSLObject->m_WdName,
  771. pWSLObject->m_pExtObject))) {
  772. pszFailedCall = pApp->m_pszRegWinStationCreate;
  773. goto BadRegCreate;
  774. }
  775. /*
  776. * Set the WinStation security in registry.
  777. */
  778. if ( m_pSecurityDescriptor &&
  779. (Status = RegWinStationSetSecurity(
  780. SERVERNAME_CURRENT,
  781. WSName,
  782. m_pSecurityDescriptor,
  783. GetSecurityDescriptorLength(m_pSecurityDescriptor) )) ) {
  784. pszFailedCall = pApp->m_pszRegWinStationSetSecurity;
  785. goto BadRegSetSecurity;
  786. }
  787. /*
  788. * If we're not 'registry only', tell Session Manager
  789. * to re-read registry.
  790. */
  791. #ifdef WINSTA
  792. if ( !pApp->m_nRegistryOnly ) {
  793. _WinStationReadRegistry(SERVERNAME_CURRENT);
  794. /*
  795. * If this is a modem winstation and it's enabled,
  796. * issue the 'must reboot' message and flag the
  797. * winstation as 'must reboot'.
  798. */
  799. if ( *EWSDlg.m_WSConfig.Pd[0].Params.Async.ModemName &&
  800. EWSDlg.m_WSConfig.Create.fEnableWinStation ) {
  801. QuestionMessage( MB_OK | MB_ICONEXCLAMATION,
  802. IDP_NOTICE_REBOOTFORMODEM_ADD, WSName );
  803. pWSLObject->m_Flags |= WSL_MUST_REBOOT;
  804. }
  805. }
  806. #endif // WINSTA
  807. /*
  808. * A new WSLObject was added: update the entire view.
  809. */
  810. UpdateAllViews(NULL, 0, NULL);
  811. /*
  812. * Return the new WSLObject's index.
  813. */
  814. return(nIndex);
  815. } else {
  816. /*
  817. * User canceled the Add; just return the previously given index.
  818. */
  819. DeleteExtensionObject(EWSDlg.m_pExtObject, EWSDlg.m_WSConfig.Wd.WdName);
  820. return(WSLIndex);
  821. }
  822. /*==============================================================================
  823. * Error returns
  824. *============================================================================*/
  825. BadRegSetSecurity:
  826. RegWinStationDelete( SERVERNAME_CURRENT, WSName );
  827. BadRegCreate:
  828. BadGetDefaultWinStationSecurity:
  829. BadInsertInWSL:
  830. BadRefreshWSLObjectState:
  831. if ( nIndex != -1 )
  832. RemoveFromWSL(nIndex);
  833. if ( pszFailedCall ) {
  834. STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, Status,
  835. IDP_ERROR_ADDWINSTATION, WSName,
  836. pszFailedCall ))
  837. }
  838. return(-1);
  839. } // end CAppServerDoc::AddWinStation
  840. /*******************************************************************************
  841. *
  842. * CopyWinStation - CAppServerDoc member function: public operation
  843. *
  844. * Copy a given WinStation into a new one.
  845. *
  846. * ENTRY:
  847. * WSLIndex (input)
  848. * WSL index of the currently selected WinStation, to provide most
  849. * defaults for the new WinStation.
  850. * EXIT:
  851. * (int) WSL index of the added WinStation's list item; -1 if error.
  852. *
  853. ******************************************************************************/
  854. int
  855. CAppServerDoc::CopyWinStation(int WSLIndex)
  856. {
  857. LONG Status;
  858. ULONG Length;
  859. int nIndex = -1;
  860. PWSLOBJECT pWSLObject;
  861. WINSTATIONNAME WSName;
  862. WINSTATIONNAME OriginalWSName;
  863. CEditWinStationDlg EWSDlg(this);
  864. LPCTSTR pszFailedCall = NULL;
  865. /*
  866. * Get current WinStation object to obtain defaults for the new
  867. * WinStation and assure that the WSL is 'in sync' with the registry.
  868. */
  869. if ( !RefreshWSLObjectState( WSLIndex,
  870. pWSLObject = GetWSLObject(WSLIndex)) )
  871. goto BadRefreshWSLObjectState;
  872. lstrcpy( WSName, pWSLObject->m_WinStationName );
  873. /*
  874. * Get the WinStation's config structure and initialize the WSName
  875. * array.
  876. */
  877. if((Status = RegistryQuery( pWSLObject->m_WinStationName,
  878. &EWSDlg.m_WSConfig,
  879. pWSLObject->m_WdName,
  880. &EWSDlg.m_pExtObject))) {
  881. pszFailedCall = pApp->m_pszRegWinStationQuery;
  882. goto BadRegWinStationQuery;
  883. }
  884. lstrcpy( OriginalWSName, pWSLObject->m_WinStationName );
  885. /*
  886. * If this is an Async WinStation class, null the DeviceName field, since
  887. * the device used by an Async WinStation must be unique.
  888. */
  889. if ( pWSLObject->m_SdClass == SdAsync )
  890. *(EWSDlg.m_WSConfig.Pd[0].Params.Async.DeviceName) = TEXT('\0');
  891. /*
  892. * Initialize dialog variables and invoke the Edit WinStation dialog
  893. * in it's 'copy' mode.
  894. */
  895. EWSDlg.m_pWSName = WSName;
  896. EWSDlg.m_DlgMode = EWSDlgCopy;
  897. /*
  898. * Invoke the dialog.
  899. */
  900. if ( EWSDlg.DoModal() == IDOK ) {
  901. CWaitCursor wait;
  902. /*
  903. * Add a new WSLObject to the WSL.
  904. */
  905. if ( (nIndex =
  906. InsertInWSL( WSName, &EWSDlg.m_WSConfig, EWSDlg.m_pExtObject, &pWSLObject )) == -1 )
  907. goto BadInsertInWSL;
  908. /*
  909. * Fetch the original WinStation's security descriptor.
  910. */
  911. if ( (Status = GetWinStationSecurity( OriginalWSName,
  912. &m_pSecurityDescriptor))
  913. != ERROR_SUCCESS ) {
  914. pszFailedCall = pApp->m_pszGetWinStationSecurity;
  915. goto BadGetWinStationSecurity;
  916. }
  917. /*
  918. * Create the registry entry.
  919. */
  920. if((Status = RegistryCreate( WSName,
  921. TRUE,
  922. &EWSDlg.m_WSConfig,
  923. EWSDlg.m_WSConfig.Wd.WdName,
  924. EWSDlg.m_pExtObject)) ) {
  925. pszFailedCall = pApp->m_pszRegWinStationCreate;
  926. goto BadRegCreate;
  927. }
  928. /*
  929. * Set the WinStation security in registry.
  930. */
  931. if ( m_pSecurityDescriptor &&
  932. (Status = RegWinStationSetSecurity(
  933. SERVERNAME_CURRENT,
  934. WSName,
  935. m_pSecurityDescriptor,
  936. GetSecurityDescriptorLength(m_pSecurityDescriptor) )) ) {
  937. pszFailedCall = pApp->m_pszRegWinStationSetSecurity;
  938. goto BadRegSetSecurity;
  939. }
  940. /*
  941. * If we're not 'registry only', tell Session Manager
  942. * to re-read registry.
  943. */
  944. #ifdef WINSTA
  945. if ( !pApp->m_nRegistryOnly ) {
  946. _WinStationReadRegistry(SERVERNAME_CURRENT);
  947. /*
  948. * If this is a modem winstation and it's enabled,
  949. * issue the 'must reboot' message and flag the
  950. * winstation as 'must reboot'.
  951. */
  952. if ( *EWSDlg.m_WSConfig.Pd[0].Params.Async.ModemName &&
  953. EWSDlg.m_WSConfig.Create.fEnableWinStation ) {
  954. QuestionMessage( MB_OK | MB_ICONEXCLAMATION,
  955. IDP_NOTICE_REBOOTFORMODEM_ADD, WSName );
  956. pWSLObject->m_Flags |= WSL_MUST_REBOOT;
  957. }
  958. }
  959. #endif // WINSTA
  960. /*
  961. * A new WSLObject was added: update the entire view.
  962. */
  963. UpdateAllViews(NULL, 0, NULL);
  964. /*
  965. * Return the new WSLObject's index.
  966. */
  967. return(nIndex);
  968. } else {
  969. /*
  970. * User canceled the Copy; just return the previously given index.
  971. */
  972. DeleteExtensionObject(EWSDlg.m_pExtObject, EWSDlg.m_WSConfig.Wd.WdName);
  973. return(WSLIndex);
  974. }
  975. /*==============================================================================
  976. * Error returns
  977. *============================================================================*/
  978. BadRegSetSecurity:
  979. RegWinStationDelete( SERVERNAME_CURRENT, WSName );
  980. BadRegCreate:
  981. BadGetWinStationSecurity:
  982. BadInsertInWSL:
  983. BadRegWinStationQuery:
  984. BadRefreshWSLObjectState:
  985. if ( nIndex != -1 )
  986. RemoveFromWSL(nIndex);
  987. if ( pszFailedCall ) {
  988. STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, Status,
  989. IDP_ERROR_COPYWINSTATION, WSName,
  990. pszFailedCall ))
  991. }
  992. return(-1);
  993. } // end CAppServerDoc::CopyWinStation
  994. /*******************************************************************************
  995. *
  996. * RenameWinStation - CAppServerDoc member function: public operation
  997. *
  998. * Rename a WinStation.
  999. *
  1000. * ENTRY:
  1001. * WSLIndex (input)
  1002. * WSL index of the WinStation to rename.
  1003. * EXIT:
  1004. * (int) WSL index of the renamed WinStation's list item; -1 if error.
  1005. *
  1006. ******************************************************************************/
  1007. int
  1008. CAppServerDoc::RenameWinStation(int WSLIndex)
  1009. {
  1010. LONG Status;
  1011. ULONG Length;
  1012. int nIndex = -1;
  1013. CEditWinStationDlg EWSDlg(this);
  1014. PWSLOBJECT pOldWSLObject, pNewWSLObject;
  1015. WINSTATIONNAME OldWSName, NewWSName;
  1016. LPCTSTR pszFailedCall = NULL;
  1017. void *pExtObject = NULL;
  1018. /*
  1019. * Get current WinStation object and assure that the WSL is 'in sync'
  1020. * with the registry.
  1021. */
  1022. if ( !RefreshWSLObjectState( WSLIndex,
  1023. pOldWSLObject = GetWSLObject(WSLIndex)) )
  1024. goto BadRefreshWSLObjectState;
  1025. lstrcpy(OldWSName, pOldWSLObject->m_WinStationName);
  1026. /*
  1027. * Fetch the WinStation's configuration structure.
  1028. */
  1029. if((Status = RegistryQuery( pOldWSLObject->m_WinStationName,
  1030. &EWSDlg.m_WSConfig,
  1031. pOldWSLObject->m_WdName,
  1032. &pExtObject))) {
  1033. pszFailedCall = pApp->m_pszRegWinStationQuery;
  1034. goto BadRegWinStationQuery;
  1035. }
  1036. lstrcpy(NewWSName, pOldWSLObject->m_WinStationName);
  1037. /*
  1038. * copy the pExtObject into the one for the EWSDlg
  1039. */
  1040. if(pExtObject) {
  1041. PTERMLOBJECT pObject = GetWdListObject(pOldWSLObject->m_WdName);
  1042. if(pObject && pObject->m_hExtensionDLL && pObject->m_lpfnExtDupObject) {
  1043. EWSDlg.m_pExtObject = (*pObject->m_lpfnExtDupObject)(pExtObject);
  1044. }
  1045. } else {
  1046. EWSDlg.m_pExtObject = NULL;
  1047. }
  1048. /*
  1049. * Initialize the dialog's member variables.
  1050. */
  1051. EWSDlg.m_pWSName = NewWSName;
  1052. EWSDlg.m_DlgMode = EWSDlgRename;
  1053. /*
  1054. * Invoke the dialog.
  1055. */
  1056. if ( EWSDlg.DoModal() == IDOK ) {
  1057. CWaitCursor wait;
  1058. /*
  1059. * Add a new WSLObject to the WSL.
  1060. */
  1061. if ( (nIndex =
  1062. InsertInWSL(NewWSName, &EWSDlg.m_WSConfig, EWSDlg.m_pExtObject, &pNewWSLObject)) == -1 )
  1063. goto BadInsertInWSL;
  1064. /*
  1065. * Fetch the original WinStation's security descriptor.
  1066. */
  1067. if ( (Status = GetWinStationSecurity( OldWSName,
  1068. &m_pSecurityDescriptor))
  1069. != ERROR_SUCCESS ) {
  1070. pszFailedCall = pApp->m_pszGetWinStationSecurity;
  1071. goto BadGetWinStationSecurity;
  1072. }
  1073. /*
  1074. * Create the new registry entry.
  1075. */
  1076. if((Status = RegistryCreate( NewWSName,
  1077. TRUE,
  1078. &EWSDlg.m_WSConfig,
  1079. EWSDlg.m_WSConfig.Wd.WdName,
  1080. EWSDlg.m_pExtObject))) {
  1081. pszFailedCall = pApp->m_pszRegWinStationCreate;
  1082. goto BadRegCreate;
  1083. }
  1084. /*
  1085. * Set the WinStation security in registry.
  1086. */
  1087. if ( m_pSecurityDescriptor &&
  1088. (Status = RegWinStationSetSecurity(
  1089. SERVERNAME_CURRENT,
  1090. NewWSName,
  1091. m_pSecurityDescriptor,
  1092. GetSecurityDescriptorLength(m_pSecurityDescriptor) )) ) {
  1093. pszFailedCall = pApp->m_pszRegWinStationSetSecurity;
  1094. goto BadRegSetSecurity;
  1095. }
  1096. /*
  1097. * Delete the old registry entry.
  1098. */
  1099. if ( (Status = RegistryDelete(OldWSName, EWSDlg.m_WSConfig.Wd.WdName, pExtObject)) ) {
  1100. pszFailedCall = pApp->m_pszRegWinStationDelete;
  1101. goto BadRegDelete;
  1102. }
  1103. /*
  1104. * Remove old WSLObject from the WSL and recalculate the
  1105. * new WSLObject's index (may have changed).
  1106. */
  1107. RemoveFromWSL( GetWSLIndex(OldWSName) );
  1108. nIndex = GetWSLIndex(NewWSName);
  1109. /*
  1110. * If we're not 'registry only', tell Session Manager
  1111. * to re-read registry and output 'in use' message if
  1112. * necessary.
  1113. */
  1114. #ifdef WINSTA
  1115. if ( !pApp->m_nRegistryOnly ) {
  1116. _WinStationReadRegistry(SERVERNAME_CURRENT);
  1117. /*
  1118. * Issue appropriate messages if the winstation being renamed
  1119. * was enabled.
  1120. */
  1121. if ( EWSDlg.m_WSConfig.Create.fEnableWinStation ) {
  1122. if ( *EWSDlg.m_WSConfig.Pd[0].Params.Async.ModemName ) {
  1123. QuestionMessage( MB_OK | MB_ICONEXCLAMATION,
  1124. IDP_NOTICE_REBOOTFORMODEM_RENAME,
  1125. OldWSName, NewWSName );
  1126. pNewWSLObject->m_Flags |= WSL_MUST_REBOOT;
  1127. } else {
  1128. InUseMessage(OldWSName);
  1129. }
  1130. }
  1131. }
  1132. #endif // WINSTA
  1133. /*
  1134. * A new WSLObject was added: update the entire view.
  1135. */
  1136. UpdateAllViews(NULL, 0, NULL);
  1137. /*
  1138. * Return the new WSLObject's index.
  1139. */
  1140. return(nIndex);
  1141. } else {
  1142. /*
  1143. * User canceled the Rename; just return the previously given index.
  1144. */
  1145. DeleteExtensionObject(pExtObject, EWSDlg.m_WSConfig.Wd.WdName);
  1146. DeleteExtensionObject(EWSDlg.m_pExtObject, EWSDlg.m_WSConfig.Wd.WdName);
  1147. return(WSLIndex);
  1148. }
  1149. /*==============================================================================
  1150. * Error returns
  1151. *============================================================================*/
  1152. BadRegDelete:
  1153. BadRegSetSecurity:
  1154. RegWinStationDelete( SERVERNAME_CURRENT, NewWSName );
  1155. BadRegCreate:
  1156. BadGetWinStationSecurity:
  1157. BadInsertInWSL:
  1158. BadRegWinStationQuery:
  1159. BadRefreshWSLObjectState:
  1160. if ( nIndex != -1 )
  1161. RemoveFromWSL(nIndex);
  1162. if ( pszFailedCall ) {
  1163. STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, Status,
  1164. IDP_ERROR_RENAMEWINSTATION, OldWSName,
  1165. pszFailedCall ))
  1166. }
  1167. return(-1);
  1168. } // end CAppServerDoc::RenameWinStation
  1169. /*******************************************************************************
  1170. *
  1171. * EditWinStation - CAppServerDoc member function: public operation
  1172. *
  1173. * Edit a WinStation.
  1174. *
  1175. * ENTRY:
  1176. * WSLIndex (input)
  1177. * WSL index of the WinStation to edit.
  1178. * EXIT:
  1179. * (int) WSL index of the edited WinStation's list item; -1 if error.
  1180. *
  1181. ******************************************************************************/
  1182. int
  1183. CAppServerDoc::EditWinStation(int WSLIndex)
  1184. {
  1185. LONG Status;
  1186. ULONG Length;
  1187. int nIndex = -1;
  1188. BOOL bQueueOperationSuccess = TRUE, bAllowAbort = TRUE;
  1189. CEditWinStationDlg EWSDlg(this);
  1190. PWSLOBJECT pWSLObject;
  1191. WINSTATIONCONFIG2 WSConfig;
  1192. LPCTSTR pszFailedCall = NULL;
  1193. WINSTATIONNAME WSName;
  1194. void *pExtObject = NULL;
  1195. /*
  1196. * Get current WinStation object and assure that the WSL is 'in sync'
  1197. * with the registry.
  1198. */
  1199. if ( !RefreshWSLObjectState( WSLIndex,
  1200. pWSLObject = GetWSLObject(WSLIndex) ) )
  1201. goto BadRefreshWSLObjectState;
  1202. lstrcpy( WSName, pWSLObject->m_WinStationName );
  1203. /*
  1204. * Fetch the WinStation's configuration structure and save a copy for
  1205. * update comparison.
  1206. */
  1207. memset( &WSConfig, 0, sizeof(WINSTATIONCONFIG2) );
  1208. memset( &EWSDlg.m_WSConfig, 0, sizeof(WINSTATIONCONFIG2) );
  1209. if((Status = RegistryQuery( WSName,
  1210. &WSConfig,
  1211. pWSLObject->m_WdName,
  1212. &pExtObject))) {
  1213. pszFailedCall = pApp->m_pszRegWinStationQuery;
  1214. goto BadRegWinStationQuery;
  1215. }
  1216. memcpy( &EWSDlg.m_WSConfig, &WSConfig, sizeof(WINSTATIONCONFIG2) );
  1217. /*
  1218. * copy the pExtObject into the one for the EWSDlg
  1219. */
  1220. if(pExtObject) {
  1221. PTERMLOBJECT pObject = GetWdListObject(pWSLObject->m_WdName);
  1222. if(pObject && pObject->m_hExtensionDLL && pObject->m_lpfnExtDupObject) {
  1223. EWSDlg.m_pExtObject = (*pObject->m_lpfnExtDupObject)(pExtObject);
  1224. }
  1225. } else {
  1226. EWSDlg.m_pExtObject = NULL;
  1227. }
  1228. /*
  1229. * Initialize the dialog's member variables.
  1230. */
  1231. EWSDlg.m_pWSName = WSName;
  1232. EWSDlg.m_DlgMode = m_bReadOnly ? EWSDlgView : EWSDlgEdit;
  1233. /*
  1234. * Invoke the dialog & update if changes.
  1235. */
  1236. if ( (EWSDlg.DoModal() == IDOK) &&
  1237. (EWSDlg.m_DlgMode == EWSDlgEdit) &&
  1238. HasWSConfigChanged(&WSConfig, &EWSDlg.m_WSConfig, pExtObject, EWSDlg.m_pExtObject, EWSDlg.m_WSConfig.Wd.WdName) ) {
  1239. BOOL bUpdateAll = FALSE,
  1240. bDestructive = FALSE,
  1241. bAsyncDeviceChanged = ((pWSLObject->m_SdClass == SdAsync) &&
  1242. lstrcmpi(WSConfig.Pd[0].Params.Async.DeviceName,
  1243. EWSDlg.m_WSConfig.Pd[0].Params.Async.DeviceName)),
  1244. bAsyncModemChanged = ((pWSLObject->m_SdClass == SdAsync) &&
  1245. lstrcmpi(WSConfig.Pd[0].Params.Async.ModemName,
  1246. EWSDlg.m_WSConfig.Pd[0].Params.Async.ModemName)),
  1247. bNetworkDeviceChanged = ((pWSLObject->m_SdClass == SdNetwork) &&
  1248. (WSConfig.Pd[0].Params.Network.LanAdapter !=
  1249. EWSDlg.m_WSConfig.Pd[0].Params.Network.LanAdapter)),
  1250. bEnabledStateChanged = (WSConfig.Create.fEnableWinStation !=
  1251. EWSDlg.m_WSConfig.Create.fEnableWinStation),
  1252. bEnabled = EWSDlg.m_WSConfig.Create.fEnableWinStation,
  1253. bWasEnabled = WSConfig.Create.fEnableWinStation;
  1254. /*
  1255. * If the winstation is being disabled or the device (or modem) has changed
  1256. * and folks are connected, the update will cause all instances to be destroyed.
  1257. * Let user know this so that the update can be canceled. Also allow
  1258. * normal confirmation if just disabling the winstation and no users are
  1259. * presently connected.
  1260. */
  1261. if ( !bEnabled || bAsyncDeviceChanged || bAsyncModemChanged || bNetworkDeviceChanged ) {
  1262. if ( pApp->m_nConfirmation ) {
  1263. int id;
  1264. UINT nType = 0;
  1265. long count = QueryLoggedOnCount(WSName);
  1266. if ( !bEnabled && bWasEnabled ) {
  1267. nType = MB_YESNO |
  1268. (count ? MB_ICONEXCLAMATION : MB_ICONQUESTION);
  1269. id = count ?
  1270. ((count == 1) ?
  1271. IDP_CONFIRM_WINSTATIONDISABLE_1USER :
  1272. IDP_CONFIRM_WINSTATIONDISABLE_NUSERS) :
  1273. IDP_CONFIRM_WINSTATIONDISABLE;
  1274. } else if ( bAsyncDeviceChanged && count ) {
  1275. nType = MB_YESNO | MB_ICONEXCLAMATION;
  1276. id = IDP_CONFIRM_DEVICECHANGED;
  1277. } else if ( bAsyncModemChanged && count ) {
  1278. nType = MB_YESNO | MB_ICONEXCLAMATION;
  1279. id = IDP_CONFIRM_MODEMCHANGED;
  1280. } else if ( bNetworkDeviceChanged && count ) {
  1281. nType = MB_YESNO | MB_ICONEXCLAMATION;
  1282. id = ((count == 1) ? IDP_CONFIRM_ADAPTERCHANGED_1USER :
  1283. IDP_CONFIRM_ADAPTERCHANGED_NUSERS);
  1284. }
  1285. if ( nType && (QuestionMessage(nType, id, WSName ) == IDNO) )
  1286. goto CancelChanges;
  1287. }
  1288. bDestructive = TRUE;
  1289. }
  1290. CWaitCursor wait;
  1291. /*
  1292. * Special case for Async WinStation.
  1293. */
  1294. if ( pWSLObject->m_SdClass == SdAsync ) {
  1295. /*
  1296. * If a modem has been added or removed from the WinStation,
  1297. * delete the current WSLObject and add a new WSLObject to the list.
  1298. */
  1299. if ( bAsyncModemChanged ) {
  1300. RemoveFromWSL(WSLIndex);
  1301. if ( (WSLIndex = InsertInWSL( WSName,
  1302. &EWSDlg.m_WSConfig,
  1303. EWSDlg.m_pExtObject,
  1304. &pWSLObject )) == -1 ) {
  1305. LoadWSL(pApp->m_szCurrentAppServer);
  1306. goto BadInsertInWSL;
  1307. }
  1308. bUpdateAll = TRUE;
  1309. }
  1310. /*
  1311. * Make sure that the WSL device name is current.
  1312. */
  1313. FormDecoratedAsyncDeviceName(
  1314. pWSLObject->m_DeviceName,
  1315. &(EWSDlg.m_WSConfig.Pd[0].Params.Async) );
  1316. }
  1317. /*
  1318. * Special case for OEM Transport WinStation.
  1319. */
  1320. if ( pWSLObject->m_SdClass == SdOemTransport ) {
  1321. /*
  1322. * Make sure that the WSL device name is current.
  1323. */
  1324. lstrcpy( pWSLObject->m_DeviceName,
  1325. EWSDlg.m_WSConfig.Pd[0].Params.OemTd.DeviceName );
  1326. }
  1327. /*
  1328. * Update WSL fields.
  1329. */
  1330. lstrcpy( pWSLObject->m_WdName, EWSDlg.m_WSConfig.Wd.WdName );
  1331. lstrcpy( pWSLObject->m_Comment, EWSDlg.m_WSConfig.Config.Comment );
  1332. pWSLObject->m_Flags = ((pWSLObject->m_Flags & ~WSL_ENABLED) |
  1333. (EWSDlg.m_WSConfig.Create.fEnableWinStation ? WSL_ENABLED : 0));
  1334. /*
  1335. * Update registry entry.
  1336. */
  1337. if ( (Status = RegistryCreate(
  1338. WSName,
  1339. FALSE,
  1340. &EWSDlg.m_WSConfig,
  1341. EWSDlg.m_WSConfig.Wd.WdName,
  1342. EWSDlg.m_pExtObject)) ) {
  1343. pszFailedCall = pApp->m_pszRegWinStationCreate;
  1344. goto BadRegWinStationCreate;
  1345. }
  1346. /*
  1347. * If we're not 'registry only', tell Session Manager
  1348. * to re-read registry and output 'in use' message if
  1349. * necessary.
  1350. */
  1351. #ifdef WINSTA
  1352. if ( !pApp->m_nRegistryOnly ) {
  1353. _WinStationReadRegistry(SERVERNAME_CURRENT);
  1354. /*
  1355. * If the state is now 'enabled' AND
  1356. * 1) the modem has changed, OR
  1357. * 2) a modem is now configured AND
  1358. * a) the state was 'disabled' OR
  1359. * b) the COM port has changed
  1360. * Then issue the 'must reboot' message and set must reboot flag.
  1361. * Otherwise, if this is not a destructive action, issue in use message if needed
  1362. * and make sure the must reboot flag is cleared.
  1363. */
  1364. if ( bEnabled &&
  1365. (bAsyncModemChanged ||
  1366. (*EWSDlg.m_WSConfig.Pd[0].Params.Async.ModemName &&
  1367. (!bWasEnabled || bAsyncDeviceChanged))) ) {
  1368. QuestionMessage( MB_OK | MB_ICONEXCLAMATION,
  1369. IDP_NOTICE_REBOOTFORMODEM_EDIT, WSName );
  1370. pWSLObject->m_Flags |= WSL_MUST_REBOOT;
  1371. } else if ( !bDestructive ) {
  1372. InUseMessage(WSName);
  1373. pWSLObject->m_Flags &= ~WSL_MUST_REBOOT;
  1374. }
  1375. }
  1376. #endif // WINSTA
  1377. /*
  1378. * Update view.
  1379. */
  1380. if ( bUpdateAll )
  1381. UpdateAllViews( NULL, 0, NULL );
  1382. else
  1383. UpdateAllViewsWithItem( NULL, WSLIndex, pWSLObject );
  1384. } else {
  1385. /*
  1386. * We didn't need to write any changes to the registry
  1387. * Delete the extension objects we created
  1388. */
  1389. DeleteExtensionObject(pExtObject, WSConfig.Wd.WdName);
  1390. DeleteExtensionObject(EWSDlg.m_pExtObject, EWSDlg.m_WSConfig.Wd.WdName);
  1391. }
  1392. CancelChanges:
  1393. return(WSLIndex);
  1394. /*==============================================================================
  1395. * Error returns
  1396. *============================================================================*/
  1397. BadRegWinStationCreate:
  1398. BadInsertInWSL:
  1399. BadRegWinStationQuery:
  1400. BadRefreshWSLObjectState:
  1401. if ( pszFailedCall ) {
  1402. STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, Status,
  1403. IDP_ERROR_EDITWINSTATION, WSName,
  1404. pszFailedCall ))
  1405. }
  1406. return(-1);
  1407. } // end CAppServerDoc::EditWinStation
  1408. /*******************************************************************************
  1409. *
  1410. * DeleteWinStation - CAppServerDoc member function: public operation
  1411. *
  1412. * Delete a WinStation.
  1413. *
  1414. * ENTRY:
  1415. * WSLIndex (input)
  1416. * WSL index of the WinStation to delete.
  1417. * EXIT:
  1418. * (BOOL) TRUE if WinStation was deleted; FALSE otherwise.
  1419. *
  1420. ******************************************************************************/
  1421. BOOL
  1422. CAppServerDoc::DeleteWinStation(int WSLIndex)
  1423. {
  1424. PWSLOBJECT pWSLObject;
  1425. WINSTATIONNAME WSName;
  1426. LONG Status, LoggedOnCount = 0;
  1427. ULONG Length;
  1428. LPCTSTR pszFailedCall = NULL;
  1429. WINSTATIONCONFIG2 WSConfig;
  1430. void *pExtObject;
  1431. /*
  1432. * Get current WinStation object and assure that the WSL is 'in sync'
  1433. * with the registry.
  1434. */
  1435. if ( !RefreshWSLObjectState( WSLIndex,
  1436. pWSLObject = GetWSLObject(WSLIndex)) )
  1437. goto BadRefreshWSLObjectState;
  1438. lstrcpy( WSName, pWSLObject->m_WinStationName );
  1439. memset( &WSConfig, 0, sizeof(WINSTATIONCONFIG2) );
  1440. if((Status = RegistryQuery( WSName,
  1441. &WSConfig,
  1442. pWSLObject->m_WdName,
  1443. &pExtObject))) {
  1444. pszFailedCall = pApp->m_pszRegWinStationQuery;
  1445. goto BadRegWinStationQuery;
  1446. }
  1447. /*
  1448. * Confirm delete if requested.
  1449. */
  1450. if ( pApp->m_nConfirmation ) {
  1451. long count = QueryLoggedOnCount(WSName);
  1452. UINT nType = MB_YESNO;
  1453. int id;
  1454. if ( count == 0 ) {
  1455. nType |= MB_ICONQUESTION;
  1456. id = IDP_CONFIRM_WINSTATIONDELETE;
  1457. } else if ( count == 1 ) {
  1458. nType |= MB_ICONEXCLAMATION;
  1459. id = IDP_CONFIRM_WINSTATIONDELETE_1USER;
  1460. } else {
  1461. nType |= MB_ICONEXCLAMATION;
  1462. id = IDP_CONFIRM_WINSTATIONDELETE_NUSERS;
  1463. }
  1464. if ( QuestionMessage( nType, id, WSName ) == IDNO )
  1465. goto DontDelete;
  1466. }
  1467. {
  1468. CWaitCursor wait;
  1469. /*
  1470. * Delete the registry entry.
  1471. */
  1472. if ( (Status = RegistryDelete(WSName, WSConfig.Wd.WdName, pExtObject)) ) {
  1473. pszFailedCall = pApp->m_pszRegWinStationDelete;
  1474. goto BadRegDelete;
  1475. }
  1476. /*
  1477. * Remove WSLObject from the list.
  1478. */
  1479. RemoveFromWSL(WSLIndex);
  1480. /*
  1481. * If we're not 'registry only', tell Session Manager
  1482. * to re-read registry.
  1483. */
  1484. #ifdef WINSTA
  1485. if ( !pApp->m_nRegistryOnly ) {
  1486. _WinStationReadRegistry(SERVERNAME_CURRENT);
  1487. }
  1488. #endif // WINSTA
  1489. /*
  1490. * A WSLObject was removed: update the entire view.
  1491. */
  1492. UpdateAllViews(NULL, 0, NULL);
  1493. }
  1494. DontDelete:
  1495. return(TRUE);
  1496. /*==============================================================================
  1497. * Error returns
  1498. *============================================================================*/
  1499. BadRegDelete:
  1500. BadRegWinStationQuery:
  1501. BadRefreshWSLObjectState:
  1502. if ( pszFailedCall ) {
  1503. STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, Status,
  1504. IDP_ERROR_DELETEWINSTATION, WSName,
  1505. pszFailedCall ))
  1506. }
  1507. return(FALSE);
  1508. } // CAppServerDoc::DeleteWinStation
  1509. /*******************************************************************************
  1510. *
  1511. * EnableWinStation - CAppServerDoc member function: public operation
  1512. *
  1513. * Enable or Disable specified WinStation(s).
  1514. *
  1515. * ENTRY:
  1516. * WSLIndex (input)
  1517. * WSL index of the WinStation(s) to enable or disable.
  1518. * bEnable (input)
  1519. * TRUE to enable WinStation(s); FALSE to disable WinStation(s).
  1520. * EXIT:
  1521. *
  1522. ******************************************************************************/
  1523. void
  1524. CAppServerDoc::EnableWinStation( int WSLIndex,
  1525. BOOL bEnable )
  1526. {
  1527. LONG Status;
  1528. ULONG Length;
  1529. PWSLOBJECT pWSLObject;
  1530. WINSTATIONNAME WSName;
  1531. WINSTATIONCONFIG2 WSConfig;
  1532. LPCTSTR pszFailedCall = NULL;
  1533. /*
  1534. * Get current WinStation object and assure that the WSL is 'in sync'
  1535. * with the registry.
  1536. */
  1537. if ( !RefreshWSLObjectState( WSLIndex,
  1538. pWSLObject = GetWSLObject(WSLIndex) ) )
  1539. goto BadRefreshWSLObjectState;
  1540. lstrcpy( WSName, pWSLObject->m_WinStationName );
  1541. /*
  1542. * Fetch the WinStation's configuration structure.
  1543. */
  1544. if ( (Status = RegWinStationQuery(
  1545. SERVERNAME_CURRENT,
  1546. pWSLObject->m_WinStationName,
  1547. &WSConfig,
  1548. sizeof(WINSTATIONCONFIG2), &Length)) ) {
  1549. pszFailedCall = pApp->m_pszRegWinStationQuery;
  1550. goto BadRegWinStationQuery;
  1551. }
  1552. /*
  1553. * Confirm disable if requested.
  1554. */
  1555. if ( !bEnable && pApp->m_nConfirmation ) {
  1556. long count = QueryLoggedOnCount(WSName);
  1557. UINT nType = MB_YESNO;
  1558. int id;
  1559. if ( count == 0 ) {
  1560. nType |= MB_ICONQUESTION;
  1561. id = IDP_CONFIRM_WINSTATIONDISABLE;
  1562. } else if ( count == 1 ) {
  1563. nType |= MB_ICONEXCLAMATION;
  1564. id = IDP_CONFIRM_WINSTATIONDISABLE_1USER;
  1565. } else {
  1566. nType |= MB_ICONEXCLAMATION;
  1567. id = IDP_CONFIRM_WINSTATIONDISABLE_NUSERS;
  1568. }
  1569. if ( QuestionMessage( nType, id, WSName ) == IDNO )
  1570. goto DontDisable;
  1571. }
  1572. {
  1573. CWaitCursor wait;
  1574. /*
  1575. * Update registry entry.
  1576. */
  1577. WSConfig.Create.fEnableWinStation = (bEnable ? 1 : 0);
  1578. if ( (Status = RegWinStationCreate(
  1579. SERVERNAME_CURRENT,
  1580. WSName,
  1581. FALSE,
  1582. &WSConfig,
  1583. sizeof(WSConfig))) ) {
  1584. pszFailedCall = pApp->m_pszRegWinStationCreate;
  1585. goto BadRegWinStationCreate;
  1586. }
  1587. /*
  1588. * Update WSLObject state.
  1589. */
  1590. pWSLObject->m_Flags = (pWSLObject->m_Flags & ~WSL_ENABLED) |
  1591. (bEnable ? WSL_ENABLED : 0);
  1592. /*
  1593. * If we're not 'registry only', tell Session Manager
  1594. * to re-read registry.
  1595. */
  1596. #ifdef WINSTA
  1597. if ( !pApp->m_nRegistryOnly ) {
  1598. _WinStationReadRegistry(SERVERNAME_CURRENT);
  1599. /*
  1600. * If we're enabling a modem winstation, issue the 'must reboot' message and
  1601. * set 'must reboot flag. Otherwise, make sure the must reboot flag is cleared.
  1602. */
  1603. if ( bEnable && *WSConfig.Pd[0].Params.Async.ModemName ) {
  1604. QuestionMessage( MB_OK | MB_ICONEXCLAMATION,
  1605. IDP_NOTICE_REBOOTFORMODEM_ENABLE, WSName );
  1606. pWSLObject->m_Flags |= WSL_MUST_REBOOT;
  1607. } else {
  1608. pWSLObject->m_Flags &= ~WSL_MUST_REBOOT;
  1609. }
  1610. }
  1611. #endif // WINSTA
  1612. /*
  1613. * Update this WSL in the view.
  1614. */
  1615. UpdateAllViewsWithItem( NULL, WSLIndex, pWSLObject );
  1616. }
  1617. DontDisable:
  1618. return;
  1619. /*==============================================================================
  1620. * Error returns
  1621. *============================================================================*/
  1622. BadRegWinStationCreate:
  1623. BadRegWinStationQuery:
  1624. BadRefreshWSLObjectState:
  1625. if ( pszFailedCall ) {
  1626. STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, Status,
  1627. bEnable ?
  1628. IDP_ERROR_ENABLEWINSTATION :
  1629. IDP_ERROR_DISABLEWINSTATION,
  1630. WSName,
  1631. pszFailedCall ))
  1632. }
  1633. return;
  1634. } // end CAppServerDoc::EnableWinStation
  1635. /*******************************************************************************
  1636. *
  1637. * SecurityPermissions - CAppServerDoc member function: public operation
  1638. *
  1639. * View/Edit WinStation security permissions.
  1640. *
  1641. * ENTRY:
  1642. * WSLIndex (input)
  1643. * WSL index of the selected WinStation.
  1644. *
  1645. * EXIT:
  1646. *
  1647. ******************************************************************************/
  1648. void
  1649. CAppServerDoc::SecurityPermissions(int WSLIndex)
  1650. {
  1651. PWSLOBJECT pWSLObject;
  1652. /*
  1653. * If no items yet, return immediately.
  1654. */
  1655. if ( !(pWSLObject = GetWSLObject(WSLIndex)) )
  1656. return;
  1657. /*
  1658. * Get current WinStation object and assure that the WSL is 'in sync'
  1659. * with the registry.
  1660. */
  1661. if ( !RefreshWSLObjectState(WSLIndex, pWSLObject) )
  1662. return;
  1663. if ( CallPermissionsDialog( pApp->m_pMainWnd->m_hWnd,
  1664. m_bAdmin,
  1665. pWSLObject->m_WinStationName ) &&
  1666. (lstrcmpi(pWSLObject->m_WinStationName, pApp->m_szSystemConsole) != 0) ) {
  1667. /*
  1668. * If we're not 'registry only', tell Session Manager
  1669. * to re-read registry and output 'in use' message if
  1670. * necessary.
  1671. */
  1672. #ifdef WINSTA
  1673. if ( !pApp->m_nRegistryOnly ) {
  1674. _WinStationReadRegistry(SERVERNAME_CURRENT);
  1675. InUseMessage(pWSLObject->m_WinStationName);
  1676. }
  1677. #endif // WINSTA
  1678. }
  1679. } // end CAppServerDoc::SecurityPermissions
  1680. ////////////////////////////////////////////////////////////////////////////////
  1681. // CAppServerDoc private operations
  1682. /*******************************************************************************
  1683. *
  1684. * LoadWSL - CAppServerDoc member function: private operation
  1685. *
  1686. * Reset the WSL to 'empty' and read the specified AppServer's WinStation
  1687. * registry information to load up the WSL.
  1688. *
  1689. * ENTRY:
  1690. * pszAppServer (input)
  1691. * Name of the AppServer to access.
  1692. *
  1693. * EXIT:
  1694. * (BOOL) TRUE if the load was successful; FALSE if error.
  1695. *
  1696. ******************************************************************************/
  1697. BOOL
  1698. CAppServerDoc::LoadWSL( LPCTSTR pszAppServer )
  1699. {
  1700. LONG Status;
  1701. ULONG Index, ByteCount, Entries, LogonId;
  1702. WINSTATIONNAME WSName;
  1703. void *pExtObject = NULL;
  1704. /*
  1705. * Insure that the WSL is empty.
  1706. */
  1707. DeleteWSLContents();
  1708. Index = 0;
  1709. for ( Index = 0, Entries = 1, ByteCount = sizeof(WINSTATIONNAME);
  1710. (Status =
  1711. RegWinStationEnumerate( SERVERNAME_CURRENT, &Index, &Entries,
  1712. WSName, &ByteCount )) == ERROR_SUCCESS;
  1713. ByteCount = sizeof(WINSTATIONNAME) ) {
  1714. WINSTATIONCONFIG2 WSConfig;
  1715. PWSLOBJECT pWSLObject;
  1716. ULONG Length;
  1717. /*
  1718. * Ignore system console.
  1719. */
  1720. if ( !lstrcmpi(WSName, pApp->m_szSystemConsole) )
  1721. continue;
  1722. if ( (Status = RegistryQuery(WSName, &WSConfig, WSConfig.Wd.WdName,
  1723. &pExtObject)) ) {
  1724. STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, Status,
  1725. IDP_ERROR_REGWINSTATIONQUERY,
  1726. WSName ))
  1727. continue;
  1728. }
  1729. /*
  1730. * Insert a WinStation object into the WinStationList.
  1731. */
  1732. if ( InsertInWSL( WSName, &WSConfig, pExtObject, &pWSLObject ) == -1 ) {
  1733. DeleteWSLContents();
  1734. return(FALSE);
  1735. }
  1736. /*
  1737. * If this was an enabled modem WinStation and it has not been
  1738. * created by the system, flag as 'must reboot' (configured TAPI
  1739. * winstation that requires system reboot before being activated).
  1740. */
  1741. #ifdef WINSTA
  1742. if ( (pWSLObject->m_SdClass == SdAsync) &&
  1743. (pWSLObject->m_Flags & WSL_ENABLED) &&
  1744. !(pWSLObject->m_Flags & WSL_DIRECT_ASYNC) &&
  1745. !LogonIdFromWinStationName(SERVERNAME_CURRENT, WSName, &LogonId) )
  1746. pWSLObject->m_Flags |= WSL_MUST_REBOOT;
  1747. #endif // WINSTA
  1748. }
  1749. return(TRUE);
  1750. } // end CAppServerDoc::LoadWSL
  1751. /*******************************************************************************
  1752. *
  1753. * RefreshWSLObjectState - CAppServerDoc member function: private operation
  1754. *
  1755. * Make sure that the state of the specified WSL matches the WinStation
  1756. * state in the registry.
  1757. *
  1758. * ENTRY:
  1759. * nIndex (input)
  1760. * Index of WSL being refreshed.
  1761. * pWSLObject (input/output)
  1762. * Points to the WSLOBJECT containing the WinStation(s) being
  1763. * refreshed.
  1764. * EXIT:
  1765. * (BOOL) TRUE if the refresh was successful; FALSE if error.
  1766. *
  1767. ******************************************************************************/
  1768. BOOL
  1769. CAppServerDoc::RefreshWSLObjectState( int nIndex,
  1770. PWSLOBJECT pWSLObject )
  1771. {
  1772. ULONG State;
  1773. LONG Status;
  1774. /*
  1775. * Check for invalid WSLObject (return TRUE if so).
  1776. */
  1777. if ( pWSLObject == NULL )
  1778. return(TRUE);
  1779. #ifdef UNICODE
  1780. Status = RegWinStationQueryNumValue( SERVERNAME_CURRENT,
  1781. pWSLObject->m_WinStationName,
  1782. WIN_ENABLEWINSTATION,
  1783. &State );
  1784. #else
  1785. /*
  1786. * Note: this function does not have a ANSI version: must convert the
  1787. * ANSI WINSTATIONNAME(A) into UNICODE WINSTATIONNAME(W) and call
  1788. * the UNICODE RegWinStationQueryNumValueW() API.
  1789. */
  1790. WINSTATIONNAMEW WSNameW;
  1791. mbstowcs( WSNameW, pWSLObject->m_WinStationName, sizeof(WSNameW) );
  1792. Status = RegWinStationQueryNumValueW( SERVERNAME_CURRENT,
  1793. WSNameW,
  1794. WIN_ENABLEWINSTATION,
  1795. &State );
  1796. #endif
  1797. if ( Status != ERROR_SUCCESS ) {
  1798. STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, Status,
  1799. IDP_ERROR_REFRESHWINSTATIONSTATE,
  1800. pWSLObject->m_WinStationName ))
  1801. return(FALSE);
  1802. }
  1803. if ( (State && !(pWSLObject->m_Flags & WSL_ENABLED)) ||
  1804. (!State && (pWSLObject->m_Flags & WSL_ENABLED)) ) {
  1805. POSITION pos;
  1806. /*
  1807. * The registry state does not match the WSL's state: update the
  1808. * WSL and cause the view to redraw it immediately.
  1809. */
  1810. pWSLObject->m_Flags = (pWSLObject->m_Flags & ~WSL_ENABLED) |
  1811. (State ? WSL_ENABLED : 0);
  1812. UpdateAllViewsWithItem( NULL, nIndex, NULL );
  1813. GetNextView( pos = GetFirstViewPosition() )->UpdateWindow();
  1814. }
  1815. return(TRUE);
  1816. } // end CAppServerDoc::RefreshWSLObjectState
  1817. /*******************************************************************************
  1818. *
  1819. * DeleteWSLContents - CAppServerDoc member function: private operation
  1820. *
  1821. * Make sure that the WinStationObjectList is empty.
  1822. *
  1823. * ENTRY:
  1824. * EXIT:
  1825. *
  1826. ******************************************************************************/
  1827. void
  1828. CAppServerDoc::DeleteWSLContents()
  1829. {
  1830. POSITION pos1, pos2;
  1831. PWSLOBJECT pObject;
  1832. /*
  1833. * Clean up the WinStationList.
  1834. */
  1835. for ( pos1 = m_WinStationList.GetHeadPosition(); (pos2 = pos1) != NULL; ) {
  1836. m_WinStationList.GetNext( pos1 );
  1837. pObject = (PWSLOBJECT)m_WinStationList.GetAt( pos2 );
  1838. m_WinStationList.RemoveAt( pos2 );
  1839. delete ( pObject );
  1840. }
  1841. } // end CAppServerDoc::DeleteWSLContents
  1842. /*******************************************************************************
  1843. *
  1844. * InsertInWSL - CAppServerDoc member function: private operation
  1845. *
  1846. * Create a new WinStationList object and insert it into the WinStationList
  1847. * (if needed).
  1848. *
  1849. * ENTRY:
  1850. * pWSName (input)
  1851. * Points to name of WinStation.
  1852. * pConfig (input)
  1853. * Points to WinStation's WINSTATIONCONFIG2 structure.
  1854. * pExtObject (input)
  1855. * Points to the extension DLL's data for the WinStation
  1856. * ppObject (output)
  1857. * Points to a PWSLOBJECT pointer which is to receive the PWSLOBJECT
  1858. * for the new WinStationList object.
  1859. * EXIT:
  1860. * (int)
  1861. * index of the WinStationList object in the WinStationList; -1 if
  1862. * error.
  1863. *
  1864. ******************************************************************************/
  1865. int
  1866. CAppServerDoc::InsertInWSL( PWINSTATIONNAME pWSName,
  1867. PWINSTATIONCONFIG2 pWSConfig,
  1868. void *pExtObject,
  1869. PWSLOBJECT * ppObject )
  1870. {
  1871. int Index = 0;
  1872. BOOL bAdded;
  1873. POSITION oldpos, pos;
  1874. PWSLOBJECT pObject, pListObject;
  1875. /*
  1876. * Create a new WinStationList object and initialize.
  1877. */
  1878. if ( !(pObject = new CWinStationListObject) ) {
  1879. ERROR_MESSAGE((IDP_ERROR_WSLISTALLOC))
  1880. return(-1);
  1881. }
  1882. lstrcpy( pObject->m_WinStationName, pWSName );
  1883. lstrlwr(pObject->m_WinStationName);
  1884. pObject->m_Flags = pWSConfig->Create.fEnableWinStation ? WSL_ENABLED : 0;
  1885. pObject->m_Flags |= (pWSConfig->Pd[0].Create.PdFlag & PD_SINGLE_INST) ? WSL_SINGLE_INST : 0;
  1886. lstrcpy( pObject->m_PdName, pWSConfig->Pd[0].Create.PdName );
  1887. pObject->m_SdClass = pWSConfig->Pd[0].Create.SdClass;
  1888. lstrcpy( pObject->m_WdName, pWSConfig->Wd.WdName );
  1889. lstrcpy( pObject->m_Comment, pWSConfig->Config.Comment );
  1890. pObject->m_pExtObject = pExtObject;
  1891. pObject->m_pWdListObject = GetWdListObject(pObject->m_WdName);
  1892. if ( pObject->m_SdClass == SdAsync ) {
  1893. FormDecoratedAsyncDeviceName( pObject->m_DeviceName,
  1894. &(pWSConfig->Pd[0].Params.Async) );
  1895. } else if ( pObject->m_SdClass == SdOemTransport ) {
  1896. lstrcpy( pObject->m_DeviceName,
  1897. pWSConfig->Pd[0].Params.OemTd.DeviceName );
  1898. } else {
  1899. *(pObject->m_DeviceName) = TEXT('\0');
  1900. }
  1901. pObject->m_Flags |= (pObject->m_SdClass == SdAsync) ?
  1902. ( *(pWSConfig->Pd[0].Params.Async.ModemName) ?
  1903. 0 : WSL_DIRECT_ASYNC ) : 0;
  1904. pObject->m_LanAdapter = (pObject->m_SdClass == SdNetwork) ?
  1905. pWSConfig->Pd[0].Params.Network.LanAdapter : 0;
  1906. /*
  1907. * Traverse the WinStationList and insert this new WinStation,
  1908. * keeping the list sorted by SdClass, then PdName, then DirectAsync
  1909. * flag (effects SdAsync types) / LanAdapter # (effects SdNetwork
  1910. * types), then WinStationName.
  1911. */
  1912. for ( Index = 0, bAdded = FALSE,
  1913. pos = m_WinStationList.GetHeadPosition();
  1914. pos != NULL; Index++ ) {
  1915. oldpos = pos;
  1916. pListObject = (PWSLOBJECT)m_WinStationList.GetNext( pos );
  1917. if ( (pListObject->m_SdClass > pObject->m_SdClass) ||
  1918. ((pListObject->m_SdClass == pObject->m_SdClass) &&
  1919. lstrcmpi( pListObject->m_PdName,
  1920. pObject->m_PdName ) > 0) ||
  1921. ((pListObject->m_SdClass == pObject->m_SdClass) &&
  1922. !lstrcmpi( pListObject->m_PdName,
  1923. pObject->m_PdName ) &&
  1924. ((pListObject->m_Flags & WSL_DIRECT_ASYNC) >
  1925. (pObject->m_Flags & WSL_DIRECT_ASYNC))) ||
  1926. ((pListObject->m_SdClass == pObject->m_SdClass) &&
  1927. !lstrcmpi( pListObject->m_PdName,
  1928. pObject->m_PdName ) &&
  1929. (pListObject->m_LanAdapter > pObject->m_LanAdapter)) ||
  1930. ((pListObject->m_SdClass == pObject->m_SdClass) &&
  1931. !lstrcmpi( pListObject->m_PdName,
  1932. pObject->m_PdName ) &&
  1933. ((pListObject->m_Flags & WSL_DIRECT_ASYNC) ==
  1934. (pObject->m_Flags & WSL_DIRECT_ASYNC)) &&
  1935. (pListObject->m_LanAdapter == pObject->m_LanAdapter) &&
  1936. (lstrcmpi( pListObject->m_WinStationName,
  1937. pObject->m_WinStationName ) > 0)) ) {
  1938. /*
  1939. * The new object belongs before the current list object.
  1940. */
  1941. m_WinStationList.InsertBefore( oldpos, pObject );
  1942. bAdded = TRUE;
  1943. break;
  1944. }
  1945. }
  1946. /*
  1947. * If we haven't yet added the WinStation, add it now to the tail
  1948. * of the list.
  1949. */
  1950. if ( !bAdded )
  1951. m_WinStationList.AddTail( pObject );
  1952. /*
  1953. * Set the ppObject referenced PWSLOBJECT pointer to the new PWSLOBJECT
  1954. * pointer and return the index of the new WinStationList object.
  1955. */
  1956. *ppObject = pObject;
  1957. return( Index );
  1958. } // end CAppServerDoc::InsertInWSL
  1959. /*******************************************************************************
  1960. *
  1961. * RemoveFromWSL - CAppServerDoc member function: private operation
  1962. *
  1963. * Remove from the WSL the WSLObject associated with the specified
  1964. * index, and delete the removed WSLObject.
  1965. *
  1966. * ENTRY:
  1967. * nIndex (input)
  1968. * WSL index of the WSLObject to remove / delete.
  1969. * EXIT:
  1970. *
  1971. ******************************************************************************/
  1972. void
  1973. CAppServerDoc::RemoveFromWSL( int nIndex )
  1974. {
  1975. POSITION pos;
  1976. PWSLOBJECT pWSLObject;
  1977. /*
  1978. * Return immediately if invalid index.
  1979. */
  1980. if ( nIndex < 0 )
  1981. return;
  1982. pWSLObject = (PWSLOBJECT)m_WinStationList.GetAt(
  1983. (pos = m_WinStationList.FindIndex(nIndex)));
  1984. m_WinStationList.RemoveAt(pos);
  1985. delete pWSLObject;
  1986. } // end CAppServerDoc::RemoveFromWSL
  1987. /*******************************************************************************
  1988. *
  1989. * UpdateAllViewsWithItem - CAppServerDoc member function: private operation
  1990. *
  1991. * Update all views of this document with a changed WinStation item.
  1992. *
  1993. * ENTRY:
  1994. *
  1995. * pSourceView (input)
  1996. * Points to document view to update (all views if NULL).
  1997. *
  1998. * nItemIndex (input)
  1999. * Document's item (WinStation) index that is causing the update
  2000. * to occur.
  2001. *
  2002. * pWSLObject (input)
  2003. * Pointer to the Document's WinStation list object pointer (may be
  2004. * NULL).
  2005. *
  2006. * EXIT:
  2007. *
  2008. ******************************************************************************/
  2009. void
  2010. CAppServerDoc::UpdateAllViewsWithItem( CView* pSourceView,
  2011. UINT nItemIndex,
  2012. PWSLOBJECT pWSLObject )
  2013. {
  2014. CWinStationListObjectHint hint;
  2015. hint.m_WSLIndex = nItemIndex;
  2016. hint.m_pWSLObject = pWSLObject;
  2017. UpdateAllViews( pSourceView, 0, &hint );
  2018. } // end CAppServerDoc::UpdateAllViewsWithItem
  2019. /*******************************************************************************
  2020. *
  2021. * InUseMessage - CAppServerDoc member function: private operation
  2022. *
  2023. * If needed, output an appropriate 'in use' message for the specified
  2024. * WinStation.
  2025. *
  2026. * ENTRY:
  2027. * pWSName (input)
  2028. * Points WinStation name to output message for.
  2029. * EXIT:
  2030. *
  2031. ******************************************************************************/
  2032. void
  2033. CAppServerDoc::InUseMessage( PWINSTATIONNAME pWSName )
  2034. {
  2035. long count;
  2036. if ( (count = QueryLoggedOnCount(pWSName)) ) {
  2037. QuestionMessage(
  2038. MB_OK | MB_ICONINFORMATION,
  2039. (count == 1) ?
  2040. IDP_NOTICE_WSINUSE_1USER :
  2041. IDP_NOTICE_WSINUSE_NUSERS,
  2042. pWSName );
  2043. }
  2044. } // end CAppServerDoc::InUseMessage
  2045. /*******************************************************************************
  2046. *
  2047. * HasWSConfigChanged - CAppServerDoc member function: private operation
  2048. *
  2049. * Determine if WINSTATIONCONFIG2 structure has changed, calling our
  2050. * HasPDConfigChanged method to handle goofy PdConfig2 regapi behavior
  2051. * (straight memcmp won't work).
  2052. *
  2053. * ENTRY:
  2054. * pOldConfig (input)
  2055. * Points to the original WINSTATIONCONFIG2 structure.
  2056. * pNewConfig (input)
  2057. * Points to the new WINSTATIONCONFIG2 structure.
  2058. * pOldExtObject (input)
  2059. * Points to the original extension DLLs object
  2060. * pNewExtObject (input)
  2061. * Points to the new extension DLLs object
  2062. * EXIT:
  2063. * TRUE if original and new config structures differ;
  2064. * FALSE if no changes are detected.
  2065. *
  2066. ******************************************************************************/
  2067. BOOL
  2068. CAppServerDoc::HasWSConfigChanged( PWINSTATIONCONFIG2 pOldConfig,
  2069. PWINSTATIONCONFIG2 pNewConfig,
  2070. void *pOldExtObject,
  2071. void *pNewExtObject,
  2072. PWDNAME pWdName)
  2073. {
  2074. BOOL bChanged = FALSE;
  2075. if ( memcmp( &pOldConfig->Create,
  2076. &pNewConfig->Create,
  2077. sizeof(WINSTATIONCREATE) ) ||
  2078. HasPDConfigChanged(pOldConfig, pNewConfig) ||
  2079. HasExtensionObjectChanged(pWdName, pOldExtObject, pNewExtObject) ||
  2080. memcmp( &pOldConfig->Wd,
  2081. &pNewConfig->Wd,
  2082. sizeof(WDCONFIG) ) ||
  2083. memcmp( &pOldConfig->Cd,
  2084. &pNewConfig->Cd,
  2085. sizeof(CDCONFIG) ) ||
  2086. memcmp( &pOldConfig->Config,
  2087. &pNewConfig->Config,
  2088. sizeof(WINSTATIONCONFIG) ) ) {
  2089. bChanged = TRUE;
  2090. }
  2091. return(bChanged);
  2092. } // end CAppServerDoc::HasWSConfigChanged
  2093. /*******************************************************************************
  2094. *
  2095. * HasPDConfigChanged - CAppServerDoc member function: private operation
  2096. *
  2097. * Determine if the PDConfig structures have changed, with special
  2098. * compare logic to handle goofy PdConfig2 regapi behavior (straight
  2099. * memcmp won't work).
  2100. *
  2101. * ENTRY:
  2102. * pOldConfig (input)
  2103. * Points to the original WINSTATIONCONFIG2 structure.
  2104. * pNewConfig (input)
  2105. * Points to the new WINSTATIONCONFIG2 structure.
  2106. * EXIT:
  2107. * TRUE if original and new config structures differ;
  2108. * FALSE if no changes are detected.
  2109. *
  2110. ******************************************************************************/
  2111. BOOL
  2112. CAppServerDoc::HasPDConfigChanged( PWINSTATIONCONFIG2 pOldConfig,
  2113. PWINSTATIONCONFIG2 pNewConfig )
  2114. {
  2115. BOOL bChanged = FALSE;
  2116. int i;
  2117. for ( i = 0; i < MAX_PDCONFIG; i++ ) {
  2118. if ( (pOldConfig->Pd[i].Create.SdClass !=
  2119. pNewConfig->Pd[i].Create.SdClass) ||
  2120. memcmp( &pOldConfig->Pd[i].Params,
  2121. &pNewConfig->Pd[i].Params,
  2122. sizeof(PDPARAMS) ) ) {
  2123. bChanged = TRUE;
  2124. break;
  2125. }
  2126. }
  2127. return(bChanged);
  2128. } // end CAppServerDoc::HasPDConfigChanged
  2129. /*******************************************************************************
  2130. *
  2131. * HasExtensionObjectChanged - CAppServerDoc member function: private operation
  2132. *
  2133. * Determine if the object maintained by the extension DLL has changed
  2134. *
  2135. * ENTRY:
  2136. * pOldExtObject (input)
  2137. * Points to the original extension DLLs object
  2138. * pNewExtObject (input)
  2139. * Points to the new extension DLLs object
  2140. * EXIT:
  2141. * TRUE if original and new objects differ;
  2142. * FALSE if no changes are detected.
  2143. *
  2144. ******************************************************************************/
  2145. BOOL
  2146. CAppServerDoc::HasExtensionObjectChanged( PWDNAME pWdName, void *pOldExtObject,
  2147. void *pNewExtObject)
  2148. {
  2149. BOOL bChanged = FALSE;
  2150. if(!pOldExtObject && !pNewExtObject) return FALSE;
  2151. if(!pOldExtObject || !pNewExtObject) return TRUE;
  2152. /*
  2153. * Ask the extension DLL if the objects are the same.
  2154. * Extension DLL returns TRUE if the objects are the same
  2155. * and FALSE if they are not,
  2156. * Therefore, we must NOT the value before returning it
  2157. */
  2158. PTERMLOBJECT pObject = GetWdListObject(pWdName);
  2159. if(pObject && pObject->m_hExtensionDLL && pObject->m_lpfnExtCompareObjects) {
  2160. return !(*pObject->m_lpfnExtCompareObjects)(pOldExtObject, pNewExtObject);
  2161. }
  2162. /*
  2163. * If for some reason, we can't ask the extension DLL, play it safe and
  2164. * assume that the object has changed
  2165. */
  2166. return TRUE;
  2167. }
  2168. /*******************************************************************************
  2169. *
  2170. * CAppServerDoc::DeleteExtensionObject
  2171. *
  2172. * Tells the extension DLL to delete an object we no longer need
  2173. *
  2174. * ENTRY:
  2175. * pExtObject (input)
  2176. * Points to the extension object
  2177. * pWdName (input)
  2178. * Points to the name of the Wd (this is used to determine
  2179. * which extension DLL owns the object)
  2180. * EXIT:
  2181. * none
  2182. *
  2183. ******************************************************************************/
  2184. void CAppServerDoc::DeleteExtensionObject(void *pExtObject, PWDNAME pWdName)
  2185. {
  2186. if(pExtObject) {
  2187. /*
  2188. * Tell the extension DLL to delete this object
  2189. */
  2190. PTERMLOBJECT pObject = GetWdListObject(pWdName);
  2191. if(pObject && pObject->m_hExtensionDLL && pObject->m_lpfnExtDeleteObject) {
  2192. (*pObject->m_lpfnExtDeleteObject)(pExtObject);
  2193. }
  2194. }
  2195. } // end CAppServerDoc::DeleteExtensionObject
  2196. /*******************************************************************************
  2197. *
  2198. * CAppServerDoc::RegistryQuery
  2199. *
  2200. * Queries the registry for the information about a WinStation AND
  2201. * queries the extension DLL for it's information about the WinStation
  2202. *
  2203. * ENTRY:
  2204. * pWinStationName (input)
  2205. * Points to the name of the WinStation
  2206. * pWsConfig (output)
  2207. * Where to put the query results
  2208. * pWdName (input)
  2209. * Points to the name of the Wd (this is used to determine
  2210. * which extension DLL owns the object)
  2211. * pExtObject (output)
  2212. * This pointer will point to the extension DLL's object
  2213. * for this WinStation
  2214. * EXIT:
  2215. * ERROR_SUCCESS if successful
  2216. * Registry error code, if not
  2217. *
  2218. ******************************************************************************/
  2219. LONG CAppServerDoc::RegistryQuery(PWINSTATIONNAME pWinStationName, PWINSTATIONCONFIG2 pWsConfig, PWDNAME pWdName, void **pExtObject)
  2220. {
  2221. LONG Status;
  2222. ULONG Length;
  2223. /*
  2224. * Query the registry for WinStation data
  2225. */
  2226. if((Status = RegWinStationQuery( SERVERNAME_CURRENT,
  2227. pWinStationName,
  2228. pWsConfig,
  2229. sizeof(WINSTATIONCONFIG2), &Length)) ) {
  2230. return Status;
  2231. }
  2232. // Ask the extension DLL for it's data
  2233. PTERMLOBJECT pObject = GetWdListObject(pWdName);
  2234. if(pObject && pObject->m_hExtensionDLL && pObject->m_lpfnExtRegQuery) {
  2235. *pExtObject = (*pObject->m_lpfnExtRegQuery)(pWinStationName, &pWsConfig->Pd[0]);
  2236. if(!pExtObject) Status = ERROR_INVALID_FUNCTION;
  2237. }
  2238. else *pExtObject = NULL;
  2239. return Status;
  2240. } // end CAppServerDoc::RegistryQuery
  2241. /*******************************************************************************
  2242. *
  2243. * CAppServerDoc::RegistryCreate
  2244. *
  2245. * Create/Update the registry for a WinStation AND
  2246. * tell the extension DLL to store it's information about the WinStation
  2247. *
  2248. * ENTRY:
  2249. * pWinStationName (input)
  2250. * Points to the name of the WinStation
  2251. * pWsConfig (input)
  2252. * Points to the data for this WinStation
  2253. * pWdName (input)
  2254. * Points to the name of the Wd (this is used to determine
  2255. * which extension DLL owns the object)
  2256. * pExtObject (input)
  2257. * Points to the extension DLL's data for this WinStation
  2258. * EXIT:
  2259. * ERROR_SUCCESS if successful
  2260. * Registry error code, if not
  2261. *
  2262. ******************************************************************************/
  2263. LONG CAppServerDoc::RegistryCreate(PWINSTATIONNAME pWinStationName, BOOLEAN bCreate, PWINSTATIONCONFIG2 pWsConfig, PWDNAME pWdName, void *pExtObject)
  2264. {
  2265. LONG Status;
  2266. if((Status = RegWinStationCreate( SERVERNAME_CURRENT,
  2267. pWinStationName,
  2268. bCreate,
  2269. pWsConfig,
  2270. sizeof(WINSTATIONCONFIG2))) ) {
  2271. return Status;
  2272. }
  2273. if(pExtObject) {
  2274. /*
  2275. * Tell the extension DLL to write it's data
  2276. */
  2277. PTERMLOBJECT pObject = GetWdListObject(pWdName);
  2278. if(pObject && pObject->m_hExtensionDLL && pObject->m_lpfnExtRegCreate) {
  2279. Status = (*pObject->m_lpfnExtRegCreate)(pWinStationName, pExtObject, bCreate);
  2280. }
  2281. }
  2282. return Status;
  2283. } // end CAppServerDoc::RegistryCreate
  2284. /*******************************************************************************
  2285. *
  2286. * CAppServerDoc::RegistryDelete
  2287. *
  2288. * Deletes a WinStation's data from the registry AND
  2289. * tells the extension DLL to delete it's data for the WinStation from
  2290. * the registry (or wherever he stores it)
  2291. *
  2292. * ENTRY:
  2293. * pWinStationName (input)
  2294. * Points to the name of the WinStation
  2295. * pWdName (input)
  2296. * Points to the name of the Wd (this is used to determine
  2297. * which extension DLL owns the object)
  2298. * pExtObject (input)
  2299. * Points to the extension DLL's data for this WinStation
  2300. * EXIT:
  2301. * ERROR_SUCCESS if successful
  2302. * Registry error code, if not
  2303. *
  2304. ******************************************************************************/
  2305. LONG CAppServerDoc::RegistryDelete(PWINSTATIONNAME pWinStationName, PWDNAME pWdName, void *pExtObject)
  2306. {
  2307. LONG Status;
  2308. LONG ExtStatus = ERROR_SUCCESS;
  2309. /*
  2310. * Tell the extension DLL to delete it's data first.
  2311. * This is done because it could be a subkey under the WinStation's data
  2312. * in the Registry. RegWinStationDelete calls RegDeleteKey which
  2313. * cannot delete subkeys under Windows NT.
  2314. */
  2315. if(pExtObject) {
  2316. /*
  2317. * Tell the extension DLL to delete it's data
  2318. */
  2319. PTERMLOBJECT pObject = GetWdListObject(pWdName);
  2320. if(pObject && pObject->m_hExtensionDLL && pObject->m_lpfnExtRegDelete) {
  2321. ExtStatus = (*pObject->m_lpfnExtRegDelete)(pWinStationName, pExtObject);
  2322. }
  2323. }
  2324. Status = RegWinStationDelete( SERVERNAME_CURRENT, pWinStationName);
  2325. if(ExtStatus) return ExtStatus;
  2326. return Status;
  2327. } // end CAppServerDoc::RegistryDelete
  2328. ///////////////////////////////////////////////////////////////////////////////
  2329. // CAppServerDoc message map
  2330. BEGIN_MESSAGE_MAP(CAppServerDoc, CDocument)
  2331. //{{AFX_MSG_MAP(CAppServerDoc)
  2332. //}}AFX_MSG_MAP
  2333. END_MESSAGE_MAP()
  2334. ////////////////////////////////////////////////////////////////////////////////
  2335. // CAppServerDoc commands
  2336. /*******************************************************************************
  2337. *
  2338. * CWinStationListObject constructor
  2339. *
  2340. *
  2341. * ENTRY:
  2342. * none
  2343. * EXIT:
  2344. * constructors don't have return types
  2345. *
  2346. ******************************************************************************/
  2347. CWinStationListObject::CWinStationListObject()
  2348. {
  2349. m_pExtObject = NULL;
  2350. } // end CWinStationListObject::CWinStationListObject
  2351. /*******************************************************************************
  2352. *
  2353. * CWinStationListObject destructor
  2354. *
  2355. * Tells the extension DLL to delete the object associated with this guy
  2356. *
  2357. * ENTRY:
  2358. * none
  2359. * EXIT:
  2360. * destructors don't have return types
  2361. *
  2362. ******************************************************************************/
  2363. CWinStationListObject::~CWinStationListObject()
  2364. {
  2365. if(m_pExtObject) {
  2366. PTERMLOBJECT pObject = GetWdListObject(m_WdName);
  2367. if(pObject && pObject->m_hExtensionDLL && pObject->m_lpfnExtDeleteObject) {
  2368. (*pObject->m_lpfnExtDeleteObject)(m_pExtObject);
  2369. }
  2370. }
  2371. } // end CWinStationListObject::~CWinStationListObject
  2372. /*******************************************************************************
  2373. *
  2374. * GetWdListObject -
  2375. *
  2376. * Returns a pointer to the Wd list object for the specified WD
  2377. *
  2378. * ENTRY:
  2379. * pWdName (input)
  2380. * Points to the name of the Wd
  2381. * EXIT:
  2382. * pointer to Wd List Object
  2383. * NULL if not found
  2384. *
  2385. ******************************************************************************/
  2386. PTERMLOBJECT GetWdListObject(PWDNAME pWdName)
  2387. {
  2388. POSITION pos;
  2389. PTERMLOBJECT pObject;
  2390. /*
  2391. * Traverse the WD list
  2392. */
  2393. for ( pos = pApp->m_WdList.GetHeadPosition(); pos != NULL; ) {
  2394. pObject = (PTERMLOBJECT)pApp->m_WdList.GetNext( pos );
  2395. if ( !lstrcmp( pObject->m_WdConfig.Wd.WdName, pWdName ) ) {
  2396. return(pObject);
  2397. }
  2398. }
  2399. return(NULL);
  2400. } // end GetWdListObject