Release 1.5.29.
[wine] / dlls / advapi32 / lsa.c
1 /*
2  * Implementation of the Local Security Authority API
3  *
4  * Copyright 1999 Juergen Schmied
5  * Copyright 2002 Andriy Palamarchuk
6  * Copyright 2004 Mike McCormack
7  * Copyright 2005 Hans Leidekker
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #include <stdarg.h>
25
26 #include "ntstatus.h"
27 #define WIN32_NO_STATUS
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winreg.h"
31 #include "winternl.h"
32 #include "advapi32_misc.h"
33
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
38
39 #define ADVAPI_ForceLocalComputer(ServerName, FailureCode) \
40     if (!ADVAPI_IsLocalComputer(ServerName)) \
41 { \
42         FIXME("Action Implemented for local computer only. " \
43               "Requested for server %s\n", debugstr_w(ServerName)); \
44         return FailureCode; \
45 }
46
47 static void dumpLsaAttributes(const LSA_OBJECT_ATTRIBUTES *oa)
48 {
49     if (oa)
50     {
51         TRACE("\n\tlength=%u, rootdir=%p, objectname=%s\n\tattr=0x%08x, sid=%s qos=%p\n",
52               oa->Length, oa->RootDirectory,
53               oa->ObjectName?debugstr_w(oa->ObjectName->Buffer):"null",
54               oa->Attributes, debugstr_sid(oa->SecurityDescriptor),
55               oa->SecurityQualityOfService);
56     }
57 }
58
59 static void* ADVAPI_GetDomainName(unsigned sz, unsigned ofs)
60 {
61     HKEY key;
62     LONG ret;
63     BYTE* ptr = NULL;
64     UNICODE_STRING* ustr;
65
66     static const WCHAR wVNETSUP[] = {
67         'S','y','s','t','e','m','\\',
68         'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
69         'S','e','r','v','i','c','e','s','\\',
70         'V','x','D','\\','V','N','E','T','S','U','P','\0'};
71
72     ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wVNETSUP, 0, KEY_READ, &key);
73     if (ret == ERROR_SUCCESS)
74     {
75         DWORD size = 0;
76         static const WCHAR wg[] = { 'W','o','r','k','g','r','o','u','p',0 };
77
78         ret = RegQueryValueExW(key, wg, NULL, NULL, NULL, &size);
79         if (ret == ERROR_MORE_DATA || ret == ERROR_SUCCESS)
80         {
81             ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz + size);
82             if (!ptr) return NULL;
83             ustr = (UNICODE_STRING*)(ptr + ofs);
84             ustr->MaximumLength = size;
85             ustr->Buffer = (WCHAR*)(ptr + sz);
86             ret = RegQueryValueExW(key, wg, NULL, NULL, (LPBYTE)ustr->Buffer, &size);
87             if (ret != ERROR_SUCCESS)
88             {
89                 HeapFree(GetProcessHeap(), 0, ptr);
90                 ptr = NULL;
91             }   
92             else ustr->Length = size - sizeof(WCHAR);
93         }
94         RegCloseKey(key);
95     }
96     if (!ptr)
97     {
98         static const WCHAR wDomain[] = {'D','O','M','A','I','N','\0'};
99         ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
100                         sz + sizeof(wDomain));
101         if (!ptr) return NULL;
102         ustr = (UNICODE_STRING*)(ptr + ofs);
103         ustr->MaximumLength = sizeof(wDomain);
104         ustr->Buffer = (WCHAR*)(ptr + sz);
105         ustr->Length = sizeof(wDomain) - sizeof(WCHAR);
106         memcpy(ustr->Buffer, wDomain, sizeof(wDomain));
107     }
108     return ptr;
109 }
110
111 /******************************************************************************
112  * LsaAddAccountRights [ADVAPI32.@]
113  *
114  */
115 NTSTATUS WINAPI LsaAddAccountRights(
116     LSA_HANDLE policy,
117     PSID sid,
118     PLSA_UNICODE_STRING rights,
119     ULONG count)
120 {
121     FIXME("(%p,%p,%p,0x%08x) stub\n", policy, sid, rights, count);
122     return STATUS_OBJECT_NAME_NOT_FOUND;
123 }
124
125 /******************************************************************************
126  * LsaClose [ADVAPI32.@]
127  *
128  * Closes a handle to a Policy or TrustedDomain.
129  *
130  * PARAMS
131  *  ObjectHandle [I] Handle to a Policy or TrustedDomain.
132  *
133  * RETURNS
134  *  Success: STATUS_SUCCESS.
135  *  Failure: NTSTATUS code.
136  */
137 NTSTATUS WINAPI LsaClose(IN LSA_HANDLE ObjectHandle)
138 {
139     FIXME("(%p) stub\n", ObjectHandle);
140     return STATUS_SUCCESS;
141 }
142
143 /******************************************************************************
144  * LsaCreateTrustedDomainEx [ADVAPI32.@]
145  *
146  */
147 NTSTATUS WINAPI LsaCreateTrustedDomainEx(
148     LSA_HANDLE policy,
149     PTRUSTED_DOMAIN_INFORMATION_EX domain_info,
150     PTRUSTED_DOMAIN_AUTH_INFORMATION auth_info,
151     ACCESS_MASK access,
152     PLSA_HANDLE domain)
153 {
154     FIXME("(%p,%p,%p,0x%08x,%p) stub\n", policy, domain_info, auth_info,
155           access, domain);
156     return STATUS_SUCCESS;
157 }
158
159 /******************************************************************************
160  * LsaDeleteTrustedDomain [ADVAPI32.@]
161  *
162  */
163 NTSTATUS WINAPI LsaDeleteTrustedDomain(LSA_HANDLE policy, PSID sid)
164 {
165     FIXME("(%p,%p) stub\n", policy, sid);
166     return STATUS_SUCCESS;
167 }
168
169 /******************************************************************************
170  * LsaEnumerateAccountRights [ADVAPI32.@]
171  *
172  */
173 NTSTATUS WINAPI LsaEnumerateAccountRights(
174     LSA_HANDLE policy,
175     PSID sid,
176     PLSA_UNICODE_STRING *rights,
177     PULONG count)
178 {
179     FIXME("(%p,%p,%p,%p) stub\n", policy, sid, rights, count);
180     *rights = 0;
181     *count = 0;
182     return STATUS_OBJECT_NAME_NOT_FOUND;
183 }
184
185 /******************************************************************************
186  * LsaEnumerateAccountsWithUserRight [ADVAPI32.@]
187  *
188  */
189 NTSTATUS WINAPI LsaEnumerateAccountsWithUserRight(
190     LSA_HANDLE policy,
191     PLSA_UNICODE_STRING rights,
192     PVOID *buffer,
193     PULONG count)
194 {
195     FIXME("(%p,%p,%p,%p) stub\n", policy, rights, buffer, count);
196     return STATUS_NO_MORE_ENTRIES;
197 }
198
199 /******************************************************************************
200  * LsaEnumerateTrustedDomains [ADVAPI32.@]
201  *
202  * Returns the names and SIDs of trusted domains.
203  *
204  * PARAMS
205  *  PolicyHandle          [I] Handle to a Policy object.
206  *  EnumerationContext    [I] Pointer to an enumeration handle.
207  *  Buffer                [O] Contains the names and SIDs of trusted domains.
208  *  PreferredMaximumLength[I] Preferred maximum size in bytes of Buffer.
209  *  CountReturned         [O] Number of elements in Buffer.
210  *
211  * RETURNS
212  *  Success: STATUS_SUCCESS,
213  *           STATUS_MORE_ENTRIES,
214  *           STATUS_NO_MORE_ENTRIES
215  *  Failure: NTSTATUS code.
216  *
217  * NOTES
218  *  LsaEnumerateTrustedDomains can be called multiple times to enumerate
219  *  all trusted domains.
220  */
221 NTSTATUS WINAPI LsaEnumerateTrustedDomains(
222     IN LSA_HANDLE PolicyHandle,
223     IN PLSA_ENUMERATION_HANDLE EnumerationContext,
224     OUT PVOID* Buffer,
225     IN ULONG PreferredMaximumLength,
226     OUT PULONG CountReturned)
227 {
228     FIXME("(%p,%p,%p,0x%08x,%p) stub\n", PolicyHandle, EnumerationContext,
229           Buffer, PreferredMaximumLength, CountReturned);
230
231     if (CountReturned) *CountReturned = 0;
232     return STATUS_SUCCESS;
233 }
234
235 /******************************************************************************
236  * LsaEnumerateTrustedDomainsEx [ADVAPI32.@]
237  *
238  */
239 NTSTATUS WINAPI LsaEnumerateTrustedDomainsEx(
240     LSA_HANDLE policy,
241     PLSA_ENUMERATION_HANDLE context,
242     PVOID *buffer,
243     ULONG length,
244     PULONG count)
245 {
246     FIXME("(%p,%p,%p,0x%08x,%p) stub\n", policy, context, buffer, length, count);
247
248     if (count) *count = 0;
249     return STATUS_SUCCESS;
250 }
251
252 /******************************************************************************
253  * LsaFreeMemory [ADVAPI32.@]
254  *
255  * Frees memory allocated by a LSA function.
256  *
257  * PARAMS
258  *  Buffer [I] Memory buffer to free.
259  *
260  * RETURNS
261  *  Success: STATUS_SUCCESS.
262  *  Failure: NTSTATUS code.
263  */
264 NTSTATUS WINAPI LsaFreeMemory(IN PVOID Buffer)
265 {
266     TRACE("(%p)\n", Buffer);
267
268     HeapFree(GetProcessHeap(), 0, Buffer);
269     return STATUS_SUCCESS;
270 }
271
272 /******************************************************************************
273  * LsaLookupNames [ADVAPI32.@]
274  *
275  * Returns the SIDs of an array of user, group, or local group names.
276  *
277  * PARAMS
278  *  PolicyHandle      [I] Handle to a Policy object.
279  *  Count             [I] Number of names in Names.
280  *  Names             [I] Array of names to lookup.
281  *  ReferencedDomains [O] Array of domains where the names were found.
282  *  Sids              [O] Array of SIDs corresponding to Names.
283  *
284  * RETURNS
285  *  Success: STATUS_SUCCESS,
286  *           STATUS_SOME_NOT_MAPPED
287  *  Failure: STATUS_NONE_MAPPED or NTSTATUS code.
288  */
289 NTSTATUS WINAPI LsaLookupNames(
290     IN LSA_HANDLE PolicyHandle,
291     IN ULONG Count,
292     IN PLSA_UNICODE_STRING Names,
293     OUT PLSA_REFERENCED_DOMAIN_LIST* ReferencedDomains,
294     OUT PLSA_TRANSLATED_SID* Sids)
295 {
296     FIXME("(%p,0x%08x,%p,%p,%p) stub\n", PolicyHandle, Count, Names,
297           ReferencedDomains, Sids);
298
299     return STATUS_NONE_MAPPED;
300 }
301
302 static BOOL lookup_name( LSA_UNICODE_STRING *name, SID *sid, DWORD *sid_size, WCHAR *domain,
303                          DWORD *domain_size, SID_NAME_USE *use, BOOL *handled )
304 {
305     BOOL ret;
306
307     ret = lookup_local_wellknown_name( name, sid, sid_size, domain, domain_size, use, handled );
308     if (!*handled)
309         ret = lookup_local_user_name( name, sid, sid_size, domain, domain_size, use, handled );
310
311     return ret;
312 }
313
314 /* Adds domain info to referenced domain list.
315    Domain list is stored as plain buffer, layout is:
316
317        LSA_REFERENCED_DOMAIN_LIST,
318        LSA_TRUST_INFORMATION array,
319        domain data array of
320            {
321                domain name data (WCHAR buffer),
322                SID data
323            }
324
325    Parameters:
326        list   [I]  referenced list pointer
327        domain [I]  domain name string
328        data   [IO] pointer to domain data array
329 */
330 static LONG lsa_reflist_add_domain(LSA_REFERENCED_DOMAIN_LIST *list, LSA_UNICODE_STRING *domain, char **data)
331 {
332     ULONG sid_size = 0,domain_size = 0;
333     BOOL handled = FALSE;
334     SID_NAME_USE use;
335     LONG i;
336
337     for (i = 0; i < list->Entries; i++)
338     {
339         /* try to reuse index */
340         if ((list->Domains[i].Name.Length == domain->Length) &&
341             (!strncmpiW(list->Domains[i].Name.Buffer, domain->Buffer, (domain->Length / sizeof(WCHAR)))))
342         {
343             return i;
344         }
345     }
346
347     /* no matching domain found, store name */
348     list->Domains[list->Entries].Name.Length = domain->Length;
349     list->Domains[list->Entries].Name.MaximumLength = domain->MaximumLength;
350     list->Domains[list->Entries].Name.Buffer = (WCHAR*)*data;
351     memcpy(list->Domains[list->Entries].Name.Buffer, domain->Buffer, domain->MaximumLength);
352     *data += domain->MaximumLength;
353
354     /* get and store SID data */
355     list->Domains[list->Entries].Sid = *data;
356     lookup_name(domain, NULL, &sid_size, NULL, &domain_size, &use, &handled);
357     domain_size = 0;
358     lookup_name(domain, list->Domains[list->Entries].Sid, &sid_size, NULL, &domain_size, &use, &handled);
359     *data += sid_size;
360
361     return list->Entries++;
362 }
363
364 /******************************************************************************
365  * LsaLookupNames2 [ADVAPI32.@]
366  *
367  */
368 NTSTATUS WINAPI LsaLookupNames2( LSA_HANDLE policy, ULONG flags, ULONG count,
369                                  PLSA_UNICODE_STRING names, PLSA_REFERENCED_DOMAIN_LIST *domains,
370                                  PLSA_TRANSLATED_SID2 *sids )
371 {
372     ULONG i, sid_size_total = 0, domain_size_max = 0, size, domainname_size_total = 0;
373     ULONG sid_size, domain_size, mapped;
374     BOOL handled = FALSE;
375     char *domain_data;
376     SID_NAME_USE use;
377     SID *sid;
378
379     TRACE("(%p,0x%08x,0x%08x,%p,%p,%p)\n", policy, flags, count, names, domains, sids);
380
381     mapped = 0;
382     for (i = 0; i < count; i++)
383     {
384         handled = FALSE;
385         sid_size = domain_size = 0;
386         lookup_name( &names[i], NULL, &sid_size, NULL, &domain_size, &use, &handled );
387         if (handled)
388         {
389             sid_size_total += sid_size;
390             domainname_size_total += domain_size;
391             if (domain_size)
392             {
393                 if (domain_size > domain_size_max)
394                     domain_size_max = domain_size;
395             }
396             mapped++;
397         }
398     }
399     TRACE("mapped %u out of %u\n", mapped, count);
400
401     size = sizeof(LSA_TRANSLATED_SID2) * count + sid_size_total;
402     if (!(*sids = heap_alloc(size))) return STATUS_NO_MEMORY;
403
404     sid = (SID *)(*sids + count);
405
406     /* use maximum domain count */
407     if (!(*domains = heap_alloc(sizeof(LSA_REFERENCED_DOMAIN_LIST) + sizeof(LSA_TRUST_INFORMATION)*count +
408                                 sid_size_total + domainname_size_total)))
409     {
410         heap_free(*sids);
411         return STATUS_NO_MEMORY;
412     }
413     (*domains)->Entries = 0;
414     (*domains)->Domains = (LSA_TRUST_INFORMATION*)((char*)*domains + sizeof(LSA_REFERENCED_DOMAIN_LIST));
415     domain_data = (char*)(*domains)->Domains + sizeof(LSA_TRUST_INFORMATION)*count;
416
417     for (i = 0; i < count; i++)
418     {
419         LSA_UNICODE_STRING domain;
420
421         domain.Length = domain_size_max*sizeof(WCHAR);
422         domain.MaximumLength = domain_size_max*sizeof(WCHAR);
423         domain.Buffer = heap_alloc(domain.Length);
424
425         (*sids)[i].Use = SidTypeUnknown;
426         (*sids)[i].DomainIndex = -1;
427         (*sids)[i].Flags = 0;
428
429         handled = FALSE;
430         sid_size = sid_size_total;
431         domain_size = domain_size_max;
432         lookup_name( &names[i], sid, &sid_size, domain.Buffer, &domain_size, &use, &handled );
433         if (handled)
434         {
435             (*sids)[i].Sid = sid;
436             (*sids)[i].Use = use;
437
438             sid = (SID *)((char *)sid + sid_size);
439             sid_size_total -= sid_size;
440             if (domain_size)
441             {
442                 domain.Length = domain_size * sizeof(WCHAR);
443                 (*sids)[i].DomainIndex = lsa_reflist_add_domain(*domains, &domain, &domain_data);
444             }
445         }
446
447         heap_free(domain.Buffer);
448     }
449
450     if (mapped == count) return STATUS_SUCCESS;
451     if (mapped > 0 && mapped < count) return STATUS_SOME_NOT_MAPPED;
452     return STATUS_NONE_MAPPED;
453 }
454
455 /******************************************************************************
456  * LsaLookupSids [ADVAPI32.@]
457  *
458  * Looks up the names that correspond to an array of SIDs.
459  *
460  * PARAMS
461  *  PolicyHandle      [I] Handle to a Policy object.
462  *  Count             [I] Number of SIDs in the Sids array.
463  *  Sids              [I] Array of SIDs to lookup.
464  *  ReferencedDomains [O] Array of domains where the sids were found.
465  *  Names             [O] Array of names corresponding to Sids.
466  *
467  * RETURNS
468  *  Success: STATUS_SUCCESS,
469  *           STATUS_SOME_NOT_MAPPED
470  *  Failure: STATUS_NONE_MAPPED or NTSTATUS code.
471  */
472 NTSTATUS WINAPI LsaLookupSids(
473     LSA_HANDLE PolicyHandle,
474     ULONG Count,
475     PSID *Sids,
476     LSA_REFERENCED_DOMAIN_LIST **ReferencedDomains,
477     LSA_TRANSLATED_NAME **Names)
478 {
479     ULONG i, mapped, name_fullsize, domain_fullsize;
480     ULONG name_size, domain_size;
481     LSA_UNICODE_STRING domain;
482     WCHAR *name_buffer;
483     char *domain_data;
484     SID_NAME_USE use;
485
486     TRACE("(%p, %u, %p, %p, %p)\n", PolicyHandle, Count, Sids, ReferencedDomains, Names);
487
488     /* this length does not include actual string length yet */
489     name_fullsize = sizeof(LSA_TRANSLATED_NAME) * Count;
490     if (!(*Names = heap_alloc(name_fullsize))) return STATUS_NO_MEMORY;
491     /* maximum count of stored domain infos is Count, allocate it like that cause really needed
492        count could only be computed after sid data is retrieved */
493     domain_fullsize = sizeof(LSA_REFERENCED_DOMAIN_LIST) + sizeof(LSA_TRUST_INFORMATION)*Count;
494     if (!(*ReferencedDomains = heap_alloc(domain_fullsize)))
495     {
496         heap_free(*Names);
497         return STATUS_NO_MEMORY;
498     }
499     (*ReferencedDomains)->Entries = 0;
500     (*ReferencedDomains)->Domains = (LSA_TRUST_INFORMATION*)((char*)*ReferencedDomains + sizeof(LSA_REFERENCED_DOMAIN_LIST));
501
502     /* Get full names data length and full length needed to store domain name and SID */
503     for (i = 0; i < Count; i++)
504     {
505         (*Names)[i].Use = SidTypeUnknown;
506         (*Names)[i].DomainIndex = -1;
507         (*Names)[i].Name.Buffer = NULL;
508
509         memset(&(*ReferencedDomains)->Domains[i], 0, sizeof(LSA_TRUST_INFORMATION));
510
511         name_size = domain_size = 0;
512         if (!LookupAccountSidW(NULL, Sids[i], NULL, &name_size, NULL, &domain_size, &use) &&
513             GetLastError() == ERROR_INSUFFICIENT_BUFFER)
514         {
515             if (name_size)
516             {
517                 (*Names)[i].Name.Length = (name_size - 1) * sizeof(WCHAR);
518                 (*Names)[i].Name.MaximumLength = name_size * sizeof(WCHAR);
519                 name_fullsize += (*Names)[i].Name.MaximumLength;
520             }
521             else
522             {
523                 (*Names)[i].Name.Length = 0;
524                 (*Names)[i].Name.MaximumLength = 0;
525             }
526
527             /* This potentially allocates more than needed, cause different names will reuse same domain index.
528                Also it's not possible to store domain name length right here for the same reason. */
529             if (domain_size)
530             {
531                 ULONG sid_size = 0;
532                 BOOL handled = FALSE;
533                 WCHAR *name;
534
535                 domain_fullsize += domain_size * sizeof(WCHAR);
536
537                 /* get domain SID size too */
538                 name = heap_alloc(domain_size * sizeof(WCHAR));
539                 *name = 0;
540                 LookupAccountSidW(NULL, Sids[i], NULL, &name_size, name, &domain_size, &use);
541
542                 domain.Buffer = name;
543                 domain.Length = domain_size * sizeof(WCHAR);
544                 domain.MaximumLength = domain_size * sizeof(WCHAR);
545
546                 lookup_name(&domain, NULL, &sid_size, NULL, &domain_size, &use, &handled);
547                 domain_fullsize += sid_size;
548
549                 heap_free(name);
550             }
551         }
552     }
553
554     /* now we have full length needed for both */
555     *Names = heap_realloc(*Names, name_fullsize);
556     name_buffer = (WCHAR*)((char*)*Names + sizeof(LSA_TRANSLATED_NAME)*Count);
557
558     *ReferencedDomains = heap_realloc(*ReferencedDomains, domain_fullsize);
559     /* fix pointer after reallocation */
560     (*ReferencedDomains)->Domains = (LSA_TRUST_INFORMATION*)((char*)*ReferencedDomains + sizeof(LSA_REFERENCED_DOMAIN_LIST));
561     domain_data = (char*)(*ReferencedDomains)->Domains + sizeof(LSA_TRUST_INFORMATION)*Count;
562
563     mapped = 0;
564     for (i = 0; i < Count; i++)
565     {
566         name_size = domain_size = 0;
567
568         if (!LookupAccountSidW(NULL, Sids[i], NULL, &name_size, NULL, &domain_size, &use) &&
569             GetLastError() == ERROR_INSUFFICIENT_BUFFER)
570         {
571             mapped++;
572
573             if (domain_size)
574             {
575                 domain.Length = (domain_size - 1) * sizeof(WCHAR);
576                 domain.MaximumLength = domain_size * sizeof(WCHAR);
577                 domain.Buffer = heap_alloc(domain.MaximumLength);
578             }
579
580             (*Names)[i].Name.Buffer = name_buffer;
581             LookupAccountSidW(NULL, Sids[i], (*Names)[i].Name.Buffer, &name_size, domain.Buffer, &domain_size, &use);
582             (*Names)[i].Use = use;
583
584             if (domain_size)
585             {
586                 (*Names)[i].DomainIndex = lsa_reflist_add_domain(*ReferencedDomains, &domain, &domain_data);
587                 heap_free(domain.Buffer);
588             }
589         }
590
591         name_buffer += name_size;
592     }
593     TRACE("mapped %u out of %u\n", mapped, Count);
594
595     if (mapped == Count) return STATUS_SUCCESS;
596     if (mapped) return STATUS_SOME_NOT_MAPPED;
597     return STATUS_NONE_MAPPED;
598 }
599
600 /******************************************************************************
601  * LsaNtStatusToWinError [ADVAPI32.@]
602  *
603  * Converts an LSA NTSTATUS code to a Windows error code.
604  *
605  * PARAMS
606  *  Status [I] NTSTATUS code.
607  *
608  * RETURNS
609  *  Success: Corresponding Windows error code.
610  *  Failure: ERROR_MR_MID_NOT_FOUND.
611  */
612 ULONG WINAPI LsaNtStatusToWinError(NTSTATUS Status)
613 {
614     return RtlNtStatusToDosError(Status);
615 }
616
617 /******************************************************************************
618  * LsaOpenPolicy [ADVAPI32.@]
619  *
620  * Opens a handle to the Policy object on a local or remote system.
621  *
622  * PARAMS
623  *  SystemName       [I] Name of the target system.
624  *  ObjectAttributes [I] Connection attributes.
625  *  DesiredAccess    [I] Requested access rights.
626  *  PolicyHandle     [I/O] Handle to the Policy object.
627  *
628  * RETURNS
629  *  Success: STATUS_SUCCESS.
630  *  Failure: NTSTATUS code.
631  *
632  * NOTES
633  *  Set SystemName to NULL to open the local Policy object.
634  */
635 NTSTATUS WINAPI LsaOpenPolicy(
636     IN PLSA_UNICODE_STRING SystemName,
637     IN PLSA_OBJECT_ATTRIBUTES ObjectAttributes,
638     IN ACCESS_MASK DesiredAccess,
639     IN OUT PLSA_HANDLE PolicyHandle)
640 {
641     FIXME("(%s,%p,0x%08x,%p) stub\n",
642           SystemName?debugstr_w(SystemName->Buffer):"(null)",
643           ObjectAttributes, DesiredAccess, PolicyHandle);
644
645     ADVAPI_ForceLocalComputer(SystemName ? SystemName->Buffer : NULL,
646                               STATUS_ACCESS_VIOLATION);
647     dumpLsaAttributes(ObjectAttributes);
648
649     if(PolicyHandle) *PolicyHandle = (LSA_HANDLE)0xcafe;
650     return STATUS_SUCCESS;
651 }
652
653 /******************************************************************************
654  * LsaOpenTrustedDomainByName [ADVAPI32.@]
655  *
656  */
657 NTSTATUS WINAPI LsaOpenTrustedDomainByName(
658     LSA_HANDLE policy,
659     PLSA_UNICODE_STRING name,
660     ACCESS_MASK access,
661     PLSA_HANDLE handle)
662 {
663     FIXME("(%p,%p,0x%08x,%p) stub\n", policy, name, access, handle);
664     return STATUS_OBJECT_NAME_NOT_FOUND;
665 }
666
667 /******************************************************************************
668  * LsaQueryInformationPolicy [ADVAPI32.@]
669  *
670  * Returns information about a Policy object.
671  *
672  * PARAMS
673  *  PolicyHandle     [I] Handle to a Policy object.
674  *  InformationClass [I] Type of information to retrieve.
675  *  Buffer           [O] Pointer to the requested information.
676  *
677  * RETURNS
678  *  Success: STATUS_SUCCESS.
679  *  Failure: NTSTATUS code.
680  */
681 NTSTATUS WINAPI LsaQueryInformationPolicy(
682     IN LSA_HANDLE PolicyHandle,
683     IN POLICY_INFORMATION_CLASS InformationClass,
684     OUT PVOID *Buffer)
685 {
686     TRACE("(%p,0x%08x,%p)\n", PolicyHandle, InformationClass, Buffer);
687
688     if(!Buffer) return STATUS_INVALID_PARAMETER;
689     switch (InformationClass)
690     {
691         case PolicyAuditEventsInformation: /* 2 */
692         {
693             PPOLICY_AUDIT_EVENTS_INFO p = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
694                                                     sizeof(POLICY_AUDIT_EVENTS_INFO));
695             p->AuditingMode = FALSE; /* no auditing */
696             *Buffer = p;
697         }
698         break;
699         case PolicyPrimaryDomainInformation: /* 3 */
700         {
701             /* Only the domain name is valid for the local computer.
702              * All other fields are zero.
703              */
704             PPOLICY_PRIMARY_DOMAIN_INFO pinfo;
705
706             pinfo = ADVAPI_GetDomainName(sizeof(*pinfo), offsetof(POLICY_PRIMARY_DOMAIN_INFO, Name));
707
708             TRACE("setting domain to %s\n", debugstr_w(pinfo->Name.Buffer));
709
710             *Buffer = pinfo;
711         }
712         break;
713         case PolicyAccountDomainInformation: /* 5 */
714         {
715             struct di
716             {
717                 POLICY_ACCOUNT_DOMAIN_INFO info;
718                 SID sid;
719                 DWORD padding[3];
720                 WCHAR domain[MAX_COMPUTERNAME_LENGTH + 1];
721             };
722
723             DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
724             struct di * xdi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*xdi));
725
726             xdi->info.DomainName.MaximumLength = dwSize * sizeof(WCHAR);
727             xdi->info.DomainName.Buffer = xdi->domain;
728             if (GetComputerNameW(xdi->info.DomainName.Buffer, &dwSize))
729                 xdi->info.DomainName.Length = dwSize * sizeof(WCHAR);
730
731             TRACE("setting name to %s\n", debugstr_w(xdi->info.DomainName.Buffer));
732
733             xdi->info.DomainSid = &xdi->sid;
734
735             if (!ADVAPI_GetComputerSid(&xdi->sid))
736             {
737                 HeapFree(GetProcessHeap(), 0, xdi);
738
739                 WARN("Computer SID not found\n");
740
741                 return STATUS_UNSUCCESSFUL;
742             }
743
744             TRACE("setting SID to %s\n", debugstr_sid(&xdi->sid));
745
746             *Buffer = xdi;
747         }
748         break;
749         case  PolicyDnsDomainInformation:       /* 12 (0xc) */
750         {
751             /* Only the domain name is valid for the local computer.
752              * All other fields are zero.
753              */
754             PPOLICY_DNS_DOMAIN_INFO pinfo;
755
756             pinfo = ADVAPI_GetDomainName(sizeof(*pinfo), offsetof(POLICY_DNS_DOMAIN_INFO, Name));
757
758             TRACE("setting domain to %s\n", debugstr_w(pinfo->Name.Buffer));
759
760             *Buffer = pinfo;
761         }
762         break;
763         case  PolicyAuditLogInformation:
764         case  PolicyPdAccountInformation:
765         case  PolicyLsaServerRoleInformation:
766         case  PolicyReplicaSourceInformation:
767         case  PolicyDefaultQuotaInformation:
768         case  PolicyModificationInformation:
769         case  PolicyAuditFullSetInformation:
770         case  PolicyAuditFullQueryInformation:
771         {
772             FIXME("category %d not implemented\n", InformationClass);
773             return STATUS_UNSUCCESSFUL;
774         }
775     }
776     return STATUS_SUCCESS;
777 }
778
779 /******************************************************************************
780  * LsaQueryTrustedDomainInfo [ADVAPI32.@]
781  *
782  */
783 NTSTATUS WINAPI LsaQueryTrustedDomainInfo(
784     LSA_HANDLE policy,
785     PSID sid,
786     TRUSTED_INFORMATION_CLASS class,
787     PVOID *buffer)
788 {
789     FIXME("(%p,%p,%d,%p) stub\n", policy, sid, class, buffer);
790     return STATUS_OBJECT_NAME_NOT_FOUND;
791 }
792
793 /******************************************************************************
794  * LsaQueryTrustedDomainInfoByName [ADVAPI32.@]
795  *
796  */
797 NTSTATUS WINAPI LsaQueryTrustedDomainInfoByName(
798     LSA_HANDLE policy,
799     PLSA_UNICODE_STRING name,
800     TRUSTED_INFORMATION_CLASS class,
801     PVOID *buffer)
802 {
803     FIXME("(%p,%p,%d,%p) stub\n", policy, name, class, buffer);
804     return STATUS_OBJECT_NAME_NOT_FOUND;
805 }
806
807 /******************************************************************************
808  * LsaRegisterPolicyChangeNotification [ADVAPI32.@]
809  *
810  */
811 NTSTATUS WINAPI LsaRegisterPolicyChangeNotification(
812     POLICY_NOTIFICATION_INFORMATION_CLASS class,
813     HANDLE event)
814 {
815     FIXME("(%d,%p) stub\n", class, event);
816     return STATUS_UNSUCCESSFUL;
817 }
818
819 /******************************************************************************
820  * LsaRemoveAccountRights [ADVAPI32.@]
821  *
822  */
823 NTSTATUS WINAPI LsaRemoveAccountRights(
824     LSA_HANDLE policy,
825     PSID sid,
826     BOOLEAN all,
827     PLSA_UNICODE_STRING rights,
828     ULONG count)
829 {
830     FIXME("(%p,%p,%d,%p,0x%08x) stub\n", policy, sid, all, rights, count);
831     return STATUS_SUCCESS;
832 }
833
834 /******************************************************************************
835  * LsaRetrievePrivateData [ADVAPI32.@]
836  *
837  * Retrieves data stored by LsaStorePrivateData.
838  *
839  * PARAMS
840  *  PolicyHandle [I] Handle to a Policy object.
841  *  KeyName      [I] Name of the key where the data is stored.
842  *  PrivateData  [O] Pointer to the private data.
843  *
844  * RETURNS
845  *  Success: STATUS_SUCCESS.
846  *  Failure: STATUS_OBJECT_NAME_NOT_FOUND or NTSTATUS code.
847  */
848 NTSTATUS WINAPI LsaRetrievePrivateData(
849     IN LSA_HANDLE PolicyHandle,
850     IN PLSA_UNICODE_STRING KeyName,
851     OUT PLSA_UNICODE_STRING* PrivateData)
852 {
853     FIXME("(%p,%p,%p) stub\n", PolicyHandle, KeyName, PrivateData);
854     return STATUS_OBJECT_NAME_NOT_FOUND;
855 }
856
857 /******************************************************************************
858  * LsaSetInformationPolicy [ADVAPI32.@]
859  *
860  * Modifies information in a Policy object.
861  *
862  * PARAMS
863  *  PolicyHandle     [I] Handle to a Policy object.
864  *  InformationClass [I] Type of information to set.
865  *  Buffer           [I] Pointer to the information to set.
866  *
867  * RETURNS
868  *  Success: STATUS_SUCCESS.
869  *  Failure: NTSTATUS code.
870  */
871 NTSTATUS WINAPI LsaSetInformationPolicy(
872     IN LSA_HANDLE PolicyHandle,
873     IN POLICY_INFORMATION_CLASS InformationClass,
874     IN PVOID Buffer)
875 {
876     FIXME("(%p,0x%08x,%p) stub\n", PolicyHandle, InformationClass, Buffer);
877
878     return STATUS_UNSUCCESSFUL;
879 }
880
881 /******************************************************************************
882  * LsaSetSecret [ADVAPI32.@]
883  *
884  * Set old and new values on a secret handle
885  *
886  * PARAMS
887  *  SecretHandle          [I] Handle to a secret object.
888  *  EncryptedCurrentValue [I] Pointer to encrypted new value, can be NULL
889  *  EncryptedOldValue     [I] Pointer to encrypted old value, can be NULL
890  *
891  * RETURNS
892  *  Success: STATUS_SUCCESS
893  *  Failure: NTSTATUS code.
894  */
895 NTSTATUS WINAPI LsaSetSecret(
896     IN LSA_HANDLE SecretHandle,
897     IN PLSA_UNICODE_STRING EncryptedCurrentValue,
898     IN PLSA_UNICODE_STRING EncryptedOldValue)
899 {
900     FIXME("(%p,%p,%p) stub\n", SecretHandle, EncryptedCurrentValue,
901             EncryptedOldValue);
902     return STATUS_SUCCESS;
903 }
904
905 /******************************************************************************
906  * LsaSetTrustedDomainInfoByName [ADVAPI32.@]
907  *
908  */
909 NTSTATUS WINAPI LsaSetTrustedDomainInfoByName(
910     LSA_HANDLE policy,
911     PLSA_UNICODE_STRING name,
912     TRUSTED_INFORMATION_CLASS class,
913     PVOID buffer)
914 {
915     FIXME("(%p,%p,%d,%p) stub\n", policy, name, class, buffer);
916     return STATUS_SUCCESS;
917 }
918
919 /******************************************************************************
920  * LsaSetTrustedDomainInformation [ADVAPI32.@]
921  *
922  */
923 NTSTATUS WINAPI LsaSetTrustedDomainInformation(
924     LSA_HANDLE policy,
925     PSID sid,
926     TRUSTED_INFORMATION_CLASS class,
927     PVOID buffer)
928 {
929     FIXME("(%p,%p,%d,%p) stub\n", policy, sid, class, buffer);
930     return STATUS_SUCCESS;
931 }
932
933 /******************************************************************************
934  * LsaStorePrivateData [ADVAPI32.@]
935  *
936  * Stores or deletes a Policy object's data under the specified reg key.
937  *
938  * PARAMS
939  *  PolicyHandle [I] Handle to a Policy object.
940  *  KeyName      [I] Name of the key where the data will be stored.
941  *  PrivateData  [O] Pointer to the private data.
942  *
943  * RETURNS
944  *  Success: STATUS_SUCCESS.
945  *  Failure: STATUS_OBJECT_NAME_NOT_FOUND or NTSTATUS code.
946  */
947 NTSTATUS WINAPI LsaStorePrivateData(
948     IN LSA_HANDLE PolicyHandle,
949     IN PLSA_UNICODE_STRING KeyName,
950     IN PLSA_UNICODE_STRING PrivateData)
951 {
952     FIXME("(%p,%p,%p) stub\n", PolicyHandle, KeyName, PrivateData);
953     return STATUS_OBJECT_NAME_NOT_FOUND;
954 }
955
956 /******************************************************************************
957  * LsaUnregisterPolicyChangeNotification [ADVAPI32.@]
958  *
959  */
960 NTSTATUS WINAPI LsaUnregisterPolicyChangeNotification(
961     POLICY_NOTIFICATION_INFORMATION_CLASS class,
962     HANDLE event)
963 {
964     FIXME("(%d,%p) stub\n", class, event);
965     return STATUS_SUCCESS;
966 }