Synchronize with trunk's revision r57629.
[reactos.git] / dll / win32 / samsrv / setup.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: Security Account Manager (SAM) Server
4 * FILE: reactos/dll/win32/samsrv/setup.c
5 * PURPOSE: Registry setup routines
6 *
7 * PROGRAMMERS: Eric Kohl
8 */
9
10 /* INCLUDES ****************************************************************/
11
12 #include "samsrv.h"
13
14 WINE_DEFAULT_DEBUG_CHANNEL(samsrv);
15
16 /* GLOBALS *****************************************************************/
17
18 SID_IDENTIFIER_AUTHORITY SecurityNtAuthority = {SECURITY_NT_AUTHORITY};
19
20 /* FUNCTIONS ***************************************************************/
21
22 BOOL
23 SampIsSetupRunning(VOID)
24 {
25 DWORD dwError;
26 HKEY hKey;
27 DWORD dwType;
28 DWORD dwSize;
29 DWORD dwSetupType;
30
31 TRACE("SampIsSetupRunning()\n");
32
33 /* Open key */
34 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
35 L"SYSTEM\\Setup",
36 0,
37 KEY_QUERY_VALUE,
38 &hKey);
39 if (dwError != ERROR_SUCCESS)
40 return FALSE;
41
42 /* Read key */
43 dwSize = sizeof(DWORD);
44 dwError = RegQueryValueExW(hKey,
45 L"SetupType",
46 NULL,
47 &dwType,
48 (LPBYTE)&dwSetupType,
49 &dwSize);
50
51 /* Close key, and check if returned values are correct */
52 RegCloseKey(hKey);
53 if (dwError != ERROR_SUCCESS || dwType != REG_DWORD || dwSize != sizeof(DWORD))
54 return FALSE;
55
56 TRACE("SampIsSetupRunning() returns %s\n", (dwSetupType != 0) ? "TRUE" : "FALSE");
57 return (dwSetupType != 0);
58 }
59
60
61 static PSID
62 AppendRidToSid(PSID SrcSid,
63 ULONG Rid)
64 {
65 ULONG Rids[8] = {0, 0, 0, 0, 0, 0, 0, 0};
66 UCHAR RidCount;
67 PSID DstSid;
68 ULONG i;
69
70 RidCount = *RtlSubAuthorityCountSid(SrcSid);
71 if (RidCount >= 8)
72 return NULL;
73
74 for (i = 0; i < RidCount; i++)
75 Rids[i] = *RtlSubAuthoritySid(SrcSid, i);
76
77 Rids[RidCount] = Rid;
78 RidCount++;
79
80 RtlAllocateAndInitializeSid(RtlIdentifierAuthoritySid(SrcSid),
81 RidCount,
82 Rids[0],
83 Rids[1],
84 Rids[2],
85 Rids[3],
86 Rids[4],
87 Rids[5],
88 Rids[6],
89 Rids[7],
90 &DstSid);
91
92 return DstSid;
93 }
94
95
96 static BOOL
97 SampAddMemberToAlias(HKEY hDomainKey,
98 ULONG AliasId,
99 PSID MemberSid)
100 {
101 DWORD dwDisposition;
102 LPWSTR MemberSidString = NULL;
103 WCHAR szKeyName[256];
104 HKEY hMembersKey;
105
106 ConvertSidToStringSidW(MemberSid, &MemberSidString);
107
108 swprintf(szKeyName, L"Aliases\\%08lX\\Members", AliasId);
109
110 if (!RegCreateKeyExW(hDomainKey,
111 szKeyName,
112 0,
113 NULL,
114 REG_OPTION_NON_VOLATILE,
115 KEY_ALL_ACCESS,
116 NULL,
117 &hMembersKey,
118 &dwDisposition))
119 {
120 RegSetValueEx(hMembersKey,
121 MemberSidString,
122 0,
123 REG_BINARY,
124 (LPVOID)MemberSid,
125 RtlLengthSid(MemberSid));
126
127 RegCloseKey(hMembersKey);
128 }
129
130 swprintf(szKeyName, L"Aliases\\Members\\%s", MemberSidString);
131
132 if (!RegCreateKeyExW(hDomainKey,
133 szKeyName,
134 0,
135 NULL,
136 REG_OPTION_NON_VOLATILE,
137 KEY_ALL_ACCESS,
138 NULL,
139 &hMembersKey,
140 &dwDisposition))
141 {
142 swprintf(szKeyName, L"%08lX", AliasId);
143
144 RegSetValueEx(hMembersKey,
145 szKeyName,
146 0,
147 REG_BINARY,
148 (LPVOID)MemberSid,
149 RtlLengthSid(MemberSid));
150
151 RegCloseKey(hMembersKey);
152 }
153
154 if (MemberSidString != NULL)
155 LocalFree(MemberSidString);
156
157 return TRUE;
158 }
159
160
161 static BOOL
162 SampCreateAliasAccount(HKEY hDomainKey,
163 LPCWSTR lpAccountName,
164 LPCWSTR lpDescription,
165 ULONG ulRelativeId)
166 {
167 DWORD dwDisposition;
168 WCHAR szAccountKeyName[32];
169 HKEY hAccountKey = NULL;
170 HKEY hNamesKey = NULL;
171
172 swprintf(szAccountKeyName, L"Aliases\\%08lX", ulRelativeId);
173
174 if (!RegCreateKeyExW(hDomainKey,
175 szAccountKeyName,
176 0,
177 NULL,
178 REG_OPTION_NON_VOLATILE,
179 KEY_ALL_ACCESS,
180 NULL,
181 &hAccountKey,
182 &dwDisposition))
183 {
184 RegSetValueEx(hAccountKey,
185 L"Name",
186 0,
187 REG_SZ,
188 (LPVOID)lpAccountName,
189 (wcslen(lpAccountName) + 1) * sizeof(WCHAR));
190
191 RegSetValueEx(hAccountKey,
192 L"Description",
193 0,
194 REG_SZ,
195 (LPVOID)lpDescription,
196 (wcslen(lpDescription) + 1) * sizeof(WCHAR));
197
198 RegCloseKey(hAccountKey);
199 }
200
201 if (!RegOpenKeyExW(hDomainKey,
202 L"Aliases\\Names",
203 0,
204 KEY_ALL_ACCESS,
205 &hNamesKey))
206 {
207 RegSetValueEx(hNamesKey,
208 lpAccountName,
209 0,
210 REG_DWORD,
211 (LPVOID)&ulRelativeId,
212 sizeof(ULONG));
213
214 RegCloseKey(hNamesKey);
215 }
216
217 return TRUE;
218 }
219
220
221 static BOOL
222 SampCreateUserAccount(HKEY hDomainKey,
223 LPCWSTR lpAccountName,
224 ULONG ulRelativeId)
225 {
226 SAM_USER_FIXED_DATA FixedUserData;
227 LPWSTR lpEmptyString = L"";
228 DWORD dwDisposition;
229 WCHAR szAccountKeyName[32];
230 HKEY hAccountKey = NULL;
231 HKEY hNamesKey = NULL;
232
233 /* Initialize fixed user data */
234 memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA));
235 FixedUserData.Version = 1;
236
237 FixedUserData.UserId = ulRelativeId;
238
239 swprintf(szAccountKeyName, L"Users\\%08lX", ulRelativeId);
240
241 if (!RegCreateKeyExW(hDomainKey,
242 szAccountKeyName,
243 0,
244 NULL,
245 REG_OPTION_NON_VOLATILE,
246 KEY_ALL_ACCESS,
247 NULL,
248 &hAccountKey,
249 &dwDisposition))
250 {
251 RegSetValueEx(hAccountKey,
252 L"F",
253 0,
254 REG_BINARY,
255 (LPVOID)&FixedUserData,
256 sizeof(SAM_USER_FIXED_DATA));
257
258 RegSetValueEx(hAccountKey,
259 L"Name",
260 0,
261 REG_SZ,
262 (LPVOID)lpAccountName,
263 (wcslen(lpAccountName) + 1) * sizeof(WCHAR));
264
265 RegSetValueEx(hAccountKey,
266 L"FullName",
267 0,
268 REG_SZ,
269 (LPVOID)lpEmptyString,
270 sizeof(WCHAR));
271
272 RegSetValueEx(hAccountKey,
273 L"HomeDirectory",
274 0,
275 REG_SZ,
276 (LPVOID)lpEmptyString,
277 sizeof(WCHAR));
278
279 RegSetValueEx(hAccountKey,
280 L"HomeDirectoryDrive",
281 0,
282 REG_SZ,
283 (LPVOID)lpEmptyString,
284 sizeof(WCHAR));
285
286 RegSetValueEx(hAccountKey,
287 L"ScriptPath",
288 0,
289 REG_SZ,
290 (LPVOID)lpEmptyString,
291 sizeof(WCHAR));
292
293 RegSetValueEx(hAccountKey,
294 L"ProfilePath",
295 0,
296 REG_SZ,
297 (LPVOID)lpEmptyString,
298 sizeof(WCHAR));
299
300 RegSetValueEx(hAccountKey,
301 L"AdminComment",
302 0,
303 REG_SZ,
304 (LPVOID)lpEmptyString,
305 sizeof(WCHAR));
306
307 RegSetValueEx(hAccountKey,
308 L"UserComment",
309 0,
310 REG_SZ,
311 (LPVOID)lpEmptyString,
312 sizeof(WCHAR));
313
314 RegSetValueEx(hAccountKey,
315 L"WorkStations",
316 0,
317 REG_SZ,
318 (LPVOID)lpEmptyString,
319 sizeof(WCHAR));
320
321 RegCloseKey(hAccountKey);
322 }
323
324 if (!RegOpenKeyExW(hDomainKey,
325 L"Users\\Names",
326 0,
327 KEY_ALL_ACCESS,
328 &hNamesKey))
329 {
330 RegSetValueEx(hNamesKey,
331 lpAccountName,
332 0,
333 REG_DWORD,
334 (LPVOID)&ulRelativeId,
335 sizeof(ULONG));
336
337 RegCloseKey(hNamesKey);
338 }
339
340 return TRUE;
341 }
342
343
344 static BOOL
345 SampCreateDomain(IN HKEY hDomainsKey,
346 IN LPCWSTR lpKeyName,
347 IN LPCWSTR lpDomainName,
348 IN PSID lpDomainSid,
349 OUT PHKEY lpDomainKey)
350 {
351 SAM_DOMAIN_FIXED_DATA FixedData;
352 LPWSTR lpEmptyString = L"";
353 DWORD dwDisposition;
354 HKEY hDomainKey = NULL;
355 HKEY hAliasesKey = NULL;
356 HKEY hGroupsKey = NULL;
357 HKEY hUsersKey = NULL;
358 HKEY hNamesKey = NULL;
359
360 if (lpDomainKey != NULL)
361 *lpDomainKey = NULL;
362
363 /* Initialize the fixed domain data */
364 memset(&FixedData, 0, sizeof(SAM_DOMAIN_FIXED_DATA));
365 FixedData.Version = 1;
366 NtQuerySystemTime(&FixedData.CreationTime);
367 FixedData.DomainModifiedCount.QuadPart = 0;
368 // FixedData.MaxPasswordAge // 6 Weeks
369 FixedData.MinPasswordAge.QuadPart = 0; // Now
370 // FixedData.ForceLogoff
371 // FixedData.LockoutDuration // 30 minutes
372 // FixedData.LockoutObservationWindow // 30 minutes
373 FixedData.ModifiedCountAtLastPromotion.QuadPart = 0;
374 FixedData.NextRid = 1000;
375 FixedData.PasswordProperties = 0;
376 FixedData.MinPasswordLength = 0;
377 FixedData.PasswordHistoryLength = 0;
378 FixedData.LockoutThreshold = 0;
379 FixedData.DomainServerState = DomainServerEnabled;
380 FixedData.DomainServerRole = DomainServerRolePrimary;
381 FixedData.UasCompatibilityRequired = TRUE;
382
383 if (RegCreateKeyExW(hDomainsKey,
384 lpKeyName,
385 0,
386 NULL,
387 REG_OPTION_NON_VOLATILE,
388 KEY_ALL_ACCESS,
389 NULL,
390 &hDomainKey,
391 &dwDisposition))
392 return FALSE;
393
394 /* Set the fixed data value */
395 if (RegSetValueEx(hDomainKey,
396 L"F",
397 0,
398 REG_BINARY,
399 (LPVOID)&FixedData,
400 sizeof(SAM_DOMAIN_FIXED_DATA)))
401 return FALSE;
402
403 if (lpDomainSid != NULL)
404 {
405 RegSetValueEx(hDomainKey,
406 L"Name",
407 0,
408 REG_SZ,
409 (LPVOID)lpDomainName,
410 (wcslen(lpDomainName) + 1) * sizeof(WCHAR));
411
412 RegSetValueEx(hDomainKey,
413 L"SID",
414 0,
415 REG_BINARY,
416 (LPVOID)lpDomainSid,
417 RtlLengthSid(lpDomainSid));
418 }
419
420 RegSetValueEx(hDomainKey,
421 L"OemInformation",
422 0,
423 REG_SZ,
424 (LPVOID)lpEmptyString,
425 sizeof(WCHAR));
426
427 RegSetValueEx(hDomainKey,
428 L"ReplicaSourceNodeName",
429 0,
430 REG_SZ,
431 (LPVOID)lpEmptyString,
432 sizeof(WCHAR));
433
434 /* Create the Alias container */
435 if (!RegCreateKeyExW(hDomainKey,
436 L"Aliases",
437 0,
438 NULL,
439 REG_OPTION_NON_VOLATILE,
440 KEY_ALL_ACCESS,
441 NULL,
442 &hAliasesKey,
443 &dwDisposition))
444 {
445 if (!RegCreateKeyExW(hAliasesKey,
446 L"Names",
447 0,
448 NULL,
449 REG_OPTION_NON_VOLATILE,
450 KEY_ALL_ACCESS,
451 NULL,
452 &hNamesKey,
453 &dwDisposition))
454 RegCloseKey(hNamesKey);
455
456 RegCloseKey(hAliasesKey);
457 }
458
459 /* Create the Groups container */
460 if (!RegCreateKeyExW(hDomainKey,
461 L"Groups",
462 0,
463 NULL,
464 REG_OPTION_NON_VOLATILE,
465 KEY_ALL_ACCESS,
466 NULL,
467 &hGroupsKey,
468 &dwDisposition))
469 {
470 if (!RegCreateKeyExW(hGroupsKey,
471 L"Names",
472 0,
473 NULL,
474 REG_OPTION_NON_VOLATILE,
475 KEY_ALL_ACCESS,
476 NULL,
477 &hNamesKey,
478 &dwDisposition))
479 RegCloseKey(hNamesKey);
480
481 RegCloseKey(hGroupsKey);
482 }
483
484
485 /* Create the Users container */
486 if (!RegCreateKeyExW(hDomainKey,
487 L"Users",
488 0,
489 NULL,
490 REG_OPTION_NON_VOLATILE,
491 KEY_ALL_ACCESS,
492 NULL,
493 &hUsersKey,
494 &dwDisposition))
495 {
496 if (!RegCreateKeyExW(hUsersKey,
497 L"Names",
498 0,
499 NULL,
500 REG_OPTION_NON_VOLATILE,
501 KEY_ALL_ACCESS,
502 NULL,
503 &hNamesKey,
504 &dwDisposition))
505 RegCloseKey(hNamesKey);
506
507 RegCloseKey(hUsersKey);
508 }
509
510 if (lpDomainKey != NULL)
511 *lpDomainKey = hDomainKey;
512
513 return TRUE;
514 }
515
516
517 NTSTATUS
518 SampGetAccountDomainInfo(PPOLICY_ACCOUNT_DOMAIN_INFO *AccountDomainInfo)
519 {
520 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
521 LSA_HANDLE PolicyHandle;
522 NTSTATUS Status;
523
524 TRACE("SampGetAccountDomainInfo\n");
525
526 memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES));
527 ObjectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
528
529 Status = LsaOpenPolicy(NULL,
530 &ObjectAttributes,
531 POLICY_VIEW_LOCAL_INFORMATION,
532 &PolicyHandle);
533 if (Status != STATUS_SUCCESS)
534 {
535 ERR("LsaOpenPolicy failed (Status: 0x%08lx)\n", Status);
536 return Status;
537 }
538
539 Status = LsaQueryInformationPolicy(PolicyHandle,
540 PolicyAccountDomainInformation,
541 (PVOID *)AccountDomainInfo);
542
543 LsaClose(PolicyHandle);
544
545 return Status;
546 }
547
548
549 BOOL
550 SampInitializeSAM(VOID)
551 {
552 PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo = NULL;
553 DWORD dwDisposition;
554 HKEY hSamKey = NULL;
555 HKEY hDomainsKey = NULL;
556 HKEY hDomainKey = NULL;
557 PSID pBuiltinSid = NULL;
558 BOOL bResult = TRUE;
559 PSID pSid;
560 NTSTATUS Status;
561
562 TRACE("SampInitializeSAM() called\n");
563
564 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
565 L"SAM\\SAM",
566 0,
567 NULL,
568 REG_OPTION_NON_VOLATILE,
569 KEY_ALL_ACCESS,
570 NULL,
571 &hSamKey,
572 &dwDisposition))
573 {
574 ERR("Failed to create 'Sam' key! (Error %lu)\n", GetLastError());
575 return FALSE;
576 }
577
578 if (RegCreateKeyExW(hSamKey,
579 L"Domains",
580 0,
581 NULL,
582 REG_OPTION_NON_VOLATILE,
583 KEY_ALL_ACCESS,
584 NULL,
585 &hDomainsKey,
586 &dwDisposition))
587 {
588 ERR("Failed to create 'Domains' key! (Error %lu)\n", GetLastError());
589 bResult = FALSE;
590 goto done;
591 }
592
593 RegCloseKey(hSamKey);
594 hSamKey = NULL;
595
596 /* Create and initialize the Builtin Domain SID */
597 pBuiltinSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, RtlLengthRequiredSid(1));
598 if (pBuiltinSid == NULL)
599 {
600 ERR("Failed to alloacte the Builtin Domain SID\n");
601 bResult = FALSE;
602 goto done;
603 }
604
605 RtlInitializeSid(pBuiltinSid, &SecurityNtAuthority, 1);
606 *(RtlSubAuthoritySid(pBuiltinSid, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
607
608 /* Get account domain information */
609 Status = SampGetAccountDomainInfo(&AccountDomainInfo);
610 if (!NT_SUCCESS(Status))
611 {
612 ERR("SampGetAccountDomainInfo failed (Status %08lx)\n", Status);
613 bResult = FALSE;
614 goto done;
615 }
616
617 /* Create the Builtin domain */
618 if (SampCreateDomain(hDomainsKey,
619 L"Builtin",
620 L"Builtin",
621 pBuiltinSid,
622 &hDomainKey))
623 {
624 SampCreateAliasAccount(hDomainKey,
625 L"Administrators",
626 L"Testabc1234567890",
627 DOMAIN_ALIAS_RID_ADMINS);
628
629 SampCreateAliasAccount(hDomainKey,
630 L"Users",
631 L"Users Group",
632 DOMAIN_ALIAS_RID_USERS);
633
634 SampCreateAliasAccount(hDomainKey,
635 L"Guests",
636 L"Guests Group",
637 DOMAIN_ALIAS_RID_GUESTS);
638
639 SampCreateAliasAccount(hDomainKey,
640 L"Power Users",
641 L"Power Users Group",
642 DOMAIN_ALIAS_RID_POWER_USERS);
643
644
645 pSid = AppendRidToSid(AccountDomainInfo->DomainSid,
646 DOMAIN_USER_RID_ADMIN);
647 if (pSid != NULL)
648 {
649 SampAddMemberToAlias(hDomainKey,
650 DOMAIN_ALIAS_RID_ADMINS,
651 pSid);
652
653 RtlFreeHeap(RtlGetProcessHeap(), 0, pSid);
654 }
655
656
657 RegCloseKey(hDomainKey);
658 }
659
660 /* Create the Account domain */
661 if (SampCreateDomain(hDomainsKey,
662 L"Account",
663 L"",
664 AccountDomainInfo->DomainSid,
665 &hDomainKey))
666 {
667 SampCreateUserAccount(hDomainKey,
668 L"Administrator",
669 DOMAIN_USER_RID_ADMIN);
670
671 SampCreateUserAccount(hDomainKey,
672 L"Guest",
673 DOMAIN_USER_RID_GUEST);
674
675 RegCloseKey(hDomainKey);
676 }
677
678 done:
679 if (AccountDomainInfo)
680 LsaFreeMemory(AccountDomainInfo);
681
682 if (pBuiltinSid)
683 RtlFreeHeap(RtlGetProcessHeap(), 0, pBuiltinSid);
684
685 if (hDomainsKey)
686 RegCloseKey(hDomainsKey);
687
688 if (hSamKey)
689 RegCloseKey(hSamKey);
690
691 TRACE("SampInitializeSAM() done\n");
692
693 return bResult;
694 }