xref: /reactos/dll/win32/samsrv/setup.c (revision 7b2978c4)
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 static BOOL
27 SampSetupAddMemberToAlias(HKEY hDomainKey,
28                           ULONG AliasId,
29                           PSID MemberSid)
30 {
31     DWORD dwDisposition;
32     LPWSTR MemberSidString = NULL;
33     WCHAR szKeyName[256];
34     HKEY hMembersKey;
35 
36     ConvertSidToStringSidW(MemberSid, &MemberSidString);
37 
38     swprintf(szKeyName, L"Aliases\\%08lX\\Members", AliasId);
39 
40     if (!RegCreateKeyExW(hDomainKey,
41                          szKeyName,
42                          0,
43                          NULL,
44                          REG_OPTION_NON_VOLATILE,
45                          KEY_ALL_ACCESS,
46                          NULL,
47                          &hMembersKey,
48                          &dwDisposition))
49     {
50         RegSetValueEx(hMembersKey,
51                       MemberSidString,
52                       0,
53                       REG_BINARY,
54                       (LPVOID)MemberSid,
55                       RtlLengthSid(MemberSid));
56 
57         RegCloseKey(hMembersKey);
58     }
59 
60     swprintf(szKeyName, L"Aliases\\Members\\%s", MemberSidString);
61 
62     if (!RegCreateKeyExW(hDomainKey,
63                          szKeyName,
64                          0,
65                          NULL,
66                          REG_OPTION_NON_VOLATILE,
67                          KEY_ALL_ACCESS,
68                          NULL,
69                          &hMembersKey,
70                          &dwDisposition))
71     {
72         swprintf(szKeyName, L"%08lX", AliasId);
73 
74         RegSetValueEx(hMembersKey,
75                       szKeyName,
76                       0,
77                       REG_BINARY,
78                       (LPVOID)MemberSid,
79                       RtlLengthSid(MemberSid));
80 
81         RegCloseKey(hMembersKey);
82     }
83 
84     if (MemberSidString != NULL)
85         LocalFree(MemberSidString);
86 
87     return TRUE;
88 }
89 
90 
91 static
92 NTSTATUS
93 SampSetupCreateAliasAccount(HANDLE hDomainKey,
94                             LPCWSTR lpAccountName,
95                             LPCWSTR lpDescription,
96                             ULONG ulRelativeId)
97 {
98     WCHAR szAccountKeyName[32];
99     HANDLE hAccountKey = NULL;
100     HANDLE hNamesKey = NULL;
101     NTSTATUS Status;
102 
103     swprintf(szAccountKeyName, L"Aliases\\%08lX", ulRelativeId);
104 
105     Status = SampRegCreateKey(hDomainKey,
106                               szAccountKeyName,
107                               KEY_ALL_ACCESS,
108                               &hAccountKey);
109     if (!NT_SUCCESS(Status))
110         return Status;
111 
112     Status = SampRegSetValue(hAccountKey,
113                              L"Name",
114                              REG_SZ,
115                              (LPVOID)lpAccountName,
116                              (wcslen(lpAccountName) + 1) * sizeof(WCHAR));
117     if (!NT_SUCCESS(Status))
118         goto done;
119 
120     Status = SampRegSetValue(hAccountKey,
121                              L"Description",
122                              REG_SZ,
123                              (LPVOID)lpDescription,
124                              (wcslen(lpDescription) + 1) * sizeof(WCHAR));
125     if (!NT_SUCCESS(Status))
126         goto done;
127 
128 
129     Status = SampRegOpenKey(hDomainKey,
130                             L"Aliases\\Names",
131                             KEY_ALL_ACCESS,
132                             &hNamesKey);
133     if (!NT_SUCCESS(Status))
134         goto done;
135 
136     Status = SampRegSetValue(hNamesKey,
137                             lpAccountName,
138                             REG_DWORD,
139                             (LPVOID)&ulRelativeId,
140                             sizeof(ULONG));
141 
142 done:
143     if (hNamesKey != NULL)
144         SampRegCloseKey(hNamesKey);
145 
146     if (hAccountKey != NULL)
147     {
148         SampRegCloseKey(hAccountKey);
149 
150         if (!NT_SUCCESS(Status))
151             SampRegDeleteKey(hDomainKey,
152                              szAccountKeyName);
153     }
154 
155     return Status;
156 }
157 
158 
159 static
160 NTSTATUS
161 SampSetupAddMemberToGroup(IN HANDLE hDomainKey,
162                           IN ULONG GroupId,
163                           IN ULONG MemberId)
164 {
165     WCHAR szKeyName[256];
166     HANDLE hGroupKey = NULL;
167     PULONG MembersBuffer = NULL;
168     ULONG MembersCount = 0;
169     ULONG Length = 0;
170     ULONG i;
171     NTSTATUS Status;
172 
173     swprintf(szKeyName, L"Groups\\%08lX", GroupId);
174 
175     Status = SampRegOpenKey(hDomainKey,
176                             szKeyName,
177                             KEY_ALL_ACCESS,
178                             &hGroupKey);
179     if (!NT_SUCCESS(Status))
180         return Status;
181 
182     Status = SampRegQueryValue(hGroupKey,
183                                L"Members",
184                                NULL,
185                                NULL,
186                                &Length);
187     if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
188         goto done;
189 
190     MembersBuffer = midl_user_allocate(Length + sizeof(ULONG));
191     if (MembersBuffer == NULL)
192     {
193         Status = STATUS_INSUFFICIENT_RESOURCES;
194         goto done;
195     }
196 
197     if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
198     {
199         Status = SampRegQueryValue(hGroupKey,
200                                    L"Members",
201                                    NULL,
202                                    MembersBuffer,
203                                    &Length);
204         if (!NT_SUCCESS(Status))
205             goto done;
206 
207         MembersCount = Length / sizeof(ULONG);
208     }
209 
210     for (i = 0; i < MembersCount; i++)
211     {
212         if (MembersBuffer[i] == MemberId)
213         {
214             Status = STATUS_MEMBER_IN_GROUP;
215             goto done;
216         }
217     }
218 
219     MembersBuffer[MembersCount] = MemberId;
220     Length += sizeof(ULONG);
221 
222     Status = SampRegSetValue(hGroupKey,
223                              L"Members",
224                              REG_BINARY,
225                              MembersBuffer,
226                              Length);
227 
228 done:
229     if (MembersBuffer != NULL)
230         midl_user_free(MembersBuffer);
231 
232     if (hGroupKey != NULL)
233         SampRegCloseKey(hGroupKey);
234 
235     return Status;
236 }
237 
238 
239 static
240 NTSTATUS
241 SampSetupCreateGroupAccount(HANDLE hDomainKey,
242                             LPCWSTR lpAccountName,
243                             LPCWSTR lpComment,
244                             ULONG ulRelativeId)
245 {
246     SAM_GROUP_FIXED_DATA FixedGroupData;
247     WCHAR szAccountKeyName[32];
248     HANDLE hAccountKey = NULL;
249     HANDLE hNamesKey = NULL;
250     NTSTATUS Status;
251 
252     /* Initialize fixed group data */
253     FixedGroupData.Version = 1;
254     FixedGroupData.Reserved = 0;
255     FixedGroupData.GroupId = ulRelativeId;
256     FixedGroupData.Attributes = 0;
257 
258     swprintf(szAccountKeyName, L"Groups\\%08lX", ulRelativeId);
259 
260     Status = SampRegCreateKey(hDomainKey,
261                               szAccountKeyName,
262                               KEY_ALL_ACCESS,
263                               &hAccountKey);
264     if (!NT_SUCCESS(Status))
265         return Status;
266 
267     Status = SampRegSetValue(hAccountKey,
268                              L"F",
269                              REG_BINARY,
270                              (LPVOID)&FixedGroupData,
271                              sizeof(SAM_GROUP_FIXED_DATA));
272     if (!NT_SUCCESS(Status))
273         goto done;
274 
275     Status = SampRegSetValue(hAccountKey,
276                              L"Name",
277                              REG_SZ,
278                              (LPVOID)lpAccountName,
279                              (wcslen(lpAccountName) + 1) * sizeof(WCHAR));
280     if (!NT_SUCCESS(Status))
281         goto done;
282 
283     Status = SampRegSetValue(hAccountKey,
284                              L"AdminComment",
285                              REG_SZ,
286                              (LPVOID)lpComment,
287                              (wcslen(lpComment) + 1) * sizeof(WCHAR));
288     if (!NT_SUCCESS(Status))
289         goto done;
290 
291     Status = SampRegOpenKey(hDomainKey,
292                             L"Groups\\Names",
293                             KEY_ALL_ACCESS,
294                             &hNamesKey);
295     if (!NT_SUCCESS(Status))
296         goto done;
297 
298     Status = SampRegSetValue(hNamesKey,
299                             lpAccountName,
300                             REG_DWORD,
301                             (LPVOID)&ulRelativeId,
302                             sizeof(ULONG));
303 
304 done:
305     if (hNamesKey != NULL)
306         SampRegCloseKey(hNamesKey);
307 
308     if (hAccountKey != NULL)
309     {
310         SampRegCloseKey(hAccountKey);
311 
312         if (!NT_SUCCESS(Status))
313             SampRegDeleteKey(hDomainKey,
314                              szAccountKeyName);
315     }
316 
317     return Status;
318 }
319 
320 
321 static
322 NTSTATUS
323 SampSetupCreateUserAccount(HANDLE hDomainKey,
324                            LPCWSTR lpAccountName,
325                            LPCWSTR lpComment,
326                            ULONG ulRelativeId,
327                            ULONG UserAccountControl)
328 {
329     SAM_USER_FIXED_DATA FixedUserData;
330     GROUP_MEMBERSHIP GroupMembership;
331     UCHAR LogonHours[23];
332     LPWSTR lpEmptyString = L"";
333     WCHAR szAccountKeyName[32];
334     HANDLE hAccountKey = NULL;
335     HANDLE hNamesKey = NULL;
336     NTSTATUS Status;
337 
338     /* Initialize fixed user data */
339     FixedUserData.Version = 1;
340     FixedUserData.Reserved = 0;
341     FixedUserData.LastLogon.QuadPart = 0;
342     FixedUserData.LastLogoff.QuadPart = 0;
343     FixedUserData.PasswordLastSet.QuadPart = 0;
344     FixedUserData.AccountExpires.LowPart = MAXULONG;
345     FixedUserData.AccountExpires.HighPart = MAXLONG;
346     FixedUserData.LastBadPasswordTime.QuadPart = 0;
347     FixedUserData.UserId = ulRelativeId;
348     FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS;
349     FixedUserData.UserAccountControl = UserAccountControl;
350     FixedUserData.CountryCode = 0;
351     FixedUserData.CodePage = 0;
352     FixedUserData.BadPasswordCount = 0;
353     FixedUserData.LogonCount = 0;
354     FixedUserData.AdminCount = 0;
355     FixedUserData.OperatorCount = 0;
356 
357     swprintf(szAccountKeyName, L"Users\\%08lX", ulRelativeId);
358 
359     Status = SampRegCreateKey(hDomainKey,
360                               szAccountKeyName,
361                               KEY_ALL_ACCESS,
362                               &hAccountKey);
363     if (!NT_SUCCESS(Status))
364         return Status;
365 
366     Status = SampRegSetValue(hAccountKey,
367                              L"F",
368                              REG_BINARY,
369                              (LPVOID)&FixedUserData,
370                              sizeof(SAM_USER_FIXED_DATA));
371     if (!NT_SUCCESS(Status))
372         goto done;
373 
374     Status = SampRegSetValue(hAccountKey,
375                              L"Name",
376                              REG_SZ,
377                              (LPVOID)lpAccountName,
378                              (wcslen(lpAccountName) + 1) * sizeof(WCHAR));
379     if (!NT_SUCCESS(Status))
380         goto done;
381 
382     Status = SampRegSetValue(hAccountKey,
383                              L"FullName",
384                              REG_SZ,
385                              (LPVOID)lpEmptyString,
386                              sizeof(WCHAR));
387     if (!NT_SUCCESS(Status))
388         goto done;
389 
390     Status = SampRegSetValue(hAccountKey,
391                              L"HomeDirectory",
392                              REG_SZ,
393                              (LPVOID)lpEmptyString,
394                              sizeof(WCHAR));
395     if (!NT_SUCCESS(Status))
396         goto done;
397 
398     Status = SampRegSetValue(hAccountKey,
399                              L"HomeDirectoryDrive",
400                              REG_SZ,
401                              (LPVOID)lpEmptyString,
402                              sizeof(WCHAR));
403     if (!NT_SUCCESS(Status))
404         goto done;
405 
406     Status = SampRegSetValue(hAccountKey,
407                              L"ScriptPath",
408                              REG_SZ,
409                              (LPVOID)lpEmptyString,
410                              sizeof(WCHAR));
411     if (!NT_SUCCESS(Status))
412         goto done;
413 
414     Status = SampRegSetValue(hAccountKey,
415                              L"ProfilePath",
416                              REG_SZ,
417                              (LPVOID)lpEmptyString,
418                              sizeof(WCHAR));
419     if (!NT_SUCCESS(Status))
420         goto done;
421 
422     Status = SampRegSetValue(hAccountKey,
423                              L"AdminComment",
424                              REG_SZ,
425                              (LPVOID)lpComment,
426                              (wcslen(lpComment) + 1) * sizeof(WCHAR));
427     if (!NT_SUCCESS(Status))
428         goto done;
429 
430     Status = SampRegSetValue(hAccountKey,
431                              L"UserComment",
432                              REG_SZ,
433                              (LPVOID)lpEmptyString,
434                              sizeof(WCHAR));
435     if (!NT_SUCCESS(Status))
436         goto done;
437 
438     Status = SampRegSetValue(hAccountKey,
439                              L"WorkStations",
440                              REG_SZ,
441                              (LPVOID)lpEmptyString,
442                              sizeof(WCHAR));
443     if (!NT_SUCCESS(Status))
444         goto done;
445 
446     Status = SampRegSetValue(hAccountKey,
447                              L"Parameters",
448                              REG_SZ,
449                              (LPVOID)lpEmptyString,
450                              sizeof(WCHAR));
451     if (!NT_SUCCESS(Status))
452         goto done;
453 
454     /* Set LogonHours attribute*/
455     *((PUSHORT)LogonHours) = 168;
456     memset(&(LogonHours[2]), 0xff, 21);
457 
458     Status = SampRegSetValue(hAccountKey,
459                              L"LogonHours",
460                              REG_BINARY,
461                              (LPVOID)LogonHours,
462                              sizeof(LogonHours));
463     if (!NT_SUCCESS(Status))
464         goto done;
465 
466     /* Set Groups attribute*/
467     GroupMembership.RelativeId = DOMAIN_GROUP_RID_USERS;
468     GroupMembership.Attributes = SE_GROUP_MANDATORY |
469                                  SE_GROUP_ENABLED |
470                                  SE_GROUP_ENABLED_BY_DEFAULT;
471 
472     Status = SampRegSetValue(hAccountKey,
473                              L"Groups",
474                              REG_BINARY,
475                              (LPVOID)&GroupMembership,
476                              sizeof(GROUP_MEMBERSHIP));
477     if (!NT_SUCCESS(Status))
478         goto done;
479 
480     /* Set LMPwd attribute*/
481     Status = SampRegSetValue(hAccountKey,
482                              L"LMPwd",
483                              REG_BINARY,
484                              (LPVOID)&EmptyLmHash,
485                              sizeof(ENCRYPTED_LM_OWF_PASSWORD));
486     if (!NT_SUCCESS(Status))
487         goto done;
488 
489     /* Set NTPwd attribute*/
490     Status = SampRegSetValue(hAccountKey,
491                              L"NTPwd",
492                              REG_BINARY,
493                              (LPVOID)&EmptyNtHash,
494                              sizeof(ENCRYPTED_NT_OWF_PASSWORD));
495     if (!NT_SUCCESS(Status))
496         goto done;
497 
498     /* Set LMPwdHistory attribute*/
499     Status = SampRegSetValue(hAccountKey,
500                              L"LMPwdHistory",
501                              REG_BINARY,
502                              NULL,
503                              0);
504     if (!NT_SUCCESS(Status))
505         goto done;
506 
507     /* Set NTPwdHistory attribute*/
508     Status = SampRegSetValue(hAccountKey,
509                              L"NTPwdHistory",
510                              REG_BINARY,
511                              NULL,
512                              0);
513     if (!NT_SUCCESS(Status))
514         goto done;
515 
516     /* FIXME: Set SecDesc attribute*/
517 
518 
519     Status = SampRegOpenKey(hDomainKey,
520                             L"Users\\Names",
521                             KEY_ALL_ACCESS,
522                             &hNamesKey);
523     if (!NT_SUCCESS(Status))
524         goto done;
525 
526     Status = SampRegSetValue(hNamesKey,
527                             lpAccountName,
528                             REG_DWORD,
529                             (LPVOID)&ulRelativeId,
530                             sizeof(ULONG));
531 
532 done:
533     if (hNamesKey != NULL)
534         SampRegCloseKey(hNamesKey);
535 
536     if (hAccountKey != NULL)
537     {
538         SampRegCloseKey(hAccountKey);
539 
540         if (!NT_SUCCESS(Status))
541             SampRegDeleteKey(hDomainKey,
542                              szAccountKeyName);
543     }
544 
545     return Status;
546 }
547 
548 
549 static
550 NTSTATUS
551 SampSetupCreateDomain(IN HANDLE hServerKey,
552                       IN LPCWSTR lpKeyName,
553                       IN LPCWSTR lpDomainName,
554                       IN PSID lpDomainSid,
555                       IN BOOLEAN bBuiltinDomain,
556                       OUT HANDLE *lpDomainKey)
557 {
558     SAM_DOMAIN_FIXED_DATA FixedData;
559     WCHAR szDomainKeyName[32];
560     LPWSTR lpEmptyString = L"";
561     HANDLE hDomainKey = NULL;
562     HANDLE hAliasesKey = NULL;
563     HANDLE hGroupsKey = NULL;
564     HANDLE hUsersKey = NULL;
565     HANDLE hNamesKey = NULL;
566     PSECURITY_DESCRIPTOR Sd = NULL;
567     ULONG SdSize = 0;
568     NTSTATUS Status;
569 
570     if (lpDomainKey != NULL)
571         *lpDomainKey = NULL;
572 
573     /* Initialize the fixed domain data */
574     memset(&FixedData, 0, sizeof(SAM_DOMAIN_FIXED_DATA));
575     FixedData.Version = 1;
576     NtQuerySystemTime(&FixedData.CreationTime);
577     FixedData.DomainModifiedCount.QuadPart = 0;
578     FixedData.MaxPasswordAge.QuadPart = -(6LL * 7LL * 24LL * 60LL * 60LL * TICKS_PER_SECOND); /* 6 weeks */
579     FixedData.MinPasswordAge.QuadPart = 0;                                                    /* right now */
580     FixedData.ForceLogoff.QuadPart = LLONG_MAX;                                               /* very far in the future aka never */
581     FixedData.LockoutDuration.QuadPart = -(30LL * 60LL * TICKS_PER_SECOND);                   /* 30 minutes */
582     FixedData.LockoutObservationWindow.QuadPart = -(30LL * 60LL * TICKS_PER_SECOND);          /* 30 minutes */
583     FixedData.ModifiedCountAtLastPromotion.QuadPart = 0;
584     FixedData.NextRid = 1000;
585     FixedData.PasswordProperties = 0;
586     FixedData.MinPasswordLength = 0;
587     FixedData.PasswordHistoryLength = 0;
588     FixedData.LockoutThreshold = 0;
589     FixedData.DomainServerState = DomainServerEnabled;
590     FixedData.DomainServerRole = DomainServerRolePrimary;
591     FixedData.UasCompatibilityRequired = TRUE;
592 
593     wcscpy(szDomainKeyName, L"Domains\\");
594     wcscat(szDomainKeyName, lpKeyName);
595 
596     Status = SampRegCreateKey(hServerKey,
597                               szDomainKeyName,
598                               KEY_ALL_ACCESS,
599                               &hDomainKey);
600     if (!NT_SUCCESS(Status))
601         return Status;
602 
603     /* Set the fixed data value */
604     Status = SampRegSetValue(hDomainKey,
605                              L"F",
606                              REG_BINARY,
607                              (LPVOID)&FixedData,
608                              sizeof(SAM_DOMAIN_FIXED_DATA));
609     if (!NT_SUCCESS(Status))
610         goto done;
611 
612     if (lpDomainSid != NULL)
613     {
614         Status = SampRegSetValue(hDomainKey,
615                                  L"Name",
616                                  REG_SZ,
617                                  (LPVOID)lpDomainName,
618                                  (wcslen(lpDomainName) + 1) * sizeof(WCHAR));
619         if (!NT_SUCCESS(Status))
620             goto done;
621 
622         Status = SampRegSetValue(hDomainKey,
623                                  L"SID",
624                                  REG_BINARY,
625                                  (LPVOID)lpDomainSid,
626                                  RtlLengthSid(lpDomainSid));
627         if (!NT_SUCCESS(Status))
628             goto done;
629     }
630 
631     Status = SampRegSetValue(hDomainKey,
632                              L"OemInformation",
633                              REG_SZ,
634                              (LPVOID)lpEmptyString,
635                              sizeof(WCHAR));
636     if (!NT_SUCCESS(Status))
637         goto done;
638 
639     Status = SampRegSetValue(hDomainKey,
640                              L"ReplicaSourceNodeName",
641                              REG_SZ,
642                              (LPVOID)lpEmptyString,
643                              sizeof(WCHAR));
644     if (!NT_SUCCESS(Status))
645         goto done;
646 
647     /* Create the Alias container */
648     Status = SampRegCreateKey(hDomainKey,
649                               L"Aliases",
650                               KEY_ALL_ACCESS,
651                               &hAliasesKey);
652     if (!NT_SUCCESS(Status))
653         goto done;
654 
655     Status = SampRegCreateKey(hAliasesKey,
656                               L"Names",
657                               KEY_ALL_ACCESS,
658                               &hNamesKey);
659     if (!NT_SUCCESS(Status))
660         goto done;
661 
662     SampRegCloseKey(hNamesKey);
663 
664     /* Create the Groups container */
665     Status = SampRegCreateKey(hDomainKey,
666                               L"Groups",
667                               KEY_ALL_ACCESS,
668                               &hGroupsKey);
669     if (!NT_SUCCESS(Status))
670         goto done;
671 
672     Status = SampRegCreateKey(hGroupsKey,
673                               L"Names",
674                               KEY_ALL_ACCESS,
675                               &hNamesKey);
676     if (!NT_SUCCESS(Status))
677         goto done;
678 
679     SampRegCloseKey(hNamesKey);
680 
681     /* Create the Users container */
682     Status = SampRegCreateKey(hDomainKey,
683                               L"Users",
684                               KEY_ALL_ACCESS,
685                               &hUsersKey);
686     if (!NT_SUCCESS(Status))
687         goto done;
688 
689     Status = SampRegCreateKey(hUsersKey,
690                               L"Names",
691                               KEY_ALL_ACCESS,
692                               &hNamesKey);
693     if (!NT_SUCCESS(Status))
694         goto done;
695 
696     /* Create the server SD */
697     if (bBuiltinDomain == TRUE)
698         Status = SampCreateBuiltinDomainSD(&Sd,
699                                            &SdSize);
700     else
701         Status = SampCreateAccountDomainSD(&Sd,
702                                            &SdSize);
703 
704     if (!NT_SUCCESS(Status))
705         goto done;
706 
707     /* Set SecDesc attribute*/
708     Status = SampRegSetValue(hServerKey,
709                              L"SecDesc",
710                              REG_BINARY,
711                              Sd,
712                              SdSize);
713     if (!NT_SUCCESS(Status))
714         goto done;
715 
716     SampRegCloseKey(hNamesKey);
717 
718     if (lpDomainKey != NULL)
719         *lpDomainKey = hDomainKey;
720 
721 done:
722     if (Sd != NULL)
723         RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
724 
725     if (hAliasesKey != NULL)
726         SampRegCloseKey(hAliasesKey);
727 
728     if (hGroupsKey != NULL)
729         SampRegCloseKey(hGroupsKey);
730 
731     if (hUsersKey != NULL)
732         SampRegCloseKey(hUsersKey);
733 
734     if (!NT_SUCCESS(Status))
735     {
736         if (hDomainKey != NULL)
737             SampRegCloseKey(hDomainKey);
738     }
739 
740     return Status;
741 }
742 
743 
744 static
745 NTSTATUS
746 SampSetupCreateServer(IN HANDLE hSamKey,
747                       OUT HANDLE *lpServerKey)
748 {
749     HANDLE hServerKey = NULL;
750     HANDLE hDomainsKey = NULL;
751     PSECURITY_DESCRIPTOR Sd = NULL;
752     ULONG SdSize = 0;
753     NTSTATUS Status;
754 
755     Status = SampRegCreateKey(hSamKey,
756                               L"SAM",
757                               KEY_ALL_ACCESS,
758                               &hServerKey);
759     if (!NT_SUCCESS(Status))
760         return Status;
761 
762     Status = SampRegCreateKey(hServerKey,
763                               L"Domains",
764                               KEY_ALL_ACCESS,
765                               &hDomainsKey);
766     if (!NT_SUCCESS(Status))
767         goto done;
768 
769     /* Create the server SD */
770     Status = SampCreateServerSD(&Sd,
771                                 &SdSize);
772     if (!NT_SUCCESS(Status))
773         goto done;
774 
775     /* Set SecDesc attribute*/
776     Status = SampRegSetValue(hServerKey,
777                              L"SecDesc",
778                              REG_BINARY,
779                              Sd,
780                              SdSize);
781     if (!NT_SUCCESS(Status))
782         goto done;
783 
784     SampRegCloseKey(hDomainsKey);
785 
786     *lpServerKey = hServerKey;
787 
788 done:
789     if (Sd != NULL)
790         RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
791 
792     return Status;
793 }
794 
795 
796 NTSTATUS
797 SampGetAccountDomainInfo(PPOLICY_ACCOUNT_DOMAIN_INFO *AccountDomainInfo)
798 {
799     LSA_OBJECT_ATTRIBUTES ObjectAttributes;
800     LSA_HANDLE PolicyHandle;
801     NTSTATUS Status;
802 
803     TRACE("SampGetAccountDomainInfo\n");
804 
805     memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES));
806     ObjectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
807 
808     Status = LsaOpenPolicy(NULL,
809                            &ObjectAttributes,
810                            POLICY_VIEW_LOCAL_INFORMATION,
811                            &PolicyHandle);
812     if (Status != STATUS_SUCCESS)
813     {
814         ERR("LsaOpenPolicy failed (Status: 0x%08lx)\n", Status);
815         return Status;
816     }
817 
818     Status = LsaQueryInformationPolicy(PolicyHandle,
819                                        PolicyAccountDomainInformation,
820                                        (PVOID *)AccountDomainInfo);
821 
822     LsaClose(PolicyHandle);
823 
824     return Status;
825 }
826 
827 
828 BOOL
829 SampInitializeSAM(VOID)
830 {
831     PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo = NULL;
832     HANDLE hSamKey = NULL;
833     HANDLE hServerKey = NULL;
834     HANDLE hBuiltinDomainKey = NULL;
835     HANDLE hAccountDomainKey = NULL;
836     PSID pBuiltinSid = NULL;
837     BOOL bResult = TRUE;
838     PSID pSid;
839     HINSTANCE hInstance;
840     WCHAR szComment[256];
841     WCHAR szName[80];
842     NTSTATUS Status;
843 
844     TRACE("SampInitializeSAM() called\n");
845 
846     hInstance = GetModuleHandleW(L"samsrv.dll");
847 
848     /* Open the SAM key */
849     Status = SampRegOpenKey(NULL,
850                             L"\\Registry\\Machine\\SAM",
851                             KEY_READ | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS,
852                             &hSamKey);
853     if (!NT_SUCCESS(Status))
854     {
855         ERR("Failed to open the SAM key (Status: 0x%08lx)\n", Status);
856         return FALSE;
857     }
858 
859     /* Create the SAM Server object */
860     Status = SampSetupCreateServer(hSamKey,
861                                    &hServerKey);
862     if (!NT_SUCCESS(Status))
863     {
864         bResult = FALSE;
865         goto done;
866     }
867 
868     /* Create and initialize the Builtin Domain SID */
869     pBuiltinSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, RtlLengthRequiredSid(1));
870     if (pBuiltinSid == NULL)
871     {
872         ERR("Failed to alloacte the Builtin Domain SID\n");
873         bResult = FALSE;
874         goto done;
875     }
876 
877     RtlInitializeSid(pBuiltinSid, &SecurityNtAuthority, 1);
878     *(RtlSubAuthoritySid(pBuiltinSid, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
879 
880     /* Get account domain information */
881     Status = SampGetAccountDomainInfo(&AccountDomainInfo);
882     if (!NT_SUCCESS(Status))
883     {
884         ERR("SampGetAccountDomainInfo failed (Status %08lx)\n", Status);
885         bResult = FALSE;
886         goto done;
887     }
888 
889     SampLoadString(hInstance, IDS_DOMAIN_BUILTIN_NAME, szName, 80);
890 
891     /* Create the Builtin domain */
892     Status = SampSetupCreateDomain(hServerKey,
893                                    L"Builtin",
894                                    szName,
895                                    pBuiltinSid,
896                                    TRUE,
897                                    &hBuiltinDomainKey);
898     if (!NT_SUCCESS(Status))
899     {
900         bResult = FALSE;
901         goto done;
902     }
903 
904     SampLoadString(hInstance, IDS_ALIAS_ADMINISTRATORS_NAME, szName, 80);
905     SampLoadString(hInstance, IDS_ALIAS_ADMINISTRATORS_COMMENT, szComment, 256);
906 
907         SampSetupCreateAliasAccount(hBuiltinDomainKey,
908                                     szName,
909                                     szComment,
910                                     DOMAIN_ALIAS_RID_ADMINS);
911 
912         SampLoadString(hInstance, IDS_ALIAS_USERS_NAME, szName, 80);
913         SampLoadString(hInstance, IDS_ALIAS_USERS_COMMENT, szComment, 256);
914 
915         SampSetupCreateAliasAccount(hBuiltinDomainKey,
916                                     szName,
917                                     szComment,
918                                     DOMAIN_ALIAS_RID_USERS);
919 
920         SampLoadString(hInstance, IDS_ALIAS_GUESTS_NAME, szName, 80);
921         SampLoadString(hInstance, IDS_ALIAS_GUESTS_COMMENT, szComment, 256);
922 
923         SampSetupCreateAliasAccount(hBuiltinDomainKey,
924                                     szName,
925                                     szComment,
926                                     DOMAIN_ALIAS_RID_GUESTS);
927 
928         SampLoadString(hInstance, IDS_ALIAS_POWER_USERS_NAME, szName, 80);
929         SampLoadString(hInstance, IDS_ALIAS_POWER_USERS_COMMENT, szComment, 256);
930 
931         SampSetupCreateAliasAccount(hBuiltinDomainKey,
932                                     szName,
933                                     szComment,
934                                     DOMAIN_ALIAS_RID_POWER_USERS);
935 
936         /* Add the Administrator user to the Administrators alias */
937         pSid = AppendRidToSid(AccountDomainInfo->DomainSid,
938                               DOMAIN_USER_RID_ADMIN);
939         if (pSid != NULL)
940         {
941             SampSetupAddMemberToAlias(hBuiltinDomainKey,
942                                       DOMAIN_ALIAS_RID_ADMINS,
943                                       pSid);
944 
945             RtlFreeHeap(RtlGetProcessHeap(), 0, pSid);
946         }
947 
948         /* Add the Guest user to the Guests alias */
949         pSid = AppendRidToSid(AccountDomainInfo->DomainSid,
950                               DOMAIN_USER_RID_GUEST);
951         if (pSid != NULL)
952         {
953             SampSetupAddMemberToAlias(hBuiltinDomainKey,
954                                       DOMAIN_ALIAS_RID_GUESTS,
955                                       pSid);
956 
957             RtlFreeHeap(RtlGetProcessHeap(), 0, pSid);
958         }
959 
960 
961     /* Create the Account domain */
962     Status = SampSetupCreateDomain(hServerKey,
963                                    L"Account",
964                                    L"",
965                                    AccountDomainInfo->DomainSid,
966                                    FALSE,
967                                    &hAccountDomainKey);
968     if (!NT_SUCCESS(Status))
969     {
970         bResult = FALSE;
971         goto done;
972     }
973 
974         SampLoadString(hInstance, IDS_GROUP_NONE_NAME, szName, 80);
975         SampLoadString(hInstance, IDS_GROUP_NONE_COMMENT, szComment, 256);
976 
977         SampSetupCreateGroupAccount(hAccountDomainKey,
978                                     szName,
979                                     szComment,
980                                     DOMAIN_GROUP_RID_USERS);
981 
982         SampLoadString(hInstance, IDS_USER_ADMINISTRATOR_NAME, szName, 80);
983         SampLoadString(hInstance, IDS_USER_ADMINISTRATOR_COMMENT, szComment, 256);
984 
985         SampSetupCreateUserAccount(hAccountDomainKey,
986                                    szName,
987                                    szComment,
988                                    DOMAIN_USER_RID_ADMIN,
989                                    USER_DONT_EXPIRE_PASSWORD | USER_NORMAL_ACCOUNT);
990 
991         SampSetupAddMemberToGroup(hAccountDomainKey,
992                                   DOMAIN_GROUP_RID_USERS,
993                                   DOMAIN_USER_RID_ADMIN);
994 
995         SampLoadString(hInstance, IDS_USER_GUEST_NAME, szName, 80);
996         SampLoadString(hInstance, IDS_USER_GUEST_COMMENT, szComment, 256);
997 
998         SampSetupCreateUserAccount(hAccountDomainKey,
999                                    szName,
1000                                    szComment,
1001                                    DOMAIN_USER_RID_GUEST,
1002                                    USER_ACCOUNT_DISABLED | USER_DONT_EXPIRE_PASSWORD | USER_NORMAL_ACCOUNT);
1003 
1004         SampSetupAddMemberToGroup(hAccountDomainKey,
1005                                   DOMAIN_GROUP_RID_USERS,
1006                                   DOMAIN_USER_RID_GUEST);
1007 
1008 done:
1009     if (AccountDomainInfo)
1010         LsaFreeMemory(AccountDomainInfo);
1011 
1012     if (pBuiltinSid)
1013         RtlFreeHeap(RtlGetProcessHeap(), 0, pBuiltinSid);
1014 
1015     if (hAccountDomainKey != NULL)
1016         SampRegCloseKey(hAccountDomainKey);
1017 
1018     if (hBuiltinDomainKey != NULL)
1019         SampRegCloseKey(hBuiltinDomainKey);
1020 
1021     if (hServerKey != NULL)
1022         SampRegCloseKey(hServerKey);
1023 
1024     if (hSamKey != NULL)
1025         SampRegCloseKey(hSamKey);
1026 
1027     TRACE("SampInitializeSAM() done\n");
1028 
1029     return bResult;
1030 }
1031