Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1126 lines
36 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. }
  33. extern "C"
  34. {
  35. //
  36. HKEY g_hTSPolicyKey = NULL;//handle to TS_POLICY_SUB_TREE key
  37. HKEY g_hTSControlKey = NULL;//handle to REG_CONTROL_TSERVER key
  38. }
  39. /******************************************************************
  40. * *
  41. * Check to see if the policy is set to stop accepting connections *
  42. * *
  43. ******************************************************************/
  44. BOOLEAN RegDenyTSConnectionsPolicy()
  45. {
  46. LONG errorCode = ERROR_SUCCESS;
  47. DWORD ValueType;
  48. DWORD ValueSize = sizeof(DWORD);
  49. DWORD valueData ;
  50. //
  51. // first check the policy tree,
  52. //
  53. if( !g_hTSPolicyKey )
  54. {
  55. errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TS_POLICY_SUB_TREE, 0,
  56. KEY_READ, &g_hTSPolicyKey );
  57. //If error code is ERROR_FILE_NOT_FOUND, this is not an error.
  58. if( !g_hTSPolicyKey && errorCode != ERROR_FILE_NOT_FOUND )
  59. {
  60. //we could not open policy key for some reason other
  61. //than key not found.
  62. //return TRUE to be on the safe side
  63. return TRUE;
  64. }
  65. }
  66. if ( g_hTSPolicyKey )
  67. {
  68. errorCode = RegQueryValueEx( g_hTSPolicyKey, POLICY_DENY_TS_CONNECTIONS , NULL, &ValueType,
  69. (LPBYTE) &valueData, &ValueSize );
  70. switch( errorCode )
  71. {
  72. case ERROR_SUCCESS :
  73. return ( valueData ? TRUE : FALSE ) ; // we have data from the policyKey handle to return
  74. break;
  75. case ERROR_KEY_DELETED:
  76. // Group policy must have deleted this key, close it
  77. // Then, below we check for the local machine key
  78. RegCloseKey( g_hTSPolicyKey );
  79. g_hTSPolicyKey = NULL;
  80. break;
  81. case ERROR_FILE_NOT_FOUND:
  82. // there is no policy from GP, so see (below) what the local machine
  83. // value has.
  84. break;
  85. default:
  86. // if we are having any other kind of a problem, claim TRUE and
  87. // stop connections to be on the safe side (a security angle).
  88. return TRUE;
  89. break;
  90. }
  91. }
  92. // if we got this far, then no policy was set. Check the local machine now.
  93. if( !g_hTSControlKey )
  94. {
  95. errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
  96. KEY_READ, &g_hTSControlKey );
  97. }
  98. if ( g_hTSControlKey )
  99. {
  100. errorCode = RegQueryValueEx( g_hTSControlKey, POLICY_DENY_TS_CONNECTIONS , NULL, &ValueType,
  101. (LPBYTE) &valueData, &ValueSize );
  102. if (errorCode == ERROR_SUCCESS )
  103. {
  104. return ( valueData ? TRUE : FALSE ) ; // we have data from the policyKey handle to return
  105. }
  106. }
  107. // if no localKey, gee... the registry is missing data... return TRUE to be on the safe side
  108. return TRUE;
  109. }
  110. /******************************************************************
  111. * *
  112. * Wait until POLICY_DENY_TS_CONNECTIONS is changed *
  113. * *
  114. * Parameters: *
  115. * bWaitForAccept *
  116. * if TRUE, test if connections are accepted and wait for *
  117. * them to be accepted if they are not currently accepted. *
  118. * if FALSE, test if connections are not accepted and wait *
  119. * for them to be denied if they are currently accepted. *
  120. * *
  121. * hExtraEvent *
  122. * optional handle to an event to wait for. *
  123. * *
  124. * Returns: *
  125. * WAIT_OBJECT_0 *
  126. * if a change in TS connections policy occurred *
  127. * *
  128. * WAIT_OBJECT_0 + 1 *
  129. * if the extra event is present and signaled *
  130. * *
  131. ******************************************************************/
  132. //
  133. // Note that opening the global g_hTSControlKey without protection
  134. // can cause the key to be opened twice.
  135. //
  136. // This macro is TRUE if the TS connections are denied
  137. #define TSConnectionsDenied (RegDenyTSConnectionsPolicy() && \
  138. !(RegIsMachinePolicyAllowHelp() && RegIsMachineInHelpMode()))
  139. DWORD WaitForTSConnectionsPolicyChanges(
  140. BOOLEAN bWaitForAccept,
  141. HANDLE hExtraEvent
  142. )
  143. {
  144. //
  145. // Wait for a policy change if
  146. // we want TS connections and they are denied OR
  147. // we don't want TS connections and they are accepted
  148. //
  149. if((bWaitForAccept && TSConnectionsDenied) ||
  150. (!bWaitForAccept && !TSConnectionsDenied))
  151. {
  152. DWORD errorCode = ERROR_SUCCESS;
  153. if( !g_hTSControlKey )
  154. {
  155. errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
  156. KEY_READ, &g_hTSControlKey );
  157. if( !g_hTSControlKey )
  158. {
  159. SetLastError( errorCode );
  160. return WAIT_FAILED;
  161. }
  162. }
  163. HKEY hPoliciesKey = NULL;
  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. SetLastError( errorCode );
  171. return WAIT_FAILED;
  172. }
  173. HANDLE hEvents[3] = { NULL, NULL, NULL };
  174. hEvents[0] = CreateEvent(NULL,FALSE,FALSE,NULL);
  175. hEvents[1] = CreateEvent(NULL,FALSE,FALSE,NULL);
  176. hEvents[2] = hExtraEvent;
  177. if( !hEvents[0] || !hEvents[1] )
  178. {
  179. errorCode = GetLastError();
  180. RegCloseKey(hPoliciesKey);
  181. SetLastError( errorCode );
  182. return WAIT_FAILED;
  183. }
  184. BOOLEAN key1NeedsToBeNotified = TRUE;
  185. BOOLEAN key2NeedsToBeNotified = TRUE;
  186. DWORD whichObject;
  187. for( ;; )
  188. {
  189. if (key1NeedsToBeNotified)
  190. {
  191. errorCode = RegNotifyChangeKeyValue(g_hTSControlKey,
  192. FALSE,REG_NOTIFY_CHANGE_LAST_SET,
  193. hEvents[0], TRUE );
  194. if( errorCode != ERROR_SUCCESS )
  195. {
  196. CloseHandle( hEvents[0] );
  197. CloseHandle( hEvents[1] );
  198. RegCloseKey(hPoliciesKey);
  199. SetLastError( errorCode );
  200. return WAIT_FAILED;
  201. }
  202. else
  203. {
  204. key1NeedsToBeNotified = FALSE;
  205. }
  206. }
  207. if (key2NeedsToBeNotified)
  208. {
  209. errorCode = RegNotifyChangeKeyValue(hPoliciesKey,
  210. TRUE,REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_NAME,
  211. hEvents[1], TRUE );
  212. if( errorCode != ERROR_SUCCESS )
  213. {
  214. CloseHandle( hEvents[0] );
  215. CloseHandle( hEvents[1] );
  216. RegCloseKey(hPoliciesKey);
  217. SetLastError( errorCode );
  218. return WAIT_FAILED;
  219. }
  220. else
  221. {
  222. key2NeedsToBeNotified = FALSE;
  223. }
  224. }
  225. if ( hExtraEvent == NULL )
  226. {
  227. whichObject = WaitForMultipleObjects(2,hEvents,FALSE,INFINITE);
  228. }
  229. else
  230. {
  231. whichObject = WaitForMultipleObjects(3,hEvents,FALSE,INFINITE);
  232. }
  233. if(whichObject == WAIT_FAILED)
  234. {
  235. errorCode = GetLastError();
  236. CloseHandle( hEvents[0] );
  237. CloseHandle( hEvents[1] );
  238. RegCloseKey(hPoliciesKey);
  239. SetLastError( errorCode );
  240. return WAIT_FAILED;
  241. }
  242. else
  243. {
  244. if ( whichObject == WAIT_OBJECT_0 )
  245. {
  246. key1NeedsToBeNotified = TRUE;
  247. }
  248. else if ( whichObject == WAIT_OBJECT_0 + 1 )
  249. {
  250. key2NeedsToBeNotified = TRUE;
  251. }
  252. else if ( (whichObject == WAIT_OBJECT_0 + 2) && hExtraEvent )
  253. {
  254. CloseHandle( hEvents[0] );
  255. CloseHandle( hEvents[1] );
  256. RegCloseKey(hPoliciesKey);
  257. return WAIT_OBJECT_0 + 1;
  258. }
  259. else
  260. {
  261. KdPrint(("ERROR : WaitForTSConnectionsPolicyChanges()'s WaitForMultipleObjects() returned 0x%lx\n", whichObject ));
  262. }
  263. /*
  264. if((bWaitForAccept && TSConnectionsDenied) ||
  265. (!bWaitForAccept && !TSConnectionsDenied))
  266. {
  267. continue;
  268. }
  269. else
  270. {
  271. break;
  272. }
  273. */
  274. // always return, the tests will be done by the caller
  275. break;
  276. }
  277. }
  278. CloseHandle( hEvents[0] );
  279. CloseHandle( hEvents[1] );
  280. RegCloseKey(hPoliciesKey);
  281. }
  282. return WAIT_OBJECT_0;
  283. }
  284. /********************************************************************************
  285. *
  286. * GPGetNumValue()
  287. *
  288. * Params
  289. * [in] policyKey : hkey to the policy reg tree where values are stored
  290. * [in] ValueName : name of the value (which is the policy) we are looking for
  291. * [out] pValueData: the data for the policy
  292. *
  293. * Return:
  294. * if the policy defined by the passed in valuename is present, then
  295. * return TRUE. Else, return FALSE
  296. *
  297. ********************************************************************************/
  298. BOOLEAN GPGetNumValue(
  299. HKEY policyKey,
  300. LPWSTR ValueName,
  301. DWORD *pValueData )
  302. {
  303. LONG Status = ERROR_SUCCESS;
  304. DWORD ValueType;
  305. DWORD ValueSize = sizeof(DWORD);
  306. // init data value to zero, just to get Prefix off our backs. This is a wasted OP
  307. // since unless policy is set, value is not used.
  308. *pValueData = 0;
  309. //
  310. // See if any values are present from the policyKey .
  311. //
  312. if ( policyKey )
  313. {
  314. Status = RegQueryValueEx( policyKey, ValueName, NULL, &ValueType,
  315. (LPBYTE) pValueData, &ValueSize );
  316. if (Status == ERROR_SUCCESS )
  317. {
  318. return TRUE; // we have data from the policyKey handle to return
  319. }
  320. }
  321. // else, no key means policy is not set
  322. return FALSE;
  323. }
  324. /********************************************************************************
  325. *
  326. * GPGetStringValue()
  327. *
  328. * same as GPGetNumValue() but for policies that have a string value
  329. *
  330. *
  331. ********************************************************************************/
  332. BOOLEAN
  333. GPGetStringValue( HKEY policyKey,
  334. LPWSTR ValueName,
  335. LPWSTR pValueData,
  336. DWORD MaxValueSize )
  337. {
  338. LONG Status;
  339. DWORD ValueType;
  340. DWORD ValueSize = MaxValueSize << 1;
  341. if (policyKey )
  342. {
  343. Status = RegQueryValueEx( policyKey, ValueName, NULL, &ValueType,
  344. (LPBYTE) pValueData, &ValueSize );
  345. if ( Status != ERROR_SUCCESS || ValueSize == sizeof(UNICODE_NULL) )
  346. {
  347. return FALSE; // no data found.
  348. }
  349. else
  350. {
  351. if ( ValueType != REG_SZ )
  352. {
  353. return FALSE; // bad data, pretend we have no data.
  354. }
  355. }
  356. // we did get data
  357. return( TRUE );
  358. }
  359. return FALSE;
  360. }
  361. /*******************************************************************************
  362. *
  363. * GPQueryUserConfig
  364. *
  365. * query USERCONFIG structure
  366. *
  367. * Params:
  368. * policyKey : hkey to the HKCU policy tree
  369. * pPolicy : points to the user policy struct which has flags for any policy
  370. * value that is present in the policy tree
  371. * pUser : pointer to a userconfigw struct used as a sracth pad to hold the
  372. * policy values (if present).
  373. * Return:
  374. * void
  375. *
  376. ******************************************************************************/
  377. VOID
  378. GPQueryUserConfig( HKEY policyKey, PPOLICY_TS_USER pPolicy , PUSERCONFIGW pUser )
  379. {
  380. UCHAR seed;
  381. UNICODE_STRING UnicodePassword;
  382. WCHAR encPassword[ PASSWORD_LENGTH + 2 ];
  383. DWORD dwTmpValue;
  384. // ----------------
  385. pPolicy->fPolicyInitialProgram = GPGetStringValue( policyKey, WIN_INITIALPROGRAM,
  386. pUser->InitialProgram,
  387. INITIALPROGRAM_LENGTH + 1 );
  388. GPGetStringValue( policyKey, WIN_WORKDIRECTORY,
  389. pUser->WorkDirectory,
  390. DIRECTORY_LENGTH + 1 );
  391. // ----------------
  392. pPolicy->fPolicyResetBroken =
  393. GPGetNumValue( policyKey,WIN_RESETBROKEN , & dwTmpValue );
  394. pUser->fResetBroken = (BOOLEAN) dwTmpValue;
  395. // ----------------
  396. pPolicy->fPolicyReconnectSame =
  397. GPGetNumValue( policyKey,WIN_RECONNECTSAME , &dwTmpValue );
  398. pUser->fReconnectSame = (BOOLEAN) dwTmpValue;
  399. // ----------------
  400. pPolicy->fPolicyShadow =
  401. GPGetNumValue( policyKey, WIN_SHADOW, &dwTmpValue );
  402. pUser->Shadow = (SHADOWCLASS) dwTmpValue;
  403. // ----------------
  404. pPolicy->fPolicyMaxSessionTime =
  405. GPGetNumValue( policyKey, WIN_MAXCONNECTIONTIME , &dwTmpValue );
  406. pUser->MaxConnectionTime = dwTmpValue;
  407. // ----------------
  408. pPolicy->fPolicyMaxDisconnectionTime =
  409. GPGetNumValue( policyKey,WIN_MAXDISCONNECTIONTIME ,&dwTmpValue );
  410. pUser->MaxDisconnectionTime = dwTmpValue;
  411. // ----------------
  412. pPolicy->fPolicyMaxIdleTime =
  413. GPGetNumValue( policyKey,WIN_MAXIDLETIME , &dwTmpValue );
  414. pUser->MaxIdleTime = dwTmpValue;
  415. // ----------------
  416. pPolicy->fPolicyCallback =
  417. GPGetNumValue( policyKey, WIN_CALLBACK, &dwTmpValue );
  418. pUser->Callback = (CALLBACKCLASS ) dwTmpValue;
  419. // ----------------
  420. pPolicy->fPolicyCallbackNumber =
  421. GPGetStringValue( policyKey, WIN_CALLBACKNUMBER,
  422. pUser->CallbackNumber,
  423. CALLBACK_LENGTH + 1 );
  424. // ----------------
  425. pPolicy->fPolicyAutoClientDrives =
  426. GPGetNumValue( policyKey,WIN_AUTOCLIENTDRIVES , &dwTmpValue );
  427. pUser->fAutoClientDrives = (BOOLEAN) dwTmpValue;
  428. // ----------------
  429. pPolicy->fPolicyAutoClientLpts =
  430. GPGetNumValue( policyKey,WIN_AUTOCLIENTLPTS , &dwTmpValue );
  431. pUser->fAutoClientLpts = (BOOLEAN) dwTmpValue;
  432. // ----------------
  433. pPolicy->fPolicyForceClientLptDef =
  434. GPGetNumValue( policyKey,WIN_FORCECLIENTLPTDEF , &dwTmpValue );
  435. pUser->fForceClientLptDef = (BOOLEAN) dwTmpValue;
  436. }
  437. /*******************************************************************************
  438. * RegGetUserPolicy()
  439. *
  440. * Params:
  441. * [in] userSID : user sid in a text format
  442. * [out] pPolicy : user policy struct
  443. * [out] pUser : policy values
  444. *
  445. * Return:
  446. * BOOLEAN : TRUE if user policy was found
  447. * FALSE if there was a problem getting user policy
  448. *******************************************************************************/
  449. BOOLEAN RegGetUserPolicy(
  450. LPWSTR userSID ,
  451. PPOLICY_TS_USER pPolicy,
  452. PUSERCONFIGW pUser )
  453. {
  454. DWORD status= ERROR_SUCCESS;
  455. HKEY policyKey;
  456. WCHAR userHive [MAX_PATH];
  457. if (userSID) // this would never happen, but Master Prefix complains and we must server him!
  458. {
  459. wcscpy(userHive, userSID);
  460. wcscat(userHive, L"\\");
  461. wcscat(userHive, TS_POLICY_SUB_TREE );
  462. status = RegOpenKeyEx( HKEY_USERS, userHive , 0,
  463. KEY_READ, &policyKey );
  464. if (status == ERROR_SUCCESS )
  465. {
  466. GPQueryUserConfig( policyKey, pPolicy, pUser );
  467. RegCloseKey( policyKey );
  468. return TRUE;
  469. }
  470. }
  471. return FALSE;
  472. }
  473. /*******************************************************************************
  474. * GPQueryMachineConfig()
  475. *
  476. * Params:
  477. * [in] policyKey : key to the policy tree under hklm
  478. * [out] pPolicy : pointer to a machine policy data that is filled up by this function
  479. *
  480. * Return:
  481. * void
  482. *
  483. *
  484. * !!! WARNING !!!
  485. *
  486. * All TS related values MUST be in the flat TS-POLICY-TREE, no sub keys.
  487. * This is due to the fact that time-stamp checks by the caller of RegGetMachinePolicyEx() will
  488. * check the time stamp on the TS-POLICY key, which is NOT updated when a value in a sub-key is
  489. * altered.
  490. *
  491. *
  492. *******************************************************************************/
  493. void GPQueryMachineConfig( HKEY policyKey, PPOLICY_TS_MACHINE pPolicy )
  494. {
  495. DWORD dwTmpValue;
  496. // ---------------- SessionDirectoryActive
  497. pPolicy->fPolicySessionDirectoryActive =
  498. GPGetNumValue( policyKey,WIN_SESSIONDIRECTORYACTIVE, &dwTmpValue );
  499. pPolicy->SessionDirectoryActive = (BOOLEAN) dwTmpValue;
  500. // ---------------- SessionDirectoryLocation
  501. pPolicy->fPolicySessionDirectoryLocation = GPGetStringValue( policyKey, WIN_SESSIONDIRECTORYLOCATION ,
  502. pPolicy->SessionDirectoryLocation,
  503. DIRECTORY_LENGTH + 1 );
  504. // ---------------- SessionDirectoryClusterName
  505. pPolicy->fPolicySessionDirectoryClusterName = GPGetStringValue( policyKey, WIN_SESSIONDIRECTORYCLUSTERNAME ,
  506. pPolicy->SessionDirectoryClusterName,
  507. DIRECTORY_LENGTH + 1 );
  508. // ---------------- SessionDirectoryAdditionalParams
  509. pPolicy->fPolicySessionDirectoryAdditionalParams = GPGetStringValue( policyKey, WIN_SESSIONDIRECTORYADDITIONALPARAMS ,
  510. pPolicy->SessionDirectoryAdditionalParams,
  511. DIRECTORY_LENGTH + 1 );
  512. // ---------------- Clipboard
  513. pPolicy->fPolicyDisableClip =
  514. GPGetNumValue( policyKey,WIN_DISABLECLIP, &dwTmpValue );
  515. pPolicy->fDisableClip = (BOOLEAN) dwTmpValue;
  516. // ---------------- Audio
  517. pPolicy->fPolicyDisableCam =
  518. GPGetNumValue( policyKey,WIN_DISABLECAM , &dwTmpValue );
  519. pPolicy->fDisableCam = (BOOLEAN) dwTmpValue;
  520. // ---------------- Comport
  521. pPolicy->fPolicyDisableCcm =
  522. GPGetNumValue( policyKey,WIN_DISABLECCM , &dwTmpValue );
  523. pPolicy->fDisableCcm = (BOOLEAN) dwTmpValue;
  524. // ---------------- LPT
  525. pPolicy->fPolicyDisableLPT =
  526. GPGetNumValue( policyKey,WIN_DISABLELPT , &dwTmpValue );
  527. pPolicy->fDisableLPT = (BOOLEAN) dwTmpValue;
  528. // ---------------- PRN
  529. pPolicy->fPolicyDisableCpm =
  530. GPGetNumValue( policyKey,WIN_DISABLECPM , &dwTmpValue );
  531. pPolicy->fDisableCpm = (BOOLEAN) dwTmpValue;
  532. // ---------------- Password
  533. pPolicy->fPolicyPromptForPassword =
  534. GPGetNumValue( policyKey, WIN_PROMPTFORPASSWORD , &dwTmpValue );
  535. pPolicy->fPromptForPassword = (BOOLEAN) dwTmpValue;
  536. // ---------------- Max Instance Count
  537. pPolicy->fPolicyMaxInstanceCount =
  538. GPGetNumValue( policyKey,WIN_MAXINSTANCECOUNT , &dwTmpValue );
  539. pPolicy->MaxInstanceCount = dwTmpValue;
  540. // ---------------- Min Encryption Level
  541. pPolicy->fPolicyMinEncryptionLevel =
  542. GPGetNumValue( policyKey, WIN_MINENCRYPTIONLEVEL , &dwTmpValue );
  543. pPolicy->MinEncryptionLevel = (BYTE) dwTmpValue;
  544. // ---------------- AutoReconect
  545. pPolicy->fPolicyDisableAutoReconnect =
  546. GPGetNumValue( policyKey, WIN_DISABLEAUTORECONNECT , &dwTmpValue );
  547. pPolicy->fDisableAutoReconnect = (BOOLEAN) dwTmpValue;
  548. // New machine wide profile, home dir and home drive
  549. pPolicy->fPolicyWFProfilePath = GPGetStringValue( policyKey, WIN_WFPROFILEPATH,
  550. pPolicy ->WFProfilePath,
  551. DIRECTORY_LENGTH + 1 );
  552. pPolicy->fPolicyWFHomeDir = GPGetStringValue( policyKey, WIN_WFHOMEDIR ,
  553. pPolicy->WFHomeDir,
  554. DIRECTORY_LENGTH + 1 );
  555. pPolicy->fPolicyWFHomeDirDrive =GPGetStringValue( policyKey, WIN_WFHOMEDIRDRIVE,
  556. pPolicy->WFHomeDirDrive,
  557. 4 );
  558. // if home dir is of the form "driveletter:\path" (such as c:\foo), null out the dir-drive to
  559. // eliminate any confusion.
  560. if ( pPolicy->WFHomeDir[1] == L':' )
  561. {
  562. pPolicy->WFHomeDirDrive[0] = L'\0';
  563. }
  564. // --------------- deny connection policy, this is directly read by RegDenyTSConnectionsPolicy() too
  565. pPolicy->fPolicyDenyTSConnections =
  566. GPGetNumValue( policyKey, POLICY_DENY_TS_CONNECTIONS , &dwTmpValue );
  567. pPolicy->fDenyTSConnections = (BOOLEAN) dwTmpValue;
  568. // track the rest of all possivle GP policies
  569. // even thou not all are used by term-srv's USERCONFIGW . A good example is the
  570. // delete tmp folders that Winlogon/wlnotify uses.
  571. // --------------- Per session tmp folders, WARNING : GINA reads policy tree directly for the sake of lower overhead during login
  572. pPolicy->fPolicyTempFoldersPerSession =
  573. GPGetNumValue( policyKey, REG_TERMSRV_PERSESSIONTEMPDIR , &dwTmpValue );
  574. pPolicy-> fTempFoldersPerSession = (BOOLEAN) dwTmpValue;
  575. // -------------- delete per session folders on exit, WARNING : GINA reads policy tree directly for the sake of lower overhead during login
  576. pPolicy->fPolicyDeleteTempFoldersOnExit =
  577. GPGetNumValue( policyKey, REG_CITRIX_DELETETEMPDIRSONEXIT , &dwTmpValue );
  578. pPolicy->fDeleteTempFoldersOnExit = (BOOLEAN) dwTmpValue;
  579. pPolicy->fPolicyPreventLicenseUpgrade =
  580. GPGetNumValue( policyKey, REG_POLICY_PREVENT_LICENSE_UPGRADE , &dwTmpValue );
  581. pPolicy->fPreventLicenseUpgrade = (BOOLEAN) dwTmpValue;
  582. // -------------- Color Depth
  583. pPolicy->fPolicyColorDepth =
  584. GPGetNumValue( policyKey, POLICY_TS_COLOR_DEPTH , &dwTmpValue );
  585. // disabled policy will set value to zero, which we will force it
  586. // to be the min color depth of 8 bits.
  587. if ( dwTmpValue < TS_8BPP_SUPPORT )
  588. {
  589. pPolicy->ColorDepth = TS_8BPP_SUPPORT ;
  590. }
  591. else if ( dwTmpValue == TS_CLIENT_COMPAT_BPP_SUPPORT )
  592. {
  593. pPolicy->ColorDepth = TS_24BPP_SUPPORT; // our current max, may change in teh future.
  594. }
  595. else
  596. {
  597. pPolicy->ColorDepth = dwTmpValue;
  598. }
  599. // ---------------- TSCC's permissions TAB
  600. pPolicy->fPolicyWritableTSCCPermissionsTAB =
  601. GPGetNumValue( policyKey, POLICY_TS_TSCC_PERM_TAB_WRITABLE , &dwTmpValue );
  602. pPolicy->fWritableTSCCPermissionsTAB= (BOOLEAN) dwTmpValue;
  603. // ----------------
  604. // Ritu has folded the user policy into machine policy for the drive re-direction.
  605. pPolicy->fPolicyDisableCdm =
  606. GPGetNumValue( policyKey, WIN_DISABLECDM , &dwTmpValue );
  607. pPolicy->fDisableCdm = (BOOLEAN) dwTmpValue;
  608. // ----------------
  609. // fold user config policy into machine config policy
  610. pPolicy->fPolicyForceClientLptDef =
  611. GPGetNumValue( policyKey,WIN_FORCECLIENTLPTDEF , &dwTmpValue );
  612. pPolicy->fForceClientLptDef = (BOOLEAN) dwTmpValue;
  613. // for user config policy into machine config policy
  614. // ----------------
  615. pPolicy->fPolicyShadow =
  616. GPGetNumValue( policyKey, WIN_SHADOW, &dwTmpValue );
  617. pPolicy->Shadow = (SHADOWCLASS) dwTmpValue;
  618. //
  619. // ---- Sessions Policy
  620. //
  621. // ----------------
  622. pPolicy->fPolicyResetBroken =
  623. GPGetNumValue( policyKey,WIN_RESETBROKEN , & dwTmpValue );
  624. pPolicy->fResetBroken = (BOOLEAN) dwTmpValue;
  625. // ----------------
  626. pPolicy->fPolicyReconnectSame =
  627. GPGetNumValue( policyKey,WIN_RECONNECTSAME , &dwTmpValue );
  628. pPolicy->fReconnectSame = (BOOLEAN) dwTmpValue;
  629. // ----------------
  630. pPolicy->fPolicyMaxSessionTime =
  631. GPGetNumValue( policyKey, WIN_MAXCONNECTIONTIME , &dwTmpValue );
  632. pPolicy->MaxConnectionTime = dwTmpValue;
  633. // ----------------
  634. pPolicy->fPolicyMaxDisconnectionTime =
  635. GPGetNumValue( policyKey,WIN_MAXDISCONNECTIONTIME ,&dwTmpValue );
  636. pPolicy->MaxDisconnectionTime = dwTmpValue;
  637. // ----------------
  638. pPolicy->fPolicyMaxIdleTime =
  639. GPGetNumValue( policyKey,WIN_MAXIDLETIME , &dwTmpValue );
  640. pPolicy->MaxIdleTime = dwTmpValue;
  641. // ---------------- Start program policy
  642. pPolicy->fPolicyInitialProgram = GPGetStringValue( policyKey, WIN_INITIALPROGRAM,
  643. pPolicy->InitialProgram,
  644. INITIALPROGRAM_LENGTH + 1 );
  645. GPGetStringValue( policyKey, WIN_WORKDIRECTORY,
  646. pPolicy->WorkDirectory,
  647. DIRECTORY_LENGTH + 1 );
  648. // ---------------- single session per user
  649. pPolicy->fPolicySingleSessionPerUser=
  650. GPGetNumValue( policyKey,POLICY_TS_SINGLE_SESSION_PER_USER, &dwTmpValue );
  651. pPolicy->fSingleSessionPerUser = dwTmpValue;
  652. pPolicy->fPolicySessionDirectoryExposeServerIP =
  653. GPGetNumValue( policyKey, REG_TS_SESSDIR_EXPOSE_SERVER_ADDR , &dwTmpValue );
  654. pPolicy->SessionDirectoryExposeServerIP = dwTmpValue;
  655. // policy for disabling wallpaper in remote desktop
  656. pPolicy->fPolicyDisableWallpaper =
  657. GPGetNumValue( policyKey, POLICY_TS_NO_REMOTE_DESKTOP_WALLPAPER, &dwTmpValue );
  658. pPolicy->fDisableWallpaper = dwTmpValue;
  659. // policy to enable disable keep alive
  660. pPolicy->fPolicyKeepAlive =
  661. GPGetNumValue( policyKey, KEEP_ALIVE_ENABLE_KEY , &dwTmpValue );
  662. pPolicy->fKeepAliveEnable = dwTmpValue;
  663. GPGetNumValue( policyKey, KEEP_ALIVE_INTERVAL_KEY , &dwTmpValue );
  664. pPolicy->KeepAliveInterval = dwTmpValue;
  665. }
  666. /*******************************************************************************
  667. * RegGetMachinePolicy()
  668. *
  669. * Params:
  670. * [out] pPolicy : the machine policy used by ts session's userconfig
  671. *
  672. * Return:
  673. * void
  674. *
  675. *******************************************************************************/
  676. void RegGetMachinePolicy(
  677. PPOLICY_TS_MACHINE pPolicy )
  678. {
  679. NTSTATUS status= STATUS_SUCCESS;
  680. HKEY policyKey;
  681. status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TS_POLICY_SUB_TREE, 0,
  682. KEY_READ, &policyKey );
  683. if ( status != ERROR_SUCCESS)
  684. {
  685. policyKey = NULL; // prefix complains.
  686. }
  687. // ok to call this with policyKey=NULL since func will init pPolicy using default values for the case of NULL key.
  688. GPQueryMachineConfig( policyKey, pPolicy );
  689. if ( policyKey )
  690. {
  691. RegCloseKey( policyKey );
  692. }
  693. }
  694. /*******************************************************************************
  695. * RegGetMachinePolicyiEx()
  696. *
  697. * This func is identical to RegGetMachinePolicy() , and provides the time stampt for
  698. * the last write time of the policy key, and if the time of the key is the same as the
  699. * time for the last read, then it will not bother with any reads and return false
  700. *
  701. * Params:
  702. * [in ] forcePolicyRead : 1st time around, you want to init all vars so force a read.
  703. * [in/out] pTime : caller passes in the last write time for the machine policy key.
  704. * if key is missing, then time is set to zero.
  705. * On return, this param is updated to reflect the most recent
  706. * update time, which could be zero if the policy key was deleted
  707. *
  708. * [out] pPolicy : the machine policy struct updated
  709. *
  710. * Return:
  711. * TRUE : means there was a real change present
  712. * FALSE : means no values had changed.
  713. *******************************************************************************/
  714. BOOLEAN RegGetMachinePolicyEx(
  715. BOOLEAN forcePolicyRead,
  716. FILETIME *pTime ,
  717. PPOLICY_TS_MACHINE pPolicy )
  718. {
  719. HKEY policyKey;
  720. FILETIME newTime;
  721. NTSTATUS status= STATUS_SUCCESS;
  722. BOOLEAN rc = FALSE;
  723. status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TS_POLICY_SUB_TREE, 0,
  724. KEY_READ, &policyKey );
  725. if ( status != ERROR_SUCCESS)
  726. {
  727. policyKey = NULL; // prefix complains.
  728. }
  729. // if we have a policy key, get the time for that key
  730. if (policyKey)
  731. {
  732. RegQueryInfoKey( policyKey, NULL, NULL, NULL, NULL, NULL,
  733. NULL, NULL, NULL, NULL, NULL, &newTime );
  734. }
  735. else // else, init time to the current system time
  736. {
  737. SYSTEMTIME currentTimeOnSystemInSystemTimeUnits;
  738. GetSystemTime( &currentTimeOnSystemInSystemTimeUnits );
  739. SystemTimeToFileTime( & currentTimeOnSystemInSystemTimeUnits , & newTime );
  740. }
  741. if ( forcePolicyRead ||
  742. ( (pTime->dwHighDateTime < newTime.dwHighDateTime ) ||
  743. ( ( pTime->dwHighDateTime == newTime.dwHighDateTime ) && pTime->dwLowDateTime < newTime.dwLowDateTime ) ) )
  744. {
  745. // this call will init struct memebers even if the policy key in null, so it
  746. // is required to make this call on startup, with or without an actual reg key being present
  747. GPQueryMachineConfig( policyKey, pPolicy );
  748. rc = TRUE;
  749. }
  750. pTime->dwHighDateTime = newTime.dwHighDateTime;
  751. pTime->dwLowDateTime = newTime.dwLowDateTime;
  752. if ( policyKey )
  753. {
  754. RegCloseKey( policyKey );
  755. }
  756. return rc;
  757. }
  758. /*******************************************************************************
  759. * RegMergeMachinePolicy()
  760. *
  761. * Params:
  762. * [in] pPolicy : policy data to use to override userconfig
  763. * [in/out] pWSConfig : userconfig data that is modified based on the policy data
  764. *
  765. * Return:
  766. * void
  767. *
  768. ********************************************************************************/
  769. void RegMergeMachinePolicy(
  770. PPOLICY_TS_MACHINE pPolicy, // the policy override data
  771. USERCONFIGW * pWSConfig, // the machine config data represented thru a USERCONFIGW data struct (mostly)
  772. PWINSTATIONCREATE pCreate // some of winstation data is stored here
  773. )
  774. {
  775. // ---------------------------------------------- Clipboard
  776. if ( pPolicy->fPolicyDisableClip )
  777. {
  778. pWSConfig->fDisableClip = pPolicy->fDisableClip;
  779. }
  780. // ---------------------------------------------- Audio
  781. if ( pPolicy->fPolicyDisableCam )
  782. {
  783. pWSConfig->fDisableCam = pPolicy->fDisableCam;
  784. }
  785. // ---------------------------------------------- Comport
  786. if ( pPolicy->fPolicyDisableCcm )
  787. {
  788. pWSConfig->fDisableCcm = pPolicy->fDisableCcm;
  789. }
  790. // ---------------------------------------------- LPT
  791. if ( pPolicy->fPolicyDisableLPT )
  792. {
  793. pWSConfig->fDisableLPT = pPolicy->fDisableLPT;
  794. }
  795. // ---------------------------------------------- PRN
  796. if ( pPolicy->fPolicyDisableCpm )
  797. {
  798. pWSConfig->fDisableCpm = pPolicy->fDisableCpm;
  799. }
  800. // ---------------------------------------------- Password
  801. if ( pPolicy->fPolicyPromptForPassword )
  802. {
  803. pWSConfig->fPromptForPassword = pPolicy->fPromptForPassword;
  804. }
  805. // ---------------------------------------------- Max Instance
  806. if ( pPolicy->fPolicyMaxInstanceCount )
  807. {
  808. pCreate->MaxInstanceCount = pPolicy->MaxInstanceCount;
  809. }
  810. // ---------------------------------------------- Min Encryption Level
  811. if ( pPolicy->fPolicyMinEncryptionLevel )
  812. {
  813. pWSConfig->MinEncryptionLevel = pPolicy->MinEncryptionLevel;
  814. }
  815. // ---------------------------------------------- Auto Reconnect disable
  816. if ( pPolicy->fPolicyDisableAutoReconnect )
  817. {
  818. pWSConfig->fDisableAutoReconnect = pPolicy->fDisableAutoReconnect;
  819. }
  820. // ----------------------------------------------
  821. if (pPolicy->fPolicyWFProfilePath )
  822. {
  823. wcscpy( pWSConfig->WFProfilePath, pPolicy->WFProfilePath );
  824. }
  825. else
  826. {
  827. pWSConfig->WFProfilePath[0] = L'\0';
  828. }
  829. // ----------------------------------------------
  830. if ( pPolicy->fPolicyWFHomeDir )
  831. {
  832. wcscpy( pWSConfig->WFHomeDir, pPolicy->WFHomeDir );
  833. }
  834. else
  835. {
  836. pWSConfig->WFHomeDir[0] = L'\0';
  837. }
  838. // ----------------------------------------------
  839. if ( pPolicy->fPolicyWFHomeDirDrive )
  840. {
  841. wcscpy( pWSConfig->WFHomeDirDrive, pPolicy->WFHomeDirDrive );
  842. }
  843. else
  844. {
  845. pWSConfig->WFHomeDirDrive[0] = L'\0';
  846. }
  847. if ( pPolicy->fPolicyColorDepth)
  848. {
  849. pWSConfig->ColorDepth = pPolicy->ColorDepth ;
  850. //NA 2/23/01
  851. pWSConfig->fInheritColorDepth = FALSE;
  852. }
  853. //
  854. if ( pPolicy->fPolicyDisableCdm)
  855. {
  856. pWSConfig->fDisableCdm = pPolicy->fDisableCdm;
  857. }
  858. //
  859. if ( pPolicy->fPolicyForceClientLptDef )
  860. {
  861. pWSConfig->fForceClientLptDef = pPolicy->fForceClientLptDef;
  862. }
  863. // Shadow
  864. if ( pPolicy->fPolicyShadow)
  865. {
  866. pWSConfig->Shadow = pPolicy->Shadow;
  867. pWSConfig->fInheritShadow = FALSE;
  868. }
  869. if (pPolicy->fPolicyResetBroken )
  870. {
  871. pWSConfig->fResetBroken = pPolicy->fResetBroken;
  872. pWSConfig->fInheritResetBroken = FALSE;
  873. }
  874. if (pPolicy->fPolicyReconnectSame )
  875. {
  876. pWSConfig->fReconnectSame = pPolicy->fReconnectSame;
  877. pWSConfig->fInheritReconnectSame = FALSE;
  878. }
  879. if (pPolicy->fPolicyMaxSessionTime )
  880. {
  881. pWSConfig->MaxConnectionTime = pPolicy->MaxConnectionTime;
  882. pWSConfig->fInheritMaxSessionTime = FALSE;
  883. }
  884. if (pPolicy->fPolicyMaxDisconnectionTime)
  885. {
  886. pWSConfig->MaxDisconnectionTime = pPolicy->MaxDisconnectionTime;
  887. pWSConfig->fInheritMaxDisconnectionTime = FALSE;
  888. }
  889. if (pPolicy->fPolicyMaxIdleTime)
  890. {
  891. pWSConfig->MaxIdleTime = pPolicy->MaxIdleTime;
  892. pWSConfig->fInheritMaxIdleTime = FALSE;
  893. }
  894. if (pPolicy->fPolicyInitialProgram)
  895. {
  896. wcscpy( pWSConfig->InitialProgram, pPolicy->InitialProgram );
  897. wcscpy( pWSConfig->WorkDirectory, pPolicy->WorkDirectory );
  898. pWSConfig->fInheritInitialProgram = FALSE;
  899. }
  900. if ( pPolicy->fPolicyDisableWallpaper )
  901. {
  902. pWSConfig->fWallPaperDisabled = pPolicy->fDisableWallpaper ;
  903. }
  904. // ----------------------------------------------
  905. // There is no UI for setting these... So it's probably never used
  906. //
  907. // if ( pPolicy->fPolicytSecurity )
  908. // {
  909. // pWSConfig->fDisableEncryption = pPolicy->fDisableEncryption;
  910. // pWSConfig->MinEncryptionLevel = pPolicy->MinEncryptionLevel;
  911. // }
  912. // else
  913. // {
  914. // if ( pWSConfig->fInheritSecurity )
  915. // {
  916. // pWSConfig->fDisableEncryption = pPolicy->fDisableEncryption;
  917. // pWSConfig->MinEncryptionLevel = pPolicy->MinEncryptionLevel;
  918. // }
  919. // }
  920. }