[MSI]
[reactos.git] / reactos / dll / win32 / samlib / samlib.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 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS system libraries
23 * PURPOSE: SAM interface library
24 * FILE: lib/samlib/samlib.c
25 * PROGRAMER: Eric Kohl
26 */
27
28 /* INCLUDES *****************************************************************/
29 #define WIN32_NO_STATUS
30 #include <windows.h>
31 #include <winerror.h>
32 #define NTOS_MODE_USER
33 #include <ndk/ntndk.h>
34
35 #define NDEBUG
36 #include "debug.h"
37
38
39 /* GLOBALS *******************************************************************/
40
41
42 /* FUNCTIONS *****************************************************************/
43
44
45 static BOOL
46 CreateBuiltinAliases (HKEY hAliasesKey)
47 {
48 return TRUE;
49 }
50
51
52 static BOOL
53 CreateBuiltinGroups (HKEY hGroupsKey)
54 {
55 return TRUE;
56 }
57
58
59 static BOOL
60 CreateBuiltinUsers (HKEY hUsersKey)
61 {
62 return TRUE;
63 }
64
65
66 BOOL WINAPI
67 SamInitializeSAM (VOID)
68 {
69 DWORD dwDisposition;
70 HKEY hSamKey;
71 HKEY hDomainsKey;
72 HKEY hAccountKey;
73 HKEY hBuiltinKey;
74 HKEY hAliasesKey;
75 HKEY hGroupsKey;
76 HKEY hUsersKey;
77
78 DPRINT("SamInitializeSAM() called\n");
79
80 if (RegCreateKeyExW (HKEY_LOCAL_MACHINE,
81 L"SAM\\SAM",
82 0,
83 NULL,
84 REG_OPTION_NON_VOLATILE,
85 KEY_ALL_ACCESS,
86 NULL,
87 &hSamKey,
88 &dwDisposition))
89 {
90 DPRINT1 ("Failed to create 'Sam' key! (Error %lu)\n", GetLastError());
91 return FALSE;
92 }
93
94 if (RegCreateKeyExW (hSamKey,
95 L"Domains",
96 0,
97 NULL,
98 REG_OPTION_NON_VOLATILE,
99 KEY_ALL_ACCESS,
100 NULL,
101 &hDomainsKey,
102 &dwDisposition))
103 {
104 DPRINT1 ("Failed to create 'Domains' key! (Error %lu)\n", GetLastError());
105 RegCloseKey (hSamKey);
106 return FALSE;
107 }
108
109 RegCloseKey (hSamKey);
110
111 /* Create the 'Domains\\Account' key */
112 if (RegCreateKeyExW (hDomainsKey,
113 L"Account",
114 0,
115 NULL,
116 REG_OPTION_NON_VOLATILE,
117 KEY_ALL_ACCESS,
118 NULL,
119 &hAccountKey,
120 &dwDisposition))
121 {
122 DPRINT1 ("Failed to create 'Domains\\Account' key! (Error %lu)\n", GetLastError());
123 RegCloseKey (hDomainsKey);
124 return FALSE;
125 }
126
127
128 /* Create the 'Account\Aliases' key */
129 if (RegCreateKeyExW (hAccountKey,
130 L"Aliases",
131 0,
132 NULL,
133 REG_OPTION_NON_VOLATILE,
134 KEY_ALL_ACCESS,
135 NULL,
136 &hAliasesKey,
137 &dwDisposition))
138 {
139 DPRINT1 ("Failed to create 'Account\\Aliases' key! (Error %lu)\n", GetLastError());
140 RegCloseKey (hAccountKey);
141 RegCloseKey (hDomainsKey);
142 return FALSE;
143 }
144
145 RegCloseKey (hAliasesKey);
146
147
148 /* Create the 'Account\Groups' key */
149 if (RegCreateKeyExW (hAccountKey,
150 L"Groups",
151 0,
152 NULL,
153 REG_OPTION_NON_VOLATILE,
154 KEY_ALL_ACCESS,
155 NULL,
156 &hGroupsKey,
157 &dwDisposition))
158 {
159 DPRINT1 ("Failed to create 'Account\\Groups' key! (Error %lu)\n", GetLastError());
160 RegCloseKey (hAccountKey);
161 RegCloseKey (hDomainsKey);
162 return FALSE;
163 }
164
165 RegCloseKey (hGroupsKey);
166
167
168 /* Create the 'Account\Users' key */
169 if (RegCreateKeyExW (hAccountKey,
170 L"Users",
171 0,
172 NULL,
173 REG_OPTION_NON_VOLATILE,
174 KEY_ALL_ACCESS,
175 NULL,
176 &hUsersKey,
177 &dwDisposition))
178 {
179 DPRINT1 ("Failed to create 'Account\\Users' key! (Error %lu)\n", GetLastError());
180 RegCloseKey (hAccountKey);
181 RegCloseKey (hDomainsKey);
182 return FALSE;
183 }
184
185 RegCloseKey (hUsersKey);
186
187 RegCloseKey (hAccountKey);
188
189
190 /* Create the 'Domains\\Builtin' */
191 if (RegCreateKeyExW (hDomainsKey,
192 L"Builtin",
193 0,
194 NULL,
195 REG_OPTION_NON_VOLATILE,
196 KEY_ALL_ACCESS,
197 NULL,
198 &hBuiltinKey,
199 &dwDisposition))
200 {
201 DPRINT1 ("Failed to create Builtin key! (Error %lu)\n", GetLastError());
202 RegCloseKey (hDomainsKey);
203 return FALSE;
204 }
205
206
207 /* Create the 'Builtin\Aliases' key */
208 if (RegCreateKeyExW (hBuiltinKey,
209 L"Aliases",
210 0,
211 NULL,
212 REG_OPTION_NON_VOLATILE,
213 KEY_ALL_ACCESS,
214 NULL,
215 &hAliasesKey,
216 &dwDisposition))
217 {
218 DPRINT1 ("Failed to create 'Builtin\\Aliases' key! (Error %lu)\n", GetLastError());
219 RegCloseKey (hBuiltinKey);
220 RegCloseKey (hDomainsKey);
221 return FALSE;
222 }
223
224 /* Create builtin aliases */
225 if (!CreateBuiltinAliases (hAliasesKey))
226 {
227 DPRINT1 ("Failed to create builtin aliases!\n");
228 RegCloseKey (hAliasesKey);
229 RegCloseKey (hBuiltinKey);
230 RegCloseKey (hDomainsKey);
231 return FALSE;
232 }
233
234 RegCloseKey (hAliasesKey);
235
236
237 /* Create the 'Builtin\Groups' key */
238 if (RegCreateKeyExW (hBuiltinKey,
239 L"Groups",
240 0,
241 NULL,
242 REG_OPTION_NON_VOLATILE,
243 KEY_ALL_ACCESS,
244 NULL,
245 &hGroupsKey,
246 &dwDisposition))
247 {
248 DPRINT1 ("Failed to create 'Builtin\\Groups' key! (Error %lu)\n", GetLastError());
249 RegCloseKey (hBuiltinKey);
250 RegCloseKey (hDomainsKey);
251 return FALSE;
252 }
253
254 /* Create builtin groups */
255 if (!CreateBuiltinGroups (hGroupsKey))
256 {
257 DPRINT1 ("Failed to create builtin groups!\n");
258 RegCloseKey (hGroupsKey);
259 RegCloseKey (hBuiltinKey);
260 RegCloseKey (hDomainsKey);
261 return FALSE;
262 }
263
264 RegCloseKey (hGroupsKey);
265
266
267 /* Create the 'Builtin\Users' key */
268 if (RegCreateKeyExW (hBuiltinKey,
269 L"Users",
270 0,
271 NULL,
272 REG_OPTION_NON_VOLATILE,
273 KEY_ALL_ACCESS,
274 NULL,
275 &hUsersKey,
276 &dwDisposition))
277 {
278 DPRINT1 ("Failed to create 'Builtin\\Users' key! (Error %lu)\n", GetLastError());
279 RegCloseKey (hBuiltinKey);
280 RegCloseKey (hDomainsKey);
281 return FALSE;
282 }
283
284 /* Create builtin users */
285 if (!CreateBuiltinUsers (hUsersKey))
286 {
287 DPRINT1 ("Failed to create builtin users!\n");
288 RegCloseKey (hUsersKey);
289 RegCloseKey (hBuiltinKey);
290 RegCloseKey (hDomainsKey);
291 return FALSE;
292 }
293
294 RegCloseKey (hUsersKey);
295
296 RegCloseKey (hBuiltinKey);
297
298 RegCloseKey (hDomainsKey);
299
300 DPRINT ("SamInitializeSAM() done\n");
301
302 return TRUE;
303 }
304
305
306 BOOL WINAPI
307 SamGetDomainSid (PSID *Sid)
308 {
309 DPRINT ("SamGetDomainSid() called\n");
310
311 return FALSE;
312 }
313
314
315 BOOL WINAPI
316 SamSetDomainSid (PSID Sid)
317 {
318 HKEY hAccountKey;
319
320 DPRINT ("SamSetDomainSid() called\n");
321
322 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
323 L"SAM\\SAM\\Domains\\Account",
324 0,
325 KEY_ALL_ACCESS,
326 &hAccountKey))
327 {
328 DPRINT1 ("Failed to open the Account key! (Error %lu)\n", GetLastError());
329 return FALSE;
330 }
331
332 if (RegSetValueExW (hAccountKey,
333 L"Sid",
334 0,
335 REG_BINARY,
336 (LPBYTE)Sid,
337 RtlLengthSid (Sid)))
338 {
339 DPRINT1 ("Failed to set Domain-SID value! (Error %lu)\n", GetLastError());
340 RegCloseKey (hAccountKey);
341 return FALSE;
342 }
343
344 RegCloseKey (hAccountKey);
345
346 DPRINT ("SamSetDomainSid() called\n");
347
348 return TRUE;
349 }
350
351
352 /*
353 * ERROR_USER_EXISTS
354 */
355 BOOL WINAPI
356 SamCreateUser (PWSTR UserName,
357 PWSTR UserPassword,
358 PSID UserSid)
359 {
360 DWORD dwDisposition;
361 HKEY hUsersKey;
362 HKEY hUserKey;
363
364 DPRINT ("SamCreateUser() called\n");
365
366 /* FIXME: Check whether the SID is a real user sid */
367
368 /* Open the Users key */
369 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
370 L"SAM\\SAM\\Domains\\Account\\Users",
371 0,
372 KEY_ALL_ACCESS,
373 &hUsersKey))
374 {
375 DPRINT1 ("Failed to open Account key! (Error %lu)\n", GetLastError());
376 return FALSE;
377 }
378
379 /* Create user name key */
380 if (RegCreateKeyExW (hUsersKey,
381 UserName,
382 0,
383 NULL,
384 REG_OPTION_NON_VOLATILE,
385 KEY_ALL_ACCESS,
386 NULL,
387 &hUserKey,
388 &dwDisposition))
389 {
390 DPRINT1 ("Failed to create/open the user key! (Error %lu)\n", GetLastError());
391 RegCloseKey (hUsersKey);
392 return FALSE;
393 }
394
395 RegCloseKey (hUsersKey);
396
397 if (dwDisposition == REG_OPENED_EXISTING_KEY)
398 {
399 DPRINT1 ("User already exists!\n");
400 RegCloseKey (hUserKey);
401 SetLastError (ERROR_USER_EXISTS);
402 return FALSE;
403 }
404
405
406 /* Set 'Name' value */
407 if (RegSetValueExW (hUserKey,
408 L"Name",
409 0,
410 REG_SZ,
411 (LPBYTE)UserName,
412 (wcslen (UserName) + 1) * sizeof (WCHAR)))
413 {
414 DPRINT1 ("Failed to set the user name value! (Error %lu)\n", GetLastError());
415 RegCloseKey (hUserKey);
416 return FALSE;
417 }
418
419 /* Set 'Password' value */
420 if (RegSetValueExW (hUserKey,
421 L"Password",
422 0,
423 REG_SZ,
424 (LPBYTE)UserPassword,
425 (wcslen (UserPassword) + 1) * sizeof (WCHAR)))
426 {
427 DPRINT1 ("Failed to set the user name value! (Error %lu)\n", GetLastError());
428 RegCloseKey (hUserKey);
429 return FALSE;
430 }
431
432 /* Set 'Sid' value */
433 if (RegSetValueExW (hUserKey,
434 L"Sid",
435 0,
436 REG_BINARY,
437 (LPBYTE)UserSid,
438 RtlLengthSid (UserSid)))
439 {
440 DPRINT1 ("Failed to set the user SID value! (Error %lu)\n", GetLastError());
441 RegCloseKey (hUserKey);
442 return FALSE;
443 }
444
445 RegCloseKey (hUserKey);
446
447 DPRINT ("SamCreateUser() done\n");
448
449 return TRUE;
450 }
451
452
453 /*
454 * ERROR_WRONG_PASSWORD
455 * ERROR_NO_SUCH_USER
456 */
457 BOOL WINAPI
458 SamCheckUserPassword (PWSTR UserName,
459 PWSTR UserPassword)
460 {
461 WCHAR szPassword[256];
462 DWORD dwLength;
463 HKEY hUsersKey;
464 HKEY hUserKey;
465
466 DPRINT ("SamCheckUserPassword() called\n");
467
468 /* Open the Users key */
469 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
470 L"SAM\\SAM\\Domains\\Account\\Users",
471 0,
472 KEY_READ,
473 &hUsersKey))
474 {
475 DPRINT1 ("Failed to open Users key! (Error %lu)\n", GetLastError());
476 return FALSE;
477 }
478
479 /* Open the user key */
480 if (RegOpenKeyExW (hUsersKey,
481 UserName,
482 0,
483 KEY_READ,
484 &hUserKey))
485 {
486 if (GetLastError () == ERROR_FILE_NOT_FOUND)
487 {
488 DPRINT1 ("Invalid user name!\n");
489 SetLastError (ERROR_NO_SUCH_USER);
490 }
491 else
492 {
493 DPRINT1 ("Failed to open user key! (Error %lu)\n", GetLastError());
494 }
495
496 RegCloseKey (hUsersKey);
497 return FALSE;
498 }
499
500 RegCloseKey (hUsersKey);
501
502 /* Get the password */
503 dwLength = 256 * sizeof(WCHAR);
504 if (RegQueryValueExW (hUserKey,
505 L"Password",
506 NULL,
507 NULL,
508 (LPBYTE)szPassword,
509 &dwLength))
510 {
511 DPRINT1 ("Failed to read the password! (Error %lu)\n", GetLastError());
512 RegCloseKey (hUserKey);
513 return FALSE;
514 }
515
516 RegCloseKey (hUserKey);
517
518 /* Compare passwords */
519 if ((wcslen (szPassword) != wcslen (UserPassword)) ||
520 (wcscmp (szPassword, UserPassword) != 0))
521 {
522 DPRINT1 ("Wrong password!\n");
523 SetLastError (ERROR_WRONG_PASSWORD);
524 return FALSE;
525 }
526
527 DPRINT ("SamCheckUserPassword() done\n");
528
529 return TRUE;
530 }
531
532
533 BOOL WINAPI
534 SamGetUserSid (PWSTR UserName,
535 PSID *Sid)
536 {
537 PSID lpSid;
538 DWORD dwLength;
539 HKEY hUsersKey;
540 HKEY hUserKey;
541
542 DPRINT ("SamGetUserSid() called\n");
543
544 if (Sid != NULL)
545 *Sid = NULL;
546
547 /* Open the Users key */
548 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
549 L"SAM\\SAM\\Domains\\Account\\Users",
550 0,
551 KEY_READ,
552 &hUsersKey))
553 {
554 DPRINT1 ("Failed to open Users key! (Error %lu)\n", GetLastError());
555 return FALSE;
556 }
557
558 /* Open the user key */
559 if (RegOpenKeyExW (hUsersKey,
560 UserName,
561 0,
562 KEY_READ,
563 &hUserKey))
564 {
565 if (GetLastError () == ERROR_FILE_NOT_FOUND)
566 {
567 DPRINT1 ("Invalid user name!\n");
568 SetLastError (ERROR_NO_SUCH_USER);
569 }
570 else
571 {
572 DPRINT1 ("Failed to open user key! (Error %lu)\n", GetLastError());
573 }
574
575 RegCloseKey (hUsersKey);
576 return FALSE;
577 }
578
579 RegCloseKey (hUsersKey);
580
581 /* Get SID size */
582 dwLength = 0;
583 if (RegQueryValueExW (hUserKey,
584 L"Sid",
585 NULL,
586 NULL,
587 NULL,
588 &dwLength))
589 {
590 DPRINT1 ("Failed to read the SID size! (Error %lu)\n", GetLastError());
591 RegCloseKey (hUserKey);
592 return FALSE;
593 }
594
595 /* Allocate sid buffer */
596 DPRINT ("Required SID buffer size: %lu\n", dwLength);
597 lpSid = (PSID)RtlAllocateHeap (RtlGetProcessHeap (),
598 0,
599 dwLength);
600 if (lpSid == NULL)
601 {
602 DPRINT1 ("Failed to allocate SID buffer!\n");
603 RegCloseKey (hUserKey);
604 return FALSE;
605 }
606
607 /* Read sid */
608 if (RegQueryValueExW (hUserKey,
609 L"Sid",
610 NULL,
611 NULL,
612 (LPBYTE)lpSid,
613 &dwLength))
614 {
615 DPRINT1 ("Failed to read the SID! (Error %lu)\n", GetLastError());
616 RtlFreeHeap (RtlGetProcessHeap (),
617 0,
618 lpSid);
619 RegCloseKey (hUserKey);
620 return FALSE;
621 }
622
623 RegCloseKey (hUserKey);
624
625 *Sid = lpSid;
626
627 DPRINT ("SamGetUserSid() done\n");
628
629 return TRUE;
630 }
631
632 /* EOF */