Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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