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.

913 lines
30 KiB

  1. /*************************************************************************
  2. *
  3. * winset.c
  4. *
  5. * Window station set APS
  6. *
  7. * Copyright Microsoft Corporation, 1998
  8. *
  9. *
  10. *************************************************************************/
  11. /*
  12. * Includes
  13. */
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #include "conntfy.h" // for SetLockedState
  17. /*
  18. * External Procedures
  19. */
  20. NTSTATUS xxxWinStationSetInformation( ULONG, WINSTATIONINFOCLASS,
  21. PVOID, ULONG );
  22. VOID _ReadUserProfile( PWCHAR, PWCHAR, PUSERCONFIG );
  23. extern BOOL IsCallerSystem( VOID );
  24. extern BOOL IsCallerAdmin( VOID );
  25. /*
  26. * Internal Procedures used
  27. */
  28. NTSTATUS _SetConfig( PWINSTATION, PWINSTATIONCONFIG, ULONG );
  29. NTSTATUS _SetPdParams( PWINSTATION, PPDPARAMS, ULONG );
  30. NTSTATUS _SetBeep( PWINSTATION, PBEEPINPUT, ULONG );
  31. NTSTATUS WinStationShadowChangeMode( PWINSTATION, PWINSTATIONSHADOW, ULONG );
  32. NTSTATUS FlushVirtualInput( PWINSTATION, VIRTUALCHANNELCLASS, ULONG );
  33. NTSTATUS
  34. RpcCheckClientAccess(
  35. PWINSTATION pWinStation,
  36. ACCESS_MASK DesiredAccess,
  37. BOOLEAN AlreadyImpersonating
  38. );
  39. NTSTATUS
  40. CheckWireBuffer(WINSTATIONINFOCLASS InfoClass,
  41. PVOID WireBuf,
  42. ULONG WireBufLen,
  43. PVOID *ppLocalBuf,
  44. PULONG pLocalBufLen);
  45. NTSTATUS
  46. ValidateInputConfig( PWINSTATION pWinStation, PWINSTATIONCONFIG pConfig );
  47. /*
  48. * Global data
  49. */
  50. typedef ULONG_PTR (*PFN)();
  51. HMODULE ghNetApiDll = NULL;
  52. PFN pNetGetAnyDCName = NULL;
  53. PFN pNetApiBufferFree = NULL;
  54. /*
  55. * External data
  56. */
  57. NTSTATUS
  58. _CheckCallerLocalAndSystem()
  59. /*++
  60. Checking caller is calling from local and also is running
  61. under system context
  62. --*/
  63. {
  64. NTSTATUS Status;
  65. BOOL bRevert = FALSE;
  66. UINT LocalFlag;
  67. Status = RpcImpersonateClient( NULL );
  68. if( Status != RPC_S_OK ) {
  69. DBGPRINT((" RpcImpersonateClient() failed : 0x%x\n",Status));
  70. Status = STATUS_CANNOT_IMPERSONATE;
  71. goto CLEANUPANDEXIT;
  72. }
  73. bRevert = TRUE;
  74. //
  75. // Inquire if local RPC call
  76. //
  77. Status = I_RpcBindingIsClientLocal(
  78. 0, // Active RPC call we are servicing
  79. &LocalFlag
  80. );
  81. if( Status != RPC_S_OK ) {
  82. DBGPRINT((" I_RpcBindingIsClientLocal() failed : 0x%x\n",Status));
  83. Status = STATUS_ACCESS_DENIED;
  84. goto CLEANUPANDEXIT;
  85. }
  86. if( !LocalFlag ) {
  87. DBGPRINT((" Not a local client call\n"));
  88. Status = STATUS_ACCESS_DENIED;
  89. goto CLEANUPANDEXIT;
  90. }
  91. Status = (IsCallerSystem()) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
  92. CLEANUPANDEXIT:
  93. if( TRUE == bRevert ) {
  94. RpcRevertToSelf();
  95. }
  96. return Status;
  97. }
  98. /*******************************************************************************
  99. *
  100. * xxxWinStationSetInformation
  101. *
  102. * set window station information (worker routine)
  103. *
  104. * ENTRY:
  105. * pWinStation (input)
  106. * pointer to citrix window station structure
  107. * WinStationInformationClass (input)
  108. * Specifies the type of information to set at the specified window
  109. * station object.
  110. * pWinStationInformation (input)
  111. * A pointer to a buffer that contains information to set for the
  112. * specified window station. The format and contents of the buffer
  113. * depend on the specified information class being set.
  114. * WinStationInformationLength (input)
  115. * Specifies the length in bytes of the window station information
  116. * buffer.
  117. *
  118. * EXIT:
  119. * STATUS_SUCCESS - no error
  120. *
  121. ******************************************************************************/
  122. NTSTATUS
  123. xxxWinStationSetInformation( ULONG LogonId,
  124. WINSTATIONINFOCLASS WinStationInformationClass,
  125. PVOID pWinStationInformation,
  126. ULONG WinStationInformationLength )
  127. {
  128. NTSTATUS Status = STATUS_SUCCESS;
  129. PWINSTATION pWinStation;
  130. ULONG cbReturned;
  131. WINSTATION_APIMSG msg;
  132. PWINSTATIONCONFIG pConfig;
  133. ULONG ConfigLength;
  134. PPDPARAMS pPdParams;
  135. ULONG PdParamsLength;
  136. RPC_STATUS RpcStatus;
  137. TRACE((hTrace,TC_ICASRV,TT_API2,"TERMSRV: WinStationSetInformation LogonId=%d, Class=%d\n",
  138. LogonId, (ULONG)WinStationInformationClass ));
  139. /*
  140. * Find the WinStation
  141. * Return error if not found or currently terminating.
  142. */
  143. pWinStation = FindWinStationById( LogonId, FALSE );
  144. if ( !pWinStation )
  145. return( STATUS_CTX_WINSTATION_NOT_FOUND );
  146. if ( pWinStation->Terminating ) {
  147. ReleaseWinStation( pWinStation );
  148. return( STATUS_CTX_CLOSE_PENDING );
  149. }
  150. /*
  151. * Verify that client has SET access
  152. */
  153. Status = RpcCheckClientAccess( pWinStation, WINSTATION_SET, FALSE );
  154. if ( !NT_SUCCESS( Status ) ) {
  155. ReleaseWinStation( pWinStation );
  156. return( Status );
  157. }
  158. switch ( WinStationInformationClass ) {
  159. case WinStationPdParams :
  160. Status = CheckWireBuffer(WinStationInformationClass,
  161. pWinStationInformation,
  162. WinStationInformationLength,
  163. &pPdParams,
  164. &PdParamsLength);
  165. if ( !NT_SUCCESS(Status) ) {
  166. break;
  167. }
  168. if ( pWinStation->hStack ) {
  169. // Check for availability
  170. if ( pWinStation->pWsx &&
  171. pWinStation->pWsx->pWsxIcaStackIoControl ) {
  172. Status = pWinStation->pWsx->pWsxIcaStackIoControl(
  173. pWinStation->pWsxContext,
  174. pWinStation->hIca,
  175. pWinStation->hStack,
  176. IOCTL_ICA_STACK_SET_PARAMS,
  177. pPdParams,
  178. PdParamsLength,
  179. NULL,
  180. 0,
  181. NULL );
  182. }
  183. else {
  184. Status = STATUS_INVALID_INFO_CLASS;
  185. }
  186. }
  187. LocalFree((PVOID)pPdParams);
  188. break;
  189. case WinStationConfiguration :
  190. Status = CheckWireBuffer(WinStationInformationClass,
  191. pWinStationInformation,
  192. WinStationInformationLength,
  193. &pConfig,
  194. &ConfigLength);
  195. if ( !NT_SUCCESS(Status) ) {
  196. break;
  197. }
  198. Status = _SetConfig( pWinStation,
  199. pConfig,
  200. ConfigLength );
  201. LocalFree((PVOID)pConfig);
  202. break;
  203. case WinStationTrace :
  204. RpcStatus = RpcImpersonateClient( NULL );
  205. if( RpcStatus != RPC_S_OK ) {
  206. Status = STATUS_CANNOT_IMPERSONATE;
  207. break;
  208. }
  209. if (!IsCallerAdmin() && !IsCallerSystem()) {
  210. Status = STATUS_ACCESS_DENIED;
  211. }
  212. RpcRevertToSelf();
  213. if (!NT_SUCCESS(Status)) {
  214. break;
  215. }
  216. if ( WinStationInformationLength < sizeof(ICA_TRACE) ) {
  217. Status = STATUS_BUFFER_TOO_SMALL;
  218. break;
  219. }
  220. if ( pWinStation->hIca ) {
  221. Status = IcaIoControl( pWinStation->hIca,
  222. IOCTL_ICA_SET_TRACE,
  223. pWinStationInformation,
  224. WinStationInformationLength,
  225. NULL,
  226. 0,
  227. NULL );
  228. }
  229. break;
  230. case WinStationSystemTrace :
  231. RpcStatus = RpcImpersonateClient( NULL );
  232. if( RpcStatus != RPC_S_OK ) {
  233. Status = STATUS_CANNOT_IMPERSONATE;
  234. break;
  235. }
  236. if (!IsCallerAdmin() && !IsCallerSystem()) {
  237. Status = STATUS_ACCESS_DENIED;
  238. }
  239. RpcRevertToSelf();
  240. if (!NT_SUCCESS(Status)) {
  241. break;
  242. }
  243. if ( WinStationInformationLength < sizeof(ICA_TRACE) ) {
  244. Status = STATUS_BUFFER_TOO_SMALL;
  245. break;
  246. }
  247. /*
  248. * Open ICA device driver
  249. */
  250. if ( hTrace == NULL ) {
  251. Status = IcaOpen( &hTrace );
  252. if ( !NT_SUCCESS(Status) )
  253. hTrace = NULL;
  254. }
  255. if ( hTrace ) {
  256. Status = IcaIoControl( hTrace,
  257. IOCTL_ICA_SET_SYSTEM_TRACE,
  258. pWinStationInformation,
  259. WinStationInformationLength,
  260. NULL,
  261. 0,
  262. NULL );
  263. }
  264. break;
  265. case WinStationPrinter :
  266. break;
  267. case WinStationBeep :
  268. if (WinStationInformationLength < sizeof(BEEPINPUT)) {
  269. Status = STATUS_BUFFER_TOO_SMALL ;
  270. break;
  271. }
  272. Status = _SetBeep( pWinStation,
  273. (PBEEPINPUT) pWinStationInformation,
  274. WinStationInformationLength );
  275. break;
  276. case WinStationEncryptionOff :
  277. if ( pWinStation->hStack ) {
  278. // Check for availability
  279. if ( pWinStation->pWsx &&
  280. pWinStation->pWsx->pWsxIcaStackIoControl ) {
  281. Status = pWinStation->pWsx->pWsxIcaStackIoControl(
  282. pWinStation->pWsxContext,
  283. pWinStation->hIca,
  284. pWinStation->hStack,
  285. IOCTL_ICA_STACK_ENCRYPTION_OFF,
  286. pWinStationInformation,
  287. WinStationInformationLength,
  288. NULL,
  289. 0,
  290. NULL );
  291. }
  292. else {
  293. Status = STATUS_INVALID_INFO_CLASS;
  294. }
  295. }
  296. break;
  297. case WinStationEncryptionPerm :
  298. if ( pWinStation->hStack ) {
  299. // Check for availability
  300. if ( pWinStation->pWsx &&
  301. pWinStation->pWsx->pWsxIcaStackIoControl ) {
  302. Status = pWinStation->pWsx->pWsxIcaStackIoControl(
  303. pWinStation->pWsxContext,
  304. pWinStation->hIca,
  305. pWinStation->hStack,
  306. IOCTL_ICA_STACK_ENCRYPTION_PERM,
  307. pWinStationInformation,
  308. WinStationInformationLength,
  309. NULL,
  310. 0,
  311. NULL );
  312. }
  313. else {
  314. Status = STATUS_INVALID_INFO_CLASS;
  315. }
  316. }
  317. break;
  318. case WinStationSecureDesktopEnter :
  319. if ( pWinStation->hStack ) {
  320. // Check for availability
  321. if ( pWinStation->pWsx &&
  322. pWinStation->pWsx->pWsxIcaStackIoControl ) {
  323. Status = pWinStation->pWsx->pWsxIcaStackIoControl(
  324. pWinStation->pWsxContext,
  325. pWinStation->hIca,
  326. pWinStation->hStack,
  327. IOCTL_ICA_STACK_ENCRYPTION_ENTER,
  328. pWinStationInformation,
  329. WinStationInformationLength,
  330. NULL,
  331. 0,
  332. NULL );
  333. }
  334. else {
  335. Status = STATUS_INVALID_INFO_CLASS;
  336. }
  337. }
  338. break;
  339. case WinStationSecureDesktopExit :
  340. if ( pWinStation->hStack ) {
  341. // Check for availability
  342. if ( pWinStation->pWsx &&
  343. pWinStation->pWsx->pWsxIcaStackIoControl ) {
  344. Status = pWinStation->pWsx->pWsxIcaStackIoControl(
  345. pWinStation->pWsxContext,
  346. pWinStation->hIca,
  347. pWinStation->hStack,
  348. IOCTL_ICA_STACK_ENCRYPTION_EXIT,
  349. pWinStationInformation,
  350. WinStationInformationLength,
  351. NULL,
  352. 0,
  353. NULL );
  354. }
  355. else {
  356. Status = STATUS_INVALID_INFO_CLASS;
  357. }
  358. }
  359. break;
  360. /*
  361. * Give focus to winlogon security desktop
  362. * -- used by progman.exe
  363. */
  364. case WinStationNtSecurity :
  365. /*
  366. * Tell the WinStation to Send Winlogon the CTR-ALT-DEL message
  367. */
  368. msg.ApiNumber = SMWinStationNtSecurity;
  369. Status = SendWinStationCommand( pWinStation, &msg, 0 );
  370. break;
  371. case WinStationClientData :
  372. //
  373. // Handles multiple client data items. The data buffer
  374. // format is:
  375. // ULONG // Length of next data item
  376. // WINSTATIONCLIENTDATA // Including variable length part
  377. // ULONG // Length of next data item
  378. // WINSTATIONCLIENTDATA // Including variable length part
  379. // etc
  380. //
  381. // WinStationInformationLength is the length of the entire
  382. // data buffer. Keep processing client data items until
  383. // the buffer is exhausted.
  384. //
  385. if ( WinStationInformationLength < sizeof(ULONG) +
  386. sizeof(WINSTATIONCLIENTDATA) )
  387. {
  388. Status = STATUS_INFO_LENGTH_MISMATCH;
  389. break;
  390. }
  391. if ( pWinStation->hStack )
  392. {
  393. // Check for availability
  394. if ( pWinStation->pWsx &&
  395. pWinStation->pWsx->pWsxIcaStackIoControl )
  396. {
  397. ULONG CurLen;
  398. ULONG LenUsed =0;
  399. PBYTE CurPtr = (PBYTE)pWinStationInformation;
  400. while (LenUsed + sizeof(ULONG) < WinStationInformationLength)
  401. {
  402. CurLen = *(ULONG UNALIGNED *)CurPtr;
  403. LenUsed += sizeof(ULONG);
  404. CurPtr += sizeof(ULONG);
  405. if ( (LenUsed + CurLen >= LenUsed) &&
  406. (LenUsed + CurLen <= WinStationInformationLength))
  407. {
  408. Status = pWinStation->pWsx->pWsxIcaStackIoControl(
  409. pWinStation->pWsxContext,
  410. pWinStation->hIca,
  411. pWinStation->hStack,
  412. IOCTL_ICA_STACK_SET_CLIENT_DATA,
  413. CurPtr,
  414. CurLen,
  415. NULL,
  416. 0,
  417. NULL );
  418. LenUsed += CurLen;
  419. CurPtr += CurLen;
  420. }else
  421. {
  422. Status = STATUS_INVALID_USER_BUFFER;
  423. break;
  424. }
  425. }
  426. }
  427. else
  428. {
  429. Status = STATUS_INVALID_INFO_CLASS;
  430. }
  431. }
  432. break;
  433. case WinStationInitialProgram :
  434. /*
  435. * Identify first program, non-consoles only
  436. */
  437. if ( LogonId != 0 ) {
  438. /*
  439. * Tell the WinStation this is the initial program
  440. */
  441. msg.ApiNumber = SMWinStationInitialProgram;
  442. Status = SendWinStationCommand( pWinStation, &msg, 0 );
  443. }
  444. break;
  445. case WinStationShadowInfo:
  446. Status = _CheckCallerLocalAndSystem();
  447. if( NT_SUCCESS(Status) ) {
  448. Status = WinStationShadowChangeMode( pWinStation,
  449. (PWINSTATIONSHADOW) pWinStationInformation,
  450. WinStationInformationLength );
  451. }
  452. break;
  453. case WinStationLockedState:
  454. {
  455. BOOL bLockedState;
  456. if (WinStationInformationLength == sizeof(bLockedState))
  457. {
  458. bLockedState = * (LPBOOL) pWinStationInformation;
  459. Status = SetLockedState (pWinStation, bLockedState);
  460. }
  461. else
  462. {
  463. Status = STATUS_INFO_LENGTH_MISMATCH;
  464. }
  465. break;
  466. }
  467. case WinStationDisallowAutoReconnect:
  468. {
  469. RpcStatus = RpcImpersonateClient( NULL );
  470. if( RpcStatus != RPC_S_OK ) {
  471. Status = STATUS_CANNOT_IMPERSONATE;
  472. break;
  473. }
  474. if (!IsCallerSystem()) {
  475. Status = STATUS_ACCESS_DENIED;
  476. }
  477. RpcRevertToSelf();
  478. if (Status != STATUS_SUCCESS) {
  479. break;
  480. }
  481. if (WinStationInformationLength == sizeof(BOOLEAN)) {
  482. pWinStation->fDisallowAutoReconnect = * (PBOOLEAN) pWinStationInformation;
  483. } else {
  484. Status = STATUS_INFO_LENGTH_MISMATCH;
  485. }
  486. break;
  487. }
  488. case WinStationMprNotifyInfo:
  489. {
  490. Status = _CheckCallerLocalAndSystem();
  491. if (Status != STATUS_SUCCESS) {
  492. break;
  493. }
  494. if (WinStationInformationLength == sizeof(ExtendedClientCredentials)) {
  495. pExtendedClientCredentials pMprInfo ;
  496. pMprInfo = (pExtendedClientCredentials) pWinStationInformation;
  497. wcsncpy(g_MprNotifyInfo.Domain, pMprInfo->Domain, EXTENDED_DOMAIN_LEN);
  498. g_MprNotifyInfo.Domain[EXTENDED_DOMAIN_LEN] = L'\0';
  499. wcsncpy(g_MprNotifyInfo.UserName, pMprInfo->UserName, EXTENDED_USERNAME_LEN);
  500. g_MprNotifyInfo.UserName[EXTENDED_USERNAME_LEN] = L'\0';
  501. wcsncpy(g_MprNotifyInfo.Password, pMprInfo->Password, EXTENDED_PASSWORD_LEN);
  502. g_MprNotifyInfo.Password[EXTENDED_PASSWORD_LEN] = L'\0';
  503. } else {
  504. Status = STATUS_INFO_LENGTH_MISMATCH;
  505. }
  506. break;
  507. }
  508. case WinStationExecSrvSystemPipe:
  509. RpcStatus = RpcImpersonateClient( NULL );
  510. if( RpcStatus != RPC_S_OK ) {
  511. Status = STATUS_CANNOT_IMPERSONATE;
  512. break;
  513. }
  514. if (!IsCallerSystem()) {
  515. Status = STATUS_ACCESS_DENIED;
  516. }
  517. RpcRevertToSelf();
  518. if (Status != STATUS_SUCCESS) {
  519. break;
  520. }
  521. if ( WinStationInformationLength <= ( EXECSRVPIPENAMELEN * sizeof(WCHAR) ) ) {
  522. memcpy( pWinStation->ExecSrvSystemPipe, pWinStationInformation, WinStationInformationLength );
  523. }
  524. break;
  525. default:
  526. /*
  527. * Fail the call
  528. */
  529. Status = STATUS_INVALID_INFO_CLASS;
  530. break;
  531. }
  532. ReleaseWinStation( pWinStation );
  533. TRACE((hTrace,TC_ICASRV,TT_API2,"TERMSRV: WinStationSetInformation LogonId=%d, Class=%d, Status=0x%x\n",
  534. LogonId, (ULONG)WinStationInformationClass, Status));
  535. return( Status );
  536. }
  537. /*******************************************************************************
  538. *
  539. * _SetConfig
  540. *
  541. * Set window station configuration
  542. * This API does not do a user policy or user pref merge between source and destination,
  543. * the caller of this API ( assuming the Set privilage is set) will be able to change the
  544. * config data of an already active session, although only the shadow value has an impact (in practise).
  545. * The rest of the values are only used upon login, nothing happens after login. The reason
  546. * Shadow is different is becasue the shadow thread which uses the shadow info only start
  547. * (and reads config data) when shadowing, so as logn as shadow session has not started, you
  548. * can use this api to change the shadow value and have an impact on this session's behavior in
  549. * as far as shadow is concerned.
  550. *
  551. *
  552. * ENTRY:
  553. * pWinStation (input)
  554. * pointer to citrix window station structure
  555. * pConfig (input)
  556. * pointer to configuration structure
  557. * Length (input)
  558. * length of configuration structure
  559. *
  560. * EXIT:
  561. * STATUS_SUCCESS - no error
  562. *
  563. ******************************************************************************/
  564. NTSTATUS
  565. _SetConfig( PWINSTATION pWinStation,
  566. PWINSTATIONCONFIG pConfig,
  567. ULONG Length )
  568. {
  569. USERCONFIG UserConfig;
  570. NTSTATUS Status;
  571. /*
  572. * Validate length
  573. */
  574. if ( Length < sizeof(WINSTATIONCONFIG) )
  575. return( STATUS_BUFFER_TOO_SMALL );
  576. /*
  577. * Check the input configuration
  578. */
  579. Status = ValidateInputConfig(pWinStation, pConfig );
  580. if (Status != STATUS_SUCCESS) {
  581. return Status;
  582. }
  583. /*
  584. * Copy structure
  585. */
  586. pWinStation->Config.Config = *pConfig;
  587. /*
  588. * Merge client data into winstation structure
  589. */
  590. if ( pWinStation->pWsx &&
  591. pWinStation->pWsx->pWsxInitializeUserConfig ) {
  592. pWinStation->pWsx->pWsxInitializeUserConfig( pWinStation->pWsxContext,
  593. pWinStation->hStack,
  594. pWinStation->hIcaThinwireChannel,
  595. &pWinStation->Config.Config.User,
  596. &pWinStation->Client.HRes,
  597. &pWinStation->Client.VRes,
  598. &pWinStation->Client.ColorDepth);
  599. }
  600. #if NT2195
  601. // in win2k, this could accomplish nothing since all of userconfigw data was already consumed
  602. // by various TS modules at login time, changing them while a session was active had no impact.
  603. // The same is true when you use TSCC to make a change, it warns you that changes will not affect
  604. // live sessions, etc.
  605. /*
  606. * If user is logged on -> merge user profile data
  607. */
  608. if ( pWinStation->UserName[0] ) {
  609. /*
  610. * Read user profile data
  611. */
  612. _ReadUserProfile( pWinStation->Domain,
  613. pWinStation->UserName,
  614. &UserConfig );
  615. /*
  616. * Merge user config data into the winstation
  617. */
  618. MergeUserConfigData( pWinStation, &UserConfig );
  619. }
  620. #endif
  621. /*
  622. * Convert any "published app" to absolute path
  623. */
  624. if ( pWinStation->pWsx &&
  625. pWinStation->pWsx->pWsxConvertPublishedApp ) {
  626. (void) pWinStation->pWsx->pWsxConvertPublishedApp( pWinStation->pWsxContext,
  627. &pWinStation->Config.Config.User);
  628. }
  629. return( STATUS_SUCCESS );
  630. }
  631. NTSTATUS
  632. ValidateInputConfig( PWINSTATION pWinStation, PWINSTATIONCONFIG pConfig )
  633. {
  634. NTSTATUS Status = STATUS_SUCCESS;
  635. pConfig->User.UserName[ USERNAME_LENGTH ] = L'\0';
  636. pConfig->User.Domain[ DOMAIN_LENGTH ] = L'\0';
  637. pConfig->User.Password[ PASSWORD_LENGTH ] = L'\0';
  638. pConfig->User.WorkDirectory[ DIRECTORY_LENGTH ] = L'\0';
  639. pConfig->User.InitialProgram[ INITIALPROGRAM_LENGTH] = L'\0';
  640. pConfig->User.CallbackNumber[ CALLBACK_LENGTH ] = L'\0';
  641. /* fInheritSecurity */
  642. //BYTE MinEncryptionLevel;
  643. pConfig->User.NWLogonServer[ NASIFILESERVER_LENGTH] = L'\0';
  644. /* WinFrame Profile Path - Overrides standard profile path */
  645. pConfig->User.WFProfilePath[ DIRECTORY_LENGTH ] = L'\0';
  646. /* WinFrame Home Directory - Overrides standard Home Directory */
  647. pConfig->User.WFHomeDir[ DIRECTORY_LENGTH ] = L'\0';
  648. return Status;
  649. }
  650. /*******************************************************************************
  651. *
  652. * _ReadUserProfile
  653. *
  654. * This routine reads the user profile data from the registry
  655. *
  656. * ENTRY:
  657. * pDomain (input)
  658. * domain of user
  659. * pUserName (input)
  660. * user name to read
  661. * pUserConfig (output)
  662. * address to return user profile data
  663. *
  664. * EXIT:
  665. * None.
  666. *
  667. ******************************************************************************/
  668. VOID
  669. _ReadUserProfile( PWCHAR pDomain, PWCHAR pUserName, PUSERCONFIG pUserConfig )
  670. {
  671. PWCHAR pServerName;
  672. ULONG Length;
  673. LONG Error;
  674. /*
  675. * Get Domain Controller name and userconfig data.
  676. * If no userconfig data for user then get default values.
  677. */
  678. if ( ghNetApiDll == NULL ) {
  679. ghNetApiDll = LoadLibrary( L"NETAPI32" );
  680. if ( ghNetApiDll ) {
  681. pNetGetAnyDCName = GetProcAddress( ghNetApiDll, "NetGetAnyDCName" );
  682. pNetApiBufferFree = GetProcAddress( ghNetApiDll, "NetApiBufferFree" );
  683. }
  684. }
  685. /*
  686. * Check to make sure we got a server name
  687. */
  688. if ( pNetGetAnyDCName == NULL ||
  689. pNetGetAnyDCName( NULL, pDomain, (LPBYTE *)&pServerName ) != ERROR_SUCCESS )
  690. pServerName = NULL;
  691. /*
  692. * Read user profile data
  693. */
  694. Error = RegUserConfigQuery( pServerName,
  695. pUserName,
  696. pUserConfig,
  697. sizeof(USERCONFIG),
  698. &Length );
  699. TRACE((hTrace,TC_ICASRV,TT_API1, "RegUserConfigQuery: \\\\%S\\%S, server %S, Error=%u\n",
  700. pDomain, pUserName, pServerName, Error ));
  701. if ( Error != ERROR_SUCCESS ) {
  702. Error = RegDefaultUserConfigQuery( pServerName, pUserConfig,
  703. sizeof(USERCONFIG), &Length );
  704. TRACE((hTrace,TC_ICASRV,TT_ERROR, "RegDefaultUserConfigQuery, Error=%u\n", Error ));
  705. }
  706. /*
  707. * Free memory
  708. */
  709. if ( pServerName && pNetApiBufferFree )
  710. pNetApiBufferFree( pServerName );
  711. }
  712. /*******************************************************************************
  713. *
  714. * _SetBeep
  715. *
  716. * Beep the WinStation
  717. *
  718. * ENTRY:
  719. * pWinStation (input)
  720. * pointer to citrix window station structure
  721. * pBeepInput (input)
  722. * pointer to Beep input structure
  723. * Length (input)
  724. * length of Beep input structure
  725. *
  726. * EXIT:
  727. * STATUS_SUCCESS - no error
  728. *
  729. ******************************************************************************/
  730. NTSTATUS
  731. _SetBeep( PWINSTATION pWinStation,
  732. PBEEPINPUT pBeepInput,
  733. ULONG Length)
  734. {
  735. NTSTATUS Status = STATUS_SUCCESS;
  736. BEEP_SET_PARAMETERS BeepParameters;
  737. IO_STATUS_BLOCK IoStatus;
  738. /*
  739. * Do the regular Beep, so you can support fancy Beeps from
  740. * sound cards.
  741. */
  742. if ( pWinStation->LogonId == 0 ) {
  743. if ( MessageBeep( pBeepInput->uType ) )
  744. return( STATUS_SUCCESS );
  745. else
  746. return( STATUS_UNSUCCESSFUL );
  747. }
  748. BeepParameters.Frequency = 440;
  749. BeepParameters.Duration = 125;
  750. if ( pWinStation->hIcaBeepChannel ) {
  751. Status = NtDeviceIoControlFile( pWinStation->hIcaBeepChannel,
  752. NULL,
  753. NULL,
  754. NULL,
  755. &IoStatus,
  756. IOCTL_BEEP_SET,
  757. &BeepParameters,
  758. sizeof( BeepParameters ),
  759. NULL,
  760. 0
  761. );
  762. }
  763. return( STATUS_SUCCESS );
  764. }