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