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.

846 lines
25 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: setup.cxx
  7. //
  8. // Contents: Task Scheduler setup program
  9. //
  10. // Classes: None.
  11. //
  12. // Functions:
  13. //
  14. // History: 04-Apr-96 MarkBl Created
  15. // 23-Sep-96 AnirudhS Added SetTaskFolderSecurity, etc.
  16. // 30-Sep-96 AnirudhS Added /firstlogon and /logon options
  17. // 15-Nov-96 AnirudhS Conditionally enable the service on NT too
  18. // 01-09-97 DavidMun Add sysagent.exe path value under
  19. // app paths, backup sysagent.exe
  20. // 04-14-97 DavidMun Add DoMemphisSetup
  21. // 03-03-01 JBenton Prefix BUG 333200 use of uninit memory
  22. // 03-10-01 JBenton BUG 142333 tighten Tasks folder security
  23. // October 01 Maxa Updated security on Tasks folder in preparation for addition of auditing.
  24. //
  25. //-----------------------------------------------------------------------------
  26. #include <windows.h>
  27. #include <tchar.h>
  28. #include <sddl.h>
  29. #include <StrSafe.h>
  30. #include "security.hxx"
  31. #include "setupids.h"
  32. #define ARRAY_LEN(a) (sizeof(a)/sizeof((a)[0]))
  33. #define ARG_DELIMITERS TEXT(" \t")
  34. #define MINUTES_BEFORE_IDLE_DEFAULT 15
  35. #define MAX_LOG_SIZE_DEFAULT (0x20)
  36. //
  37. // Note that the svchost registry keys to run schedule service as a part
  38. // of netsvcs is set in hivesft.inx file.
  39. //
  40. #define SCHED_SETUP_SWITCH TEXT("/setup")
  41. #define SCHED_SERVICE_EXE_PATH TEXT("%SystemRoot%\\System32\\svchost.exe -k netsvcs")
  42. #define SCHED_SERVICE_DLL TEXT("MSTask.dll")
  43. #define SCHED_SERVICE_NAME TEXT("Schedule")
  44. #define SCHED_SERVICE_GROUP TEXT("SchedulerGroup")
  45. #define MINUTESBEFOREIDLE TEXT("MinutesBeforeIdle")
  46. #define MAXLOGSIZEKB TEXT("MaxLogSizeKB")
  47. #define TASKSFOLDER TEXT("TasksFolder")
  48. #define FIRSTBOOT TEXT("FirstBoot")
  49. #define SM_SA_KEY TEXT("Software\\Microsoft\\SchedulingAgent")
  50. //
  51. // Entry points from mstask.dll
  52. // Note they are used with GetProcAddress, which always wants an ANSI string.
  53. //
  54. #define CONVERT_AT_TASKS_API "ConvertAtJobsToTasks"
  55. //
  56. // Function pointer types used when loading above functions from mstask.dll
  57. //
  58. typedef HRESULT (__stdcall *PSTDAPI)(void);
  59. typedef BOOL (__stdcall *PBOOLAPI)(void);
  60. typedef VOID (__stdcall *PVOIDAPI)(void);
  61. typedef struct _MYSIDINFO {
  62. PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority;
  63. DWORD dwSubAuthority;
  64. DWORD dwSubSubAuthority;
  65. PSID pSid;
  66. } MYSIDINFO;
  67. DWORD SetTaskFolderSecurity(LPCWSTR pwszFolderPath);
  68. DWORD AllocateAndInitializeDomainSid(
  69. PSID pDomainSid,
  70. MYSIDINFO * pDomainSidInfo);
  71. void DoSetup(void);
  72. void ErrorDialog(UINT ErrorFmtStringID, TCHAR * szRoutine, DWORD ErrorCode);
  73. HINSTANCE ghInstance = NULL;
  74. //+----------------------------------------------------------------------------
  75. //
  76. // Function: WinMainCRTStartup
  77. //
  78. // Synopsis: entry point
  79. //
  80. //-----------------------------------------------------------------------------
  81. void _cdecl
  82. main(int argc, char ** argv)
  83. {
  84. //
  85. // Skip EXE name and find first parameter, if any
  86. //
  87. LPTSTR ptszStart;
  88. LPTSTR szArg1 = _tcstok(ptszStart = GetCommandLine(), ARG_DELIMITERS);
  89. szArg1 = _tcstok(NULL, ARG_DELIMITERS);
  90. //
  91. // Switch based on the first parameter
  92. //
  93. if (szArg1 == NULL)
  94. {
  95. ; // Do nothing
  96. }
  97. else if (lstrcmpi(szArg1, SCHED_SETUP_SWITCH) == 0)
  98. {
  99. DoSetup();
  100. }
  101. }
  102. //+----------------------------------------------------------------------------
  103. //
  104. // Function: DoSetup
  105. //
  106. // Synopsis: Performs the normal setup procedure
  107. //
  108. //-----------------------------------------------------------------------------
  109. void
  110. DoSetup(void)
  111. {
  112. #define SCHED_SERVICE_DEPENDENCY L"RpcSs\0"
  113. #define SCC_AT_SVC_KEY L"System\\CurrentControlSet\\Services\\Schedule"
  114. #define TASKS_FOLDER_DEFAULT L"%SystemRoot%\\Tasks"
  115. TCHAR szTasksFolder[MAX_PATH + 1] = TEXT("");
  116. TCHAR tszDisplayName[50]; // "Task Scheduler"
  117. DWORD dwTmp;
  118. HKEY hKey;
  119. //
  120. // Disable hard-error popups.
  121. //
  122. SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  123. ghInstance = GetModuleHandle(NULL);
  124. //
  125. // Load the service display name.
  126. //
  127. int cch = LoadString(ghInstance, IDS_SERVICE_DISPLAY_NAME, tszDisplayName,
  128. ARRAY_LEN(tszDisplayName));
  129. if (!(0 < cch && cch < ARRAY_LEN(tszDisplayName) - 1))
  130. {
  131. ErrorDialog(IDS_INSTALL_FAILURE,
  132. TEXT("LoadString"),
  133. GetLastError());
  134. return;
  135. }
  136. //
  137. // Create/open the Scheduling Agent key in Software\Microsoft.
  138. //
  139. LONG lErr = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  140. SM_SA_KEY,
  141. 0,
  142. NULL,
  143. REG_OPTION_NON_VOLATILE,
  144. KEY_ALL_ACCESS,
  145. NULL,
  146. &hKey,
  147. &dwTmp);
  148. if (ERROR_SUCCESS != lErr)
  149. {
  150. ErrorDialog(IDS_INSTALL_FAILURE, TEXT("RegCreateKeyEx"), lErr);
  151. return;
  152. }
  153. // Creator/Owner, System, Builtin Admins: Full control,
  154. // Authenticated users: generic read
  155. WCHAR pwszSDDL[] = L"D:P(A;OICIIO;FA;;;CO)(A;OICI;FA;;;BA)(A;OICI;FA;;;SY)(A;OICI;GR;;;AU)";
  156. PSECURITY_DESCRIPTOR pSD = NULL;
  157. if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(pwszSDDL, SDDL_REVISION_1, &pSD, NULL))
  158. {
  159. lErr = (GetLastError());
  160. ErrorDialog(IDS_INSTALL_FAILURE, TEXT("ConvertStringSecurityDescriptorToSecurityDescriptorW"), lErr);
  161. RegCloseKey(hKey);
  162. return;
  163. }
  164. lErr = RegSetKeySecurity(hKey, DACL_SECURITY_INFORMATION, pSD);
  165. LocalFree(pSD);
  166. if (ERROR_SUCCESS != lErr)
  167. {
  168. ErrorDialog(IDS_INSTALL_FAILURE, TEXT("RegSetKeySecurity"), lErr);
  169. RegCloseKey(hKey);
  170. return;
  171. }
  172. // Set MinutesBeforeIdle to a default value of 15 mins.
  173. //
  174. dwTmp = MINUTES_BEFORE_IDLE_DEFAULT;
  175. lErr = RegSetValueEx(hKey,
  176. MINUTESBEFOREIDLE,
  177. 0,
  178. REG_DWORD,
  179. (CONST BYTE *)&dwTmp,
  180. sizeof(dwTmp));
  181. if (ERROR_SUCCESS != lErr)
  182. {
  183. ErrorDialog(IDS_INSTALL_FAILURE, TEXT("RegSetValueEx"), lErr);
  184. RegCloseKey(hKey);
  185. return;
  186. }
  187. // Set MaxLogSizeKB to 32K or 0x7FFF.
  188. //
  189. dwTmp = MAX_LOG_SIZE_DEFAULT;
  190. lErr = RegSetValueEx(hKey,
  191. MAXLOGSIZEKB,
  192. 0,
  193. REG_DWORD,
  194. (CONST BYTE *)&dwTmp,
  195. sizeof(dwTmp));
  196. if (ERROR_SUCCESS != lErr)
  197. {
  198. ErrorDialog(IDS_INSTALL_FAILURE, TEXT("RegSetValueEx"), lErr);
  199. RegCloseKey(hKey);
  200. return;
  201. }
  202. // Read the tasks folder location. The .INF should've set this.
  203. // If not, default.
  204. //
  205. dwTmp = MAX_PATH * sizeof(TCHAR);
  206. if (RegQueryValueEx(hKey,
  207. TASKSFOLDER,
  208. NULL,
  209. NULL,
  210. (LPBYTE)szTasksFolder,
  211. &dwTmp) != ERROR_SUCCESS ||
  212. szTasksFolder[0] == TEXT('\0'))
  213. {
  214. StringCchCopy(szTasksFolder, MAX_PATH + 1, TASKS_FOLDER_DEFAULT);
  215. }
  216. // Set FirstBoot to non-zero.
  217. //
  218. dwTmp = 1;
  219. lErr = RegSetValueEx(hKey,
  220. FIRSTBOOT,
  221. 0,
  222. REG_DWORD,
  223. (CONST BYTE *)&dwTmp,
  224. sizeof(dwTmp));
  225. RegCloseKey(hKey);
  226. if (ERROR_SUCCESS != lErr)
  227. {
  228. ErrorDialog(IDS_INSTALL_FAILURE, TEXT("RegSetValueEx"), lErr);
  229. return;
  230. }
  231. //
  232. // Set the right permissions on the job folder.
  233. // The default permissions allow anyone to delete any job, which we
  234. // don't want.
  235. //
  236. {
  237. TCHAR szTaskFolderPath[MAX_PATH + 1];
  238. DWORD cch = ExpandEnvironmentStrings(szTasksFolder,
  239. szTaskFolderPath,
  240. ARRAY_LEN(szTaskFolderPath));
  241. if (cch == 0 || cch > ARRAY_LEN(szTaskFolderPath))
  242. {
  243. //
  244. // The job folder path is too long.
  245. //
  246. ErrorDialog(IDS_INSTALL_FAILURE,
  247. TEXT("ExpandEnvironmentStrings"),
  248. cch ? ERROR_BUFFER_OVERFLOW : GetLastError());
  249. return;
  250. }
  251. DWORD dwError = SetTaskFolderSecurity(szTaskFolderPath);
  252. if (dwError != ERROR_SUCCESS)
  253. {
  254. ErrorDialog(IDS_INSTALL_FAILURE,
  255. TEXT("SetTaskFolderSecurity"),
  256. dwError);
  257. return;
  258. }
  259. }
  260. HINSTANCE hinstMSTask = LoadLibrary(SCHED_SERVICE_DLL);
  261. if (!hinstMSTask)
  262. {
  263. ErrorDialog(IDS_INSTALL_FAILURE,
  264. SCHED_SERVICE_DLL,
  265. GetLastError());
  266. return;
  267. }
  268. PVOIDAPI pfnConvertLegacyJobsToTasks = (PVOIDAPI)
  269. GetProcAddress(hinstMSTask, CONVERT_AT_TASKS_API);
  270. if (!pfnConvertLegacyJobsToTasks)
  271. {
  272. ErrorDialog(IDS_INSTALL_FAILURE,
  273. TEXT("GetProcAddress"),
  274. GetLastError());
  275. return;
  276. }
  277. pfnConvertLegacyJobsToTasks();
  278. //
  279. // Install the Win32 service.
  280. //
  281. SC_HANDLE hSCMgr = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
  282. if (hSCMgr == NULL)
  283. {
  284. //
  285. // Yow, we're hosed.
  286. //
  287. ErrorDialog(IDS_INSTALL_FAILURE,
  288. TEXT("OpenSCManager"),
  289. GetLastError());
  290. return;
  291. }
  292. //
  293. // Is the service already installed? If so, change its parameters;
  294. // otherwise, create it.
  295. //
  296. SC_HANDLE hSvc = OpenService(hSCMgr,
  297. SCHED_SERVICE_NAME,
  298. SERVICE_CHANGE_CONFIG | SERVICE_START);
  299. if (hSvc == NULL)
  300. {
  301. hSvc = CreateService(hSCMgr,
  302. SCHED_SERVICE_NAME,
  303. tszDisplayName,
  304. SERVICE_CHANGE_CONFIG | SERVICE_START,
  305. SERVICE_WIN32_SHARE_PROCESS,
  306. SERVICE_AUTO_START,
  307. SERVICE_ERROR_NORMAL,
  308. SCHED_SERVICE_EXE_PATH,
  309. SCHED_SERVICE_GROUP,
  310. NULL,
  311. SCHED_SERVICE_DEPENDENCY,
  312. NULL,
  313. NULL);
  314. if (hSvc == NULL)
  315. {
  316. ErrorDialog(IDS_INSTALL_FAILURE,
  317. TEXT("CreateService"),
  318. GetLastError());
  319. CloseServiceHandle(hSCMgr);
  320. return;
  321. }
  322. }
  323. else
  324. {
  325. //
  326. // This path will be followed when we upgrade the At service
  327. // to the Scheduling Agent. The service name will remain the
  328. // same, but the display name will be set to the new display
  329. // name (the At service had no display name) and the image path
  330. // will be changed to point to the new exe.
  331. // (The old binary will be left on disk in order to make it easy
  332. // to revert to it, in case of compatibility problems.)
  333. //
  334. if (!ChangeServiceConfig(
  335. hSvc, // hService
  336. SERVICE_WIN32_SHARE_PROCESS, // dwServiceType
  337. SERVICE_AUTO_START, // dwStartType
  338. SERVICE_ERROR_NORMAL, // dwErrorControl
  339. SCHED_SERVICE_EXE_PATH, // lpBinaryPathName
  340. SCHED_SERVICE_GROUP, // lpLoadOrderGroup
  341. NULL, // lpdwTagId
  342. SCHED_SERVICE_DEPENDENCY, // lpDependencies
  343. L".\\LocalSystem", // lpServiceStartName
  344. L"", // lpPassword
  345. tszDisplayName // lpDisplayName
  346. ))
  347. {
  348. ErrorDialog(IDS_INSTALL_FAILURE,
  349. TEXT("ChangeServiceConfig"),
  350. GetLastError());
  351. CloseServiceHandle(hSvc);
  352. CloseServiceHandle(hSCMgr);
  353. return;
  354. }
  355. }
  356. // in either case, set the recovery options
  357. // not checking return - it's a minor glitch, no need to upset the user
  358. SC_ACTION actions[3] = {{SC_ACTION_RESTART, 6000},{SC_ACTION_RESTART, 60000},{SC_ACTION_NONE, 0}};
  359. SERVICE_FAILURE_ACTIONS recoveryInfo = {24*60*60, NULL, NULL, 3, &(actions[0])};
  360. ChangeServiceConfig2(hSvc,SERVICE_CONFIG_FAILURE_ACTIONS, (LPVOID)&recoveryInfo);
  361. CloseServiceHandle(hSvc);
  362. CloseServiceHandle(hSCMgr);
  363. }
  364. //+----------------------------------------------------------------------------
  365. //
  366. // Function: ErrorDialog
  367. //
  368. // Synopsis: Displays an error message.
  369. //
  370. //-----------------------------------------------------------------------------
  371. void
  372. ErrorDialog(UINT ErrorFmtStringID, TCHAR * szRoutine, DWORD ErrorCode)
  373. {
  374. #define ERROR_BUFFER_SIZE (MAX_PATH * 2)
  375. TCHAR szErrorFmt[MAX_PATH + 1] = TEXT("");
  376. TCHAR szError[ERROR_BUFFER_SIZE + 1];
  377. TCHAR * pszError = szError;
  378. LoadString(ghInstance, ErrorFmtStringID, szErrorFmt, MAX_PATH);
  379. if (*szErrorFmt)
  380. {
  381. StringCchPrintf(szError, ERROR_BUFFER_SIZE + 1, szErrorFmt, szRoutine, ErrorCode);
  382. }
  383. else
  384. {
  385. //
  386. // Not a localizable string, but done just in case LoadString
  387. // should fail for some reason.
  388. //
  389. StringCchCopy(szErrorFmt, MAX_PATH + 1, TEXT("Error installing Task Scheduler; error = 0x%x"));
  390. StringCchPrintf(szError, ERROR_BUFFER_SIZE + 1, szErrorFmt, ErrorCode);
  391. }
  392. MessageBox(NULL, szError, NULL, MB_ICONSTOP | MB_OK);
  393. }
  394. //+---------------------------------------------------------------------------
  395. //
  396. // Function: SetTaskFolderSecurity
  397. //
  398. // Synopsis: Grant the following permissions to the task folder:
  399. //
  400. // LocalSystem All Access.
  401. // Domain Administrators All Access.
  402. // World RWX Access (no permission to delete
  403. // child files).
  404. //
  405. // Arguments: [pwszFolderPath] -- Task folder path.
  406. //
  407. // Notes: None.
  408. //
  409. //----------------------------------------------------------------------------
  410. DWORD
  411. SetTaskFolderSecurity(LPCWSTR pwszFolderPath)
  412. {
  413. DWORD dwError = ERROR_SUCCESS;
  414. BOOL bSuccess;
  415. BOOL bWasEnabled = FALSE;
  416. BOOL bSetSacl = TRUE;
  417. PSECURITY_DESCRIPTOR pSecurityDescriptor = 0;
  418. DWORD i;
  419. SECURITY_INFORMATION dwSecInfo = 0;
  420. const DWORD c_dwBaseSidCount = 6;
  421. const DWORD c_dwDomainSidCount = 3;
  422. const DWORD c_dwDaclAceCountSrv = 5;
  423. const DWORD c_dwDaclAceCountWks = 4;
  424. const DWORD c_dwSaclAceCount = 2;
  425. //
  426. // Build the SIDs that will go in the security descriptor.
  427. //
  428. SID_IDENTIFIER_AUTHORITY NtAuth = SECURITY_NT_AUTHORITY;
  429. SID_IDENTIFIER_AUTHORITY WorldAuth = SECURITY_WORLD_SID_AUTHORITY;
  430. SID_IDENTIFIER_AUTHORITY CreatorAuth = SECURITY_CREATOR_SID_AUTHORITY;
  431. MYSIDINFO rgBaseSidInfo[c_dwBaseSidCount] =
  432. {
  433. {
  434. &NtAuth, // Local System.
  435. SECURITY_LOCAL_SYSTEM_RID,
  436. NULL
  437. },
  438. {
  439. &NtAuth, // Built in domain. (Used for
  440. SECURITY_BUILTIN_DOMAIN_RID, // domain admins SID.)
  441. NULL
  442. },
  443. {
  444. &NtAuth, // Authenticated user.
  445. SECURITY_AUTHENTICATED_USER_RID,
  446. NULL
  447. },
  448. {
  449. &CreatorAuth, // Creator.
  450. SECURITY_CREATOR_OWNER_RID,
  451. NULL
  452. },
  453. {
  454. &WorldAuth, // Everyone.
  455. SECURITY_WORLD_RID,
  456. NULL
  457. },
  458. {
  459. &NtAuth, // Anonymous.
  460. SECURITY_ANONYMOUS_LOGON_RID,
  461. NULL
  462. },
  463. };
  464. MYSIDINFO rgDomainSidInfo[c_dwDomainSidCount] =
  465. {
  466. {
  467. NULL, // Domain administrators.
  468. DOMAIN_ALIAS_RID_ADMINS,
  469. NULL
  470. },
  471. {
  472. NULL, // Server Operators.
  473. DOMAIN_ALIAS_RID_SYSTEM_OPS,
  474. NULL
  475. },
  476. {
  477. NULL, // Backup Operators.
  478. DOMAIN_ALIAS_RID_BACKUP_OPS,
  479. NULL
  480. }
  481. };
  482. //
  483. // Create the base SIDs.
  484. //
  485. for (i = 0; i < c_dwBaseSidCount; i++)
  486. {
  487. if (!AllocateAndInitializeSid(
  488. rgBaseSidInfo[i].pIdentifierAuthority,
  489. 1,
  490. rgBaseSidInfo[i].dwSubAuthority,
  491. 0, 0, 0, 0, 0, 0, 0,
  492. &rgBaseSidInfo[i].pSid))
  493. {
  494. dwError = GetLastError();
  495. break;
  496. }
  497. }
  498. if (dwError == ERROR_SUCCESS)
  499. {
  500. //
  501. // Create the domain SIDs.
  502. //
  503. for (i = 0; i < c_dwDomainSidCount; i++)
  504. {
  505. dwError = AllocateAndInitializeDomainSid(
  506. rgBaseSidInfo[1].pSid,
  507. &rgDomainSidInfo[i]);
  508. if (dwError != ERROR_SUCCESS)
  509. {
  510. break;
  511. }
  512. }
  513. }
  514. //
  515. // Create the security descriptor.
  516. //
  517. ACE_DESC rgDaclAcesSrv[c_dwDaclAceCountSrv] =
  518. {
  519. {
  520. FILE_ALL_ACCESS,
  521. ACCESS_ALLOWED_ACE_TYPE,
  522. OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
  523. rgBaseSidInfo[0].pSid // Local System
  524. },
  525. {
  526. FILE_ALL_ACCESS,
  527. ACCESS_ALLOWED_ACE_TYPE,
  528. OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
  529. rgDomainSidInfo[0].pSid // Domain admins
  530. },
  531. {
  532. FILE_GENERIC_READ | FILE_GENERIC_EXECUTE | FILE_WRITE_DATA,
  533. ACCESS_ALLOWED_ACE_TYPE,
  534. 0,
  535. rgDomainSidInfo[1].pSid // Backup Operators
  536. },
  537. {
  538. FILE_GENERIC_READ | FILE_GENERIC_EXECUTE | FILE_WRITE_DATA,
  539. ACCESS_ALLOWED_ACE_TYPE,
  540. 0,
  541. rgDomainSidInfo[2].pSid // Server Operators
  542. },
  543. {
  544. FILE_ALL_ACCESS,
  545. ACCESS_ALLOWED_ACE_TYPE,
  546. OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE,
  547. rgBaseSidInfo[3].pSid // Creator
  548. }
  549. };
  550. ACE_DESC rgDaclAcesWks[c_dwDaclAceCountWks] =
  551. {
  552. {
  553. FILE_ALL_ACCESS,
  554. ACCESS_ALLOWED_ACE_TYPE,
  555. OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
  556. rgBaseSidInfo[0].pSid // Local System
  557. },
  558. {
  559. FILE_ALL_ACCESS,
  560. ACCESS_ALLOWED_ACE_TYPE,
  561. OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
  562. rgDomainSidInfo[0].pSid // Domain admins
  563. },
  564. {
  565. FILE_GENERIC_READ | FILE_GENERIC_EXECUTE | FILE_WRITE_DATA,
  566. ACCESS_ALLOWED_ACE_TYPE,
  567. 0,
  568. rgBaseSidInfo[2].pSid // Authenticated user
  569. },
  570. {
  571. FILE_ALL_ACCESS,
  572. ACCESS_ALLOWED_ACE_TYPE,
  573. OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE,
  574. rgBaseSidInfo[3].pSid // Creator
  575. }
  576. };
  577. ACE_DESC rgSaclAces[c_dwSaclAceCount] =
  578. {
  579. {
  580. FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_DELETE_CHILD | DELETE | WRITE_DAC | WRITE_OWNER,
  581. SYSTEM_AUDIT_ACE_TYPE,
  582. SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
  583. rgBaseSidInfo[4].pSid // Everyone
  584. },
  585. {
  586. FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_DELETE_CHILD | DELETE | WRITE_DAC | WRITE_OWNER,
  587. SYSTEM_AUDIT_ACE_TYPE,
  588. SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
  589. rgBaseSidInfo[5].pSid // Anonymous
  590. }
  591. };
  592. if (dwError != ERROR_SUCCESS)
  593. {
  594. goto Cleanup;
  595. }
  596. // different security on workstation vs server
  597. OSVERSIONINFOEX verInfo;
  598. verInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  599. if (!GetVersionEx((LPOSVERSIONINFOW)&verInfo))
  600. {
  601. dwError = ERROR_NOT_SUPPORTED;
  602. goto Cleanup;
  603. }
  604. if (verInfo.wProductType == VER_NT_WORKSTATION)
  605. {
  606. dwError = CreateSecurityDescriptor(
  607. &pSecurityDescriptor,
  608. c_dwDaclAceCountWks,
  609. rgDaclAcesWks,
  610. c_dwSaclAceCount,
  611. rgSaclAces);
  612. if (dwError != ERROR_SUCCESS)
  613. {
  614. goto Cleanup;
  615. }
  616. }
  617. else
  618. {
  619. dwError = CreateSecurityDescriptor(
  620. &pSecurityDescriptor,
  621. c_dwDaclAceCountSrv,
  622. rgDaclAcesSrv,
  623. c_dwSaclAceCount,
  624. rgSaclAces);
  625. if (dwError != ERROR_SUCCESS)
  626. {
  627. goto Cleanup;
  628. }
  629. }
  630. //
  631. // Enable SecurityPrivilege in order to be able
  632. // to set the SACL.
  633. //
  634. dwError = EnablePrivilege(
  635. SE_SECURITY_NAME,
  636. TRUE,
  637. &bWasEnabled);
  638. if (dwError != ERROR_SUCCESS)
  639. {
  640. bSetSacl = FALSE;
  641. }
  642. //
  643. // Finally, set permissions.
  644. //
  645. dwSecInfo |= DACL_SECURITY_INFORMATION;
  646. if (bSetSacl && c_dwSaclAceCount)
  647. {
  648. dwSecInfo |= SACL_SECURITY_INFORMATION;
  649. }
  650. bSuccess = SetFileSecurity(
  651. pwszFolderPath,
  652. dwSecInfo,
  653. pSecurityDescriptor);
  654. if (!bWasEnabled)
  655. {
  656. EnablePrivilege(
  657. SE_SECURITY_NAME,
  658. FALSE,
  659. 0);
  660. }
  661. if (!bSuccess)
  662. {
  663. dwError = GetLastError();
  664. goto Cleanup;
  665. }
  666. dwError = ERROR_SUCCESS;
  667. Cleanup:
  668. for (i = 0; i < c_dwBaseSidCount; i++)
  669. {
  670. if (rgBaseSidInfo[i].pSid != NULL)
  671. {
  672. FreeSid(rgBaseSidInfo[i].pSid);
  673. }
  674. }
  675. for (i = 0; i < c_dwDomainSidCount; i++)
  676. {
  677. LocalFree(rgDomainSidInfo[i].pSid);
  678. }
  679. if (pSecurityDescriptor != NULL)
  680. {
  681. DeleteSecurityDescriptor(pSecurityDescriptor);
  682. }
  683. return dwError;
  684. }
  685. //+---------------------------------------------------------------------------
  686. //
  687. // Function: AllocateAndInitializeDomainSid
  688. //
  689. // Synopsis:
  690. //
  691. // Arguments: [pDomainSid] --
  692. // [pDomainSidInfo] --
  693. //
  694. // Notes: None.
  695. //
  696. //----------------------------------------------------------------------------
  697. DWORD
  698. AllocateAndInitializeDomainSid(
  699. PSID pDomainSid,
  700. MYSIDINFO * pDomainSidInfo)
  701. {
  702. UCHAR DomainIdSubAuthorityCount;
  703. DWORD SidLength;
  704. //
  705. // Allocate a Sid which has one more sub-authority than the domain ID.
  706. //
  707. DomainIdSubAuthorityCount = *(GetSidSubAuthorityCount(pDomainSid));
  708. SidLength = GetSidLengthRequired(DomainIdSubAuthorityCount + 1);
  709. pDomainSidInfo->pSid = (PSID) LocalAlloc(0, SidLength);
  710. if (pDomainSidInfo->pSid == NULL)
  711. {
  712. return(ERROR_NOT_ENOUGH_MEMORY);
  713. }
  714. //
  715. // Initialize the new SID to have the same initial value as the
  716. // domain ID.
  717. //
  718. if (!CopySid(SidLength, pDomainSidInfo->pSid, pDomainSid))
  719. {
  720. LocalFree(pDomainSidInfo->pSid);
  721. pDomainSidInfo->pSid = NULL;
  722. return(GetLastError());
  723. }
  724. //
  725. // Adjust the sub-authority count and add the relative Id unique
  726. // to the newly allocated SID
  727. //
  728. (*(GetSidSubAuthorityCount(pDomainSidInfo->pSid)))++;
  729. *(GetSidSubAuthority(pDomainSidInfo->pSid,
  730. DomainIdSubAuthorityCount)) =
  731. pDomainSidInfo->dwSubAuthority;
  732. return(ERROR_SUCCESS);
  733. }