[SAMSRV]
[reactos.git] / reactos / dll / win32 / samsrv / user.c
1 /*
2 * PROJECT: Local Security Authority Server DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/samsrv/user.c
5 * PURPOSE: User specific helper functions
6 * COPYRIGHT: Copyright 2013 Eric Kohl
7 */
8
9 /* INCLUDES ****************************************************************/
10
11 #include "samsrv.h"
12
13 WINE_DEFAULT_DEBUG_CHANNEL(samsrv);
14
15
16 /* FUNCTIONS ***************************************************************/
17
18 NTSTATUS
19 SampOpenUserObject(IN PSAM_DB_OBJECT DomainObject,
20 IN ULONG UserId,
21 IN ACCESS_MASK DesiredAccess,
22 OUT PSAM_DB_OBJECT *UserObject)
23 {
24 WCHAR szRid[9];
25
26 TRACE("(%p %lu %lx %p)\n",
27 DomainObject, UserId, DesiredAccess, UserObject);
28
29 /* Convert the RID into a string (hex) */
30 swprintf(szRid, L"%08lX", UserId);
31
32 /* Create the user object */
33 return SampOpenDbObject(DomainObject,
34 L"Users",
35 szRid,
36 UserId,
37 SamDbUserObject,
38 DesiredAccess,
39 UserObject);
40 }
41
42
43 NTSTATUS
44 SampAddGroupMembershipToUser(IN PSAM_DB_OBJECT UserObject,
45 IN ULONG GroupId,
46 IN ULONG Attributes)
47 {
48 PGROUP_MEMBERSHIP GroupsBuffer = NULL;
49 ULONG GroupsCount = 0;
50 ULONG Length = 0;
51 ULONG i;
52 NTSTATUS Status;
53
54 TRACE("(%p %lu %lx)\n",
55 UserObject, GroupId, Attributes);
56
57 Status = SampGetObjectAttribute(UserObject,
58 L"Groups",
59 NULL,
60 NULL,
61 &Length);
62 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
63 goto done;
64
65 GroupsBuffer = midl_user_allocate(Length + sizeof(GROUP_MEMBERSHIP));
66 if (GroupsBuffer == NULL)
67 {
68 Status = STATUS_INSUFFICIENT_RESOURCES;
69 goto done;
70 }
71
72 if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
73 {
74 Status = SampGetObjectAttribute(UserObject,
75 L"Groups",
76 NULL,
77 GroupsBuffer,
78 &Length);
79 if (!NT_SUCCESS(Status))
80 goto done;
81
82 GroupsCount = Length / sizeof(GROUP_MEMBERSHIP);
83 }
84
85 for (i = 0; i < GroupsCount; i++)
86 {
87 if (GroupsBuffer[i].RelativeId == GroupId)
88 {
89 Status = STATUS_MEMBER_IN_GROUP;
90 goto done;
91 }
92 }
93
94 GroupsBuffer[GroupsCount].RelativeId = GroupId;
95 GroupsBuffer[GroupsCount].Attributes = Attributes;
96 Length += sizeof(GROUP_MEMBERSHIP);
97
98 Status = SampSetObjectAttribute(UserObject,
99 L"Groups",
100 REG_BINARY,
101 GroupsBuffer,
102 Length);
103
104 done:
105 if (GroupsBuffer != NULL)
106 midl_user_free(GroupsBuffer);
107
108 return Status;
109 }
110
111
112 NTSTATUS
113 SampRemoveGroupMembershipFromUser(IN PSAM_DB_OBJECT UserObject,
114 IN ULONG GroupId)
115 {
116 PGROUP_MEMBERSHIP GroupsBuffer = NULL;
117 ULONG GroupsCount = 0;
118 ULONG Length = 0;
119 ULONG i;
120 NTSTATUS Status = STATUS_SUCCESS;
121
122 TRACE("(%p %lu)\n",
123 UserObject, GroupId);
124
125 SampGetObjectAttribute(UserObject,
126 L"Groups",
127 NULL,
128 NULL,
129 &Length);
130
131 if (Length == 0)
132 return STATUS_MEMBER_NOT_IN_GROUP;
133
134 GroupsBuffer = midl_user_allocate(Length);
135 if (GroupsBuffer == NULL)
136 {
137 Status = STATUS_INSUFFICIENT_RESOURCES;
138 goto done;
139 }
140
141 Status = SampGetObjectAttribute(UserObject,
142 L"Groups",
143 NULL,
144 GroupsBuffer,
145 &Length);
146 if (!NT_SUCCESS(Status))
147 goto done;
148
149 Status = STATUS_MEMBER_NOT_IN_GROUP;
150
151 GroupsCount = Length / sizeof(GROUP_MEMBERSHIP);
152 for (i = 0; i < GroupsCount; i++)
153 {
154 if (GroupsBuffer[i].RelativeId == GroupId)
155 {
156 Length -= sizeof(GROUP_MEMBERSHIP);
157 Status = STATUS_SUCCESS;
158
159 if (GroupsCount - i - 1 > 0)
160 {
161 CopyMemory(&GroupsBuffer[i],
162 &GroupsBuffer[i + 1],
163 (GroupsCount - i - 1) * sizeof(GROUP_MEMBERSHIP));
164 }
165
166 break;
167 }
168 }
169
170 if (!NT_SUCCESS(Status))
171 goto done;
172
173 Status = SampSetObjectAttribute(UserObject,
174 L"Groups",
175 REG_BINARY,
176 GroupsBuffer,
177 Length);
178
179 done:
180 if (GroupsBuffer != NULL)
181 midl_user_free(GroupsBuffer);
182
183 return Status;
184 }
185
186
187 NTSTATUS
188 SampGetUserGroupAttributes(IN PSAM_DB_OBJECT DomainObject,
189 IN ULONG UserId,
190 IN ULONG GroupId,
191 OUT PULONG GroupAttributes)
192 {
193 PSAM_DB_OBJECT UserObject = NULL;
194 PGROUP_MEMBERSHIP GroupsBuffer = NULL;
195 ULONG Length = 0;
196 ULONG i;
197 NTSTATUS Status;
198
199 Status = SampOpenUserObject(DomainObject,
200 UserId,
201 0,
202 &UserObject);
203 if (!NT_SUCCESS(Status))
204 {
205 return Status;
206 }
207
208 SampGetObjectAttribute(UserObject,
209 L"Groups",
210 NULL,
211 NULL,
212 &Length);
213
214 if (Length == 0)
215 return STATUS_UNSUCCESSFUL; /* FIXME */
216
217 GroupsBuffer = midl_user_allocate(Length);
218 if (GroupsBuffer == NULL)
219 {
220 Status = STATUS_INSUFFICIENT_RESOURCES;
221 goto done;
222 }
223
224 Status = SampGetObjectAttribute(UserObject,
225 L"Groups",
226 NULL,
227 GroupsBuffer,
228 &Length);
229 if (!NT_SUCCESS(Status))
230 goto done;
231
232 for (i = 0; i < (Length / sizeof(GROUP_MEMBERSHIP)); i++)
233 {
234 if (GroupsBuffer[i].RelativeId == GroupId)
235 {
236 *GroupAttributes = GroupsBuffer[i].Attributes;
237 goto done;
238 }
239 }
240
241 done:
242 if (GroupsBuffer != NULL)
243 midl_user_free(GroupsBuffer);
244
245 if (UserObject != NULL)
246 SampCloseDbObject(UserObject);
247
248 return Status;
249 }
250
251
252 NTSTATUS
253 SampSetUserGroupAttributes(IN PSAM_DB_OBJECT DomainObject,
254 IN ULONG UserId,
255 IN ULONG GroupId,
256 IN ULONG GroupAttributes)
257 {
258 PSAM_DB_OBJECT UserObject = NULL;
259 PGROUP_MEMBERSHIP GroupsBuffer = NULL;
260 ULONG Length = 0;
261 ULONG i;
262 NTSTATUS Status;
263
264 Status = SampOpenUserObject(DomainObject,
265 UserId,
266 0,
267 &UserObject);
268 if (!NT_SUCCESS(Status))
269 {
270 return Status;
271 }
272
273 SampGetObjectAttribute(UserObject,
274 L"Groups",
275 NULL,
276 NULL,
277 &Length);
278
279 if (Length == 0)
280 return STATUS_UNSUCCESSFUL; /* FIXME */
281
282 GroupsBuffer = midl_user_allocate(Length);
283 if (GroupsBuffer == NULL)
284 {
285 Status = STATUS_INSUFFICIENT_RESOURCES;
286 goto done;
287 }
288
289 Status = SampGetObjectAttribute(UserObject,
290 L"Groups",
291 NULL,
292 GroupsBuffer,
293 &Length);
294 if (!NT_SUCCESS(Status))
295 goto done;
296
297 for (i = 0; i < (Length / sizeof(GROUP_MEMBERSHIP)); i++)
298 {
299 if (GroupsBuffer[i].RelativeId == GroupId)
300 {
301 GroupsBuffer[i].Attributes = GroupAttributes;
302 break;
303 }
304 }
305
306 Status = SampSetObjectAttribute(UserObject,
307 L"Groups",
308 REG_BINARY,
309 GroupsBuffer,
310 Length);
311
312 done:
313 if (GroupsBuffer != NULL)
314 midl_user_free(GroupsBuffer);
315
316 if (UserObject != NULL)
317 SampCloseDbObject(UserObject);
318
319 return Status;
320 }
321
322 /* EOF */