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.

1652 lines
55 KiB

  1. //*************************************************************
  2. //
  3. // Group Policy Support for planning mode
  4. //
  5. // Microsoft Confidential
  6. // Copyright (c) Microsoft Corporation 1997-1998
  7. // All rights reserved
  8. //
  9. //*************************************************************
  10. #include "gphdr.h"
  11. #include <strsafe.h>
  12. DWORD GenerateRegistryPolicy( DWORD dwFlags,
  13. BOOL *pbAbort,
  14. WCHAR *pwszSite,
  15. PRSOP_TARGET pComputerTarget,
  16. PRSOP_TARGET pUserTarget );
  17. BOOL GenerateGpoInfo( WCHAR *pwszDomain, WCHAR *pwszDomainDns, WCHAR *pwszAccount,
  18. WCHAR *pwszNewSOM, SAFEARRAY *psaSecGroups,
  19. DWORD dwFlags, BOOL bMachine, WCHAR *pwszSite, CGpoFilter *pGpoFilter, CLocator *pLocator,
  20. WCHAR *pwszMachAccount, WCHAR *pwszNewMachSOM, LPGPOINFO pGpoInfo, PNETAPI32_API pNetAPI32 );
  21. BOOL GetCategory( WCHAR *pwszDomain, WCHAR *pwszAccount, WCHAR **ppwszDNName );
  22. extern "C" DWORD ProcessMachAndUserGpoList( LPGPEXT lpExtMach, LPGPEXT lpExtUser, DWORD dwFlags, WCHAR *pwszSite,
  23. WCHAR *pwszMach, WCHAR *pwszNewComputerOU, SAFEARRAY *psaComputerSecurityGroups, LPGPOINFO pGpoInfoMach,
  24. WCHAR *pwszUser, WCHAR *pwszNewUserOU, SAFEARRAY *psaUserSecurityGroups, LPGPOINFO pGpoInfoUser );
  25. BOOL ProcessRegistryFiles(PRSOP_TARGET pTarget, REGHASHTABLE *pHashTable);
  26. BOOL ProcessRegistryValue ( void* pUnused,
  27. LPTSTR lpKeyName,
  28. LPTSTR lpValueName,
  29. DWORD dwType,
  30. DWORD dwDataLength,
  31. LPBYTE lpData,
  32. WCHAR *pwszGPO,
  33. WCHAR *pwszSOM,
  34. REGHASHTABLE *pHashTable);
  35. BOOL ProcessAdmData( PRSOP_TARGET pTarget, BOOL bUser );
  36. //*************************************************************
  37. //
  38. // GenerateRsopPolicy()
  39. //
  40. // Purpose: Generates planning mode Rsop policy for specified target
  41. //
  42. // Parameters: dwFlags - Processing flags
  43. // bstrMachName - Target computer name
  44. // bstrNewMachSOM - New machine domain or OU
  45. // psaMachSecGroups - New machine security groups
  46. // bstrUserName - Target user name
  47. // psaUserSecGroups - New user security groups
  48. // bstrSite - Site of target computer
  49. // pwszNameSpace - Namespace to write Rsop data
  50. // pvProgress - Progress indicator class
  51. // pvGpoFilter - GPO filter class
  52. //
  53. // Return: True if successful, False otherwise
  54. //
  55. // Notes: If a new SOM is specified then that is used instead of
  56. // the SOM the target belongs to. Similarly, if new
  57. // security groups are specified then that is used instead of
  58. // the security groups that the target belongs to. If
  59. // target name is null and both new SOM and new security
  60. // groups are non-null, then we simulate a dummy target; otherwise
  61. // we skip generating planning mode info for the target.
  62. //
  63. //*************************************************************
  64. BOOL GenerateRsopPolicy( DWORD dwFlags, BSTR bstrMachName,
  65. BSTR bstrNewMachSOM, SAFEARRAY *psaMachSecGroups,
  66. BSTR bstrUserName, BSTR bstrNewUserSOM,
  67. SAFEARRAY *psaUserSecGroups,
  68. BSTR bstrSite,
  69. WCHAR *pwszNameSpace,
  70. LPVOID pvProgress,
  71. LPVOID pvMachGpoFilter,
  72. LPVOID pvUserGpoFilter )
  73. {
  74. LPGPOINFO pGpoInfoMach = NULL;
  75. LPGPOINFO pGpoInfoUser = NULL;
  76. PNETAPI32_API pNetAPI32 = NULL;
  77. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pDsInfo = NULL;
  78. BOOL bDC = FALSE;
  79. DWORD dwResult;
  80. LPWSTR pwszDomain = NULL;
  81. LPWSTR pwszMachDns = NULL;
  82. LPWSTR pwszDomainDns = NULL;
  83. DWORD dwSize = 0;
  84. BOOL bResult = FALSE;
  85. LPGPEXT lpExtMach = NULL;
  86. LPGPEXT lpExtUser = NULL;
  87. LPGPEXT lpExt,lpTemp = NULL;
  88. WCHAR *pwszMach = (WCHAR *) bstrMachName;
  89. WCHAR *pwszUser = (WCHAR *) bstrUserName;
  90. DWORD dwExtCount = 1;
  91. DWORD dwIncrPercent;
  92. CProgressIndicator* pProgress = (CProgressIndicator*) pvProgress;
  93. CGpoFilter *pMachGpoFilter = (CGpoFilter *) pvMachGpoFilter;
  94. CGpoFilter *pUserGpoFilter = (CGpoFilter *) pvUserGpoFilter;
  95. RSOPSESSIONDATA rsopSessionData;
  96. LPRSOPSESSIONDATA lprsopSessionData;
  97. BOOL bDummyMach = pwszMach == NULL && bstrNewMachSOM != NULL;
  98. BOOL bDummyUser = pwszUser == NULL && bstrNewUserSOM != NULL;
  99. DWORD dwUserGPCoreError = ERROR_SUCCESS;
  100. DWORD dwMachGPCoreError = ERROR_SUCCESS;
  101. CLocator locator;
  102. HRESULT hr = S_OK;
  103. XLastError xe;
  104. //
  105. // Allow debugging level to be changed dynamically
  106. //
  107. InitDebugSupport( FALSE );
  108. if ( pwszUser == NULL && pwszMach == NULL && !bDummyUser && !bDummyMach ) {
  109. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Both user and machine names cannot be NULL.")));
  110. xe = ERROR_INVALID_PARAMETER;
  111. return FALSE;
  112. }
  113. pNetAPI32 = LoadNetAPI32();
  114. if (!pNetAPI32) {
  115. xe = GetLastError();
  116. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Failed to load netapi32 with %d."),
  117. GetLastError()));
  118. // error logged in LoadNetAPI32
  119. goto Exit;
  120. }
  121. //
  122. // Get the role of this computer
  123. //
  124. dwResult = pNetAPI32->pfnDsRoleGetPrimaryDomainInformation( NULL, DsRolePrimaryDomainInfoBasic,
  125. (PBYTE *)&pDsInfo );
  126. if (dwResult != ERROR_SUCCESS) {
  127. xe = GetLastError();
  128. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: DsRoleGetPrimaryDomainInformation failed with %d."), dwResult));
  129. goto Exit;
  130. }
  131. if ( pDsInfo->MachineRole == DsRole_RoleBackupDomainController
  132. || pDsInfo->MachineRole == DsRole_RolePrimaryDomainController ) {
  133. bDC = TRUE;
  134. }
  135. if ( !bDC ) {
  136. xe = ERROR_ACCESS_DENIED;
  137. DebugMsg((DM_WARNING, TEXT("GeneratRsopPolicy: Rsop data can be generated on a DC only")));
  138. goto Exit;
  139. }
  140. pwszDomain = pDsInfo->DomainNameFlat;
  141. //
  142. // Get the machine name in dns format, so that ldap_bind can be done to this specific DC.
  143. //
  144. dwSize = 0;
  145. GetComputerNameEx( ComputerNameDnsFullyQualified, pwszMachDns, &dwSize );
  146. if ( dwSize > 0 ) {
  147. pwszMachDns = (WCHAR *) LocalAlloc (LPTR, dwSize * sizeof(WCHAR) );
  148. if ( pwszMachDns == NULL ) {
  149. xe = GetLastError();
  150. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Failed to allocate memory")));
  151. goto Exit;
  152. }
  153. } else {
  154. xe = GetLastError();
  155. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: GetComputerNameEx failed")));
  156. goto Exit;
  157. }
  158. bResult = GetComputerNameEx( ComputerNameDnsFullyQualified, pwszMachDns, &dwSize );
  159. if ( !bResult ) {
  160. xe = GetLastError();
  161. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: GetComputerNameEx failed")));
  162. goto Exit;
  163. }
  164. pwszDomainDns = pwszMachDns;
  165. //
  166. // 5% of the task is done
  167. //
  168. pProgress->IncrementBy( 5 );
  169. //
  170. // Setup computer target info, if any
  171. //
  172. bResult = FALSE;
  173. if ( pwszMach || bDummyMach ) {
  174. pGpoInfoMach = (LPGPOINFO) LocalAlloc (LPTR, sizeof(GPOINFO));
  175. if (!pGpoInfoMach) {
  176. xe = GetLastError();
  177. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Failed to alloc lpGPOInfo (%d)."),
  178. GetLastError()));
  179. CEvents ev(TRUE, EVENT_FAILED_ALLOCATION);
  180. ev.AddArgWin32Error(GetLastError()); ev.Report();
  181. goto Exit;
  182. }
  183. pGpoInfoMach->dwFlags = GP_PLANMODE | GP_MACHINE;
  184. bResult = GetWbemServices( pGpoInfoMach, pwszNameSpace, TRUE, NULL, &(pGpoInfoMach->pWbemServices) );
  185. if (!bResult) {
  186. xe = GetLastError();
  187. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Error when getting Wbemservices.")));
  188. goto Exit;
  189. }
  190. //
  191. // First set dirty to be true
  192. //
  193. bResult = LogExtSessionStatus(pGpoInfoMach->pWbemServices, NULL, TRUE);
  194. if (!bResult) {
  195. xe = GetLastError();
  196. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Error when logging user Session data.")));
  197. goto Exit;
  198. }
  199. if ( ! GenerateGpoInfo( pwszDomain, pwszDomainDns, pwszMach,
  200. (WCHAR *) bstrNewMachSOM, psaMachSecGroups, dwFlags, TRUE,
  201. (WCHAR *) bstrSite, pMachGpoFilter, &locator, NULL, NULL, pGpoInfoMach, pNetAPI32 ) ) {
  202. xe = GetLastError();
  203. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: GenerateGpoInfo failed with %d."), xe));
  204. dwMachGPCoreError = (xe) ? xe : E_FAIL;
  205. }
  206. else {
  207. dwMachGPCoreError = ERROR_SUCCESS;
  208. }
  209. }
  210. //
  211. // 10% of the task is done
  212. //
  213. pProgress->IncrementBy( 5 );
  214. //
  215. // Setup user target info, if any
  216. //
  217. if ( pwszUser || bDummyUser ) {
  218. pGpoInfoUser = (LPGPOINFO) LocalAlloc (LPTR, sizeof(GPOINFO));
  219. if (!pGpoInfoUser) {
  220. xe = GetLastError();
  221. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Failed to alloc lpGPOInfo (%d)."),
  222. GetLastError()));
  223. CEvents ev(TRUE, EVENT_FAILED_ALLOCATION);
  224. ev.AddArgWin32Error(GetLastError()); ev.Report();
  225. goto Exit;
  226. }
  227. pGpoInfoUser->dwFlags = GP_PLANMODE;
  228. bResult = GetWbemServices( pGpoInfoUser, pwszNameSpace, TRUE, NULL, &(pGpoInfoUser->pWbemServices));
  229. if (!bResult) {
  230. xe = GetLastError();
  231. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Error when getting Wbemservices.")));
  232. goto Exit;
  233. }
  234. //
  235. // First set dirty to be true
  236. //
  237. bResult = LogExtSessionStatus(pGpoInfoUser->pWbemServices, NULL, TRUE);
  238. if (!bResult) {
  239. xe = GetLastError();
  240. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Error when logging user Session data.")));
  241. goto Exit;
  242. }
  243. if ( ! GenerateGpoInfo( pwszDomain, pwszDomainDns, pwszUser,
  244. (WCHAR *) bstrNewUserSOM, psaUserSecGroups, dwFlags, FALSE, (WCHAR *) bstrSite,
  245. pUserGpoFilter, &locator, pwszMach, (WCHAR *) bstrNewMachSOM, pGpoInfoUser, pNetAPI32 ) ) {
  246. xe = GetLastError();
  247. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: GenerateGpoInfo failed with %d."), xe));
  248. dwUserGPCoreError = (xe) ? xe : E_FAIL;
  249. }
  250. else {
  251. dwUserGPCoreError = ERROR_SUCCESS;
  252. }
  253. }
  254. //
  255. // Log Gpo info to WMI's database
  256. //
  257. lprsopSessionData = &rsopSessionData;
  258. if ( pwszMach || bDummyMach ) {
  259. XPtrLF<TOKEN_GROUPS> xGrps;
  260. if ( pGpoInfoMach->pRsopToken != NULL )
  261. {
  262. hr = RsopSidsFromToken(pGpoInfoMach->pRsopToken, &xGrps);
  263. if (FAILED(hr)) {
  264. xe = HRESULT_CODE(hr);
  265. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: RsopSidsFromToken failed with error 0x%x."), hr));
  266. goto Exit;
  267. }
  268. }
  269. //
  270. // Fill up the rsop Session Data (Machine Specific)
  271. //
  272. //
  273. // Add the relevant flags corresponding to the input parameters for machine
  274. //
  275. DebugMsg((DM_VERBOSE, TEXT("GenerateRsopPolicy: Marking the flags for machine with appropriate input parameters")));
  276. lprsopSessionData->dwFlags = FLAG_PLANNING_MODE;
  277. lprsopSessionData->dwFlags |= (dwFlags & FLAG_ASSUME_COMP_WQLFILTER_TRUE);
  278. lprsopSessionData->pwszTargetName = pwszMach;
  279. lprsopSessionData->pwszSOM = GetSomPath(bstrNewMachSOM ? bstrNewMachSOM : pGpoInfoMach->lpDNName);
  280. if ( pGpoInfoMach->pRsopToken != NULL )
  281. {
  282. lprsopSessionData->pSecurityGroups = (PTOKEN_GROUPS)xGrps;
  283. lprsopSessionData->bLogSecurityGroup = TRUE;
  284. }
  285. else
  286. {
  287. lprsopSessionData->pSecurityGroups = 0;
  288. lprsopSessionData->bLogSecurityGroup = FALSE;
  289. }
  290. lprsopSessionData->pwszSite = (WCHAR *) bstrSite;
  291. lprsopSessionData->bMachine = TRUE;
  292. lprsopSessionData->bSlowLink = ( dwFlags & FLAG_ASSUME_SLOW_LINK ) ? TRUE: FALSE;
  293. bResult = LogRsopData( pGpoInfoMach, lprsopSessionData );
  294. if (!bResult) {
  295. xe = GetLastError();
  296. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Error when logging machine Rsop data.")));
  297. goto Exit;
  298. }
  299. pGpoInfoMach->bRsopLogging = TRUE;
  300. }
  301. if ( pwszUser || bDummyUser ) {
  302. XPtrLF<TOKEN_GROUPS> xGrps;
  303. if ( pGpoInfoUser->pRsopToken != NULL )
  304. {
  305. hr = RsopSidsFromToken(pGpoInfoUser->pRsopToken, &xGrps);
  306. if (FAILED(hr)) {
  307. xe = HRESULT_CODE(hr);
  308. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: RsopSidsFromToken failed with error 0x%x."), hr));
  309. goto Exit;
  310. }
  311. }
  312. //
  313. // Fill up the rsop Session Data (User Specific)
  314. //
  315. lprsopSessionData->pwszTargetName = pwszUser;
  316. lprsopSessionData->pwszSOM = GetSomPath(bstrNewUserSOM ? bstrNewUserSOM : pGpoInfoUser->lpDNName);
  317. //
  318. // Add the relevant flags corresponding to the input parameters for user
  319. //
  320. lprsopSessionData->dwFlags = FLAG_PLANNING_MODE;
  321. lprsopSessionData->dwFlags |= (dwFlags & FLAG_ASSUME_USER_WQLFILTER_TRUE);
  322. lprsopSessionData->dwFlags |= (dwFlags & FLAG_LOOPBACK_MERGE);
  323. lprsopSessionData->dwFlags |= (dwFlags & FLAG_LOOPBACK_REPLACE);
  324. DebugMsg((DM_VERBOSE, TEXT("GenerateRsopPolicy: Marking the flags for user with appropriate input parameters")));
  325. if ( pGpoInfoUser->pRsopToken != NULL )
  326. {
  327. lprsopSessionData->pSecurityGroups = (PTOKEN_GROUPS)xGrps;
  328. lprsopSessionData->bLogSecurityGroup = TRUE;
  329. }
  330. else
  331. {
  332. lprsopSessionData->pSecurityGroups = 0;
  333. lprsopSessionData->bLogSecurityGroup = FALSE;
  334. }
  335. lprsopSessionData->pwszSite = (WCHAR *) bstrSite;
  336. lprsopSessionData->bMachine = FALSE;
  337. lprsopSessionData->bSlowLink = ( dwFlags & FLAG_ASSUME_SLOW_LINK ) ? TRUE: FALSE;
  338. bResult = LogRsopData( pGpoInfoUser, lprsopSessionData );
  339. if (!bResult) {
  340. xe = GetLastError();
  341. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Error when logging user Rsop data.")));
  342. goto Exit;
  343. }
  344. pGpoInfoUser->bRsopLogging = TRUE;
  345. }
  346. if ( ( dwUserGPCoreError != ERROR_SUCCESS) || ( dwMachGPCoreError != ERROR_SUCCESS) ){
  347. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Couldn't fetch the user/computer GPO list. Exitting provider.")));
  348. // note that at this point bResult can be true and we want to actually return that
  349. // since this error will be part of the GP Core error...
  350. goto Exit;
  351. }
  352. //
  353. // 15% of the task is done
  354. //
  355. pProgress->IncrementBy( 5 );
  356. if ( dwFlags & FLAG_NO_CSE_INVOKE )
  357. {
  358. bResult = TRUE;
  359. goto Exit;
  360. }
  361. //
  362. // By this time, pGPOInfoMach should be defined if
  363. // we needed data for mach and pGPOInfoUser should be
  364. // defined if we needed the data for user.
  365. //
  366. // Assumption: lpExt is the same for both user and Machine
  367. //
  368. if (pGpoInfoMach)
  369. lpExt = lpExtMach = pGpoInfoMach->lpExtensions;
  370. if (pGpoInfoUser)
  371. lpExt = lpExtUser = pGpoInfoUser->lpExtensions;
  372. //
  373. // count the number of extensions
  374. //
  375. DmAssert(lpExt);
  376. lpTemp = lpExt;
  377. while ( lpExt )
  378. {
  379. dwExtCount++;
  380. lpExt = lpExt->pNext;
  381. }
  382. lpExt = lpTemp;
  383. dwIncrPercent = ( pProgress->MaxProgress() - pProgress->CurrentProgress() ) / dwExtCount;
  384. //
  385. // Loop through registered extensions, asking them to generate planning mode info
  386. //
  387. while ( lpExt ) {
  388. //
  389. // Add check here for cancellation of policy generation
  390. //
  391. DebugMsg((DM_VERBOSE, TEXT("GenerateRsopPolicy: -----------------------")));
  392. DebugMsg((DM_VERBOSE, TEXT("GenerateRsopPolicy: Processing extension %s"), lpExt->lpDisplayName));
  393. if (lpExtMach)
  394. FilterGPOs( lpExtMach, pGpoInfoMach );
  395. if (lpExtUser)
  396. FilterGPOs( lpExtUser, pGpoInfoUser );
  397. __try {
  398. dwResult = ProcessMachAndUserGpoList( lpExtMach, lpExtUser, dwFlags, (WCHAR *) bstrSite,
  399. pwszMach, (WCHAR *) bstrNewMachSOM, psaMachSecGroups, pGpoInfoMach,
  400. pwszUser, (WCHAR *) bstrNewUserSOM, psaUserSecGroups, pGpoInfoUser );
  401. pProgress->IncrementBy( dwIncrPercent );
  402. }
  403. __except( GPOExceptionFilter( GetExceptionInformation() ) ) {
  404. RevertToSelf();
  405. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Extension %s ProcessGroupPolicy threw unhandled exception 0x%x."),
  406. lpExt->lpDisplayName, GetExceptionCode() ));
  407. CEvents ev(TRUE, EVENT_CAUGHT_EXCEPTION);
  408. ev.AddArg(lpExt->lpDisplayName); ev.AddArgHex(GetExceptionCode()); ev.Report();
  409. }
  410. DebugMsg((DM_VERBOSE, TEXT("GenerateRsopPolicy: -----------------------")));
  411. if (lpExtMach)
  412. lpExtMach = lpExtMach->pNext;
  413. if (lpExtUser)
  414. lpExtUser = lpExtUser->pNext;
  415. lpExt = lpExt->pNext;
  416. }
  417. bResult = TRUE;
  418. Exit:
  419. //
  420. // if all logging was successful
  421. //
  422. if ((pGpoInfoUser) && (pGpoInfoUser->bRsopLogging)) {
  423. bResult = UpdateExtSessionStatus(pGpoInfoUser->pWbemServices, NULL, (!bResult), dwUserGPCoreError );
  424. }
  425. if ((pGpoInfoMach) && (pGpoInfoMach->bRsopLogging)) {
  426. bResult = UpdateExtSessionStatus(pGpoInfoMach->pWbemServices, NULL, (!bResult), dwMachGPCoreError);
  427. }
  428. UnloadGPExtensions( pGpoInfoMach );
  429. UnloadGPExtensions( pGpoInfoUser ); // Frees lpExtensions field
  430. if ( pDsInfo ) {
  431. pNetAPI32->pfnDsRoleFreeMemory (pDsInfo);
  432. }
  433. LocalFree( pwszMachDns );
  434. FreeGpoInfo( pGpoInfoUser );
  435. FreeGpoInfo( pGpoInfoMach );
  436. return bResult;
  437. }
  438. //*************************************************************
  439. //
  440. // GenerateGpoInfo()
  441. //
  442. // Purpose: Allocates and fills in pGpoInfo for specified target
  443. //
  444. // Parameters: pwszDomain - Domain name
  445. // pwszDomainDns - Dns name of machine for ldap binding
  446. // pwszAccount - User or machine account name
  447. // pwszNewSOM - New SOM of target
  448. // psaSecGroups - New security groups of target
  449. // dwFlags - Processing flags
  450. // bMachine - Is this machine processing
  451. // pwszSite - Site name
  452. // pGpoFilter - Gpo filter
  453. // pLocator - Wbem interface class
  454. // pwszMachAccount - Machine account
  455. // pwszNewMachSOM - Machine SOM (abv 2 are applicable only for loopback)
  456. // ppGpoInfo - Gpo info returned here
  457. // pNetApi32 - Delay loaded netap32.dll
  458. //
  459. // Return: True if successful, False otherwise
  460. //
  461. //*************************************************************
  462. BOOL GenerateGpoInfo( WCHAR *pwszDomain, WCHAR *pwszDomainDns, WCHAR *pwszAccount,
  463. WCHAR *pwszNewSOM, SAFEARRAY *psaSecGroups,
  464. DWORD dwFlags, BOOL bMachine, WCHAR *pwszSite, CGpoFilter *pGpoFilter, CLocator *pLocator,
  465. WCHAR *pwszMachAccount, WCHAR *pwszNewMachSOM, LPGPOINFO pGpoInfo, PNETAPI32_API pNetAPI32 )
  466. {
  467. HRESULT hr;
  468. BOOL bResult = FALSE;
  469. XPtrLF<WCHAR> xszXlatName;
  470. PSECUR32_API pSecur32;
  471. XLastError xe;
  472. DWORD dwError = ERROR_SUCCESS;
  473. XPtrLF<WCHAR> xwszTargetDomain;
  474. DWORD dwUserPolicyMode = 0;
  475. DWORD dwLocFlags;
  476. if (!bMachine) {
  477. if (dwFlags & FLAG_LOOPBACK_MERGE ) {
  478. dwUserPolicyMode = 1;
  479. }
  480. else if (dwFlags & FLAG_LOOPBACK_REPLACE ) {
  481. dwUserPolicyMode = 2;
  482. }
  483. }
  484. dwLocFlags = GP_PLANMODE | (dwFlags & FLAG_ASSUME_COMP_WQLFILTER_TRUE) | (dwFlags & FLAG_ASSUME_USER_WQLFILTER_TRUE);
  485. //
  486. // Load secur32.dll
  487. //
  488. pSecur32 = LoadSecur32();
  489. if (!pSecur32) {
  490. xe = GetLastError();
  491. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Failed to load Secur32.")));
  492. return NULL;
  493. }
  494. if ( pwszAccount == NULL ) {
  495. if ( pwszNewSOM == NULL ) {
  496. //
  497. // When dummy user is specified then both SOM and security groups
  498. // must be specified.
  499. //
  500. xe = GetLastError();
  501. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Incorrect SOM or security specification for dummy target"),
  502. GetLastError()));
  503. goto Exit;
  504. }
  505. }
  506. if ( bMachine )
  507. dwFlags |= GP_MACHINE;
  508. dwFlags |= GP_PLANMODE; // mark the processing as planning mode processing
  509. pGpoInfo->dwFlags = dwFlags;
  510. //
  511. // caller can force slow link in planning mode
  512. //
  513. if ( dwFlags & FLAG_ASSUME_SLOW_LINK )
  514. {
  515. pGpoInfo->dwFlags |= GP_SLOW_LINK;
  516. }
  517. else
  518. {
  519. pGpoInfo->dwFlags &= ~GP_SLOW_LINK;
  520. }
  521. if ( pwszAccount ) {
  522. if ( !GetCategory( pwszDomain, pwszAccount, &pGpoInfo->lpDNName ) ) {
  523. xe = GetLastError();
  524. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo - getCategory failed with error - %d"), GetLastError()));
  525. goto Exit;
  526. }
  527. }
  528. //
  529. // TranslateName to SamCompatible so that the rest of the functions work correctly
  530. // for any of the various name formats
  531. //
  532. if ( pwszAccount ) {
  533. DWORD dwSize = MAX_PATH+1;
  534. xszXlatName = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*dwSize);
  535. if (!xszXlatName) {
  536. xe = GetLastError();
  537. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo - Couldn't allocate memory for Name...")));
  538. goto Exit;
  539. }
  540. if (!pSecur32->pfnTranslateName( pwszAccount,
  541. NameUnknown,
  542. NameSamCompatible,
  543. xszXlatName,
  544. &dwSize )) {
  545. BOOL bOk = FALSE;
  546. if (dwSize > (MAX_PATH+1)) {
  547. xszXlatName = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*dwSize);
  548. if (!xszXlatName) {
  549. xe = GetLastError();
  550. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo - Couldn't allocate memory for Name...")));
  551. goto Exit;
  552. }
  553. bOk = pSecur32->pfnTranslateName( pwszAccount,
  554. NameUnknown,
  555. NameSamCompatible,
  556. xszXlatName,
  557. &dwSize );
  558. }
  559. if (!bOk) {
  560. xe = GetLastError();
  561. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo - TranslateName failed with error %d"), GetLastError()));
  562. goto Exit;
  563. }
  564. }
  565. DebugMsg((DM_VERBOSE, TEXT("GenerateGpoInfo: RsopCreateToken for Account Name <%s>"), (LPWSTR)xszXlatName));
  566. }
  567. hr = RsopCreateToken( xszXlatName, psaSecGroups, &pGpoInfo->pRsopToken );
  568. if ( FAILED(hr) ) {
  569. xe = HRESULT_CODE(hr);
  570. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Failed to create Rsop token. Error - %d"), HRESULT_CODE(hr)));
  571. goto Exit;
  572. }
  573. dwError = GetDomain(pwszNewSOM ? pwszNewSOM : pGpoInfo->lpDNName, &xwszTargetDomain);
  574. if (dwError != ERROR_SUCCESS) {
  575. xe = dwError;
  576. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Failed to Get domain. Error - %d"), dwError));
  577. goto Exit;
  578. }
  579. //
  580. // Query for the GPO list based upon the mode
  581. //
  582. // 0 is normal
  583. // 1 is merge. Merge user list + machine list
  584. // 2 is replace. use machine list instead of user list
  585. //
  586. if (dwUserPolicyMode == 0) {
  587. DebugMsg((DM_VERBOSE, TEXT("GenerateGpoInfo: Calling GetGPOInfo for normal policy mode")));
  588. bResult = GetGPOInfo( dwLocFlags | ((pGpoInfo->dwFlags & GP_MACHINE) ? GPO_LIST_FLAG_MACHINE : 0),
  589. xwszTargetDomain,
  590. pwszNewSOM ? pwszNewSOM : pGpoInfo->lpDNName,
  591. NULL,
  592. &pGpoInfo->lpGPOList,
  593. &pGpoInfo->lpSOMList, &pGpoInfo->lpGpContainerList,
  594. pNetAPI32, FALSE, pGpoInfo->pRsopToken, pwszSite, pGpoFilter, pLocator );
  595. if ( !bResult ) {
  596. xe = GetLastError();
  597. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: GetGPOInfo failed.")));
  598. CEvents ev( TRUE, EVENT_GPO_QUERY_FAILED ); ev.Report();
  599. goto Exit;
  600. }
  601. } else if (dwUserPolicyMode == 2) {
  602. XPtrLF<TCHAR> xMachDNName;
  603. XPtrLF<TCHAR> xwszMachDomain;
  604. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Calling GetGPOInfo for replacement user policy mode")));
  605. if ( pwszMachAccount ) {
  606. if ( !GetCategory( pwszDomain, pwszMachAccount, &xMachDNName ) ) {
  607. xe = GetLastError();
  608. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo - getCategory failed with error - %d"), GetLastError()));
  609. goto Exit;
  610. }
  611. }
  612. dwError = GetDomain(pwszNewMachSOM ? pwszNewMachSOM : xMachDNName, &xwszMachDomain);
  613. if (dwError != ERROR_SUCCESS) {
  614. xe = dwError;
  615. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Failed to Get domain. Error - %d"), dwError));
  616. goto Exit;
  617. }
  618. bResult = GetGPOInfo( dwLocFlags | 0,
  619. xwszMachDomain,
  620. pwszNewMachSOM ? pwszNewMachSOM : xMachDNName,
  621. NULL,
  622. &pGpoInfo->lpGPOList,
  623. &pGpoInfo->lpLoopbackSOMList,
  624. &pGpoInfo->lpLoopbackGpContainerList,
  625. pNetAPI32, FALSE, pGpoInfo->pRsopToken, pwszSite, pGpoFilter, pLocator );
  626. if ( !bResult ) {
  627. xe = GetLastError();
  628. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: GetGPOInfo failed.")));
  629. CEvents ev( TRUE, EVENT_GPO_QUERY_FAILED ); ev.Report();
  630. goto Exit;
  631. }
  632. }
  633. else {
  634. XPtrLF<TCHAR> xMachDNName;
  635. XPtrLF<TCHAR> xwszMachDomain;
  636. PGROUP_POLICY_OBJECT lpGPO = NULL;
  637. PGROUP_POLICY_OBJECT lpGPOTemp;
  638. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Calling GetGPOInfo for merging user policy mode")));
  639. bResult = GetGPOInfo( dwLocFlags | ((pGpoInfo->dwFlags & GP_MACHINE) ? GPO_LIST_FLAG_MACHINE : 0),
  640. xwszTargetDomain,
  641. pwszNewSOM ? pwszNewSOM : pGpoInfo->lpDNName,
  642. NULL,
  643. &pGpoInfo->lpGPOList,
  644. &pGpoInfo->lpSOMList, &pGpoInfo->lpGpContainerList,
  645. pNetAPI32, FALSE, pGpoInfo->pRsopToken, pwszSite, pGpoFilter, pLocator );
  646. if ( !bResult ) {
  647. xe = GetLastError();
  648. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: GetGPOInfo failed.")));
  649. CEvents ev( TRUE, EVENT_GPO_QUERY_FAILED ); ev.Report();
  650. goto Exit;
  651. }
  652. if ( pwszMachAccount ) {
  653. if ( !GetCategory( pwszDomain, pwszMachAccount, &xMachDNName ) ) {
  654. xe = GetLastError();
  655. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo - getCategory failed with error - %d"), GetLastError()));
  656. goto Exit;
  657. }
  658. }
  659. dwError = GetDomain(pwszNewMachSOM ? pwszNewMachSOM : xMachDNName, &xwszMachDomain);
  660. if (dwError != ERROR_SUCCESS) {
  661. xe = dwError;
  662. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Failed to Get domain. Error - %d"), dwError));
  663. goto Exit;
  664. }
  665. bResult = GetGPOInfo( 0 | dwLocFlags,
  666. xwszMachDomain,
  667. pwszNewMachSOM ? pwszNewMachSOM : xMachDNName,
  668. NULL,
  669. &lpGPO,
  670. &pGpoInfo->lpLoopbackSOMList,
  671. &pGpoInfo->lpLoopbackGpContainerList,
  672. pNetAPI32, FALSE, pGpoInfo->pRsopToken, pwszSite, pGpoFilter, pLocator );
  673. if ( !bResult ) {
  674. xe = GetLastError();
  675. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: GetGPOInfo failed.")));
  676. CEvents ev( TRUE, EVENT_GPO_QUERY_FAILED ); ev.Report();
  677. goto Exit;
  678. }
  679. if (pGpoInfo->lpGPOList && lpGPO) {
  680. DebugMsg((DM_VERBOSE, TEXT("GenerateGpoInfo: Both user and machine lists are defined. Merging them together.")));
  681. //
  682. // Need to merge the lists together
  683. //
  684. lpGPOTemp = pGpoInfo->lpGPOList;
  685. while (lpGPOTemp->pNext) {
  686. lpGPOTemp = lpGPOTemp->pNext;
  687. }
  688. lpGPOTemp->pNext = lpGPO;
  689. } else if (!pGpoInfo->lpGPOList && lpGPO) {
  690. DebugMsg((DM_VERBOSE, TEXT("GenerateGpoInfo: Only machine list is defined.")));
  691. pGpoInfo->lpGPOList = lpGPO;
  692. } else {
  693. DebugMsg((DM_VERBOSE, TEXT("GenerateGpoInfo: Only user list is defined.")));
  694. }
  695. }
  696. if ( !ReadGPExtensions( pGpoInfo ) ) {
  697. xe = GetLastError();
  698. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: ReadGPExtensions failed.")));
  699. CEvents ev( TRUE, EVENT_READ_EXT_FAILED ); ev.Report();
  700. goto Exit;
  701. }
  702. if ( !CheckForSkippedExtensions( pGpoInfo, TRUE ) ) {
  703. xe = GetLastError();
  704. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Checking extensions for skipping failed")));
  705. goto Exit;
  706. }
  707. bResult = SetupGPOFilter( pGpoInfo );
  708. if ( !bResult ) {
  709. xe = GetLastError();
  710. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: SetupGPOFilter failed.")));
  711. CEvents ev(TRUE, EVENT_SETUP_GPOFILTER_FAILED); ev.Report();
  712. goto Exit;
  713. }
  714. Exit:
  715. return bResult;
  716. }
  717. //*************************************************************
  718. //
  719. // GetCategory()
  720. //
  721. // Purpose: Gets the fully qualified domain name
  722. //
  723. // Parameters: pwszDomain - Domain name
  724. // pwszAccount - User or machine account name
  725. // pwszDNName - Fully qualified domain name returned here
  726. //
  727. // Return: True if successful, False otherwise
  728. //
  729. //*************************************************************
  730. BOOL GetCategory( WCHAR *pwszDomain, WCHAR *pwszAccount, WCHAR **ppwszDNName )
  731. {
  732. PSECUR32_API pSecur32Api;
  733. BOOL bResult = FALSE;
  734. ULONG ulSize = 512;
  735. XLastError xe;
  736. *ppwszDNName = NULL;
  737. *ppwszDNName = (WCHAR *) LocalAlloc (LPTR, ulSize * sizeof(WCHAR) );
  738. if ( *ppwszDNName == NULL ) {
  739. xe = GetLastError();
  740. DebugMsg((DM_WARNING, TEXT("GetCategory: Memory allocation failed.")));
  741. goto Exit;
  742. }
  743. pSecur32Api = LoadSecur32();
  744. if (!pSecur32Api) {
  745. xe = GetLastError();
  746. DebugMsg((DM_WARNING, TEXT("GetCategory: Failed to load secur32 api.")));
  747. goto Exit;
  748. }
  749. bResult = pSecur32Api->pfnTranslateName( pwszAccount, NameUnknown, NameFullyQualifiedDN,
  750. *ppwszDNName, &ulSize );
  751. if ( !bResult && ulSize > 0 ) {
  752. LocalFree( *ppwszDNName );
  753. *ppwszDNName = (WCHAR *) LocalAlloc (LPTR, ulSize * sizeof(WCHAR) );
  754. if ( *ppwszDNName == NULL ) {
  755. xe = GetLastError();
  756. DebugMsg((DM_WARNING, TEXT("GetCategory: Memory allocation failed.")));
  757. goto Exit;
  758. }
  759. bResult = pSecur32Api->pfnTranslateName( pwszAccount, NameUnknown, NameFullyQualifiedDN,
  760. *ppwszDNName, &ulSize );
  761. if (!bResult) {
  762. xe = GetLastError();
  763. DebugMsg((DM_WARNING, TEXT("GetCategory: TranslateName failed with error %d."), GetLastError()));
  764. }
  765. }
  766. else {
  767. if (!bResult) {
  768. xe = GetLastError();
  769. DebugMsg((DM_WARNING, TEXT("GetCategory: TranslateName failed with error %d."), GetLastError()));
  770. }
  771. }
  772. Exit:
  773. if ( !bResult ) {
  774. LocalFree( *ppwszDNName );
  775. *ppwszDNName = NULL;
  776. }
  777. return bResult;
  778. }
  779. //*************************************************************
  780. //
  781. // ProcessMachAndUserGpoList()
  782. //
  783. // Purpose: Calls the various extensions to do the planning
  784. // mode logging
  785. //
  786. // Parameters: lpExtMach - Machine extension struct
  787. // lpExtUser - User extension struct
  788. // dwFlags - Processing flags
  789. // pwszSite - Site name
  790. // pwszNewComputerSOM - New computer scope of management
  791. // psaCompSecGroups - New computer security groups
  792. // pGpoInfoMach - Machine Gpo info
  793. // ... - Similarly for user account
  794. //
  795. // Return: True if successful, False otherwise
  796. //
  797. //*************************************************************
  798. DWORD ProcessMachAndUserGpoList( LPGPEXT lpExtMach, LPGPEXT lpExtUser, DWORD dwFlags, WCHAR *pwszSite,
  799. WCHAR *pwszMach, WCHAR *pwszNewComputerSOM, SAFEARRAY *psaComputerSecurityGroups, LPGPOINFO pGpoInfoMach,
  800. WCHAR *pwszUser, WCHAR *pwszNewUserSOM, SAFEARRAY *psaUserSecurityGroups, LPGPOINFO pGpoInfoUser )
  801. {
  802. BOOL bAbort = FALSE;
  803. DWORD dwResult;
  804. RSOP_TARGET computerTarget, userTarget;
  805. PRSOP_TARGET pComputerTarget = NULL;
  806. PRSOP_TARGET pUserTarget = NULL;
  807. BOOL bPlanningSupported = TRUE;
  808. LPGPEXT lpExt;
  809. lpExt = (lpExtMach != NULL) ? lpExtMach : lpExtUser;
  810. if (!lpExt) {
  811. DebugMsg((DM_WARNING, TEXT("ProcessMachAndUserGpoList: Both user and computer exts are null, returning.")));
  812. return TRUE;
  813. }
  814. bPlanningSupported = lpExt->bRegistryExt || (lpExt->lpRsopFunctionName ? TRUE : FALSE);
  815. if ( lpExtMach && !lpExtMach->bSkipped && pGpoInfoMach->lpGPOList ) {
  816. //
  817. // Computer target is non-null
  818. //
  819. pComputerTarget = &computerTarget;
  820. pComputerTarget->pwszAccountName = pwszMach;
  821. pComputerTarget->pwszNewSOM = pwszNewComputerSOM;
  822. pComputerTarget->psaSecurityGroups = psaComputerSecurityGroups;
  823. pComputerTarget->pRsopToken = pGpoInfoMach->pRsopToken;
  824. pComputerTarget->pGPOList = pGpoInfoMach->lpGPOList;
  825. pComputerTarget->pWbemServices = pGpoInfoMach->pWbemServices;
  826. if (pGpoInfoMach->bRsopLogging) {
  827. pGpoInfoMach->bRsopLogging = LogExtSessionStatus(pGpoInfoMach->pWbemServices, lpExtMach,
  828. bPlanningSupported);
  829. if (!pGpoInfoMach->bRsopLogging) {
  830. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Error when logging user Session data.")));
  831. }
  832. }
  833. }
  834. if ( lpExtUser && !lpExtUser->bSkipped && pGpoInfoUser->lpGPOList ) {
  835. //
  836. // User target is non-null
  837. //
  838. pUserTarget = &userTarget;
  839. pUserTarget->pwszAccountName = pwszUser;
  840. pUserTarget->pwszNewSOM = pwszNewUserSOM;
  841. pUserTarget->psaSecurityGroups = psaUserSecurityGroups;
  842. pUserTarget->pRsopToken = pGpoInfoUser->pRsopToken;
  843. pUserTarget->pGPOList = pGpoInfoUser->lpGPOList;
  844. pUserTarget->pWbemServices = pGpoInfoUser->pWbemServices;
  845. if (pGpoInfoUser->bRsopLogging) {
  846. pGpoInfoUser->bRsopLogging = LogExtSessionStatus(pGpoInfoUser->pWbemServices, lpExtUser,
  847. bPlanningSupported);
  848. if (!pGpoInfoUser->bRsopLogging) {
  849. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Error when logging user Session data.")));
  850. }
  851. }
  852. }
  853. if ( pComputerTarget == NULL && pUserTarget == NULL ) {
  854. DebugMsg((DM_WARNING, TEXT("ProcessMachAndUserGpoList: Both user and computer targets are null, returning.")));
  855. return TRUE;
  856. }
  857. if ( lpExt->bRegistryExt ) {
  858. //
  859. // Registry pseudo extension
  860. //
  861. dwResult = GenerateRegistryPolicy( dwFlags,
  862. &bAbort,
  863. pwszSite,
  864. pComputerTarget,
  865. pUserTarget );
  866. } else {
  867. if ( LoadGPExtension( lpExt, TRUE ) ) {
  868. dwResult = lpExt->pRsopEntryPoint( dwFlags,
  869. &bAbort,
  870. pwszSite,
  871. pComputerTarget,
  872. pUserTarget );
  873. }
  874. else {
  875. dwResult = GetLastError();
  876. }
  877. }
  878. if ( lpExtUser && !lpExtUser->bSkipped && pGpoInfoUser->bRsopLogging) {
  879. if ( !bPlanningSupported )
  880. UpdateExtSessionStatus(pGpoInfoUser->pWbemServices, lpExtUser->lpKeyName, TRUE, ERROR_SUCCESS);
  881. else if (dwResult != ERROR_SUCCESS)
  882. UpdateExtSessionStatus(pGpoInfoUser->pWbemServices, lpExtUser->lpKeyName, TRUE, dwResult);
  883. else
  884. UpdateExtSessionStatus(pGpoInfoUser->pWbemServices, lpExtUser->lpKeyName, FALSE, dwResult);
  885. }
  886. if ( lpExtMach && !lpExtMach->bSkipped && pGpoInfoMach->bRsopLogging) {
  887. if ( !bPlanningSupported )
  888. UpdateExtSessionStatus(pGpoInfoMach->pWbemServices, lpExtMach->lpKeyName, TRUE, ERROR_SUCCESS);
  889. else if (dwResult != ERROR_SUCCESS)
  890. UpdateExtSessionStatus(pGpoInfoMach->pWbemServices, lpExtMach->lpKeyName, TRUE, dwResult);
  891. else
  892. UpdateExtSessionStatus(pGpoInfoMach->pWbemServices, lpExtMach->lpKeyName, FALSE, dwResult);
  893. }
  894. return dwResult;
  895. }
  896. //*********************************************************************
  897. // * Planning mode registry stuff
  898. //*********************************************************************
  899. //*************************************************************
  900. //
  901. // ProcessRegistryFiles()
  902. //
  903. // Purpose: Called from GenerateRegsitryPolicy to process registry data from
  904. // the registry files associated with a policy target.
  905. //
  906. // Parameters:
  907. // pTarget - Policy for which registry policy is to be processed.
  908. // pHashTable - Hash table to keep registry policy information.
  909. //
  910. // Return: On success, TRUE. Otherwise, FALSE.
  911. //
  912. //*************************************************************
  913. BOOL ProcessRegistryFiles(PRSOP_TARGET pTarget, REGHASHTABLE *pHashTable)
  914. {
  915. PGROUP_POLICY_OBJECT lpGPO;
  916. TCHAR szRegistry[MAX_PATH];
  917. LPTSTR lpEnd;
  918. HRESULT hr;
  919. XLastError xe;
  920. //
  921. // Check parameters
  922. //
  923. DmAssert(pHashTable);
  924. if(!pHashTable) {
  925. DebugMsg((DM_WARNING, TEXT("ProcessRegistryFiles: Invalid parameter.")));
  926. return FALSE;
  927. }
  928. //
  929. // Spin through GPOs in the list.
  930. //
  931. lpGPO = pTarget->pGPOList;
  932. while ( lpGPO ) {
  933. //
  934. // Build the path to Registry.pol
  935. //
  936. DmAssert( lstrlen(lpGPO->lpFileSysPath) + lstrlen(c_szRegistryPol) + 1 < MAX_PATH );
  937. if(lstrlen(lpGPO->lpFileSysPath) + lstrlen(c_szRegistryPol) + 1 >= MAX_PATH) {
  938. DebugMsg((DM_WARNING, TEXT("ProcessRegistryFiles: Length of path to registry.pol exceeded MAX_PATH.")));
  939. return FALSE;
  940. }
  941. hr = StringCchCopy (szRegistry, ARRAYSIZE(szRegistry), lpGPO->lpFileSysPath);
  942. if (FAILED(hr)) {
  943. xe = HRESULT_CODE(hr);
  944. return FALSE;
  945. }
  946. lpEnd = CheckSlash (szRegistry);
  947. hr = StringCchCopy (lpEnd, ARRAYSIZE(szRegistry) - (lpEnd - szRegistry), c_szRegistryPol);
  948. if (FAILED(hr)) {
  949. xe = HRESULT_CODE(hr);
  950. return FALSE;
  951. }
  952. //
  953. // Process registry data for this particular file.
  954. //
  955. if (!ParseRegistryFile (NULL, szRegistry, (PFNREGFILECALLBACK)ProcessRegistryValue, NULL,
  956. lpGPO->lpDSPath, lpGPO->lpLink,pHashTable, TRUE)) {
  957. DebugMsg((DM_WARNING, TEXT("ProcessRegistryFiles: ProcessRegistryFile failed.")));
  958. return FALSE;
  959. }
  960. lpGPO = lpGPO->pNext;
  961. }
  962. return TRUE;
  963. }
  964. //*************************************************************
  965. //
  966. // ProcessAdmData()
  967. //
  968. // Purpose: Called from GenerateRegistryPolicy in order to process Admin templates
  969. // data associated with a registry policy target.
  970. //
  971. // Parameters: pTarget - Target for which data is to be processed
  972. // bUser - Is this for user or machine policy ?
  973. //
  974. // Return: On success, TRUE. Otherwise, FALSE.
  975. //
  976. //*************************************************************
  977. BOOL ProcessAdmData( PRSOP_TARGET pTarget, BOOL bUser )
  978. {
  979. PGROUP_POLICY_OBJECT lpGPO;
  980. WIN32_FIND_DATA findData;
  981. ADMFILEINFO *pAdmFileCache = 0;
  982. TCHAR szRegistry[MAX_PATH];
  983. LPTSTR lpEnd;
  984. HANDLE hFindFile;
  985. WIN32_FILE_ATTRIBUTE_DATA attrData;
  986. DWORD dwFilePathSize;
  987. DWORD dwSize;
  988. WCHAR *pwszEnd;
  989. WCHAR *pwszFile;
  990. HRESULT hr;
  991. //
  992. // Check parameters
  993. //
  994. if(pTarget == NULL ) {
  995. DebugMsg((DM_WARNING, TEXT("ProcessAdmData: Invalid paramter.")));
  996. return FALSE;
  997. }
  998. lpGPO = pTarget->pGPOList;
  999. while(lpGPO) {
  1000. //
  1001. // Log Adm data
  1002. //
  1003. dwFilePathSize = lstrlen( lpGPO->lpFileSysPath );
  1004. dwSize = dwFilePathSize + MAX_PATH;
  1005. pwszFile = (WCHAR *) LocalAlloc( LPTR, dwSize * sizeof(WCHAR) );
  1006. if ( pwszFile == 0 ) {
  1007. DebugMsg((DM_WARNING, TEXT("ProcessAdmData: Failed to allocate memory.")));
  1008. FreeAdmFileCache( pAdmFileCache );
  1009. return FALSE;
  1010. }
  1011. hr = StringCchCopy( pwszFile, dwSize, lpGPO->lpFileSysPath );
  1012. ASSERT(SUCCEEDED(hr));
  1013. //
  1014. // Strip off trailing 'machine' or 'user'
  1015. //
  1016. pwszEnd = pwszFile + lstrlen( pwszFile );
  1017. if ( !bUser )
  1018. pwszEnd -= 7; // length of "machine"
  1019. else
  1020. pwszEnd -= 4; // length of "user"
  1021. hr = StringCchCopy( pwszEnd, dwSize - (pwszEnd - pwszFile), L"Adm\\*.adm");
  1022. ASSERT(SUCCEEDED(hr));
  1023. //
  1024. // Remember end point so that the actual Adm filename can be
  1025. // easily concatenated.
  1026. //
  1027. pwszEnd = pwszEnd + lstrlen( L"Adm\\" );
  1028. //
  1029. // Enumerate all Adm files
  1030. //
  1031. hFindFile = FindFirstFile( pwszFile, &findData);
  1032. if ( hFindFile != INVALID_HANDLE_VALUE )
  1033. {
  1034. do
  1035. {
  1036. if ( !(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
  1037. {
  1038. DmAssert( dwFilePathSize + lstrlen(findData.cFileName) + lstrlen( L"\\Adm\\" ) < dwSize );
  1039. hr = StringCchCopy( pwszEnd, dwSize - (pwszEnd - pwszFile), findData.cFileName);
  1040. ASSERT(SUCCEEDED(hr));
  1041. ZeroMemory (&attrData, sizeof(attrData));
  1042. if ( GetFileAttributesEx (pwszFile, GetFileExInfoStandard, &attrData ) != 0 ) {
  1043. if ( !AddAdmFile( pwszFile, lpGPO->lpDSPath,
  1044. &attrData.ftLastWriteTime, NULL, &pAdmFileCache ) ) {
  1045. DebugMsg((DM_WARNING, TEXT("ProcessAdmData: NewAdmData failed.")));
  1046. }
  1047. }
  1048. } // if findData & file_attr_dir
  1049. } while ( FindNextFile(hFindFile, &findData) );// do
  1050. FindClose(hFindFile);
  1051. } // if hfindfile
  1052. LocalFree( pwszFile );
  1053. lpGPO = lpGPO->pNext;
  1054. }
  1055. if ( ! LogAdmRsopData( pAdmFileCache, pTarget->pWbemServices ) ) {
  1056. DebugMsg((DM_WARNING, TEXT("ProcessAdmData: Error when logging Adm Rsop data. Continuing.")));
  1057. }
  1058. FreeAdmFileCache( pAdmFileCache );
  1059. return TRUE;
  1060. }
  1061. //*************************************************************
  1062. //
  1063. // GenerateRegistryPolicy()
  1064. //
  1065. // Purpose: Implementation of Planning mode regsitry pseudo-extension
  1066. //
  1067. // Parameters: dwFlags - Flags
  1068. // pbAbort - Abort processing
  1069. // pwszSite - Site of target
  1070. // pComputerTarget - Computer target specification
  1071. // pUserTarget - User target specification
  1072. //
  1073. // Return: On success, S_OK. Otherwise, E_FAIL.
  1074. //
  1075. //*************************************************************
  1076. DWORD GenerateRegistryPolicy( DWORD dwFlags,
  1077. BOOL *pbAbort,
  1078. WCHAR *pwszSite,
  1079. PRSOP_TARGET pComputerTarget,
  1080. PRSOP_TARGET pUserTarget )
  1081. {
  1082. REGHASHTABLE *pHashTable = NULL;
  1083. BOOL bUser;
  1084. if(pComputerTarget && pComputerTarget->pGPOList) {
  1085. //
  1086. // Setup computer hash table
  1087. //
  1088. pHashTable = AllocHashTable();
  1089. if ( pHashTable == NULL ) {
  1090. DebugMsg((DM_WARNING, TEXT("GenerateRegistryPolicy: AllocHashTable failed.")));
  1091. return E_FAIL;
  1092. }
  1093. //
  1094. // Process computer GPO list
  1095. //
  1096. if(!ProcessRegistryFiles(pComputerTarget, pHashTable)) {
  1097. DebugMsg((DM_WARNING, TEXT("GenerateRegistryPolicy: ProcessRegistryFiles failed.")));
  1098. FreeHashTable( pHashTable );
  1099. return E_FAIL;
  1100. }
  1101. //
  1102. // Log computer registry data to Cimom database
  1103. //
  1104. if ( ! LogRegistryRsopData( GP_MACHINE, pHashTable, pComputerTarget->pWbemServices ) ) {
  1105. DebugMsg((DM_WARNING, TEXT("GenerateRegistryPolicy: LogRegistryRsopData failed.")));
  1106. FreeHashTable( pHashTable );
  1107. return E_FAIL;
  1108. }
  1109. FreeHashTable( pHashTable );
  1110. pHashTable = NULL;
  1111. //
  1112. // Process ADM data
  1113. //
  1114. bUser = FALSE;
  1115. if (pComputerTarget && !ProcessAdmData( pComputerTarget, bUser ) ) {
  1116. DebugMsg((DM_WARNING, TEXT("GenerateRegistryPolicy: ProcessAdmData failed.")));
  1117. return E_FAIL;
  1118. }
  1119. }
  1120. //
  1121. // Process user GPO list
  1122. //
  1123. if(pUserTarget && pUserTarget->pGPOList) {
  1124. //
  1125. // Setup user hash table
  1126. //
  1127. pHashTable = AllocHashTable();
  1128. if ( pHashTable == NULL ) {
  1129. DebugMsg((DM_WARNING, TEXT("GenerateRegistryPolicy: AllocHashTable failed.")));
  1130. return E_FAIL;
  1131. }
  1132. if(!ProcessRegistryFiles(pUserTarget, pHashTable)) {
  1133. DebugMsg((DM_WARNING, TEXT("GenerateRegistryPolicy: ProcessRegistryFiles failed.")));
  1134. FreeHashTable( pHashTable );
  1135. return E_FAIL;
  1136. }
  1137. //
  1138. // Log user registry data to Cimom database
  1139. //
  1140. if ( ! LogRegistryRsopData( 0, pHashTable, pUserTarget->pWbemServices ) ) {
  1141. DebugMsg((DM_WARNING, TEXT("GenerateRegistryPolicy: LogRegistryRsopData failed.")));
  1142. FreeHashTable( pHashTable );
  1143. return E_FAIL;
  1144. }
  1145. FreeHashTable( pHashTable );
  1146. pHashTable = NULL;
  1147. //
  1148. // Process ADM data
  1149. //
  1150. bUser = TRUE;
  1151. if (pUserTarget && !ProcessAdmData( pUserTarget, bUser ) ) {
  1152. DebugMsg((DM_WARNING, TEXT("GenerateRegistryPolicy: ProcessAdmData failed.")));
  1153. return E_FAIL;
  1154. }
  1155. }
  1156. return S_OK;
  1157. }
  1158. //*************************************************************
  1159. //
  1160. // CheckOUAccess()
  1161. //
  1162. // Purpose: Determines if the user / machine has read access to
  1163. // the OU.
  1164. //
  1165. // Parameters: pld - LDAP connection
  1166. // pLDAP - LDAP function table pointer
  1167. // pMessage - LDAP message
  1168. // pRsopToken - RSOP token of the user or machine
  1169. // pSD - Security descriptor returned here
  1170. // pcbSDLen - Length of security descriptor returned here
  1171. // pbAccessGranted - Receives the final yes / no status
  1172. //
  1173. // Return: TRUE if successful
  1174. // FALSE if an error occurs.
  1175. //
  1176. //*************************************************************
  1177. BOOL CheckOUAccess( PLDAP_API pLDAP,
  1178. PLDAP pld,
  1179. PLDAPMessage pMessage,
  1180. PRSOPTOKEN pRsopToken,
  1181. BOOL *pbAccessGranted )
  1182. {
  1183. BOOL bResult = FALSE;
  1184. TCHAR szSDProperty[] = TEXT("nTSecurityDescriptor");
  1185. PWSTR *ppwszValues;
  1186. *pbAccessGranted = FALSE;
  1187. //
  1188. // Get the security descriptor value
  1189. //
  1190. ppwszValues = pLDAP->pfnldap_get_values( pld, pMessage, szSDProperty );
  1191. if (!ppwszValues)
  1192. {
  1193. if (pld->ld_errno == LDAP_NO_SUCH_ATTRIBUTE)
  1194. {
  1195. DebugMsg((DM_VERBOSE, TEXT("CheckOUAccess: Object can not be accessed.")));
  1196. bResult = TRUE;
  1197. }
  1198. else
  1199. {
  1200. DebugMsg((DM_WARNING, TEXT("CheckOUAccess: ldap_get_values failed with 0x%x"),
  1201. pld->ld_errno));
  1202. }
  1203. }
  1204. else
  1205. {
  1206. PLDAP_BERVAL *pSize;
  1207. //
  1208. // Get the length of the security descriptor
  1209. //
  1210. pSize = pLDAP->pfnldap_get_values_len(pld, pMessage, szSDProperty);
  1211. if (!pSize)
  1212. {
  1213. DebugMsg((DM_WARNING, TEXT("CheckOUAccess: ldap_get_values_len failed with 0x%x"),
  1214. pld->ld_errno));
  1215. }
  1216. else
  1217. {
  1218. //
  1219. // Allocate the memory for the security descriptor
  1220. //
  1221. PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, (*pSize)->bv_len);
  1222. if ( pSD == NULL )
  1223. {
  1224. DebugMsg((DM_WARNING, TEXT("CheckOUAccess: Failed to allocate memory for SD with %d"),
  1225. GetLastError()));
  1226. }
  1227. else
  1228. {
  1229. //
  1230. // OU {bf967aa8-0de6-11d0-a285-00aa003049e2}
  1231. //
  1232. GUID OrganizationalUnit = { 0xbf967aa5, 0x0de6, 0x11d0, 0xa2, 0x85, 0x00, 0xaa, 0x00, 0x30, 0x49, 0xe2 };
  1233. //
  1234. // gPOptions {f30e3bbf-9ff0-11d1-b603-0000f80367c1}
  1235. //
  1236. GUID gPOptionsGuid = { 0xf30e3bbf, 0x9ff0, 0x11d1, 0xb6, 0x03, 0x00, 0x00, 0xf8, 0x03, 0x67, 0xc1 };
  1237. //
  1238. // gPLink {f30e3bbe-9ff0-11d1-b603-0000f80367c1}
  1239. //
  1240. GUID gPLinkGuid = { 0xf30e3bbe, 0x9ff0, 0x11d1, 0xb6, 0x03, 0x00, 0x00, 0xf8, 0x03, 0x67, 0xc1 };
  1241. OBJECT_TYPE_LIST ObjType[] = { { ACCESS_OBJECT_GUID, 0, &OrganizationalUnit },
  1242. { ACCESS_PROPERTY_SET_GUID, 0, &gPLinkGuid },
  1243. { ACCESS_PROPERTY_SET_GUID, 0, &gPOptionsGuid } };
  1244. HRESULT hr;
  1245. PRIVILEGE_SET PrivSet;
  1246. DWORD PrivSetLength = sizeof(PRIVILEGE_SET);
  1247. DWORD dwGrantedAccess;
  1248. BOOL bAccessStatus = TRUE;
  1249. GENERIC_MAPPING DS_GENERIC_MAPPING = { DS_GENERIC_READ,
  1250. DS_GENERIC_WRITE,
  1251. DS_GENERIC_EXECUTE,
  1252. DS_GENERIC_ALL };
  1253. //
  1254. // Copy the security descriptor
  1255. //
  1256. CopyMemory( pSD, (PBYTE)(*pSize)->bv_val, (*pSize)->bv_len);
  1257. //
  1258. // Now we use RsopAccessCheckByType to determine if the user / machine
  1259. // should have this GPO applied to them
  1260. //
  1261. hr = RsopAccessCheckByType(pSD,
  1262. 0,
  1263. pRsopToken,
  1264. ACTRL_DS_READ_PROP,
  1265. ObjType,
  1266. ARRAYSIZE(ObjType),
  1267. &DS_GENERIC_MAPPING,
  1268. &PrivSet,
  1269. &PrivSetLength,
  1270. &dwGrantedAccess,
  1271. &bAccessStatus );
  1272. if ( FAILED( hr ) )
  1273. {
  1274. DebugMsg((DM_WARNING, TEXT("CheckOUAccess: RsopAccessCheckByType failed with %d"), GetLastError()));
  1275. }
  1276. else
  1277. {
  1278. *pbAccessGranted = bAccessStatus;
  1279. bResult = TRUE;
  1280. }
  1281. LocalFree( pSD );
  1282. }
  1283. pLDAP->pfnldap_value_free_len(pSize);
  1284. }
  1285. pLDAP->pfnldap_value_free(ppwszValues);
  1286. }
  1287. return bResult;
  1288. }