ReactOS  0.4.14-dev-293-g2b39b42
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 /* GLOBALS *****************************************************************/
12 
14 
15 
16 /* FUNCTIONS ***************************************************************/
17 
20 {
22 
23  TRACE("SampInitDatabase()\n");
24 
26  L"\\Registry\\Machine\\SAM",
28  &SamKeyHandle);
29  if (!NT_SUCCESS(Status))
30  {
31  ERR("Failed to open the SAM key (Status: 0x%08lx)\n", Status);
32  return Status;
33  }
34 
35  TRACE("SampInitDatabase() done\n");
36 
37  return STATUS_SUCCESS;
38 }
39 
40 
43  IN LPWSTR ContainerName,
45  IN ULONG RelativeId,
48  OUT PSAM_DB_OBJECT *DbObject)
49 {
51  HANDLE ParentKeyHandle;
52  HANDLE ContainerKeyHandle = NULL;
53  HANDLE ObjectKeyHandle = NULL;
54  HANDLE MembersKeyHandle = NULL;
56 
57  if (DbObject == NULL)
59 
60  *DbObject = NULL;
61 
62  if (ParentObject == NULL)
63  ParentKeyHandle = SamKeyHandle;
64  else
65  ParentKeyHandle = ParentObject->KeyHandle;
66 
67  if (ContainerName != NULL)
68  {
69  /* Open the container key */
70  Status = SampRegOpenKey(ParentKeyHandle,
71  ContainerName,
73  &ContainerKeyHandle);
74  if (!NT_SUCCESS(Status))
75  {
76  goto done;
77  }
78 
79  /* Create the object key */
80  Status = SampRegCreateKey(ContainerKeyHandle,
81  ObjectName,
83  &ObjectKeyHandle);
84  if (!NT_SUCCESS(Status))
85  {
86  goto done;
87  }
88 
90  {
91  /* Create the object key */
92  Status = SampRegCreateKey(ContainerKeyHandle,
93  L"Members",
95  &MembersKeyHandle);
96  if (!NT_SUCCESS(Status))
97  {
98  goto done;
99  }
100  }
101  }
102  else
103  {
104  /* Create the object key */
105  Status = SampRegCreateKey(ParentKeyHandle,
106  ObjectName,
108  &ObjectKeyHandle);
109  if (!NT_SUCCESS(Status))
110  {
111  goto done;
112  }
113  }
114 
115  NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
117  sizeof(SAM_DB_OBJECT));
118  if (NewObject == NULL)
119  {
121  goto done;
122  }
123 
124  NewObject->Name = RtlAllocateHeap(RtlGetProcessHeap(),
125  0,
126  (wcslen(ObjectName) + 1) * sizeof(WCHAR));
127  if (NewObject->Name == NULL)
128  {
130  goto done;
131  }
132 
133  wcscpy(NewObject->Name, ObjectName);
134 
135  NewObject->Signature = SAMP_DB_SIGNATURE;
136  NewObject->RefCount = 1;
137  NewObject->ObjectType = ObjectType;
138  NewObject->Access = DesiredAccess;
139  NewObject->KeyHandle = ObjectKeyHandle;
140  NewObject->MembersKeyHandle = MembersKeyHandle;
141  NewObject->RelativeId = RelativeId;
142  NewObject->ParentObject = ParentObject;
143 
144  if (ParentObject != NULL)
145  NewObject->Trusted = ParentObject->Trusted;
146 
147  *DbObject = NewObject;
148 
149 done:
150  if (!NT_SUCCESS(Status))
151  {
152  if (NewObject != NULL)
153  {
154  if (NewObject->Name != NULL)
155  RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject->Name);
156 
157  RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject);
158  }
159 
160  SampRegCloseKey(&MembersKeyHandle);
161  SampRegCloseKey(&ObjectKeyHandle);
162  }
163 
164  SampRegCloseKey(&ContainerKeyHandle);
165 
166  return Status;
167 }
168 
169 
170 NTSTATUS
172  IN LPWSTR ContainerName,
174  IN ULONG RelativeId,
177  OUT PSAM_DB_OBJECT *DbObject)
178 {
180  HANDLE ParentKeyHandle;
181  HANDLE ContainerKeyHandle = NULL;
182  HANDLE ObjectKeyHandle = NULL;
183  HANDLE MembersKeyHandle = NULL;
185 
186  if (DbObject == NULL)
188 
189  *DbObject = NULL;
190 
191  if (ParentObject == NULL)
192  ParentKeyHandle = SamKeyHandle;
193  else
194  ParentKeyHandle = ParentObject->KeyHandle;
195 
196  if (ContainerName != NULL)
197  {
198  /* Open the container key */
199  Status = SampRegOpenKey(ParentKeyHandle,
200  ContainerName,
202  &ContainerKeyHandle);
203  if (!NT_SUCCESS(Status))
204  {
205  goto done;
206  }
207 
208  /* Open the object key */
209  Status = SampRegOpenKey(ContainerKeyHandle,
210  ObjectName,
212  &ObjectKeyHandle);
213  if (!NT_SUCCESS(Status))
214  {
215  goto done;
216  }
217 
219  {
220  /* Open the object key */
221  Status = SampRegOpenKey(ContainerKeyHandle,
222  L"Members",
224  &MembersKeyHandle);
225  if (!NT_SUCCESS(Status))
226  {
227  goto done;
228  }
229  }
230  }
231  else
232  {
233  /* Open the object key */
234  Status = SampRegOpenKey(ParentKeyHandle,
235  ObjectName,
237  &ObjectKeyHandle);
238  if (!NT_SUCCESS(Status))
239  {
240  goto done;
241  }
242  }
243 
244  NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
246  sizeof(SAM_DB_OBJECT));
247  if (NewObject == NULL)
248  {
250  goto done;
251  }
252 
253  NewObject->Name = RtlAllocateHeap(RtlGetProcessHeap(),
254  0,
255  (wcslen(ObjectName) + 1) * sizeof(WCHAR));
256  if (NewObject->Name == NULL)
257  {
259  goto done;
260  }
261 
262  wcscpy(NewObject->Name, ObjectName);
263  NewObject->Signature = SAMP_DB_SIGNATURE;
264  NewObject->RefCount = 1;
265  NewObject->ObjectType = ObjectType;
266  NewObject->Access = DesiredAccess;
267  NewObject->KeyHandle = ObjectKeyHandle;
268  NewObject->MembersKeyHandle = MembersKeyHandle;
269  NewObject->RelativeId = RelativeId;
270  NewObject->ParentObject = ParentObject;
271 
272  if (ParentObject != NULL)
273  NewObject->Trusted = ParentObject->Trusted;
274 
275  *DbObject = NewObject;
276 
277 done:
278  if (!NT_SUCCESS(Status))
279  {
280  if (NewObject != NULL)
281  {
282  if (NewObject->Name != NULL)
283  RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject->Name);
284 
285  RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject);
286  }
287 
288  SampRegCloseKey(&MembersKeyHandle);
289  SampRegCloseKey(&ObjectKeyHandle);
290  }
291 
292  SampRegCloseKey(&ContainerKeyHandle);
293 
294  return Status;
295 }
296 
297 
298 NTSTATUS
302  PSAM_DB_OBJECT *DbObject)
303 {
304  PSAM_DB_OBJECT LocalObject = (PSAM_DB_OBJECT)Handle;
305  BOOLEAN bValid = FALSE;
306 
307  _SEH2_TRY
308  {
309  if (LocalObject->Signature == SAMP_DB_SIGNATURE)
310  {
311  if ((ObjectType == SamDbIgnoreObject) ||
312  (LocalObject->ObjectType == ObjectType))
313  bValid = TRUE;
314  }
315  }
317  {
318  bValid = FALSE;
319  }
320  _SEH2_END;
321 
322  if (bValid == FALSE)
323  return STATUS_INVALID_HANDLE;
324 
325  if (DesiredAccess != 0)
326  {
327  /* Check for granted access rights */
328  if ((LocalObject->Access & DesiredAccess) != DesiredAccess)
329  {
330  ERR("SampValidateDbObject access check failed %08lx %08lx\n",
331  LocalObject->Access, DesiredAccess);
332  return STATUS_ACCESS_DENIED;
333  }
334  }
335 
336  if (DbObject != NULL)
337  *DbObject = LocalObject;
338 
339  return STATUS_SUCCESS;
340 }
341 
342 
343 NTSTATUS
345 {
347 
348  DbObject->RefCount--;
349 
350  if (DbObject->RefCount > 0)
351  return STATUS_SUCCESS;
352 
353  SampRegCloseKey(&DbObject->KeyHandle);
354  SampRegCloseKey(&DbObject->MembersKeyHandle);
355 
356  if (DbObject->Name != NULL)
357  RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject->Name);
358 
359  RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
360 
361  return Status;
362 }
363 
364 
365 NTSTATUS
367 {
368  LPCWSTR ContainerName;
369  LPWSTR AccountName = NULL;
370  HANDLE ContainerKey = NULL;
371  HANDLE NamesKey = NULL;
372  ULONG Length = 0;
374 
375  TRACE("(%p)\n", DbObject);
376 
377  /* Server and Domain objects cannot be deleted */
378  switch (DbObject->ObjectType)
379  {
380  case SamDbAliasObject:
381  ContainerName = L"Aliases";
382  break;
383 
384  case SamDbGroupObject:
385  ContainerName = L"Groups";
386  break;
387 
388  case SamDbUserObject:
389  ContainerName = L"Users";
390  break;
391 
392  default:
394  }
395 
396  /* Get the account name */
397  Status = SampGetObjectAttribute(DbObject,
398  L"Name",
399  NULL,
400  NULL,
401  &Length);
403  {
404  TRACE("SampGetObjectAttribute failed (Status 0x%08lx)\n", Status);
405  goto done;
406  }
407 
408  AccountName = RtlAllocateHeap(RtlGetProcessHeap(),
410  Length);
411  if (AccountName == NULL)
412  {
414  goto done;
415  }
416 
417  Status = SampGetObjectAttribute(DbObject,
418  L"Name",
419  NULL,
420  (PVOID)AccountName,
421  &Length);
422  if (!NT_SUCCESS(Status))
423  {
424  TRACE("SampGetObjectAttribute failed (Status 0x%08lx)\n", Status);
425  goto done;
426  }
427 
428  SampRegCloseKey(&DbObject->KeyHandle);
429 
430  if (DbObject->ObjectType == SamDbAliasObject)
431  {
432  SampRegCloseKey(&DbObject->MembersKeyHandle);
433 
434  SampRegDeleteKey(DbObject->KeyHandle,
435  L"Members");
436  }
437 
438  /* Open the domain container key */
439  Status = SampRegOpenKey(DbObject->ParentObject->KeyHandle,
440  ContainerName,
442  &ContainerKey);
443  if (!NT_SUCCESS(Status))
444  {
445  TRACE("SampRegOpenKey failed (Status 0x%08lx)\n", Status);
446  goto done;
447  }
448 
449  /* Open the Names key */
450  Status = SampRegOpenKey(ContainerKey,
451  L"Names",
453  &NamesKey);
454  if (!NT_SUCCESS(Status))
455  {
456  TRACE("SampRegOpenKey failed (Status 0x%08lx)\n", Status);
457  goto done;
458  }
459 
460  /* Remove the account from the Names key */
461  Status = SampRegDeleteValue(NamesKey,
462  AccountName);
463  if (!NT_SUCCESS(Status))
464  {
465  TRACE("SampRegDeleteValue failed (Status 0x%08lx)\n", Status);
466  goto done;
467  }
468 
469  /* Remove the account key from the container */
470  Status = SampRegDeleteKey(ContainerKey,
471  DbObject->Name);
472  if (!NT_SUCCESS(Status))
473  {
474  TRACE("SampRegDeleteKey failed (Status 0x%08lx)\n", Status);
475  goto done;
476  }
477 
478  /* Release the database object name */
479  if (DbObject->Name != NULL)
480  RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject->Name);
481 
482  /* Release the database object */
483  RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
484 
486 
487 done:
488  SampRegCloseKey(&NamesKey);
489  SampRegCloseKey(&ContainerKey);
490 
491  if (AccountName != NULL)
492  RtlFreeHeap(RtlGetProcessHeap(), 0, AccountName);
493 
494  return Status;
495 }
496 
497 
498 NTSTATUS
500  LPWSTR AttributeName,
501  ULONG AttributeType,
503  ULONG AttributeSize)
504 {
505  return SampRegSetValue(DbObject->KeyHandle,
506  AttributeName,
507  AttributeType,
509  AttributeSize);
510 }
511 
512 
513 NTSTATUS
515  LPWSTR AttributeName,
516  PULONG AttributeType,
518  PULONG AttributeSize)
519 {
520  return SampRegQueryValue(DbObject->KeyHandle,
521  AttributeName,
522  AttributeType,
524  AttributeSize);
525 }
526 
527 
528 NTSTATUS
530  LPWSTR AttributeName,
532 {
533  ULONG Length = 0;
535 
536  Status = SampGetObjectAttribute(DbObject,
537  AttributeName,
538  NULL,
539  NULL,
540  &Length);
542  {
543  TRACE("Status 0x%08lx\n", Status);
544  goto done;
545  }
546 
547  if (Length == 0)
548  {
549  String->Length = 0;
550  String->MaximumLength = 0;
551  String->Buffer = NULL;
552 
554  goto done;
555  }
556 
557  String->Length = (USHORT)(Length - sizeof(WCHAR));
558  String->MaximumLength = (USHORT)Length;
559  String->Buffer = midl_user_allocate(Length);
560  if (String->Buffer == NULL)
561  {
563  goto done;
564  }
565 
566  TRACE("Length: %lu\n", Length);
567  Status = SampGetObjectAttribute(DbObject,
568  AttributeName,
569  NULL,
570  (PVOID)String->Buffer,
571  &Length);
572  if (!NT_SUCCESS(Status))
573  {
574  TRACE("Status 0x%08lx\n", Status);
575  goto done;
576  }
577 
578 done:
579  if (!NT_SUCCESS(Status))
580  {
581  if (String->Buffer != NULL)
582  {
583  midl_user_free(String->Buffer);
584  String->Buffer = NULL;
585  }
586  }
587 
588  return Status;
589 }
590 
591 
592 NTSTATUS
594  LPWSTR AttributeName,
596 {
597  PWCHAR Buffer = NULL;
598  USHORT Length = 0;
599 
600  if ((String != NULL) && (String->Buffer != NULL))
601  {
602  Buffer = String->Buffer;
603  Length = String->Length + sizeof(WCHAR);
604  }
605 
606  return SampSetObjectAttribute(DbObject,
607  AttributeName,
608  REG_SZ,
609  Buffer,
610  Length);
611 }
612 
613 
614 /* EOF */
615 
ULONG Signature
Definition: samsrv.h:46
ObjectType
Definition: metafile.c:80
enum _SAM_DB_OBJECT_TYPE SAM_DB_OBJECT_TYPE
#define IN
Definition: typedefs.h:38
#define midl_user_free
Definition: rpc.h:45
#define TRUE
Definition: types.h:120
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:42
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define KEY_SET_VALUE
Definition: nt_native.h:1017
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
SAM_DB_OBJECT_TYPE ObjectType
Definition: samsrv.h:47
#define KEY_READ
Definition: nt_native.h:1023
#define midl_user_allocate
Definition: rpc.h:44
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
NTSTATUS SampSetObjectAttribute(PSAM_DB_OBJECT DbObject, LPWSTR AttributeName, ULONG AttributeType, LPVOID AttributeData, ULONG AttributeSize)
Definition: database.c:499
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
NTSTATUS SampRegDeleteValue(IN HANDLE KeyHandle, IN LPCWSTR ValueName)
Definition: registry.c:212
static WCHAR String[]
Definition: stringtable.c:55
uint16_t * PWCHAR
Definition: typedefs.h:54
_In_ PVOID _Out_opt_ PULONG_PTR _Outptr_opt_ PCUNICODE_STRING * ObjectName
Definition: cmfuncs.h:62
NTSTATUS SampDeleteAccountDbObject(PSAM_DB_OBJECT DbObject)
Definition: database.c:366
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:231
_SEH2_TRY
Definition: create.c:4250
NTSTATUS SampRegCloseKey(IN OUT PHANDLE KeyHandle)
Definition: registry.c:26
HANDLE MembersKeyHandle
Definition: samsrv.h:52
struct _SAM_DB_OBJECT * PSAM_DB_OBJECT
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char BOOLEAN
static HANDLE SamKeyHandle
Definition: database.c:13
smooth NULL
Definition: ftsmooth.c:416
ULONG RefCount
Definition: samsrv.h:48
Definition: bufpool.h:45
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
_In_ HANDLE Handle
Definition: extypes.h:390
LPWSTR Name
Definition: samsrv.h:50
#define TRACE(s)
Definition: solgame.cpp:4
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTATUS SampGetObjectAttributeString(PSAM_DB_OBJECT DbObject, LPWSTR AttributeName, PRPC_UNICODE_STRING String)
Definition: database.c:529
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
NTSTATUS SampValidateDbObject(SAMPR_HANDLE Handle, SAM_DB_OBJECT_TYPE ObjectType, ACCESS_MASK DesiredAccess, PSAM_DB_OBJECT *DbObject)
Definition: database.c:299
NTSTATUS SampCloseDbObject(PSAM_DB_OBJECT DbObject)
Definition: database.c:344
NTSTATUS SampGetObjectAttribute(PSAM_DB_OBJECT DbObject, LPWSTR AttributeName, PULONG AttributeType, LPVOID AttributeData, PULONG AttributeSize)
Definition: database.c:514
NTSTATUS SampRegDeleteKey(IN HANDLE ParentKeyHandle, IN LPCWSTR KeyName)
Definition: registry.c:71
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
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
static const WCHAR L[]
Definition: oid.c:1250
ACCESS_MASK Access
Definition: samsrv.h:49
Status
Definition: gdiplustypes.h:24
NTSTATUS SampInitDatabase(VOID)
Definition: database.c:19
HANDLE KeyHandle
Definition: samsrv.h:51
#define ERR(fmt,...)
Definition: debug.h:109
_SEH2_END
Definition: create.c:4424
struct _SAM_DB_OBJECT * ParentObject
Definition: samsrv.h:55
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
NTSTATUS SampRegOpenKey(IN HANDLE ParentKeyHandle, IN LPCWSTR KeyName, IN ACCESS_MASK DesiredAccess, OUT PHANDLE KeyHandle)
Definition: registry.c:158
unsigned short USHORT
Definition: pedump.c:61
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK DesiredAccess
Definition: create.c:4157
unsigned int * PULONG
Definition: retypes.h:1
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
NTSTATUS SampRegSetValue(HANDLE KeyHandle, LPCWSTR ValueName, ULONG Type, LPVOID Data, ULONG DataLength)
Definition: registry.c:402
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS SampSetObjectAttributeString(PSAM_DB_OBJECT DbObject, LPWSTR AttributeName, PRPC_UNICODE_STRING String)
Definition: database.c:593
#define SAMP_DB_SIGNATURE
Definition: samsrv.h:58
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
NTSTATUS SampRegCreateKey(IN HANDLE ParentKeyHandle, IN LPCWSTR KeyName, IN ACCESS_MASK DesiredAccess, OUT PHANDLE KeyHandle)
Definition: registry.c:42
WCHAR * LPWSTR
Definition: xmlstorage.h:184
_Inout_opt_ PACCESS_STATE _In_opt_ ACCESS_MASK _In_ ULONG _Out_opt_ PVOID * NewObject
Definition: obfuncs.h:71
return STATUS_SUCCESS
Definition: btrfs.c:2966
#define KEY_CREATE_SUB_KEY
Definition: nt_native.h:1018
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define DELETE
Definition: nt_native.h:57
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:171
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
#define REG_SZ
Definition: layer.c:22