ReactOS 0.4.16-dev-320-g3bd9ddc
database.c
Go to the documentation of this file.
1/*
2 * PROJECT: Local Security Authority Server DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/samsrv/database.c
5 * PURPOSE: SAM object database
6 * COPYRIGHT: Copyright 2012 Eric Kohl
7 */
8
9#include "samsrv.h"
10
11#include <pseh/pseh2.h>
12
13/* GLOBALS *****************************************************************/
14
16
17
18/* FUNCTIONS ***************************************************************/
19
22{
24
25 TRACE("SampInitDatabase()\n");
26
28 L"\\Registry\\Machine\\SAM",
31 if (!NT_SUCCESS(Status))
32 {
33 ERR("Failed to open the SAM key (Status: 0x%08lx)\n", Status);
34 return Status;
35 }
36
37 TRACE("SampInitDatabase() done\n");
38
39 return STATUS_SUCCESS;
40}
41
42
45 IN LPWSTR ContainerName,
47 IN ULONG RelativeId,
50 OUT PSAM_DB_OBJECT *DbObject)
51{
53 HANDLE ParentKeyHandle;
54 HANDLE ContainerKeyHandle = NULL;
55 HANDLE ObjectKeyHandle = NULL;
56 HANDLE MembersKeyHandle = NULL;
58
59 if (DbObject == NULL)
61
62 *DbObject = NULL;
63
64 if (ParentObject == NULL)
65 ParentKeyHandle = SamKeyHandle;
66 else
67 ParentKeyHandle = ParentObject->KeyHandle;
68
69 if (ContainerName != NULL)
70 {
71 /* Open the container key */
72 Status = SampRegOpenKey(ParentKeyHandle,
73 ContainerName,
75 &ContainerKeyHandle);
76 if (!NT_SUCCESS(Status))
77 {
78 goto done;
79 }
80
81 /* Create the object key */
82 Status = SampRegCreateKey(ContainerKeyHandle,
85 &ObjectKeyHandle);
86 if (!NT_SUCCESS(Status))
87 {
88 goto done;
89 }
90
92 {
93 /* Create the object key */
94 Status = SampRegCreateKey(ContainerKeyHandle,
95 L"Members",
97 &MembersKeyHandle);
98 if (!NT_SUCCESS(Status))
99 {
100 goto done;
101 }
102 }
103 }
104 else
105 {
106 /* Create the object key */
107 Status = SampRegCreateKey(ParentKeyHandle,
110 &ObjectKeyHandle);
111 if (!NT_SUCCESS(Status))
112 {
113 goto done;
114 }
115 }
116
117 NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
119 sizeof(SAM_DB_OBJECT));
120 if (NewObject == NULL)
121 {
123 goto done;
124 }
125
126 NewObject->Name = RtlAllocateHeap(RtlGetProcessHeap(),
127 0,
128 (wcslen(ObjectName) + 1) * sizeof(WCHAR));
129 if (NewObject->Name == NULL)
130 {
132 goto done;
133 }
134
136
137 NewObject->Signature = SAMP_DB_SIGNATURE;
138 NewObject->RefCount = 1;
139 NewObject->ObjectType = ObjectType;
140 NewObject->Access = DesiredAccess;
141 NewObject->KeyHandle = ObjectKeyHandle;
142 NewObject->MembersKeyHandle = MembersKeyHandle;
143 NewObject->RelativeId = RelativeId;
144 NewObject->ParentObject = ParentObject;
145
146 if (ParentObject != NULL)
147 NewObject->Trusted = ParentObject->Trusted;
148
149 *DbObject = NewObject;
150
151done:
152 if (!NT_SUCCESS(Status))
153 {
154 if (NewObject != NULL)
155 {
156 if (NewObject->Name != NULL)
157 RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject->Name);
158
159 RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject);
160 }
161
162 SampRegCloseKey(&MembersKeyHandle);
163 SampRegCloseKey(&ObjectKeyHandle);
164 }
165
166 SampRegCloseKey(&ContainerKeyHandle);
167
168 return Status;
169}
170
171
174 IN LPWSTR ContainerName,
176 IN ULONG RelativeId,
179 OUT PSAM_DB_OBJECT *DbObject)
180{
182 HANDLE ParentKeyHandle;
183 HANDLE ContainerKeyHandle = NULL;
184 HANDLE ObjectKeyHandle = NULL;
185 HANDLE MembersKeyHandle = NULL;
187
188 if (DbObject == NULL)
190
191 *DbObject = NULL;
192
193 if (ParentObject == NULL)
194 ParentKeyHandle = SamKeyHandle;
195 else
196 ParentKeyHandle = ParentObject->KeyHandle;
197
198 if (ContainerName != NULL)
199 {
200 /* Open the container key */
201 Status = SampRegOpenKey(ParentKeyHandle,
202 ContainerName,
204 &ContainerKeyHandle);
205 if (!NT_SUCCESS(Status))
206 {
207 goto done;
208 }
209
210 /* Open the object key */
211 Status = SampRegOpenKey(ContainerKeyHandle,
214 &ObjectKeyHandle);
215 if (!NT_SUCCESS(Status))
216 {
217 goto done;
218 }
219
221 {
222 /* Open the object key */
223 Status = SampRegOpenKey(ContainerKeyHandle,
224 L"Members",
226 &MembersKeyHandle);
227 if (!NT_SUCCESS(Status))
228 {
229 goto done;
230 }
231 }
232 }
233 else
234 {
235 /* Open the object key */
236 Status = SampRegOpenKey(ParentKeyHandle,
239 &ObjectKeyHandle);
240 if (!NT_SUCCESS(Status))
241 {
242 goto done;
243 }
244 }
245
246 NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
248 sizeof(SAM_DB_OBJECT));
249 if (NewObject == NULL)
250 {
252 goto done;
253 }
254
255 NewObject->Name = RtlAllocateHeap(RtlGetProcessHeap(),
256 0,
257 (wcslen(ObjectName) + 1) * sizeof(WCHAR));
258 if (NewObject->Name == NULL)
259 {
261 goto done;
262 }
263
265 NewObject->Signature = SAMP_DB_SIGNATURE;
266 NewObject->RefCount = 1;
267 NewObject->ObjectType = ObjectType;
268 NewObject->Access = DesiredAccess;
269 NewObject->KeyHandle = ObjectKeyHandle;
270 NewObject->MembersKeyHandle = MembersKeyHandle;
271 NewObject->RelativeId = RelativeId;
272 NewObject->ParentObject = ParentObject;
273
274 if (ParentObject != NULL)
275 NewObject->Trusted = ParentObject->Trusted;
276
277 *DbObject = NewObject;
278
279done:
280 if (!NT_SUCCESS(Status))
281 {
282 if (NewObject != NULL)
283 {
284 if (NewObject->Name != NULL)
285 RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject->Name);
286
287 RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject);
288 }
289
290 SampRegCloseKey(&MembersKeyHandle);
291 SampRegCloseKey(&ObjectKeyHandle);
292 }
293
294 SampRegCloseKey(&ContainerKeyHandle);
295
296 return Status;
297}
298
299
304 PSAM_DB_OBJECT *DbObject)
305{
306 PSAM_DB_OBJECT LocalObject = (PSAM_DB_OBJECT)Handle;
307 BOOLEAN bValid = FALSE;
308
310 {
311 if (LocalObject->Signature == SAMP_DB_SIGNATURE)
312 {
313 if ((ObjectType == SamDbIgnoreObject) ||
314 (LocalObject->ObjectType == ObjectType))
315 bValid = TRUE;
316 }
317 }
319 {
320 bValid = FALSE;
321 }
322 _SEH2_END;
323
324 if (bValid == FALSE)
326
327 if (DesiredAccess != 0)
328 {
329 /* Check for granted access rights */
330 if ((LocalObject->Access & DesiredAccess) != DesiredAccess)
331 {
332 ERR("SampValidateDbObject access check failed %08lx %08lx\n",
333 LocalObject->Access, DesiredAccess);
335 }
336 }
337
338 if (DbObject != NULL)
339 *DbObject = LocalObject;
340
341 return STATUS_SUCCESS;
342}
343
344
347{
349
350 DbObject->RefCount--;
351
352 if (DbObject->RefCount > 0)
353 return STATUS_SUCCESS;
354
355 SampRegCloseKey(&DbObject->KeyHandle);
357
358 if (DbObject->Name != NULL)
359 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject->Name);
360
361 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
362
363 return Status;
364}
365
366
369{
370 LPCWSTR ContainerName;
371 LPWSTR AccountName = NULL;
372 HANDLE ContainerKey = NULL;
373 HANDLE NamesKey = NULL;
374 ULONG Length = 0;
376
377 TRACE("(%p)\n", DbObject);
378
379 /* Server and Domain objects cannot be deleted */
380 switch (DbObject->ObjectType)
381 {
382 case SamDbAliasObject:
383 ContainerName = L"Aliases";
384 break;
385
386 case SamDbGroupObject:
387 ContainerName = L"Groups";
388 break;
389
390 case SamDbUserObject:
391 ContainerName = L"Users";
392 break;
393
394 default:
396 }
397
398 /* Get the account name */
400 L"Name",
401 NULL,
402 NULL,
403 &Length);
405 {
406 TRACE("SampGetObjectAttribute failed (Status 0x%08lx)\n", Status);
407 goto done;
408 }
409
410 AccountName = RtlAllocateHeap(RtlGetProcessHeap(),
412 Length);
413 if (AccountName == NULL)
414 {
416 goto done;
417 }
418
420 L"Name",
421 NULL,
422 (PVOID)AccountName,
423 &Length);
424 if (!NT_SUCCESS(Status))
425 {
426 TRACE("SampGetObjectAttribute failed (Status 0x%08lx)\n", Status);
427 goto done;
428 }
429
430 SampRegCloseKey(&DbObject->KeyHandle);
431
432 if (DbObject->ObjectType == SamDbAliasObject)
433 {
435
436 SampRegDeleteKey(DbObject->KeyHandle,
437 L"Members");
438 }
439
440 /* Open the domain container key */
441 Status = SampRegOpenKey(DbObject->ParentObject->KeyHandle,
442 ContainerName,
444 &ContainerKey);
445 if (!NT_SUCCESS(Status))
446 {
447 TRACE("SampRegOpenKey failed (Status 0x%08lx)\n", Status);
448 goto done;
449 }
450
451 /* Open the Names key */
452 Status = SampRegOpenKey(ContainerKey,
453 L"Names",
455 &NamesKey);
456 if (!NT_SUCCESS(Status))
457 {
458 TRACE("SampRegOpenKey failed (Status 0x%08lx)\n", Status);
459 goto done;
460 }
461
462 /* Remove the account from the Names key */
463 Status = SampRegDeleteValue(NamesKey,
464 AccountName);
465 if (!NT_SUCCESS(Status))
466 {
467 TRACE("SampRegDeleteValue failed (Status 0x%08lx)\n", Status);
468 goto done;
469 }
470
471 /* Remove the account key from the container */
472 Status = SampRegDeleteKey(ContainerKey,
473 DbObject->Name);
474 if (!NT_SUCCESS(Status))
475 {
476 TRACE("SampRegDeleteKey failed (Status 0x%08lx)\n", Status);
477 goto done;
478 }
479
480 /* Release the database object name */
481 if (DbObject->Name != NULL)
482 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject->Name);
483
484 /* Release the database object */
485 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
486
488
489done:
490 SampRegCloseKey(&NamesKey);
491 SampRegCloseKey(&ContainerKey);
492
493 if (AccountName != NULL)
494 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountName);
495
496 return Status;
497}
498
499
502 LPWSTR AttributeName,
503 ULONG AttributeType,
505 ULONG AttributeSize)
506{
507 return SampRegSetValue(DbObject->KeyHandle,
508 AttributeName,
509 AttributeType,
511 AttributeSize);
512}
513
514
517 LPWSTR AttributeName,
518 PULONG AttributeType,
520 PULONG AttributeSize)
521{
522 return SampRegQueryValue(DbObject->KeyHandle,
523 AttributeName,
524 AttributeType,
526 AttributeSize);
527}
528
529
532 LPWSTR AttributeName,
534{
535 ULONG Length = 0;
537
539 AttributeName,
540 NULL,
541 NULL,
542 &Length);
544 {
545 TRACE("Status 0x%08lx\n", Status);
546 goto done;
547 }
548
549 if (Length == 0)
550 {
551 String->Length = 0;
552 String->MaximumLength = 0;
553 String->Buffer = NULL;
554
556 goto done;
557 }
558
559 String->Length = (USHORT)(Length - sizeof(WCHAR));
560 String->MaximumLength = (USHORT)Length;
562 if (String->Buffer == NULL)
563 {
565 goto done;
566 }
567
568 TRACE("Length: %lu\n", Length);
570 AttributeName,
571 NULL,
572 (PVOID)String->Buffer,
573 &Length);
574 if (!NT_SUCCESS(Status))
575 {
576 TRACE("Status 0x%08lx\n", Status);
577 goto done;
578 }
579
580done:
581 if (!NT_SUCCESS(Status))
582 {
583 if (String->Buffer != NULL)
584 {
585 midl_user_free(String->Buffer);
586 String->Buffer = NULL;
587 }
588 }
589
590 return Status;
591}
592
593
596 LPWSTR AttributeName,
598{
600 USHORT Length = 0;
601
602 if ((String != NULL) && (String->Buffer != NULL))
603 {
604 Buffer = String->Buffer;
605 Length = String->Length + sizeof(WCHAR);
606 }
607
608 return SampSetObjectAttribute(DbObject,
609 AttributeName,
610 REG_SZ,
611 Buffer,
612 Length);
613}
614
615
616/* EOF */
617
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define ERR(fmt,...)
Definition: precomp.h:57
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
Definition: bufpool.h:45
#define STATUS_INVALID_HANDLE
Definition: d3dkmdt.h:40
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
NTSTATUS SampGetObjectAttribute(PSAM_DB_OBJECT DbObject, LPWSTR AttributeName, PULONG AttributeType, LPVOID AttributeData, PULONG AttributeSize)
Definition: database.c:516
NTSTATUS SampSetObjectAttribute(PSAM_DB_OBJECT DbObject, LPWSTR AttributeName, ULONG AttributeType, LPVOID AttributeData, ULONG AttributeSize)
Definition: database.c:501
NTSTATUS SampCloseDbObject(PSAM_DB_OBJECT DbObject)
Definition: database.c:346
NTSTATUS SampOpenDbObject(IN PSAM_DB_OBJECT ParentObject, IN LPWSTR ContainerName, IN LPWSTR ObjectName, IN ULONG RelativeId, IN SAM_DB_OBJECT_TYPE ObjectType, IN ACCESS_MASK DesiredAccess, OUT PSAM_DB_OBJECT *DbObject)
Definition: database.c:173
NTSTATUS SampDeleteAccountDbObject(PSAM_DB_OBJECT DbObject)
Definition: database.c:368
NTSTATUS SampValidateDbObject(SAMPR_HANDLE Handle, SAM_DB_OBJECT_TYPE ObjectType, ACCESS_MASK DesiredAccess, PSAM_DB_OBJECT *DbObject)
Definition: database.c:301
NTSTATUS SampCreateDbObject(IN PSAM_DB_OBJECT ParentObject, IN LPWSTR ContainerName, IN LPWSTR ObjectName, IN ULONG RelativeId, IN SAM_DB_OBJECT_TYPE ObjectType, IN ACCESS_MASK DesiredAccess, OUT PSAM_DB_OBJECT *DbObject)
Definition: database.c:44
NTSTATUS SampSetObjectAttributeString(PSAM_DB_OBJECT DbObject, LPWSTR AttributeName, PRPC_UNICODE_STRING String)
Definition: database.c:595
NTSTATUS SampInitDatabase(VOID)
Definition: database.c:21
NTSTATUS SampGetObjectAttributeString(PSAM_DB_OBJECT DbObject, LPWSTR AttributeName, PRPC_UNICODE_STRING String)
Definition: database.c:531
static HANDLE SamKeyHandle
Definition: database.c:15
NTSTATUS SampRegQueryValue(IN HANDLE KeyHandle, IN LPCWSTR ValueName, OUT PULONG Type OPTIONAL, OUT PVOID Data OPTIONAL, IN OUT PULONG DataLength OPTIONAL)
Definition: registry.c:332
NTSTATUS SampRegCloseKey(IN OUT PHANDLE KeyHandle)
Definition: registry.c:26
NTSTATUS SampRegSetValue(HANDLE KeyHandle, LPCWSTR ValueName, ULONG Type, LPVOID Data, ULONG DataLength)
Definition: registry.c:402
NTSTATUS SampRegDeleteKey(IN HANDLE ParentKeyHandle, IN LPCWSTR KeyName)
Definition: registry.c:71
NTSTATUS SampRegOpenKey(IN HANDLE ParentKeyHandle, IN LPCWSTR KeyName, IN ACCESS_MASK DesiredAccess, OUT PHANDLE KeyHandle)
Definition: registry.c:158
NTSTATUS SampRegDeleteValue(IN HANDLE KeyHandle, IN LPCWSTR ValueName)
Definition: registry.c:212
NTSTATUS SampRegCreateKey(IN HANDLE ParentKeyHandle, IN LPCWSTR KeyName, IN ACCESS_MASK DesiredAccess, OUT PHANDLE KeyHandle)
Definition: registry.c:42
#define SAMP_DB_SIGNATURE
Definition: samsrv.h:59
enum _SAM_DB_OBJECT_TYPE SAM_DB_OBJECT_TYPE
struct _SAM_DB_OBJECT * PSAM_DB_OBJECT
@ SamDbGroupObject
Definition: samsrv.h:41
@ SamDbUserObject
Definition: samsrv.h:42
@ SamDbIgnoreObject
Definition: samsrv.h:37
@ SamDbAliasObject
Definition: samsrv.h:40
@ AttributeData
Definition: ntfs.h:168
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define REG_SZ
Definition: layer.c:22
ObjectType
Definition: metafile.c:81
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define KEY_READ
Definition: nt_native.h:1023
#define KEY_CREATE_SUB_KEY
Definition: nt_native.h:1018
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
#define DELETE
Definition: nt_native.h:57
#define KEY_SET_VALUE
Definition: nt_native.h:1017
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define L(x)
Definition: ntvdm.h:50
unsigned short USHORT
Definition: pedump.c:61
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
#define midl_user_free
Definition: rpc.h:45
#define midl_user_allocate
Definition: rpc.h:44
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define TRACE(s)
Definition: solgame.cpp:4
LPWSTR Name
Definition: samsrv.h:51
HANDLE KeyHandle
Definition: samsrv.h:52
ULONG RefCount
Definition: samsrv.h:49
ACCESS_MASK Access
Definition: samsrv.h:50
SAM_DB_OBJECT_TYPE ObjectType
Definition: samsrv.h:48
HANDLE MembersKeyHandle
Definition: samsrv.h:53
struct _SAM_DB_OBJECT * ParentObject
Definition: samsrv.h:56
ULONG Signature
Definition: samsrv.h:47
uint32_t * PULONG
Definition: typedefs.h:59
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2433
_In_ PVOID _Out_opt_ PULONG_PTR _Outptr_opt_ PCUNICODE_STRING * ObjectName
Definition: cmfuncs.h:64
_Inout_opt_ PACCESS_STATE _In_opt_ ACCESS_MASK _In_ ULONG _Out_opt_ PVOID * NewObject
Definition: obfuncs.h:74
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185