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.

6939 lines
187 KiB

  1. /*************************************************************************
  2. *
  3. * winsta.c
  4. *
  5. * Client side APIs for window stations objects
  6. *
  7. * Copyright Microsoft Corporation, 1998
  8. *
  9. *************************************************************************/
  10. /*
  11. * Includes
  12. */
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <ntddkbd.h>
  17. #include <ntddmou.h>
  18. #include <windows.h>
  19. #include <winbase.h>
  20. #include <winerror.h>
  21. #include <allproc.h>
  22. #include <winsta.h>
  23. #include <winwlx.h>
  24. #include <malloc.h>
  25. #include <stdio.h>
  26. #include <dbt.h>
  27. /*
  28. * Include the RPC generated common header
  29. */
  30. #include "tsrpc.h"
  31. #include "rpcwire.h"
  32. #ifdef NTSDDEBUG
  33. #define NTSDDBGPRINT(x) DbgPrint x
  34. #else
  35. #define NTSDDBGPRINT(x)
  36. #endif
  37. #if DBG
  38. #define VERIFY(x) ASSERT(x) // we already have ASSERT;
  39. #else
  40. #define VERIFY(x) (x)
  41. #endif
  42. #if DBG
  43. ULONG
  44. DbgPrint(
  45. PCH Format,
  46. ...
  47. );
  48. #define DBGPRINT(x) DbgPrint x
  49. #if DBGTRACE
  50. #define TRACE0(x) DbgPrint x
  51. #define TRACE1(x) DbgPrint x
  52. #else
  53. #define TRACE0(x)
  54. #define TRACE1(x)
  55. #endif
  56. #else
  57. #define DBGPRINT(x)
  58. #define TRACE0(x)
  59. #define TRACE1(x)
  60. #endif
  61. /*
  62. * This handle is returned when there is no terminal
  63. * server present on the system. (Non-Hydra)
  64. */
  65. #define RPC_HANDLE_NO_SERVER (HANDLE)IntToPtr( 0xFFFFFFFD )
  66. /*
  67. * Private Procedures defined here
  68. */
  69. BOOLEAN DllInitialize(IN PVOID, IN ULONG, IN PCONTEXT OPTIONAL);
  70. RPC_STATUS
  71. RpcWinStationBind(
  72. LPWSTR pszUuid,
  73. LPWSTR pszProtocolSequence,
  74. LPWSTR pszNetworkAddress,
  75. LPWSTR pszEndPoint,
  76. LPWSTR pszOptions,
  77. RPC_BINDING_HANDLE *pHandle
  78. );
  79. BOOLEAN
  80. RpcLocalAutoBind(
  81. VOID
  82. );
  83. /*
  84. * Global data
  85. */
  86. // Critical section to protect the handlelist from multiple threads
  87. RTL_CRITICAL_SECTION WstHandleLock;
  88. /*
  89. * RPC program identifier and security options
  90. */
  91. LPWSTR pszUuid = L"5ca4a760-ebb1-11cf-8611-00a0245420ed"; // From ICAAPI.IDL
  92. LPWSTR pszOptions = L"Security=Impersonation Dynamic False";
  93. /*
  94. * RPC over LPC binding information
  95. */
  96. LPWSTR pszProtocolSequence = L"ncalrpc"; // RPC over LPC
  97. LPWSTR pszEndPoint = L"IcaApi";
  98. /*
  99. * RPC over named pipes binding information
  100. */
  101. LPWSTR pszRemoteProtocolSequence = L"ncacn_np"; // RPC over Named pipes
  102. LPWSTR pszRemoteEndPoint = L"\\pipe\\Ctx_WinStation_API_service";
  103. /*
  104. * other internal Procedures used (not defined here)
  105. */
  106. VOID UnicodeToAnsi( CHAR *, ULONG, WCHAR * );
  107. VOID AnsiToUnicode( WCHAR *, ULONG, CHAR * );
  108. VOID PdConfig2U2A( PPDCONFIG2A, PPDCONFIG2W );
  109. VOID PdConfig2A2U( PPDCONFIG2W, PPDCONFIG2A );
  110. VOID PdParamsU2A( PPDPARAMSA, PPDPARAMSW );
  111. VOID PdParamsA2U( PPDPARAMSW, PPDPARAMSA );
  112. VOID WdConfigU2A( PWDCONFIGA, PWDCONFIGW );
  113. VOID WdConfigA2U( PWDCONFIGW, PWDCONFIGA );
  114. VOID WinStationCreateU2A( PWINSTATIONCREATEA, PWINSTATIONCREATEW );
  115. VOID WinStationCreateA2U( PWINSTATIONCREATEW, PWINSTATIONCREATEA );
  116. VOID WinStationConfigU2A( PWINSTATIONCONFIGA, PWINSTATIONCONFIGW );
  117. VOID WinStationConfigA2U( PWINSTATIONCONFIGW, PWINSTATIONCONFIGA );
  118. VOID WinStationPrinterU2A( PWINSTATIONPRINTERA, PWINSTATIONPRINTERW );
  119. VOID WinStationPrinterA2U( PWINSTATIONPRINTERW, PWINSTATIONPRINTERA );
  120. VOID WinStationInformationU2A( PWINSTATIONINFORMATIONA,
  121. PWINSTATIONINFORMATIONW );
  122. VOID WinStationInformationA2U( PWINSTATIONINFORMATIONW,
  123. PWINSTATIONINFORMATIONA );
  124. VOID WinStationClientU2A( PWINSTATIONCLIENTA, PWINSTATIONCLIENTW );
  125. VOID WinStationProductIdU2A( PWINSTATIONPRODIDA, PWINSTATIONPRODIDW );
  126. ULONG CheckUserBuffer(WINSTATIONINFOCLASS,
  127. PVOID,
  128. ULONG,
  129. PVOID *,
  130. PULONG,
  131. BOOLEAN *);
  132. BOOLEAN CloseContextHandle(HANDLE *pHandle, DWORD *pdwResult);
  133. /*
  134. * Check to see that caller does not hold the loader critsec.
  135. * WinStation APIs must NOT be called while holding the loader critsec
  136. * since deadlock may occur.
  137. */
  138. #define CheckLoaderLock() \
  139. ASSERT( NtCurrentTeb()->ClientId.UniqueThread != \
  140. ((PRTL_CRITICAL_SECTION)(NtCurrentPeb()->LoaderLock))->OwningThread );
  141. /*
  142. * Handle the SERVERNAME_CURRENT for auto local binding.
  143. */
  144. #define HANDLE_CURRENT_BINDING( hServer ) \
  145. CheckLoaderLock(); \
  146. if( hServer == SERVERNAME_CURRENT ) { \
  147. if( IcaApi_IfHandle == NULL ) { \
  148. if( !RpcLocalAutoBind() ) { \
  149. return FALSE; \
  150. } \
  151. } \
  152. hServer = IcaApi_IfHandle; \
  153. } \
  154. if( hServer == RPC_HANDLE_NO_SERVER ) { \
  155. SetLastError( ERROR_APP_WRONG_OS ); \
  156. return FALSE; \
  157. }
  158. #define HANDLE_CURRENT_BINDING_BUFFER( hServer, pBuffer ) \
  159. CheckLoaderLock(); \
  160. if( hServer == SERVERNAME_CURRENT ) { \
  161. if( IcaApi_IfHandle == NULL ) { \
  162. if( !RpcLocalAutoBind() ) { \
  163. if (pBuffer != NULL) { \
  164. LocalFree(pBuffer); \
  165. } \
  166. return FALSE; \
  167. } \
  168. } \
  169. hServer = IcaApi_IfHandle; \
  170. } \
  171. if( hServer == RPC_HANDLE_NO_SERVER ) { \
  172. if (pBuffer != NULL) { \
  173. LocalFree(pBuffer); \
  174. } \
  175. SetLastError( ERROR_APP_WRONG_OS ); \
  176. return FALSE; \
  177. }
  178. /*
  179. * Handle the SERVERNAME_CURRENT for auto local binding that
  180. * allows the RPC_HANDLE_NO_SERVER handle.
  181. */
  182. #define HANDLE_CURRENT_BINDING_NO_SERVER( hServer ) \
  183. CheckLoaderLock(); \
  184. if( hServer == SERVERNAME_CURRENT ) { \
  185. if( IcaApi_IfHandle == NULL ) { \
  186. if( !RpcLocalAutoBind() ) { \
  187. return FALSE; \
  188. } \
  189. } \
  190. hServer = IcaApi_IfHandle; \
  191. }
  192. /****************************************************************************
  193. *
  194. * DllInitialize
  195. *
  196. * Function is called when the DLL is loaded. The only work we do here
  197. * is initialize our CriticalSection.
  198. *
  199. * ENTRY:
  200. *
  201. * DllHandle
  202. * Loaded handle to our DLL image
  203. *
  204. * Reason
  205. * Reason for notifying us
  206. *
  207. * Context
  208. * Reason specific parameter from NT
  209. *
  210. ****************************************************************************/
  211. BOOLEAN
  212. DllInitialize(
  213. IN PVOID DllHandle,
  214. IN ULONG Reason,
  215. IN PCONTEXT Context OPTIONAL
  216. )
  217. {
  218. BOOLEAN rc;
  219. DWORD Result;
  220. RPC_STATUS Status;
  221. BOOLEAN Success;
  222. NTSTATUS ntStatus;
  223. static BOOLEAN sbIniOK = FALSE;
  224. (VOID)Context;
  225. Success = TRUE;
  226. switch ( Reason ) {
  227. case DLL_PROCESS_ATTACH:
  228. /*
  229. // some instrumentation for catching the bug #
  230. // 145378 TRACKING: Winsta.dll getting loaded into csrss
  231. DBGPRINT(("Checking if winsta is being loaded into csrss.exe\n"));
  232. if(NULL != wcsstr(GetCommandLine(), TEXT("csrss.exe")))
  233. {
  234. DBGPRINT(("**** will break because csrss.exe loaded winsta.dll ***** \n"));
  235. DebugBreak();
  236. }
  237. */
  238. ntStatus = RtlInitializeCriticalSection( &WstHandleLock );
  239. IcaApi_IfHandle = NULL;
  240. if (!NT_SUCCESS(ntStatus)) {
  241. Success = FALSE;
  242. }else {
  243. sbIniOK = TRUE;
  244. }
  245. break;
  246. case DLL_PROCESS_DETACH:
  247. if (sbIniOK) {
  248. if( (IcaApi_IfHandle != NULL) && (IcaApi_IfHandle != RPC_HANDLE_NO_SERVER) )
  249. {
  250. HANDLE hTmp = InterlockedExchangePointer(&IcaApi_IfHandle,NULL);
  251. if( hTmp && !IcaApi_IfHandle )
  252. {
  253. CloseContextHandle(&hTmp, &Result);
  254. }
  255. }
  256. RtlDeleteCriticalSection( &WstHandleLock );
  257. }
  258. break;
  259. default:
  260. break;
  261. }
  262. return Success;
  263. }
  264. /*****************************************************************************
  265. *
  266. * RpcWinStationBind
  267. *
  268. * Perform the RPC binding sequence.
  269. *
  270. * This is an internal function.
  271. *
  272. * ENTRY:
  273. * Param1 (input/output)
  274. * Comments
  275. *
  276. * EXIT:
  277. * ERROR_SUCCESS - no error
  278. *
  279. ****************************************************************************/
  280. RPC_STATUS
  281. RpcWinStationBind(
  282. LPWSTR pszUuid,
  283. LPWSTR pszProtocolSequence,
  284. LPWSTR pszNetworkAddress,
  285. LPWSTR pszEndPoint,
  286. LPWSTR pszOptions,
  287. RPC_BINDING_HANDLE *pHandle
  288. )
  289. {
  290. RPC_STATUS Status;
  291. LPWSTR pszString = NULL;
  292. /*
  293. * Compose the binding string using the helper routine
  294. * and our protocol sequence, security options, UUID, etc.
  295. */
  296. Status = RpcStringBindingCompose(
  297. pszUuid,
  298. pszProtocolSequence,
  299. pszNetworkAddress,
  300. pszEndPoint,
  301. pszOptions,
  302. &pszString
  303. );
  304. if( Status != RPC_S_OK ) {
  305. DBGPRINT(("Error %d in RpcStringBindingCompose\n",Status));
  306. return( Status );
  307. }
  308. /*
  309. * Now generate the RPC binding from the cononical RPC
  310. * binding string.
  311. */
  312. Status = RpcBindingFromStringBinding(
  313. pszString,
  314. pHandle
  315. );
  316. if( Status != RPC_S_OK ) {
  317. DBGPRINT(("Error %d in RpcBindingFromStringBinding\n",Status));
  318. RpcStringFree( &pszString );
  319. return( Status );
  320. }
  321. /*
  322. * Free the memory returned from RpcStringBindingCompose()
  323. */
  324. RpcStringFree( &pszString );
  325. return( Status );
  326. }
  327. /*****************************************************************************
  328. *
  329. * WinStationOpenLocalServer (Private)
  330. *
  331. * Connect to the local RPC over LPC server for WINSTATION API's.
  332. *
  333. * On non-terminal server machines, it returns a handle that allows
  334. * a subset of the DLL's functions to operate locally.
  335. *
  336. * ENTRY:
  337. *
  338. * EXIT:
  339. *
  340. ****************************************************************************/
  341. HANDLE WINAPI
  342. WinStationOpenLocalServer(
  343. )
  344. {
  345. RPC_STATUS Status;
  346. DWORD Result;
  347. BOOLEAN rc;
  348. RPC_BINDING_HANDLE RpcHandle;
  349. HANDLE ContextHandle;
  350. if( !(USER_SHARED_DATA->SuiteMask & (1 << TerminalServer)) ) {
  351. return( RPC_HANDLE_NO_SERVER );
  352. }
  353. /*
  354. * Do the RPC bind to the local server.
  355. *
  356. * We use explict binding handles since we want
  357. * to allow a single application to talk to multiple
  358. * WinFrame servers at a time.
  359. *
  360. * NOTE: We use the auto handle from the .ACF file
  361. * for our local connections.
  362. */
  363. Status = RpcWinStationBind(
  364. pszUuid,
  365. pszProtocolSequence,
  366. NULL, // ServerName
  367. pszEndPoint,
  368. pszOptions,
  369. &RpcHandle
  370. );
  371. if( Status != RPC_S_OK ) {
  372. SetLastError( RtlNtStatusToDosError(RPC_NT_SERVER_UNAVAILABLE) );
  373. return( NULL );
  374. }
  375. //
  376. // Get a context handle from the server so it can
  377. // manage the connections state
  378. //
  379. // NOTE: This can fail due to authentication failure.
  380. //
  381. RpcTryExcept {
  382. rc = RpcWinStationOpenServer( RpcHandle, &Result, &ContextHandle );
  383. }
  384. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  385. Result = RpcExceptionCode();
  386. rc = FALSE;
  387. #if DBG
  388. if ( Result != RPC_S_SERVER_UNAVAILABLE ) {
  389. DBGPRINT(("RPC Exception %d\n",Result));
  390. }
  391. #endif
  392. }
  393. RpcEndExcept
  394. if( rc ) {
  395. //
  396. // Close the server binding handle now that we
  397. // have a client specific context handle
  398. //
  399. RpcBindingFree( &RpcHandle );
  400. return( (HANDLE)ContextHandle );
  401. }
  402. else {
  403. #if DBG
  404. if ( Result != RPC_S_SERVER_UNAVAILABLE ) {
  405. DBGPRINT(("WinStationOpenLocalServer: Error %d getting context handle\n",Result));
  406. }
  407. #endif
  408. RpcBindingFree( &RpcHandle );
  409. SetLastError( Result );
  410. return( NULL );
  411. }
  412. }
  413. /*****************************************************************************
  414. *
  415. * RpcLocalAutoBind
  416. *
  417. * Handle auto binding to the local server.
  418. *
  419. * ENTRY:
  420. *
  421. * EXIT:
  422. * TRUE - Success
  423. * FALSE - Error, Use GetLastError() to retrieve reason.
  424. *
  425. ****************************************************************************/
  426. BOOLEAN
  427. RpcLocalAutoBind(void)
  428. {
  429. if( IcaApi_IfHandle == NULL ) {
  430. DWORD Result;
  431. HANDLE hTmp = WinStationOpenLocalServer();
  432. if( hTmp == NULL ) {
  433. SetLastError( RPC_S_INVALID_BINDING );
  434. return( FALSE );
  435. }
  436. InterlockedCompareExchangePointer(&IcaApi_IfHandle,hTmp,NULL);
  437. if(IcaApi_IfHandle != hTmp) {
  438. CloseContextHandle(&hTmp, &Result);
  439. }
  440. }
  441. return( TRUE );
  442. }
  443. /*****************************************************************************
  444. *
  445. * WinStationOpenServerA
  446. *
  447. * Connect to a WinFrame computer in order to issue
  448. * ICA API's
  449. *
  450. * NULL for machine name means local system.
  451. *
  452. * ENTRY:
  453. * Machine (input)
  454. * Name of WinFrame computer to connect to
  455. *
  456. * EXIT:
  457. * handle to server (or NULL on error)
  458. *
  459. ****************************************************************************/
  460. HANDLE WINAPI
  461. WinStationOpenServerA(
  462. LPSTR pServerName
  463. )
  464. {
  465. HANDLE hServer;
  466. ULONG NameLength;
  467. PWCHAR pServerNameW = NULL;
  468. if( pServerName == NULL ) {
  469. return( WinStationOpenServerW( NULL ) );
  470. }
  471. NameLength = strlen( pServerName ) + 1;
  472. pServerNameW = LocalAlloc( 0, NameLength * sizeof(WCHAR) );
  473. if( pServerNameW == NULL ) {
  474. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  475. return( NULL );
  476. }
  477. AnsiToUnicode( pServerNameW, NameLength*sizeof(WCHAR), pServerName );
  478. hServer = WinStationOpenServerW( pServerNameW );
  479. LocalFree( pServerNameW );
  480. return( hServer );
  481. }
  482. /*****************************************************************************
  483. *
  484. * WinStationOpenServerW
  485. *
  486. * Connect to a WinFrame computer in order to issue
  487. * ICA API's
  488. *
  489. * NULL for machine name means local system.
  490. *
  491. * ENTRY:
  492. * Machine (input)
  493. * Name of WinFrame computer to connect to
  494. *
  495. * EXIT:
  496. * handle to server (or NULL on error)
  497. *
  498. ****************************************************************************/
  499. HANDLE WINAPI
  500. WinStationOpenServerW(
  501. LPWSTR pServerName
  502. )
  503. {
  504. DWORD Result;
  505. BOOLEAN rc;
  506. RPC_STATUS Status;
  507. RPC_BINDING_HANDLE RpcHandle;
  508. HANDLE ContextHandle;
  509. /*
  510. * If the server name is NULL, attempt to open
  511. * the local machines ICA server over LPC.
  512. */
  513. if( pServerName == NULL ) {
  514. return( WinStationOpenLocalServer() );
  515. }
  516. /*
  517. * Do the RPC bind to the server.
  518. *
  519. * We use explict binding handles since we want
  520. * to allow a single application to talk to multiple
  521. * WinFrame servers at a time.
  522. */
  523. Status = RpcWinStationBind(
  524. pszUuid,
  525. pszRemoteProtocolSequence,
  526. pServerName,
  527. pszRemoteEndPoint,
  528. pszOptions,
  529. &RpcHandle
  530. );
  531. if( Status != RPC_S_OK ) {
  532. SetLastError( RtlNtStatusToDosError(RPC_NT_SERVER_UNAVAILABLE) );
  533. return( NULL );
  534. }
  535. //
  536. // Get a context handle from the server so it can
  537. // manage the connections state
  538. //
  539. // NOTE: This can fail due to authentication failure.
  540. //
  541. RpcTryExcept {
  542. rc = RpcWinStationOpenServer( RpcHandle, &Result, &ContextHandle );
  543. }
  544. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  545. Result = RpcExceptionCode();
  546. rc = FALSE;
  547. DBGPRINT(("RPC Exception %d\n",Result));
  548. }
  549. RpcEndExcept
  550. if( rc ) {
  551. //
  552. // Close the server binding handle now that we
  553. // have a client specific context handle
  554. //
  555. RpcBindingFree( &RpcHandle );
  556. return( (HANDLE)ContextHandle );
  557. }
  558. else {
  559. DBGPRINT(("WinStationOpenServerW: Error %d getting context handle\n",Result));
  560. SetLastError( Result );
  561. return( NULL );
  562. }
  563. }
  564. /*****************************************************************************
  565. *
  566. * WinStationCloseServer
  567. *
  568. * Close a connection to a WinFrame computer.
  569. *
  570. * ENTRY:
  571. * hServer (input)
  572. * Handle to close
  573. *
  574. * EXIT:
  575. * ERROR_SUCCESS - no error
  576. *
  577. ****************************************************************************/
  578. BOOLEAN WINAPI
  579. WinStationCloseServer(
  580. HANDLE hServer
  581. )
  582. {
  583. BOOLEAN rc;
  584. DWORD Result;
  585. //
  586. // Do not close the implicit handles
  587. //
  588. if( (hServer == IcaApi_IfHandle) ||
  589. (hServer == RPC_HANDLE_NO_SERVER) ) {
  590. return( TRUE );
  591. }
  592. //
  593. // Send the close to the remote side so it clean
  594. // cleanup its context
  595. //
  596. rc = CloseContextHandle(&hServer, &Result);
  597. if( rc ) {
  598. return( TRUE );
  599. }
  600. else {
  601. DBGPRINT(("WinStationCloseServer: Error %d closing context handle\n",Result));
  602. SetLastError( Result );
  603. return( FALSE );
  604. }
  605. }
  606. /*****************************************************************************
  607. *
  608. * MIDL_user_allocate
  609. *
  610. * Handles RPC's allocation of argument data structures
  611. *
  612. * ENTRY:
  613. * Param1 (input/output)
  614. * Comments
  615. *
  616. * EXIT:
  617. * ERROR_SUCCESS - no error
  618. *
  619. ****************************************************************************/
  620. void __RPC_FAR * __RPC_USER
  621. MIDL_user_allocate(
  622. size_t Size
  623. )
  624. {
  625. return( LocalAlloc(LMEM_FIXED,Size) );
  626. }
  627. /*****************************************************************************
  628. *
  629. * MIDL_user_allocate
  630. *
  631. * Handles RPC's de-allocation of argument data structures
  632. *
  633. * ENTRY:
  634. * Param1 (input/output)
  635. * Comments
  636. *
  637. * EXIT:
  638. * ERROR_SUCCESS - no error
  639. *
  640. ****************************************************************************/
  641. void __RPC_USER
  642. MIDL_user_free(
  643. void __RPC_FAR *p
  644. )
  645. {
  646. LocalFree( p );
  647. }
  648. /*****************************************************************************
  649. *
  650. * WinStationServerPing
  651. *
  652. * Ping the given WinFrame server handle to see if it is still up.
  653. *
  654. * ENTRY:
  655. * hServer (input)
  656. * Open RPC server handle
  657. *
  658. * EXIT:
  659. * ERROR_SUCCESS - no error
  660. *
  661. ****************************************************************************/
  662. BOOLEAN WINAPI
  663. WinStationServerPing(
  664. HANDLE hServer
  665. )
  666. {
  667. DWORD Result;
  668. BOOLEAN rc;
  669. HANDLE_CURRENT_BINDING( hServer );
  670. /*
  671. * Do the RPC
  672. *
  673. * NOTE: This must be done under an RPC exception handler,
  674. * since the RPC runtime code throws exceptions if
  675. * network errors occur, or the server can not be
  676. * reached.
  677. */
  678. RpcTryExcept {
  679. rc = RpcIcaServerPing(
  680. hServer,
  681. &Result
  682. );
  683. Result = RtlNtStatusToDosError( Result );
  684. if( !rc ) SetLastError(Result);
  685. TRACE0(("RpcIcaServerPing rc 0x%x, Result 0x%x\n",rc, Result));
  686. }
  687. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  688. Result = RpcExceptionCode();
  689. SetLastError( Result );
  690. DBGPRINT(("RPC Exception %d\n",Result));
  691. rc = FALSE;
  692. }
  693. RpcEndExcept
  694. return( rc );
  695. }
  696. /*******************************************************************************
  697. *
  698. * WinStationEnumerateA (ANSI stub)
  699. *
  700. * Returns a list of window station objects.
  701. *
  702. * ENTRY:
  703. *
  704. * see WinStationEnumerateW
  705. *
  706. * EXIT:
  707. *
  708. * see WinStationEnumerateW, plus
  709. *
  710. * ERROR_NOT_ENOUGH_MEMORY - the LocalAlloc failed
  711. *
  712. ******************************************************************************/
  713. BOOLEAN WINAPI
  714. WinStationEnumerateA(
  715. HANDLE hServer,
  716. PLOGONIDA *ppLogonId,
  717. PULONG pEntries
  718. )
  719. {
  720. PLOGONIDW pLogonIdW, pLogonIdBaseW;
  721. PLOGONIDA pLogonIdA;
  722. BOOLEAN Status;
  723. ULONG Count;
  724. /*
  725. * Call UNICODE WinStationEnumerateW first.
  726. */
  727. *pEntries = 0;
  728. *ppLogonId = NULL;
  729. Status = WinStationEnumerateW( hServer, &pLogonIdBaseW, &Count );
  730. if ( !Status )
  731. goto badenumerate;
  732. /*
  733. * Allocate buffer and perform conversion from UNICODE to ANSI.
  734. */
  735. if ( !(pLogonIdA = (PLOGONIDA)LocalAlloc( 0, Count * sizeof(LOGONIDA) )) ) {
  736. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  737. Status = FALSE;
  738. goto nomemory;
  739. }
  740. *pEntries = Count;
  741. *ppLogonId = pLogonIdA;
  742. for ( pLogonIdW = pLogonIdBaseW; Count; Count-- ) {
  743. pLogonIdA->LogonId = pLogonIdW->LogonId;
  744. UnicodeToAnsi( pLogonIdA->WinStationName,
  745. sizeof(WINSTATIONNAMEA),
  746. pLogonIdW->WinStationName );
  747. pLogonIdA->State = pLogonIdW->State;
  748. pLogonIdA++;
  749. pLogonIdW++;
  750. }
  751. nomemory:
  752. /*
  753. * Free the UNICODE enumerate buffer.
  754. */
  755. WinStationFreeMemory( pLogonIdBaseW );
  756. badenumerate:
  757. return(Status);
  758. }
  759. /*******************************************************************************
  760. *
  761. * WinStationEnumerateW (UNICODE)
  762. *
  763. * Returns a list of window station objects.
  764. *
  765. * ENTRY:
  766. * hServer (input)
  767. * Server handle
  768. * ppLogonId (output)
  769. * Points to a pointer to a buffer to receive the enumeration results,
  770. * which are returned as an array of LOGONID structures. The buffer is
  771. * allocated within this API and is disposed of using
  772. * WinStationFreeMemory.
  773. * pEntries (output)
  774. * Points to a variable specifying the number of entries read.
  775. *
  776. * EXIT:
  777. *
  778. * TRUE -- The enumerate operation succeeded.
  779. *
  780. * FALSE -- The operation failed. Extended error status is available
  781. * using GetLastError.
  782. *
  783. ******************************************************************************/
  784. BOOLEAN WINAPI
  785. WinStationEnumerateW(
  786. HANDLE hServer,
  787. PLOGONIDW *ppLogonId,
  788. PULONG pEntries
  789. )
  790. {
  791. DWORD Result;
  792. BOOLEAN rc;
  793. ULONG LogonIdCount = 50;
  794. PLOGONIDW pLogonId, pLogonIdTemp;
  795. ULONG Length;
  796. ULONG Index = 0;
  797. ULONG ByteCount = 0;
  798. HANDLE_CURRENT_BINDING( hServer );
  799. *pEntries = 0;
  800. *ppLogonId = NULL;
  801. Length = LogonIdCount * sizeof(LOGONIDW);
  802. if ( !(pLogonId = (PLOGONIDW)LocalAlloc( 0, Length)) ) {
  803. Result = ERROR_NOT_ENOUGH_MEMORY;
  804. goto nomemexit;
  805. }
  806. /*
  807. * get list of all WinStations
  808. */
  809. for (;;) {
  810. if ( Index ) {
  811. ByteCount = *pEntries * sizeof(LOGONIDW);
  812. *pEntries += LogonIdCount;
  813. if ( !(pLogonIdTemp = (PSESSIONIDW)LocalAlloc( 0,
  814. (*pEntries * sizeof(LOGONIDW)))) ) {
  815. Result = ERROR_NOT_ENOUGH_MEMORY;
  816. goto errexit;
  817. }
  818. if ( *ppLogonId ) {
  819. MoveMemory( pLogonIdTemp, *ppLogonId, ByteCount );
  820. LocalFree(*ppLogonId);
  821. }
  822. MoveMemory( ((PBYTE)pLogonIdTemp + ByteCount), pLogonId,
  823. (LogonIdCount * sizeof(LOGONIDW)) );
  824. *ppLogonId = pLogonIdTemp;
  825. }
  826. RpcTryExcept {
  827. rc = RpcWinStationEnumerate(
  828. hServer,
  829. &Result,
  830. &LogonIdCount,
  831. (PCHAR)pLogonId,
  832. &Length,
  833. &Index
  834. );
  835. Result = RtlNtStatusToDosError( Result );
  836. if ( Result == ERROR_NO_MORE_ITEMS) {
  837. Result = ERROR_SUCCESS;
  838. break;
  839. }
  840. }
  841. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  842. Result = RpcExceptionCode();
  843. DBGPRINT(("RPC Exception %d\n",Result));
  844. goto nomemexit;
  845. }
  846. RpcEndExcept
  847. }
  848. errexit:
  849. LocalFree( pLogonId );
  850. nomemexit:
  851. if ( Result ) {
  852. if ( *ppLogonId ) {
  853. LocalFree( *ppLogonId );
  854. *ppLogonId = NULL;
  855. }
  856. SetLastError(Result);
  857. return(FALSE);
  858. } else {
  859. return(TRUE);
  860. }
  861. }
  862. /*******************************************************************************
  863. *
  864. * WinStationEnumerate_IndexedA (ANSI stub)
  865. *
  866. * Returns a list of window station objects (multi-call indexed).
  867. *
  868. * NOTE: this API used to be WinStationEnumerateA in WinFrame 1.6 and
  869. * earlier. It is provided now for backward compatibility with
  870. * Citrix code built around the indexed enumeration procedure.
  871. * New code should use the WinStationEnumerateA call.
  872. *
  873. * ENTRY:
  874. *
  875. * see WinStationEnumerate_IndexedW
  876. *
  877. * EXIT:
  878. *
  879. * see WinStationEnumerate_IndexedW, plus
  880. *
  881. * ERROR_NOT_ENOUGH_MEMORY - the LocalAlloc failed
  882. *
  883. ******************************************************************************/
  884. BOOLEAN WINAPI
  885. WinStationEnumerate_IndexedA(
  886. HANDLE hServer,
  887. PULONG pEntries,
  888. PLOGONIDA pLogonId,
  889. PULONG pByteCount,
  890. PULONG pIndex
  891. )
  892. {
  893. PLOGONIDW pBuffer = NULL, pLogonIdW;
  894. BOOLEAN Status;
  895. ULONG Count, ByteCountW = (*pByteCount << 1);
  896. /*
  897. * If the caller supplied a buffer and the length is not 0,
  898. * allocate a corresponding (*2) buffer for UNICODE strings.
  899. */
  900. if ( pLogonId && ByteCountW ) {
  901. if ( !(pBuffer = LocalAlloc(0, ByteCountW)) ) {
  902. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  903. return(FALSE);
  904. }
  905. }
  906. /*
  907. * Enumerate WinStations
  908. */
  909. pLogonIdW = pBuffer;
  910. Status = WinStationEnumerate_IndexedW( hServer, pEntries, pLogonIdW,
  911. &ByteCountW, pIndex );
  912. /*
  913. * Always /2 the resultant ByteCount (whether sucessful or not).
  914. */
  915. *pByteCount = (ByteCountW >> 1);
  916. /*
  917. * If the function completed sucessfully and caller
  918. * (and stub) defined a buffer to copy into, perform conversion
  919. * from UNICODE to ANSI.
  920. */
  921. if ( Status && pLogonIdW && pLogonId ) {
  922. for ( Count = *pEntries; Count; Count-- ) {
  923. pLogonId->LogonId = pLogonIdW->LogonId;
  924. UnicodeToAnsi( pLogonId->WinStationName,
  925. sizeof(WINSTATIONNAMEA),
  926. pLogonIdW->WinStationName );
  927. pLogonId->State = pLogonIdW->State;
  928. (char*)pLogonId += sizeof(LOGONIDA);
  929. (char*)pLogonIdW += sizeof(LOGONIDW);
  930. }
  931. }
  932. /*
  933. * If we defined a buffer, free it now, then return the status of
  934. * the WinStationEnumerateW call.
  935. */
  936. if ( pBuffer )
  937. LocalFree(pBuffer);
  938. return(Status);
  939. }
  940. /*******************************************************************************
  941. *
  942. * WinStationEnumerate_IndexedW (UNICODE)
  943. *
  944. * Returns a list of window station objects (multi-call indexed).
  945. *
  946. * NOTE: this API used to be WinStationEnumerateW in WinFrame 1.6 and
  947. * earlier. It is provided now for backward compatibility with
  948. * Citrix code built around the indexed enumeration procedure.
  949. * New code should use the WinStationEnumerateW call.
  950. *
  951. * ENTRY:
  952. *
  953. * pEntries (input/output)
  954. * Points to a variable specifying the number of entries requested.
  955. * If the number requested is 0xFFFFFFFF, the function returns as
  956. * many entries as possible. When the function finishes successfully,
  957. * the variable pointed to by the pEntries parameter contains the
  958. * number of entries actually read.
  959. *
  960. * pLogonId (output)
  961. * Points to the buffer to receive the enumeration results, which are
  962. * returned as an array of LOGONID structures. If the window
  963. * station is disconnected the name is null.
  964. *
  965. * pByteCount (input/output)
  966. * Points to a variable that specifies the size, in bytes, of the
  967. * pLogonId parameter. If the buffer is too small to receive even
  968. * one entry, this variable receives the required size of the buffer.
  969. *
  970. * pIndex (input/output)
  971. * Points to a ULONG that specifies where to start the enumeration.
  972. * The only user visible value is 0, for starting at the begining.
  973. * Each call will update this so that the next call will return the
  974. * next WinStation in the list, till end of list.
  975. * The user should not interpret, or use the internal values, other
  976. * than the special case 0.
  977. *
  978. * EXIT:
  979. *
  980. * TRUE - The enumeration succeeded, and the buffer contains the
  981. * requested data. The calling application can continue to call
  982. * the WinStationEnumerate function to complete the enumeration.
  983. *
  984. * FALSE - The operation failed. Extended error status is available using
  985. * GetLastError. Possible return values from GetLastError include
  986. * the following:
  987. *
  988. * ERROR_NO_MORE_ITEMS - There are no more entries. The buffer
  989. * contents are undefined.
  990. * ERROR_MORE_DATA - The buffer is too small for even one entry.
  991. *
  992. ******************************************************************************/
  993. BOOLEAN WINAPI
  994. WinStationEnumerate_IndexedW(
  995. HANDLE hServer,
  996. PULONG pEntries,
  997. PLOGONIDW pLogonId,
  998. PULONG pByteCount,
  999. PULONG pIndex
  1000. )
  1001. {
  1002. DWORD Result;
  1003. BOOLEAN rc;
  1004. HANDLE_CURRENT_BINDING( hServer );
  1005. RpcTryExcept {
  1006. rc = RpcWinStationEnumerate(
  1007. hServer,
  1008. &Result,
  1009. pEntries,
  1010. (PCHAR)pLogonId,
  1011. pByteCount,
  1012. pIndex
  1013. );
  1014. Result = RtlNtStatusToDosError( Result );
  1015. if( !rc ) SetLastError(Result);
  1016. }
  1017. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1018. Result = RpcExceptionCode();
  1019. SetLastError( Result );
  1020. DBGPRINT(("RPC Exception %d\n",Result));
  1021. rc = FALSE;
  1022. }
  1023. RpcEndExcept
  1024. return( rc );
  1025. }
  1026. /*******************************************************************************
  1027. *
  1028. * WinStationGetAllProcesses (UNICODE)
  1029. *
  1030. * Returns a structure containing TS_SYS_PROCESS_INFORMATION structures
  1031. * for each process on the specified server.
  1032. *
  1033. * ENTRY:
  1034. *
  1035. * EXIT:
  1036. * TRUE - The enumeration succeeded, and the buffer contains the
  1037. * requested data.
  1038. * FALSE - The operation failed. Extended error status is available using
  1039. * GetLastError.
  1040. *
  1041. ******************************************************************************/
  1042. BOOLEAN WINAPI
  1043. WinStationGetAllProcesses(
  1044. HANDLE hServer,
  1045. ULONG Level,
  1046. ULONG *pNumberOfProcesses,
  1047. PVOID *ppProcessArray
  1048. )
  1049. {
  1050. BOOLEAN bGetAllProcessesOk = FALSE;
  1051. DWORD dwResult;
  1052. if (Level != GAP_LEVEL_BASIC)
  1053. {
  1054. dwResult = RtlNtStatusToDosError( STATUS_NOT_IMPLEMENTED );
  1055. SetLastError(dwResult);
  1056. return FALSE;
  1057. }
  1058. HANDLE_CURRENT_BINDING( hServer );
  1059. // The Win2K server uses PTS_ALL_PROCESSES_INFO structure for the process information.
  1060. // And the whistler server uses PTS_SYS_PROCESS_INFORMATION_NT6 structure for the same.
  1061. // So, we have to try two different RPC APIs. Assume initially that the server is a
  1062. // Whistler server and use RpcWinStationGetAllProcesses_NT6. If it is Win2K server, this
  1063. // call will fail, because this API does not exist on Win2K server. In that case we will
  1064. // use RpcWinStationGetAllProcesses.
  1065. // Try out Whistler interface first.
  1066. RpcTryExcept {
  1067. bGetAllProcessesOk = RpcWinStationGetAllProcesses_NT6(hServer,
  1068. (ULONG *)&dwResult,
  1069. Level,
  1070. pNumberOfProcesses,
  1071. (PTS_ALL_PROCESSES_INFO_NT6 *)ppProcessArray);
  1072. if( !bGetAllProcessesOk )
  1073. {
  1074. dwResult = RtlNtStatusToDosError( dwResult );
  1075. SetLastError(dwResult);
  1076. }
  1077. }
  1078. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1079. dwResult = RpcExceptionCode();
  1080. if (dwResult == RPC_S_PROCNUM_OUT_OF_RANGE) {
  1081. // Whistler interface failed.
  1082. goto TryW2KInterface;
  1083. }
  1084. SetLastError( dwResult );
  1085. DBGPRINT(("RPC Exception %d\n",dwResult));
  1086. bGetAllProcessesOk = FALSE;
  1087. }
  1088. RpcEndExcept
  1089. return( bGetAllProcessesOk );
  1090. TryW2KInterface:
  1091. // Try out Win2K interface now.
  1092. RpcTryExcept {
  1093. bGetAllProcessesOk = RpcWinStationGetAllProcesses(hServer,
  1094. (ULONG *)&dwResult,
  1095. Level,
  1096. pNumberOfProcesses,
  1097. (PTS_ALL_PROCESSES_INFO *)ppProcessArray);
  1098. if( !bGetAllProcessesOk )
  1099. {
  1100. dwResult = RtlNtStatusToDosError( dwResult );
  1101. SetLastError(dwResult);
  1102. }
  1103. }
  1104. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1105. dwResult = RpcExceptionCode();
  1106. SetLastError( dwResult );
  1107. DBGPRINT(("RPC Exception %d\n",dwResult));
  1108. bGetAllProcessesOk = FALSE;
  1109. }
  1110. RpcEndExcept
  1111. return( bGetAllProcessesOk );
  1112. }
  1113. /*******************************************************************************
  1114. * WinStationGetProcessSid()
  1115. * username for the requested process
  1116. * For identifying correct process processid and start
  1117. * time are required
  1118. *
  1119. * hServer - input, Handle of the server to find info about,
  1120. * if NULL use local.
  1121. * ProcessId - input, ProcessID
  1122. * ProcessStartTime- input, Process start time, (identifies unique process
  1123. * together with ProcessID)
  1124. * pProcessUserSid - output, process user sid
  1125. * dwSidSize - input, memory allocated for pProcessUserSid
  1126. *
  1127. * returns TURE if succeeded, FALSE if failed. in case of failure
  1128. * GetLastError() will gives more infromation about failure.
  1129. *
  1130. ******************************************************************************/
  1131. BOOLEAN WINAPI
  1132. WinStationGetProcessSid(
  1133. HANDLE hServer,
  1134. DWORD ProcessId,
  1135. FILETIME ProcessStartTime,
  1136. PBYTE pProcessUserSid,
  1137. DWORD *pdwSidSize
  1138. )
  1139. {
  1140. BOOLEAN rc;
  1141. LARGE_INTEGER CreateTime;
  1142. DWORD Result;
  1143. NTSTATUS Status;
  1144. HANDLE_CURRENT_BINDING( hServer );
  1145. CreateTime.LowPart = ProcessStartTime.dwLowDateTime;
  1146. CreateTime.HighPart = ProcessStartTime.dwHighDateTime;
  1147. RpcTryExcept
  1148. {
  1149. rc = RpcWinStationGetProcessSid(
  1150. hServer,
  1151. ProcessId,
  1152. CreateTime,
  1153. &Status,
  1154. pProcessUserSid,
  1155. *pdwSidSize,
  1156. pdwSidSize
  1157. );
  1158. if( !rc )
  1159. {
  1160. Result = RtlNtStatusToDosError( Status );
  1161. SetLastError(Result);
  1162. }
  1163. }
  1164. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  1165. {
  1166. Result = RpcExceptionCode();
  1167. SetLastError(Result);
  1168. DBGPRINT(("RPC Exception %d\n",Result));
  1169. rc = FALSE;
  1170. }
  1171. RpcEndExcept
  1172. return( rc );
  1173. }
  1174. /*******************************************************************************
  1175. *
  1176. * WinStationGetLanAdapterNameW (UNICODE)
  1177. *
  1178. * Returns a Network Adapter name
  1179. *
  1180. * ENTRY:
  1181. *
  1182. * EXIT:
  1183. * TRUE - The Query succeeded, and the buffer contains the
  1184. * requested data.
  1185. * FALSE - The operation failed. Extended error status is available using
  1186. * GetLastError.
  1187. *
  1188. ******************************************************************************/
  1189. BOOLEAN WINAPI
  1190. WinStationGetLanAdapterNameW(
  1191. HANDLE hServer,
  1192. ULONG LanAdapter,
  1193. ULONG pdNameLength,
  1194. PWCHAR pPdName,
  1195. ULONG *pLength,
  1196. PWCHAR *ppLanAdapter
  1197. )
  1198. {
  1199. BOOLEAN bGetLanAdapter = FALSE;
  1200. DWORD dwResult;
  1201. HANDLE_CURRENT_BINDING( hServer );
  1202. RpcTryExcept
  1203. {
  1204. bGetLanAdapter = RpcWinStationGetLanAdapterName(hServer,
  1205. &dwResult,
  1206. pdNameLength,
  1207. pPdName,
  1208. LanAdapter,
  1209. pLength,
  1210. ppLanAdapter
  1211. );
  1212. if( !bGetLanAdapter )
  1213. {
  1214. dwResult = RtlNtStatusToDosError( dwResult );
  1215. SetLastError(dwResult);
  1216. }
  1217. }
  1218. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  1219. {
  1220. dwResult = RpcExceptionCode();
  1221. SetLastError( dwResult );
  1222. DBGPRINT(("RPC Exception %d\n",dwResult));
  1223. bGetLanAdapter = FALSE;
  1224. }
  1225. RpcEndExcept
  1226. return( bGetLanAdapter );
  1227. }
  1228. /*******************************************************************************
  1229. *
  1230. * WinStationGetLanAdapterNameA
  1231. *
  1232. * Returns a Network Adapter name - Ansi equivalent for WinStationGetLanAdapterNameW
  1233. *
  1234. * ENTRY:
  1235. *
  1236. * EXIT:
  1237. * TRUE - The Query succeeded, and the buffer contains the
  1238. * requested data.
  1239. * FALSE - The operation failed. Extended error status is available using
  1240. * GetLastError.
  1241. *
  1242. ******************************************************************************/
  1243. BOOLEAN WINAPI
  1244. WinStationGetLanAdapterNameA(
  1245. HANDLE hServer,
  1246. ULONG LanAdapter,
  1247. ULONG pdNameLength,
  1248. PCHAR pPdName,
  1249. ULONG *pLength,
  1250. PCHAR *ppLanAdapter
  1251. )
  1252. {
  1253. BOOLEAN bGetLanAdapter = FALSE;
  1254. PWCHAR pPdNameW = NULL;
  1255. PWCHAR pLanAdapterW = NULL;
  1256. ULONG Size = 0;
  1257. *ppLanAdapter = NULL;
  1258. *pLength = 0;
  1259. pPdNameW = LocalAlloc(0,pdNameLength * sizeof(WCHAR));
  1260. if (NULL == pPdNameW)
  1261. {
  1262. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1263. return(FALSE);
  1264. }
  1265. AnsiToUnicode(pPdNameW, pdNameLength * sizeof(WCHAR), pPdName );
  1266. bGetLanAdapter = WinStationGetLanAdapterNameW(hServer,LanAdapter,pdNameLength * sizeof(WCHAR),pPdNameW,&Size,&pLanAdapterW);
  1267. if(bGetLanAdapter )
  1268. {
  1269. *ppLanAdapter = LocalAlloc(0,lstrlen(pLanAdapterW) + 1);
  1270. if(NULL == *ppLanAdapter)
  1271. {
  1272. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1273. bGetLanAdapter = FALSE;
  1274. }
  1275. else
  1276. {
  1277. UnicodeToAnsi(*ppLanAdapter,lstrlen(pLanAdapterW) + 1,pLanAdapterW);
  1278. *pLength = lstrlen(pLanAdapterW) + 1;
  1279. }
  1280. WinStationFreeMemory(pLanAdapterW);
  1281. }
  1282. LocalFree(pPdNameW);
  1283. return( bGetLanAdapter );
  1284. }
  1285. /*******************************************************************************
  1286. *
  1287. * WinStationEnumerateProcesses (UNICODE)
  1288. *
  1289. * Returns a buffer containing SYSTEM_PROCESS_INFORMATION structures
  1290. * for each process on the specified server.
  1291. *
  1292. * IMPORTANT: This API can ONLY be used to access TS 4.0 servers.
  1293. * The process structure has changed in Windows 2000 !
  1294. *
  1295. * ENTRY:
  1296. * ppProcessBuffer (output)
  1297. * Points to a variable that will be set to the beginning of the
  1298. * process buffer on success. The buffer is allocated within this
  1299. * API and is disposed of using WinStationFreeMemory.
  1300. *
  1301. * EXIT:
  1302. * TRUE - The enumeration succeeded, and the buffer contains the
  1303. * requested data.
  1304. * FALSE - The operation failed. Extended error status is available using
  1305. * GetLastError.
  1306. *
  1307. ******************************************************************************/
  1308. BOOLEAN WINAPI
  1309. WinStationEnumerateProcesses(
  1310. HANDLE hServer,
  1311. PVOID *ppProcessBuffer
  1312. )
  1313. {
  1314. DWORD Result;
  1315. BOOLEAN rc;
  1316. PBYTE pBuffer;
  1317. ULONG ByteCount;
  1318. // From pstat.c
  1319. #define BUFFER_SIZE 32*1024
  1320. HANDLE_CURRENT_BINDING( hServer );
  1321. RpcTryExcept {
  1322. ByteCount = BUFFER_SIZE;
  1323. *ppProcessBuffer = NULL;
  1324. for(;;) {
  1325. if ( (pBuffer = LocalAlloc( 0, ByteCount )) == NULL ) {
  1326. Result = (DWORD)STATUS_NO_MEMORY;
  1327. rc = FALSE;
  1328. break;
  1329. }
  1330. //#ifdef notdef
  1331. /*
  1332. * get process info from server
  1333. */
  1334. rc = RpcWinStationEnumerateProcesses(
  1335. hServer,
  1336. &Result,
  1337. pBuffer,
  1338. ByteCount
  1339. );
  1340. //#else
  1341. #ifdef notdef
  1342. Result = NtQuerySystemInformation( SystemProcessInformation,
  1343. (PVOID)pBuffer,
  1344. ByteCount,
  1345. NULL );
  1346. rc = (Result == STATUS_SUCCESS) ? TRUE : FALSE;
  1347. #endif
  1348. if ( rc || (Result != STATUS_INFO_LENGTH_MISMATCH) )
  1349. break;
  1350. LocalFree( pBuffer );
  1351. ByteCount *= 2;
  1352. }
  1353. if( !rc ) {
  1354. Result = RtlNtStatusToDosError( Result );
  1355. SetLastError(Result);
  1356. LocalFree( pBuffer );
  1357. *ppProcessBuffer = NULL;
  1358. } else {
  1359. //#ifdef notdef
  1360. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  1361. PCITRIX_PROCESS_INFORMATION CitrixInfo;
  1362. ULONG TotalOffset;
  1363. /*
  1364. * Walk the returned buffer (it's in SYSTEM_PROCESS_INFORMATION
  1365. * format) and fixup the addresses (now containing
  1366. * offsets) to pointers in our address space within pBuffer.
  1367. */
  1368. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)pBuffer;
  1369. TotalOffset = 0;
  1370. for(;;) {
  1371. /*
  1372. * Fixup image name buffer address
  1373. */
  1374. if ( ProcessInfo->ImageName.Buffer )
  1375. ProcessInfo->ImageName.Buffer =
  1376. (PWSTR)&pBuffer[(ULONG_PTR)(ProcessInfo->ImageName.Buffer)];
  1377. /*
  1378. * Fixup ProcessSid address
  1379. */
  1380. //
  1381. // Note: this is necessary because we may access to a Hydra 4 server
  1382. // the MagicNumber should prevent us from doing wrong.
  1383. //
  1384. CitrixInfo = (PCITRIX_PROCESS_INFORMATION)
  1385. (((PUCHAR)ProcessInfo) +
  1386. SIZEOF_TS4_SYSTEM_PROCESS_INFORMATION +
  1387. (SIZEOF_TS4_SYSTEM_THREAD_INFORMATION * (int)ProcessInfo->NumberOfThreads));
  1388. if( (CitrixInfo->MagicNumber == CITRIX_PROCESS_INFO_MAGIC) &&
  1389. (CitrixInfo->ProcessSid) ) {
  1390. CitrixInfo->ProcessSid =
  1391. (PVOID)&pBuffer[(ULONG_PTR)(CitrixInfo->ProcessSid)];
  1392. }
  1393. if( ProcessInfo->NextEntryOffset == 0 )
  1394. break;
  1395. else
  1396. TotalOffset += ProcessInfo->NextEntryOffset;
  1397. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&pBuffer[TotalOffset];
  1398. }
  1399. //#endif
  1400. *ppProcessBuffer = (PVOID)pBuffer;
  1401. }
  1402. }
  1403. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1404. Result = RpcExceptionCode();
  1405. SetLastError( Result );
  1406. DBGPRINT(("RPC Exception %d\n",Result));
  1407. rc = FALSE;
  1408. }
  1409. RpcEndExcept
  1410. return( rc );
  1411. }
  1412. /*******************************************************************************
  1413. *
  1414. * WinStationRenameA (ANSI stub)
  1415. *
  1416. * Renames a window station object in the session manager.
  1417. * (see WinStationRenameW)
  1418. *
  1419. * ENTRY:
  1420. *
  1421. * see WinStationRenameW
  1422. *
  1423. * EXIT:
  1424. *
  1425. * see WinStationRenameW
  1426. *
  1427. ******************************************************************************/
  1428. BOOLEAN
  1429. WinStationRenameA(
  1430. HANDLE hServer,
  1431. PWINSTATIONNAMEA pWinStationNameOld,
  1432. PWINSTATIONNAMEA pWinStationNameNew
  1433. )
  1434. {
  1435. WINSTATIONNAMEW WinStationNameOldW;
  1436. WINSTATIONNAMEW WinStationNameNewW;
  1437. /*
  1438. * Convert ANSI WinStationNames to UNICODE.
  1439. */
  1440. AnsiToUnicode( WinStationNameOldW, sizeof(WINSTATIONNAMEW), pWinStationNameOld );
  1441. AnsiToUnicode( WinStationNameNewW, sizeof(WINSTATIONNAMEW), pWinStationNameNew );
  1442. /*
  1443. * Call WinStationRenameW & return it's status.
  1444. */
  1445. return ( WinStationRenameW( hServer, WinStationNameOldW, WinStationNameNewW ) );
  1446. }
  1447. /*******************************************************************************
  1448. *
  1449. * WinStationRenameW (UNICODE)
  1450. *
  1451. * Renames a window station object in the session manager.
  1452. *
  1453. * ENTRY:
  1454. *
  1455. * pWinStationNameOld (input)
  1456. * Old name of window station.
  1457. *
  1458. * pWinStationNameNew (input)
  1459. * New name of window station.
  1460. *
  1461. *
  1462. * EXIT:
  1463. *
  1464. * TRUE -- The rename operation succeeded.
  1465. *
  1466. * FALSE -- The operation failed. Extended error status is available
  1467. * using GetLastError.
  1468. *
  1469. ******************************************************************************/
  1470. BOOLEAN
  1471. WinStationRenameW(
  1472. HANDLE hServer,
  1473. PWINSTATIONNAMEW pWinStationNameOld,
  1474. PWINSTATIONNAMEW pWinStationNameNew
  1475. )
  1476. {
  1477. DWORD Result;
  1478. BOOLEAN rc;
  1479. WCHAR* rpcBufferOld;
  1480. WCHAR* rpcBufferNew;
  1481. HANDLE_CURRENT_BINDING( hServer );
  1482. // Since, due to legacy clients, we cannot change the interface,
  1483. // as a workarround to bug#265954, we double the size of RPC Buffers.
  1484. rpcBufferOld = LocalAlloc(LPTR, sizeof(PWINSTATIONNAMEW) * sizeof(WCHAR));
  1485. if (rpcBufferOld != NULL) {
  1486. CopyMemory(rpcBufferOld, pWinStationNameOld, sizeof(PWINSTATIONNAMEW));
  1487. } else {
  1488. SetLastError(ERROR_OUTOFMEMORY);
  1489. return(FALSE);
  1490. }
  1491. rpcBufferNew = LocalAlloc(LPTR, sizeof(PWINSTATIONNAMEW) * sizeof(WCHAR));
  1492. if (rpcBufferNew != NULL) {
  1493. CopyMemory(rpcBufferNew, pWinStationNameNew, sizeof(PWINSTATIONNAMEW));
  1494. } else {
  1495. LocalFree(rpcBufferOld);
  1496. SetLastError(ERROR_OUTOFMEMORY);
  1497. return(FALSE);
  1498. }
  1499. RpcTryExcept {
  1500. rc = RpcWinStationRename(
  1501. hServer,
  1502. &Result,
  1503. (PWCHAR)rpcBufferOld,
  1504. sizeof(WINSTATIONNAMEW),
  1505. (PWCHAR)rpcBufferNew,
  1506. sizeof(WINSTATIONNAMEW)
  1507. );
  1508. Result = RtlNtStatusToDosError( Result );
  1509. }
  1510. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1511. Result = RpcExceptionCode();
  1512. DBGPRINT(("RPC Exception %d\n",Result));
  1513. rc = FALSE;
  1514. }
  1515. RpcEndExcept
  1516. LocalFree(rpcBufferOld);
  1517. LocalFree(rpcBufferNew);
  1518. if( !rc ) SetLastError(Result);
  1519. return( rc );
  1520. }
  1521. /*******************************************************************************
  1522. *
  1523. * WinStationQueryInformationA (ANSI stub)
  1524. *
  1525. * Queries configuration information about a window station object.
  1526. *
  1527. * ENTRY:
  1528. *
  1529. * see WinStationQueryInformationW
  1530. *
  1531. * EXIT:
  1532. *
  1533. * see WinStationQueryInformationW
  1534. *
  1535. ******************************************************************************/
  1536. BOOLEAN
  1537. WinStationQueryInformationA(
  1538. HANDLE hServer,
  1539. ULONG LogonId,
  1540. WINSTATIONINFOCLASS WinStationInformationClass,
  1541. PVOID pWinStationInformation,
  1542. ULONG WinStationInformationLength,
  1543. PULONG pReturnLength
  1544. )
  1545. {
  1546. PVOID pInfo;
  1547. ULONG InfoLength, ValidInputLength;
  1548. struct {
  1549. union {
  1550. WINSTATIONCREATEW CreateData;
  1551. WINSTATIONCONFIGW Configuration;
  1552. PDPARAMSW PdParams;
  1553. WDCONFIGW Wd;
  1554. PDCONFIGW Pd;
  1555. WINSTATIONPRINTERW Printer;
  1556. WINSTATIONINFORMATIONW Information;
  1557. WINSTATIONCLIENTW Client;
  1558. WINSTATIONPRODIDW DigProdId;
  1559. };
  1560. } Info;
  1561. /*
  1562. * Validate the caller supplied buffer length and set up for
  1563. * call to WinStationQueryInformationW.
  1564. */
  1565. switch ( WinStationInformationClass ) {
  1566. case WinStationCreateData:
  1567. pInfo = &Info.CreateData;
  1568. InfoLength = sizeof(Info.CreateData);
  1569. ValidInputLength = sizeof(WINSTATIONCREATEA);
  1570. break;
  1571. case WinStationConfiguration:
  1572. pInfo = &Info.Configuration;
  1573. InfoLength = sizeof(Info.Configuration);
  1574. ValidInputLength = sizeof(WINSTATIONCONFIGA);
  1575. break;
  1576. case WinStationPdParams:
  1577. pInfo = &Info.PdParams;
  1578. ((PPDPARAMSW)pInfo)->SdClass = ((PPDPARAMSA)pWinStationInformation)->SdClass;
  1579. InfoLength = sizeof(Info.PdParams);
  1580. ValidInputLength = sizeof(PDPARAMSA);
  1581. break;
  1582. case WinStationWd:
  1583. pInfo = &Info.Wd;
  1584. InfoLength = sizeof(Info.Wd);
  1585. ValidInputLength = sizeof(WDCONFIGA);
  1586. break;
  1587. case WinStationPd:
  1588. pInfo = &Info.Pd;
  1589. InfoLength = sizeof(Info.Pd);
  1590. ValidInputLength = sizeof(PDCONFIGA);
  1591. break;
  1592. case WinStationPrinter:
  1593. pInfo = &Info.Printer;
  1594. InfoLength = sizeof(Info.Printer);
  1595. ValidInputLength = sizeof(WINSTATIONPRINTERA);
  1596. break;
  1597. case WinStationInformation:
  1598. pInfo = &Info.Information;
  1599. InfoLength = sizeof(Info.Information);
  1600. ValidInputLength = sizeof(WINSTATIONINFORMATIONA);
  1601. break;
  1602. case WinStationClient:
  1603. pInfo = &Info.Client;
  1604. InfoLength = sizeof(Info.Client);
  1605. ValidInputLength = sizeof(WINSTATIONCLIENTA);
  1606. break;
  1607. case WinStationDigProductId:
  1608. pInfo = &Info.DigProdId;
  1609. InfoLength = sizeof(Info.DigProdId);
  1610. ValidInputLength = sizeof(WINSTATIONPRODIDA);
  1611. break;
  1612. /*
  1613. * The other WINSTATIONINFOCLASSes don't need converting.
  1614. */
  1615. default:
  1616. pInfo = pWinStationInformation;
  1617. ValidInputLength = InfoLength = WinStationInformationLength;
  1618. break;
  1619. }
  1620. /*
  1621. * If the caller-supplied buffer is not the proper size, set error
  1622. * and return FALSE.
  1623. */
  1624. if ( WinStationInformationLength != ValidInputLength )
  1625. {
  1626. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1627. return(FALSE);
  1628. }
  1629. /*
  1630. * Call the WinStationQueryInformationW function, returning if
  1631. * failure.
  1632. */
  1633. if ( !WinStationQueryInformationW( hServer, LogonId,
  1634. WinStationInformationClass,
  1635. pInfo, InfoLength, pReturnLength ) )
  1636. return(FALSE);
  1637. /*
  1638. * Convert the returned UNICODE information to ANSI, if needed.
  1639. */
  1640. switch ( WinStationInformationClass ) {
  1641. case WinStationCreateData:
  1642. WinStationCreateU2A( (PWINSTATIONCREATEA)pWinStationInformation,
  1643. (PWINSTATIONCREATEW)pInfo );
  1644. *pReturnLength = ValidInputLength;
  1645. break;
  1646. case WinStationConfiguration:
  1647. WinStationConfigU2A( (PWINSTATIONCONFIGA)pWinStationInformation,
  1648. (PWINSTATIONCONFIGW)pInfo );
  1649. *pReturnLength = ValidInputLength;
  1650. break;
  1651. case WinStationPdParams:
  1652. PdParamsU2A( (PPDPARAMSA)pWinStationInformation,
  1653. (PPDPARAMSW)pInfo );
  1654. *pReturnLength = ValidInputLength;
  1655. break;
  1656. case WinStationWd:
  1657. WdConfigU2A( (PWDCONFIGA)pWinStationInformation,
  1658. (PWDCONFIGW)pInfo );
  1659. *pReturnLength = ValidInputLength;
  1660. break;
  1661. case WinStationPd:
  1662. PdConfig2U2A( &((PPDCONFIGA)pWinStationInformation)->Create,
  1663. &((PPDCONFIGW)pInfo)->Create );
  1664. PdParamsU2A( &((PPDCONFIGA)pWinStationInformation)->Params,
  1665. &((PPDCONFIGW)pInfo)->Params );
  1666. *pReturnLength = ValidInputLength;
  1667. break;
  1668. case WinStationPrinter:
  1669. WinStationPrinterU2A( (PWINSTATIONPRINTERA)pWinStationInformation,
  1670. (PWINSTATIONPRINTERW)pInfo );
  1671. *pReturnLength = ValidInputLength;
  1672. break;
  1673. case WinStationInformation:
  1674. WinStationInformationU2A( (PWINSTATIONINFORMATIONA)pWinStationInformation,
  1675. (PWINSTATIONINFORMATIONW)pInfo );
  1676. *pReturnLength = ValidInputLength;
  1677. break;
  1678. case WinStationClient:
  1679. WinStationClientU2A( (PWINSTATIONCLIENTA)pWinStationInformation,
  1680. (PWINSTATIONCLIENTW)pInfo );
  1681. *pReturnLength = ValidInputLength;
  1682. break;
  1683. case WinStationDigProductId:
  1684. WinStationProductIdU2A( (PWINSTATIONPRODIDA)pWinStationInformation,
  1685. (PWINSTATIONPRODIDW)pInfo );
  1686. *pReturnLength = ValidInputLength;
  1687. break;
  1688. default:
  1689. break;
  1690. }
  1691. return(TRUE);
  1692. }
  1693. /*******************************************************************************
  1694. *
  1695. * WinStationQueryInformationW (UNICODE)
  1696. *
  1697. * Queries configuration information about a window station object.
  1698. *
  1699. * ENTRY:
  1700. *
  1701. * WinStationHandle (input)
  1702. * Identifies the window station object. The handle must have
  1703. * WINSTATION_QUERY access.
  1704. *
  1705. * WinStationInformationClass (input)
  1706. * Specifies the type of information to retrieve from the specified
  1707. * window station object.
  1708. *
  1709. * pWinStationInformation (output)
  1710. * A pointer to a buffer that will receive information about the
  1711. * specified window station. The format and contents of the buffer
  1712. * depend on the specified information class being queried.
  1713. *
  1714. * WinStationInformationLength (input)
  1715. * Specifies the length in bytes of the window station information
  1716. * buffer.
  1717. *
  1718. * pReturnLength (output)
  1719. * An optional parameter that if specified, receives the number of
  1720. * bytes placed in the window station information buffer.
  1721. *
  1722. * EXIT:
  1723. *
  1724. * TRUE -- The query succeeded, and the buffer contains the requested data.
  1725. *
  1726. * FALSE -- The operation failed. Extended error status is available
  1727. * using GetLastError.
  1728. *
  1729. ******************************************************************************/
  1730. BOOLEAN
  1731. WinStationQueryInformationW(
  1732. HANDLE hServer,
  1733. ULONG LogonId,
  1734. WINSTATIONINFOCLASS WinStationInformationClass,
  1735. PVOID pWinStationInformation,
  1736. ULONG WinStationInformationLength,
  1737. PULONG pReturnLength
  1738. )
  1739. {
  1740. DWORD Result;
  1741. BOOLEAN rc;
  1742. PCHAR RpcBuf;
  1743. ULONG RpcBufLen;
  1744. PVOID WireBuf;
  1745. PVOID AllocatedBuff = NULL;
  1746. ULONG WireBufLen;
  1747. BOOLEAN WireBufAllocated;
  1748. ULONG Status;
  1749. static UINT AlreadyWaitedForTermsrv = 0; // a flag which helps to determine if we already waited for TermSrv to be up
  1750. if ((Status = CheckUserBuffer(WinStationInformationClass,
  1751. pWinStationInformation,
  1752. WinStationInformationLength,
  1753. &WireBuf,
  1754. &WireBufLen,
  1755. &WireBufAllocated)) != ERROR_SUCCESS) {
  1756. SetLastError(Status);
  1757. return(FALSE);
  1758. }
  1759. if (WireBufAllocated) {
  1760. AllocatedBuff = WireBuf;
  1761. RpcBuf = (PCHAR) WireBuf;
  1762. RpcBufLen = WireBufLen;
  1763. CopyInWireBuf(WinStationInformationClass,
  1764. pWinStationInformation,
  1765. WireBuf);
  1766. } else {
  1767. RpcBuf = (PCHAR) pWinStationInformation;
  1768. RpcBufLen = WinStationInformationLength;
  1769. }
  1770. HANDLE_CURRENT_BINDING_BUFFER( hServer, AllocatedBuff );
  1771. // First wait for termsrv to get started if User Token is queried
  1772. // This is for Session 0 only where termsrv is started after 60 seconds on Per and Pro
  1773. // Need to do this only for the first time - AlreadyWaitedForTermsrv flag helps to determine this
  1774. if ( (LogonId == 0) && (WinStationInformationClass == WinStationUserToken) && (AlreadyWaitedForTermsrv == 0) ) {
  1775. HANDLE ReadyEventHandle ;
  1776. ReadyEventHandle = CreateEvent(NULL, TRUE, FALSE, TEXT("Global\\TermSrvReadyEvent"));
  1777. if (ReadyEventHandle != NULL) {
  1778. DWORD dwTimeOut = 1000*60*3; // 3 minutes
  1779. AlreadyWaitedForTermsrv++;
  1780. // wait until termsrv is actually ready.
  1781. WaitForSingleObject(ReadyEventHandle, dwTimeOut);
  1782. CloseHandle(ReadyEventHandle);
  1783. }
  1784. }
  1785. RpcTryExcept {
  1786. rc = RpcWinStationQueryInformation(
  1787. hServer,
  1788. &Result,
  1789. (LogonId == LOGONID_CURRENT) ? NtCurrentPeb()->SessionId : LogonId,
  1790. (DWORD)WinStationInformationClass,
  1791. RpcBuf,
  1792. RpcBufLen,
  1793. pReturnLength
  1794. );
  1795. Result = RtlNtStatusToDosError( Result );
  1796. if( !rc ) SetLastError(Result);
  1797. }
  1798. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1799. Result = RpcExceptionCode();
  1800. SetLastError( Result );
  1801. DBGPRINT(("RPC Exception %d\n",Result));
  1802. rc = FALSE;
  1803. }
  1804. RpcEndExcept
  1805. if (WireBufAllocated) {
  1806. if (rc) {
  1807. CopyOutWireBuf(WinStationInformationClass,
  1808. pWinStationInformation,
  1809. WireBuf);
  1810. *pReturnLength = WinStationInformationLength;
  1811. }
  1812. LocalFree(WireBuf);
  1813. }
  1814. return( rc );
  1815. }
  1816. /*******************************************************************************
  1817. *
  1818. * WinStationSetInformationA (ANSI stub)
  1819. *
  1820. * Sets configuration information for a window station object.
  1821. *
  1822. * ENTRY:
  1823. *
  1824. * see WinStationSetInformationW
  1825. *
  1826. * EXIT:
  1827. *
  1828. * see WinStationSetInformationW
  1829. *
  1830. ******************************************************************************/
  1831. BOOLEAN
  1832. WinStationSetInformationA(
  1833. HANDLE hServer,
  1834. ULONG LogonId,
  1835. WINSTATIONINFOCLASS WinStationInformationClass,
  1836. PVOID pWinStationInformation,
  1837. ULONG WinStationInformationLength
  1838. )
  1839. {
  1840. PVOID pInfo;
  1841. ULONG InfoLength;
  1842. struct {
  1843. union {
  1844. WINSTATIONCREATEW CreateData;
  1845. WINSTATIONCONFIGW Configuration;
  1846. PDPARAMSW PdParams;
  1847. WDCONFIGW Wd;
  1848. PDCONFIGW Pd;
  1849. WINSTATIONPRINTERW Printer;
  1850. WINSTATIONINFORMATIONW Information;
  1851. };
  1852. } Info;
  1853. /*
  1854. * Validate the caller supplied buffer length and convert to the
  1855. * appropriate UNICODE buffer for call to WinStationSetInformationW.
  1856. */
  1857. switch ( WinStationInformationClass ) {
  1858. case WinStationCreateData:
  1859. pInfo = &Info.CreateData;
  1860. InfoLength = sizeof(Info.CreateData);
  1861. if ( WinStationInformationLength != sizeof(WINSTATIONCREATEA) )
  1862. goto BadBufferLength;
  1863. WinStationCreateA2U( (PWINSTATIONCREATEW)pInfo,
  1864. (PWINSTATIONCREATEA)pWinStationInformation );
  1865. break;
  1866. case WinStationConfiguration:
  1867. pInfo = &Info.Configuration;
  1868. InfoLength = sizeof(Info.Configuration);
  1869. if ( WinStationInformationLength != sizeof(WINSTATIONCONFIGA) )
  1870. goto BadBufferLength;
  1871. WinStationConfigA2U( (PWINSTATIONCONFIGW)pInfo,
  1872. (PWINSTATIONCONFIGA)pWinStationInformation );
  1873. break;
  1874. case WinStationPdParams:
  1875. pInfo = &Info.PdParams;
  1876. InfoLength = sizeof(Info.PdParams);
  1877. if ( WinStationInformationLength != sizeof(PDPARAMSA) )
  1878. goto BadBufferLength;
  1879. PdParamsA2U( (PPDPARAMSW)pInfo,
  1880. (PPDPARAMSA)pWinStationInformation );
  1881. break;
  1882. case WinStationWd:
  1883. pInfo = &Info.Wd;
  1884. InfoLength = sizeof(Info.Wd);
  1885. if ( WinStationInformationLength != sizeof(WDCONFIGA) )
  1886. goto BadBufferLength;
  1887. WdConfigA2U( (PWDCONFIGW)pInfo,
  1888. (PWDCONFIGA)pWinStationInformation );
  1889. break;
  1890. case WinStationPd:
  1891. pInfo = &Info.Pd;
  1892. InfoLength = sizeof(Info.Pd);
  1893. if ( WinStationInformationLength != sizeof(PDCONFIGA) )
  1894. goto BadBufferLength;
  1895. PdConfig2A2U( &((PPDCONFIGW)pInfo)->Create,
  1896. &((PPDCONFIGA)pWinStationInformation)->Create );
  1897. PdParamsA2U( &((PPDCONFIGW)pInfo)->Params,
  1898. &((PPDCONFIGA)pWinStationInformation)->Params );
  1899. break;
  1900. case WinStationPrinter:
  1901. pInfo = &Info.Printer;
  1902. InfoLength = sizeof(Info.Printer);
  1903. if ( WinStationInformationLength != sizeof(WINSTATIONPRINTERA) )
  1904. goto BadBufferLength;
  1905. WinStationPrinterA2U( (PWINSTATIONPRINTERW)pInfo,
  1906. (PWINSTATIONPRINTERA)pWinStationInformation );
  1907. break;
  1908. case WinStationInformation:
  1909. pInfo = &Info.Information;
  1910. InfoLength = sizeof(Info.Information);
  1911. if ( WinStationInformationLength != sizeof(WINSTATIONINFORMATIONA) )
  1912. goto BadBufferLength;
  1913. WinStationInformationA2U( (PWINSTATIONINFORMATIONW)pInfo,
  1914. (PWINSTATIONINFORMATIONA)pWinStationInformation );
  1915. break;
  1916. /*
  1917. * The other WINSTATIONINFOCLASSes don't need converting.
  1918. */
  1919. default:
  1920. pInfo = pWinStationInformation;
  1921. InfoLength = WinStationInformationLength;
  1922. break;
  1923. }
  1924. /*
  1925. * Call the WinStationSetInformationW function and return it's
  1926. * status.
  1927. */
  1928. return ( WinStationSetInformationW( hServer, LogonId,
  1929. WinStationInformationClass,
  1930. pInfo, InfoLength ) );
  1931. /*--------------------------------------
  1932. * Error clean-up and return...
  1933. */
  1934. BadBufferLength:
  1935. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1936. return(FALSE);
  1937. }
  1938. /*******************************************************************************
  1939. *
  1940. * WinStationSetInformationW (UNICODE)
  1941. *
  1942. * Sets configuration information for a window station object.
  1943. *
  1944. * ENTRY:
  1945. *
  1946. * WinStationHandle (input)
  1947. * Identifies the window station object. The handle must have
  1948. * WINSTATION_SET access.
  1949. *
  1950. * WinStationInformationClass (input)
  1951. * Specifies the type of information to retrieve from the specified
  1952. * window station object.
  1953. *
  1954. * pWinStationInformation (input)
  1955. * A pointer to a buffer that contains information to set for the
  1956. * specified window station. The format and contents of the buffer
  1957. * depend on the specified information class being set.
  1958. *
  1959. * WinStationInformationLength (input)
  1960. * Specifies the length in bytes of the window station information
  1961. * buffer.
  1962. *
  1963. * EXIT:
  1964. *
  1965. * TRUE -- The set operation succeeded.
  1966. *
  1967. * FALSE -- The operation failed. Extended error status is available
  1968. * using GetLastError.
  1969. *
  1970. ******************************************************************************/
  1971. BOOLEAN
  1972. WinStationSetInformationW(
  1973. HANDLE hServer,
  1974. ULONG LogonId,
  1975. WINSTATIONINFOCLASS WinStationInformationClass,
  1976. PVOID pWinStationInformation,
  1977. ULONG WinStationInformationLength
  1978. )
  1979. {
  1980. DWORD Result;
  1981. BOOLEAN rc;
  1982. PCHAR RpcBuf;
  1983. ULONG RpcBufLen;
  1984. PVOID WireBuf;
  1985. PVOID AllocatedBuff = NULL;
  1986. ULONG WireBufLen;
  1987. BOOLEAN WireBufAllocated;
  1988. ULONG Status;
  1989. if ((Status = CheckUserBuffer(WinStationInformationClass,
  1990. pWinStationInformation,
  1991. WinStationInformationLength,
  1992. &WireBuf,
  1993. &WireBufLen,
  1994. &WireBufAllocated)) != ERROR_SUCCESS) {
  1995. SetLastError(Status);
  1996. return(FALSE);
  1997. }
  1998. if (WireBufAllocated) {
  1999. AllocatedBuff = WireBuf;
  2000. RpcBuf = (PCHAR) WireBuf;
  2001. RpcBufLen = WireBufLen;
  2002. CopyInWireBuf(WinStationInformationClass,
  2003. pWinStationInformation,
  2004. WireBuf);
  2005. } else {
  2006. RpcBuf = (PCHAR) pWinStationInformation;
  2007. RpcBufLen = WinStationInformationLength;
  2008. }
  2009. HANDLE_CURRENT_BINDING_BUFFER( hServer, AllocatedBuff );
  2010. RpcTryExcept {
  2011. rc = RpcWinStationSetInformation(
  2012. hServer,
  2013. &Result,
  2014. (LogonId == LOGONID_CURRENT) ? NtCurrentPeb()->SessionId : LogonId,
  2015. (DWORD)WinStationInformationClass,
  2016. RpcBuf,
  2017. RpcBufLen
  2018. );
  2019. Result = RtlNtStatusToDosError( Result );
  2020. if( !rc ) SetLastError(Result);
  2021. }
  2022. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2023. Result = RpcExceptionCode();
  2024. SetLastError( Result );
  2025. DBGPRINT(("RPC Exception %d\n",Result));
  2026. rc = FALSE;
  2027. }
  2028. RpcEndExcept
  2029. if (WireBufAllocated) {
  2030. LocalFree(WireBuf);
  2031. }
  2032. return( rc );
  2033. }
  2034. /*******************************************************************************
  2035. *
  2036. * WinStationSendMessageA (ANSI stub)
  2037. *
  2038. * Sends a message to the specified window station object and optionally
  2039. * waits for a reply. The reply is returned to the caller of
  2040. * WinStationSendMessage.
  2041. *
  2042. * ENTRY:
  2043. *
  2044. * see WinStationSendMessageW
  2045. *
  2046. * EXIT:
  2047. *
  2048. * see WinStationSendMessageW, plus
  2049. *
  2050. * ERROR_NOT_ENOUGH_MEMORY - the LocalAlloc failed
  2051. *
  2052. ******************************************************************************/
  2053. BOOLEAN
  2054. WinStationSendMessageA(
  2055. HANDLE hServer,
  2056. ULONG LogonId,
  2057. LPSTR pTitle,
  2058. ULONG TitleLength,
  2059. LPSTR pMessage,
  2060. ULONG MessageLength,
  2061. ULONG Style,
  2062. ULONG Timeout,
  2063. PULONG pResponse,
  2064. BOOLEAN DoNotWait
  2065. )
  2066. {
  2067. BOOLEAN status;
  2068. LPWSTR pTitleW, pMessageW;
  2069. ULONG TitleLengthW, MessageLengthW;
  2070. /*
  2071. * Allocate a buffer for UNICODE version of Title and convert.
  2072. */
  2073. if ( !(pTitleW = LocalAlloc( 0,
  2074. TitleLengthW =
  2075. (TitleLength*sizeof(WCHAR)) )) ) {
  2076. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2077. return(FALSE);
  2078. }
  2079. AnsiToUnicode( pTitleW, TitleLengthW, pTitle );
  2080. /*
  2081. * Allocate a buffer for UNICODE version of Message and convert.
  2082. */
  2083. if ( !(pMessageW = LocalAlloc( 0,
  2084. MessageLengthW =
  2085. (MessageLength*sizeof(WCHAR)) )) ) {
  2086. LocalFree(pTitleW);
  2087. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2088. return(FALSE);
  2089. }
  2090. AnsiToUnicode( pMessageW, MessageLengthW, pMessage );
  2091. /*
  2092. * Call WinStationSendMessageW
  2093. */
  2094. status = WinStationSendMessageW( hServer,
  2095. LogonId,
  2096. pTitleW,
  2097. TitleLengthW,
  2098. pMessageW,
  2099. MessageLengthW,
  2100. Style,
  2101. Timeout,
  2102. pResponse,
  2103. DoNotWait );
  2104. /*
  2105. * Free allocated buffers and return status.
  2106. */
  2107. LocalFree(pTitleW);
  2108. LocalFree(pMessageW);
  2109. return(status);
  2110. }
  2111. /*******************************************************************************
  2112. *
  2113. * WinStationSendMessageW (UNICODE)
  2114. *
  2115. * Sends a message to the specified window station object and optionally
  2116. * waits for a reply. The reply is returned to the caller of
  2117. * WinStationSendMessage.
  2118. *
  2119. * ENTRY:
  2120. *
  2121. * WinStationHandle (input)
  2122. * Specifies the window station object to send a message to.
  2123. *
  2124. * pTitle (input)
  2125. * Pointer to title for message box to display.
  2126. *
  2127. * TitleLength (input)
  2128. * Length of title to display in bytes.
  2129. *
  2130. * pMessage (input)
  2131. * Pointer to message to display.
  2132. *
  2133. * MessageLength (input)
  2134. * Length of message in bytes to display at the specified window station.
  2135. *
  2136. * Style (input)
  2137. * Standard Windows MessageBox() style parameter.
  2138. *
  2139. * Timeout (input)
  2140. * Response timeout in seconds. If message is not responded to in
  2141. * Timeout seconds then a response code of IDTIMEOUT (cwin.h) is
  2142. * returned to signify the message timed out.
  2143. *
  2144. * pResponse (output)
  2145. * Address to return selected response.
  2146. *
  2147. * DoNotWait (input)
  2148. * Do not wait for the response. Causes pResponse to be set to
  2149. * IDASYNC (cwin.h) if no errors queueing the message.
  2150. *
  2151. * EXIT:
  2152. *
  2153. * TRUE -- The send message operation succeeded.
  2154. *
  2155. * FALSE -- The operation failed. Extended error status is available
  2156. * using GetLastError.
  2157. *
  2158. ******************************************************************************/
  2159. BOOLEAN
  2160. WinStationSendMessageW(
  2161. HANDLE hServer,
  2162. ULONG LogonId,
  2163. LPWSTR pTitle,
  2164. ULONG TitleLength,
  2165. LPWSTR pMessage,
  2166. ULONG MessageLength,
  2167. ULONG Style,
  2168. ULONG Timeout,
  2169. PULONG pResponse,
  2170. BOOLEAN DoNotWait
  2171. )
  2172. {
  2173. DWORD Result;
  2174. BOOLEAN rc;
  2175. WCHAR* rpcBuffer1;
  2176. WCHAR* rpcBuffer2;
  2177. HANDLE_CURRENT_BINDING( hServer );
  2178. // Since, due to legacy clients, we cannot change the interface,
  2179. // as a workarround to bug#265954, we double the size of RPC Buffers.
  2180. rpcBuffer1 = LocalAlloc(LPTR, MessageLength * sizeof(WCHAR));
  2181. if (rpcBuffer1 != NULL) {
  2182. CopyMemory(rpcBuffer1, pMessage, MessageLength);
  2183. } else {
  2184. SetLastError(ERROR_OUTOFMEMORY);
  2185. return(FALSE);
  2186. }
  2187. rpcBuffer2 = LocalAlloc(LPTR, TitleLength * sizeof(WCHAR));
  2188. if (rpcBuffer2 != NULL) {
  2189. CopyMemory(rpcBuffer2, pTitle, TitleLength);
  2190. } else {
  2191. LocalFree(rpcBuffer1);
  2192. SetLastError(ERROR_OUTOFMEMORY);
  2193. return(FALSE);
  2194. }
  2195. RpcTryExcept {
  2196. rc = RpcWinStationSendMessage(
  2197. hServer,
  2198. &Result,
  2199. (LogonId == LOGONID_CURRENT) ? NtCurrentPeb()->SessionId : LogonId,
  2200. rpcBuffer2,
  2201. TitleLength,
  2202. rpcBuffer1,
  2203. MessageLength,
  2204. Style,
  2205. Timeout,
  2206. pResponse,
  2207. DoNotWait
  2208. );
  2209. Result = RtlNtStatusToDosError( Result );
  2210. }
  2211. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2212. Result = RpcExceptionCode();
  2213. DBGPRINT(("RPC Exception %d\n",Result));
  2214. rc = FALSE;
  2215. }
  2216. RpcEndExcept
  2217. LocalFree(rpcBuffer1);
  2218. LocalFree(rpcBuffer2);
  2219. if (!rc) {
  2220. SetLastError( Result );
  2221. }
  2222. return( rc );
  2223. }
  2224. /*******************************************************************************
  2225. *
  2226. * LogonIdFromWinStationNameA (ANSI stub)
  2227. *
  2228. * Returns the LogonId for the specified window station name.
  2229. *
  2230. * ENTRY:
  2231. *
  2232. * see LogonIdFromWinStationNameW
  2233. *
  2234. * EXIT:
  2235. *
  2236. * see LogonIdFromWinStationNameW
  2237. *
  2238. ******************************************************************************/
  2239. BOOLEAN
  2240. LogonIdFromWinStationNameA(
  2241. HANDLE hServer,
  2242. PWINSTATIONNAMEA pWinStationName,
  2243. PULONG pLogonId
  2244. )
  2245. {
  2246. WINSTATIONNAMEW WinStationNameW;
  2247. /*
  2248. * Convert ANSI WinStationName to UNICODE.
  2249. */
  2250. AnsiToUnicode( WinStationNameW, sizeof(WINSTATIONNAMEW), pWinStationName );
  2251. /*
  2252. * Call LogonIdFromWinStationNameW & return it's status.
  2253. */
  2254. return ( LogonIdFromWinStationNameW( hServer, WinStationNameW, pLogonId ) );
  2255. }
  2256. /*******************************************************************************
  2257. *
  2258. * LogonIdFromWinStationNameW (UNICODE)
  2259. *
  2260. * Returns the LogonId for the specified window station name.
  2261. *
  2262. * ENTRY:
  2263. *
  2264. * pWinStationName (input)
  2265. * Window station name.
  2266. *
  2267. * pLogonId (output)
  2268. * Pointer to where to place the LogonId if found
  2269. *
  2270. * EXIT:
  2271. *
  2272. * If the function succeeds, the return value is TRUE, otherwise, it is
  2273. * FALSE.
  2274. * To get extended error information, use the GetLastError function.
  2275. *
  2276. ******************************************************************************/
  2277. BOOLEAN
  2278. LogonIdFromWinStationNameW(
  2279. HANDLE hServer,
  2280. PWINSTATIONNAMEW pWinStationName,
  2281. PULONG pLogonId
  2282. )
  2283. {
  2284. DWORD Result;
  2285. BOOLEAN rc;
  2286. WCHAR* rpcBuffer;
  2287. HANDLE_CURRENT_BINDING( hServer );
  2288. /*
  2289. * rpcBuffer is a workaround for bug 229753. The bug can't be fixed
  2290. * completely without breaking TS4 clients.
  2291. */
  2292. rpcBuffer = LocalAlloc(LPTR, sizeof(WINSTATIONNAMEW) * sizeof(WCHAR));
  2293. if (rpcBuffer != NULL) {
  2294. CopyMemory(rpcBuffer, pWinStationName, sizeof(WINSTATIONNAMEW));
  2295. } else {
  2296. SetLastError(ERROR_OUTOFMEMORY);
  2297. return(FALSE);
  2298. }
  2299. RpcTryExcept {
  2300. rc = RpcLogonIdFromWinStationName(
  2301. hServer,
  2302. &Result,
  2303. rpcBuffer,
  2304. sizeof(WINSTATIONNAMEW),
  2305. pLogonId
  2306. );
  2307. Result = RtlNtStatusToDosError( Result );
  2308. }
  2309. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2310. Result = RpcExceptionCode();
  2311. DBGPRINT(("RPC Exception %d\n",Result));
  2312. rc = FALSE;
  2313. }
  2314. RpcEndExcept
  2315. if (rpcBuffer != NULL) {
  2316. LocalFree(rpcBuffer);
  2317. }
  2318. if( !rc ) SetLastError(Result);
  2319. return( rc );
  2320. }
  2321. /*******************************************************************************
  2322. *
  2323. * WinStationNameFromLogonIdA (ANSI stub)
  2324. *
  2325. * Returns the WinStation name for the specified LogonId.
  2326. *
  2327. * ENTRY:
  2328. *
  2329. * see WinStationNameFromLogonIdW
  2330. *
  2331. * EXIT:
  2332. *
  2333. * see WinStationNameFromLogonIdW
  2334. *
  2335. ******************************************************************************/
  2336. BOOLEAN
  2337. WinStationNameFromLogonIdA(
  2338. HANDLE hServer,
  2339. ULONG LogonId,
  2340. PWINSTATIONNAMEA pWinStationName
  2341. )
  2342. {
  2343. BOOLEAN Result;
  2344. WINSTATIONNAMEW WinStationNameW;
  2345. /*
  2346. * Call WinStationNameFromLogonIdW
  2347. */
  2348. Result = WinStationNameFromLogonIdW( hServer, LogonId, WinStationNameW );
  2349. /*
  2350. * if successful, convert UNICODE WinStationName to ANSI.
  2351. */
  2352. if ( Result ) {
  2353. UnicodeToAnsi( pWinStationName, sizeof(WINSTATIONNAMEA), WinStationNameW );
  2354. }
  2355. return( Result );
  2356. }
  2357. /*******************************************************************************
  2358. *
  2359. * WinStationNameFromLogonIdW (UNICODE)
  2360. *
  2361. * Returns the WinStation name for the specified LogonId.
  2362. *
  2363. * ENTRY:
  2364. *
  2365. * LogonId (input)
  2366. * LogonId to query
  2367. *
  2368. * pWinStationName (output)
  2369. * Location to return WinStation name
  2370. *
  2371. * EXIT:
  2372. *
  2373. * If the function succeeds, the return value is TRUE, otherwise, it is
  2374. * FALSE.
  2375. * To get extended error information, use the GetLastError function.
  2376. *
  2377. ******************************************************************************/
  2378. BOOLEAN
  2379. WinStationNameFromLogonIdW(
  2380. HANDLE hServer,
  2381. ULONG LogonId,
  2382. PWINSTATIONNAMEW pWinStationName
  2383. )
  2384. {
  2385. DWORD Result;
  2386. BOOLEAN rc;
  2387. WCHAR* rpcBuffer;
  2388. HANDLE_CURRENT_BINDING( hServer );
  2389. /*
  2390. * rpcBuffer is a workaround for bug 229753. The bug can't be fixed
  2391. * completely without breaking TS4 clients.
  2392. */
  2393. rpcBuffer = LocalAlloc(LPTR, sizeof(WINSTATIONNAMEW) * sizeof(WCHAR));
  2394. if (rpcBuffer == NULL) {
  2395. SetLastError(ERROR_OUTOFMEMORY);
  2396. return(FALSE);
  2397. }
  2398. RpcTryExcept {
  2399. rc = RpcWinStationNameFromLogonId(
  2400. hServer,
  2401. &Result,
  2402. (LogonId == LOGONID_CURRENT) ?
  2403. NtCurrentPeb()->SessionId : LogonId,
  2404. rpcBuffer,
  2405. sizeof(WINSTATIONNAMEW)
  2406. );
  2407. Result = RtlNtStatusToDosError( Result );
  2408. if (rc) {
  2409. CopyMemory(pWinStationName, rpcBuffer, sizeof(WINSTATIONNAMEW));
  2410. }
  2411. }
  2412. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2413. Result = RpcExceptionCode();
  2414. DBGPRINT(("RPC Exception %d\n",Result));
  2415. rc = FALSE;
  2416. }
  2417. RpcEndExcept
  2418. if (rpcBuffer != NULL) {
  2419. LocalFree(rpcBuffer);
  2420. }
  2421. if( !rc ) SetLastError(Result);
  2422. return( rc );
  2423. }
  2424. /*******************************************************************************
  2425. *
  2426. * WinStationConnectA (ANSI stub)
  2427. *
  2428. * Connects a window station object to the configured terminal and Pd.
  2429. *
  2430. * ENTRY:
  2431. *
  2432. * see WinStationConnectW
  2433. *
  2434. * EXIT:
  2435. *
  2436. * see WinStationConnectW
  2437. *
  2438. ******************************************************************************/
  2439. BOOLEAN
  2440. WinStationConnectA( HANDLE hServer,
  2441. ULONG LogonId,
  2442. ULONG TargetLogonId,
  2443. PCHAR pPassword,
  2444. BOOLEAN bWait )
  2445. {
  2446. WCHAR PasswordW[ PASSWORD_LENGTH + 1 ];
  2447. /*
  2448. * Convert ANSI Password to UNICODE.
  2449. */
  2450. AnsiToUnicode( PasswordW, sizeof(PasswordW), pPassword );
  2451. /*
  2452. * Call WinStationConnectW & return it's status.
  2453. */
  2454. return ( WinStationConnectW( hServer, LogonId, TargetLogonId, PasswordW, bWait ) );
  2455. }
  2456. /*******************************************************************************
  2457. *
  2458. * WinStationConnectW (UNICODE)
  2459. *
  2460. * Connects a window station object to the configured terminal and Pd.
  2461. *
  2462. * ENTRY:
  2463. *
  2464. * LogonId (input)
  2465. * ID of window station object to connect.
  2466. *
  2467. * TargetLogonId (input)
  2468. * ID of target window station.
  2469. *
  2470. * pPassword (input)
  2471. * password of LogonId window station (not needed if same domain/username)
  2472. *
  2473. * bWait (input)
  2474. * Specifies whether or not to wait for connect to complete
  2475. *
  2476. * EXIT:
  2477. *
  2478. * TRUE -- The connect operation succeeded.
  2479. *
  2480. * FALSE -- The operation failed. Extended error status is available
  2481. * using GetLastError.
  2482. *
  2483. ******************************************************************************/
  2484. BOOLEAN
  2485. WinStationConnectW(
  2486. HANDLE hServer,
  2487. ULONG LogonId,
  2488. ULONG TargetLogonId,
  2489. PWCHAR pPassword,
  2490. BOOLEAN bWait
  2491. )
  2492. {
  2493. DWORD Result;
  2494. BOOLEAN rc;
  2495. DWORD PasswordLength;
  2496. WCHAR* rpcBuffer;
  2497. HANDLE_CURRENT_BINDING( hServer );
  2498. RpcTryExcept {
  2499. if( pPassword ) {
  2500. PasswordLength = (lstrlenW( pPassword ) + 1) * sizeof(WCHAR);
  2501. /*
  2502. * rpcBuffer is a workaround for bug 229753. The bug can't be
  2503. * fixed completely without breaking TS4 clients.
  2504. */
  2505. rpcBuffer = LocalAlloc(LPTR, PasswordLength * sizeof(WCHAR));
  2506. if (rpcBuffer != NULL) {
  2507. CopyMemory(rpcBuffer, pPassword, PasswordLength);
  2508. } else {
  2509. SetLastError(ERROR_OUTOFMEMORY);
  2510. return(FALSE);
  2511. }
  2512. } else {
  2513. PasswordLength = 0;
  2514. rpcBuffer = NULL;
  2515. }
  2516. rc = RpcWinStationConnect(
  2517. hServer,
  2518. &Result,
  2519. NtCurrentPeb()->SessionId,
  2520. (LogonId == LOGONID_CURRENT) ?
  2521. NtCurrentPeb()->SessionId : LogonId,
  2522. (TargetLogonId == LOGONID_CURRENT) ?
  2523. NtCurrentPeb()->SessionId : TargetLogonId,
  2524. rpcBuffer,
  2525. PasswordLength,
  2526. bWait
  2527. );
  2528. Result = RtlNtStatusToDosError( Result );
  2529. }
  2530. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2531. Result = RpcExceptionCode();
  2532. DBGPRINT(("RPC Exception %d\n",Result));
  2533. rc = FALSE;
  2534. }
  2535. RpcEndExcept
  2536. if (rpcBuffer != NULL) {
  2537. LocalFree(rpcBuffer);
  2538. }
  2539. if( !rc ) SetLastError(Result);
  2540. return( rc );
  2541. }
  2542. /*****************************************************************************
  2543. *
  2544. * WinStationVirtualOpen
  2545. *
  2546. * Open a virtual channel
  2547. *
  2548. * ENTRY:
  2549. * Param1 (input/output)
  2550. * Comments
  2551. *
  2552. * EXIT:
  2553. * ERROR_SUCCESS - no error
  2554. *
  2555. ****************************************************************************/
  2556. HANDLE WINAPI
  2557. WinStationVirtualOpen(
  2558. HANDLE hServer,
  2559. ULONG LogonId,
  2560. PVIRTUALCHANNELNAME pVirtualName /* ascii name */
  2561. )
  2562. {
  2563. BOOLEAN rc;
  2564. DWORD Result;
  2565. DWORD NameLength;
  2566. DWORD VirtualHandle = (DWORD)0;
  2567. HANDLE_CURRENT_BINDING( hServer );
  2568. RpcTryExcept {
  2569. if( pVirtualName )
  2570. NameLength = strlen( pVirtualName ) + 1;
  2571. else
  2572. NameLength = 0;
  2573. rc = RpcWinStationVirtualOpen(
  2574. hServer,
  2575. &Result,
  2576. (LogonId == LOGONID_CURRENT) ? NtCurrentPeb()->SessionId : LogonId,
  2577. GetCurrentProcessId(),
  2578. (PCHAR)pVirtualName,
  2579. NameLength,
  2580. &VirtualHandle
  2581. );
  2582. Result = RtlNtStatusToDosError( Result );
  2583. if( !rc ) {
  2584. SetLastError(Result);
  2585. VirtualHandle = (DWORD)0;
  2586. }
  2587. }
  2588. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2589. Result = RpcExceptionCode();
  2590. SetLastError( Result );
  2591. DBGPRINT(("RPC Exception %d\n",Result));
  2592. rc = FALSE;
  2593. }
  2594. RpcEndExcept
  2595. return( (HANDLE)LongToHandle( VirtualHandle ) );
  2596. }
  2597. /*****************************************************************************
  2598. *
  2599. * _WinStationBeepOpen
  2600. *
  2601. * Open a beep channel
  2602. *
  2603. * ENTRY:
  2604. * Param1 (input/output)
  2605. * Comments
  2606. *
  2607. * EXIT:
  2608. * ERROR_SUCCESS - no error
  2609. *
  2610. ****************************************************************************/
  2611. HANDLE WINAPI
  2612. _WinStationBeepOpen(
  2613. ULONG LogonId
  2614. )
  2615. {
  2616. BOOLEAN rc;
  2617. DWORD Result;
  2618. DWORD VirtualHandle = (DWORD)0;
  2619. HANDLE hServer = SERVERNAME_CURRENT;
  2620. HANDLE_CURRENT_BINDING( hServer );
  2621. RpcTryExcept {
  2622. rc = RpcWinStationBeepOpen(
  2623. hServer,
  2624. &Result,
  2625. (LogonId == LOGONID_CURRENT) ? NtCurrentPeb()->SessionId : LogonId,
  2626. GetCurrentProcessId(),
  2627. &VirtualHandle
  2628. );
  2629. Result = RtlNtStatusToDosError( Result );
  2630. if( !rc ) {
  2631. SetLastError(Result);
  2632. VirtualHandle = (DWORD)0;
  2633. }
  2634. }
  2635. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2636. Result = RpcExceptionCode();
  2637. SetLastError( Result );
  2638. DBGPRINT(("RPC Exception %d\n",Result));
  2639. rc = FALSE;
  2640. }
  2641. RpcEndExcept
  2642. return( (HANDLE)LongToHandle( VirtualHandle ) );
  2643. }
  2644. /*******************************************************************************
  2645. *
  2646. * WinStationDisconnect
  2647. *
  2648. * Disconects a window station object from the configured terminal and Pd.
  2649. * While disconnected all window station i/o is bit bucketed.
  2650. *
  2651. * ENTRY:
  2652. *
  2653. * LogonId (input)
  2654. * ID of window station object to disconnect.
  2655. * bWait (input)
  2656. * Specifies whether or not to wait for disconnect to complete
  2657. *
  2658. * EXIT:
  2659. *
  2660. * TRUE -- The disconnect operation succeeded.
  2661. *
  2662. * FALSE -- The operation failed. Extended error status is available
  2663. * using GetLastError.
  2664. *
  2665. ******************************************************************************/
  2666. BOOLEAN
  2667. WinStationDisconnect(
  2668. HANDLE hServer,
  2669. ULONG LogonId,
  2670. BOOLEAN bWait
  2671. )
  2672. {
  2673. DWORD Result;
  2674. BOOLEAN rc;
  2675. HANDLE_CURRENT_BINDING( hServer );
  2676. RpcTryExcept {
  2677. rc = RpcWinStationDisconnect(
  2678. hServer,
  2679. &Result,
  2680. (LogonId == LOGONID_CURRENT) ? NtCurrentPeb()->SessionId : LogonId,
  2681. bWait
  2682. );
  2683. Result = RtlNtStatusToDosError( Result );
  2684. if( !rc ) SetLastError(Result);
  2685. }
  2686. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2687. Result = RpcExceptionCode();
  2688. SetLastError( Result );
  2689. DBGPRINT(("RPC Exception %d\n",Result));
  2690. rc = FALSE;
  2691. }
  2692. RpcEndExcept
  2693. return( rc );
  2694. }
  2695. /*******************************************************************************
  2696. *
  2697. * WinStationReset
  2698. *
  2699. * Reset the specified window station.
  2700. *
  2701. * ENTRY:
  2702. *
  2703. * LogonId (input)
  2704. * Identifies the window station object to reset.
  2705. * bWait (input)
  2706. * Specifies whether or not to wait for reset to complete
  2707. *
  2708. * EXIT:
  2709. *
  2710. * TRUE -- The reset operation succeeded.
  2711. *
  2712. * FALSE -- The operation failed. Extended error status is available
  2713. * using GetLastError.
  2714. *
  2715. ******************************************************************************/
  2716. BOOLEAN
  2717. WinStationReset(
  2718. HANDLE hServer,
  2719. ULONG LogonId,
  2720. BOOLEAN bWait
  2721. )
  2722. {
  2723. DWORD Result;
  2724. BOOLEAN rc;
  2725. HANDLE_CURRENT_BINDING( hServer );
  2726. RpcTryExcept {
  2727. rc = RpcWinStationReset(
  2728. hServer,
  2729. &Result,
  2730. (LogonId == LOGONID_CURRENT) ? NtCurrentPeb()->SessionId : LogonId,
  2731. bWait
  2732. );
  2733. Result = RtlNtStatusToDosError( Result );
  2734. if( !rc ) SetLastError(Result);
  2735. }
  2736. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2737. Result = RpcExceptionCode();
  2738. SetLastError( Result );
  2739. DBGPRINT(("RPC Exception %d\n",Result));
  2740. rc = FALSE;
  2741. }
  2742. RpcEndExcept
  2743. return( rc );
  2744. }
  2745. /*******************************************************************************
  2746. *
  2747. * WinStationShadowStop
  2748. *
  2749. * Stop the shadow on the specified window station.
  2750. *
  2751. * ENTRY:
  2752. *
  2753. * LogonId (input)
  2754. * Identifies the window station object to stop the shadow on.
  2755. * bWait (input)
  2756. * Specifies whether or not to wait for reset to complete
  2757. *
  2758. * EXIT:
  2759. *
  2760. * TRUE -- The operation succeeded.
  2761. *
  2762. * FALSE -- The operation failed. Extended error status is available
  2763. * using GetLastError.
  2764. *
  2765. ******************************************************************************/
  2766. BOOLEAN
  2767. WinStationShadowStop(
  2768. HANDLE hServer,
  2769. ULONG LogonId,
  2770. BOOLEAN bWait
  2771. )
  2772. {
  2773. DWORD Result;
  2774. BOOLEAN rc;
  2775. HANDLE_CURRENT_BINDING( hServer );
  2776. RpcTryExcept {
  2777. rc = RpcWinStationShadowStop(
  2778. hServer,
  2779. &Result,
  2780. (LogonId == LOGONID_CURRENT) ? NtCurrentPeb()->SessionId : LogonId,
  2781. bWait
  2782. );
  2783. Result = RtlNtStatusToDosError( Result );
  2784. if( !rc ) SetLastError(Result);
  2785. }
  2786. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2787. Result = RpcExceptionCode();
  2788. SetLastError( Result );
  2789. DBGPRINT(("RPC Exception %d\n",Result));
  2790. rc = FALSE;
  2791. }
  2792. RpcEndExcept
  2793. return( rc );
  2794. }
  2795. /*******************************************************************************
  2796. *
  2797. * WinStationShutdownSystem
  2798. *
  2799. * Shutdown the system and optionally logoff all WinStations
  2800. * and/or reboot the system.
  2801. *
  2802. * ENTRY:
  2803. *
  2804. * ShutdownFlags (input)
  2805. * Flags which specify shutdown options.
  2806. *
  2807. * EXIT:
  2808. *
  2809. * TRUE -- The shutdown operation succeeded.
  2810. *
  2811. * FALSE -- The operation failed. Extended error status is available
  2812. * using GetLastError.
  2813. *
  2814. ******************************************************************************/
  2815. BOOLEAN
  2816. WinStationShutdownSystem(
  2817. HANDLE hServer,
  2818. ULONG ShutdownFlags
  2819. )
  2820. {
  2821. DWORD Result;
  2822. BOOLEAN rc;
  2823. HANDLE_CURRENT_BINDING( hServer );
  2824. RpcTryExcept {
  2825. rc = RpcWinStationShutdownSystem(
  2826. hServer,
  2827. &Result,
  2828. NtCurrentPeb()->SessionId,
  2829. ShutdownFlags
  2830. );
  2831. Result = RtlNtStatusToDosError( Result );
  2832. if( !rc ) SetLastError(Result);
  2833. }
  2834. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2835. Result = RpcExceptionCode();
  2836. SetLastError( Result );
  2837. DBGPRINT(("RPC Exception %d\n",Result));
  2838. rc = FALSE;
  2839. }
  2840. RpcEndExcept
  2841. return( rc );
  2842. }
  2843. /*******************************************************************************
  2844. *
  2845. * WinStationTerminateProcess
  2846. *
  2847. * Terminate the specified process
  2848. *
  2849. * ENTRY:
  2850. *
  2851. * hServer (input)
  2852. * handle to winframe server
  2853. * ProcessId (input)
  2854. * process id of the process to terminate
  2855. * ExitCode (input)
  2856. * Termination status for each thread in the process
  2857. *
  2858. *
  2859. * EXIT:
  2860. *
  2861. * TRUE -- The terminate operation succeeded.
  2862. *
  2863. * FALSE -- The operation failed. Extended error status is available
  2864. * using GetLastError.
  2865. *
  2866. ******************************************************************************/
  2867. BOOLEAN
  2868. WinStationTerminateProcess(
  2869. HANDLE hServer,
  2870. ULONG ProcessId,
  2871. ULONG ExitCode
  2872. )
  2873. {
  2874. DWORD Result;
  2875. BOOLEAN rc;
  2876. HANDLE_CURRENT_BINDING( hServer );
  2877. RpcTryExcept {
  2878. rc = RpcWinStationTerminateProcess(
  2879. hServer,
  2880. &Result,
  2881. ProcessId,
  2882. ExitCode
  2883. );
  2884. Result = RtlNtStatusToDosError( Result );
  2885. if( !rc ) SetLastError(Result);
  2886. }
  2887. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2888. Result = RpcExceptionCode();
  2889. SetLastError( Result );
  2890. DBGPRINT(("RPC Exception %d\n",Result));
  2891. rc = FALSE;
  2892. }
  2893. RpcEndExcept
  2894. return( rc );
  2895. }
  2896. /*******************************************************************************
  2897. *
  2898. * WinStationWaitSystemEvent
  2899. *
  2900. * Waits for an event (WinStation create, delete, connect, etc) before
  2901. * returning to the caller.
  2902. *
  2903. * ENTRY:
  2904. *
  2905. * EventFlags (input)
  2906. * Bit mask that specifies which event(s) to wait for.
  2907. * pEventFlags (output)
  2908. * Bit mask of event(s) that occurred.
  2909. *
  2910. * EXIT:
  2911. *
  2912. * TRUE -- The wait event operation succeeded.
  2913. *
  2914. * FALSE -- The operation failed. Extended error status is available
  2915. * using GetLastError.
  2916. *
  2917. ******************************************************************************/
  2918. BOOLEAN
  2919. WinStationWaitSystemEvent(
  2920. HANDLE hServer,
  2921. ULONG EventMask,
  2922. PULONG pEventFlags
  2923. )
  2924. {
  2925. DWORD Result;
  2926. BOOLEAN rc;
  2927. HANDLE_CURRENT_BINDING( hServer );
  2928. RpcTryExcept {
  2929. rc = RpcWinStationWaitSystemEvent(
  2930. hServer,
  2931. &Result,
  2932. EventMask,
  2933. pEventFlags
  2934. );
  2935. Result = RtlNtStatusToDosError( Result );
  2936. if( !rc ) SetLastError(Result);
  2937. }
  2938. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2939. Result = RpcExceptionCode();
  2940. SetLastError( Result );
  2941. DBGPRINT(("RPC Exception %d\n",Result));
  2942. rc = FALSE;
  2943. }
  2944. RpcEndExcept
  2945. return( rc );
  2946. }
  2947. /*****************************************************************************
  2948. *
  2949. * WinStationShadow
  2950. *
  2951. * Start a Winstation shadow operation
  2952. *
  2953. * ENTRY:
  2954. * hServer (input)
  2955. * open RPC server handle
  2956. * pTargetServerName (input)
  2957. * name of target WinFrame server
  2958. * TargetLogonId (input)
  2959. * shadow target login id (where the app is running)
  2960. * HotkeyVk (input)
  2961. * virtual key to press to stop shadow
  2962. * HotkeyModifiers (input)
  2963. * virtual modifer to press to stop shadow (i.e. shift, control)
  2964. *
  2965. * EXIT:
  2966. * ERROR_SUCCESS - no error
  2967. *
  2968. ****************************************************************************/
  2969. BOOLEAN WINAPI
  2970. WinStationShadow(
  2971. HANDLE hServer,
  2972. LPWSTR pTargetServerName,
  2973. ULONG TargetLogonId,
  2974. BYTE HotkeyVk,
  2975. USHORT HotkeyModifiers
  2976. )
  2977. {
  2978. DWORD NameSize;
  2979. DWORD Result;
  2980. BOOLEAN rc;
  2981. WCHAR* rpcBuffer;
  2982. HANDLE_CURRENT_BINDING( hServer );
  2983. RpcTryExcept {
  2984. if ( pTargetServerName && *pTargetServerName ) {
  2985. NameSize = (lstrlenW( pTargetServerName ) + 1) * sizeof(WCHAR);
  2986. /*
  2987. * rpcBuffer is a workaround for bug 229753. The bug can't be
  2988. * fixed completely without breaking TS4 clients.
  2989. */
  2990. rpcBuffer = LocalAlloc(LPTR, NameSize * sizeof(WCHAR));
  2991. if (rpcBuffer != NULL) {
  2992. CopyMemory(rpcBuffer, pTargetServerName, NameSize);
  2993. } else {
  2994. SetLastError(ERROR_OUTOFMEMORY);
  2995. return(FALSE);
  2996. }
  2997. } else {
  2998. NameSize = 0;
  2999. rpcBuffer = NULL;
  3000. }
  3001. rc = RpcWinStationShadow(
  3002. hServer,
  3003. &Result,
  3004. NtCurrentPeb()->SessionId,
  3005. rpcBuffer,
  3006. NameSize,
  3007. TargetLogonId,
  3008. HotkeyVk,
  3009. HotkeyModifiers
  3010. );
  3011. Result = RtlNtStatusToDosError( Result );
  3012. }
  3013. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3014. Result = RpcExceptionCode();
  3015. DBGPRINT(("RPC Exception %d\n",Result));
  3016. rc = FALSE;
  3017. }
  3018. RpcEndExcept
  3019. if (rpcBuffer != NULL) {
  3020. LocalFree(rpcBuffer);
  3021. }
  3022. if( !rc ) SetLastError(Result);
  3023. return( rc );
  3024. }
  3025. /*****************************************************************************
  3026. *
  3027. * _WinStationShadowTargetSetup
  3028. *
  3029. * private api used to initialize the target size of a shadow
  3030. *
  3031. * ENTRY:
  3032. * hServer (input)
  3033. * target server
  3034. * LogonId (input)
  3035. * target logon id
  3036. * pClientName (input)
  3037. * pointer to client name string (domain/username)
  3038. * ClientNameLength (input)
  3039. * length of client name string
  3040. *
  3041. * EXIT:
  3042. * ERROR_SUCCESS - no error
  3043. *
  3044. ****************************************************************************/
  3045. BOOLEAN WINAPI
  3046. _WinStationShadowTargetSetup(
  3047. HANDLE hServer,
  3048. ULONG LogonId
  3049. )
  3050. {
  3051. DWORD Result;
  3052. BOOLEAN rc;
  3053. HANDLE_CURRENT_BINDING( hServer );
  3054. RpcTryExcept {
  3055. rc = RpcWinStationShadowTargetSetup(
  3056. hServer,
  3057. &Result,
  3058. (LogonId == LOGONID_CURRENT) ? NtCurrentPeb()->SessionId : LogonId
  3059. );
  3060. //Result = RtlNtStatusToDosError( Result );
  3061. if( !rc ) SetLastError(RtlNtStatusToDosError(Result));
  3062. }
  3063. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3064. Result = RpcExceptionCode();
  3065. SetLastError( Result );
  3066. DBGPRINT(("RPC Exception %d\n",Result));
  3067. rc = FALSE;
  3068. }
  3069. RpcEndExcept
  3070. return( rc );
  3071. }
  3072. /*****************************************************************************
  3073. *
  3074. * _WinStationShadowTarget
  3075. *
  3076. * private api used to initialize the target size of a shadow
  3077. *
  3078. * ENTRY:
  3079. * hServer (input)
  3080. * target server
  3081. * LogonId (input)
  3082. * target logon id
  3083. * pConfig (input)
  3084. * pointer to WinStation config data (to configure shadow stack)
  3085. * pAddress (input)
  3086. * address of shadow client
  3087. * pModuleData (input)
  3088. * pointer to client module data
  3089. * ModuleDataLength (input)
  3090. * length of client module data
  3091. * pThinwireData (input)
  3092. * pointer to thinwire module data
  3093. * ThinwireDataLength (input)
  3094. * length of thinwire module data
  3095. * pClientName (input)
  3096. * pointer to client name string (domain/username)
  3097. * ClientNameLength (input)
  3098. * length of client name string
  3099. *
  3100. * EXIT:
  3101. * ERROR_SUCCESS - no error
  3102. *
  3103. ****************************************************************************/
  3104. NTSTATUS WINAPI
  3105. _WinStationShadowTarget(
  3106. HANDLE hServer,
  3107. ULONG LogonId,
  3108. PWINSTATIONCONFIG2 pConfig,
  3109. PICA_STACK_ADDRESS pAddress,
  3110. PVOID pModuleData,
  3111. ULONG ModuleDataLength,
  3112. PVOID pThinwireData,
  3113. ULONG ThinwireDataLength,
  3114. PVOID pClientName,
  3115. ULONG ClientNameLength
  3116. )
  3117. {
  3118. DWORD Result;
  3119. BOOLEAN rc;
  3120. HANDLE_CURRENT_BINDING( hServer );
  3121. RpcTryExcept {
  3122. rc = RpcWinStationShadowTarget(
  3123. hServer,
  3124. &Result,
  3125. (LogonId == LOGONID_CURRENT) ? NtCurrentPeb()->SessionId : LogonId,
  3126. (PBYTE) pConfig,
  3127. sizeof(*pConfig),
  3128. (PBYTE) pAddress,
  3129. sizeof(*pAddress),
  3130. pModuleData,
  3131. ModuleDataLength,
  3132. pThinwireData,
  3133. ThinwireDataLength,
  3134. pClientName,
  3135. ClientNameLength
  3136. );
  3137. // Since a program has called us, we need to set the last error code such
  3138. // that extended error information is available
  3139. if (!rc)
  3140. SetLastError(RtlNtStatusToDosError(Result));
  3141. }
  3142. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3143. Result = RpcExceptionCode();
  3144. SetLastError( Result );
  3145. DBGPRINT(("RPC Exception %d\n",Result));
  3146. rc = FALSE;
  3147. }
  3148. RpcEndExcept
  3149. return Result;
  3150. }
  3151. /*******************************************************************************
  3152. *
  3153. * WinStationFreeMemory
  3154. *
  3155. * Called to free memory which was allocated by a WinStation API.
  3156. *
  3157. * ENTRY:
  3158. * pBuffer (input)
  3159. *
  3160. * EXIT:
  3161. * TRUE -- The install operation succeeded.
  3162. *
  3163. ******************************************************************************/
  3164. BOOLEAN WINAPI
  3165. WinStationFreeMemory(
  3166. PVOID pBuffer
  3167. )
  3168. {
  3169. if ( pBuffer )
  3170. LocalFree( pBuffer );
  3171. return( TRUE );
  3172. }
  3173. /*******************************************************************************
  3174. *
  3175. * WinStationFreeGAPMemory
  3176. *
  3177. * Called to free memory which was allocated by the WinStationGetAllProcesses API.
  3178. *
  3179. *
  3180. ******************************************************************************/
  3181. BOOLEAN WINAPI
  3182. WinStationFreeGAPMemory(ULONG Level,
  3183. PVOID pProcArray,
  3184. ULONG NumberOfProcesses)
  3185. {
  3186. ULONG i;
  3187. PTS_ALL_PROCESSES_INFO pProcessArray = (PTS_ALL_PROCESSES_INFO)pProcArray;
  3188. if (Level == GAP_LEVEL_BASIC) // only level supported right now
  3189. {
  3190. if ( pProcessArray != NULL)
  3191. {
  3192. for (i=0; i < NumberOfProcesses ; i++)
  3193. {
  3194. if (pProcessArray[i].pTsProcessInfo != NULL)
  3195. {
  3196. if (((pProcessArray[i].pTsProcessInfo)->ImageName).Buffer != NULL)
  3197. {
  3198. //
  3199. // free the ImageName string
  3200. //
  3201. LocalFree(((pProcessArray[i].pTsProcessInfo)->ImageName).Buffer);
  3202. }
  3203. //
  3204. // free the Process Info buffer
  3205. //
  3206. LocalFree(pProcessArray[i].pTsProcessInfo);
  3207. }
  3208. if (pProcessArray[i].pSid != NULL)
  3209. {
  3210. //
  3211. // free the SID
  3212. //
  3213. LocalFree(pProcessArray[i].pSid);
  3214. }
  3215. }
  3216. LocalFree(pProcessArray);
  3217. }
  3218. return TRUE;
  3219. }
  3220. else
  3221. {
  3222. return FALSE;
  3223. }
  3224. }
  3225. /*******************************************************************************
  3226. *
  3227. * WinStationGenerateLicense
  3228. *
  3229. * Called to generate a license from a given serial number string.
  3230. *
  3231. * ENTRY:
  3232. * hServer (input)
  3233. * Server handle
  3234. * pSerialNumberString (input)
  3235. * Pointer to a null-terminated, wide-character Serial Number string
  3236. * pLicense (output)
  3237. * Pointer to a License structure that will be filled in with
  3238. * information based on pSerialNumberString
  3239. * LicenseSize (input)
  3240. * Size in bytes of the structure pointed to by pLicense
  3241. *
  3242. * EXIT:
  3243. *
  3244. * TRUE -- The install operation succeeded.
  3245. *
  3246. * FALSE -- The operation failed. Extended error status is available
  3247. * using GetLastError.
  3248. *
  3249. ******************************************************************************/
  3250. BOOLEAN WINAPI
  3251. WinStationGenerateLicense(
  3252. HANDLE hServer,
  3253. PWCHAR pSerialNumberString,
  3254. PVOID pLicense,
  3255. DWORD LicenseSize
  3256. )
  3257. {
  3258. BOOLEAN rc;
  3259. DWORD Result;
  3260. DWORD Length;
  3261. WCHAR* rpcBuffer;
  3262. HANDLE_CURRENT_BINDING( hServer );
  3263. RpcTryExcept {
  3264. if ( pSerialNumberString ) {
  3265. Length = (lstrlenW( pSerialNumberString ) + 1) * sizeof(WCHAR);
  3266. /*
  3267. * rpcBuffer is a workaround for 229753.
  3268. */
  3269. rpcBuffer = LocalAlloc(LPTR, Length * sizeof(WCHAR));
  3270. if (rpcBuffer != NULL) {
  3271. CopyMemory(rpcBuffer, pSerialNumberString, Length);
  3272. } else {
  3273. SetLastError(ERROR_OUTOFMEMORY);
  3274. return(FALSE);
  3275. }
  3276. } else {
  3277. Length = 0;
  3278. rpcBuffer = NULL;
  3279. }
  3280. rc = RpcWinStationGenerateLicense(
  3281. hServer,
  3282. &Result,
  3283. rpcBuffer,
  3284. Length,
  3285. (PCHAR)pLicense,
  3286. LicenseSize
  3287. );
  3288. }
  3289. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3290. Result = RpcExceptionCode();
  3291. DBGPRINT(("RPC Exception %d\n",Result));
  3292. rc = FALSE;
  3293. }
  3294. RpcEndExcept
  3295. if (rpcBuffer != NULL) {
  3296. LocalFree(rpcBuffer);
  3297. }
  3298. if( !rc ) SetLastError(Result);
  3299. return( rc );
  3300. }
  3301. /*******************************************************************************
  3302. *
  3303. * WinStationInstallLicense
  3304. *
  3305. * Called to install a license.
  3306. *
  3307. * ENTRY:
  3308. * hServer (input)
  3309. * Server handle
  3310. * pLicense (input)
  3311. * Pointer to a License structure containing the license to
  3312. * be installed
  3313. * LicenseSize (input)
  3314. * Size in bytes of the structure pointed to by pLicense
  3315. *
  3316. * EXIT:
  3317. *
  3318. * TRUE -- The install operation succeeded.
  3319. *
  3320. * FALSE -- The operation failed. Extended error status is available
  3321. * using GetLastError.
  3322. *
  3323. ******************************************************************************/
  3324. BOOLEAN
  3325. WinStationInstallLicense(
  3326. HANDLE hServer,
  3327. PVOID pLicense,
  3328. DWORD LicenseSize
  3329. )
  3330. {
  3331. BOOLEAN rc;
  3332. DWORD Result;
  3333. HANDLE_CURRENT_BINDING( hServer );
  3334. RpcTryExcept {
  3335. rc = RpcWinStationInstallLicense(
  3336. hServer,
  3337. &Result,
  3338. (PCHAR) pLicense,
  3339. LicenseSize
  3340. );
  3341. if( !rc ) SetLastError(Result);
  3342. }
  3343. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3344. Result = RpcExceptionCode();
  3345. SetLastError( Result );
  3346. DBGPRINT(("RPC Exception %d\n",Result));
  3347. rc = FALSE;
  3348. }
  3349. RpcEndExcept
  3350. return( rc );
  3351. }
  3352. /*******************************************************************************
  3353. *
  3354. * WinStationEnumerateLicenses
  3355. *
  3356. * Called to return the list of valid licenses.
  3357. *
  3358. * ENTRY:
  3359. * hServer (input)
  3360. * Server handle
  3361. * ppLicense (output)
  3362. * Points to a pointer to a buffer to receive the enumeration results,
  3363. * which are returned as an array of LICENSE structures. The buffer is
  3364. * allocated within this API and is disposed of using
  3365. * WinStationFreeMemory.
  3366. * pEntries (output)
  3367. * Points to a variable specifying the number of entries read.
  3368. *
  3369. * EXIT:
  3370. *
  3371. * TRUE -- The enumerate operation succeeded.
  3372. *
  3373. * FALSE -- The operation failed. Extended error status is available
  3374. * using GetLastError.
  3375. *
  3376. ******************************************************************************/
  3377. #define _LICENSE_REQUEST_SIZE 10
  3378. #define _LICENSE_SIZE 1024 // This is arbitrary
  3379. BOOLEAN
  3380. WinStationEnumerateLicenses(
  3381. HANDLE hServer,
  3382. PVOID *ppLicense,
  3383. DWORD *pEntries
  3384. )
  3385. {
  3386. ULONG ByteCount;
  3387. ULONG BumpSize;
  3388. ULONG TotalSize;
  3389. LONG Index;
  3390. int i;
  3391. BOOLEAN rc;
  3392. DWORD Result;
  3393. HANDLE_CURRENT_BINDING( hServer );
  3394. BumpSize = _LICENSE_SIZE * _LICENSE_REQUEST_SIZE;
  3395. TotalSize = 0;
  3396. *ppLicense = NULL;
  3397. *pEntries = 0;
  3398. Index = 0;
  3399. for ( ;; ) {
  3400. PVOID pNewLicense;
  3401. LONG BumpEntries;
  3402. /*
  3403. * Allocate a enough memory for _LICENSE_REQUEST_SIZE more
  3404. * entries.
  3405. */
  3406. pNewLicense = LocalAlloc( 0, TotalSize + BumpSize );
  3407. if ( !pNewLicense ) {
  3408. if ( *ppLicense )
  3409. WinStationFreeMemory( *ppLicense );
  3410. SetLastError( ERROR_OUTOFMEMORY );
  3411. return( FALSE );
  3412. }
  3413. /*
  3414. * If this is not the first pass through, then copy
  3415. * the previous buffer's contents to the new buffer.
  3416. */
  3417. if ( TotalSize ) {
  3418. RtlCopyMemory( pNewLicense, *ppLicense, TotalSize );
  3419. WinStationFreeMemory( *ppLicense );
  3420. }
  3421. *ppLicense = pNewLicense;
  3422. /*
  3423. * Get up to _LICENSE_REQUEST_SIZE Licenses
  3424. */
  3425. ByteCount = BumpSize;
  3426. BumpEntries = _LICENSE_REQUEST_SIZE;
  3427. RpcTryExcept {
  3428. rc = RpcWinStationEnumerateLicenses(
  3429. hServer,
  3430. &Result,
  3431. &Index,
  3432. &BumpEntries,
  3433. (PCHAR) (((PCHAR) *ppLicense) + TotalSize),
  3434. ByteCount,
  3435. &ByteCount
  3436. );
  3437. Result = rc ? ERROR_SUCCESS : Result;
  3438. }
  3439. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3440. Result = RpcExceptionCode();
  3441. DBGPRINT(("RPC Exception %d\n",Result));
  3442. }
  3443. RpcEndExcept
  3444. if ( Result != ERROR_SUCCESS && Result != ERROR_NO_MORE_ITEMS ) {
  3445. SetLastError( Result );
  3446. return( FALSE );
  3447. }
  3448. else {
  3449. /*
  3450. * Bump the Total Size of the License buffer by the size of
  3451. * the request
  3452. */
  3453. TotalSize += BumpSize;
  3454. /*
  3455. * Include the new Licenses in the entry count
  3456. */
  3457. *pEntries += BumpEntries;
  3458. if ( Result == ERROR_NO_MORE_ITEMS ) {
  3459. return( TRUE );
  3460. }
  3461. }
  3462. } // for ( ;; )
  3463. }
  3464. /*******************************************************************************
  3465. *
  3466. * WinStationActivateLicense
  3467. *
  3468. * Called to Activate a license for a given License
  3469. *
  3470. * ENTRY:
  3471. * hServer (input)
  3472. * Server handle
  3473. * pLicense (input/output)
  3474. * Pointer to a License structure that will be activated
  3475. * LicenseSize (input)
  3476. * Size in bytes of the structure pointed to by pLicense
  3477. * pActivationCode (input)
  3478. * Pointer to a null-terminated, wide-character Activation Code string
  3479. *
  3480. * EXIT:
  3481. *
  3482. * TRUE -- The install operation succeeded.
  3483. *
  3484. * FALSE -- The operation failed. Extended error status is available
  3485. * using GetLastError.
  3486. *
  3487. ******************************************************************************/
  3488. BOOLEAN
  3489. WinStationActivateLicense(
  3490. HANDLE hServer,
  3491. PVOID pLicense,
  3492. DWORD LicenseSize,
  3493. PWCHAR pActivationCode
  3494. )
  3495. {
  3496. BOOLEAN rc;
  3497. DWORD Result;
  3498. DWORD Length;
  3499. WCHAR* rpcBuffer;
  3500. HANDLE_CURRENT_BINDING( hServer );
  3501. RpcTryExcept {
  3502. if ( pActivationCode ) {
  3503. Length = (lstrlenW( pActivationCode ) + 1) * sizeof(WCHAR);
  3504. /*
  3505. * rpcBuffer is a workaround for 229753.
  3506. */
  3507. rpcBuffer = LocalAlloc(LPTR, Length * sizeof(WCHAR));
  3508. if (rpcBuffer != NULL) {
  3509. CopyMemory(rpcBuffer, pActivationCode, Length);
  3510. } else {
  3511. SetLastError(ERROR_OUTOFMEMORY);
  3512. return(FALSE);
  3513. }
  3514. } else {
  3515. Length = 0;
  3516. rpcBuffer = NULL;
  3517. }
  3518. rc = RpcWinStationActivateLicense(
  3519. hServer,
  3520. &Result,
  3521. (PCHAR)pLicense,
  3522. LicenseSize,
  3523. rpcBuffer,
  3524. Length
  3525. );
  3526. }
  3527. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3528. Result = RpcExceptionCode();
  3529. DBGPRINT(("RPC Exception %d\n",Result));
  3530. rc = FALSE;
  3531. }
  3532. RpcEndExcept
  3533. if (rpcBuffer != NULL) {
  3534. LocalFree(rpcBuffer);
  3535. }
  3536. if( !rc ) SetLastError(Result);
  3537. return( rc );
  3538. }
  3539. /*****************************************************************************
  3540. *
  3541. * WinStationQueryLicense
  3542. *
  3543. * Query the license(s) on the WinFrame server and the network
  3544. *
  3545. * ENTRY:
  3546. * hServer (input)
  3547. * Server handle
  3548. * pLicenseCounts (output)
  3549. * pointer to buffer to return license count structure
  3550. * ByteCount (input)
  3551. * length of buffer in bytes
  3552. *
  3553. * EXIT:
  3554. * ERROR_SUCCESS - no error
  3555. *
  3556. ****************************************************************************/
  3557. BOOLEAN WINAPI
  3558. WinStationQueryLicense(
  3559. HANDLE hServer,
  3560. PVOID pLicenseCounts,
  3561. ULONG ByteCount
  3562. )
  3563. {
  3564. DWORD Result;
  3565. BOOLEAN rc;
  3566. HANDLE_CURRENT_BINDING( hServer );
  3567. RpcTryExcept {
  3568. memset( pLicenseCounts, 0, ByteCount );
  3569. rc = RpcWinStationQueryLicense(
  3570. hServer,
  3571. &Result,
  3572. (PCHAR) pLicenseCounts,
  3573. ByteCount
  3574. );
  3575. Result = RtlNtStatusToDosError( Result );
  3576. if( !rc ) SetLastError(Result);
  3577. }
  3578. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3579. Result = RpcExceptionCode();
  3580. SetLastError( Result );
  3581. DBGPRINT(("RPC Exception %d\n",Result));
  3582. rc = FALSE;
  3583. }
  3584. RpcEndExcept
  3585. return( rc );
  3586. }
  3587. /*****************************************************************************
  3588. *
  3589. * WinStationQueryUpdateRequired
  3590. *
  3591. * Query the license(s) on the WinFrame server and determine if an
  3592. * update is required. (worker)
  3593. *
  3594. * ENTRY:
  3595. * hServer (input)
  3596. * Server handle
  3597. * pUpdateFlag (output)
  3598. * Update flag, set if an update is required
  3599. *
  3600. * EXIT:
  3601. * ERROR_SUCCESS - no error
  3602. *
  3603. ****************************************************************************/
  3604. BOOLEAN WINAPI
  3605. WinStationQueryUpdateRequired(
  3606. HANDLE hServer,
  3607. PULONG pUpdateFlag
  3608. )
  3609. {
  3610. DWORD Result;
  3611. BOOLEAN rc;
  3612. HANDLE_CURRENT_BINDING( hServer );
  3613. RpcTryExcept {
  3614. rc = RpcWinStationQueryUpdateRequired(
  3615. hServer,
  3616. &Result,
  3617. pUpdateFlag
  3618. );
  3619. Result = RtlNtStatusToDosError( Result );
  3620. if( !rc ) SetLastError(Result);
  3621. }
  3622. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3623. Result = RpcExceptionCode();
  3624. SetLastError( Result );
  3625. DBGPRINT(("RPC Exception %d\n",Result));
  3626. rc = FALSE;
  3627. }
  3628. RpcEndExcept
  3629. return( rc );
  3630. }
  3631. /*******************************************************************************
  3632. *
  3633. * WinStationRemoveLicense
  3634. *
  3635. * Called to remove a license diskette.
  3636. *
  3637. * ENTRY:
  3638. * hServer (input)
  3639. * Server handle
  3640. * pLicense (input)
  3641. * Pointer to a License structure containing the license to
  3642. * be removed
  3643. * LicenseSize (input)
  3644. * Size in bytes of the structure pointed to by pLicense
  3645. *
  3646. * EXIT:
  3647. *
  3648. * TRUE -- The install operation succeeded.
  3649. *
  3650. * FALSE -- The operation failed. Extended error status is available
  3651. * using GetLastError.
  3652. *
  3653. ******************************************************************************/
  3654. BOOLEAN
  3655. WinStationRemoveLicense(
  3656. HANDLE hServer,
  3657. PVOID pLicense,
  3658. DWORD LicenseSize
  3659. )
  3660. {
  3661. BOOLEAN rc;
  3662. DWORD Result;
  3663. HANDLE_CURRENT_BINDING( hServer );
  3664. RpcTryExcept {
  3665. rc = RpcWinStationRemoveLicense(
  3666. hServer,
  3667. &Result,
  3668. (PCHAR) pLicense,
  3669. LicenseSize
  3670. );
  3671. if( !rc ) SetLastError(Result);
  3672. }
  3673. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3674. Result = RpcExceptionCode();
  3675. SetLastError( Result );
  3676. DBGPRINT(("RPC Exception %d\n",Result));
  3677. rc = FALSE;
  3678. }
  3679. RpcEndExcept
  3680. return( rc );
  3681. }
  3682. /*******************************************************************************
  3683. *
  3684. * WinStationSetPoolCount
  3685. *
  3686. * Called to change the PoolCount for a given License
  3687. *
  3688. * ENTRY:
  3689. * hServer (input)
  3690. * Server handle
  3691. * pLicense (input/output)
  3692. * Pointer to a License structure that will be changed
  3693. * LicenseSize (input)
  3694. * Size in bytes of the structure pointed to by pLicense
  3695. *
  3696. * EXIT:
  3697. *
  3698. * TRUE -- The change operation succeeded.
  3699. *
  3700. * FALSE -- The operation failed. Extended error status is available
  3701. * using GetLastError.
  3702. *
  3703. ******************************************************************************/
  3704. BOOLEAN
  3705. WinStationSetPoolCount(
  3706. HANDLE hServer,
  3707. PVOID pLicense,
  3708. DWORD LicenseSize
  3709. )
  3710. {
  3711. BOOLEAN rc;
  3712. DWORD Result;
  3713. HANDLE_CURRENT_BINDING( hServer );
  3714. RpcTryExcept {
  3715. rc = RpcWinStationSetPoolCount(
  3716. hServer,
  3717. &Result,
  3718. (PCHAR) pLicense,
  3719. LicenseSize
  3720. );
  3721. if( !rc ) SetLastError(Result);
  3722. }
  3723. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3724. Result = RpcExceptionCode();
  3725. SetLastError( Result );
  3726. DBGPRINT(("RPC Exception %d\n",Result));
  3727. rc = FALSE;
  3728. }
  3729. RpcEndExcept
  3730. return( rc );
  3731. }
  3732. /*****************************************************************************
  3733. *
  3734. * _WinStationAnnoyancePopup
  3735. *
  3736. * Comment
  3737. *
  3738. * ENTRY:
  3739. * Param1 (input/output)
  3740. * Comments
  3741. *
  3742. * EXIT:
  3743. * ERROR_SUCCESS - no error
  3744. *
  3745. ****************************************************************************/
  3746. BOOLEAN WINAPI
  3747. _WinStationAnnoyancePopup(
  3748. HANDLE hServer,
  3749. ULONG LogonId
  3750. )
  3751. {
  3752. BOOLEAN rc;
  3753. DWORD Result;
  3754. HANDLE_CURRENT_BINDING( hServer );
  3755. RpcTryExcept {
  3756. rc = RpcWinStationAnnoyancePopup(
  3757. hServer,
  3758. &Result,
  3759. (LogonId == LOGONID_CURRENT) ? NtCurrentPeb()->SessionId : LogonId
  3760. );
  3761. Result = RtlNtStatusToDosError( Result );
  3762. if( !rc ) SetLastError(Result);
  3763. }
  3764. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3765. Result = RpcExceptionCode();
  3766. SetLastError( Result );
  3767. DBGPRINT(("RPC Exception %d\n",Result));
  3768. rc = FALSE;
  3769. }
  3770. RpcEndExcept
  3771. return( rc );
  3772. }
  3773. /*****************************************************************************
  3774. *
  3775. * _WinStationCallback
  3776. *
  3777. * Comment
  3778. *
  3779. * ENTRY:
  3780. * Param1 (input/output)
  3781. * Comments
  3782. *
  3783. * EXIT:
  3784. * ERROR_SUCCESS - no error
  3785. *
  3786. ****************************************************************************/
  3787. BOOLEAN WINAPI
  3788. _WinStationCallback(
  3789. HANDLE hServer,
  3790. ULONG LogonId,
  3791. LPWSTR pPhoneNumber
  3792. )
  3793. {
  3794. BOOLEAN rc;
  3795. DWORD Result;
  3796. DWORD Length;
  3797. WCHAR* rpcBuffer;
  3798. HANDLE_CURRENT_BINDING_NO_SERVER( hServer );
  3799. if( hServer == RPC_HANDLE_NO_SERVER ) {
  3800. return TRUE;
  3801. }
  3802. RpcTryExcept {
  3803. if( pPhoneNumber ) {
  3804. Length = (lstrlenW( pPhoneNumber ) + 1) * sizeof(WCHAR);
  3805. /*
  3806. * rpcBuffer is a workaround for 229753.
  3807. */
  3808. rpcBuffer = LocalAlloc(LPTR, Length * sizeof(WCHAR));
  3809. if (rpcBuffer != NULL) {
  3810. CopyMemory(rpcBuffer, pPhoneNumber, Length);
  3811. } else {
  3812. SetLastError(ERROR_OUTOFMEMORY);
  3813. return(FALSE);
  3814. }
  3815. } else {
  3816. Length = 0;
  3817. rpcBuffer = NULL;
  3818. }
  3819. rc = RpcWinStationCallback(
  3820. hServer,
  3821. &Result,
  3822. (LogonId == LOGONID_CURRENT) ?
  3823. NtCurrentPeb()->SessionId : LogonId,
  3824. rpcBuffer,
  3825. Length
  3826. );
  3827. Result = RtlNtStatusToDosError( Result );
  3828. }
  3829. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3830. Result = RpcExceptionCode();
  3831. DBGPRINT(("RPC Exception %d\n",Result));
  3832. rc = FALSE;
  3833. }
  3834. RpcEndExcept
  3835. if (rpcBuffer != NULL) {
  3836. LocalFree(rpcBuffer);
  3837. }
  3838. if( !rc ) SetLastError(Result);
  3839. return( rc );
  3840. }
  3841. /*****************************************************************************
  3842. *
  3843. * _WinStationBreakPoint
  3844. *
  3845. * Comment
  3846. *
  3847. * ENTRY:
  3848. * Param1 (input/output)
  3849. * Comments
  3850. *
  3851. * EXIT:
  3852. * ERROR_SUCCESS - no error
  3853. *
  3854. ****************************************************************************/
  3855. BOOLEAN WINAPI
  3856. _WinStationBreakPoint(
  3857. HANDLE hServer,
  3858. ULONG LogonId,
  3859. BOOLEAN KernelFlag
  3860. )
  3861. {
  3862. DWORD Result;
  3863. BOOLEAN rc;
  3864. HANDLE_CURRENT_BINDING( hServer );
  3865. RpcTryExcept {
  3866. rc = RpcWinStationBreakPoint(
  3867. hServer,
  3868. &Result,
  3869. (LogonId == LOGONID_CURRENT) ? NtCurrentPeb()->SessionId : LogonId,
  3870. KernelFlag
  3871. );
  3872. Result = RtlNtStatusToDosError( Result );
  3873. if( !rc ) SetLastError(Result);
  3874. }
  3875. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3876. Result = RpcExceptionCode();
  3877. SetLastError( Result );
  3878. DBGPRINT(("RPC Exception %d\n",Result));
  3879. rc = FALSE;
  3880. }
  3881. RpcEndExcept
  3882. return( rc );
  3883. }
  3884. /*****************************************************************************
  3885. *
  3886. * _WinStationReadRegistry
  3887. *
  3888. * Comment
  3889. *
  3890. * ENTRY:
  3891. * Param1 (input/output)
  3892. * Comments
  3893. *
  3894. * EXIT:
  3895. * ERROR_SUCCESS - no error
  3896. *
  3897. ****************************************************************************/
  3898. BOOLEAN WINAPI
  3899. _WinStationReadRegistry(
  3900. HANDLE hServer
  3901. )
  3902. {
  3903. DWORD Result;
  3904. BOOLEAN rc;
  3905. HANDLE_CURRENT_BINDING_NO_SERVER( hServer );
  3906. if( hServer == RPC_HANDLE_NO_SERVER ) {
  3907. return TRUE;
  3908. }
  3909. RpcTryExcept {
  3910. rc = RpcWinStationReadRegistry(
  3911. hServer,
  3912. &Result
  3913. );
  3914. Result = RtlNtStatusToDosError( Result );
  3915. if( !rc ) SetLastError(Result);
  3916. }
  3917. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3918. Result = RpcExceptionCode();
  3919. SetLastError( Result );
  3920. DBGPRINT(("RPC Exception %d\n",Result));
  3921. rc = FALSE;
  3922. }
  3923. RpcEndExcept
  3924. return( rc );
  3925. }
  3926. /*****************************************************************************
  3927. *
  3928. * _WinStationUpdateSettings
  3929. *
  3930. * Comment
  3931. *
  3932. * ENTRY:
  3933. * Param1 (input/output)
  3934. * Comments
  3935. *
  3936. * EXIT:
  3937. * ERROR_SUCCESS - no error
  3938. *
  3939. ****************************************************************************/
  3940. BOOLEAN WINAPI
  3941. _WinStationUpdateSettings(
  3942. HANDLE hServer,
  3943. WINSTATIONUPDATECFGCLASS SettingsClass,
  3944. DWORD SettingsParameters
  3945. )
  3946. {
  3947. DWORD Result;
  3948. BOOLEAN rc;
  3949. HANDLE_CURRENT_BINDING_NO_SERVER( hServer );
  3950. if( hServer == RPC_HANDLE_NO_SERVER ) {
  3951. return TRUE;
  3952. }
  3953. RpcTryExcept {
  3954. rc = RpcWinStationUpdateSettings(
  3955. hServer,
  3956. &Result,
  3957. (DWORD)SettingsClass,
  3958. SettingsParameters
  3959. );
  3960. Result = RtlNtStatusToDosError( Result );
  3961. if( !rc ) SetLastError(Result);
  3962. }
  3963. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3964. Result = RpcExceptionCode();
  3965. SetLastError( Result );
  3966. DBGPRINT(("RPC Exception %d\n",Result));
  3967. rc = FALSE;
  3968. }
  3969. RpcEndExcept
  3970. return( rc );
  3971. }
  3972. /*****************************************************************************
  3973. *
  3974. * _WinStationReInitializeSecurity
  3975. *
  3976. * Comment
  3977. *
  3978. * ENTRY:
  3979. * Param1 (input/output)
  3980. * Comments
  3981. *
  3982. * EXIT:
  3983. * ERROR_SUCCESS - no error
  3984. *
  3985. ****************************************************************************/
  3986. BOOLEAN WINAPI
  3987. _WinStationReInitializeSecurity(
  3988. HANDLE hServer
  3989. )
  3990. {
  3991. DWORD Result;
  3992. BOOLEAN rc;
  3993. HANDLE_CURRENT_BINDING_NO_SERVER( hServer );
  3994. if( hServer == RPC_HANDLE_NO_SERVER ) {
  3995. return TRUE;
  3996. }
  3997. RpcTryExcept {
  3998. rc = RpcWinStationReInitializeSecurity(
  3999. hServer,
  4000. &Result
  4001. );
  4002. Result = RtlNtStatusToDosError( Result );
  4003. if( !rc ) SetLastError(Result);
  4004. }
  4005. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4006. Result = RpcExceptionCode();
  4007. SetLastError( Result );
  4008. DBGPRINT(("RPC Exception %d\n",Result));
  4009. rc = FALSE;
  4010. }
  4011. RpcEndExcept
  4012. return( rc );
  4013. }
  4014. /*****************************************************************************
  4015. *
  4016. * _WinStationWaitForConnect
  4017. *
  4018. * Comment
  4019. *
  4020. * ENTRY:
  4021. * Param1 (input/output)
  4022. * Comments
  4023. *
  4024. * EXIT:
  4025. * ERROR_SUCCESS - no error
  4026. *
  4027. ****************************************************************************/
  4028. BOOLEAN WINAPI
  4029. _WinStationWaitForConnect(
  4030. VOID
  4031. )
  4032. {
  4033. DWORD Result;
  4034. BOOLEAN rc;
  4035. HANDLE hServer = SERVERNAME_CURRENT;
  4036. HANDLE_CURRENT_BINDING_NO_SERVER( hServer );
  4037. if( hServer == RPC_HANDLE_NO_SERVER ) {
  4038. if (NtCurrentPeb()->SessionId != 0) {
  4039. DbgPrint("hServer == RPC_HANDLE_NO_SERVER for SessionId %d\n",NtCurrentPeb()->SessionId);
  4040. ASSERT(FALSE);
  4041. return FALSE;
  4042. } else {
  4043. return TRUE;
  4044. }
  4045. }
  4046. RpcTryExcept {
  4047. rc = RpcWinStationWaitForConnect(
  4048. hServer,
  4049. &Result,
  4050. NtCurrentPeb()->SessionId,
  4051. GetCurrentProcessId()
  4052. );
  4053. Result = RtlNtStatusToDosError( Result );
  4054. if( !rc ) SetLastError(Result);
  4055. }
  4056. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4057. Result = RpcExceptionCode();
  4058. SetLastError( Result );
  4059. DBGPRINT(("RPC Exception %d\n",Result));
  4060. rc = FALSE;
  4061. }
  4062. RpcEndExcept
  4063. return( rc );
  4064. }
  4065. /*****************************************************************************
  4066. *
  4067. * _WinStationNotifyLogon
  4068. *
  4069. * Comment
  4070. *
  4071. * ENTRY:
  4072. * Param1 (input/output)
  4073. * Comments
  4074. *
  4075. * EXIT:
  4076. * ERROR_SUCCESS - no error
  4077. *
  4078. ****************************************************************************/
  4079. BOOLEAN WINAPI
  4080. _WinStationNotifyLogon(
  4081. BOOLEAN fUserIsAdmin,
  4082. HANDLE UserToken,
  4083. PWCHAR pDomain,
  4084. PWCHAR pUserName,
  4085. PWCHAR pPassword,
  4086. UCHAR Seed,
  4087. PUSERCONFIGW pUserConfig
  4088. )
  4089. {
  4090. BOOLEAN rc;
  4091. DWORD Result;
  4092. DWORD DomainLength;
  4093. DWORD UserNameLength;
  4094. DWORD PasswordLength;
  4095. HANDLE hServer = SERVERNAME_CURRENT;
  4096. HANDLE ReadyEventHandle;
  4097. DWORD TermSrvWaitTime = 180 * 1000; // 3 Minutes
  4098. WCHAR* rpcBuffer1 = NULL;
  4099. WCHAR* rpcBuffer2 = NULL;
  4100. WCHAR* rpcBuffer3 = NULL;
  4101. HANDLE_CURRENT_BINDING_NO_SERVER( hServer );
  4102. if( hServer == RPC_HANDLE_NO_SERVER ) {
  4103. return TRUE;
  4104. }
  4105. //
  4106. // Wait for the TermSrvReadyEvent to be set by TERMSRV.EXE. This
  4107. // event indicates that TermSrv is initialized to the point that
  4108. // the data used by _WinStationNotifyLogon() is available.
  4109. //
  4110. ReadyEventHandle = CreateEvent(NULL, TRUE, FALSE,
  4111. TEXT("Global\\TermSrvReadyEvent"));
  4112. if (ReadyEventHandle != NULL)
  4113. {
  4114. if (WaitForSingleObject(ReadyEventHandle, TermSrvWaitTime) != 0)
  4115. {
  4116. DBGPRINT(("WinLogon: Wait for ReadyEventHandle failed\n"));
  4117. }
  4118. CloseHandle(ReadyEventHandle);
  4119. }
  4120. else
  4121. {
  4122. DBGPRINT(("WinLogon: Create failed for ReadyEventHandle\n"));
  4123. }
  4124. RpcTryExcept {
  4125. if( pDomain ) {
  4126. DomainLength = (lstrlenW( pDomain ) + 1) * sizeof(WCHAR);
  4127. /*
  4128. * rpcBuffer[1,2,3] is a workaround for 229753.
  4129. */
  4130. rpcBuffer1 = LocalAlloc(LPTR, DomainLength * sizeof(WCHAR));
  4131. if (rpcBuffer1 != NULL) {
  4132. CopyMemory(rpcBuffer1, pDomain, DomainLength);
  4133. } else {
  4134. Result = ERROR_OUTOFMEMORY;
  4135. rc = FALSE;
  4136. goto Error;
  4137. }
  4138. } else {
  4139. DomainLength = 0;
  4140. rpcBuffer1 = NULL;
  4141. }
  4142. if( pUserName ) {
  4143. UserNameLength = (lstrlenW( pUserName ) + 1) * sizeof(WCHAR);
  4144. rpcBuffer2 = LocalAlloc(LPTR, UserNameLength * sizeof(WCHAR));
  4145. if (rpcBuffer2 != NULL) {
  4146. CopyMemory(rpcBuffer2, pUserName, UserNameLength);
  4147. } else {
  4148. Result = ERROR_OUTOFMEMORY;
  4149. rc = FALSE;
  4150. goto Error;
  4151. }
  4152. } else {
  4153. UserNameLength = 0;
  4154. rpcBuffer2 = NULL;
  4155. }
  4156. if( pPassword ) {
  4157. PasswordLength = (lstrlenW( pPassword ) + 1) * sizeof(WCHAR);
  4158. rpcBuffer3 = LocalAlloc(LPTR, PasswordLength * sizeof(WCHAR));
  4159. if (rpcBuffer3 != NULL) {
  4160. CopyMemory(rpcBuffer3, pPassword, PasswordLength);
  4161. } else {
  4162. Result = ERROR_OUTOFMEMORY;
  4163. rc = FALSE;
  4164. goto Error;
  4165. }
  4166. } else {
  4167. PasswordLength = 0;
  4168. rpcBuffer3 = NULL;
  4169. }
  4170. rc = RpcWinStationNotifyLogon(
  4171. hServer,
  4172. &Result,
  4173. NtCurrentPeb()->SessionId,
  4174. GetCurrentProcessId(),
  4175. fUserIsAdmin,
  4176. (DWORD)(INT_PTR)UserToken,
  4177. rpcBuffer1,
  4178. DomainLength,
  4179. rpcBuffer2,
  4180. UserNameLength,
  4181. rpcBuffer3,
  4182. PasswordLength,
  4183. Seed,
  4184. (PCHAR)pUserConfig,
  4185. sizeof(*pUserConfig)
  4186. );
  4187. if( !rc ) {
  4188. Result = RtlNtStatusToDosError( Result );
  4189. }
  4190. }
  4191. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4192. Result = RpcExceptionCode();
  4193. DBGPRINT(("RPC Exception %d\n",Result));
  4194. rc = FALSE;
  4195. }
  4196. RpcEndExcept
  4197. Error:
  4198. if (rpcBuffer1 != NULL) {
  4199. LocalFree(rpcBuffer1);
  4200. }
  4201. if (rpcBuffer2 != NULL) {
  4202. LocalFree(rpcBuffer2);
  4203. }
  4204. if (rpcBuffer3 != NULL) {
  4205. LocalFree(rpcBuffer3);
  4206. }
  4207. if( !rc ) SetLastError(Result);
  4208. return( rc );
  4209. }
  4210. /*****************************************************************************
  4211. *
  4212. * _WinStationNotifyLogoff
  4213. *
  4214. * Comment
  4215. *
  4216. * ENTRY:
  4217. * Param1 (input/output)
  4218. * Comments
  4219. *
  4220. * EXIT:
  4221. * ERROR_SUCCESS - no error
  4222. *
  4223. ****************************************************************************/
  4224. BOOLEAN WINAPI
  4225. _WinStationNotifyLogoff(
  4226. VOID
  4227. )
  4228. {
  4229. DWORD Result;
  4230. BOOLEAN rc;
  4231. HANDLE hServer = SERVERNAME_CURRENT;
  4232. HANDLE_CURRENT_BINDING_NO_SERVER( hServer );
  4233. if( hServer == RPC_HANDLE_NO_SERVER ) {
  4234. return TRUE;
  4235. }
  4236. RpcTryExcept {
  4237. rc = RpcWinStationNotifyLogoff(
  4238. hServer,
  4239. NtCurrentPeb()->SessionId,
  4240. GetCurrentProcessId(),
  4241. &Result
  4242. );
  4243. Result = RtlNtStatusToDosError( Result );
  4244. if( !rc ) SetLastError(Result);
  4245. }
  4246. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4247. Result = RpcExceptionCode();
  4248. SetLastError( Result );
  4249. DBGPRINT(("RPC Exception %d\n",Result));
  4250. rc = FALSE;
  4251. }
  4252. RpcEndExcept
  4253. return( rc );
  4254. }
  4255. /*****************************************************************************
  4256. *
  4257. * _WinStationNotifyNewSession
  4258. *
  4259. * Comment
  4260. *
  4261. * ENTRY:
  4262. * Param1 (input/output)
  4263. * Comments
  4264. *
  4265. * EXIT:
  4266. * ERROR_SUCCESS - no error
  4267. *
  4268. ****************************************************************************/
  4269. BOOLEAN WINAPI
  4270. _WinStationNotifyNewSession(
  4271. HANDLE hServer,
  4272. ULONG LogonId
  4273. )
  4274. {
  4275. DWORD Result;
  4276. BOOLEAN rc;
  4277. //
  4278. // If the local machine has no TSRPC interface running, this is most
  4279. // likely the console winlogon attempting to logon before termsrv.exe
  4280. // is running.
  4281. //
  4282. HANDLE_CURRENT_BINDING_NO_SERVER( hServer );
  4283. if( hServer == RPC_HANDLE_NO_SERVER )
  4284. {
  4285. return(TRUE);
  4286. }
  4287. RpcTryExcept {
  4288. rc = RpcWinStationNotifyNewSession(
  4289. hServer,
  4290. &Result,
  4291. (LogonId == LOGONID_CURRENT) ? NtCurrentPeb()->SessionId : LogonId
  4292. );
  4293. Result = RtlNtStatusToDosError( Result );
  4294. if( !rc ) SetLastError(Result);
  4295. }
  4296. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4297. Result = RpcExceptionCode();
  4298. SetLastError( Result );
  4299. DBGPRINT(("RPC Exception %d\n",Result));
  4300. rc = FALSE;
  4301. }
  4302. RpcEndExcept
  4303. return( rc );
  4304. }
  4305. /*****************************************************************************
  4306. *
  4307. * _RpcServerNWLogonSetAdmin
  4308. *
  4309. * Comment
  4310. *
  4311. * ENTRY:
  4312. * Param1 (input/output)
  4313. * Comments
  4314. *
  4315. * EXIT:
  4316. * ERROR_SUCCESS - no error
  4317. *
  4318. ****************************************************************************/
  4319. BOOLEAN WINAPI
  4320. _NWLogonSetAdmin(
  4321. HANDLE hServer,
  4322. PWCHAR pServerName,
  4323. PNWLOGONADMIN pNWLogon
  4324. )
  4325. {
  4326. BOOLEAN rc;
  4327. DWORD Result;
  4328. DWORD ServerNameLength;
  4329. WCHAR* rpcBuffer;
  4330. HANDLE_CURRENT_BINDING( hServer );
  4331. if (pServerName) {
  4332. ServerNameLength = (lstrlenW(pServerName) + 1) * sizeof(WCHAR);
  4333. /*
  4334. * rpcBuffer is a workaround for bug 229753. The bug can't be fixed
  4335. * completely without breaking TS4 clients.
  4336. */
  4337. rpcBuffer = LocalAlloc(LPTR, ServerNameLength * sizeof(WCHAR));
  4338. if (rpcBuffer != NULL) {
  4339. CopyMemory(rpcBuffer, pServerName, ServerNameLength);
  4340. } else {
  4341. SetLastError(ERROR_OUTOFMEMORY);
  4342. return(FALSE);
  4343. }
  4344. } else {
  4345. ServerNameLength = 0;
  4346. rpcBuffer = NULL;
  4347. }
  4348. RpcTryExcept {
  4349. rc = RpcServerNWLogonSetAdmin(
  4350. hServer,
  4351. &Result,
  4352. rpcBuffer,
  4353. ServerNameLength,
  4354. (PCHAR)pNWLogon,
  4355. sizeof(NWLOGONADMIN)
  4356. );
  4357. Result = RtlNtStatusToDosError( Result );
  4358. }
  4359. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4360. Result = RpcExceptionCode();
  4361. DBGPRINT(("RPC Exception %d\n",Result));
  4362. rc = FALSE;
  4363. }
  4364. RpcEndExcept
  4365. if (rpcBuffer != NULL) {
  4366. LocalFree(rpcBuffer);
  4367. }
  4368. if( !rc ) SetLastError(Result);
  4369. return( rc );
  4370. }
  4371. /*****************************************************************************
  4372. *
  4373. * _RpcServerNWLogonQueryAdmin
  4374. *
  4375. * Comment
  4376. *
  4377. * ENTRY:
  4378. * Param1 (input/output)
  4379. * Comments
  4380. *
  4381. * EXIT:
  4382. * ERROR_SUCCESS - no error
  4383. *
  4384. ****************************************************************************/
  4385. BOOLEAN WINAPI
  4386. _NWLogonQueryAdmin(
  4387. HANDLE hServer,
  4388. PWCHAR pServerName,
  4389. PNWLOGONADMIN pNWLogon
  4390. )
  4391. {
  4392. BOOLEAN rc;
  4393. DWORD Result;
  4394. DWORD ServerNameLength;
  4395. WCHAR* rpcBuffer;
  4396. HANDLE_CURRENT_BINDING( hServer );
  4397. if (pServerName) {
  4398. ServerNameLength = (lstrlenW(pServerName) + 1) * sizeof(WCHAR);
  4399. /*
  4400. * rpcBuffer is a workaround for bug 229753. The bug can't be fixed
  4401. * completely without breaking TS4 clients.
  4402. */
  4403. rpcBuffer = LocalAlloc(LPTR, ServerNameLength * sizeof(WCHAR));
  4404. if (rpcBuffer != NULL) {
  4405. CopyMemory(rpcBuffer, pServerName, ServerNameLength);
  4406. } else {
  4407. SetLastError(ERROR_OUTOFMEMORY);
  4408. return(FALSE);
  4409. }
  4410. } else {
  4411. ServerNameLength = 0;
  4412. rpcBuffer = NULL;
  4413. }
  4414. RpcTryExcept {
  4415. rc = RpcServerNWLogonQueryAdmin(
  4416. hServer,
  4417. &Result,
  4418. rpcBuffer,
  4419. ServerNameLength,
  4420. (PCHAR)pNWLogon,
  4421. sizeof(NWLOGONADMIN)
  4422. );
  4423. Result = RtlNtStatusToDosError( Result );
  4424. }
  4425. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4426. Result = RpcExceptionCode();
  4427. DBGPRINT(("RPC Exception %d\n",Result));
  4428. rc = FALSE;
  4429. }
  4430. RpcEndExcept
  4431. if (rpcBuffer != NULL) {
  4432. LocalFree(rpcBuffer);
  4433. }
  4434. if( !rc ) SetLastError(Result);
  4435. return( rc );
  4436. }
  4437. /*******************************************************************************
  4438. *
  4439. * _WinStationCheckForApplicationName
  4440. *
  4441. * Handles published applications.
  4442. *
  4443. * ENTRY:
  4444. *
  4445. * EXIT:
  4446. *
  4447. * TRUE -- The query succeeded, and the buffer contains the requested data.
  4448. *
  4449. * FALSE -- The operation failed. Extended error status is available
  4450. * using GetLastError.
  4451. *
  4452. ******************************************************************************/
  4453. BOOLEAN
  4454. _WinStationCheckForApplicationName(
  4455. HANDLE hServer,
  4456. ULONG LogonId,
  4457. PWCHAR pUserName,
  4458. DWORD UserNameSize,
  4459. PWCHAR pDomain,
  4460. DWORD DomainSize,
  4461. PWCHAR pPassword,
  4462. DWORD *pPasswordSize,
  4463. DWORD MaxPasswordSize,
  4464. PCHAR pSeed,
  4465. PBOOLEAN pfPublished,
  4466. PBOOLEAN pfAnonymous
  4467. )
  4468. {
  4469. DWORD Result;
  4470. BOOLEAN rc;
  4471. WCHAR* rpcBufferName;
  4472. WCHAR* rpcBufferDomain;
  4473. WCHAR* rpcBufferPassword;
  4474. HANDLE_CURRENT_BINDING( hServer );
  4475. // Since, due to legacy clients, we cannot change the interface,
  4476. // as a workarround to bug#265954, we double the size of RPC Buffers.
  4477. rpcBufferName = LocalAlloc(LPTR, UserNameSize * sizeof(WCHAR));
  4478. if (rpcBufferName != NULL) {
  4479. CopyMemory(rpcBufferName, pUserName, UserNameSize);
  4480. } else {
  4481. SetLastError(ERROR_OUTOFMEMORY);
  4482. return(FALSE);
  4483. }
  4484. rpcBufferDomain = LocalAlloc(LPTR, DomainSize * sizeof(WCHAR));
  4485. if (rpcBufferDomain != NULL) {
  4486. CopyMemory(rpcBufferDomain, pDomain, DomainSize);
  4487. } else {
  4488. LocalFree(rpcBufferName);
  4489. SetLastError(ERROR_OUTOFMEMORY);
  4490. return(FALSE);
  4491. }
  4492. rpcBufferPassword = LocalAlloc(LPTR,MaxPasswordSize * sizeof(WCHAR));
  4493. if (rpcBufferPassword != NULL) {
  4494. CopyMemory(rpcBufferPassword, pPassword, MaxPasswordSize);
  4495. } else {
  4496. LocalFree(rpcBufferName);
  4497. LocalFree(rpcBufferDomain);
  4498. SetLastError(ERROR_OUTOFMEMORY);
  4499. return(FALSE);
  4500. }
  4501. RpcTryExcept {
  4502. rc = RpcWinStationCheckForApplicationName(
  4503. hServer,
  4504. &Result,
  4505. LogonId,
  4506. rpcBufferName,
  4507. UserNameSize,
  4508. rpcBufferDomain,
  4509. DomainSize,
  4510. rpcBufferPassword,
  4511. pPasswordSize,
  4512. MaxPasswordSize,
  4513. pSeed,
  4514. pfPublished,
  4515. pfAnonymous
  4516. );
  4517. Result = RtlNtStatusToDosError( Result );
  4518. }
  4519. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4520. Result = RpcExceptionCode();
  4521. DBGPRINT(("RPC Exception %d\n",Result));
  4522. rc = FALSE;
  4523. }
  4524. RpcEndExcept
  4525. LocalFree(rpcBufferName);
  4526. LocalFree(rpcBufferDomain);
  4527. LocalFree(rpcBufferPassword);
  4528. if( !rc ) SetLastError(Result);
  4529. return( rc );
  4530. }
  4531. /*******************************************************************************
  4532. *
  4533. * _WinStationGetApplicationInfo
  4534. *
  4535. * Gets info about published applications.
  4536. *
  4537. * ENTRY:
  4538. *
  4539. * EXIT:
  4540. *
  4541. * TRUE -- The query succeeded, and the buffer contains the requested data.
  4542. *
  4543. * FALSE -- The operation failed. Extended error status is available
  4544. * using GetLastError.
  4545. *
  4546. ******************************************************************************/
  4547. BOOLEAN
  4548. _WinStationGetApplicationInfo(
  4549. HANDLE hServer,
  4550. ULONG LogonId,
  4551. PBOOLEAN pfPublished,
  4552. PBOOLEAN pfAnonymous
  4553. )
  4554. {
  4555. DWORD Result;
  4556. BOOLEAN rc;
  4557. HANDLE_CURRENT_BINDING( hServer );
  4558. RpcTryExcept {
  4559. rc = RpcWinStationGetApplicationInfo(
  4560. hServer,
  4561. &Result,
  4562. LogonId,
  4563. pfPublished,
  4564. pfAnonymous
  4565. );
  4566. Result = RtlNtStatusToDosError( Result );
  4567. if( !rc ) SetLastError(Result);
  4568. }
  4569. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4570. Result = RpcExceptionCode();
  4571. SetLastError( Result );
  4572. DBGPRINT(("RPC Exception %d\n",Result));
  4573. rc = FALSE;
  4574. }
  4575. RpcEndExcept
  4576. return( rc );
  4577. }
  4578. /*******************************************************************************
  4579. *
  4580. * WinStationNtsdDebug
  4581. *
  4582. * Set up a debug connection for ntsd
  4583. *
  4584. * ENTRY:
  4585. *
  4586. * EXIT:
  4587. *
  4588. * TRUE -- The function succeeds
  4589. *
  4590. * FALSE -- The operation failed. Extended error status is available
  4591. * using GetLastError.
  4592. *
  4593. ******************************************************************************/
  4594. BOOLEAN
  4595. WinStationNtsdDebug(
  4596. ULONG LogonId,
  4597. LONG ProcessId,
  4598. ULONG DbgProcessId,
  4599. ULONG DbgThreadId,
  4600. PVOID AttachCompletionRoutine
  4601. )
  4602. {
  4603. DWORD Result;
  4604. BOOLEAN rc;
  4605. HANDLE hServer = SERVERNAME_CURRENT;
  4606. NTSDDBGPRINT(("In WinStationNtsdDebug command\n"));
  4607. HANDLE_CURRENT_BINDING( hServer );
  4608. RpcTryExcept {
  4609. rc = RpcWinStationNtsdDebug(
  4610. hServer,
  4611. &Result,
  4612. LogonId,
  4613. ProcessId,
  4614. DbgProcessId,
  4615. DbgThreadId,
  4616. (DWORD_PTR) AttachCompletionRoutine
  4617. );
  4618. DbgPrint("RpcWinStationNtsdDebug: returned 0x%x\n", rc);
  4619. Result = RtlNtStatusToDosError( Result );
  4620. if( !rc ) SetLastError(Result);
  4621. }
  4622. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4623. Result = RpcExceptionCode();
  4624. SetLastError( Result );
  4625. DBGPRINT(("RPC Exception %d\n",Result));
  4626. rc = FALSE;
  4627. }
  4628. RpcEndExcept
  4629. NTSDDBGPRINT(("WinStationNtsdDebug returning %d\n", rc));
  4630. return( rc );
  4631. }
  4632. /*******************************************************************************
  4633. *
  4634. * WinStationGetTermSrvCountersValue
  4635. *
  4636. * Gets TermSrv Counters value
  4637. *
  4638. * ENTRY:
  4639. *
  4640. * EXIT:
  4641. *
  4642. * TRUE -- The query succeeded, and the buffer contains the requested data.
  4643. *
  4644. * FALSE -- The operation failed. Extended error status is available
  4645. * using GetLastError.
  4646. *
  4647. ******************************************************************************/
  4648. BOOLEAN
  4649. WinStationGetTermSrvCountersValue(
  4650. HANDLE hServer,
  4651. ULONG dwEntries,
  4652. PVOID pCounter
  4653. )
  4654. {
  4655. DWORD Result;
  4656. BOOLEAN rc;
  4657. HANDLE_CURRENT_BINDING( hServer );
  4658. RpcTryExcept {
  4659. rc = RpcWinStationGetTermSrvCountersValue(
  4660. hServer,
  4661. &Result,
  4662. dwEntries,
  4663. (PTS_COUNTER)pCounter
  4664. );
  4665. Result = RtlNtStatusToDosError( Result );
  4666. if( !rc ) SetLastError(Result);
  4667. }
  4668. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4669. Result = RpcExceptionCode();
  4670. SetLastError( Result );
  4671. DBGPRINT(("RPC Exception %d\n",Result));
  4672. rc = FALSE;
  4673. }
  4674. RpcEndExcept
  4675. return( rc );
  4676. }
  4677. /*****************************************************************************
  4678. *
  4679. * WinStationBroadcastSystemMessageWorker
  4680. *
  4681. * Perform the the equivalent to Window's standard API BroadcastSystemMessage to
  4682. * all Hydra sessions. This is an exported function, at least used by the PNP manager to
  4683. * send a device change message to all sessions.
  4684. *
  4685. * LIMITATIONS:
  4686. * some messages, such as WM_COPYDATA send an address pointer to some user data as lParam.
  4687. * In this API. the only such case that is currently supported is for WM_DEVICECHANGE
  4688. * No error code will be returned if you try to use such an unsupported message, simply the
  4689. * lParam will be ignored.
  4690. *
  4691. * ENTRY:
  4692. * hServer
  4693. * this is a handle which identifies a Hydra server. For the local server, hServer
  4694. * should be set to SERVERNAME_CURRENT
  4695. *
  4696. * sendToAllWinstations
  4697. * This should be set to TRUE if you want to broadcast message to all winstations
  4698. *
  4699. * sessionID,
  4700. * if sendToAllWinstations = FALSE, then message is only sent to only the
  4701. * winstation with the specified sessionID
  4702. *
  4703. * timeOut
  4704. * set this to the amount of time you are willing to wait to get a response
  4705. * from the specified winstation. Even though Window's SendMessage API
  4706. * is blocking, the call from this side MUST choose how long it is willing to
  4707. * wait for a response.
  4708. *
  4709. * dwFlags
  4710. * see MSDN on BroadcastSystemMessage(). Be aware that POST is not allowed on any
  4711. * where the wparam is a pointer to some user mode data structure.
  4712. * For more info, see ntos\...\client\ntstubs.c
  4713. *
  4714. * lpdwRecipients
  4715. * Pointer to a variable that contains and receives information about the recipients of the message.
  4716. * see MSDN for more info
  4717. *
  4718. * uiMessage
  4719. * the window's message to send, limited to WM_DEVICECHANGE and WM_SETTINGSCHANGE
  4720. * at this time.
  4721. *
  4722. * wParam
  4723. * first message param
  4724. *
  4725. * lParam
  4726. * second message parameter
  4727. *
  4728. * pResponse
  4729. * this is the response to the message sent, see MSDN
  4730. *
  4731. * idOfSessionBeingIgnored
  4732. * if -1, then no sessions are ignored. Else, the id of the session passed in is ignored
  4733. *
  4734. * EXIT:
  4735. * TRUE if all went well or
  4736. * FALSE if something went wrong.
  4737. *
  4738. * WARNINGs:
  4739. * since the RPC call never blocks, you need to specify a reasonable timeOut if you want to wait for
  4740. * a response. Please remember that since this message is being sent to all winstations, the timeOut value
  4741. * will be on per-winstation.
  4742. *
  4743. * Also, Do not use flag BSF_POSTMESSAGE, since an app/window on a
  4744. * winstation is not setup to send back a response to the
  4745. * query in an asynchronous fashion.
  4746. * You must wait for the response (until the time out period).
  4747. *
  4748. * Comments:
  4749. * For more info, please see MSDN for BroadcastSystemMessage()
  4750. *
  4751. ****************************************************************************/
  4752. LONG WinStationBroadcastSystemMessageWorker(
  4753. HANDLE hServer,
  4754. BOOL sendToAllWinstations,
  4755. ULONG sessionID,
  4756. ULONG timeOut,
  4757. DWORD dwFlags,
  4758. DWORD *lpdwRecipients,
  4759. ULONG uiMessage,
  4760. WPARAM wParam,
  4761. LPARAM lParam,
  4762. LONG *pResponse, // this is the response to the message sent
  4763. DWORD idOfSessionBeingIgnored
  4764. )
  4765. {
  4766. DWORD Result = ERROR_SUCCESS;
  4767. LONG rc;
  4768. LONG status;
  4769. ULONG i;
  4770. LONG response=0;
  4771. PLOGONID pWd;
  4772. ULONG ByteCount, Index;
  4773. UINT WdCount;
  4774. // these are used for PNP messages
  4775. PBYTE rpcBuffer=NULL;
  4776. ULONG bufferSize=0;
  4777. ULONG maxSize;
  4778. BOOLEAN fBufferHasValidData = FALSE;
  4779. // Since the PNP message uses the lparam to pass the address of a user memory location, we
  4780. // need to handle this by creating our own copy of that data, and then pass it to
  4781. // termServ
  4782. // we may want to make this general for the future... hence use switch
  4783. switch( uiMessage )
  4784. {
  4785. // if this is a PNP message
  4786. case WM_DEVICECHANGE:
  4787. if ( lParam ) // see if the PNP message has a pointer to some user data
  4788. {
  4789. bufferSize = ( (DEV_BROADCAST_HDR *)(lParam))->dbch_size;
  4790. rpcBuffer = LocalAlloc( LPTR, bufferSize );
  4791. if ( rpcBuffer )
  4792. {
  4793. // copy from user-space into our local rpc buffer
  4794. CopyMemory(rpcBuffer, (PBYTE)lParam, bufferSize );
  4795. fBufferHasValidData = TRUE;
  4796. }
  4797. else
  4798. {
  4799. SetLastError( ERROR_OUTOFMEMORY );
  4800. return ( FALSE );
  4801. }
  4802. }
  4803. break;
  4804. // if this is a settings change message the system-CPL sends out
  4805. // when an Admin changes the system env vars...
  4806. case WM_SETTINGCHANGE:
  4807. if ( lParam ) // see if message has a string data
  4808. {
  4809. // put some artificial limit on how large a buffer we are willing to use
  4810. // in order to protect against malicious use of this api
  4811. maxSize = 4096;
  4812. bufferSize = lstrlenW( (PWCHAR) lParam ) * sizeof( WCHAR );
  4813. if ( bufferSize < maxSize )
  4814. {
  4815. rpcBuffer = LocalAlloc( LPTR, bufferSize );
  4816. if ( rpcBuffer )
  4817. {
  4818. // copy from user-space into our local rpc buffer
  4819. CopyMemory(rpcBuffer, (PBYTE) lParam, bufferSize );
  4820. fBufferHasValidData = TRUE;
  4821. }
  4822. else
  4823. {
  4824. SetLastError( ERROR_OUTOFMEMORY );
  4825. return ( FALSE );
  4826. }
  4827. }
  4828. else
  4829. {
  4830. // we have too many
  4831. // vars in the user's profile.
  4832. KdPrint(("lParam length too big = %d \n", bufferSize));
  4833. break;
  4834. SetLastError( ERROR_MESSAGE_EXCEEDS_MAX_SIZE );
  4835. return ( FALSE );
  4836. }
  4837. }
  4838. break;
  4839. }
  4840. //
  4841. // if the rpcBuffer is still empty (meaning, this was not a PNP message), we must fill it up
  4842. // with some bogus data, otherwise, we will get an RPC error of RPC_X_NULL_REF_POINTER
  4843. // (error code of 1780). It looks like Rpc does not check the
  4844. // bufferSize value, and it just throws an exception if the buffer is NULL.
  4845. //
  4846. if ( !rpcBuffer )
  4847. {
  4848. rpcBuffer = LocalAlloc( LPTR, sizeof(UINT) );
  4849. if (!rpcBuffer)
  4850. {
  4851. SetLastError( ERROR_OUTOFMEMORY );
  4852. return ( FALSE );
  4853. }
  4854. bufferSize = sizeof(UINT);
  4855. fBufferHasValidData = FALSE; // note that this is set to FALSE, which means, the recepient will
  4856. // not use the buffer. We do free the alloc below in either case.
  4857. }
  4858. HANDLE_CURRENT_BINDING_BUFFER( hServer, rpcBuffer );
  4859. WdCount = 1000;
  4860. pWd = NULL; // it will be allocated by Winstation Enumerate()
  4861. rc = WinStationEnumerate( hServer, &pWd, &WdCount );
  4862. /*
  4863. * Do not use this flag, since no process on the session side can respond back to a console process
  4864. * thru the post message mechanism, since there is no session ID abstraction in that call.
  4865. */
  4866. dwFlags &= ~BSF_POSTMESSAGE;
  4867. if ( rc != TRUE )
  4868. {
  4869. status = GetLastError();
  4870. DBGPRINT(( "WinstationEnumerate = %d, failed at %s %d\n", status,__FILE__,__LINE__));
  4871. if ( pWd )
  4872. {
  4873. WinStationFreeMemory(pWd);
  4874. }
  4875. return(FALSE);
  4876. }
  4877. //
  4878. // the loop for sending data to each winstation
  4879. //
  4880. for ( i=0; i < WdCount; i++ )
  4881. {
  4882. // id of the session being ignored
  4883. if ( pWd[i].SessionId == idOfSessionBeingIgnored)
  4884. continue;
  4885. // either send to all winstations, or to a specific winstation
  4886. if ( sendToAllWinstations || pWd[i].SessionId == sessionID )
  4887. {
  4888. // don't send message to any winstation unless it is either Active or in the disconnect state
  4889. if ( pWd[i].State == State_Active ||
  4890. pWd[i].State == State_Disconnected)
  4891. {
  4892. RpcTryExcept
  4893. {
  4894. rc = RpcWinStationBroadcastSystemMessage(
  4895. hServer,
  4896. pWd[i].SessionId,
  4897. timeOut,
  4898. dwFlags,
  4899. lpdwRecipients,
  4900. uiMessage,
  4901. wParam,
  4902. lParam,
  4903. rpcBuffer,
  4904. bufferSize,
  4905. fBufferHasValidData,
  4906. &response );
  4907. DBGPRINT(("done with call RpcWinStationBroadcastSystemMessage() for sessionID= %d\n", pWd[i].SessionId ));
  4908. *pResponse |= response; // keep an OR of all return values
  4909. // @@@
  4910. // if response is -1 from any winstation, maybe we should give up and return ?
  4911. }
  4912. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  4913. {
  4914. Result = RpcExceptionCode();
  4915. DBGPRINT(("RPC Exception %d in RpcWinStationBroadcastSystemMessage() for sessionID = %d \n",Result, sessionID));
  4916. rc = FALSE; // change rc to FALSE
  4917. break; // get out of the for-loop, we have a problem with at least one of the winstations
  4918. }
  4919. RpcEndExcept
  4920. } // end if winstation state check
  4921. } // if ( sendToAllWinstations || pWd[i].SessionId == sessionID )
  4922. } // end of the for loop
  4923. WinStationFreeMemory(pWd);
  4924. LocalFree( rpcBuffer );
  4925. SetLastError( Result );
  4926. return( rc );
  4927. }
  4928. /*************************************************************************
  4929. * *
  4930. * This struct is used to pack data passed into a workder thread which is *
  4931. * altimetly passed to WinStationBroadcastSystemMessageWorker() *
  4932. * *
  4933. *************************************************************************/
  4934. typedef struct {
  4935. HANDLE hServer;
  4936. BOOL sendToAllWinstations;
  4937. ULONG sessionID;
  4938. ULONG timeOut;
  4939. DWORD dwFlags;
  4940. DWORD *lpdwRecipients;
  4941. ULONG uiMessage;
  4942. WPARAM wParam;
  4943. LPARAM lParam;
  4944. LONG *pResponse;
  4945. DWORD idOfSessionBeingIgnored ;
  4946. } BSM_DATA_PACKAGE;
  4947. /***********************************************************************************************
  4948. * *
  4949. * This is a workder thread used to make a call into WinStationBroadcastSystemMessageWorker() *
  4950. * The reason for this is in certain cases, we don't want to block the caller of this func from *
  4951. * processing window messages *
  4952. * DWORD WINAPI WinStationBSMWorkerThread( LPVOID p ) *
  4953. *
  4954. ***********************************************************************************************/
  4955. DWORD WINAPI WinStationBSMWorkerThread( LPVOID p )
  4956. {
  4957. DWORD rc;
  4958. BSM_DATA_PACKAGE *pd = (BSM_DATA_PACKAGE *)p;
  4959. rc = WinStationBroadcastSystemMessageWorker(
  4960. pd->hServer ,
  4961. pd->sendToAllWinstations ,
  4962. pd->sessionID ,
  4963. pd->timeOut ,
  4964. pd->dwFlags ,
  4965. pd->lpdwRecipients ,
  4966. pd->uiMessage ,
  4967. pd->wParam ,
  4968. pd->lParam ,
  4969. pd->pResponse ,
  4970. pd->idOfSessionBeingIgnored);
  4971. return rc;
  4972. }
  4973. /**************************************************************************************************
  4974. * *
  4975. * This func is used to wait on a thread, and still allow the user of this thread (aka the creator *
  4976. * of this thread) to process window messages *
  4977. * *
  4978. **************************************************************************************************/
  4979. DWORD MsgWaitForMultipleObjectsLoop(HANDLE hEvent, DWORD dwTimeout)
  4980. {
  4981. while (1)
  4982. {
  4983. MSG msg;
  4984. DWORD dwObject = MsgWaitForMultipleObjects(1, &hEvent, FALSE, dwTimeout, QS_ALLEVENTS);
  4985. // Are we done waiting?
  4986. switch (dwObject)
  4987. {
  4988. case WAIT_OBJECT_0:
  4989. case WAIT_FAILED:
  4990. return dwObject;
  4991. case WAIT_TIMEOUT:
  4992. return WAIT_TIMEOUT;
  4993. case WAIT_OBJECT_0 + 1:
  4994. // This PeekMessage has the side effect of processing any broadcast messages.
  4995. // It doesn't matter what message we actually peek for but if we don't peek
  4996. // then other threads that have sent broadcast sendmessages will hang until
  4997. // hEvent is signaled. Since the process we're waiting on could be the one
  4998. // that sent the broadcast message that could cause a deadlock otherwise.
  4999. PeekMessage(&msg, NULL, WM_NULL, WM_USER, PM_NOREMOVE);
  5000. break;
  5001. }
  5002. }
  5003. // never gets here
  5004. // return dwObject;
  5005. }
  5006. /*****************************************************************************
  5007. *
  5008. * WinStationBroadcastSystemMessage
  5009. *
  5010. * Perform the the equivalent to Window's standard API BroadcastSystemMessage to
  5011. * all Hydra sessions. This is an exported function, at least used by the PNP manager to
  5012. * send a device change message to all sessions.
  5013. *
  5014. * LIMITATIONS:
  5015. * some messages, such as WM_COPYDATA send an address pointer to some user data as lParam.
  5016. * In this API. the only such case that is currently supported is for WM_DEVICECHANGE
  5017. * No error code will be returned if you try to use such an unsupported message, simply the
  5018. * lParam will be ignored.
  5019. *
  5020. * This func will only allow WM_DEVICECHNAGE and WM_SETTINGSCHANGE to go thru.
  5021. *
  5022. * ENTRY:
  5023. * hServer
  5024. * this is a handle which identifies a Hydra server. For the local server, hServer
  5025. * should be set to SERVERNAME_CURRENT
  5026. *
  5027. * sendToAllWinstations
  5028. * This should be set to TRUE if you want to broadcast message to all winstations
  5029. *
  5030. * sessionID,
  5031. * if sendToAllWinstations = FALSE, then message is only sent to only the
  5032. * winstation with the specified sessionID
  5033. *
  5034. * timeOut [ IN SECONDS ]
  5035. * set this to the amount of time you are willing to wait to get a response
  5036. * from the specified winstation. Even though Window's SendMessage API
  5037. * is blocking, the call from this side MUST choose how long it is willing to
  5038. * wait for a response.
  5039. *
  5040. * dwFlags
  5041. * see MSDN on BroadcastSystemMessage(). Be aware that POST is not allowed on any
  5042. * where the wparam is a pointer to some user mode data structure.
  5043. * For more info, see ntos\...\client\ntstubs.c
  5044. *
  5045. * lpdwRecipients
  5046. * Pointer to a variable that contains and receives information about the recipients of the message.
  5047. * see MSDN for more info
  5048. *
  5049. * uiMessage
  5050. * the window's message to send, limited to WM_DEVICECHANGE and WM_SETTINGSCHANGE
  5051. * at this time.
  5052. *
  5053. * wParam
  5054. * first message param
  5055. *
  5056. * lParam
  5057. * second message parameter
  5058. *
  5059. * pResponse
  5060. * this is the response to the message sent, see MSDN
  5061. *
  5062. * EXIT:
  5063. * TRUE if all went well or
  5064. * FALSE if something went wrong.
  5065. *
  5066. * WARNINGs:
  5067. * since the RPC call never blocks, you need to specify a reasonable timeOut if you want to wait for
  5068. * a response. Please remember that since this message is being sent to all winstations, the timeOut value
  5069. * will be on per-winstation.
  5070. *
  5071. * Also, Do not use flag BSF_POSTMESSAGE, since an app/window on a
  5072. * winstation is not setup to send back a response to the
  5073. * query in an asynchronous fashion.
  5074. * You must wait for the response (until the time out period).
  5075. *
  5076. * For WM_SETTINGGSCHNAGE, a second therad is used to allow the caller to still process windows
  5077. * messages.
  5078. * For WM_DEVICECHANGE, no such thread is used.
  5079. *
  5080. * Comments:
  5081. * For more info, please see MSDN for BroadcastSystemMessage()
  5082. *
  5083. ****************************************************************************/
  5084. LONG WinStationBroadcastSystemMessage(
  5085. HANDLE hServer,
  5086. BOOL sendToAllWinstations,
  5087. ULONG sessionID,
  5088. ULONG timeOut,
  5089. DWORD dwFlags,
  5090. DWORD *lpdwRecipients,
  5091. ULONG uiMessage,
  5092. WPARAM wParam,
  5093. LPARAM lParam,
  5094. LONG *pResponse // this is the response to the message sent
  5095. )
  5096. {
  5097. LONG rc;
  5098. DWORD dwRecipients=0; // caller may be passing null, so use a local var 1st, and then set
  5099. // value passed in by caller if an only if the caller's address is not null.
  5100. BOOLEAN fBufferHasValidData = FALSE;
  5101. BOOL bIsTerminalServer = !!(USER_SHARED_DATA->SuiteMask & (1 << TerminalServer));
  5102. if (!bIsTerminalServer)
  5103. {
  5104. return TRUE; // all is well, but we are not on a Hydra server
  5105. }
  5106. if (lpdwRecipients) // if caller passed in a non-NULL pointer for lpdwRec, use it's value
  5107. {
  5108. dwRecipients = *lpdwRecipients ;
  5109. }
  5110. // we may want to make this general for the future, but for now...
  5111. // we only let WM_DEVICECHANGE or WM_SETTINGCHANGE messages to go thru
  5112. switch ( uiMessage)
  5113. {
  5114. case WM_DEVICECHANGE:
  5115. rc = WinStationBroadcastSystemMessageWorker(
  5116. hServer,
  5117. sendToAllWinstations,
  5118. sessionID,
  5119. timeOut,
  5120. dwFlags,
  5121. &dwRecipients,
  5122. uiMessage,
  5123. wParam,
  5124. lParam,
  5125. pResponse,
  5126. NtCurrentPeb()->SessionId // ID of the session to be ignored.
  5127. );
  5128. if (lpdwRecipients) // if caller passed in a non-NULL pointer for lpdwRec, then set value
  5129. {
  5130. *lpdwRecipients = dwRecipients;
  5131. }
  5132. break;
  5133. case WM_SETTINGCHANGE:
  5134. {
  5135. BSM_DATA_PACKAGE d;
  5136. ULONG threadID;
  5137. HANDLE hThread;
  5138. //pack the data passed to the thread proc
  5139. d.hServer = hServer ;
  5140. d.sendToAllWinstations = sendToAllWinstations;
  5141. d.sessionID = sessionID;
  5142. d.timeOut = timeOut;
  5143. d.dwFlags = dwFlags;
  5144. d.lpdwRecipients = &dwRecipients;
  5145. d.uiMessage = uiMessage;
  5146. d.wParam = wParam;
  5147. d.lParam = lParam;
  5148. d.pResponse = pResponse;
  5149. d.idOfSessionBeingIgnored = NtCurrentPeb()->SessionId ;
  5150. // a remote admin may change env-settings
  5151. // and expect all sessions includin the
  5152. // console session to be updated
  5153. // A -1 means no sessions are ignored
  5154. // Call from shell\cpls\system\envvar.c already sent the message to the current session
  5155. hThread = CreateThread( NULL, 0, WinStationBSMWorkerThread,
  5156. (void *) &d, 0 , &threadID );
  5157. if ( hThread )
  5158. {
  5159. MsgWaitForMultipleObjectsLoop( hThread, INFINITE );
  5160. if (lpdwRecipients) // if caller passed in a non-NULL pointer for lpdwRec, then set value
  5161. {
  5162. *lpdwRecipients = *d.lpdwRecipients ;
  5163. }
  5164. GetExitCodeThread( hThread, &rc );
  5165. CloseHandle( hThread );
  5166. }
  5167. else
  5168. {
  5169. rc = FALSE;
  5170. }
  5171. }
  5172. break;
  5173. default:
  5174. DBGPRINT(("Request is rejected \n"));
  5175. rc = FALSE;
  5176. break;
  5177. }
  5178. return rc;
  5179. }
  5180. /*****************************************************************************
  5181. *
  5182. * WinStationSendWindowMessage
  5183. *
  5184. * Perform the the equivalent to SendMessage to a specific winstation as
  5185. * identified by the session ID. This is an exported function, at least used
  5186. * by the PNP manager to send a device change message (or any other window's message)
  5187. *
  5188. * LIMITATIONS:
  5189. * some messages, such as WM_COPYDATA send an address pointer to some user data as lParam.
  5190. * In this API, the only such case that is currently supported is for WM_DEVICECHANGE
  5191. * No error code will be returned if you try to use such an unsupported message, simply the
  5192. * lParam will be ignored.
  5193. *
  5194. * ENTRY:
  5195. * hServer
  5196. * this is a handle which identifies a Hydra server. For the local server, hServer
  5197. * should be set to SERVERNAME_CURRENT
  5198. * sessionID
  5199. * this idefntifies the hydra session to which message is being sent
  5200. *
  5201. * timeOut [ IN SECONDS ]
  5202. * set this to the amount of time you are willing to wait to get a response
  5203. * from the specified winstation. Even though Window's SendMessage API
  5204. * is blocking, the call from this side MUST choose how long it is willing to
  5205. * wait for a response.
  5206. *
  5207. * hWnd
  5208. * This is the HWND of the target window in the specified session that
  5209. * a message will be sent to.
  5210. * Msg
  5211. * the window's message to send
  5212. * wParam
  5213. * first message param
  5214. * lParam
  5215. * second message parameter
  5216. * pResponse
  5217. * this is the response to the message sent, it depends on the type of message sent, see MSDN
  5218. *
  5219. *
  5220. * EXIT:
  5221. * TRUE if all went well , check presponse for the actual response to the send message
  5222. * FALSE if something went wrong, the value of pResponse is not altered.
  5223. *
  5224. * WARNINGs:
  5225. * since the RPC call never blocks, you need to specify a reasonable timeOut if you want to wait for
  5226. * a response. Please remember that since this message is being sent to all winstations, the timeOut value
  5227. * will be on per-winstation.
  5228. *
  5229. *
  5230. * Comments:
  5231. * For more info, please see MSDN for SendMessage()
  5232. *
  5233. ****************************************************************************/
  5234. LONG WinStationSendWindowMessage(
  5235. HANDLE hServer,
  5236. ULONG sessionID,
  5237. ULONG timeOut,
  5238. ULONG hWnd, // handle of destination window
  5239. ULONG Msg, // message to send
  5240. WPARAM wParam, // first message parameter
  5241. LPARAM lParam, // second message parameter
  5242. LONG *pResponse
  5243. )
  5244. {
  5245. DWORD Result = ERROR_SUCCESS;
  5246. LONG rc = TRUE ;
  5247. // these are used for PNP messages
  5248. PBYTE rpcBuffer=NULL;
  5249. ULONG bufferSize=0;
  5250. PWCHAR lpStr;
  5251. ULONG maxSize;
  5252. BOOLEAN fBufferHasValidData=FALSE;
  5253. BOOL bIsTerminalServer = !!(USER_SHARED_DATA->SuiteMask & (1 << TerminalServer));
  5254. if (!bIsTerminalServer)
  5255. {
  5256. return TRUE; // all is well, but we are not on a Hydra server
  5257. }
  5258. // we may want to make this general for the future, but for now...
  5259. // since we only alloc/copy the lparam in case of an WM_DEVICECHANGE msg, then, only
  5260. // let message with either lparam=0 to go thru, or any WM_DEVICECHANGE msg.
  5261. if (lParam)
  5262. {
  5263. switch ( Msg)
  5264. {
  5265. case WM_DEVICECHANGE:
  5266. case WM_SETTINGCHANGE:
  5267. case WM_APPCOMMAND:
  5268. case WM_KEYDOWN:
  5269. case WM_KEYUP:
  5270. // these are ok
  5271. break;
  5272. default:
  5273. DBGPRINT(("Request is rejected \n"));
  5274. return FALSE;
  5275. break;
  5276. }
  5277. }
  5278. HANDLE_CURRENT_BINDING( hServer );
  5279. // Since the PNP message uses the lparam to pass the address of a user memory location, we
  5280. // need to handle this by creating our own copy of that data, and then pass it to
  5281. // termServ
  5282. switch( Msg )
  5283. {
  5284. // if this is a PNP message
  5285. case WM_DEVICECHANGE:
  5286. if ( lParam ) // see if the PNP message has a pointer to some user data
  5287. {
  5288. bufferSize = ( (DEV_BROADCAST_HDR *)(lParam))->dbch_size;
  5289. rpcBuffer = LocalAlloc( LPTR, bufferSize );
  5290. if ( rpcBuffer )
  5291. {
  5292. // copy from user-space into our local rpc buffer
  5293. CopyMemory(rpcBuffer, (PBYTE) lParam, bufferSize );
  5294. fBufferHasValidData = TRUE;
  5295. }
  5296. else
  5297. {
  5298. SetLastError( ERROR_OUTOFMEMORY );
  5299. return ( FALSE );
  5300. }
  5301. }
  5302. break;
  5303. // if this is a settings change message the system-CPL sends out
  5304. // when an Admin changes the system env vars...
  5305. case WM_SETTINGCHANGE:
  5306. if ( lParam ) // see if message has a string data
  5307. {
  5308. // put some artificial limit on how large a buffer we are willing to use
  5309. // in order to protect against malicious use of this api
  5310. maxSize = 4096;
  5311. bufferSize = lstrlenW( (PWCHAR) lParam ) * sizeof( WCHAR );
  5312. if ( bufferSize < maxSize )
  5313. {
  5314. rpcBuffer = LocalAlloc( LPTR, bufferSize );
  5315. if ( rpcBuffer )
  5316. {
  5317. // copy from user-space into our local rpc buffer
  5318. CopyMemory(rpcBuffer, (PBYTE) lParam, bufferSize );
  5319. fBufferHasValidData = TRUE;
  5320. }
  5321. else
  5322. {
  5323. SetLastError( ERROR_OUTOFMEMORY );
  5324. return ( FALSE );
  5325. }
  5326. }
  5327. else
  5328. {
  5329. // we have too many
  5330. // vars in the user's profile.
  5331. KdPrint(("lParam length too big = %d \n", bufferSize));
  5332. break;
  5333. SetLastError( ERROR_MESSAGE_EXCEEDS_MAX_SIZE );
  5334. return ( FALSE );
  5335. }
  5336. }
  5337. break;
  5338. }
  5339. // if the rpcBuffer is still empty, we must fill it up with some bogus data, otherwise, we will get
  5340. // an RPC error of RPC_X_NULL_REF_POINTER (error code of 1780). It looks like Rpc does not check the
  5341. // bufferSize value, and it just throws an exception if the buffer is NULL.
  5342. if ( !rpcBuffer )
  5343. {
  5344. rpcBuffer = LocalAlloc( LPTR, sizeof(UINT) );
  5345. if ( !rpcBuffer )
  5346. {
  5347. SetLastError( ERROR_OUTOFMEMORY );
  5348. return ( FALSE );
  5349. }
  5350. bufferSize = sizeof(UINT);
  5351. fBufferHasValidData = FALSE; // note that this is set to FALSE, which means, the recepient will
  5352. // not use the buffer. We do free the alloc below in either case.
  5353. }
  5354. RpcTryExcept {
  5355. // rc is set to TRUE for a successful call, else, FALSE
  5356. rc = RpcWinStationSendWindowMessage(
  5357. hServer,
  5358. sessionID ,
  5359. timeOut,
  5360. hWnd,
  5361. Msg,
  5362. wParam,
  5363. lParam ,
  5364. rpcBuffer ,
  5365. bufferSize,
  5366. fBufferHasValidData,
  5367. pResponse );
  5368. //DBGPRINT(("done with call RpcWinStationSendWindowMessage() for sessionID= %d\n", sessionID ));
  5369. }
  5370. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  5371. Result = RpcExceptionCode();
  5372. DBGPRINT(("RPC Exception %d in RpcWinStationSendWindowMessage() for sessionID = %d \n",Result, sessionID ));
  5373. rc = FALSE;
  5374. }
  5375. RpcEndExcept
  5376. LocalFree( rpcBuffer );
  5377. SetLastError( Result );
  5378. return( rc );
  5379. }
  5380. /****************************************************************************
  5381. *
  5382. * _WinStationUpdateUserConfig()
  5383. * Used by notify when shell is about to start
  5384. * This will cause an update to the userconfig of the session by loading the user profile
  5385. * and reading policy data from their HKCU
  5386. *
  5387. * Params:
  5388. * [in] UserToken,
  5389. * [in] pDomain,
  5390. * [in] pUserName
  5391. *
  5392. * Return:
  5393. * TRUE if no errors, FALSE in case of error, use GetLastError() for more info
  5394. *
  5395. ****************************************************************************/
  5396. BOOLEAN WINAPI
  5397. _WinStationUpdateUserConfig(
  5398. HANDLE UserToken
  5399. )
  5400. {
  5401. DWORD Result;
  5402. BOOLEAN rc = TRUE;
  5403. HANDLE hServer = SERVERNAME_CURRENT;
  5404. DWORD result;
  5405. HANDLE_CURRENT_BINDING_NO_SERVER( hServer );
  5406. if( hServer == RPC_HANDLE_NO_SERVER ) {
  5407. return FALSE;
  5408. }
  5409. RpcTryExcept {
  5410. rc = RpcWinStationUpdateUserConfig(
  5411. hServer,
  5412. NtCurrentPeb()->SessionId,
  5413. GetCurrentProcessId(),
  5414. (DWORD)(INT_PTR) UserToken,
  5415. &result
  5416. );
  5417. }
  5418. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  5419. Result = RpcExceptionCode();
  5420. SetLastError( Result );
  5421. DBGPRINT(("RPC Exception %d\n",Result));
  5422. rc = FALSE;
  5423. }
  5424. RpcEndExcept
  5425. return( rc );
  5426. }
  5427. /*
  5428. * WinStationQueryLogonCredentialsW
  5429. *
  5430. * Used by Winlogon to get auto-logon credentials from termsrv. This replaces
  5431. * the dual calls to WinStationQueryInformation and
  5432. * ServerQueryInetConnectorInformation.
  5433. */
  5434. BOOLEAN WINAPI
  5435. WinStationQueryLogonCredentialsW(
  5436. PWLX_CLIENT_CREDENTIALS_INFO_V2_0 pCredentials
  5437. )
  5438. {
  5439. BOOLEAN fRet;
  5440. HANDLE hServer;
  5441. NTSTATUS Status;
  5442. PCHAR pWire;
  5443. ULONG cbWire;
  5444. if (pCredentials == NULL)
  5445. {
  5446. return(FALSE);
  5447. }
  5448. if (pCredentials->dwType != WLX_CREDENTIAL_TYPE_V2_0)
  5449. {
  5450. return(FALSE);
  5451. }
  5452. hServer = SERVERNAME_CURRENT;
  5453. HANDLE_CURRENT_BINDING(hServer);
  5454. pWire = NULL;
  5455. cbWire = 0;
  5456. __try
  5457. {
  5458. fRet = RpcWinStationQueryLogonCredentials(
  5459. hServer,
  5460. NtCurrentPeb()->SessionId,
  5461. &pWire,
  5462. &cbWire
  5463. );
  5464. }
  5465. __except(EXCEPTION_EXECUTE_HANDLER)
  5466. {
  5467. fRet = FALSE;
  5468. }
  5469. if (fRet)
  5470. {
  5471. fRet = CopyCredFromWire((PWLXCLIENTCREDWIREW)pWire, pCredentials);
  5472. }
  5473. if (pWire != NULL)
  5474. {
  5475. MIDL_user_free(pWire);
  5476. }
  5477. return(fRet);
  5478. }
  5479. BOOL WINAPI WinStationRegisterConsoleNotification (
  5480. HANDLE hServer,
  5481. HWND hWnd,
  5482. DWORD dwFlags
  5483. )
  5484. {
  5485. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  5486. BOOL bResult = FALSE;
  5487. HANDLE_CURRENT_BINDING( hServer );
  5488. RpcTryExcept {
  5489. bResult = RpcWinStationRegisterConsoleNotification (
  5490. hServer,
  5491. &Status,
  5492. NtCurrentPeb()->SessionId,
  5493. HandleToUlong(hWnd),
  5494. dwFlags
  5495. );
  5496. if (!bResult) {
  5497. //
  5498. // Convert NTSTATUS to winerror, and set last error here.
  5499. //
  5500. SetLastError(RtlNtStatusToDosError(Status));
  5501. }
  5502. }
  5503. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  5504. SetLastError(RpcExceptionCode());
  5505. }
  5506. RpcEndExcept
  5507. return (bResult);
  5508. }
  5509. BOOL WINAPI WinStationUnRegisterConsoleNotification (
  5510. HANDLE hServer,
  5511. HWND hWnd
  5512. )
  5513. {
  5514. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  5515. BOOL bResult = FALSE;
  5516. HANDLE_CURRENT_BINDING( hServer );
  5517. RpcTryExcept {
  5518. bResult = RpcWinStationUnRegisterConsoleNotification (
  5519. hServer,
  5520. &Status,
  5521. NtCurrentPeb()->SessionId,
  5522. HandleToUlong(hWnd)
  5523. );
  5524. if (!bResult) {
  5525. SetLastError(RtlNtStatusToDosError(Status));
  5526. }
  5527. }
  5528. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  5529. SetLastError(RpcExceptionCode());
  5530. }
  5531. RpcEndExcept
  5532. return (bResult);
  5533. }
  5534. BOOLEAN CloseContextHandle(HANDLE *pHandle, DWORD *pdwResult)
  5535. {
  5536. BOOLEAN bSuccess;
  5537. ASSERT(pHandle);
  5538. ASSERT(pdwResult);
  5539. RpcTryExcept {
  5540. bSuccess = RpcWinStationCloseServerEx( pHandle, pdwResult );
  5541. if( !bSuccess ) *pdwResult = RtlNtStatusToDosError( *pdwResult );
  5542. }
  5543. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  5544. *pdwResult = RpcExceptionCode();
  5545. bSuccess = FALSE;
  5546. }
  5547. RpcEndExcept
  5548. if (!bSuccess && (*pdwResult == RPC_S_PROCNUM_OUT_OF_RANGE)) {
  5549. //
  5550. // most probabaly we are calling an older server which does not have
  5551. // RpcWinStationCloseServerEx, so lets give a try to RpcWinStationCloseServer
  5552. //
  5553. RpcTryExcept {
  5554. bSuccess = RpcWinStationCloseServer( *pHandle, pdwResult );
  5555. if( !bSuccess ) *pdwResult = RtlNtStatusToDosError( *pdwResult );
  5556. }
  5557. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  5558. *pdwResult = RpcExceptionCode();
  5559. bSuccess = FALSE;
  5560. DBGPRINT(("RPC Exception %d\n", *pdwResult));
  5561. }
  5562. RpcEndExcept
  5563. //
  5564. // RpcWinStationCloseServer does not take care of destroying the context handle.
  5565. // we we have to do it here at client end.
  5566. //
  5567. RpcTryExcept {
  5568. RpcSsDestroyClientContext(pHandle);
  5569. }
  5570. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  5571. ASSERT(FALSE);
  5572. }
  5573. RpcEndExcept
  5574. }
  5575. return (bSuccess);
  5576. }
  5577. BOOLEAN WINAPI
  5578. RemoteAssistancePrepareSystemRestore(
  5579. HANDLE hServer
  5580. )
  5581. /*++
  5582. --*/
  5583. {
  5584. DWORD Result;
  5585. BOOLEAN rc;
  5586. HANDLE_CURRENT_BINDING( hServer );
  5587. RpcTryExcept {
  5588. rc = RpcRemoteAssistancePrepareSystemRestore(
  5589. hServer,
  5590. &Result
  5591. );
  5592. // TermSrv RpcRemoteAssistancePrepareSystemRestore() return
  5593. // win32 ERROR code or actual HRESULT code.
  5594. SetLastError(Result);
  5595. }
  5596. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  5597. Result = RpcExceptionCode();
  5598. SetLastError( Result );
  5599. DBGPRINT(("RPC Exception %d\n",Result));
  5600. rc = FALSE;
  5601. }
  5602. RpcEndExcept
  5603. return rc;
  5604. }
  5605. BOOLEAN WinStationIsHelpAssistantSession(
  5606. SERVER_HANDLE hServer,
  5607. ULONG LogonId
  5608. )
  5609. /*++
  5610. --*/
  5611. {
  5612. DWORD Result;
  5613. BOOLEAN rc;
  5614. HANDLE_CURRENT_BINDING( hServer );
  5615. RpcTryExcept {
  5616. rc = RpcWinStationIsHelpAssistantSession(
  5617. hServer,
  5618. &Result,
  5619. (LogonId == LOGONID_CURRENT) ? NtCurrentPeb()->SessionId : LogonId
  5620. );
  5621. // Since a program has called us, we need to set the last error code such
  5622. // that extended error information is available
  5623. if (!rc)
  5624. SetLastError(RtlNtStatusToDosError(Result));
  5625. }
  5626. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  5627. Result = RpcExceptionCode();
  5628. SetLastError( Result );
  5629. DBGPRINT(("RPC Exception %d\n",Result));
  5630. rc = FALSE;
  5631. }
  5632. RpcEndExcept
  5633. return rc;
  5634. }
  5635. /*
  5636. *
  5637. * WinStationGetMachinePolicy
  5638. * Pass it a pointer to the callers ALREADY allocated policy struct, and this func
  5639. * will fill it up from the current machine policy known to TermSrv
  5640. *
  5641. * Params:
  5642. * hServer
  5643. * this is a handle which identifies a Hydra server. For the local server, hServer
  5644. * should be set to SERVERNAME_CURRENT
  5645. *
  5646. * pPolicy
  5647. * pointer to POLICY_TS_MACHINE already allocated by the caller.
  5648. *
  5649. */
  5650. BOOLEAN WinStationGetMachinePolicy (
  5651. HANDLE hServer,
  5652. POLICY_TS_MACHINE *pPolicy
  5653. )
  5654. {
  5655. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  5656. BOOLEAN bResult = FALSE;
  5657. HANDLE_CURRENT_BINDING( hServer );
  5658. RpcTryExcept {
  5659. bResult = RpcWinStationGetMachinePolicy (
  5660. hServer,
  5661. (PBYTE)pPolicy,
  5662. sizeof( POLICY_TS_MACHINE )
  5663. );
  5664. if (!bResult) {
  5665. SetLastError(RtlNtStatusToDosError(Status));
  5666. }
  5667. }
  5668. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  5669. SetLastError(RpcExceptionCode());
  5670. }
  5671. RpcEndExcept
  5672. return (bResult);
  5673. }
  5674. /*****************************************************************************************************************
  5675. *
  5676. * _WinStationUpdateClientCachedCreadentials
  5677. *
  5678. * Comment
  5679. * Msgina calls this routine to notify TermSrv about the exact credentials specified by the User during logon
  5680. * TermSrv uses this information to send back notification information to the client
  5681. * This call was introduced because the notification used before did not support UPN Names
  5682. *
  5683. * ENTRY:
  5684. * [in] pDomain
  5685. * [in] pUserName
  5686. *
  5687. * EXIT:
  5688. * ERROR_SUCCESS - no error
  5689. *
  5690. ******************************************************************************************************************/
  5691. BOOLEAN WINAPI
  5692. _WinStationUpdateClientCachedCredentials(
  5693. PWCHAR pDomain,
  5694. PWCHAR pUserName
  5695. )
  5696. {
  5697. BOOLEAN rc;
  5698. DWORD Result;
  5699. DWORD DomainLength;
  5700. DWORD UserNameLength;
  5701. HANDLE hServer = SERVERNAME_CURRENT;
  5702. HANDLE ReadyEventHandle;
  5703. DWORD TermSrvWaitTime = 0;
  5704. HANDLE_CURRENT_BINDING_NO_SERVER( hServer );
  5705. if( hServer == RPC_HANDLE_NO_SERVER ) {
  5706. return TRUE;
  5707. }
  5708. //
  5709. // Wait for the TermSrvReadyEvent to be set by TERMSRV.EXE. This
  5710. // event indicates that TermSrv is initialized to the point that
  5711. // the data used by _WinStationUpdateClientCachedCredentials() is available.
  5712. //
  5713. ReadyEventHandle = CreateEvent(NULL, TRUE, FALSE,
  5714. TEXT("Global\\TermSrvReadyEvent"));
  5715. if (ReadyEventHandle != NULL) {
  5716. if (WaitForSingleObject(ReadyEventHandle, TermSrvWaitTime) != 0) {
  5717. DBGPRINT(("WinLogon: Wait for ReadyEventHandle failed\n"));
  5718. return TRUE;
  5719. }
  5720. CloseHandle(ReadyEventHandle);
  5721. } else {
  5722. DBGPRINT(("WinLogon: Create failed for ReadyEventHandle\n"));
  5723. return TRUE;
  5724. }
  5725. RpcTryExcept {
  5726. if( pDomain ) {
  5727. DomainLength = lstrlenW(pDomain) + 1;
  5728. } else {
  5729. DomainLength = 0;
  5730. }
  5731. if( pUserName ) {
  5732. UserNameLength = lstrlenW(pUserName) + 1;
  5733. } else {
  5734. UserNameLength = 0;
  5735. }
  5736. rc = RpcWinStationUpdateClientCachedCredentials(
  5737. hServer,
  5738. &Result,
  5739. NtCurrentPeb()->SessionId,
  5740. GetCurrentProcessId(),
  5741. pDomain,
  5742. DomainLength,
  5743. pUserName,
  5744. UserNameLength
  5745. );
  5746. if( !rc ) {
  5747. Result = RtlNtStatusToDosError( Result );
  5748. }
  5749. }
  5750. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  5751. Result = RpcExceptionCode();
  5752. DBGPRINT(("RPC Exception %d\n",Result));
  5753. rc = FALSE;
  5754. }
  5755. RpcEndExcept
  5756. if( !rc ) SetLastError(Result);
  5757. return( rc );
  5758. }
  5759. /*****************************************************************************************************************
  5760. *
  5761. * _WinStationFUSCanRemoteUserDisconnect
  5762. *
  5763. * Comment
  5764. * FUS specific call when a remote user wants to connect and hence disconnect the present User
  5765. * Winlogon calls this routine so that we can ask the present user if it is ok to disconnect him
  5766. * The Target LogonId, Username and Domain of the remote user are passed on from Winlogon (useful to display the MessageBox)
  5767. *
  5768. * ENTRY:
  5769. * [in] LogonId - Session Id of the new session
  5770. * [in] pDomain - Domain name of the remote user trying to connect
  5771. * [in] pUserName - Username of the remote user trying to connect
  5772. *
  5773. * EXIT:
  5774. * TRUE when local user allows the remote user to connect. FALSE otherwise.
  5775. *
  5776. ******************************************************************************************************************/
  5777. BOOLEAN WINAPI
  5778. _WinStationFUSCanRemoteUserDisconnect(
  5779. ULONG LogonId,
  5780. PWCHAR pDomain,
  5781. PWCHAR pUserName
  5782. )
  5783. {
  5784. BOOLEAN rc;
  5785. DWORD Result;
  5786. DWORD DomainLength;
  5787. DWORD UserNameLength;
  5788. HANDLE hServer = SERVERNAME_CURRENT;
  5789. HANDLE ReadyEventHandle;
  5790. DWORD TermSrvWaitTime = 0;
  5791. HANDLE_CURRENT_BINDING_NO_SERVER( hServer );
  5792. if( hServer == RPC_HANDLE_NO_SERVER ) {
  5793. return TRUE;
  5794. }
  5795. RpcTryExcept {
  5796. if( pDomain ) {
  5797. DomainLength = lstrlenW(pDomain) + 1;
  5798. } else {
  5799. DomainLength = 0;
  5800. }
  5801. if( pUserName ) {
  5802. UserNameLength = lstrlenW(pUserName) + 1;
  5803. } else {
  5804. UserNameLength = 0;
  5805. }
  5806. rc = RpcWinStationFUSCanRemoteUserDisconnect(
  5807. hServer,
  5808. &Result,
  5809. LogonId,
  5810. NtCurrentPeb()->SessionId,
  5811. GetCurrentProcessId(),
  5812. pDomain,
  5813. DomainLength,
  5814. pUserName,
  5815. UserNameLength
  5816. );
  5817. if( !rc ) {
  5818. Result = RtlNtStatusToDosError( Result );
  5819. }
  5820. }
  5821. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  5822. Result = RpcExceptionCode();
  5823. DBGPRINT(("RPC Exception %d\n",Result));
  5824. rc = FALSE;
  5825. }
  5826. RpcEndExcept
  5827. if( !rc ) SetLastError(Result);
  5828. return( rc );
  5829. }
  5830. /*****************************************************************************
  5831. *
  5832. * WinStationCheckLoopBack
  5833. *
  5834. * Check if there is a loopback when a client tries to connect
  5835. *
  5836. * ENTRY:
  5837. * IN hServer : open RPC server handle
  5838. * IN ClientSessionId : ID of the Session from which the Client was started
  5839. * IN TargetLogonId : Session ID to which the client is trying to connect to
  5840. * IN pTargetServerName : name of target server
  5841. *
  5842. * EXIT:
  5843. * TRUE if there is a Loopback. FALSE otherwise.
  5844. *
  5845. ****************************************************************************/
  5846. BOOLEAN WINAPI
  5847. WinStationCheckLoopBack(
  5848. HANDLE hServer,
  5849. ULONG ClientSessionId,
  5850. ULONG TargetLogonId,
  5851. LPWSTR pTargetServerName
  5852. )
  5853. {
  5854. DWORD NameSize;
  5855. DWORD Result;
  5856. BOOLEAN rc;
  5857. HANDLE_CURRENT_BINDING_NO_SERVER( hServer );
  5858. if( hServer == RPC_HANDLE_NO_SERVER ) {
  5859. return TRUE;
  5860. }
  5861. RpcTryExcept {
  5862. if (pTargetServerName) {
  5863. NameSize = lstrlenW(pTargetServerName) + 1;
  5864. } else {
  5865. NameSize = 0;
  5866. }
  5867. rc = RpcWinStationCheckLoopBack(
  5868. hServer,
  5869. &Result,
  5870. ClientSessionId,
  5871. TargetLogonId,
  5872. pTargetServerName,
  5873. NameSize
  5874. );
  5875. Result = RtlNtStatusToDosError( Result );
  5876. }
  5877. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  5878. Result = RpcExceptionCode();
  5879. DBGPRINT(("RPC Exception %d\n",Result));
  5880. rc = FALSE;
  5881. }
  5882. RpcEndExcept
  5883. if( !rc ) SetLastError(Result);
  5884. return( rc );
  5885. }
  5886. //
  5887. // generic routine that can support all kind of protocol but this will
  5888. // require including tdi.h
  5889. //
  5890. BOOLEAN
  5891. WinStationConnectCallback(
  5892. HANDLE hServer,
  5893. DWORD Timeout,
  5894. ULONG AddressType,
  5895. PBYTE pAddress,
  5896. ULONG AddressSize
  5897. )
  5898. {
  5899. BOOLEAN rc;
  5900. DWORD Result;
  5901. HANDLE_CURRENT_BINDING( hServer );
  5902. RpcTryExcept {
  5903. rc = RpcConnectCallback(
  5904. hServer,
  5905. &Result,
  5906. Timeout,
  5907. AddressType,
  5908. pAddress,
  5909. AddressSize
  5910. );
  5911. if( !rc ) SetLastError( RtlNtStatusToDosError(Result) );
  5912. }
  5913. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  5914. Result = RpcExceptionCode();
  5915. SetLastError( Result );
  5916. DBGPRINT(("RPC Exception %d\n",Result));
  5917. rc = FALSE;
  5918. }
  5919. RpcEndExcept
  5920. return( rc );
  5921. }
  5922. /*****************************************************************************************************************
  5923. *
  5924. * _WinStationNotifyDisconnectPipe
  5925. *
  5926. * Comment
  5927. * This routine is called by the temperory winlogon created during console reconnect, when it wants to inform
  5928. * the session 0 winlogon to disconnect the autologon Named Pipe. This can happen in some error handling paths
  5929. * during console reconnect.
  5930. *
  5931. * ENTRY: None
  5932. *
  5933. * EXIT:
  5934. * TRUE when notification succeeded. FALSE otherwise.
  5935. *
  5936. ******************************************************************************************************************/
  5937. BOOLEAN WINAPI
  5938. _WinStationNotifyDisconnectPipe(
  5939. VOID
  5940. )
  5941. {
  5942. BOOLEAN rc;
  5943. DWORD Result;
  5944. HANDLE hServer = SERVERNAME_CURRENT;
  5945. HANDLE_CURRENT_BINDING_NO_SERVER( hServer );
  5946. if( hServer == RPC_HANDLE_NO_SERVER ) {
  5947. return TRUE;
  5948. }
  5949. RpcTryExcept {
  5950. rc = RpcWinStationNotifyDisconnectPipe(
  5951. hServer,
  5952. &Result,
  5953. NtCurrentPeb()->SessionId,
  5954. GetCurrentProcessId()
  5955. );
  5956. if( !rc ) {
  5957. Result = RtlNtStatusToDosError( Result );
  5958. }
  5959. }
  5960. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  5961. Result = RpcExceptionCode();
  5962. DBGPRINT(("RPC Exception %d\n",Result));
  5963. rc = FALSE;
  5964. }
  5965. RpcEndExcept
  5966. if( !rc ) SetLastError(Result);
  5967. return( rc );
  5968. }
  5969. /*******************************************************************************
  5970. *
  5971. * WinStationAutoReconnect
  5972. *
  5973. * Atomically:
  5974. * 1) Queries a winstation to see if it should be autoreconnected
  5975. * and which session ID to autoreconnect to
  5976. * 2) Performs security checks to ensure session is authorized to ARC
  5977. * 3) Auto reconnect is done
  5978. *
  5979. * ENTRY:
  5980. *
  5981. * flags (input)
  5982. * Extra settings, currently unused
  5983. *
  5984. * EXIT:
  5985. * The return value is an NTSTATUS code which could have the infromational
  5986. * class set to specify the call succeeded but autoreconnect did not happen
  5987. *
  5988. ******************************************************************************/
  5989. ULONG WINAPI
  5990. WinStationAutoReconnect(
  5991. ULONG flags
  5992. )
  5993. {
  5994. DWORD Result;
  5995. BOOLEAN rc;
  5996. HANDLE hServer = SERVERNAME_CURRENT;
  5997. HANDLE_CURRENT_BINDING( hServer );
  5998. RpcTryExcept {
  5999. rc = RpcWinStationAutoReconnect(
  6000. hServer,
  6001. &Result,
  6002. NtCurrentPeb()->SessionId,
  6003. flags
  6004. );
  6005. }
  6006. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  6007. Result = RpcExceptionCode();
  6008. SetLastError( Result );
  6009. DBGPRINT(("RPC Exception %d\n",Result));
  6010. rc = FALSE;
  6011. }
  6012. RpcEndExcept
  6013. return( Result );
  6014. }