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
9 /* INCLUDES ****************************************************************/
13 WINE_DEFAULT_DEBUG_CHANNEL(samsrv
);
16 /* GLOBALS *****************************************************************/
18 static HANDLE SamKeyHandle
= NULL
;
21 /* FUNCTIONS ***************************************************************/
24 SampInitDatabase(VOID
)
28 TRACE("SampInitDatabase()\n");
30 Status
= SampRegOpenKey(NULL
,
31 L
"\\Registry\\Machine\\SAM",
32 KEY_READ
| KEY_CREATE_SUB_KEY
| KEY_ENUMERATE_SUB_KEYS
,
34 if (!NT_SUCCESS(Status
))
36 ERR("Failed to open the SAM key (Status: 0x%08lx)\n", Status
);
40 TRACE("SampInitDatabase() done\n");
42 return STATUS_SUCCESS
;
47 SampCreateDbObject(IN PSAM_DB_OBJECT ParentObject
,
48 IN LPWSTR ContainerName
,
51 IN SAM_DB_OBJECT_TYPE ObjectType
,
52 IN ACCESS_MASK DesiredAccess
,
53 OUT PSAM_DB_OBJECT
*DbObject
)
55 PSAM_DB_OBJECT NewObject
= NULL
;
56 HANDLE ParentKeyHandle
;
57 HANDLE ContainerKeyHandle
= NULL
;
58 HANDLE ObjectKeyHandle
= NULL
;
59 HANDLE MembersKeyHandle
= NULL
;
63 return STATUS_INVALID_PARAMETER
;
67 if (ParentObject
== NULL
)
68 ParentKeyHandle
= SamKeyHandle
;
70 ParentKeyHandle
= ParentObject
->KeyHandle
;
72 if (ContainerName
!= NULL
)
74 /* Open the container key */
75 Status
= SampRegOpenKey(ParentKeyHandle
,
79 if (!NT_SUCCESS(Status
))
84 /* Create the object key */
85 Status
= SampRegCreateKey(ContainerKeyHandle
,
89 if (!NT_SUCCESS(Status
))
94 if (ObjectType
== SamDbAliasObject
)
96 /* Create the object key */
97 Status
= SampRegCreateKey(ContainerKeyHandle
,
101 if (!NT_SUCCESS(Status
))
109 /* Create the object key */
110 Status
= SampRegCreateKey(ParentKeyHandle
,
114 if (!NT_SUCCESS(Status
))
120 NewObject
= RtlAllocateHeap(RtlGetProcessHeap(),
122 sizeof(SAM_DB_OBJECT
));
123 if (NewObject
== NULL
)
125 Status
= STATUS_INSUFFICIENT_RESOURCES
;
129 NewObject
->Name
= RtlAllocateHeap(RtlGetProcessHeap(),
131 (wcslen(ObjectName
) + 1) * sizeof(WCHAR
));
132 if (NewObject
->Name
== NULL
)
134 Status
= STATUS_INSUFFICIENT_RESOURCES
;
138 wcscpy(NewObject
->Name
, ObjectName
);
140 NewObject
->Signature
= SAMP_DB_SIGNATURE
;
141 NewObject
->RefCount
= 1;
142 NewObject
->ObjectType
= ObjectType
;
143 NewObject
->Access
= DesiredAccess
;
144 NewObject
->KeyHandle
= ObjectKeyHandle
;
145 NewObject
->MembersKeyHandle
= MembersKeyHandle
;
146 NewObject
->RelativeId
= RelativeId
;
147 NewObject
->ParentObject
= ParentObject
;
149 if (ParentObject
!= NULL
)
150 NewObject
->Trusted
= ParentObject
->Trusted
;
152 *DbObject
= NewObject
;
155 if (!NT_SUCCESS(Status
))
157 if (NewObject
!= NULL
)
159 if (NewObject
->Name
!= NULL
)
160 RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject
->Name
);
162 RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject
);
165 SampRegCloseKey(&MembersKeyHandle
);
166 SampRegCloseKey(&ObjectKeyHandle
);
169 SampRegCloseKey(&ContainerKeyHandle
);
176 SampOpenDbObject(IN PSAM_DB_OBJECT ParentObject
,
177 IN LPWSTR ContainerName
,
178 IN LPWSTR ObjectName
,
180 IN SAM_DB_OBJECT_TYPE ObjectType
,
181 IN ACCESS_MASK DesiredAccess
,
182 OUT PSAM_DB_OBJECT
*DbObject
)
184 PSAM_DB_OBJECT NewObject
= NULL
;
185 HANDLE ParentKeyHandle
;
186 HANDLE ContainerKeyHandle
= NULL
;
187 HANDLE ObjectKeyHandle
= NULL
;
188 HANDLE MembersKeyHandle
= NULL
;
191 if (DbObject
== NULL
)
192 return STATUS_INVALID_PARAMETER
;
196 if (ParentObject
== NULL
)
197 ParentKeyHandle
= SamKeyHandle
;
199 ParentKeyHandle
= ParentObject
->KeyHandle
;
201 if (ContainerName
!= NULL
)
203 /* Open the container key */
204 Status
= SampRegOpenKey(ParentKeyHandle
,
207 &ContainerKeyHandle
);
208 if (!NT_SUCCESS(Status
))
213 /* Open the object key */
214 Status
= SampRegOpenKey(ContainerKeyHandle
,
218 if (!NT_SUCCESS(Status
))
223 if (ObjectType
== SamDbAliasObject
)
225 /* Open the object key */
226 Status
= SampRegOpenKey(ContainerKeyHandle
,
230 if (!NT_SUCCESS(Status
))
238 /* Open the object key */
239 Status
= SampRegOpenKey(ParentKeyHandle
,
243 if (!NT_SUCCESS(Status
))
249 NewObject
= RtlAllocateHeap(RtlGetProcessHeap(),
251 sizeof(SAM_DB_OBJECT
));
252 if (NewObject
== NULL
)
254 Status
= STATUS_INSUFFICIENT_RESOURCES
;
258 NewObject
->Name
= RtlAllocateHeap(RtlGetProcessHeap(),
260 (wcslen(ObjectName
) + 1) * sizeof(WCHAR
));
261 if (NewObject
->Name
== NULL
)
263 Status
= STATUS_INSUFFICIENT_RESOURCES
;
267 wcscpy(NewObject
->Name
, ObjectName
);
268 NewObject
->Signature
= SAMP_DB_SIGNATURE
;
269 NewObject
->RefCount
= 1;
270 NewObject
->ObjectType
= ObjectType
;
271 NewObject
->Access
= DesiredAccess
;
272 NewObject
->KeyHandle
= ObjectKeyHandle
;
273 NewObject
->MembersKeyHandle
= MembersKeyHandle
;
274 NewObject
->RelativeId
= RelativeId
;
275 NewObject
->ParentObject
= ParentObject
;
277 if (ParentObject
!= NULL
)
278 NewObject
->Trusted
= ParentObject
->Trusted
;
280 *DbObject
= NewObject
;
283 if (!NT_SUCCESS(Status
))
285 if (NewObject
!= NULL
)
287 if (NewObject
->Name
!= NULL
)
288 RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject
->Name
);
290 RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject
);
293 SampRegCloseKey(&MembersKeyHandle
);
294 SampRegCloseKey(&ObjectKeyHandle
);
297 SampRegCloseKey(&ContainerKeyHandle
);
304 SampValidateDbObject(SAMPR_HANDLE Handle
,
305 SAM_DB_OBJECT_TYPE ObjectType
,
306 ACCESS_MASK DesiredAccess
,
307 PSAM_DB_OBJECT
*DbObject
)
309 PSAM_DB_OBJECT LocalObject
= (PSAM_DB_OBJECT
)Handle
;
310 BOOLEAN bValid
= FALSE
;
314 if (LocalObject
->Signature
== SAMP_DB_SIGNATURE
)
316 if ((ObjectType
== SamDbIgnoreObject
) ||
317 (LocalObject
->ObjectType
== ObjectType
))
321 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
328 return STATUS_INVALID_HANDLE
;
330 if (DesiredAccess
!= 0)
332 /* Check for granted access rights */
333 if ((LocalObject
->Access
& DesiredAccess
) != DesiredAccess
)
335 ERR("SampValidateDbObject access check failed %08lx %08lx\n",
336 LocalObject
->Access
, DesiredAccess
);
337 return STATUS_ACCESS_DENIED
;
341 if (DbObject
!= NULL
)
342 *DbObject
= LocalObject
;
344 return STATUS_SUCCESS
;
349 SampCloseDbObject(PSAM_DB_OBJECT DbObject
)
351 NTSTATUS Status
= STATUS_SUCCESS
;
353 DbObject
->RefCount
--;
355 if (DbObject
->RefCount
> 0)
356 return STATUS_SUCCESS
;
358 SampRegCloseKey(&DbObject
->KeyHandle
);
359 SampRegCloseKey(&DbObject
->MembersKeyHandle
);
361 if (DbObject
->Name
!= NULL
)
362 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject
->Name
);
364 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject
);
371 SampDeleteAccountDbObject(PSAM_DB_OBJECT DbObject
)
373 LPCWSTR ContainerName
;
374 LPWSTR AccountName
= NULL
;
375 HANDLE ContainerKey
= NULL
;
376 HANDLE NamesKey
= NULL
;
378 NTSTATUS Status
= STATUS_SUCCESS
;
380 TRACE("(%p)\n", DbObject
);
382 /* Server and Domain objects cannot be deleted */
383 switch (DbObject
->ObjectType
)
385 case SamDbAliasObject
:
386 ContainerName
= L
"Aliases";
389 case SamDbGroupObject
:
390 ContainerName
= L
"Groups";
393 case SamDbUserObject
:
394 ContainerName
= L
"Users";
398 return STATUS_INVALID_PARAMETER
;
401 /* Get the account name */
402 Status
= SampGetObjectAttribute(DbObject
,
407 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_OVERFLOW
)
409 TRACE("SampGetObjectAttribute failed (Status 0x%08lx)\n", Status
);
413 AccountName
= RtlAllocateHeap(RtlGetProcessHeap(),
416 if (AccountName
== NULL
)
418 Status
= STATUS_INSUFFICIENT_RESOURCES
;
422 Status
= SampGetObjectAttribute(DbObject
,
427 if (!NT_SUCCESS(Status
))
429 TRACE("SampGetObjectAttribute failed (Status 0x%08lx)\n", Status
);
433 SampRegCloseKey(&DbObject
->KeyHandle
);
435 if (DbObject
->ObjectType
== SamDbAliasObject
)
437 SampRegCloseKey(&DbObject
->MembersKeyHandle
);
439 SampRegDeleteKey(DbObject
->KeyHandle
,
443 /* Open the domain container key */
444 Status
= SampRegOpenKey(DbObject
->ParentObject
->KeyHandle
,
446 DELETE
| KEY_SET_VALUE
,
448 if (!NT_SUCCESS(Status
))
450 TRACE("SampRegOpenKey failed (Status 0x%08lx)\n", Status
);
454 /* Open the Names key */
455 Status
= SampRegOpenKey(ContainerKey
,
459 if (!NT_SUCCESS(Status
))
461 TRACE("SampRegOpenKey failed (Status 0x%08lx)\n", Status
);
465 /* Remove the account from the Names key */
466 Status
= SampRegDeleteValue(NamesKey
,
468 if (!NT_SUCCESS(Status
))
470 TRACE("SampRegDeleteValue failed (Status 0x%08lx)\n", Status
);
474 /* Remove the account key from the container */
475 Status
= SampRegDeleteKey(ContainerKey
,
477 if (!NT_SUCCESS(Status
))
479 TRACE("SampRegDeleteKey failed (Status 0x%08lx)\n", Status
);
483 /* Release the database object name */
484 if (DbObject
->Name
!= NULL
)
485 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject
->Name
);
487 /* Release the database object */
488 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject
);
490 Status
= STATUS_SUCCESS
;
493 SampRegCloseKey(&NamesKey
);
494 SampRegCloseKey(&ContainerKey
);
496 if (AccountName
!= NULL
)
497 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountName
);
504 SampSetObjectAttribute(PSAM_DB_OBJECT DbObject
,
505 LPWSTR AttributeName
,
507 LPVOID AttributeData
,
510 return SampRegSetValue(DbObject
->KeyHandle
,
519 SampGetObjectAttribute(PSAM_DB_OBJECT DbObject
,
520 LPWSTR AttributeName
,
521 PULONG AttributeType
,
522 LPVOID AttributeData
,
523 PULONG AttributeSize
)
525 return SampRegQueryValue(DbObject
->KeyHandle
,
534 SampGetObjectAttributeString(PSAM_DB_OBJECT DbObject
,
535 LPWSTR AttributeName
,
536 PRPC_UNICODE_STRING String
)
541 Status
= SampGetObjectAttribute(DbObject
,
546 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_OVERFLOW
)
548 TRACE("Status 0x%08lx\n", Status
);
555 String
->MaximumLength
= 0;
556 String
->Buffer
= NULL
;
558 Status
= STATUS_SUCCESS
;
562 String
->Length
= (USHORT
)(Length
- sizeof(WCHAR
));
563 String
->MaximumLength
= (USHORT
)Length
;
564 String
->Buffer
= midl_user_allocate(Length
);
565 if (String
->Buffer
== NULL
)
567 Status
= STATUS_INSUFFICIENT_RESOURCES
;
571 TRACE("Length: %lu\n", Length
);
572 Status
= SampGetObjectAttribute(DbObject
,
575 (PVOID
)String
->Buffer
,
577 if (!NT_SUCCESS(Status
))
579 TRACE("Status 0x%08lx\n", Status
);
584 if (!NT_SUCCESS(Status
))
586 if (String
->Buffer
!= NULL
)
588 midl_user_free(String
->Buffer
);
589 String
->Buffer
= NULL
;
598 SampSetObjectAttributeString(PSAM_DB_OBJECT DbObject
,
599 LPWSTR AttributeName
,
600 PRPC_UNICODE_STRING String
)
602 PWCHAR Buffer
= NULL
;
605 if ((String
!= NULL
) && (String
->Buffer
!= NULL
))
607 Buffer
= String
->Buffer
;
608 Length
= String
->Length
+ sizeof(WCHAR
);
611 return SampSetObjectAttribute(DbObject
,