[SAMSRV]
[reactos.git] / reactos / 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 DWORD dwDisposition;
228 WCHAR szAccountKeyName[32];
229 HKEY hAccountKey = NULL;
230 HKEY hNamesKey = NULL;
231
232 /* Initialize fixed user data */
233 memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA));
234 FixedUserData.Version = 1;
235
236 FixedUserData.UserId = ulRelativeId;
237
238 swprintf(szAccountKeyName, L"Users\\%08lX", ulRelativeId);
239
240 if (!RegCreateKeyExW(hDomainKey,
241 szAccountKeyName,
242 0,
243 NULL,
244 REG_OPTION_NON_VOLATILE,
245 KEY_ALL_ACCESS,
246 NULL,
247 &hAccountKey,
248 &dwDisposition))
249 {
250 RegSetValueEx(hAccountKey,
251 L"F",
252 0,
253 REG_BINARY,
254 (LPVOID)&FixedUserData,
255 sizeof(SAM_USER_FIXED_DATA));
256
257 RegSetValueEx(hAccountKey,
258 L"Name",
259 0,
260 REG_SZ,
261 (LPVOID)lpAccountName,
262 (wcslen(lpAccountName) + 1) * sizeof(WCHAR));
263
264 RegCloseKey(hAccountKey);
265 }
266
267 if (!RegOpenKeyExW(hDomainKey,
268 L"Users\\Names",
269 0,
270 KEY_ALL_ACCESS,
271 &hNamesKey))
272 {
273 RegSetValueEx(hNamesKey,
274 lpAccountName,
275 0,
276 REG_DWORD,
277 (LPVOID)&ulRelativeId,
278 sizeof(ULONG));
279
280 RegCloseKey(hNamesKey);
281 }
282
283 return TRUE;
284 }
285
286
287 static BOOL
288 SampCreateDomain(IN HKEY hDomainsKey,
289 IN LPCWSTR lpKeyName,
290 IN LPCWSTR lpDomainName,
291 IN PSID lpDomainSid,
292 OUT PHKEY lpDomainKey)
293 {
294 SAM_DOMAIN_FIXED_DATA FixedData;
295 LPWSTR lpEmptyString = L"";
296 DWORD dwDisposition;
297 HKEY hDomainKey = NULL;
298 HKEY hAliasesKey = NULL;
299 HKEY hGroupsKey = NULL;
300 HKEY hUsersKey = NULL;
301 HKEY hNamesKey = NULL;
302
303 if (lpDomainKey != NULL)
304 *lpDomainKey = NULL;
305
306 /* Initialize the fixed domain data */
307 memset(&FixedData, 0, sizeof(SAM_DOMAIN_FIXED_DATA));
308 FixedData.Version = 1;
309 NtQuerySystemTime(&FixedData.CreationTime);
310 FixedData.DomainModifiedCount.QuadPart = 0;
311 // FixedData.MaxPasswordAge // 6 Weeks
312 FixedData.MinPasswordAge.QuadPart = 0; // Now
313 // FixedData.ForceLogoff
314 // FixedData.LockoutDuration // 30 minutes
315 // FixedData.LockoutObservationWindow // 30 minutes
316 FixedData.ModifiedCountAtLastPromotion.QuadPart = 0;
317 FixedData.NextRid = 1000;
318 FixedData.PasswordProperties = 0;
319 FixedData.MinPasswordLength = 0;
320 FixedData.PasswordHistoryLength = 0;
321 FixedData.LockoutThreshold = 0;
322 FixedData.DomainServerState = DomainServerEnabled;
323 FixedData.DomainServerRole = DomainServerRolePrimary;
324 FixedData.UasCompatibilityRequired = TRUE;
325
326 if (RegCreateKeyExW(hDomainsKey,
327 lpKeyName,
328 0,
329 NULL,
330 REG_OPTION_NON_VOLATILE,
331 KEY_ALL_ACCESS,
332 NULL,
333 &hDomainKey,
334 &dwDisposition))
335 return FALSE;
336
337 /* Set the fixed data value */
338 if (RegSetValueEx(hDomainKey,
339 L"F",
340 0,
341 REG_BINARY,
342 (LPVOID)&FixedData,
343 sizeof(SAM_DOMAIN_FIXED_DATA)))
344 return FALSE;
345
346 if (lpDomainSid != NULL)
347 {
348 RegSetValueEx(hDomainKey,
349 L"Name",
350 0,
351 REG_SZ,
352 (LPVOID)lpDomainName,
353 (wcslen(lpDomainName) + 1) * sizeof(WCHAR));
354
355 RegSetValueEx(hDomainKey,
356 L"SID",
357 0,
358 REG_BINARY,
359 (LPVOID)lpDomainSid,
360 RtlLengthSid(lpDomainSid));
361 }
362
363 RegSetValueEx(hDomainKey,
364 L"OemInformation",
365 0,
366 REG_SZ,
367 (LPVOID)lpEmptyString,
368 sizeof(WCHAR));
369
370 RegSetValueEx(hDomainKey,
371 L"ReplicaSourceNodeName",
372 0,
373 REG_SZ,
374 (LPVOID)lpEmptyString,
375 sizeof(WCHAR));
376
377 /* Create the Alias container */
378 if (!RegCreateKeyExW(hDomainKey,
379 L"Aliases",
380 0,
381 NULL,
382 REG_OPTION_NON_VOLATILE,
383 KEY_ALL_ACCESS,
384 NULL,
385 &hAliasesKey,
386 &dwDisposition))
387 {
388 if (!RegCreateKeyExW(hAliasesKey,
389 L"Names",
390 0,
391 NULL,
392 REG_OPTION_NON_VOLATILE,
393 KEY_ALL_ACCESS,
394 NULL,
395 &hNamesKey,
396 &dwDisposition))
397 RegCloseKey(hNamesKey);
398
399 RegCloseKey(hAliasesKey);
400 }
401
402 /* Create the Groups container */
403 if (!RegCreateKeyExW(hDomainKey,
404 L"Groups",
405 0,
406 NULL,
407 REG_OPTION_NON_VOLATILE,
408 KEY_ALL_ACCESS,
409 NULL,
410 &hGroupsKey,
411 &dwDisposition))
412 {
413 if (!RegCreateKeyExW(hGroupsKey,
414 L"Names",
415 0,
416 NULL,
417 REG_OPTION_NON_VOLATILE,
418 KEY_ALL_ACCESS,
419 NULL,
420 &hNamesKey,
421 &dwDisposition))
422 RegCloseKey(hNamesKey);
423
424 RegCloseKey(hGroupsKey);
425 }
426
427
428 /* Create the Users container */
429 if (!RegCreateKeyExW(hDomainKey,
430 L"Users",
431 0,
432 NULL,
433 REG_OPTION_NON_VOLATILE,
434 KEY_ALL_ACCESS,
435 NULL,
436 &hUsersKey,
437 &dwDisposition))
438 {
439 if (!RegCreateKeyExW(hUsersKey,
440 L"Names",
441 0,
442 NULL,
443 REG_OPTION_NON_VOLATILE,
444 KEY_ALL_ACCESS,
445 NULL,
446 &hNamesKey,
447 &dwDisposition))
448 RegCloseKey(hNamesKey);
449
450 RegCloseKey(hUsersKey);
451 }
452
453 if (lpDomainKey != NULL)
454 *lpDomainKey = hDomainKey;
455
456 return TRUE;
457 }
458
459
460 NTSTATUS
461 SampGetAccountDomainInfo(PPOLICY_ACCOUNT_DOMAIN_INFO *AccountDomainInfo)
462 {
463 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
464 LSA_HANDLE PolicyHandle;
465 NTSTATUS Status;
466
467 TRACE("SampGetAccountDomainInfo\n");
468
469 memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES));
470 ObjectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
471
472 Status = LsaOpenPolicy(NULL,
473 &ObjectAttributes,
474 POLICY_TRUST_ADMIN,
475 &PolicyHandle);
476 if (Status != STATUS_SUCCESS)
477 {
478 ERR("LsaOpenPolicy failed (Status: 0x%08lx)\n", Status);
479 return Status;
480 }
481
482 Status = LsaQueryInformationPolicy(PolicyHandle,
483 PolicyAccountDomainInformation,
484 (PVOID *)AccountDomainInfo);
485
486 LsaClose(PolicyHandle);
487
488 return Status;
489 }
490
491
492 BOOL
493 SampInitializeSAM(VOID)
494 {
495 PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo = NULL;
496 DWORD dwDisposition;
497 HKEY hSamKey = NULL;
498 HKEY hDomainsKey = NULL;
499 HKEY hDomainKey = NULL;
500 PSID pBuiltinSid = NULL;
501 BOOL bResult = TRUE;
502 PSID pSid;
503 NTSTATUS Status;
504
505 TRACE("SampInitializeSAM() called\n");
506
507 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
508 L"SAM\\SAM",
509 0,
510 NULL,
511 REG_OPTION_NON_VOLATILE,
512 KEY_ALL_ACCESS,
513 NULL,
514 &hSamKey,
515 &dwDisposition))
516 {
517 ERR("Failed to create 'Sam' key! (Error %lu)\n", GetLastError());
518 return FALSE;
519 }
520
521 if (RegCreateKeyExW(hSamKey,
522 L"Domains",
523 0,
524 NULL,
525 REG_OPTION_NON_VOLATILE,
526 KEY_ALL_ACCESS,
527 NULL,
528 &hDomainsKey,
529 &dwDisposition))
530 {
531 ERR("Failed to create 'Domains' key! (Error %lu)\n", GetLastError());
532 bResult = FALSE;
533 goto done;
534 }
535
536 RegCloseKey(hSamKey);
537 hSamKey = NULL;
538
539 /* Create and initialize the Builtin Domain SID */
540 pBuiltinSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, RtlLengthRequiredSid(1));
541 if (pBuiltinSid == NULL)
542 {
543 ERR("Failed to alloacte the Builtin Domain SID\n");
544 bResult = FALSE;
545 goto done;
546 }
547
548 RtlInitializeSid(pBuiltinSid, &SecurityNtAuthority, 1);
549 *(RtlSubAuthoritySid(pBuiltinSid, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
550
551 /* Get account domain information */
552 Status = SampGetAccountDomainInfo(&AccountDomainInfo);
553 if (!NT_SUCCESS(Status))
554 {
555 ERR("SampGetAccountDomainInfo failed (Status %08lx)\n", Status);
556 bResult = FALSE;
557 goto done;
558 }
559
560 /* Create the Builtin domain */
561 if (SampCreateDomain(hDomainsKey,
562 L"Builtin",
563 L"Builtin",
564 pBuiltinSid,
565 &hDomainKey))
566 {
567 SampCreateAliasAccount(hDomainKey,
568 L"Administrators",
569 L"Testabc1234567890",
570 DOMAIN_ALIAS_RID_ADMINS);
571
572 SampCreateAliasAccount(hDomainKey,
573 L"Users",
574 L"Users Group",
575 DOMAIN_ALIAS_RID_USERS);
576
577 SampCreateAliasAccount(hDomainKey,
578 L"Guests",
579 L"Guests Group",
580 DOMAIN_ALIAS_RID_GUESTS);
581
582 SampCreateAliasAccount(hDomainKey,
583 L"Power Users",
584 L"Power Users Group",
585 DOMAIN_ALIAS_RID_POWER_USERS);
586
587
588 pSid = AppendRidToSid(AccountDomainInfo->DomainSid,
589 DOMAIN_USER_RID_ADMIN);
590 if (pSid != NULL)
591 {
592 SampAddMemberToAlias(hDomainKey,
593 DOMAIN_ALIAS_RID_ADMINS,
594 pSid);
595
596 RtlFreeHeap(RtlGetProcessHeap(), 0, pSid);
597 }
598
599
600 RegCloseKey(hDomainKey);
601 }
602
603 /* Create the Account domain */
604 if (SampCreateDomain(hDomainsKey,
605 L"Account",
606 L"",
607 AccountDomainInfo->DomainSid,
608 &hDomainKey))
609 {
610 SampCreateUserAccount(hDomainKey,
611 L"Administrator",
612 DOMAIN_USER_RID_ADMIN);
613
614 SampCreateUserAccount(hDomainKey,
615 L"Guest",
616 DOMAIN_USER_RID_GUEST);
617
618 RegCloseKey(hDomainKey);
619 }
620
621 done:
622 if (AccountDomainInfo)
623 LsaFreeMemory(AccountDomainInfo);
624
625 if (pBuiltinSid)
626 RtlFreeHeap(RtlGetProcessHeap(), 0, pBuiltinSid);
627
628 if (hDomainsKey)
629 RegCloseKey(hDomainsKey);
630
631 if (hSamKey)
632 RegCloseKey(hSamKey);
633
634 TRACE("SampInitializeSAM() done\n");
635
636 return bResult;
637 }