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
11 /* GLOBALS *****************************************************************/
13 static HANDLE SamKeyHandle
= NULL
;
16 /* FUNCTIONS ***************************************************************/
19 SampInitDatabase(VOID
)
23 TRACE("SampInitDatabase()\n");
25 Status
= SampRegOpenKey(NULL
,
26 L
"\\Registry\\Machine\\SAM",
27 KEY_READ
| KEY_CREATE_SUB_KEY
| KEY_ENUMERATE_SUB_KEYS
,
29 if (!NT_SUCCESS(Status
))
31 ERR("Failed to open the SAM key (Status: 0x%08lx)\n", Status
);
35 TRACE("SampInitDatabase() done\n");
37 return STATUS_SUCCESS
;
42 SampCreateDbObject(IN PSAM_DB_OBJECT ParentObject
,
43 IN LPWSTR ContainerName
,
46 IN SAM_DB_OBJECT_TYPE ObjectType
,
47 IN ACCESS_MASK DesiredAccess
,
48 OUT PSAM_DB_OBJECT
*DbObject
)
50 PSAM_DB_OBJECT NewObject
= NULL
;
51 HANDLE ParentKeyHandle
;
52 HANDLE ContainerKeyHandle
= NULL
;
53 HANDLE ObjectKeyHandle
= NULL
;
54 HANDLE MembersKeyHandle
= NULL
;
58 return STATUS_INVALID_PARAMETER
;
62 if (ParentObject
== NULL
)
63 ParentKeyHandle
= SamKeyHandle
;
65 ParentKeyHandle
= ParentObject
->KeyHandle
;
67 if (ContainerName
!= NULL
)
69 /* Open the container key */
70 Status
= SampRegOpenKey(ParentKeyHandle
,
74 if (!NT_SUCCESS(Status
))
79 /* Create the object key */
80 Status
= SampRegCreateKey(ContainerKeyHandle
,
84 if (!NT_SUCCESS(Status
))
89 if (ObjectType
== SamDbAliasObject
)
91 /* Create the object key */
92 Status
= SampRegCreateKey(ContainerKeyHandle
,
96 if (!NT_SUCCESS(Status
))
104 /* Create the object key */
105 Status
= SampRegCreateKey(ParentKeyHandle
,
109 if (!NT_SUCCESS(Status
))
115 NewObject
= RtlAllocateHeap(RtlGetProcessHeap(),
117 sizeof(SAM_DB_OBJECT
));
118 if (NewObject
== NULL
)
120 Status
= STATUS_INSUFFICIENT_RESOURCES
;
124 NewObject
->Name
= RtlAllocateHeap(RtlGetProcessHeap(),
126 (wcslen(ObjectName
) + 1) * sizeof(WCHAR
));
127 if (NewObject
->Name
== NULL
)
129 Status
= STATUS_INSUFFICIENT_RESOURCES
;
133 wcscpy(NewObject
->Name
, ObjectName
);
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
;
144 if (ParentObject
!= NULL
)
145 NewObject
->Trusted
= ParentObject
->Trusted
;
147 *DbObject
= NewObject
;
150 if (!NT_SUCCESS(Status
))
152 if (NewObject
!= NULL
)
154 if (NewObject
->Name
!= NULL
)
155 RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject
->Name
);
157 RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject
);
160 SampRegCloseKey(&MembersKeyHandle
);
161 SampRegCloseKey(&ObjectKeyHandle
);
164 SampRegCloseKey(&ContainerKeyHandle
);
171 SampOpenDbObject(IN PSAM_DB_OBJECT ParentObject
,
172 IN LPWSTR ContainerName
,
173 IN LPWSTR ObjectName
,
175 IN SAM_DB_OBJECT_TYPE ObjectType
,
176 IN ACCESS_MASK DesiredAccess
,
177 OUT PSAM_DB_OBJECT
*DbObject
)
179 PSAM_DB_OBJECT NewObject
= NULL
;
180 HANDLE ParentKeyHandle
;
181 HANDLE ContainerKeyHandle
= NULL
;
182 HANDLE ObjectKeyHandle
= NULL
;
183 HANDLE MembersKeyHandle
= NULL
;
186 if (DbObject
== NULL
)
187 return STATUS_INVALID_PARAMETER
;
191 if (ParentObject
== NULL
)
192 ParentKeyHandle
= SamKeyHandle
;
194 ParentKeyHandle
= ParentObject
->KeyHandle
;
196 if (ContainerName
!= NULL
)
198 /* Open the container key */
199 Status
= SampRegOpenKey(ParentKeyHandle
,
202 &ContainerKeyHandle
);
203 if (!NT_SUCCESS(Status
))
208 /* Open the object key */
209 Status
= SampRegOpenKey(ContainerKeyHandle
,
213 if (!NT_SUCCESS(Status
))
218 if (ObjectType
== SamDbAliasObject
)
220 /* Open the object key */
221 Status
= SampRegOpenKey(ContainerKeyHandle
,
225 if (!NT_SUCCESS(Status
))
233 /* Open the object key */
234 Status
= SampRegOpenKey(ParentKeyHandle
,
238 if (!NT_SUCCESS(Status
))
244 NewObject
= RtlAllocateHeap(RtlGetProcessHeap(),
246 sizeof(SAM_DB_OBJECT
));
247 if (NewObject
== NULL
)
249 Status
= STATUS_INSUFFICIENT_RESOURCES
;
253 NewObject
->Name
= RtlAllocateHeap(RtlGetProcessHeap(),
255 (wcslen(ObjectName
) + 1) * sizeof(WCHAR
));
256 if (NewObject
->Name
== NULL
)
258 Status
= STATUS_INSUFFICIENT_RESOURCES
;
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
;
272 if (ParentObject
!= NULL
)
273 NewObject
->Trusted
= ParentObject
->Trusted
;
275 *DbObject
= NewObject
;
278 if (!NT_SUCCESS(Status
))
280 if (NewObject
!= NULL
)
282 if (NewObject
->Name
!= NULL
)
283 RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject
->Name
);
285 RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject
);
288 SampRegCloseKey(&MembersKeyHandle
);
289 SampRegCloseKey(&ObjectKeyHandle
);
292 SampRegCloseKey(&ContainerKeyHandle
);
299 SampValidateDbObject(SAMPR_HANDLE Handle
,
300 SAM_DB_OBJECT_TYPE ObjectType
,
301 ACCESS_MASK DesiredAccess
,
302 PSAM_DB_OBJECT
*DbObject
)
304 PSAM_DB_OBJECT LocalObject
= (PSAM_DB_OBJECT
)Handle
;
305 BOOLEAN bValid
= FALSE
;
309 if (LocalObject
->Signature
== SAMP_DB_SIGNATURE
)
311 if ((ObjectType
== SamDbIgnoreObject
) ||
312 (LocalObject
->ObjectType
== ObjectType
))
316 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
323 return STATUS_INVALID_HANDLE
;
325 if (DesiredAccess
!= 0)
327 /* Check for granted access rights */
328 if ((LocalObject
->Access
& DesiredAccess
) != DesiredAccess
)
330 ERR("SampValidateDbObject access check failed %08lx %08lx\n",
331 LocalObject
->Access
, DesiredAccess
);
332 return STATUS_ACCESS_DENIED
;
336 if (DbObject
!= NULL
)
337 *DbObject
= LocalObject
;
339 return STATUS_SUCCESS
;
344 SampCloseDbObject(PSAM_DB_OBJECT DbObject
)
346 NTSTATUS Status
= STATUS_SUCCESS
;
348 DbObject
->RefCount
--;
350 if (DbObject
->RefCount
> 0)
351 return STATUS_SUCCESS
;
353 SampRegCloseKey(&DbObject
->KeyHandle
);
354 SampRegCloseKey(&DbObject
->MembersKeyHandle
);
356 if (DbObject
->Name
!= NULL
)
357 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject
->Name
);
359 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject
);
366 SampDeleteAccountDbObject(PSAM_DB_OBJECT DbObject
)
368 LPCWSTR ContainerName
;
369 LPWSTR AccountName
= NULL
;
370 HANDLE ContainerKey
= NULL
;
371 HANDLE NamesKey
= NULL
;
373 NTSTATUS Status
= STATUS_SUCCESS
;
375 TRACE("(%p)\n", DbObject
);
377 /* Server and Domain objects cannot be deleted */
378 switch (DbObject
->ObjectType
)
380 case SamDbAliasObject
:
381 ContainerName
= L
"Aliases";
384 case SamDbGroupObject
:
385 ContainerName
= L
"Groups";
388 case SamDbUserObject
:
389 ContainerName
= L
"Users";
393 return STATUS_INVALID_PARAMETER
;
396 /* Get the account name */
397 Status
= SampGetObjectAttribute(DbObject
,
402 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_OVERFLOW
)
404 TRACE("SampGetObjectAttribute failed (Status 0x%08lx)\n", Status
);
408 AccountName
= RtlAllocateHeap(RtlGetProcessHeap(),
411 if (AccountName
== NULL
)
413 Status
= STATUS_INSUFFICIENT_RESOURCES
;
417 Status
= SampGetObjectAttribute(DbObject
,
422 if (!NT_SUCCESS(Status
))
424 TRACE("SampGetObjectAttribute failed (Status 0x%08lx)\n", Status
);
428 SampRegCloseKey(&DbObject
->KeyHandle
);
430 if (DbObject
->ObjectType
== SamDbAliasObject
)
432 SampRegCloseKey(&DbObject
->MembersKeyHandle
);
434 SampRegDeleteKey(DbObject
->KeyHandle
,
438 /* Open the domain container key */
439 Status
= SampRegOpenKey(DbObject
->ParentObject
->KeyHandle
,
441 DELETE
| KEY_SET_VALUE
,
443 if (!NT_SUCCESS(Status
))
445 TRACE("SampRegOpenKey failed (Status 0x%08lx)\n", Status
);
449 /* Open the Names key */
450 Status
= SampRegOpenKey(ContainerKey
,
454 if (!NT_SUCCESS(Status
))
456 TRACE("SampRegOpenKey failed (Status 0x%08lx)\n", Status
);
460 /* Remove the account from the Names key */
461 Status
= SampRegDeleteValue(NamesKey
,
463 if (!NT_SUCCESS(Status
))
465 TRACE("SampRegDeleteValue failed (Status 0x%08lx)\n", Status
);
469 /* Remove the account key from the container */
470 Status
= SampRegDeleteKey(ContainerKey
,
472 if (!NT_SUCCESS(Status
))
474 TRACE("SampRegDeleteKey failed (Status 0x%08lx)\n", Status
);
478 /* Release the database object name */
479 if (DbObject
->Name
!= NULL
)
480 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject
->Name
);
482 /* Release the database object */
483 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject
);
485 Status
= STATUS_SUCCESS
;
488 SampRegCloseKey(&NamesKey
);
489 SampRegCloseKey(&ContainerKey
);
491 if (AccountName
!= NULL
)
492 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountName
);
499 SampSetObjectAttribute(PSAM_DB_OBJECT DbObject
,
500 LPWSTR AttributeName
,
502 LPVOID AttributeData
,
505 return SampRegSetValue(DbObject
->KeyHandle
,
514 SampGetObjectAttribute(PSAM_DB_OBJECT DbObject
,
515 LPWSTR AttributeName
,
516 PULONG AttributeType
,
517 LPVOID AttributeData
,
518 PULONG AttributeSize
)
520 return SampRegQueryValue(DbObject
->KeyHandle
,
529 SampGetObjectAttributeString(PSAM_DB_OBJECT DbObject
,
530 LPWSTR AttributeName
,
531 PRPC_UNICODE_STRING String
)
536 Status
= SampGetObjectAttribute(DbObject
,
541 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_OVERFLOW
)
543 TRACE("Status 0x%08lx\n", Status
);
550 String
->MaximumLength
= 0;
551 String
->Buffer
= NULL
;
553 Status
= STATUS_SUCCESS
;
557 String
->Length
= (USHORT
)(Length
- sizeof(WCHAR
));
558 String
->MaximumLength
= (USHORT
)Length
;
559 String
->Buffer
= midl_user_allocate(Length
);
560 if (String
->Buffer
== NULL
)
562 Status
= STATUS_INSUFFICIENT_RESOURCES
;
566 TRACE("Length: %lu\n", Length
);
567 Status
= SampGetObjectAttribute(DbObject
,
570 (PVOID
)String
->Buffer
,
572 if (!NT_SUCCESS(Status
))
574 TRACE("Status 0x%08lx\n", Status
);
579 if (!NT_SUCCESS(Status
))
581 if (String
->Buffer
!= NULL
)
583 midl_user_free(String
->Buffer
);
584 String
->Buffer
= NULL
;
593 SampSetObjectAttributeString(PSAM_DB_OBJECT DbObject
,
594 LPWSTR AttributeName
,
595 PRPC_UNICODE_STRING String
)
597 PWCHAR Buffer
= NULL
;
600 if ((String
!= NULL
) && (String
->Buffer
!= NULL
))
602 Buffer
= String
->Buffer
;
603 Length
= String
->Length
+ sizeof(WCHAR
);
606 return SampSetObjectAttribute(DbObject
,