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.

1391 lines
45 KiB

  1. /*
  2. * Includes
  3. */
  4. #include <nt.h>
  5. #include <ntrtl.h>
  6. #include <nturtl.h>
  7. #include <ntlsa.h>
  8. #include <ntsam.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <windows.h>
  12. #include <lm.h>
  13. #include <winsta.h>
  14. #include <rpc.h>
  15. #include <rpcdce.h>
  16. #include <ntdsapi.h>
  17. // For more info, check out \\index1\src\nt\private\security\tools\delegate\ldap.c
  18. #include "usrprop.h"
  19. #include "regapi.h"
  20. extern "C" {
  21. BOOLEAN RegGetUserPolicy( LPWSTR userSID , PPOLICY_TS_USER pPolicy , PUSERCONFIGW pData );
  22. void RegGetMachinePolicy( PPOLICY_TS_MACHINE pPolicy );
  23. void RegMergeMachinePolicy( PPOLICY_TS_MACHINE pPolicy, USERCONFIGW *pMachineConfigData ,
  24. WINSTATIONCREATE * pCreate );
  25. BOOLEAN RegDenyTSConnectionsPolicy();
  26. DWORD WaitForTSConnectionsPolicyChanges( BOOLEAN bWaitForAccept, HANDLE hExtraEvent);
  27. BOOLEAN RegGetMachinePolicyEx(
  28. BOOLEAN forcePolicyRead,
  29. FILETIME *pTime ,
  30. PPOLICY_TS_MACHINE pPolicy );
  31. BOOLEAN RegIsMachineInHelpMode();
  32. BOOLEAN RegIsTimeZoneRedirectionEnabled();
  33. }
  34. extern "C"
  35. {
  36. //
  37. HKEY g_hTSPolicyKey = NULL;//handle to TS_POLICY_SUB_TREE key
  38. HKEY g_hTSControlKey = NULL;//handle to REG_CONTROL_TSERVER key
  39. }
  40. /******************************************************************
  41. * *
  42. * Check to see if the policy is set to stop accepting connections *
  43. * *
  44. ******************************************************************/
  45. BOOLEAN RegDenyTSConnectionsPolicy()
  46. {
  47. LONG errorCode = ERROR_SUCCESS;
  48. DWORD ValueType;
  49. DWORD ValueSize = sizeof(DWORD);
  50. DWORD valueData ;
  51. //
  52. // first check the policy tree,
  53. //
  54. if( !g_hTSPolicyKey )
  55. {
  56. errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TS_POLICY_SUB_TREE, 0,
  57. KEY_READ, &g_hTSPolicyKey );
  58. //If error code is ERROR_FILE_NOT_FOUND, this is not an error.
  59. if( !g_hTSPolicyKey && errorCode != ERROR_FILE_NOT_FOUND )
  60. {
  61. //we could not open policy key for some reason other
  62. //than key not found.
  63. //return TRUE to be on the safe side
  64. return TRUE;
  65. }
  66. }
  67. if ( g_hTSPolicyKey )
  68. {
  69. errorCode = RegQueryValueEx( g_hTSPolicyKey, POLICY_DENY_TS_CONNECTIONS , NULL, &ValueType,
  70. (LPBYTE) &valueData, &ValueSize );
  71. switch( errorCode )
  72. {
  73. case ERROR_SUCCESS :
  74. return ( valueData ? TRUE : FALSE ) ; // we have data from the policyKey handle to return
  75. break;
  76. case ERROR_KEY_DELETED:
  77. // Group policy must have deleted this key, close it
  78. // Then, below we check for the local machine key
  79. RegCloseKey( g_hTSPolicyKey );
  80. g_hTSPolicyKey = NULL;
  81. break;
  82. case ERROR_FILE_NOT_FOUND:
  83. // there is no policy from GP, so see (below) what the local machine
  84. // value has.
  85. break;
  86. default:
  87. // if we are having any other kind of a problem, claim TRUE and
  88. // stop connections to be on the safe side (a security angle).
  89. return TRUE;
  90. break;
  91. }
  92. }
  93. // if we got this far, then no policy was set. Check the local machine now.
  94. if( !g_hTSControlKey )
  95. {
  96. errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
  97. KEY_READ, &g_hTSControlKey );
  98. }
  99. if ( g_hTSControlKey )
  100. {
  101. errorCode = RegQueryValueEx( g_hTSControlKey, POLICY_DENY_TS_CONNECTIONS , NULL, &ValueType,
  102. (LPBYTE) &valueData, &ValueSize );
  103. if (errorCode == ERROR_SUCCESS )
  104. {
  105. return ( valueData ? TRUE : FALSE ) ; // we have data from the policyKey handle to return
  106. }
  107. }
  108. // if no localKey, gee... the registry is missing data... return TRUE to be on the safe side
  109. return TRUE;
  110. }
  111. /******************************************************************
  112. * *
  113. * Wait until POLICY_DENY_TS_CONNECTIONS is changed *
  114. * *
  115. * Parameters: *
  116. * bWaitForAccept *
  117. * if TRUE, test if connections are accepted and wait for *
  118. * them to be accepted if they are not currently accepted. *
  119. * if FALSE, test if connections are not accepted and wait *
  120. * for them to be denied if they are currently accepted. *
  121. * *
  122. * hExtraEvent *
  123. * optional handle to an event to wait for. *
  124. * *
  125. * Returns: *
  126. * WAIT_OBJECT_0 *
  127. * if a change in TS connections policy occurred *
  128. * *
  129. * WAIT_OBJECT_0 + 1 *
  130. * if the extra event is present and signaled *
  131. * *
  132. ******************************************************************/
  133. //
  134. // Note that opening the global g_hTSControlKey without protection
  135. // can cause the key to be opened twice.
  136. //
  137. // This macro is TRUE if the TS connections are denied
  138. #define TSConnectionsDenied (RegDenyTSConnectionsPolicy() && \
  139. !(RegIsMachinePolicyAllowHelp() && RegIsMachineInHelpMode()))
  140. DWORD WaitForTSConnectionsPolicyChanges(
  141. BOOLEAN bWaitForAccept,
  142. HANDLE hExtraEvent
  143. )
  144. {
  145. DWORD errorCode = ERROR_SUCCESS;
  146. HKEY hControlKey = NULL;
  147. HKEY hPoliciesKey = NULL;
  148. HKEY hFipsPolicy = NULL;
  149. HANDLE hEvents[4] = { NULL, NULL, NULL, NULL };
  150. //
  151. // Wait for a policy change if
  152. // we want TS connections and they are denied OR
  153. // we don't want TS connections and they are accepted
  154. //
  155. if((bWaitForAccept && TSConnectionsDenied) ||
  156. (!bWaitForAccept && !TSConnectionsDenied))
  157. {
  158. errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
  159. KEY_READ, &hControlKey );
  160. if( !hControlKey )
  161. {
  162. goto error_exit;
  163. }
  164. //We cannot wait for g_hTSPolicyKey because it can be deleted and created
  165. //Instead we wait for HKLM\Policies key
  166. errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Policies"), 0,
  167. KEY_READ, &hPoliciesKey );
  168. if( !hPoliciesKey )
  169. {
  170. goto error_exit;
  171. }
  172. errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TS_FIPS_POLICY, 0,
  173. KEY_READ, &hFipsPolicy );
  174. hEvents[0] = CreateEvent(NULL,FALSE,FALSE,NULL);
  175. if( !hEvents[0])
  176. {
  177. errorCode = GetLastError();
  178. goto error_exit;
  179. }
  180. hEvents[1] = CreateEvent(NULL,FALSE,FALSE,NULL);
  181. if( !hEvents[1])
  182. {
  183. errorCode = GetLastError();
  184. goto error_exit;
  185. }
  186. hEvents[2] = CreateEvent(NULL,FALSE,FALSE,NULL);
  187. if( !hEvents[2])
  188. {
  189. errorCode = GetLastError();
  190. goto error_exit;
  191. }
  192. hEvents[3] = hExtraEvent;
  193. DWORD whichObject;
  194. errorCode = RegNotifyChangeKeyValue(hControlKey,
  195. FALSE,REG_NOTIFY_CHANGE_LAST_SET,
  196. hEvents[0], TRUE );
  197. if( errorCode != ERROR_SUCCESS )
  198. {
  199. goto error_exit;
  200. }
  201. errorCode = RegNotifyChangeKeyValue(hPoliciesKey,
  202. TRUE,REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_NAME,
  203. hEvents[1], TRUE );
  204. if( errorCode != ERROR_SUCCESS )
  205. {
  206. goto error_exit;
  207. }
  208. errorCode = RegNotifyChangeKeyValue(hFipsPolicy,
  209. TRUE,REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_NAME,
  210. hEvents[2], TRUE );
  211. if( errorCode != ERROR_SUCCESS )
  212. {
  213. goto error_exit;
  214. }
  215. if ( hExtraEvent == NULL )
  216. {
  217. whichObject = WaitForMultipleObjects(3,hEvents,FALSE,INFINITE);
  218. }
  219. else
  220. {
  221. whichObject = WaitForMultipleObjects(4,hEvents,FALSE,INFINITE);
  222. }
  223. errorCode = GetLastError();
  224. CloseHandle( hEvents[0] );
  225. CloseHandle( hEvents[1] );
  226. CloseHandle( hEvents[2] );
  227. RegCloseKey(hPoliciesKey);
  228. RegCloseKey(hControlKey);
  229. RegCloseKey(hFipsPolicy);
  230. if(whichObject == WAIT_FAILED)
  231. {
  232. SetLastError( errorCode );
  233. return WAIT_FAILED;
  234. }
  235. else
  236. {
  237. if ( whichObject >= WAIT_OBJECT_0 + 2 )
  238. {
  239. return WAIT_OBJECT_0 + 1;
  240. }
  241. else
  242. {
  243. return WAIT_OBJECT_0;
  244. }
  245. }
  246. }
  247. return WAIT_OBJECT_0;
  248. error_exit:
  249. if(hEvents[0])
  250. {
  251. CloseHandle( hEvents[0] );
  252. }
  253. if(hEvents[1])
  254. {
  255. CloseHandle( hEvents[1] );
  256. }
  257. if(hEvents[2])
  258. {
  259. CloseHandle( hEvents[2] );
  260. }
  261. if(hPoliciesKey)
  262. {
  263. RegCloseKey(hPoliciesKey);
  264. }
  265. if(hControlKey)
  266. {
  267. RegCloseKey(hControlKey);
  268. }
  269. if(hFipsPolicy)
  270. {
  271. RegCloseKey(hFipsPolicy);
  272. }
  273. SetLastError( errorCode );
  274. return WAIT_FAILED;
  275. }
  276. /********************************************************************************
  277. *
  278. * GPGetNumValue()
  279. *
  280. * Params
  281. * [in] policyKey : hkey to the policy reg tree where values are stored
  282. * [in] ValueName : name of the value (which is the policy) we are looking for
  283. * [out] pValueData: the data for the policy
  284. *
  285. * Return:
  286. * if the policy defined by the passed in valuename is present, then
  287. * return TRUE. Else, return FALSE
  288. *
  289. ********************************************************************************/
  290. BOOLEAN GPGetNumValue(
  291. HKEY policyKey,
  292. LPWSTR ValueName,
  293. DWORD *pValueData )
  294. {
  295. LONG Status = ERROR_SUCCESS;
  296. DWORD ValueType;
  297. DWORD ValueSize = sizeof(DWORD);
  298. // init data value to zero, just to get Prefix off our backs. This is a wasted OP
  299. // since unless policy is set, value is not used.
  300. *pValueData = 0;
  301. //
  302. // See if any values are present from the policyKey .
  303. //
  304. if ( policyKey )
  305. {
  306. Status = RegQueryValueEx( policyKey, ValueName, NULL, &ValueType,
  307. (LPBYTE) pValueData, &ValueSize );
  308. if (Status == ERROR_SUCCESS )
  309. {
  310. return TRUE; // we have data from the policyKey handle to return
  311. }
  312. }
  313. // else, no key means policy is not set
  314. return FALSE;
  315. }
  316. /********************************************************************************
  317. *
  318. * GPGetStringValue()
  319. *
  320. * same as GPGetNumValue() but for policies that have a string value
  321. *
  322. *
  323. ********************************************************************************/
  324. BOOLEAN
  325. GPGetStringValue( HKEY policyKey,
  326. LPWSTR ValueName,
  327. LPWSTR pValueData,
  328. DWORD MaxValueSize )
  329. {
  330. LONG Status;
  331. DWORD ValueType;
  332. DWORD ValueSize = MaxValueSize << 1;
  333. if (policyKey )
  334. {
  335. Status = RegQueryValueEx( policyKey, ValueName, NULL, &ValueType,
  336. (LPBYTE) pValueData, &ValueSize );
  337. if ( Status != ERROR_SUCCESS || ValueSize == sizeof(UNICODE_NULL) )
  338. {
  339. return FALSE; // no data found.
  340. }
  341. else
  342. {
  343. if ( ValueType != REG_SZ )
  344. {
  345. return FALSE; // bad data, pretend we have no data.
  346. }
  347. }
  348. // we did get data
  349. return( TRUE );
  350. }
  351. return FALSE;
  352. }
  353. /********************************************************************************
  354. *
  355. * GPGetStringValue()
  356. *
  357. * Variant of the above function that returns false if error happens, but not
  358. * when value does not exist.
  359. * If the value does not exist it sets bValueExists to FALSE.
  360. *
  361. *
  362. ********************************************************************************/
  363. extern "C"
  364. BOOLEAN
  365. GPGetStringValue( HKEY policyKey,
  366. LPWSTR ValueName,
  367. LPWSTR pValueData,
  368. DWORD MaxValueSize,
  369. BOOLEAN *pbValueExists)
  370. {
  371. LONG Status;
  372. DWORD ValueType;
  373. DWORD ValueSize = MaxValueSize << 1;
  374. if(!pValueData || !MaxValueSize)
  375. {
  376. return FALSE;
  377. }
  378. *pbValueExists = FALSE;
  379. pValueData[0] = 0;
  380. if (policyKey )
  381. {
  382. Status = RegQueryValueEx( policyKey, ValueName, NULL, &ValueType,
  383. (LPBYTE) pValueData, &ValueSize );
  384. if ( Status == ERROR_FILE_NOT_FOUND || ValueSize == sizeof(UNICODE_NULL) )
  385. {
  386. return TRUE; // no data found.
  387. }
  388. else
  389. {
  390. if ( Status != ERROR_SUCCESS || ValueType != REG_SZ )
  391. {
  392. return FALSE; // bad data, DO NOT pretend we have no data.
  393. }
  394. }
  395. // we did get data
  396. *pbValueExists = TRUE;
  397. return( TRUE );
  398. }
  399. else
  400. {
  401. //Policy key may not exist. Now we pretend we have no data!
  402. return TRUE;
  403. }
  404. }
  405. /*******************************************************************************
  406. *
  407. * GPQueryUserConfig
  408. *
  409. * query USERCONFIG structure
  410. *
  411. * Params:
  412. * policyKey : hkey to the HKCU policy tree
  413. * pPolicy : points to the user policy struct which has flags for any policy
  414. * value that is present in the policy tree
  415. * pUser : pointer to a userconfigw struct used as a sracth pad to hold the
  416. * policy values (if present).
  417. * Return:
  418. * void
  419. *
  420. ******************************************************************************/
  421. VOID
  422. GPQueryUserConfig( HKEY policyKey, PPOLICY_TS_USER pPolicy , PUSERCONFIGW pUser )
  423. {
  424. UCHAR seed;
  425. UNICODE_STRING UnicodePassword;
  426. WCHAR encPassword[ PASSWORD_LENGTH + 2 ];
  427. DWORD dwTmpValue;
  428. // ----------------
  429. pPolicy->fPolicyInitialProgram = GPGetStringValue( policyKey, WIN_INITIALPROGRAM,
  430. pUser->InitialProgram,
  431. INITIALPROGRAM_LENGTH + 1 );
  432. GPGetStringValue( policyKey, WIN_WORKDIRECTORY,
  433. pUser->WorkDirectory,
  434. DIRECTORY_LENGTH + 1 );
  435. // ----------------
  436. pPolicy->fPolicyResetBroken =
  437. GPGetNumValue( policyKey,WIN_RESETBROKEN , & dwTmpValue );
  438. pUser->fResetBroken = (BOOLEAN) dwTmpValue;
  439. // ----------------
  440. pPolicy->fPolicyReconnectSame =
  441. GPGetNumValue( policyKey,WIN_RECONNECTSAME , &dwTmpValue );
  442. pUser->fReconnectSame = (BOOLEAN) dwTmpValue;
  443. // ----------------
  444. pPolicy->fPolicyShadow =
  445. GPGetNumValue( policyKey, WIN_SHADOW, &dwTmpValue );
  446. pUser->Shadow = (SHADOWCLASS) dwTmpValue;
  447. // ----------------
  448. pPolicy->fPolicyMaxSessionTime =
  449. GPGetNumValue( policyKey, WIN_MAXCONNECTIONTIME , &dwTmpValue );
  450. pUser->MaxConnectionTime = dwTmpValue;
  451. // ----------------
  452. pPolicy->fPolicyMaxDisconnectionTime =
  453. GPGetNumValue( policyKey,WIN_MAXDISCONNECTIONTIME ,&dwTmpValue );
  454. pUser->MaxDisconnectionTime = dwTmpValue;
  455. // ----------------
  456. pPolicy->fPolicyMaxIdleTime =
  457. GPGetNumValue( policyKey,WIN_MAXIDLETIME , &dwTmpValue );
  458. pUser->MaxIdleTime = dwTmpValue;
  459. // ----------------
  460. pPolicy->fPolicyCallback =
  461. GPGetNumValue( policyKey, WIN_CALLBACK, &dwTmpValue );
  462. pUser->Callback = (CALLBACKCLASS ) dwTmpValue;
  463. // ----------------
  464. pPolicy->fPolicyCallbackNumber =
  465. GPGetStringValue( policyKey, WIN_CALLBACKNUMBER,
  466. pUser->CallbackNumber,
  467. CALLBACK_LENGTH + 1 );
  468. // ----------------
  469. pPolicy->fPolicyAutoClientDrives =
  470. GPGetNumValue( policyKey,WIN_AUTOCLIENTDRIVES , &dwTmpValue );
  471. pUser->fAutoClientDrives = (BOOLEAN) dwTmpValue;
  472. // ----------------
  473. pPolicy->fPolicyAutoClientLpts =
  474. GPGetNumValue( policyKey,WIN_AUTOCLIENTLPTS , &dwTmpValue );
  475. pUser->fAutoClientLpts = (BOOLEAN) dwTmpValue;
  476. // ----------------
  477. pPolicy->fPolicyForceClientLptDef =
  478. GPGetNumValue( policyKey,WIN_FORCECLIENTLPTDEF , &dwTmpValue );
  479. pUser->fForceClientLptDef = (BOOLEAN) dwTmpValue;
  480. }
  481. /*******************************************************************************
  482. * RegGetUserPolicy()
  483. *
  484. * Params:
  485. * [in] userSID : user sid in a text format
  486. * [out] pPolicy : user policy struct
  487. * [out] pUser : policy values
  488. *
  489. * Return:
  490. * BOOLEAN : TRUE if user policy was found
  491. * FALSE if there was a problem getting user policy
  492. *******************************************************************************/
  493. BOOLEAN RegGetUserPolicy(
  494. LPWSTR userSID ,
  495. PPOLICY_TS_USER pPolicy,
  496. PUSERCONFIGW pUser )
  497. {
  498. DWORD status= ERROR_SUCCESS;
  499. HKEY policyKey;
  500. WCHAR userHive [MAX_PATH];
  501. if (userSID) // this would never happen, but Master Prefix complains and we must server him!
  502. {
  503. wcscpy(userHive, userSID);
  504. wcscat(userHive, L"\\");
  505. wcscat(userHive, TS_POLICY_SUB_TREE );
  506. status = RegOpenKeyEx( HKEY_USERS, userHive , 0,
  507. KEY_READ, &policyKey );
  508. if (status == ERROR_SUCCESS )
  509. {
  510. GPQueryUserConfig( policyKey, pPolicy, pUser );
  511. RegCloseKey( policyKey );
  512. return TRUE;
  513. }
  514. }
  515. return FALSE;
  516. }
  517. /*******************************************************************************
  518. * GPQueryMachineConfig()
  519. *
  520. * Params:
  521. * [in] policyKey : key to the policy tree under hklm
  522. * [out] pPolicy : pointer to a machine policy data that is filled up by this function
  523. *
  524. * Return:
  525. * void
  526. *
  527. *
  528. * !!! WARNING !!!
  529. *
  530. * All TS related values MUST be in the flat TS-POLICY-TREE, no sub keys.
  531. * This is due to the fact that time-stamp checks by the caller of RegGetMachinePolicyEx() will
  532. * check the time stamp on the TS-POLICY key, which is NOT updated when a value in a sub-key is
  533. * altered.
  534. *
  535. *
  536. *******************************************************************************/
  537. void GPQueryMachineConfig( HKEY policyKey, PPOLICY_TS_MACHINE pPolicy )
  538. {
  539. DWORD dwTmpValue;
  540. // ---------------- SessionDirectoryActive
  541. pPolicy->fPolicySessionDirectoryActive =
  542. GPGetNumValue( policyKey,WIN_SESSIONDIRECTORYACTIVE, &dwTmpValue );
  543. pPolicy->SessionDirectoryActive = (BOOLEAN) dwTmpValue;
  544. // ---------------- SessionDirectoryLocation
  545. pPolicy->fPolicySessionDirectoryLocation = GPGetStringValue( policyKey, WIN_SESSIONDIRECTORYLOCATION ,
  546. pPolicy->SessionDirectoryLocation,
  547. DIRECTORY_LENGTH + 1 );
  548. // ---------------- SessionDirectoryClusterName
  549. pPolicy->fPolicySessionDirectoryClusterName = GPGetStringValue( policyKey, WIN_SESSIONDIRECTORYCLUSTERNAME ,
  550. pPolicy->SessionDirectoryClusterName,
  551. DIRECTORY_LENGTH + 1 );
  552. // ---------------- SessionDirectoryAdditionalParams
  553. pPolicy->fPolicySessionDirectoryAdditionalParams = GPGetStringValue( policyKey, WIN_SESSIONDIRECTORYADDITIONALPARAMS ,
  554. pPolicy->SessionDirectoryAdditionalParams,
  555. DIRECTORY_LENGTH + 1 );
  556. // ---------------- EnableTimeZoneRedirection
  557. pPolicy->fPolicyEnableTimeZoneRedirection =
  558. GPGetNumValue( policyKey,POLICY_TS_ENABLE_TIME_ZONE_REDIRECTION , &dwTmpValue );
  559. pPolicy->fEnableTimeZoneRedirection = (BOOLEAN) dwTmpValue;
  560. // ---------------- EncryptRPCTraffic
  561. pPolicy->fPolicyEncryptRPCTraffic =
  562. GPGetNumValue( policyKey, POLICY_TS_ENCRYPT_RPC_TRAFFIC , &dwTmpValue );
  563. if(pPolicy->fPolicyEncryptRPCTraffic)
  564. {
  565. pPolicy->fEncryptRPCTraffic = (BOOLEAN) dwTmpValue;
  566. }
  567. else
  568. {
  569. pPolicy->fEncryptRPCTraffic = FALSE;
  570. }
  571. // ---------------- Clipboard
  572. pPolicy->fPolicyDisableClip =
  573. GPGetNumValue( policyKey,WIN_DISABLECLIP, &dwTmpValue );
  574. pPolicy->fDisableClip = (BOOLEAN) dwTmpValue;
  575. // ---------------- Audio
  576. pPolicy->fPolicyDisableCam =
  577. GPGetNumValue( policyKey,WIN_DISABLECAM , &dwTmpValue );
  578. pPolicy->fDisableCam = (BOOLEAN) dwTmpValue;
  579. // ---------------- Comport
  580. pPolicy->fPolicyDisableCcm =
  581. GPGetNumValue( policyKey,WIN_DISABLECCM , &dwTmpValue );
  582. pPolicy->fDisableCcm = (BOOLEAN) dwTmpValue;
  583. // ---------------- LPT
  584. pPolicy->fPolicyDisableLPT =
  585. GPGetNumValue( policyKey,WIN_DISABLELPT , &dwTmpValue );
  586. pPolicy->fDisableLPT = (BOOLEAN) dwTmpValue;
  587. // ---------------- PRN
  588. pPolicy->fPolicyDisableCpm =
  589. GPGetNumValue( policyKey,WIN_DISABLECPM , &dwTmpValue );
  590. pPolicy->fDisableCpm = (BOOLEAN) dwTmpValue;
  591. // ---------------- Password
  592. pPolicy->fPolicyPromptForPassword =
  593. GPGetNumValue( policyKey, WIN_PROMPTFORPASSWORD , &dwTmpValue );
  594. pPolicy->fPromptForPassword = (BOOLEAN) dwTmpValue;
  595. // ---------------- Max Instance Count
  596. pPolicy->fPolicyMaxInstanceCount =
  597. GPGetNumValue( policyKey,WIN_MAXINSTANCECOUNT , &dwTmpValue );
  598. pPolicy->MaxInstanceCount = dwTmpValue;
  599. // ---------------- Min Encryption Level
  600. pPolicy->fPolicyMinEncryptionLevel =
  601. GPGetNumValue( policyKey, WIN_MINENCRYPTIONLEVEL , &dwTmpValue );
  602. pPolicy->MinEncryptionLevel = (BYTE) dwTmpValue;
  603. // ---------------- AutoReconect
  604. pPolicy->fPolicyDisableAutoReconnect =
  605. GPGetNumValue( policyKey, WIN_DISABLEAUTORECONNECT , &dwTmpValue );
  606. pPolicy->fDisableAutoReconnect = (BOOLEAN) dwTmpValue;
  607. // New machine wide profile, home dir and home drive
  608. /*
  609. pPolicy->fPolicyWFProfilePath = GPGetStringValue( policyKey, WIN_WFPROFILEPATH,
  610. pPolicy ->WFProfilePath,
  611. DIRECTORY_LENGTH + 1 );
  612. */
  613. pPolicy->fErrorInvalidProfile = FALSE;
  614. BOOLEAN bValueExists;
  615. pPolicy->fErrorInvalidProfile = !GPGetStringValue( policyKey, WIN_WFPROFILEPATH,
  616. pPolicy ->WFProfilePath, DIRECTORY_LENGTH + 1, &bValueExists );
  617. pPolicy->fPolicyWFProfilePath = bValueExists;
  618. if (!pPolicy->fPolicyWFProfilePath)
  619. {
  620. pPolicy->WFProfilePath[0]=L'\0';
  621. }
  622. pPolicy->fPolicyWFHomeDir = GPGetStringValue( policyKey, WIN_WFHOMEDIR ,
  623. pPolicy->WFHomeDir,
  624. DIRECTORY_LENGTH + 1 );
  625. if (!pPolicy->fPolicyWFHomeDir)
  626. {
  627. pPolicy->WFHomeDir[0]=L'\0';
  628. }
  629. pPolicy->fPolicyWFHomeDirDrive =GPGetStringValue( policyKey, WIN_WFHOMEDIRDRIVE,
  630. pPolicy->WFHomeDirDrive,
  631. 4 );
  632. if(!pPolicy->WFHomeDir[0])
  633. {
  634. pPolicy->WFHomeDirDrive[0] = L'\0';
  635. }
  636. // if home dir is of the form "driveletter:\path" (such as c:\foo), null out the dir-drive to
  637. // eliminate any confusion.
  638. if ( pPolicy->WFHomeDir[1] == L':' )
  639. {
  640. pPolicy->WFHomeDirDrive[0] = L'\0';
  641. }
  642. // --------------- deny connection policy, this is directly read by RegDenyTSConnectionsPolicy() too
  643. pPolicy->fPolicyDenyTSConnections =
  644. GPGetNumValue( policyKey, POLICY_DENY_TS_CONNECTIONS , &dwTmpValue );
  645. pPolicy->fDenyTSConnections = (BOOLEAN) dwTmpValue;
  646. // track the rest of all possivle GP policies
  647. // even thou not all are used by term-srv's USERCONFIGW . A good example is the
  648. // delete tmp folders that Winlogon/wlnotify uses.
  649. // --------------- Per session tmp folders, WARNING : GINA reads policy tree directly for the sake of lower overhead during login
  650. pPolicy->fPolicyTempFoldersPerSession =
  651. GPGetNumValue( policyKey, REG_TERMSRV_PERSESSIONTEMPDIR , &dwTmpValue );
  652. pPolicy-> fTempFoldersPerSession = (BOOLEAN) dwTmpValue;
  653. // -------------- delete per session folders on exit, WARNING : GINA reads policy tree directly for the sake of lower overhead during login
  654. pPolicy->fPolicyDeleteTempFoldersOnExit =
  655. GPGetNumValue( policyKey, REG_CITRIX_DELETETEMPDIRSONEXIT , &dwTmpValue );
  656. pPolicy->fDeleteTempFoldersOnExit = (BOOLEAN) dwTmpValue;
  657. pPolicy->fPolicyPreventLicenseUpgrade =
  658. GPGetNumValue( policyKey, REG_POLICY_PREVENT_LICENSE_UPGRADE , &dwTmpValue );
  659. pPolicy->fPreventLicenseUpgrade = (BOOLEAN) dwTmpValue;
  660. pPolicy->fPolicySecureLicensing =
  661. GPGetNumValue( policyKey, REG_POLICY_SECURE_LICENSING , &dwTmpValue );
  662. pPolicy->fSecureLicensing = (BOOLEAN) dwTmpValue;
  663. // -------------- Color Depth
  664. pPolicy->fPolicyColorDepth =
  665. GPGetNumValue( policyKey, POLICY_TS_COLOR_DEPTH , &dwTmpValue );
  666. // disabled policy will set value to zero, which we will force it
  667. // to be the min color depth of 8 bits.
  668. if ( dwTmpValue < TS_8BPP_SUPPORT )
  669. {
  670. pPolicy->ColorDepth = TS_8BPP_SUPPORT ;
  671. }
  672. else if ( dwTmpValue == TS_CLIENT_COMPAT_BPP_SUPPORT )
  673. {
  674. pPolicy->ColorDepth = TS_24BPP_SUPPORT; // our current max, may change in teh future.
  675. }
  676. else
  677. {
  678. pPolicy->ColorDepth = dwTmpValue;
  679. }
  680. // ---------------- TSCC's permissions TAB
  681. pPolicy->fPolicyWritableTSCCPermissionsTAB =
  682. GPGetNumValue( policyKey, POLICY_TS_TSCC_PERM_TAB_WRITABLE , &dwTmpValue );
  683. pPolicy->fWritableTSCCPermissionsTAB= (BOOLEAN) dwTmpValue;
  684. // ----------------
  685. // Ritu has folded the user policy into machine policy for the drive re-direction.
  686. pPolicy->fPolicyDisableCdm =
  687. GPGetNumValue( policyKey, WIN_DISABLECDM , &dwTmpValue );
  688. pPolicy->fDisableCdm = (BOOLEAN) dwTmpValue;
  689. // ----------------
  690. // fold user config policy into machine config policy
  691. pPolicy->fPolicyForceClientLptDef =
  692. GPGetNumValue( policyKey,WIN_FORCECLIENTLPTDEF , &dwTmpValue );
  693. pPolicy->fForceClientLptDef = (BOOLEAN) dwTmpValue;
  694. // for user config policy into machine config policy
  695. // ----------------
  696. pPolicy->fPolicyShadow =
  697. GPGetNumValue( policyKey, WIN_SHADOW, &dwTmpValue );
  698. pPolicy->Shadow = (SHADOWCLASS) dwTmpValue;
  699. //
  700. // ---- Sessions Policy
  701. //
  702. // ----------------
  703. pPolicy->fPolicyResetBroken =
  704. GPGetNumValue( policyKey,WIN_RESETBROKEN , & dwTmpValue );
  705. pPolicy->fResetBroken = (BOOLEAN) dwTmpValue;
  706. // ----------------
  707. pPolicy->fPolicyReconnectSame =
  708. GPGetNumValue( policyKey,WIN_RECONNECTSAME , &dwTmpValue );
  709. pPolicy->fReconnectSame = (BOOLEAN) dwTmpValue;
  710. // ----------------
  711. pPolicy->fPolicyMaxSessionTime =
  712. GPGetNumValue( policyKey, WIN_MAXCONNECTIONTIME , &dwTmpValue );
  713. pPolicy->MaxConnectionTime = dwTmpValue;
  714. // ----------------
  715. pPolicy->fPolicyMaxDisconnectionTime =
  716. GPGetNumValue( policyKey,WIN_MAXDISCONNECTIONTIME ,&dwTmpValue );
  717. pPolicy->MaxDisconnectionTime = dwTmpValue;
  718. // ----------------
  719. pPolicy->fPolicyMaxIdleTime =
  720. GPGetNumValue( policyKey,WIN_MAXIDLETIME , &dwTmpValue );
  721. pPolicy->MaxIdleTime = dwTmpValue;
  722. // ---------------- Start program policy
  723. pPolicy->fPolicyInitialProgram = GPGetStringValue( policyKey, WIN_INITIALPROGRAM,
  724. pPolicy->InitialProgram,
  725. INITIALPROGRAM_LENGTH + 1 );
  726. GPGetStringValue( policyKey, WIN_WORKDIRECTORY,
  727. pPolicy->WorkDirectory,
  728. DIRECTORY_LENGTH + 1 );
  729. // ---------------- single session per user
  730. pPolicy->fPolicySingleSessionPerUser=
  731. GPGetNumValue( policyKey,POLICY_TS_SINGLE_SESSION_PER_USER, &dwTmpValue );
  732. pPolicy->fSingleSessionPerUser = dwTmpValue;
  733. pPolicy->fPolicySessionDirectoryExposeServerIP =
  734. GPGetNumValue( policyKey, REG_TS_SESSDIR_EXPOSE_SERVER_ADDR , &dwTmpValue );
  735. pPolicy->SessionDirectoryExposeServerIP = dwTmpValue;
  736. // policy for disabling wallpaper in remote desktop
  737. pPolicy->fPolicyDisableWallpaper =
  738. GPGetNumValue( policyKey, POLICY_TS_NO_REMOTE_DESKTOP_WALLPAPER, &dwTmpValue );
  739. pPolicy->fDisableWallpaper = dwTmpValue;
  740. // policy to enable disable keep alive
  741. pPolicy->fPolicyKeepAlive =
  742. GPGetNumValue( policyKey, KEEP_ALIVE_ENABLE_KEY , &dwTmpValue );
  743. pPolicy->fKeepAliveEnable = dwTmpValue;
  744. GPGetNumValue( policyKey, KEEP_ALIVE_INTERVAL_KEY , &dwTmpValue );
  745. pPolicy->KeepAliveInterval = dwTmpValue;
  746. // Policy for disabling forcible logoff
  747. pPolicy->fPolicyDisableForcibleLogoff =
  748. GPGetNumValue( policyKey, POLICY_TS_DISABLE_FORCIBLE_LOGOFF, &dwTmpValue );
  749. pPolicy->fDisableForcibleLogoff = dwTmpValue;
  750. // ---------------- FIPS Encryption Enabled/Disabled
  751. // FIPS policy key is stored separately from the others so we must explicity
  752. // read it in from its location in registry
  753. HKEY hkey;
  754. LONG lRet;
  755. lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  756. TS_FIPS_POLICY,
  757. 0,
  758. KEY_READ,
  759. &hkey);
  760. if (lRet == ERROR_SUCCESS)
  761. {
  762. // if policy is not set GPGetNumValue returns dwTmpValue = 0
  763. GPGetNumValue(hkey, FIPS_ALGORITH_POLICY, &dwTmpValue);
  764. pPolicy->fPolicyFipsEnabled = dwTmpValue;
  765. RegCloseKey(hkey);
  766. }
  767. else
  768. pPolicy->fPolicyFipsEnabled = 0;
  769. }
  770. /*******************************************************************************
  771. * RegGetMachinePolicy()
  772. *
  773. * Params:
  774. * [out] pPolicy : the machine policy used by ts session's userconfig
  775. *
  776. * Return:
  777. * void
  778. *
  779. *******************************************************************************/
  780. void RegGetMachinePolicy(
  781. PPOLICY_TS_MACHINE pPolicy )
  782. {
  783. NTSTATUS status= STATUS_SUCCESS;
  784. HKEY policyKey;
  785. status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TS_POLICY_SUB_TREE, 0,
  786. KEY_READ, &policyKey );
  787. if ( status != ERROR_SUCCESS)
  788. {
  789. policyKey = NULL; // prefix complains.
  790. }
  791. // ok to call this with policyKey=NULL since func will init pPolicy using default values for the case of NULL key.
  792. GPQueryMachineConfig( policyKey, pPolicy );
  793. if ( policyKey )
  794. {
  795. RegCloseKey( policyKey );
  796. }
  797. }
  798. /*******************************************************************************
  799. * RegGetMachinePolicyiEx()
  800. *
  801. * This func is identical to RegGetMachinePolicy() , and provides the time stampt for
  802. * the last write time of the policy key, and if the time of the key is the same as the
  803. * time for the last read, then it will not bother with any reads and return false
  804. *
  805. * Params:
  806. * [in ] forcePolicyRead : 1st time around, you want to init all vars so force a read.
  807. * [in/out] pTime : caller passes in the last write time for the machine policy key.
  808. * if key is missing, then time is set to zero.
  809. * On return, this param is updated to reflect the most recent
  810. * update time, which could be zero if the policy key was deleted
  811. *
  812. * [out] pPolicy : the machine policy struct updated
  813. *
  814. * Return:
  815. * TRUE : means there was a real change present
  816. * FALSE : means no values had changed.
  817. *******************************************************************************/
  818. BOOLEAN RegGetMachinePolicyEx(
  819. BOOLEAN forcePolicyRead,
  820. FILETIME *pTime ,
  821. PPOLICY_TS_MACHINE pPolicy )
  822. {
  823. HKEY policyKey;
  824. HKEY FipsPolicyKey;
  825. FILETIME newTime;
  826. FILETIME FipsNewTime;
  827. NTSTATUS status = STATUS_SUCCESS;
  828. BOOLEAN rc = FALSE;
  829. status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  830. TS_POLICY_SUB_TREE,
  831. 0,
  832. KEY_READ,
  833. &policyKey );
  834. if (status != ERROR_SUCCESS)
  835. {
  836. policyKey = NULL; // prefix complains.
  837. }
  838. // if we have a policy key, get the time for that key
  839. if (policyKey)
  840. {
  841. RegQueryInfoKey( policyKey, NULL, NULL, NULL, NULL, NULL,
  842. NULL, NULL, NULL, NULL, NULL, &newTime );
  843. }
  844. status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  845. TS_FIPS_POLICY,
  846. 0,
  847. KEY_READ,
  848. &FipsPolicyKey);
  849. if (status != ERROR_SUCCESS)
  850. {
  851. FipsPolicyKey = NULL; // prefix complains.
  852. }
  853. // if we have a Fips policy key, get the time for that key
  854. if (FipsPolicyKey)
  855. {
  856. RegQueryInfoKey(FipsPolicyKey, NULL, NULL, NULL, NULL, NULL,
  857. NULL, NULL, NULL, NULL, NULL, &FipsNewTime);
  858. }
  859. // If we got times back for both policies pick the newest
  860. if (policyKey && FipsPolicyKey)
  861. {
  862. if ( (FipsNewTime.dwHighDateTime > newTime.dwHighDateTime) ||
  863. ( (FipsNewTime.dwHighDateTime == newTime.dwHighDateTime) &&
  864. (FipsNewTime.dwLowDateTime > newTime.dwLowDateTime) ) )
  865. {
  866. // FipsNewTime is newer, set it as the time to use
  867. newTime = FipsNewTime;
  868. }
  869. }
  870. // If we don't have a time for either policy keys then init time to the current system time
  871. else
  872. {
  873. SYSTEMTIME currentTimeOnSystemInSystemTimeUnits;
  874. GetSystemTime(&currentTimeOnSystemInSystemTimeUnits);
  875. SystemTimeToFileTime(&currentTimeOnSystemInSystemTimeUnits, &newTime);
  876. }
  877. if ( forcePolicyRead ||
  878. ( (pTime->dwHighDateTime < newTime.dwHighDateTime ) ||
  879. ( ( pTime->dwHighDateTime == newTime.dwHighDateTime ) && pTime->dwLowDateTime < newTime.dwLowDateTime ) ) )
  880. {
  881. // this call will init struct memebers even if the policy key in null, so it
  882. // is required to make this call on startup, with or without an actual reg key being present
  883. GPQueryMachineConfig( policyKey, pPolicy );
  884. rc = TRUE;
  885. }
  886. pTime->dwHighDateTime = newTime.dwHighDateTime;
  887. pTime->dwLowDateTime = newTime.dwLowDateTime;
  888. if ( policyKey )
  889. {
  890. RegCloseKey( policyKey );
  891. }
  892. if ( FipsPolicyKey )
  893. {
  894. RegCloseKey( FipsPolicyKey );
  895. }
  896. return rc;
  897. }
  898. /*******************************************************************************
  899. * RegMergeMachinePolicy()
  900. *
  901. * Params:
  902. * [in] pPolicy : policy data to use to override userconfig
  903. * [in/out] pWSConfig : userconfig data that is modified based on the policy data
  904. *
  905. * Return:
  906. * void
  907. *
  908. ********************************************************************************/
  909. void RegMergeMachinePolicy(
  910. PPOLICY_TS_MACHINE pPolicy, // the policy override data
  911. USERCONFIGW * pWSConfig, // the machine config data represented thru a USERCONFIGW data struct (mostly)
  912. PWINSTATIONCREATE pCreate // some of winstation data is stored here
  913. )
  914. {
  915. // ---------------------------------------------- Clipboard
  916. if ( pPolicy->fPolicyDisableClip )
  917. {
  918. pWSConfig->fDisableClip = pPolicy->fDisableClip;
  919. }
  920. // ---------------------------------------------- Audio
  921. if ( pPolicy->fPolicyDisableCam )
  922. {
  923. pWSConfig->fDisableCam = pPolicy->fDisableCam;
  924. }
  925. // ---------------------------------------------- Comport
  926. if ( pPolicy->fPolicyDisableCcm )
  927. {
  928. pWSConfig->fDisableCcm = pPolicy->fDisableCcm;
  929. }
  930. // ---------------------------------------------- LPT
  931. if ( pPolicy->fPolicyDisableLPT )
  932. {
  933. pWSConfig->fDisableLPT = pPolicy->fDisableLPT;
  934. }
  935. // ---------------------------------------------- PRN
  936. if ( pPolicy->fPolicyDisableCpm )
  937. {
  938. pWSConfig->fDisableCpm = pPolicy->fDisableCpm;
  939. }
  940. // ---------------------------------------------- Password
  941. if ( pPolicy->fPolicyPromptForPassword )
  942. {
  943. pWSConfig->fPromptForPassword = pPolicy->fPromptForPassword;
  944. }
  945. // ---------------------------------------------- Max Instance
  946. if ( pPolicy->fPolicyMaxInstanceCount )
  947. {
  948. pCreate->MaxInstanceCount = pPolicy->MaxInstanceCount;
  949. }
  950. // ---------------------------------------------- Min Encryption Level
  951. if ( pPolicy->fPolicyMinEncryptionLevel )
  952. {
  953. pWSConfig->MinEncryptionLevel = pPolicy->MinEncryptionLevel;
  954. }
  955. // ---------------------------------------------- FIPS Enabled/Disabled
  956. if ( pPolicy->fPolicyFipsEnabled )
  957. {
  958. pWSConfig->MinEncryptionLevel = (BYTE)REG_FIPS_ENCRYPTION_LEVEL;
  959. }
  960. // ---------------------------------------------- Auto Reconnect disable
  961. if ( pPolicy->fPolicyDisableAutoReconnect )
  962. {
  963. pWSConfig->fDisableAutoReconnect = pPolicy->fDisableAutoReconnect;
  964. }
  965. //----------------------------------------------- "Invalid Profile" flag
  966. if(pPolicy->fErrorInvalidProfile)
  967. {
  968. pWSConfig->fErrorInvalidProfile = pPolicy->fErrorInvalidProfile;
  969. }
  970. // ---------------------------------------------- Profile Path
  971. if (pPolicy->fPolicyWFProfilePath )
  972. {
  973. wcscpy( pWSConfig->WFProfilePath, pPolicy->WFProfilePath );
  974. }
  975. // ---------------------------------------------- Home Directory
  976. if ( pPolicy->fPolicyWFHomeDir )
  977. {
  978. wcscpy( pWSConfig->WFHomeDir, pPolicy->WFHomeDir );
  979. }
  980. // ---------------------------------------------- Home Directory Drive
  981. if ( pPolicy->fPolicyWFHomeDirDrive )
  982. {
  983. wcscpy( pWSConfig->WFHomeDirDrive, pPolicy->WFHomeDirDrive );
  984. }
  985. // ---------------------------------------------- Color Depth
  986. if ( pPolicy->fPolicyColorDepth)
  987. {
  988. pWSConfig->ColorDepth = pPolicy->ColorDepth ;
  989. pWSConfig->fInheritColorDepth = FALSE;
  990. }
  991. //
  992. if ( pPolicy->fPolicyDisableCdm)
  993. {
  994. pWSConfig->fDisableCdm = pPolicy->fDisableCdm;
  995. }
  996. //
  997. if ( pPolicy->fPolicyForceClientLptDef )
  998. {
  999. pWSConfig->fForceClientLptDef = pPolicy->fForceClientLptDef;
  1000. }
  1001. // Shadow
  1002. if ( pPolicy->fPolicyShadow)
  1003. {
  1004. pWSConfig->Shadow = pPolicy->Shadow;
  1005. pWSConfig->fInheritShadow = FALSE;
  1006. }
  1007. if (pPolicy->fPolicyResetBroken )
  1008. {
  1009. pWSConfig->fResetBroken = pPolicy->fResetBroken;
  1010. pWSConfig->fInheritResetBroken = FALSE;
  1011. }
  1012. if (pPolicy->fPolicyReconnectSame )
  1013. {
  1014. pWSConfig->fReconnectSame = pPolicy->fReconnectSame;
  1015. pWSConfig->fInheritReconnectSame = FALSE;
  1016. }
  1017. if (pPolicy->fPolicyMaxSessionTime )
  1018. {
  1019. pWSConfig->MaxConnectionTime = pPolicy->MaxConnectionTime;
  1020. pWSConfig->fInheritMaxSessionTime = FALSE;
  1021. }
  1022. if (pPolicy->fPolicyMaxDisconnectionTime)
  1023. {
  1024. pWSConfig->MaxDisconnectionTime = pPolicy->MaxDisconnectionTime;
  1025. pWSConfig->fInheritMaxDisconnectionTime = FALSE;
  1026. }
  1027. if (pPolicy->fPolicyMaxIdleTime)
  1028. {
  1029. pWSConfig->MaxIdleTime = pPolicy->MaxIdleTime;
  1030. pWSConfig->fInheritMaxIdleTime = FALSE;
  1031. }
  1032. if (pPolicy->fPolicyInitialProgram)
  1033. {
  1034. wcscpy( pWSConfig->InitialProgram, pPolicy->InitialProgram );
  1035. wcscpy( pWSConfig->WorkDirectory, pPolicy->WorkDirectory );
  1036. pWSConfig->fInheritInitialProgram = FALSE;
  1037. }
  1038. if ( pPolicy->fPolicyDisableWallpaper )
  1039. {
  1040. pWSConfig->fWallPaperDisabled = pPolicy->fDisableWallpaper ;
  1041. }
  1042. // ----------------------------------------------
  1043. // There is no UI for setting these... So it's probably never used
  1044. //
  1045. // if ( pPolicy->fPolicytSecurity )
  1046. // {
  1047. // pWSConfig->fDisableEncryption = pPolicy->fDisableEncryption;
  1048. // pWSConfig->MinEncryptionLevel = pPolicy->MinEncryptionLevel;
  1049. // }
  1050. // else
  1051. // {
  1052. // if ( pWSConfig->fInheritSecurity )
  1053. // {
  1054. // pWSConfig->fDisableEncryption = pPolicy->fDisableEncryption;
  1055. // pWSConfig->MinEncryptionLevel = pPolicy->MinEncryptionLevel;
  1056. // }
  1057. // }
  1058. }
  1059. __inline BOOL IsAppServer()
  1060. {
  1061. OSVERSIONINFOEX osVersionInfo;
  1062. DWORDLONG dwlConditionMask = 0;
  1063. BOOL fIsWTS = FALSE;
  1064. osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  1065. fIsWTS = GetVersionEx((OSVERSIONINFO *)&osVersionInfo) &&
  1066. (osVersionInfo.wSuiteMask & VER_SUITE_TERMINAL) &&
  1067. !(osVersionInfo.wSuiteMask & VER_SUITE_SINGLEUSERTS);
  1068. return fIsWTS;
  1069. }
  1070. /*******************************************************************************
  1071. * RegIsTimeZoneRedirectionEnabled()
  1072. *
  1073. * Purpose:
  1074. * Checks the registry settings for Time Zone redirection.
  1075. * Params:
  1076. * NONE
  1077. *
  1078. * Return:
  1079. * TRUE if time zone redirection is enabled.
  1080. * Note:
  1081. * This function reads the registry only once. So for new settings to take
  1082. * effect one needs to reboot machine. This is done on purpose, to avoid
  1083. * confusions when one creates a session having TZ redirection disabled, then
  1084. * disconnects, enables TZ redirection and reconnects again.
  1085. ********************************************************************************/
  1086. BOOLEAN
  1087. RegIsTimeZoneRedirectionEnabled()
  1088. {
  1089. LONG errorCode = ERROR_SUCCESS;
  1090. DWORD ValueType;
  1091. DWORD ValueSize = sizeof(DWORD);
  1092. DWORD valueData ;
  1093. HKEY hKey = NULL;
  1094. if(!IsAppServer())
  1095. {
  1096. return FALSE;
  1097. }
  1098. //
  1099. // first check the policy tree,
  1100. //
  1101. errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TS_POLICY_SUB_TREE, 0, KEY_READ, &hKey );
  1102. //If error code is ERROR_FILE_NOT_FOUND, this is not an error.
  1103. if( !hKey && errorCode != ERROR_FILE_NOT_FOUND )
  1104. {
  1105. return FALSE;
  1106. }
  1107. if ( hKey )
  1108. {
  1109. errorCode = RegQueryValueEx( hKey, POLICY_TS_ENABLE_TIME_ZONE_REDIRECTION,
  1110. NULL, &ValueType, (LPBYTE) &valueData, &ValueSize );
  1111. RegCloseKey(hKey);
  1112. hKey = NULL;
  1113. switch( errorCode )
  1114. {
  1115. case ERROR_SUCCESS :
  1116. return (valueData != 0); // we have data from the policyKey handle to return
  1117. case ERROR_FILE_NOT_FOUND:
  1118. // there is no policy from GP, so see (below) what the local machine
  1119. // value has.
  1120. break;
  1121. default:
  1122. // if we are having any other kind of a problem, claim FALSE
  1123. //to be on the safe side.
  1124. return FALSE;
  1125. }
  1126. }
  1127. // if we got this far, then no policy was set. Check the local machine now.
  1128. errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0, KEY_READ, &hKey );
  1129. if ( hKey )
  1130. {
  1131. errorCode = RegQueryValueEx( hKey, POLICY_TS_ENABLE_TIME_ZONE_REDIRECTION,
  1132. NULL, &ValueType, (LPBYTE) &valueData, &ValueSize );
  1133. RegCloseKey(hKey);
  1134. hKey = NULL;
  1135. if (errorCode == ERROR_SUCCESS )
  1136. {
  1137. return (valueData != 0); // we have data from the ControlKey handle to return
  1138. }
  1139. }
  1140. return FALSE;
  1141. }