Sync with trunk rev.61910 to get latest improvements and bugfixes.
[reactos.git] / dll / win32 / userenv / misc.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2004 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS system libraries
22 * FILE: dll/win32/userenv/misc.c
23 * PURPOSE: User profile code
24 * PROGRAMMER: Eric Kohl
25 */
26
27 #include "precomp.h"
28
29 #include <ndk/sefuncs.h>
30
31 #define NDEBUG
32 #include <debug.h>
33
34 static SID_IDENTIFIER_AUTHORITY LocalSystemAuthority = {SECURITY_NT_AUTHORITY};
35 static SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
36
37 /* FUNCTIONS ***************************************************************/
38
39 LPWSTR
40 AppendBackslash(LPWSTR String)
41 {
42 ULONG Length;
43
44 Length = lstrlenW(String);
45 if (String[Length - 1] != L'\\')
46 {
47 String[Length] = L'\\';
48 Length++;
49 String[Length] = (WCHAR)0;
50 }
51
52 return &String[Length];
53 }
54
55
56 BOOL
57 GetUserSidFromToken(HANDLE hToken,
58 PSID *Sid)
59 {
60 PTOKEN_USER UserBuffer, nsb;
61 PSID pSid = NULL;
62 ULONG Length;
63 NTSTATUS Status;
64
65 Length = 256;
66 UserBuffer = LocalAlloc(LPTR, Length);
67 if (UserBuffer == NULL)
68 {
69 return FALSE;
70 }
71
72 Status = NtQueryInformationToken(hToken,
73 TokenUser,
74 (PVOID)UserBuffer,
75 Length,
76 &Length);
77 if (Status == STATUS_BUFFER_TOO_SMALL)
78 {
79 nsb = LocalReAlloc(UserBuffer, Length, LMEM_MOVEABLE);
80 if (nsb == NULL)
81 {
82 LocalFree(UserBuffer);
83 return FALSE;
84 }
85
86 UserBuffer = nsb;
87 Status = NtQueryInformationToken(hToken,
88 TokenUser,
89 (PVOID)UserBuffer,
90 Length,
91 &Length);
92 }
93
94 if (!NT_SUCCESS (Status))
95 {
96 LocalFree(UserBuffer);
97 return FALSE;
98 }
99
100 Length = RtlLengthSid(UserBuffer->User.Sid);
101
102 pSid = LocalAlloc(LPTR, Length);
103 if (pSid == NULL)
104 {
105 LocalFree(UserBuffer);
106 return FALSE;
107 }
108
109 Status = RtlCopySid(Length, pSid, UserBuffer->User.Sid);
110
111 LocalFree(UserBuffer);
112
113 if (!NT_SUCCESS (Status))
114 {
115 LocalFree(pSid);
116 return FALSE;
117 }
118
119 *Sid = pSid;
120
121 return TRUE;
122 }
123
124
125 BOOL
126 GetUserSidStringFromToken(HANDLE hToken,
127 PUNICODE_STRING SidString)
128 {
129 PTOKEN_USER UserBuffer, nsb;
130 ULONG Length;
131 NTSTATUS Status;
132
133 Length = 256;
134 UserBuffer = LocalAlloc(LPTR, Length);
135 if (UserBuffer == NULL)
136 return FALSE;
137
138 Status = NtQueryInformationToken(hToken,
139 TokenUser,
140 (PVOID)UserBuffer,
141 Length,
142 &Length);
143 if (Status == STATUS_BUFFER_TOO_SMALL)
144 {
145 nsb = LocalReAlloc(UserBuffer,
146 Length,
147 LMEM_MOVEABLE);
148 if (nsb == NULL)
149 {
150 LocalFree(UserBuffer);
151 return FALSE;
152 }
153
154 UserBuffer = nsb;
155 Status = NtQueryInformationToken(hToken,
156 TokenUser,
157 (PVOID)UserBuffer,
158 Length,
159 &Length);
160 }
161
162 if (!NT_SUCCESS (Status))
163 {
164 LocalFree(UserBuffer);
165 SetLastError(RtlNtStatusToDosError(Status));
166 return FALSE;
167 }
168
169 DPRINT("SidLength: %lu\n", RtlLengthSid (UserBuffer->User.Sid));
170
171 Status = RtlConvertSidToUnicodeString(SidString,
172 UserBuffer->User.Sid,
173 TRUE);
174
175 LocalFree(UserBuffer);
176
177 if (!NT_SUCCESS(Status))
178 {
179 SetLastError(RtlNtStatusToDosError(Status));
180 return FALSE;
181 }
182
183 DPRINT("SidString.Length: %lu\n", SidString->Length);
184 DPRINT("SidString.MaximumLength: %lu\n", SidString->MaximumLength);
185 DPRINT("SidString: '%wZ'\n", SidString);
186
187 return TRUE;
188 }
189
190
191 PSECURITY_DESCRIPTOR
192 CreateDefaultSecurityDescriptor(VOID)
193 {
194 PSID LocalSystemSid = NULL;
195 PSID AdministratorsSid = NULL;
196 PSID EveryoneSid = NULL;
197 PACL Dacl;
198 DWORD DaclSize;
199 PSECURITY_DESCRIPTOR pSD = NULL;
200
201 /* create the SYSTEM, Administrators and Everyone SIDs */
202 if (!AllocateAndInitializeSid(&LocalSystemAuthority,
203 1,
204 SECURITY_LOCAL_SYSTEM_RID,
205 0,
206 0,
207 0,
208 0,
209 0,
210 0,
211 0,
212 &LocalSystemSid) ||
213 !AllocateAndInitializeSid(&LocalSystemAuthority,
214 2,
215 SECURITY_BUILTIN_DOMAIN_RID,
216 DOMAIN_ALIAS_RID_ADMINS,
217 0,
218 0,
219 0,
220 0,
221 0,
222 0,
223 &AdministratorsSid) ||
224 !AllocateAndInitializeSid(&WorldAuthority,
225 1,
226 SECURITY_WORLD_RID,
227 0,
228 0,
229 0,
230 0,
231 0,
232 0,
233 0,
234 &EveryoneSid))
235 {
236 DPRINT1("Failed initializing the SIDs for the default security descriptor (0x%p, 0x%p, 0x%p)\n",
237 LocalSystemSid, AdministratorsSid, EveryoneSid);
238 goto Cleanup;
239 }
240
241 /* allocate the security descriptor and DACL */
242 DaclSize = sizeof(ACL) +
243 ((GetLengthSid(LocalSystemSid) +
244 GetLengthSid(AdministratorsSid) +
245 GetLengthSid(EveryoneSid)) +
246 (3 * FIELD_OFFSET(ACCESS_ALLOWED_ACE,
247 SidStart)));
248
249 pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED,
250 (SIZE_T)DaclSize + sizeof(SECURITY_DESCRIPTOR));
251 if (pSD == NULL)
252 {
253 DPRINT1("Failed to allocate the default security descriptor and ACL\n");
254 goto Cleanup;
255 }
256
257 if (!InitializeSecurityDescriptor(pSD,
258 SECURITY_DESCRIPTOR_REVISION))
259 {
260 DPRINT1("Failed to initialize the default security descriptor\n");
261 goto Cleanup;
262 }
263
264 /* initialize and build the DACL */
265 Dacl = (PACL)((ULONG_PTR)pSD + sizeof(SECURITY_DESCRIPTOR));
266 if (!InitializeAcl(Dacl,
267 (DWORD)DaclSize,
268 ACL_REVISION))
269 {
270 DPRINT1("Failed to initialize the DACL of the default security descriptor\n");
271 goto Cleanup;
272 }
273
274 /* add the SYSTEM Ace */
275 if (!AddAccessAllowedAce(Dacl,
276 ACL_REVISION,
277 GENERIC_ALL,
278 LocalSystemSid))
279 {
280 DPRINT1("Failed to add the SYSTEM ACE\n");
281 goto Cleanup;
282 }
283
284 /* add the Administrators Ace */
285 if (!AddAccessAllowedAce(Dacl,
286 ACL_REVISION,
287 GENERIC_ALL,
288 AdministratorsSid))
289 {
290 DPRINT1("Failed to add the Administrators ACE\n");
291 goto Cleanup;
292 }
293
294 /* add the Everyone Ace */
295 if (!AddAccessAllowedAce(Dacl,
296 ACL_REVISION,
297 GENERIC_EXECUTE,
298 EveryoneSid))
299 {
300 DPRINT1("Failed to add the Everyone ACE\n");
301 goto Cleanup;
302 }
303
304 /* set the DACL */
305 if (!SetSecurityDescriptorDacl(pSD,
306 TRUE,
307 Dacl,
308 FALSE))
309 {
310 DPRINT1("Failed to set the DACL of the default security descriptor\n");
311
312 Cleanup:
313 if (pSD != NULL)
314 {
315 LocalFree((HLOCAL)pSD);
316 pSD = NULL;
317 }
318 }
319
320 if (LocalSystemSid != NULL)
321 {
322 FreeSid(LocalSystemSid);
323 }
324 if (AdministratorsSid != NULL)
325 {
326 FreeSid(AdministratorsSid);
327 }
328 if (EveryoneSid != NULL)
329 {
330 FreeSid(EveryoneSid);
331 }
332
333 return pSD;
334 }
335
336 /* Dynamic DLL loading interface **********************************************/
337
338 /* OLE32.DLL import table */
339 DYN_MODULE DynOle32 =
340 {
341 L"ole32.dll",
342 {
343 "CoInitialize",
344 "CoCreateInstance",
345 "CoUninitialize",
346 NULL
347 }
348 };
349
350
351 /*
352 * Use this function to load functions from other modules. We cannot statically
353 * link to e.g. ole32.dll because those dlls would get loaded on startup with
354 * winlogon and they may try to register classes etc when not even a window station
355 * has been created!
356 */
357 BOOL
358 LoadDynamicImports(PDYN_MODULE Module,
359 PDYN_FUNCS DynFuncs)
360 {
361 LPSTR *fname;
362 PVOID *fn;
363
364 ZeroMemory(DynFuncs, sizeof(DYN_FUNCS));
365
366 DynFuncs->hModule = LoadLibraryW(Module->Library);
367 if (!DynFuncs->hModule)
368 {
369 return FALSE;
370 }
371
372 fn = &DynFuncs->fn.foo;
373
374 /* load the imports */
375 for (fname = Module->Functions; *fname != NULL; fname++)
376 {
377 *fn = GetProcAddress(DynFuncs->hModule, *fname);
378 if (*fn == NULL)
379 {
380 FreeLibrary(DynFuncs->hModule);
381 DynFuncs->hModule = (HMODULE)0;
382
383 return FALSE;
384 }
385
386 fn++;
387 }
388
389 return TRUE;
390 }
391
392
393 VOID
394 UnloadDynamicImports(PDYN_FUNCS DynFuncs)
395 {
396 if (DynFuncs->hModule)
397 {
398 FreeLibrary(DynFuncs->hModule);
399 DynFuncs->hModule = (HMODULE)0;
400 }
401 }
402
403 /* EOF */