advapi32: EqualSid should set last error to ERROR_SUCCESS.
[wine] / dlls / advapi32 / security.c
1 /*
2  * Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net>
3  * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
4  * Copyright 2006 Robert Reif
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  */
21
22 #include <stdarg.h>
23 #include <string.h>
24
25 #include "ntstatus.h"
26 #define WIN32_NO_STATUS
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "winreg.h"
31 #include "winsafer.h"
32 #include "winternl.h"
33 #include "winioctl.h"
34 #include "ntsecapi.h"
35 #include "accctrl.h"
36 #include "sddl.h"
37 #include "winsvc.h"
38 #include "aclapi.h"
39 #include "objbase.h"
40 #include "iads.h"
41 #include "advapi32_misc.h"
42 #include "lmcons.h"
43
44 #include "wine/debug.h"
45 #include "wine/unicode.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
48
49 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes);
50 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags, 
51     PACL pAcl, LPDWORD cBytes);
52 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl);
53 static BYTE ParseAceStringType(LPCWSTR* StringAcl);
54 static DWORD ParseAceStringRights(LPCWSTR* StringAcl);
55 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
56     LPCWSTR StringSecurityDescriptor,
57     SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
58     LPDWORD cBytes);
59 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl);
60
61 typedef struct _ACEFLAG
62 {
63    LPCWSTR wstr;
64    DWORD value;
65 } ACEFLAG, *LPACEFLAG;
66
67 typedef struct _MAX_SID
68 {
69     /* same fields as struct _SID */
70     BYTE Revision;
71     BYTE SubAuthorityCount;
72     SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
73     DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
74 } MAX_SID;
75
76 typedef struct WELLKNOWNSID
77 {
78     WCHAR wstr[2];
79     WELL_KNOWN_SID_TYPE Type;
80     MAX_SID Sid;
81 } WELLKNOWNSID;
82
83 static const WELLKNOWNSID WellKnownSids[] =
84 {
85     { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } },
86     { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } },
87     { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } },
88     { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } },
89     { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } },
90     { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } },
91     { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } },
92     { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } },
93     { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } },
94     { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } },
95     { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } },
96     { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } },
97     { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } },
98     { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } },
99     { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } },
100     { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } },
101     { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } },
102     { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } },
103     { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } },
104     { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } },
105     { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } },
106     { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } },
107     { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } },
108     { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } },
109     { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } },
110     { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } },
111     { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } },
112     { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } },
113     { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } },
114     { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } },
115     { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } },
116     { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } },
117     { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } },
118     { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } },
119     { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } },
120     { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } },
121     { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } },
122     { {0,0}, WinNTLMAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID } } },
123     { {0,0}, WinDigestAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID } } },
124     { {0,0}, WinSChannelAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID } } },
125     { {0,0}, WinThisOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_THIS_ORGANIZATION_RID } } },
126     { {0,0}, WinOtherOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_OTHER_ORGANIZATION_RID } } },
127     { {0,0}, WinBuiltinIncomingForestTrustBuildersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS  } } },
128     { {0,0}, WinBuiltinPerfMonitoringUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS } } },
129     { {0,0}, WinBuiltinPerfLoggingUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS } } },
130     { {0,0}, WinBuiltinAuthorizationAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS } } },
131     { {0,0}, WinBuiltinTerminalServerLicenseServersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS } } },
132     { {0,0}, WinBuiltinDCOMUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS } } },
133     { {'L','W'}, WinLowLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_LOW_RID} } },
134     { {'M','E'}, WinMediumLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_MEDIUM_RID } } },
135     { {'H','I'}, WinHighLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_HIGH_RID } } },
136     { {'S','I'}, WinSystemLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_SYSTEM_RID } } },
137 };
138
139 /* these SIDs must be constructed as relative to some domain - only the RID is well-known */
140 typedef struct WELLKNOWNRID
141 {
142     WELL_KNOWN_SID_TYPE Type;
143     DWORD Rid;
144 } WELLKNOWNRID;
145
146 static const WELLKNOWNRID WellKnownRids[] = {
147     { WinAccountAdministratorSid,    DOMAIN_USER_RID_ADMIN },
148     { WinAccountGuestSid,            DOMAIN_USER_RID_GUEST },
149     { WinAccountKrbtgtSid,           DOMAIN_USER_RID_KRBTGT },
150     { WinAccountDomainAdminsSid,     DOMAIN_GROUP_RID_ADMINS },
151     { WinAccountDomainUsersSid,      DOMAIN_GROUP_RID_USERS },
152     { WinAccountDomainGuestsSid,     DOMAIN_GROUP_RID_GUESTS },
153     { WinAccountComputersSid,        DOMAIN_GROUP_RID_COMPUTERS },
154     { WinAccountControllersSid,      DOMAIN_GROUP_RID_CONTROLLERS },
155     { WinAccountCertAdminsSid,       DOMAIN_GROUP_RID_CERT_ADMINS },
156     { WinAccountSchemaAdminsSid,     DOMAIN_GROUP_RID_SCHEMA_ADMINS },
157     { WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS },
158     { WinAccountPolicyAdminsSid,     DOMAIN_GROUP_RID_POLICY_ADMINS },
159     { WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS },
160 };
161
162
163 static SID const sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
164
165 typedef struct _AccountSid {
166     WELL_KNOWN_SID_TYPE type;
167     LPCWSTR account;
168     LPCWSTR domain;
169     SID_NAME_USE name_use;
170     LPCWSTR alias;
171 } AccountSid;
172
173 static const WCHAR Account_Operators[] = { 'A','c','c','o','u','n','t',' ','O','p','e','r','a','t','o','r','s',0 };
174 static const WCHAR Administrator[] = {'A','d','m','i','n','i','s','t','r','a','t','o','r',0 };
175 static const WCHAR Administrators[] = { 'A','d','m','i','n','i','s','t','r','a','t','o','r','s',0 };
176 static const WCHAR ANONYMOUS_LOGON[] = { 'A','N','O','N','Y','M','O','U','S',' ','L','O','G','O','N',0 };
177 static const WCHAR Authenticated_Users[] = { 'A','u','t','h','e','n','t','i','c','a','t','e','d',' ','U','s','e','r','s',0 };
178 static const WCHAR Backup_Operators[] = { 'B','a','c','k','u','p',' ','O','p','e','r','a','t','o','r','s',0 };
179 static const WCHAR BATCH[] = { 'B','A','T','C','H',0 };
180 static const WCHAR Blank[] = { 0 };
181 static const WCHAR BUILTIN[] = { 'B','U','I','L','T','I','N',0 };
182 static const WCHAR Cert_Publishers[] = { 'C','e','r','t',' ','P','u','b','l','i','s','h','e','r','s',0 };
183 static const WCHAR CREATOR_GROUP[] = { 'C','R','E','A','T','O','R',' ','G','R','O','U','P',0 };
184 static const WCHAR CREATOR_GROUP_SERVER[] = { 'C','R','E','A','T','O','R',' ','G','R','O','U','P',' ','S','E','R','V','E','R',0 };
185 static const WCHAR CREATOR_OWNER[] = { 'C','R','E','A','T','O','R',' ','O','W','N','E','R',0 };
186 static const WCHAR CREATOR_OWNER_SERVER[] = { 'C','R','E','A','T','O','R',' ','O','W','N','E','R',' ','S','E','R','V','E','R',0 };
187 static const WCHAR CURRENT_USER[] = { 'C','U','R','R','E','N','T','_','U','S','E','R',0 };
188 static const WCHAR DIALUP[] = { 'D','I','A','L','U','P',0 };
189 static const WCHAR Digest_Authentication[] = { 'D','i','g','e','s','t',' ','A','u','t','h','e','n','t','i','c','a','t','i','o','n',0 };
190 static const WCHAR DOMAIN[] = {'D','O','M','A','I','N',0};
191 static const WCHAR Domain_Admins[] = { 'D','o','m','a','i','n',' ','A','d','m','i','n','s',0 };
192 static const WCHAR Domain_Computers[] = { 'D','o','m','a','i','n',' ','C','o','m','p','u','t','e','r','s',0 };
193 static const WCHAR Domain_Controllers[] = { 'D','o','m','a','i','n',' ','C','o','n','t','r','o','l','l','e','r','s',0 };
194 static const WCHAR Domain_Guests[] = { 'D','o','m','a','i','n',' ','G','u','e','s','t','s',0 };
195 static const WCHAR Domain_Users[] = { 'D','o','m','a','i','n',' ','U','s','e','r','s',0 };
196 static const WCHAR Enterprise_Admins[] = { 'E','n','t','e','r','p','r','i','s','e',' ','A','d','m','i','n','s',0 };
197 static const WCHAR ENTERPRISE_DOMAIN_CONTROLLERS[] = { 'E','N','T','E','R','P','R','I','S','E',' ','D','O','M','A','I','N',' ','C','O','N','T','R','O','L','L','E','R','S',0 };
198 static const WCHAR Everyone[] = { 'E','v','e','r','y','o','n','e',0 };
199 static const WCHAR Group_Policy_Creator_Owners[] = { 'G','r','o','u','p',' ','P','o','l','i','c','y',' ','C','r','e','a','t','o','r',' ','O','w','n','e','r','s',0 };
200 static const WCHAR Guest[] = { 'G','u','e','s','t',0 };
201 static const WCHAR Guests[] = { 'G','u','e','s','t','s',0 };
202 static const WCHAR INTERACTIVE[] = { 'I','N','T','E','R','A','C','T','I','V','E',0 };
203 static const WCHAR LOCAL[] = { 'L','O','C','A','L',0 };
204 static const WCHAR LOCAL_SERVICE[] = { 'L','O','C','A','L',' ','S','E','R','V','I','C','E',0 };
205 static const WCHAR LOCAL_SERVICE2[] = { 'L','O','C','A','L','S','E','R','V','I','C','E',0 };
206 static const WCHAR NETWORK[] = { 'N','E','T','W','O','R','K',0 };
207 static const WCHAR Network_Configuration_Operators[] = { 'N','e','t','w','o','r','k',' ','C','o','n','f','i','g','u','r','a','t','i','o','n',' ','O','p','e','r','a','t','o','r','s',0 };
208 static const WCHAR NETWORK_SERVICE[] = { 'N','E','T','W','O','R','K',' ','S','E','R','V','I','C','E',0 };
209 static const WCHAR NETWORK_SERVICE2[] = { 'N','E','T','W','O','R','K','S','E','R','V','I','C','E',0 };
210 static const WCHAR NT_AUTHORITY[] = { 'N','T',' ','A','U','T','H','O','R','I','T','Y',0 };
211 static const WCHAR NT_Pseudo_Domain[] = { 'N','T',' ','P','s','e','u','d','o',' ','D','o','m','a','i','n',0 };
212 static const WCHAR NTML_Authentication[] = { 'N','T','M','L',' ','A','u','t','h','e','n','t','i','c','a','t','i','o','n',0 };
213 static const WCHAR NULL_SID[] = { 'N','U','L','L',' ','S','I','D',0 };
214 static const WCHAR Other_Organization[] = { 'O','t','h','e','r',' ','O','r','g','a','n','i','z','a','t','i','o','n',0 };
215 static const WCHAR Performance_Log_Users[] = { 'P','e','r','f','o','r','m','a','n','c','e',' ','L','o','g',' ','U','s','e','r','s',0 };
216 static const WCHAR Performance_Monitor_Users[] = { 'P','e','r','f','o','r','m','a','n','c','e',' ','M','o','n','i','t','o','r',' ','U','s','e','r','s',0 };
217 static const WCHAR Power_Users[] = { 'P','o','w','e','r',' ','U','s','e','r','s',0 };
218 static const WCHAR Pre_Windows_2000_Compatible_Access[] = { 'P','r','e','-','W','i','n','d','o','w','s',' ','2','0','0','0',' ','C','o','m','p','a','t','i','b','l','e',' ','A','c','c','e','s','s',0 };
219 static const WCHAR Print_Operators[] = { 'P','r','i','n','t',' ','O','p','e','r','a','t','o','r','s',0 };
220 static const WCHAR PROXY[] = { 'P','R','O','X','Y',0 };
221 static const WCHAR RAS_and_IAS_Servers[] = { 'R','A','S',' ','a','n','d',' ','I','A','S',' ','S','e','r','v','e','r','s',0 };
222 static const WCHAR Remote_Desktop_Users[] = { 'R','e','m','o','t','e',' ','D','e','s','k','t','o','p',' ','U','s','e','r','s',0 };
223 static const WCHAR REMOTE_INTERACTIVE_LOGON[] = { 'R','E','M','O','T','E',' ','I','N','T','E','R','A','C','T','I','V','E',' ','L','O','G','O','N',0 };
224 static const WCHAR Replicators[] = { 'R','e','p','l','i','c','a','t','o','r','s',0 };
225 static const WCHAR RESTRICTED[] = { 'R','E','S','T','R','I','C','T','E','D',0 };
226 static const WCHAR SChannel_Authentication[] = { 'S','C','h','a','n','n','e','l',' ','A','u','t','h','e','n','t','i','c','a','t','i','o','n',0 };
227 static const WCHAR Schema_Admins[] = { 'S','c','h','e','m','a',' ','A','d','m','i','n','s',0 };
228 static const WCHAR SELF[] = { 'S','E','L','F',0 };
229 static const WCHAR Server_Operators[] = { 'S','e','r','v','e','r',' ','O','p','e','r','a','t','o','r','s',0 };
230 static const WCHAR SERVICE[] = { 'S','E','R','V','I','C','E',0 };
231 static const WCHAR SYSTEM[] = { 'S','Y','S','T','E','M',0 };
232 static const WCHAR TERMINAL_SERVER_USER[] = { 'T','E','R','M','I','N','A','L',' ','S','E','R','V','E','R',' ','U','S','E','R',0 };
233 static const WCHAR This_Organization[] = { 'T','h','i','s',' ','O','r','g','a','n','i','z','a','t','i','o','n',0 };
234 static const WCHAR Users[] = { 'U','s','e','r','s',0 };
235
236 static const AccountSid ACCOUNT_SIDS[] = {
237     { WinNullSid, NULL_SID, Blank, SidTypeWellKnownGroup },
238     { WinWorldSid, Everyone, Blank, SidTypeWellKnownGroup },
239     { WinLocalSid, LOCAL, Blank, SidTypeWellKnownGroup },
240     { WinCreatorOwnerSid, CREATOR_OWNER, Blank, SidTypeWellKnownGroup },
241     { WinCreatorGroupSid, CREATOR_GROUP, Blank, SidTypeWellKnownGroup },
242     { WinCreatorOwnerServerSid, CREATOR_OWNER_SERVER, Blank, SidTypeWellKnownGroup },
243     { WinCreatorGroupServerSid, CREATOR_GROUP_SERVER, Blank, SidTypeWellKnownGroup },
244     { WinNtAuthoritySid, NT_Pseudo_Domain, NT_Pseudo_Domain, SidTypeDomain },
245     { WinDialupSid, DIALUP, NT_AUTHORITY, SidTypeWellKnownGroup },
246     { WinNetworkSid, NETWORK, NT_AUTHORITY, SidTypeWellKnownGroup },
247     { WinBatchSid, BATCH, NT_AUTHORITY, SidTypeWellKnownGroup },
248     { WinInteractiveSid, INTERACTIVE, NT_AUTHORITY, SidTypeWellKnownGroup },
249     { WinServiceSid, SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup },
250     { WinAnonymousSid, ANONYMOUS_LOGON, NT_AUTHORITY, SidTypeWellKnownGroup },
251     { WinProxySid, PROXY, NT_AUTHORITY, SidTypeWellKnownGroup },
252     { WinEnterpriseControllersSid, ENTERPRISE_DOMAIN_CONTROLLERS, NT_AUTHORITY, SidTypeWellKnownGroup },
253     { WinSelfSid, SELF, NT_AUTHORITY, SidTypeWellKnownGroup },
254     { WinAuthenticatedUserSid, Authenticated_Users, NT_AUTHORITY, SidTypeWellKnownGroup },
255     { WinRestrictedCodeSid, RESTRICTED, NT_AUTHORITY, SidTypeWellKnownGroup },
256     { WinTerminalServerSid, TERMINAL_SERVER_USER, NT_AUTHORITY, SidTypeWellKnownGroup },
257     { WinRemoteLogonIdSid, REMOTE_INTERACTIVE_LOGON, NT_AUTHORITY, SidTypeWellKnownGroup },
258     { WinLocalSystemSid, SYSTEM, NT_AUTHORITY, SidTypeWellKnownGroup },
259     { WinLocalServiceSid, LOCAL_SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup, LOCAL_SERVICE2 },
260     { WinNetworkServiceSid, NETWORK_SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup , NETWORK_SERVICE2},
261     { WinBuiltinDomainSid, BUILTIN, BUILTIN, SidTypeDomain },
262     { WinBuiltinAdministratorsSid, Administrators, BUILTIN, SidTypeAlias },
263     { WinBuiltinUsersSid, Users, BUILTIN, SidTypeAlias },
264     { WinBuiltinGuestsSid, Guests, BUILTIN, SidTypeAlias },
265     { WinBuiltinPowerUsersSid, Power_Users, BUILTIN, SidTypeAlias },
266     { WinBuiltinAccountOperatorsSid, Account_Operators, BUILTIN, SidTypeAlias },
267     { WinBuiltinSystemOperatorsSid, Server_Operators, BUILTIN, SidTypeAlias },
268     { WinBuiltinPrintOperatorsSid, Print_Operators, BUILTIN, SidTypeAlias },
269     { WinBuiltinBackupOperatorsSid, Backup_Operators, BUILTIN, SidTypeAlias },
270     { WinBuiltinReplicatorSid, Replicators, BUILTIN, SidTypeAlias },
271     { WinBuiltinPreWindows2000CompatibleAccessSid, Pre_Windows_2000_Compatible_Access, BUILTIN, SidTypeAlias },
272     { WinBuiltinRemoteDesktopUsersSid, Remote_Desktop_Users, BUILTIN, SidTypeAlias },
273     { WinBuiltinNetworkConfigurationOperatorsSid, Network_Configuration_Operators, BUILTIN, SidTypeAlias },
274     { WinNTLMAuthenticationSid, NTML_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
275     { WinDigestAuthenticationSid, Digest_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
276     { WinSChannelAuthenticationSid, SChannel_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
277     { WinThisOrganizationSid, This_Organization, NT_AUTHORITY, SidTypeWellKnownGroup },
278     { WinOtherOrganizationSid, Other_Organization, NT_AUTHORITY, SidTypeWellKnownGroup },
279     { WinBuiltinPerfMonitoringUsersSid, Performance_Monitor_Users, BUILTIN, SidTypeAlias },
280     { WinBuiltinPerfLoggingUsersSid, Performance_Log_Users, BUILTIN, SidTypeAlias },
281 };
282 /*
283  * ACE access rights
284  */
285 static const WCHAR SDDL_READ_CONTROL[]     = {'R','C',0};
286 static const WCHAR SDDL_WRITE_DAC[]        = {'W','D',0};
287 static const WCHAR SDDL_WRITE_OWNER[]      = {'W','O',0};
288 static const WCHAR SDDL_STANDARD_DELETE[]  = {'S','D',0};
289
290 static const WCHAR SDDL_READ_PROPERTY[]    = {'R','P',0};
291 static const WCHAR SDDL_WRITE_PROPERTY[]   = {'W','P',0};
292 static const WCHAR SDDL_CREATE_CHILD[]     = {'C','C',0};
293 static const WCHAR SDDL_DELETE_CHILD[]     = {'D','C',0};
294 static const WCHAR SDDL_LIST_CHILDREN[]    = {'L','C',0};
295 static const WCHAR SDDL_SELF_WRITE[]       = {'S','W',0};
296 static const WCHAR SDDL_LIST_OBJECT[]      = {'L','O',0};
297 static const WCHAR SDDL_DELETE_TREE[]      = {'D','T',0};
298 static const WCHAR SDDL_CONTROL_ACCESS[]   = {'C','R',0};
299
300 static const WCHAR SDDL_FILE_ALL[]         = {'F','A',0};
301 static const WCHAR SDDL_FILE_READ[]        = {'F','R',0};
302 static const WCHAR SDDL_FILE_WRITE[]       = {'F','W',0};
303 static const WCHAR SDDL_FILE_EXECUTE[]     = {'F','X',0};
304
305 static const WCHAR SDDL_KEY_ALL[]          = {'K','A',0};
306 static const WCHAR SDDL_KEY_READ[]         = {'K','R',0};
307 static const WCHAR SDDL_KEY_WRITE[]        = {'K','W',0};
308 static const WCHAR SDDL_KEY_EXECUTE[]      = {'K','X',0};
309
310 static const WCHAR SDDL_GENERIC_ALL[]      = {'G','A',0};
311 static const WCHAR SDDL_GENERIC_READ[]     = {'G','R',0};
312 static const WCHAR SDDL_GENERIC_WRITE[]    = {'G','W',0};
313 static const WCHAR SDDL_GENERIC_EXECUTE[]  = {'G','X',0};
314
315 /*
316  * ACL flags
317  */
318 static const WCHAR SDDL_PROTECTED[]             = {'P',0};
319 static const WCHAR SDDL_AUTO_INHERIT_REQ[]      = {'A','R',0};
320 static const WCHAR SDDL_AUTO_INHERITED[]        = {'A','I',0};
321
322 /*
323  * ACE types
324  */
325 static const WCHAR SDDL_ACCESS_ALLOWED[]        = {'A',0};
326 static const WCHAR SDDL_ACCESS_DENIED[]         = {'D',0};
327 static const WCHAR SDDL_OBJECT_ACCESS_ALLOWED[] = {'O','A',0};
328 static const WCHAR SDDL_OBJECT_ACCESS_DENIED[]  = {'O','D',0};
329 static const WCHAR SDDL_AUDIT[]                 = {'A','U',0};
330 static const WCHAR SDDL_ALARM[]                 = {'A','L',0};
331 static const WCHAR SDDL_OBJECT_AUDIT[]          = {'O','U',0};
332 static const WCHAR SDDL_OBJECT_ALARMp[]         = {'O','L',0};
333
334 /*
335  * ACE flags
336  */
337 static const WCHAR SDDL_CONTAINER_INHERIT[]  = {'C','I',0};
338 static const WCHAR SDDL_OBJECT_INHERIT[]     = {'O','I',0};
339 static const WCHAR SDDL_NO_PROPAGATE[]       = {'N','P',0};
340 static const WCHAR SDDL_INHERIT_ONLY[]       = {'I','O',0};
341 static const WCHAR SDDL_INHERITED[]          = {'I','D',0};
342 static const WCHAR SDDL_AUDIT_SUCCESS[]      = {'S','A',0};
343 static const WCHAR SDDL_AUDIT_FAILURE[]      = {'F','A',0};
344
345 const char * debugstr_sid(PSID sid)
346 {
347     int auth = 0;
348     SID * psid = sid;
349
350     if (psid == NULL)
351         return "(null)";
352
353     auth = psid->IdentifierAuthority.Value[5] +
354            (psid->IdentifierAuthority.Value[4] << 8) +
355            (psid->IdentifierAuthority.Value[3] << 16) +
356            (psid->IdentifierAuthority.Value[2] << 24);
357
358     switch (psid->SubAuthorityCount) {
359     case 0:
360         return wine_dbg_sprintf("S-%d-%d", psid->Revision, auth);
361     case 1:
362         return wine_dbg_sprintf("S-%d-%d-%u", psid->Revision, auth,
363             psid->SubAuthority[0]);
364     case 2:
365         return wine_dbg_sprintf("S-%d-%d-%u-%u", psid->Revision, auth,
366             psid->SubAuthority[0], psid->SubAuthority[1]);
367     case 3:
368         return wine_dbg_sprintf("S-%d-%d-%u-%u-%u", psid->Revision, auth,
369             psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]);
370     case 4:
371         return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u", psid->Revision, auth,
372             psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
373             psid->SubAuthority[3]);
374     case 5:
375         return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u", psid->Revision, auth,
376             psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
377             psid->SubAuthority[3], psid->SubAuthority[4]);
378     case 6:
379         return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
380             psid->SubAuthority[3], psid->SubAuthority[1], psid->SubAuthority[2],
381             psid->SubAuthority[0], psid->SubAuthority[4], psid->SubAuthority[5]);
382     case 7:
383         return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
384             psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
385             psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
386             psid->SubAuthority[6]);
387     case 8:
388         return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
389             psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
390             psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
391             psid->SubAuthority[6], psid->SubAuthority[7]);
392     }
393     return "(too-big)";
394 }
395
396 /* set last error code from NT status and get the proper boolean return value */
397 /* used for functions that are a simple wrapper around the corresponding ntdll API */
398 static inline BOOL set_ntstatus( NTSTATUS status )
399 {
400     if (status) SetLastError( RtlNtStatusToDosError( status ));
401     return !status;
402 }
403
404 #define WINE_SIZE_OF_WORLD_ACCESS_ACL   (sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD))
405
406 static void GetWorldAccessACL(PACL pACL)
407 {
408     PACCESS_ALLOWED_ACE pACE = (PACCESS_ALLOWED_ACE) (pACL + 1);
409
410     pACL->AclRevision = ACL_REVISION;
411     pACL->Sbz1 = 0;
412     pACL->AclSize = WINE_SIZE_OF_WORLD_ACCESS_ACL;
413     pACL->AceCount = 1;
414     pACL->Sbz2 = 0;
415
416     pACE->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
417     pACE->Header.AceFlags = CONTAINER_INHERIT_ACE;
418     pACE->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD);
419     pACE->Mask = 0xf3ffffff; /* Everything except reserved bits */
420     memcpy(&pACE->SidStart, &sidWorld, sizeof(sidWorld));
421 }
422
423 /************************************************************
424  *                ADVAPI_IsLocalComputer
425  *
426  * Checks whether the server name indicates local machine.
427  */
428 BOOL ADVAPI_IsLocalComputer(LPCWSTR ServerName)
429 {
430     DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
431     BOOL Result;
432     LPWSTR buf;
433
434     if (!ServerName || !ServerName[0])
435         return TRUE;
436
437     buf = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR));
438     Result = GetComputerNameW(buf,  &dwSize);
439     if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\'))
440         ServerName += 2;
441     Result = Result && !lstrcmpW(ServerName, buf);
442     HeapFree(GetProcessHeap(), 0, buf);
443
444     return Result;
445 }
446
447 /************************************************************
448  *                ADVAPI_GetComputerSid
449  *
450  * Reads the computer SID from the registry.
451  */
452 BOOL ADVAPI_GetComputerSid(PSID sid)
453 {
454     HKEY key;
455     LONG ret;
456     BOOL retval = FALSE;
457     static const WCHAR Account[] = { 'S','E','C','U','R','I','T','Y','\\','S','A','M','\\','D','o','m','a','i','n','s','\\','A','c','c','o','u','n','t',0 };
458     static const WCHAR V[] = { 'V',0 };
459
460     if ((ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, Account, 0,
461         KEY_READ, &key)) == ERROR_SUCCESS)
462     {
463         DWORD size = 0;
464         ret = RegQueryValueExW(key, V, NULL, NULL, NULL, &size);
465         if (ret == ERROR_MORE_DATA || ret == ERROR_SUCCESS)
466         {
467             BYTE * data = HeapAlloc(GetProcessHeap(), 0, size);
468             if (data)
469             {
470                 if ((ret = RegQueryValueExW(key, V, NULL, NULL,
471                      data, &size)) == ERROR_SUCCESS)
472                 {
473                     /* the SID is in the last 24 bytes of the binary data */
474                     CopyMemory(sid, &data[size-24], 24);
475                     retval = TRUE;
476                 }
477                 HeapFree(GetProcessHeap(), 0, data);
478             }
479         }
480         RegCloseKey(key);
481     }
482
483     if(retval == TRUE) return retval;
484
485     /* create a new random SID */
486     if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, Account,
487         0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL) == ERROR_SUCCESS)
488     {
489         PSID new_sid;
490         SID_IDENTIFIER_AUTHORITY identifierAuthority = {SECURITY_NT_AUTHORITY};
491         DWORD id[3];
492
493         if (RtlGenRandom(id, sizeof(id)))
494         {
495             if (AllocateAndInitializeSid(&identifierAuthority, 4, SECURITY_NT_NON_UNIQUE, id[0], id[1], id[2], 0, 0, 0, 0, &new_sid))
496             {
497                 if (RegSetValueExW(key, V, 0, REG_BINARY, new_sid, GetLengthSid(new_sid)) == ERROR_SUCCESS)
498                     retval = CopySid(GetLengthSid(new_sid), sid, new_sid);
499
500                 FreeSid(new_sid);
501             }
502         }
503         RegCloseKey(key);
504     }
505
506     return retval;
507 }
508
509 /*      ##############################
510         ######  TOKEN FUNCTIONS ######
511         ##############################
512 */
513
514 /******************************************************************************
515  * OpenProcessToken                     [ADVAPI32.@]
516  * Opens the access token associated with a process handle.
517  *
518  * PARAMS
519  *   ProcessHandle [I] Handle to process
520  *   DesiredAccess [I] Desired access to process
521  *   TokenHandle   [O] Pointer to handle of open access token
522  *
523  * RETURNS
524  *  Success: TRUE. TokenHandle contains the access token.
525  *  Failure: FALSE.
526  *
527  * NOTES
528  *  See NtOpenProcessToken.
529  */
530 BOOL WINAPI
531 OpenProcessToken( HANDLE ProcessHandle, DWORD DesiredAccess,
532                   HANDLE *TokenHandle )
533 {
534         return set_ntstatus(NtOpenProcessToken( ProcessHandle, DesiredAccess, TokenHandle ));
535 }
536
537 /******************************************************************************
538  * OpenThreadToken [ADVAPI32.@]
539  *
540  * Opens the access token associated with a thread handle.
541  *
542  * PARAMS
543  *   ThreadHandle  [I] Handle to process
544  *   DesiredAccess [I] Desired access to the thread
545  *   OpenAsSelf    [I] ???
546  *   TokenHandle   [O] Destination for the token handle
547  *
548  * RETURNS
549  *  Success: TRUE. TokenHandle contains the access token.
550  *  Failure: FALSE.
551  *
552  * NOTES
553  *  See NtOpenThreadToken.
554  */
555 BOOL WINAPI
556 OpenThreadToken( HANDLE ThreadHandle, DWORD DesiredAccess,
557                  BOOL OpenAsSelf, HANDLE *TokenHandle)
558 {
559         return set_ntstatus( NtOpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf, TokenHandle));
560 }
561
562 BOOL WINAPI
563 AdjustTokenGroups( HANDLE TokenHandle, BOOL ResetToDefault, PTOKEN_GROUPS NewState,
564                    DWORD BufferLength, PTOKEN_GROUPS PreviousState, PDWORD ReturnLength )
565 {
566     return set_ntstatus( NtAdjustGroupsToken(TokenHandle, ResetToDefault, NewState, BufferLength,
567                                              PreviousState, ReturnLength));
568 }
569
570 /******************************************************************************
571  * AdjustTokenPrivileges [ADVAPI32.@]
572  *
573  * Adjust the privileges of an open token handle.
574  * 
575  * PARAMS
576  *  TokenHandle          [I]   Handle from OpenProcessToken() or OpenThreadToken() 
577  *  DisableAllPrivileges [I]   TRUE=Remove all privileges, FALSE=Use NewState
578  *  NewState             [I]   Desired new privileges of the token
579  *  BufferLength         [I]   Length of NewState
580  *  PreviousState        [O]   Destination for the previous state
581  *  ReturnLength         [I/O] Size of PreviousState
582  *
583  *
584  * RETURNS
585  *  Success: TRUE. Privileges are set to NewState and PreviousState is updated.
586  *  Failure: FALSE.
587  *
588  * NOTES
589  *  See NtAdjustPrivilegesToken.
590  */
591 BOOL WINAPI
592 AdjustTokenPrivileges( HANDLE TokenHandle, BOOL DisableAllPrivileges,
593                        PTOKEN_PRIVILEGES NewState, DWORD BufferLength,
594                        PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength )
595 {
596     NTSTATUS status;
597
598     TRACE("\n");
599     
600     status = NtAdjustPrivilegesToken(TokenHandle, DisableAllPrivileges,
601                                                      NewState, BufferLength, PreviousState,
602                                                      ReturnLength);
603     SetLastError( RtlNtStatusToDosError( status ));
604     if ((status == STATUS_SUCCESS) || (status == STATUS_NOT_ALL_ASSIGNED))
605         return TRUE;
606     else
607         return FALSE;
608 }
609
610 /******************************************************************************
611  * CheckTokenMembership [ADVAPI32.@]
612  *
613  * Determine if an access token is a member of a SID.
614  * 
615  * PARAMS
616  *   TokenHandle [I] Handle from OpenProcessToken() or OpenThreadToken()
617  *   SidToCheck  [I] SID that possibly contains the token
618  *   IsMember    [O] Destination for result.
619  *
620  * RETURNS
621  *  Success: TRUE. IsMember is TRUE if TokenHandle is a member, FALSE otherwise.
622  *  Failure: FALSE.
623  */
624 BOOL WINAPI
625 CheckTokenMembership( HANDLE token, PSID sid_to_check,
626                       PBOOL is_member )
627 {
628     PTOKEN_GROUPS token_groups = NULL;
629     HANDLE thread_token = NULL;
630     DWORD size, i;
631     BOOL ret;
632
633     TRACE("(%p %s %p)\n", token, debugstr_sid(sid_to_check), is_member);
634
635     *is_member = FALSE;
636
637     if (!token)
638     {
639         if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &thread_token))
640         {
641             HANDLE process_token;
642             ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &process_token);
643             if (!ret)
644                 goto exit;
645             ret = DuplicateTokenEx(process_token, TOKEN_QUERY,
646                 NULL, SecurityImpersonation, TokenImpersonation,
647                 &thread_token);
648             CloseHandle(process_token);
649             if (!ret)
650                 goto exit;
651         }
652         token = thread_token;
653     }
654
655     ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size);
656     if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
657         goto exit;
658
659     token_groups = HeapAlloc(GetProcessHeap(), 0, size);
660     if (!token_groups)
661     {
662         ret = FALSE;
663         goto exit;
664     }
665
666     ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size);
667     if (!ret)
668         goto exit;
669
670     for (i = 0; i < token_groups->GroupCount; i++)
671     {
672         TRACE("Groups[%d]: {0x%x, %s}\n", i,
673             token_groups->Groups[i].Attributes,
674             debugstr_sid(token_groups->Groups[i].Sid));
675         if ((token_groups->Groups[i].Attributes & SE_GROUP_ENABLED) &&
676             EqualSid(sid_to_check, token_groups->Groups[i].Sid))
677         {
678             *is_member = TRUE;
679             TRACE("sid enabled and found in token\n");
680             break;
681         }
682     }
683
684 exit:
685     HeapFree(GetProcessHeap(), 0, token_groups);
686     if (thread_token != NULL) CloseHandle(thread_token);
687
688     return ret;
689 }
690
691 /******************************************************************************
692  * GetTokenInformation [ADVAPI32.@]
693  *
694  * Get a type of information about an access token.
695  *
696  * PARAMS
697  *   token           [I] Handle from OpenProcessToken() or OpenThreadToken()
698  *   tokeninfoclass  [I] A TOKEN_INFORMATION_CLASS from "winnt.h"
699  *   tokeninfo       [O] Destination for token information
700  *   tokeninfolength [I] Length of tokeninfo
701  *   retlen          [O] Destination for returned token information length
702  *
703  * RETURNS
704  *  Success: TRUE. tokeninfo contains retlen bytes of token information
705  *  Failure: FALSE.
706  *
707  * NOTES
708  *  See NtQueryInformationToken.
709  */
710 BOOL WINAPI
711 GetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS tokeninfoclass,
712                      LPVOID tokeninfo, DWORD tokeninfolength, LPDWORD retlen )
713 {
714     TRACE("(%p, %s, %p, %d, %p):\n",
715           token,
716           (tokeninfoclass == TokenUser) ? "TokenUser" :
717           (tokeninfoclass == TokenGroups) ? "TokenGroups" :
718           (tokeninfoclass == TokenPrivileges) ? "TokenPrivileges" :
719           (tokeninfoclass == TokenOwner) ? "TokenOwner" :
720           (tokeninfoclass == TokenPrimaryGroup) ? "TokenPrimaryGroup" :
721           (tokeninfoclass == TokenDefaultDacl) ? "TokenDefaultDacl" :
722           (tokeninfoclass == TokenSource) ? "TokenSource" :
723           (tokeninfoclass == TokenType) ? "TokenType" :
724           (tokeninfoclass == TokenImpersonationLevel) ? "TokenImpersonationLevel" :
725           (tokeninfoclass == TokenStatistics) ? "TokenStatistics" :
726           (tokeninfoclass == TokenRestrictedSids) ? "TokenRestrictedSids" :
727           (tokeninfoclass == TokenSessionId) ? "TokenSessionId" :
728           (tokeninfoclass == TokenGroupsAndPrivileges) ? "TokenGroupsAndPrivileges" :
729           (tokeninfoclass == TokenSessionReference) ? "TokenSessionReference" :
730           (tokeninfoclass == TokenSandBoxInert) ? "TokenSandBoxInert" :
731           "Unknown",
732           tokeninfo, tokeninfolength, retlen);
733     return set_ntstatus( NtQueryInformationToken( token, tokeninfoclass, tokeninfo,
734                                                   tokeninfolength, retlen));
735 }
736
737 /******************************************************************************
738  * SetTokenInformation [ADVAPI32.@]
739  *
740  * Set information for an access token.
741  *
742  * PARAMS
743  *   token           [I] Handle from OpenProcessToken() or OpenThreadToken()
744  *   tokeninfoclass  [I] A TOKEN_INFORMATION_CLASS from "winnt.h"
745  *   tokeninfo       [I] Token information to set
746  *   tokeninfolength [I] Length of tokeninfo
747  *
748  * RETURNS
749  *  Success: TRUE. The information for the token is set to tokeninfo.
750  *  Failure: FALSE.
751  */
752 BOOL WINAPI
753 SetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS tokeninfoclass,
754                      LPVOID tokeninfo, DWORD tokeninfolength )
755 {
756     TRACE("(%p, %s, %p, %d): stub\n",
757           token,
758           (tokeninfoclass == TokenUser) ? "TokenUser" :
759           (tokeninfoclass == TokenGroups) ? "TokenGroups" :
760           (tokeninfoclass == TokenPrivileges) ? "TokenPrivileges" :
761           (tokeninfoclass == TokenOwner) ? "TokenOwner" :
762           (tokeninfoclass == TokenPrimaryGroup) ? "TokenPrimaryGroup" :
763           (tokeninfoclass == TokenDefaultDacl) ? "TokenDefaultDacl" :
764           (tokeninfoclass == TokenSource) ? "TokenSource" :
765           (tokeninfoclass == TokenType) ? "TokenType" :
766           (tokeninfoclass == TokenImpersonationLevel) ? "TokenImpersonationLevel" :
767           (tokeninfoclass == TokenStatistics) ? "TokenStatistics" :
768           (tokeninfoclass == TokenRestrictedSids) ? "TokenRestrictedSids" :
769           (tokeninfoclass == TokenSessionId) ? "TokenSessionId" :
770           (tokeninfoclass == TokenGroupsAndPrivileges) ? "TokenGroupsAndPrivileges" :
771           (tokeninfoclass == TokenSessionReference) ? "TokenSessionReference" :
772           (tokeninfoclass == TokenSandBoxInert) ? "TokenSandBoxInert" :
773           "Unknown",
774           tokeninfo, tokeninfolength);
775
776     return set_ntstatus( NtSetInformationToken( token, tokeninfoclass, tokeninfo, tokeninfolength ));
777 }
778
779 /*************************************************************************
780  * SetThreadToken [ADVAPI32.@]
781  *
782  * Assigns an 'impersonation token' to a thread so it can assume the
783  * security privileges of another thread or process.  Can also remove
784  * a previously assigned token. 
785  *
786  * PARAMS
787  *   thread          [O] Handle to thread to set the token for
788  *   token           [I] Token to set
789  *
790  * RETURNS
791  *  Success: TRUE. The threads access token is set to token
792  *  Failure: FALSE.
793  *
794  * NOTES
795  *  Only supported on NT or higher. On Win9X this function does nothing.
796  *  See SetTokenInformation.
797  */
798 BOOL WINAPI SetThreadToken(PHANDLE thread, HANDLE token)
799 {
800     return set_ntstatus( NtSetInformationThread( thread ? *thread : GetCurrentThread(),
801                                                  ThreadImpersonationToken, &token, sizeof token ));
802 }
803
804 /*************************************************************************
805  * CreateRestrictedToken [ADVAPI32.@]
806  *
807  * Create a new more restricted token from an existing token.
808  *
809  * PARAMS
810  *   baseToken       [I] Token to base the new restricted token on
811  *   flags           [I] Options
812  *   nDisableSids    [I] Length of disableSids array
813  *   disableSids     [I] Array of SIDs to disable in the new token
814  *   nDeletePrivs    [I] Length of deletePrivs array
815  *   deletePrivs     [I] Array of privileges to delete in the new token
816  *   nRestrictSids   [I] Length of restrictSids array
817  *   restrictSids    [I] Array of SIDs to restrict in the new token
818  *   newToken        [O] Address where the new token is stored
819  *
820  * RETURNS
821  *  Success: TRUE
822  *  Failure: FALSE
823  */
824 BOOL WINAPI CreateRestrictedToken(
825     HANDLE baseToken,
826     DWORD flags,
827     DWORD nDisableSids,
828     PSID_AND_ATTRIBUTES disableSids,
829     DWORD nDeletePrivs,
830     PLUID_AND_ATTRIBUTES deletePrivs,
831     DWORD nRestrictSids,
832     PSID_AND_ATTRIBUTES restrictSids,
833     PHANDLE newToken)
834 {
835     FIXME("(%p, 0x%x, %u, %p, %u, %p, %u, %p, %p): stub\n",
836           baseToken, flags, nDisableSids, disableSids,
837           nDeletePrivs, deletePrivs,
838           nRestrictSids, restrictSids,
839           newToken);
840     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
841     return FALSE;
842 }
843
844 /*      ##############################
845         ######  SID FUNCTIONS   ######
846         ##############################
847 */
848
849 /******************************************************************************
850  * AllocateAndInitializeSid [ADVAPI32.@]
851  *
852  * PARAMS
853  *   pIdentifierAuthority []
854  *   nSubAuthorityCount   []
855  *   nSubAuthority0       []
856  *   nSubAuthority1       []
857  *   nSubAuthority2       []
858  *   nSubAuthority3       []
859  *   nSubAuthority4       []
860  *   nSubAuthority5       []
861  *   nSubAuthority6       []
862  *   nSubAuthority7       []
863  *   pSid                 []
864  */
865 BOOL WINAPI
866 AllocateAndInitializeSid( PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
867                           BYTE nSubAuthorityCount,
868                           DWORD nSubAuthority0, DWORD nSubAuthority1,
869                           DWORD nSubAuthority2, DWORD nSubAuthority3,
870                           DWORD nSubAuthority4, DWORD nSubAuthority5,
871                           DWORD nSubAuthority6, DWORD nSubAuthority7,
872                           PSID *pSid )
873 {
874     return set_ntstatus( RtlAllocateAndInitializeSid(
875                              pIdentifierAuthority, nSubAuthorityCount,
876                              nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
877                              nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7,
878                              pSid ));
879 }
880
881 /******************************************************************************
882  * FreeSid [ADVAPI32.@]
883  *
884  * PARAMS
885  *   pSid []
886  */
887 PVOID WINAPI
888 FreeSid( PSID pSid )
889 {
890         RtlFreeSid(pSid);
891         return NULL; /* is documented like this */
892 }
893
894 /******************************************************************************
895  * CopySid [ADVAPI32.@]
896  *
897  * PARAMS
898  *   nDestinationSidLength []
899  *   pDestinationSid       []
900  *   pSourceSid            []
901  */
902 BOOL WINAPI
903 CopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
904 {
905         return RtlCopySid(nDestinationSidLength, pDestinationSid, pSourceSid);
906 }
907
908 /******************************************************************************
909  * CreateWellKnownSid [ADVAPI32.@]
910  */
911 BOOL WINAPI
912 CreateWellKnownSid( WELL_KNOWN_SID_TYPE WellKnownSidType,
913                     PSID DomainSid,
914                     PSID pSid,
915                     DWORD* cbSid)
916 {
917     unsigned int i;
918     TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
919
920     if (cbSid == NULL || (DomainSid && !IsValidSid(DomainSid)))
921     {
922         SetLastError(ERROR_INVALID_PARAMETER);
923         return FALSE;
924     }
925
926     for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) {
927         if (WellKnownSids[i].Type == WellKnownSidType) {
928             DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
929
930             if (*cbSid < length)
931             {
932                 *cbSid = length;
933                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
934                 return FALSE;
935             }
936             if (!pSid)
937             {
938                 SetLastError(ERROR_INVALID_PARAMETER);
939                 return FALSE;
940             }
941             CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
942             *cbSid = length;
943             return TRUE;
944         }
945     }
946
947     if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES)
948     {
949         SetLastError(ERROR_INVALID_PARAMETER);
950         return FALSE;
951     }
952
953     for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
954         if (WellKnownRids[i].Type == WellKnownSidType) {
955             UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid);
956             DWORD domain_sid_length = GetSidLengthRequired(domain_subauth);
957             DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1);
958
959             if (*cbSid < output_sid_length)
960             {
961                 *cbSid = output_sid_length;
962                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
963                 return FALSE;
964             }
965             if (!pSid)
966             {
967                 SetLastError(ERROR_INVALID_PARAMETER);
968                 return FALSE;
969             }
970             CopyMemory(pSid, DomainSid, domain_sid_length);
971             (*GetSidSubAuthorityCount(pSid))++;
972             (*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid;
973             *cbSid = output_sid_length;
974             return TRUE;
975         }
976
977     SetLastError(ERROR_INVALID_PARAMETER);
978     return FALSE;
979 }
980
981 /******************************************************************************
982  * IsWellKnownSid [ADVAPI32.@]
983  */
984 BOOL WINAPI
985 IsWellKnownSid( PSID pSid, WELL_KNOWN_SID_TYPE WellKnownSidType )
986 {
987     unsigned int i;
988     TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
989
990     for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
991         if (WellKnownSids[i].Type == WellKnownSidType)
992             if (EqualSid(pSid, (PSID)&(WellKnownSids[i].Sid.Revision)))
993                 return TRUE;
994
995     return FALSE;
996 }
997
998 BOOL WINAPI
999 IsTokenRestricted( HANDLE TokenHandle )
1000 {
1001     TOKEN_GROUPS *groups;
1002     DWORD size;
1003     NTSTATUS status;
1004     BOOL restricted;
1005
1006     TRACE("(%p)\n", TokenHandle);
1007  
1008     status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, NULL, 0, &size);
1009     if (status != STATUS_BUFFER_TOO_SMALL)
1010         return FALSE;
1011  
1012     groups = HeapAlloc(GetProcessHeap(), 0, size);
1013     if (!groups)
1014     {
1015         SetLastError(ERROR_OUTOFMEMORY);
1016         return FALSE;
1017     }
1018  
1019     status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, groups, size, &size);
1020     if (status != STATUS_SUCCESS)
1021     {
1022         HeapFree(GetProcessHeap(), 0, groups);
1023         return set_ntstatus(status);
1024     }
1025  
1026     if (groups->GroupCount)
1027         restricted = TRUE;
1028     else
1029         restricted = FALSE;
1030      
1031     HeapFree(GetProcessHeap(), 0, groups);
1032  
1033     return restricted;
1034 }
1035
1036 /******************************************************************************
1037  * IsValidSid [ADVAPI32.@]
1038  *
1039  * PARAMS
1040  *   pSid []
1041  */
1042 BOOL WINAPI
1043 IsValidSid( PSID pSid )
1044 {
1045         return RtlValidSid( pSid );
1046 }
1047
1048 /******************************************************************************
1049  * EqualSid [ADVAPI32.@]
1050  *
1051  * PARAMS
1052  *   pSid1 []
1053  *   pSid2 []
1054  */
1055 BOOL WINAPI
1056 EqualSid( PSID pSid1, PSID pSid2 )
1057 {
1058         BOOL ret = RtlEqualSid( pSid1, pSid2 );
1059         SetLastError(ERROR_SUCCESS);
1060         return ret;
1061 }
1062
1063 /******************************************************************************
1064  * EqualPrefixSid [ADVAPI32.@]
1065  */
1066 BOOL WINAPI EqualPrefixSid (PSID pSid1, PSID pSid2)
1067 {
1068         return RtlEqualPrefixSid(pSid1, pSid2);
1069 }
1070
1071 /******************************************************************************
1072  * GetSidLengthRequired [ADVAPI32.@]
1073  *
1074  * PARAMS
1075  *   nSubAuthorityCount []
1076  */
1077 DWORD WINAPI
1078 GetSidLengthRequired( BYTE nSubAuthorityCount )
1079 {
1080         return RtlLengthRequiredSid(nSubAuthorityCount);
1081 }
1082
1083 /******************************************************************************
1084  * InitializeSid [ADVAPI32.@]
1085  *
1086  * PARAMS
1087  *   pIdentifierAuthority []
1088  */
1089 BOOL WINAPI
1090 InitializeSid (
1091         PSID pSid,
1092         PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
1093         BYTE nSubAuthorityCount)
1094 {
1095         return RtlInitializeSid(pSid, pIdentifierAuthority, nSubAuthorityCount);
1096 }
1097
1098 DWORD WINAPI
1099 GetEffectiveRightsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pAccessRights )
1100 {
1101     FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
1102
1103     return 1;
1104 }
1105
1106 DWORD WINAPI
1107 GetEffectiveRightsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pAccessRights )
1108 {
1109     FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
1110
1111     return 1;
1112 }
1113
1114 /******************************************************************************
1115  * GetSidIdentifierAuthority [ADVAPI32.@]
1116  *
1117  * PARAMS
1118  *   pSid []
1119  */
1120 PSID_IDENTIFIER_AUTHORITY WINAPI
1121 GetSidIdentifierAuthority( PSID pSid )
1122 {
1123         return RtlIdentifierAuthoritySid(pSid);
1124 }
1125
1126 /******************************************************************************
1127  * GetSidSubAuthority [ADVAPI32.@]
1128  *
1129  * PARAMS
1130  *   pSid          []
1131  *   nSubAuthority []
1132  */
1133 PDWORD WINAPI
1134 GetSidSubAuthority( PSID pSid, DWORD nSubAuthority )
1135 {
1136         SetLastError(ERROR_SUCCESS);
1137         return RtlSubAuthoritySid(pSid, nSubAuthority);
1138 }
1139
1140 /******************************************************************************
1141  * GetSidSubAuthorityCount [ADVAPI32.@]
1142  *
1143  * PARAMS
1144  *   pSid []
1145  */
1146 PUCHAR WINAPI
1147 GetSidSubAuthorityCount (PSID pSid)
1148 {
1149         SetLastError(ERROR_SUCCESS);
1150         return RtlSubAuthorityCountSid(pSid);
1151 }
1152
1153 /******************************************************************************
1154  * GetLengthSid [ADVAPI32.@]
1155  *
1156  * PARAMS
1157  *   pSid []
1158  */
1159 DWORD WINAPI
1160 GetLengthSid (PSID pSid)
1161 {
1162         return RtlLengthSid(pSid);
1163 }
1164
1165 /*      ##############################################
1166         ######  SECURITY DESCRIPTOR FUNCTIONS   ######
1167         ##############################################
1168 */
1169
1170  /****************************************************************************** 
1171  * BuildSecurityDescriptorA [ADVAPI32.@]
1172  *
1173  * Builds a SD from 
1174  *
1175  * PARAMS
1176  *  pOwner                [I]
1177  *  pGroup                [I]
1178  *  cCountOfAccessEntries [I]
1179  *  pListOfAccessEntries  [I]
1180  *  cCountOfAuditEntries  [I]
1181  *  pListofAuditEntries   [I]
1182  *  pOldSD                [I]
1183  *  lpdwBufferLength      [I/O]
1184  *  pNewSD                [O]
1185  *
1186  * RETURNS
1187  *  Success: ERROR_SUCCESS
1188  *  Failure: nonzero error code from Winerror.h
1189  */
1190 DWORD WINAPI BuildSecurityDescriptorA(
1191     IN PTRUSTEEA pOwner,
1192     IN PTRUSTEEA pGroup,
1193     IN ULONG cCountOfAccessEntries,
1194     IN PEXPLICIT_ACCESSA pListOfAccessEntries,
1195     IN ULONG cCountOfAuditEntries,
1196     IN PEXPLICIT_ACCESSA pListofAuditEntries,
1197     IN PSECURITY_DESCRIPTOR pOldSD,
1198     IN OUT PULONG lpdwBufferLength,
1199     OUT PSECURITY_DESCRIPTOR* pNewSD)
1200
1201     FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
1202           cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
1203           pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
1204  
1205     return ERROR_CALL_NOT_IMPLEMENTED;
1206
1207  
1208 /******************************************************************************
1209  * BuildSecurityDescriptorW [ADVAPI32.@]
1210  *
1211  * See BuildSecurityDescriptorA.
1212  */
1213 DWORD WINAPI BuildSecurityDescriptorW(
1214     IN PTRUSTEEW pOwner,
1215     IN PTRUSTEEW pGroup,
1216     IN ULONG cCountOfAccessEntries,
1217     IN PEXPLICIT_ACCESSW pListOfAccessEntries,
1218     IN ULONG cCountOfAuditEntries,
1219     IN PEXPLICIT_ACCESSW pListofAuditEntries,
1220     IN PSECURITY_DESCRIPTOR pOldSD,
1221     IN OUT PULONG lpdwBufferLength,
1222     OUT PSECURITY_DESCRIPTOR* pNewSD)
1223
1224     FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
1225           cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
1226           pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
1227  
1228     return ERROR_CALL_NOT_IMPLEMENTED;
1229
1230
1231 /******************************************************************************
1232  * InitializeSecurityDescriptor [ADVAPI32.@]
1233  *
1234  * PARAMS
1235  *   pDescr   []
1236  *   revision []
1237  */
1238 BOOL WINAPI
1239 InitializeSecurityDescriptor( PSECURITY_DESCRIPTOR pDescr, DWORD revision )
1240 {
1241         return set_ntstatus( RtlCreateSecurityDescriptor(pDescr, revision ));
1242 }
1243
1244
1245 /******************************************************************************
1246  * MakeAbsoluteSD [ADVAPI32.@]
1247  */
1248 BOOL WINAPI MakeAbsoluteSD (
1249         IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
1250         OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
1251         OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
1252         OUT PACL pDacl,
1253         OUT LPDWORD lpdwDaclSize,
1254         OUT PACL pSacl,
1255         OUT LPDWORD lpdwSaclSize,
1256         OUT PSID pOwner,
1257         OUT LPDWORD lpdwOwnerSize,
1258         OUT PSID pPrimaryGroup,
1259         OUT LPDWORD lpdwPrimaryGroupSize)
1260 {
1261     return set_ntstatus( RtlSelfRelativeToAbsoluteSD(pSelfRelativeSecurityDescriptor,
1262                                                      pAbsoluteSecurityDescriptor,
1263                                                      lpdwAbsoluteSecurityDescriptorSize,
1264                                                      pDacl, lpdwDaclSize, pSacl, lpdwSaclSize,
1265                                                      pOwner, lpdwOwnerSize,
1266                                                      pPrimaryGroup, lpdwPrimaryGroupSize));
1267 }
1268
1269 /******************************************************************************
1270  * GetKernelObjectSecurity [ADVAPI32.@]
1271  */
1272 BOOL WINAPI GetKernelObjectSecurity(
1273         HANDLE Handle,
1274         SECURITY_INFORMATION RequestedInformation,
1275         PSECURITY_DESCRIPTOR pSecurityDescriptor,
1276         DWORD nLength,
1277         LPDWORD lpnLengthNeeded )
1278 {
1279     TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", Handle, RequestedInformation,
1280           pSecurityDescriptor, nLength, lpnLengthNeeded);
1281
1282     return set_ntstatus( NtQuerySecurityObject(Handle, RequestedInformation, pSecurityDescriptor,
1283                                                nLength, lpnLengthNeeded ));
1284 }
1285
1286 /******************************************************************************
1287  * GetPrivateObjectSecurity [ADVAPI32.@]
1288  */
1289 BOOL WINAPI GetPrivateObjectSecurity(
1290         PSECURITY_DESCRIPTOR ObjectDescriptor,
1291         SECURITY_INFORMATION SecurityInformation,
1292         PSECURITY_DESCRIPTOR ResultantDescriptor,
1293         DWORD DescriptorLength,
1294         PDWORD ReturnLength )
1295 {
1296     SECURITY_DESCRIPTOR desc;
1297     BOOL defaulted, present;
1298     PACL pacl;
1299     PSID psid;
1300
1301     TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", ObjectDescriptor, SecurityInformation,
1302           ResultantDescriptor, DescriptorLength, ReturnLength);
1303
1304     if (!InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION))
1305         return FALSE;
1306
1307     if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1308     {
1309         if (!GetSecurityDescriptorOwner(ObjectDescriptor, &psid, &defaulted))
1310             return FALSE;
1311         SetSecurityDescriptorOwner(&desc, psid, defaulted);
1312     }
1313
1314     if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1315     {
1316         if (!GetSecurityDescriptorGroup(ObjectDescriptor, &psid, &defaulted))
1317             return FALSE;
1318         SetSecurityDescriptorGroup(&desc, psid, defaulted);
1319     }
1320
1321     if (SecurityInformation & DACL_SECURITY_INFORMATION)
1322     {
1323         if (!GetSecurityDescriptorDacl(ObjectDescriptor, &present, &pacl, &defaulted))
1324             return FALSE;
1325         SetSecurityDescriptorDacl(&desc, present, pacl, defaulted);
1326     }
1327
1328     if (SecurityInformation & SACL_SECURITY_INFORMATION)
1329     {
1330         if (!GetSecurityDescriptorSacl(ObjectDescriptor, &present, &pacl, &defaulted))
1331             return FALSE;
1332         SetSecurityDescriptorSacl(&desc, present, pacl, defaulted);
1333     }
1334
1335     *ReturnLength = DescriptorLength;
1336     return MakeSelfRelativeSD(&desc, ResultantDescriptor, ReturnLength);
1337 }
1338
1339 /******************************************************************************
1340  * GetSecurityDescriptorLength [ADVAPI32.@]
1341  */
1342 DWORD WINAPI GetSecurityDescriptorLength( PSECURITY_DESCRIPTOR pDescr)
1343 {
1344         return RtlLengthSecurityDescriptor(pDescr);
1345 }
1346
1347 /******************************************************************************
1348  * GetSecurityDescriptorOwner [ADVAPI32.@]
1349  *
1350  * PARAMS
1351  *   pOwner            []
1352  *   lpbOwnerDefaulted []
1353  */
1354 BOOL WINAPI
1355 GetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pDescr, PSID *pOwner,
1356                             LPBOOL lpbOwnerDefaulted )
1357 {
1358     BOOLEAN defaulted;
1359     BOOL ret = set_ntstatus( RtlGetOwnerSecurityDescriptor( pDescr, pOwner, &defaulted ));
1360     *lpbOwnerDefaulted = defaulted;
1361     return ret;
1362 }
1363
1364 /******************************************************************************
1365  * SetSecurityDescriptorOwner [ADVAPI32.@]
1366  *
1367  * PARAMS
1368  */
1369 BOOL WINAPI SetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1370                                    PSID pOwner, BOOL bOwnerDefaulted)
1371 {
1372     return set_ntstatus( RtlSetOwnerSecurityDescriptor(pSecurityDescriptor, pOwner, bOwnerDefaulted));
1373 }
1374 /******************************************************************************
1375  * GetSecurityDescriptorGroup                   [ADVAPI32.@]
1376  */
1377 BOOL WINAPI GetSecurityDescriptorGroup(
1378         PSECURITY_DESCRIPTOR SecurityDescriptor,
1379         PSID *Group,
1380         LPBOOL GroupDefaulted)
1381 {
1382     BOOLEAN defaulted;
1383     BOOL ret = set_ntstatus( RtlGetGroupSecurityDescriptor(SecurityDescriptor, Group, &defaulted ));
1384     *GroupDefaulted = defaulted;
1385     return ret;
1386 }
1387 /******************************************************************************
1388  * SetSecurityDescriptorGroup [ADVAPI32.@]
1389  */
1390 BOOL WINAPI SetSecurityDescriptorGroup ( PSECURITY_DESCRIPTOR SecurityDescriptor,
1391                                            PSID Group, BOOL GroupDefaulted)
1392 {
1393     return set_ntstatus( RtlSetGroupSecurityDescriptor( SecurityDescriptor, Group, GroupDefaulted));
1394 }
1395
1396 /******************************************************************************
1397  * IsValidSecurityDescriptor [ADVAPI32.@]
1398  *
1399  * PARAMS
1400  *   lpsecdesc []
1401  */
1402 BOOL WINAPI
1403 IsValidSecurityDescriptor( PSECURITY_DESCRIPTOR SecurityDescriptor )
1404 {
1405     return set_ntstatus( RtlValidSecurityDescriptor(SecurityDescriptor));
1406 }
1407
1408 /******************************************************************************
1409  *  GetSecurityDescriptorDacl                   [ADVAPI32.@]
1410  */
1411 BOOL WINAPI GetSecurityDescriptorDacl(
1412         IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
1413         OUT LPBOOL lpbDaclPresent,
1414         OUT PACL *pDacl,
1415         OUT LPBOOL lpbDaclDefaulted)
1416 {
1417     BOOLEAN present, defaulted;
1418     BOOL ret = set_ntstatus( RtlGetDaclSecurityDescriptor(pSecurityDescriptor, &present, pDacl, &defaulted));
1419     *lpbDaclPresent = present;
1420     *lpbDaclDefaulted = defaulted;
1421     return ret;
1422 }
1423
1424 /******************************************************************************
1425  *  SetSecurityDescriptorDacl                   [ADVAPI32.@]
1426  */
1427 BOOL WINAPI
1428 SetSecurityDescriptorDacl (
1429         PSECURITY_DESCRIPTOR lpsd,
1430         BOOL daclpresent,
1431         PACL dacl,
1432         BOOL dacldefaulted )
1433 {
1434     return set_ntstatus( RtlSetDaclSecurityDescriptor (lpsd, daclpresent, dacl, dacldefaulted ) );
1435 }
1436 /******************************************************************************
1437  *  GetSecurityDescriptorSacl                   [ADVAPI32.@]
1438  */
1439 BOOL WINAPI GetSecurityDescriptorSacl(
1440         IN PSECURITY_DESCRIPTOR lpsd,
1441         OUT LPBOOL lpbSaclPresent,
1442         OUT PACL *pSacl,
1443         OUT LPBOOL lpbSaclDefaulted)
1444 {
1445     BOOLEAN present, defaulted;
1446     BOOL ret = set_ntstatus( RtlGetSaclSecurityDescriptor(lpsd, &present, pSacl, &defaulted) );
1447     *lpbSaclPresent = present;
1448     *lpbSaclDefaulted = defaulted;
1449     return ret;
1450 }
1451
1452 /**************************************************************************
1453  * SetSecurityDescriptorSacl                    [ADVAPI32.@]
1454  */
1455 BOOL WINAPI SetSecurityDescriptorSacl (
1456         PSECURITY_DESCRIPTOR lpsd,
1457         BOOL saclpresent,
1458         PACL lpsacl,
1459         BOOL sacldefaulted)
1460 {
1461     return set_ntstatus (RtlSetSaclSecurityDescriptor(lpsd, saclpresent, lpsacl, sacldefaulted));
1462 }
1463 /******************************************************************************
1464  * MakeSelfRelativeSD [ADVAPI32.@]
1465  *
1466  * PARAMS
1467  *   lpabssecdesc  []
1468  *   lpselfsecdesc []
1469  *   lpbuflen      []
1470  */
1471 BOOL WINAPI
1472 MakeSelfRelativeSD(
1473         IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
1474         IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
1475         IN OUT LPDWORD lpdwBufferLength)
1476 {
1477     return set_ntstatus( RtlMakeSelfRelativeSD( pAbsoluteSecurityDescriptor,
1478                                                 pSelfRelativeSecurityDescriptor, lpdwBufferLength));
1479 }
1480
1481 /******************************************************************************
1482  * GetSecurityDescriptorControl                 [ADVAPI32.@]
1483  */
1484
1485 BOOL WINAPI GetSecurityDescriptorControl ( PSECURITY_DESCRIPTOR  pSecurityDescriptor,
1486                  PSECURITY_DESCRIPTOR_CONTROL pControl, LPDWORD lpdwRevision)
1487 {
1488     return set_ntstatus( RtlGetControlSecurityDescriptor(pSecurityDescriptor,pControl,lpdwRevision));
1489 }
1490
1491 /******************************************************************************
1492  * SetSecurityDescriptorControl                 [ADVAPI32.@]
1493  */
1494 BOOL WINAPI SetSecurityDescriptorControl( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1495   SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1496   SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet )
1497 {
1498     return set_ntstatus( RtlSetControlSecurityDescriptor(
1499         pSecurityDescriptor, ControlBitsOfInterest, ControlBitsToSet ) );
1500 }
1501
1502 /*      ##############################
1503         ######  ACL FUNCTIONS   ######
1504         ##############################
1505 */
1506
1507 /*************************************************************************
1508  * InitializeAcl [ADVAPI32.@]
1509  */
1510 BOOL WINAPI InitializeAcl(PACL acl, DWORD size, DWORD rev)
1511 {
1512     return set_ntstatus( RtlCreateAcl(acl, size, rev));
1513 }
1514
1515 BOOL WINAPI ImpersonateNamedPipeClient( HANDLE hNamedPipe )
1516 {
1517     IO_STATUS_BLOCK io_block;
1518
1519     TRACE("(%p)\n", hNamedPipe);
1520
1521     return set_ntstatus( NtFsControlFile(hNamedPipe, NULL, NULL, NULL,
1522                          &io_block, FSCTL_PIPE_IMPERSONATE, NULL, 0, NULL, 0) );
1523 }
1524
1525 /******************************************************************************
1526  *  AddAccessAllowedAce [ADVAPI32.@]
1527  */
1528 BOOL WINAPI AddAccessAllowedAce(
1529         IN OUT PACL pAcl,
1530         IN DWORD dwAceRevision,
1531         IN DWORD AccessMask,
1532         IN PSID pSid)
1533 {
1534     return set_ntstatus(RtlAddAccessAllowedAce(pAcl, dwAceRevision, AccessMask, pSid));
1535 }
1536
1537 /******************************************************************************
1538  *  AddAccessAllowedAceEx [ADVAPI32.@]
1539  */
1540 BOOL WINAPI AddAccessAllowedAceEx(
1541         IN OUT PACL pAcl,
1542         IN DWORD dwAceRevision,
1543         IN DWORD AceFlags,
1544         IN DWORD AccessMask,
1545         IN PSID pSid)
1546 {
1547     return set_ntstatus(RtlAddAccessAllowedAceEx(pAcl, dwAceRevision, AceFlags, AccessMask, pSid));
1548 }
1549
1550 /******************************************************************************
1551  *  AddAccessDeniedAce [ADVAPI32.@]
1552  */
1553 BOOL WINAPI AddAccessDeniedAce(
1554         IN OUT PACL pAcl,
1555         IN DWORD dwAceRevision,
1556         IN DWORD AccessMask,
1557         IN PSID pSid)
1558 {
1559     return set_ntstatus(RtlAddAccessDeniedAce(pAcl, dwAceRevision, AccessMask, pSid));
1560 }
1561
1562 /******************************************************************************
1563  *  AddAccessDeniedAceEx [ADVAPI32.@]
1564  */
1565 BOOL WINAPI AddAccessDeniedAceEx(
1566         IN OUT PACL pAcl,
1567         IN DWORD dwAceRevision,
1568         IN DWORD AceFlags,
1569         IN DWORD AccessMask,
1570         IN PSID pSid)
1571 {
1572     return set_ntstatus(RtlAddAccessDeniedAceEx(pAcl, dwAceRevision, AceFlags, AccessMask, pSid));
1573 }
1574
1575 /******************************************************************************
1576  *  AddAce [ADVAPI32.@]
1577  */
1578 BOOL WINAPI AddAce(
1579         IN OUT PACL pAcl,
1580         IN DWORD dwAceRevision,
1581         IN DWORD dwStartingAceIndex,
1582         LPVOID pAceList,
1583         DWORD nAceListLength)
1584 {
1585     return set_ntstatus(RtlAddAce(pAcl, dwAceRevision, dwStartingAceIndex, pAceList, nAceListLength));
1586 }
1587
1588 /******************************************************************************
1589  * DeleteAce [ADVAPI32.@]
1590  */
1591 BOOL WINAPI DeleteAce(PACL pAcl, DWORD dwAceIndex)
1592 {
1593     return set_ntstatus(RtlDeleteAce(pAcl, dwAceIndex));
1594 }
1595
1596 /******************************************************************************
1597  *  FindFirstFreeAce [ADVAPI32.@]
1598  */
1599 BOOL WINAPI FindFirstFreeAce(IN PACL pAcl, LPVOID * pAce)
1600 {
1601         return RtlFirstFreeAce(pAcl, (PACE_HEADER *)pAce);
1602 }
1603
1604 /******************************************************************************
1605  * GetAce [ADVAPI32.@]
1606  */
1607 BOOL WINAPI GetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1608 {
1609     return set_ntstatus(RtlGetAce(pAcl, dwAceIndex, pAce));
1610 }
1611
1612 /******************************************************************************
1613  * GetAclInformation [ADVAPI32.@]
1614  */
1615 BOOL WINAPI GetAclInformation(
1616   PACL pAcl,
1617   LPVOID pAclInformation,
1618   DWORD nAclInformationLength,
1619   ACL_INFORMATION_CLASS dwAclInformationClass)
1620 {
1621     return set_ntstatus(RtlQueryInformationAcl(pAcl, pAclInformation,
1622                                                nAclInformationLength, dwAclInformationClass));
1623 }
1624
1625 /******************************************************************************
1626  *  IsValidAcl [ADVAPI32.@]
1627  */
1628 BOOL WINAPI IsValidAcl(IN PACL pAcl)
1629 {
1630         return RtlValidAcl(pAcl);
1631 }
1632
1633 /*      ##############################
1634         ######  MISC FUNCTIONS  ######
1635         ##############################
1636 */
1637
1638 /******************************************************************************
1639  * AllocateLocallyUniqueId [ADVAPI32.@]
1640  *
1641  * PARAMS
1642  *   lpLuid []
1643  */
1644 BOOL WINAPI AllocateLocallyUniqueId( PLUID lpLuid )
1645 {
1646     return set_ntstatus(NtAllocateLocallyUniqueId(lpLuid));
1647 }
1648
1649 static const WCHAR SE_CREATE_TOKEN_NAME_W[] =
1650  { 'S','e','C','r','e','a','t','e','T','o','k','e','n','P','r','i','v','i','l','e','g','e',0 };
1651 static const WCHAR SE_ASSIGNPRIMARYTOKEN_NAME_W[] =
1652  { 'S','e','A','s','s','i','g','n','P','r','i','m','a','r','y','T','o','k','e','n','P','r','i','v','i','l','e','g','e',0 };
1653 static const WCHAR SE_LOCK_MEMORY_NAME_W[] =
1654  { 'S','e','L','o','c','k','M','e','m','o','r','y','P','r','i','v','i','l','e','g','e',0 };
1655 static const WCHAR SE_INCREASE_QUOTA_NAME_W[] =
1656  { 'S','e','I','n','c','r','e','a','s','e','Q','u','o','t','a','P','r','i','v','i','l','e','g','e',0 };
1657 static const WCHAR SE_MACHINE_ACCOUNT_NAME_W[] =
1658  { 'S','e','M','a','c','h','i','n','e','A','c','c','o','u','n','t','P','r','i','v','i','l','e','g','e',0 };
1659 static const WCHAR SE_TCB_NAME_W[] =
1660  { 'S','e','T','c','b','P','r','i','v','i','l','e','g','e',0 };
1661 static const WCHAR SE_SECURITY_NAME_W[] =
1662  { 'S','e','S','e','c','u','r','i','t','y','P','r','i','v','i','l','e','g','e',0 };
1663 static const WCHAR SE_TAKE_OWNERSHIP_NAME_W[] =
1664  { 'S','e','T','a','k','e','O','w','n','e','r','s','h','i','p','P','r','i','v','i','l','e','g','e',0 };
1665 static const WCHAR SE_LOAD_DRIVER_NAME_W[] =
1666  { 'S','e','L','o','a','d','D','r','i','v','e','r','P','r','i','v','i','l','e','g','e',0 };
1667 static const WCHAR SE_SYSTEM_PROFILE_NAME_W[] =
1668  { 'S','e','S','y','s','t','e','m','P','r','o','f','i','l','e','P','r','i','v','i','l','e','g','e',0 };
1669 static const WCHAR SE_SYSTEMTIME_NAME_W[] =
1670  { 'S','e','S','y','s','t','e','m','t','i','m','e','P','r','i','v','i','l','e','g','e',0 };
1671 static const WCHAR SE_PROF_SINGLE_PROCESS_NAME_W[] =
1672  { 'S','e','P','r','o','f','i','l','e','S','i','n','g','l','e','P','r','o','c','e','s','s','P','r','i','v','i','l','e','g','e',0 };
1673 static const WCHAR SE_INC_BASE_PRIORITY_NAME_W[] =
1674  { 'S','e','I','n','c','r','e','a','s','e','B','a','s','e','P','r','i','o','r','i','t','y','P','r','i','v','i','l','e','g','e',0 };
1675 static const WCHAR SE_CREATE_PAGEFILE_NAME_W[] =
1676  { 'S','e','C','r','e','a','t','e','P','a','g','e','f','i','l','e','P','r','i','v','i','l','e','g','e',0 };
1677 static const WCHAR SE_CREATE_PERMANENT_NAME_W[] =
1678  { 'S','e','C','r','e','a','t','e','P','e','r','m','a','n','e','n','t','P','r','i','v','i','l','e','g','e',0 };
1679 static const WCHAR SE_BACKUP_NAME_W[] =
1680  { 'S','e','B','a','c','k','u','p','P','r','i','v','i','l','e','g','e',0 };
1681 static const WCHAR SE_RESTORE_NAME_W[] =
1682  { 'S','e','R','e','s','t','o','r','e','P','r','i','v','i','l','e','g','e',0 };
1683 static const WCHAR SE_SHUTDOWN_NAME_W[] =
1684  { 'S','e','S','h','u','t','d','o','w','n','P','r','i','v','i','l','e','g','e',0 };
1685 static const WCHAR SE_DEBUG_NAME_W[] =
1686  { 'S','e','D','e','b','u','g','P','r','i','v','i','l','e','g','e',0 };
1687 static const WCHAR SE_AUDIT_NAME_W[] =
1688  { 'S','e','A','u','d','i','t','P','r','i','v','i','l','e','g','e',0 };
1689 static const WCHAR SE_SYSTEM_ENVIRONMENT_NAME_W[] =
1690  { 'S','e','S','y','s','t','e','m','E','n','v','i','r','o','n','m','e','n','t','P','r','i','v','i','l','e','g','e',0 };
1691 static const WCHAR SE_CHANGE_NOTIFY_NAME_W[] =
1692  { 'S','e','C','h','a','n','g','e','N','o','t','i','f','y','P','r','i','v','i','l','e','g','e',0 };
1693 static const WCHAR SE_REMOTE_SHUTDOWN_NAME_W[] =
1694  { 'S','e','R','e','m','o','t','e','S','h','u','t','d','o','w','n','P','r','i','v','i','l','e','g','e',0 };
1695 static const WCHAR SE_UNDOCK_NAME_W[] =
1696  { 'S','e','U','n','d','o','c','k','P','r','i','v','i','l','e','g','e',0 };
1697 static const WCHAR SE_SYNC_AGENT_NAME_W[] =
1698  { 'S','e','S','y','n','c','A','g','e','n','t','P','r','i','v','i','l','e','g','e',0 };
1699 static const WCHAR SE_ENABLE_DELEGATION_NAME_W[] =
1700  { 'S','e','E','n','a','b','l','e','D','e','l','e','g','a','t','i','o','n','P','r','i','v','i','l','e','g','e',0 };
1701 static const WCHAR SE_MANAGE_VOLUME_NAME_W[] =
1702  { 'S','e','M','a','n','a','g','e','V','o','l','u','m','e','P','r','i','v','i','l','e','g','e',0 };
1703 static const WCHAR SE_IMPERSONATE_NAME_W[] =
1704  { 'S','e','I','m','p','e','r','s','o','n','a','t','e','P','r','i','v','i','l','e','g','e',0 };
1705 static const WCHAR SE_CREATE_GLOBAL_NAME_W[] =
1706  { 'S','e','C','r','e','a','t','e','G','l','o','b','a','l','P','r','i','v','i','l','e','g','e',0 };
1707
1708 static const WCHAR * const WellKnownPrivNames[SE_MAX_WELL_KNOWN_PRIVILEGE + 1] =
1709 {
1710     NULL,
1711     NULL,
1712     SE_CREATE_TOKEN_NAME_W,
1713     SE_ASSIGNPRIMARYTOKEN_NAME_W,
1714     SE_LOCK_MEMORY_NAME_W,
1715     SE_INCREASE_QUOTA_NAME_W,
1716     SE_MACHINE_ACCOUNT_NAME_W,
1717     SE_TCB_NAME_W,
1718     SE_SECURITY_NAME_W,
1719     SE_TAKE_OWNERSHIP_NAME_W,
1720     SE_LOAD_DRIVER_NAME_W,
1721     SE_SYSTEM_PROFILE_NAME_W,
1722     SE_SYSTEMTIME_NAME_W,
1723     SE_PROF_SINGLE_PROCESS_NAME_W,
1724     SE_INC_BASE_PRIORITY_NAME_W,
1725     SE_CREATE_PAGEFILE_NAME_W,
1726     SE_CREATE_PERMANENT_NAME_W,
1727     SE_BACKUP_NAME_W,
1728     SE_RESTORE_NAME_W,
1729     SE_SHUTDOWN_NAME_W,
1730     SE_DEBUG_NAME_W,
1731     SE_AUDIT_NAME_W,
1732     SE_SYSTEM_ENVIRONMENT_NAME_W,
1733     SE_CHANGE_NOTIFY_NAME_W,
1734     SE_REMOTE_SHUTDOWN_NAME_W,
1735     SE_UNDOCK_NAME_W,
1736     SE_SYNC_AGENT_NAME_W,
1737     SE_ENABLE_DELEGATION_NAME_W,
1738     SE_MANAGE_VOLUME_NAME_W,
1739     SE_IMPERSONATE_NAME_W,
1740     SE_CREATE_GLOBAL_NAME_W,
1741 };
1742
1743 /******************************************************************************
1744  * LookupPrivilegeValueW                        [ADVAPI32.@]
1745  *
1746  * See LookupPrivilegeValueA.
1747  */
1748 BOOL WINAPI
1749 LookupPrivilegeValueW( LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid )
1750 {
1751     UINT i;
1752
1753     TRACE("%s,%s,%p\n",debugstr_w(lpSystemName), debugstr_w(lpName), lpLuid);
1754
1755     if (!ADVAPI_IsLocalComputer(lpSystemName))
1756     {
1757         SetLastError(RPC_S_SERVER_UNAVAILABLE);
1758         return FALSE;
1759     }
1760     if (!lpName)
1761     {
1762         SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1763         return FALSE;
1764     }
1765     for( i=SE_MIN_WELL_KNOWN_PRIVILEGE; i<=SE_MAX_WELL_KNOWN_PRIVILEGE; i++ )
1766     {
1767         if( !WellKnownPrivNames[i] )
1768             continue;
1769         if( strcmpiW( WellKnownPrivNames[i], lpName) )
1770             continue;
1771         lpLuid->LowPart = i;
1772         lpLuid->HighPart = 0;
1773         TRACE( "%s -> %08x-%08x\n",debugstr_w( lpSystemName ),
1774                lpLuid->HighPart, lpLuid->LowPart );
1775         return TRUE;
1776     }
1777     SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1778     return FALSE;
1779 }
1780
1781 /******************************************************************************
1782  * LookupPrivilegeValueA                        [ADVAPI32.@]
1783  *
1784  * Retrieves LUID used on a system to represent the privilege name.
1785  *
1786  * PARAMS
1787  *  lpSystemName [I] Name of the system
1788  *  lpName       [I] Name of the privilege
1789  *  lpLuid       [O] Destination for the resulting LUID
1790  *
1791  * RETURNS
1792  *  Success: TRUE. lpLuid contains the requested LUID.
1793  *  Failure: FALSE.
1794  */
1795 BOOL WINAPI
1796 LookupPrivilegeValueA( LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid )
1797 {
1798     UNICODE_STRING lpSystemNameW;
1799     UNICODE_STRING lpNameW;
1800     BOOL ret;
1801
1802     RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1803     RtlCreateUnicodeStringFromAsciiz(&lpNameW,lpName);
1804     ret = LookupPrivilegeValueW(lpSystemNameW.Buffer, lpNameW.Buffer, lpLuid);
1805     RtlFreeUnicodeString(&lpNameW);
1806     RtlFreeUnicodeString(&lpSystemNameW);
1807     return ret;
1808 }
1809
1810 BOOL WINAPI LookupPrivilegeDisplayNameA( LPCSTR lpSystemName, LPCSTR lpName, LPSTR lpDisplayName,
1811                                          LPDWORD cchDisplayName, LPDWORD lpLanguageId )
1812 {
1813     FIXME("%s %s %s %p %p - stub\n", debugstr_a(lpSystemName), debugstr_a(lpName),
1814           debugstr_a(lpDisplayName), cchDisplayName, lpLanguageId);
1815
1816     return FALSE;
1817 }
1818
1819 BOOL WINAPI LookupPrivilegeDisplayNameW( LPCWSTR lpSystemName, LPCWSTR lpName, LPWSTR lpDisplayName,
1820                                          LPDWORD cchDisplayName, LPDWORD lpLanguageId )
1821 {
1822     FIXME("%s %s %s %p %p - stub\n", debugstr_w(lpSystemName), debugstr_w(lpName),
1823           debugstr_w(lpDisplayName), cchDisplayName, lpLanguageId);
1824
1825     return FALSE;
1826 }
1827
1828 /******************************************************************************
1829  * LookupPrivilegeNameA                 [ADVAPI32.@]
1830  *
1831  * See LookupPrivilegeNameW.
1832  */
1833 BOOL WINAPI
1834 LookupPrivilegeNameA( LPCSTR lpSystemName, PLUID lpLuid, LPSTR lpName,
1835  LPDWORD cchName)
1836 {
1837     UNICODE_STRING lpSystemNameW;
1838     BOOL ret;
1839     DWORD wLen = 0;
1840
1841     TRACE("%s %p %p %p\n", debugstr_a(lpSystemName), lpLuid, lpName, cchName);
1842
1843     RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1844     ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, NULL, &wLen);
1845     if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1846     {
1847         LPWSTR lpNameW = HeapAlloc(GetProcessHeap(), 0, wLen * sizeof(WCHAR));
1848
1849         ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, lpNameW,
1850          &wLen);
1851         if (ret)
1852         {
1853             /* Windows crashes if cchName is NULL, so will I */
1854             unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName,
1855              *cchName, NULL, NULL);
1856
1857             if (len == 0)
1858             {
1859                 /* WideCharToMultiByte failed */
1860                 ret = FALSE;
1861             }
1862             else if (len > *cchName)
1863             {
1864                 *cchName = len;
1865                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1866                 ret = FALSE;
1867             }
1868             else
1869             {
1870                 /* WideCharToMultiByte succeeded, output length needs to be
1871                  * length not including NULL terminator
1872                  */
1873                 *cchName = len - 1;
1874             }
1875         }
1876         HeapFree(GetProcessHeap(), 0, lpNameW);
1877     }
1878     RtlFreeUnicodeString(&lpSystemNameW);
1879     return ret;
1880 }
1881
1882 /******************************************************************************
1883  * LookupPrivilegeNameW                 [ADVAPI32.@]
1884  *
1885  * Retrieves the privilege name referred to by the LUID lpLuid.
1886  *
1887  * PARAMS
1888  *  lpSystemName [I]   Name of the system
1889  *  lpLuid       [I]   Privilege value
1890  *  lpName       [O]   Name of the privilege
1891  *  cchName      [I/O] Number of characters in lpName.
1892  *
1893  * RETURNS
1894  *  Success: TRUE. lpName contains the name of the privilege whose value is
1895  *  *lpLuid.
1896  *  Failure: FALSE.
1897  *
1898  * REMARKS
1899  *  Only well-known privilege names (those defined in winnt.h) can be retrieved
1900  *  using this function.
1901  *  If the length of lpName is too small, on return *cchName will contain the
1902  *  number of WCHARs needed to contain the privilege, including the NULL
1903  *  terminator, and GetLastError will return ERROR_INSUFFICIENT_BUFFER.
1904  *  On success, *cchName will contain the number of characters stored in
1905  *  lpName, NOT including the NULL terminator.
1906  */
1907 BOOL WINAPI
1908 LookupPrivilegeNameW( LPCWSTR lpSystemName, PLUID lpLuid, LPWSTR lpName,
1909  LPDWORD cchName)
1910 {
1911     size_t privNameLen;
1912
1913     TRACE("%s,%p,%p,%p\n",debugstr_w(lpSystemName), lpLuid, lpName, cchName);
1914
1915     if (!ADVAPI_IsLocalComputer(lpSystemName))
1916     {
1917         SetLastError(RPC_S_SERVER_UNAVAILABLE);
1918         return FALSE;
1919     }
1920     if (lpLuid->HighPart || (lpLuid->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
1921      lpLuid->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE))
1922     {
1923         SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1924         return FALSE;
1925     }
1926     privNameLen = strlenW(WellKnownPrivNames[lpLuid->LowPart]);
1927     /* Windows crashes if cchName is NULL, so will I */
1928     if (*cchName <= privNameLen)
1929     {
1930         *cchName = privNameLen + 1;
1931         SetLastError(ERROR_INSUFFICIENT_BUFFER);
1932         return FALSE;
1933     }
1934     else
1935     {
1936         strcpyW(lpName, WellKnownPrivNames[lpLuid->LowPart]);
1937         *cchName = privNameLen;
1938         return TRUE;
1939     }
1940 }
1941
1942 /******************************************************************************
1943  * GetFileSecurityA [ADVAPI32.@]
1944  *
1945  * Obtains Specified information about the security of a file or directory.
1946  *
1947  * PARAMS
1948  *  lpFileName           [I] Name of the file to get info for
1949  *  RequestedInformation [I] SE_ flags from "winnt.h"
1950  *  pSecurityDescriptor  [O] Destination for security information
1951  *  nLength              [I] Length of pSecurityDescriptor
1952  *  lpnLengthNeeded      [O] Destination for length of returned security information
1953  *
1954  * RETURNS
1955  *  Success: TRUE. pSecurityDescriptor contains the requested information.
1956  *  Failure: FALSE. lpnLengthNeeded contains the required space to return the info. 
1957  *
1958  * NOTES
1959  *  The information returned is constrained by the callers access rights and
1960  *  privileges.
1961  */
1962 BOOL WINAPI
1963 GetFileSecurityA( LPCSTR lpFileName,
1964                     SECURITY_INFORMATION RequestedInformation,
1965                     PSECURITY_DESCRIPTOR pSecurityDescriptor,
1966                     DWORD nLength, LPDWORD lpnLengthNeeded )
1967 {
1968     DWORD len;
1969     BOOL r;
1970     LPWSTR name = NULL;
1971
1972     if( lpFileName )
1973     {
1974         len = MultiByteToWideChar( CP_ACP, 0, lpFileName, -1, NULL, 0 );
1975         name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1976         MultiByteToWideChar( CP_ACP, 0, lpFileName, -1, name, len );
1977     }
1978
1979     r = GetFileSecurityW( name, RequestedInformation, pSecurityDescriptor,
1980                           nLength, lpnLengthNeeded );
1981     HeapFree( GetProcessHeap(), 0, name );
1982
1983     return r;
1984 }
1985
1986 /******************************************************************************
1987  * GetFileSecurityW [ADVAPI32.@]
1988  *
1989  * See GetFileSecurityA.
1990  */
1991 BOOL WINAPI
1992 GetFileSecurityW( LPCWSTR lpFileName,
1993                     SECURITY_INFORMATION RequestedInformation,
1994                     PSECURITY_DESCRIPTOR pSecurityDescriptor,
1995                     DWORD nLength, LPDWORD lpnLengthNeeded )
1996 {
1997     HANDLE hfile;
1998     NTSTATUS status;
1999     DWORD access = 0;
2000
2001     TRACE("(%s,%d,%p,%d,%p)\n", debugstr_w(lpFileName),
2002           RequestedInformation, pSecurityDescriptor,
2003           nLength, lpnLengthNeeded);
2004
2005     if (RequestedInformation & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|
2006                                 DACL_SECURITY_INFORMATION))
2007         access |= READ_CONTROL;
2008     if (RequestedInformation & SACL_SECURITY_INFORMATION)
2009         access |= ACCESS_SYSTEM_SECURITY;
2010
2011     hfile = CreateFileW( lpFileName, access, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
2012                          NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2013     if ( hfile == INVALID_HANDLE_VALUE )
2014         return FALSE;
2015
2016     status = NtQuerySecurityObject( hfile, RequestedInformation, pSecurityDescriptor,
2017                                     nLength, lpnLengthNeeded );
2018     CloseHandle( hfile );
2019     return set_ntstatus( status );
2020 }
2021
2022
2023 /******************************************************************************
2024  * LookupAccountSidA [ADVAPI32.@]
2025  */
2026 BOOL WINAPI
2027 LookupAccountSidA(
2028         IN LPCSTR system,
2029         IN PSID sid,
2030         OUT LPSTR account,
2031         IN OUT LPDWORD accountSize,
2032         OUT LPSTR domain,
2033         IN OUT LPDWORD domainSize,
2034         OUT PSID_NAME_USE name_use )
2035 {
2036     DWORD len;
2037     BOOL r;
2038     LPWSTR systemW = NULL;
2039     LPWSTR accountW = NULL;
2040     LPWSTR domainW = NULL;
2041     DWORD accountSizeW = *accountSize;
2042     DWORD domainSizeW = *domainSize;
2043
2044     if (system) {
2045         len = MultiByteToWideChar( CP_ACP, 0, system, -1, NULL, 0 );
2046         systemW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
2047         MultiByteToWideChar( CP_ACP, 0, system, -1, systemW, len );
2048     }
2049     if (account)
2050         accountW = HeapAlloc( GetProcessHeap(), 0, accountSizeW * sizeof(WCHAR) );
2051     if (domain)
2052         domainW = HeapAlloc( GetProcessHeap(), 0, domainSizeW * sizeof(WCHAR) );
2053
2054     r = LookupAccountSidW( systemW, sid, accountW, &accountSizeW, domainW, &domainSizeW, name_use );
2055
2056     if (r) {
2057         if (accountW && *accountSize) {
2058             len = WideCharToMultiByte( CP_ACP, 0, accountW, -1, NULL, 0, NULL, NULL );
2059             WideCharToMultiByte( CP_ACP, 0, accountW, -1, account, len, NULL, NULL );
2060             *accountSize = len;
2061         } else
2062             *accountSize = accountSizeW + 1;
2063
2064         if (domainW && *domainSize) {
2065             len = WideCharToMultiByte( CP_ACP, 0, domainW, -1, NULL, 0, NULL, NULL );
2066             WideCharToMultiByte( CP_ACP, 0, domainW, -1, domain, len, NULL, NULL );
2067             *domainSize = len;
2068         } else
2069             *domainSize = domainSizeW + 1;
2070     }
2071
2072     HeapFree( GetProcessHeap(), 0, systemW );
2073     HeapFree( GetProcessHeap(), 0, accountW );
2074     HeapFree( GetProcessHeap(), 0, domainW );
2075
2076     return r;
2077 }
2078
2079 /******************************************************************************
2080  * LookupAccountSidW [ADVAPI32.@]
2081  *
2082  * PARAMS
2083  *   system      []
2084  *   sid         []
2085  *   account     []
2086  *   accountSize []
2087  *   domain      []
2088  *   domainSize  []
2089  *   name_use    []
2090  */
2091
2092 BOOL WINAPI
2093 LookupAccountSidW(
2094         IN LPCWSTR system,
2095         IN PSID sid,
2096         OUT LPWSTR account,
2097         IN OUT LPDWORD accountSize,
2098         OUT LPWSTR domain,
2099         IN OUT LPDWORD domainSize,
2100         OUT PSID_NAME_USE name_use )
2101 {
2102     unsigned int i, j;
2103     const WCHAR * ac = NULL;
2104     const WCHAR * dm = NULL;
2105     SID_NAME_USE use = 0;
2106     LPWSTR computer_name = NULL;
2107     LPWSTR account_name = NULL;
2108
2109     TRACE("(%s,sid=%s,%p,%p(%u),%p,%p(%u),%p)\n",
2110           debugstr_w(system),debugstr_sid(sid),
2111           account,accountSize,accountSize?*accountSize:0,
2112           domain,domainSize,domainSize?*domainSize:0,
2113           name_use);
2114
2115     if (!ADVAPI_IsLocalComputer(system)) {
2116         FIXME("Only local computer supported!\n");
2117         SetLastError(RPC_S_SERVER_UNAVAILABLE);
2118         return FALSE;
2119     }
2120
2121     /* check the well known SIDs first */
2122     for (i = 0; i <= 60; i++) {
2123         if (IsWellKnownSid(sid, i)) {
2124             for (j = 0; j < (sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0])); j++) {
2125                 if (ACCOUNT_SIDS[j].type == i) {
2126                     ac = ACCOUNT_SIDS[j].account;
2127                     dm = ACCOUNT_SIDS[j].domain;
2128                     use = ACCOUNT_SIDS[j].name_use;
2129                 }
2130             }
2131             break;
2132         }
2133     }
2134
2135     if (dm == NULL) {
2136         MAX_SID local;
2137
2138         /* check for the local computer next */
2139         if (ADVAPI_GetComputerSid(&local)) {
2140             DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
2141             BOOL result;
2142
2143             computer_name = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
2144             result = GetComputerNameW(computer_name,  &size);
2145
2146             if (result) {
2147                 if (EqualSid(sid, &local)) {
2148                     dm = computer_name;
2149                     ac = Blank;
2150                     use = 3;
2151                 } else {
2152                     local.SubAuthorityCount++;
2153
2154                     if (EqualPrefixSid(sid, &local)) {
2155                         dm = computer_name;
2156                         use = 1;
2157                         switch (((MAX_SID *)sid)->SubAuthority[4]) {
2158                         case DOMAIN_USER_RID_ADMIN:
2159                             ac = Administrator;
2160                             break;
2161                         case DOMAIN_USER_RID_GUEST:
2162                             ac = Guest;
2163                             break;
2164                         case DOMAIN_GROUP_RID_ADMINS:
2165                             ac = Domain_Admins;
2166                             break;
2167                         case DOMAIN_GROUP_RID_USERS:
2168                             ac = Domain_Users;
2169                             break;
2170                         case DOMAIN_GROUP_RID_GUESTS:
2171                             ac = Domain_Guests;
2172                             break;
2173                         case DOMAIN_GROUP_RID_COMPUTERS:
2174                             ac = Domain_Computers;
2175                             break;
2176                         case DOMAIN_GROUP_RID_CONTROLLERS:
2177                             ac = Domain_Controllers;
2178                             break;
2179                         case DOMAIN_GROUP_RID_CERT_ADMINS:
2180                             ac = Cert_Publishers;
2181                             break;
2182                         case DOMAIN_GROUP_RID_SCHEMA_ADMINS:
2183                             ac = Schema_Admins;
2184                             break;
2185                         case DOMAIN_GROUP_RID_ENTERPRISE_ADMINS:
2186                             ac = Enterprise_Admins;
2187                             break;
2188                         case DOMAIN_GROUP_RID_POLICY_ADMINS:
2189                             ac = Group_Policy_Creator_Owners;
2190                             break;
2191                         case DOMAIN_ALIAS_RID_RAS_SERVERS:
2192                             ac = RAS_and_IAS_Servers;
2193                             break;
2194                         case 1000:      /* first user account */
2195                             size = UNLEN + 1;
2196                             account_name = HeapAlloc(
2197                                 GetProcessHeap(), 0, size * sizeof(WCHAR));
2198                             if (GetUserNameW(account_name, &size))
2199                                 ac = account_name;
2200                             else
2201                                 dm = NULL;
2202
2203                             break;
2204                         default:
2205                             dm = NULL;
2206                             break;
2207                         }
2208                     }
2209                 }
2210             }
2211         }
2212     }
2213
2214     if (dm) {
2215         DWORD ac_len = lstrlenW(ac);
2216         DWORD dm_len = lstrlenW(dm);
2217         BOOL status = TRUE;
2218
2219         if (*accountSize > ac_len) {
2220             if (account)
2221                 lstrcpyW(account, ac);
2222         }
2223         if (*domainSize > dm_len) {
2224             if (domain)
2225                 lstrcpyW(domain, dm);
2226         }
2227         if (((*accountSize != 0) && (*accountSize < ac_len)) ||
2228             ((*domainSize != 0) && (*domainSize < dm_len))) {
2229             SetLastError(ERROR_INSUFFICIENT_BUFFER);
2230             status = FALSE;
2231         }
2232         if (*domainSize)
2233             *domainSize = dm_len;
2234         else
2235             *domainSize = dm_len + 1;
2236         if (*accountSize)
2237             *accountSize = ac_len;
2238         else
2239             *accountSize = ac_len + 1;
2240         *name_use = use;
2241         HeapFree(GetProcessHeap(), 0, account_name);
2242         HeapFree(GetProcessHeap(), 0, computer_name);
2243         return status;
2244     }
2245
2246     HeapFree(GetProcessHeap(), 0, account_name);
2247     HeapFree(GetProcessHeap(), 0, computer_name);
2248     SetLastError(ERROR_NONE_MAPPED);
2249     return FALSE;
2250 }
2251
2252 /******************************************************************************
2253  * SetFileSecurityA [ADVAPI32.@]
2254  *
2255  * See SetFileSecurityW.
2256  */
2257 BOOL WINAPI SetFileSecurityA( LPCSTR lpFileName,
2258                                 SECURITY_INFORMATION RequestedInformation,
2259                                 PSECURITY_DESCRIPTOR pSecurityDescriptor)
2260 {
2261     DWORD len;
2262     BOOL r;
2263     LPWSTR name = NULL;
2264
2265     if( lpFileName )
2266     {
2267         len = MultiByteToWideChar( CP_ACP, 0, lpFileName, -1, NULL, 0 );
2268         name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
2269         MultiByteToWideChar( CP_ACP, 0, lpFileName, -1, name, len );
2270     }
2271
2272     r = SetFileSecurityW( name, RequestedInformation, pSecurityDescriptor );
2273     HeapFree( GetProcessHeap(), 0, name );
2274
2275     return r;
2276 }
2277
2278 /******************************************************************************
2279  * SetFileSecurityW [ADVAPI32.@]
2280  *
2281  * Sets the security of a file or directory.
2282  *
2283  * PARAMS
2284  *   lpFileName           []
2285  *   RequestedInformation []
2286  *   pSecurityDescriptor  []
2287  *
2288  * RETURNS
2289  *  Success: TRUE.
2290  *  Failure: FALSE.
2291  */
2292 BOOL WINAPI
2293 SetFileSecurityW( LPCWSTR lpFileName,
2294                     SECURITY_INFORMATION RequestedInformation,
2295                     PSECURITY_DESCRIPTOR pSecurityDescriptor )
2296 {
2297     HANDLE file;
2298     DWORD access = 0;
2299     NTSTATUS status;
2300
2301     TRACE("(%s, 0x%x, %p)\n", debugstr_w(lpFileName), RequestedInformation,
2302           pSecurityDescriptor );
2303
2304     if (RequestedInformation & OWNER_SECURITY_INFORMATION ||
2305         RequestedInformation & GROUP_SECURITY_INFORMATION)
2306         access |= WRITE_OWNER;
2307     if (RequestedInformation & SACL_SECURITY_INFORMATION)
2308         access |= ACCESS_SYSTEM_SECURITY;
2309     if (RequestedInformation & DACL_SECURITY_INFORMATION)
2310         access |= WRITE_DAC;
2311
2312     file = CreateFileW( lpFileName, access, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
2313                         NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL );
2314     if (file == INVALID_HANDLE_VALUE)
2315         return FALSE;
2316
2317     status = NtSetSecurityObject( file, RequestedInformation, pSecurityDescriptor );
2318     CloseHandle( file );
2319     return set_ntstatus( status );
2320 }
2321
2322 /******************************************************************************
2323  * QueryWindows31FilesMigration [ADVAPI32.@]
2324  *
2325  * PARAMS
2326  *   x1 []
2327  */
2328 BOOL WINAPI
2329 QueryWindows31FilesMigration( DWORD x1 )
2330 {
2331         FIXME("(%d):stub\n",x1);
2332         return TRUE;
2333 }
2334
2335 /******************************************************************************
2336  * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@]
2337  *
2338  * PARAMS
2339  *   x1 []
2340  *   x2 []
2341  *   x3 []
2342  *   x4 []
2343  */
2344 BOOL WINAPI
2345 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3,
2346                                                DWORD x4 )
2347 {
2348         FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4);
2349         return TRUE;
2350 }
2351
2352 /******************************************************************************
2353  * NotifyBootConfigStatus [ADVAPI32.@]
2354  *
2355  * PARAMS
2356  *   x1 []
2357  */
2358 BOOL WINAPI
2359 NotifyBootConfigStatus( BOOL x1 )
2360 {
2361         FIXME("(0x%08d):stub\n",x1);
2362         return 1;
2363 }
2364
2365 /******************************************************************************
2366  * RevertToSelf [ADVAPI32.@]
2367  *
2368  * Ends the impersonation of a user.
2369  *
2370  * PARAMS
2371  *   void []
2372  *
2373  * RETURNS
2374  *  Success: TRUE.
2375  *  Failure: FALSE.
2376  */
2377 BOOL WINAPI
2378 RevertToSelf( void )
2379 {
2380     HANDLE Token = NULL;
2381     return set_ntstatus( NtSetInformationThread( GetCurrentThread(),
2382         ThreadImpersonationToken, &Token, sizeof(Token) ) );
2383 }
2384
2385 /******************************************************************************
2386  * ImpersonateSelf [ADVAPI32.@]
2387  *
2388  * Makes an impersonation token that represents the process user and assigns
2389  * to the current thread.
2390  *
2391  * PARAMS
2392  *  ImpersonationLevel [I] Level at which to impersonate.
2393  *
2394  * RETURNS
2395  *  Success: TRUE.
2396  *  Failure: FALSE.
2397  */
2398 BOOL WINAPI
2399 ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
2400 {
2401     return set_ntstatus( RtlImpersonateSelf( ImpersonationLevel ) );
2402 }
2403
2404 /******************************************************************************
2405  * ImpersonateLoggedOnUser [ADVAPI32.@]
2406  */
2407 BOOL WINAPI ImpersonateLoggedOnUser(HANDLE hToken)
2408 {
2409     DWORD size;
2410     NTSTATUS Status;
2411     HANDLE ImpersonationToken;
2412     TOKEN_TYPE Type;
2413     static BOOL warn = TRUE;
2414
2415     if (warn)
2416     {
2417         FIXME( "(%p)\n", hToken );
2418         warn = FALSE;
2419     }
2420     if (!GetTokenInformation( hToken, TokenType, &Type,
2421                               sizeof(TOKEN_TYPE), &size ))
2422         return FALSE;
2423
2424     if (Type == TokenPrimary)
2425     {
2426         OBJECT_ATTRIBUTES ObjectAttributes;
2427
2428         InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
2429
2430         Status = NtDuplicateToken( hToken,
2431                                    TOKEN_IMPERSONATE | TOKEN_QUERY,
2432                                    &ObjectAttributes,
2433                                    SecurityImpersonation,
2434                                    TokenImpersonation,
2435                                    &ImpersonationToken );
2436         if (Status != STATUS_SUCCESS)
2437         {
2438             ERR( "NtDuplicateToken failed with error 0x%08x\n", Status );
2439             SetLastError( RtlNtStatusToDosError( Status ) );
2440             return FALSE;
2441         }
2442     }
2443     else
2444         ImpersonationToken = hToken;
2445
2446     Status = NtSetInformationThread( GetCurrentThread(),
2447                                      ThreadImpersonationToken,
2448                                      &ImpersonationToken,
2449                                      sizeof(ImpersonationToken) );
2450
2451     if (Type == TokenPrimary)
2452         NtClose( ImpersonationToken );
2453
2454     if (Status != STATUS_SUCCESS)
2455     {
2456         ERR( "NtSetInformationThread failed with error 0x%08x\n", Status );
2457         SetLastError( RtlNtStatusToDosError( Status ) );
2458         return FALSE;
2459     }
2460
2461     return TRUE;
2462 }
2463
2464 /******************************************************************************
2465  * AccessCheck [ADVAPI32.@]
2466  */
2467 BOOL WINAPI
2468 AccessCheck(
2469         PSECURITY_DESCRIPTOR SecurityDescriptor,
2470         HANDLE ClientToken,
2471         DWORD DesiredAccess,
2472         PGENERIC_MAPPING GenericMapping,
2473         PPRIVILEGE_SET PrivilegeSet,
2474         LPDWORD PrivilegeSetLength,
2475         LPDWORD GrantedAccess,
2476         LPBOOL AccessStatus)
2477 {
2478     NTSTATUS access_status;
2479     BOOL ret = set_ntstatus( NtAccessCheck(SecurityDescriptor, ClientToken, DesiredAccess,
2480                                            GenericMapping, PrivilegeSet, PrivilegeSetLength,
2481                                            GrantedAccess, &access_status) );
2482     if (ret) *AccessStatus = set_ntstatus( access_status );
2483     return ret;
2484 }
2485
2486
2487 /******************************************************************************
2488  * AccessCheckByType [ADVAPI32.@]
2489  */
2490 BOOL WINAPI AccessCheckByType(
2491     PSECURITY_DESCRIPTOR pSecurityDescriptor, 
2492     PSID PrincipalSelfSid,
2493     HANDLE ClientToken, 
2494     DWORD DesiredAccess, 
2495     POBJECT_TYPE_LIST ObjectTypeList,
2496     DWORD ObjectTypeListLength,
2497     PGENERIC_MAPPING GenericMapping,
2498     PPRIVILEGE_SET PrivilegeSet,
2499     LPDWORD PrivilegeSetLength, 
2500     LPDWORD GrantedAccess,
2501     LPBOOL AccessStatus)
2502 {
2503         FIXME("stub\n");
2504
2505         *AccessStatus = TRUE;
2506
2507         return !*AccessStatus;
2508 }
2509
2510 /******************************************************************************
2511  * MapGenericMask [ADVAPI32.@]
2512  *
2513  * Maps generic access rights into specific access rights according to the
2514  * supplied mapping.
2515  *
2516  * PARAMS
2517  *  AccessMask     [I/O] Access rights.
2518  *  GenericMapping [I] The mapping between generic and specific rights.
2519  *
2520  * RETURNS
2521  *  Nothing.
2522  */
2523 VOID WINAPI MapGenericMask( PDWORD AccessMask, PGENERIC_MAPPING GenericMapping )
2524 {
2525     RtlMapGenericMask( AccessMask, GenericMapping );
2526 }
2527
2528 /*************************************************************************
2529  * SetKernelObjectSecurity [ADVAPI32.@]
2530  */
2531 BOOL WINAPI SetKernelObjectSecurity (
2532         IN HANDLE Handle,
2533         IN SECURITY_INFORMATION SecurityInformation,
2534         IN PSECURITY_DESCRIPTOR SecurityDescriptor )
2535 {
2536     return set_ntstatus (NtSetSecurityObject (Handle, SecurityInformation, SecurityDescriptor));
2537 }
2538
2539
2540 /******************************************************************************
2541  *  AddAuditAccessAce [ADVAPI32.@]
2542  */
2543 BOOL WINAPI AddAuditAccessAce(
2544     IN OUT PACL pAcl, 
2545     IN DWORD dwAceRevision, 
2546     IN DWORD dwAccessMask, 
2547     IN PSID pSid, 
2548     IN BOOL bAuditSuccess, 
2549     IN BOOL bAuditFailure) 
2550 {
2551     return set_ntstatus( RtlAddAuditAccessAce(pAcl, dwAceRevision, dwAccessMask, pSid, 
2552                                               bAuditSuccess, bAuditFailure) ); 
2553 }
2554
2555 /******************************************************************************
2556  *  AddAuditAccessAce [ADVAPI32.@]
2557  */
2558 BOOL WINAPI AddAuditAccessAceEx(
2559     IN OUT PACL pAcl,
2560     IN DWORD dwAceRevision,
2561     IN DWORD dwAceFlags,
2562     IN DWORD dwAccessMask,
2563     IN PSID pSid,
2564     IN BOOL bAuditSuccess,
2565     IN BOOL bAuditFailure)
2566 {
2567     return set_ntstatus( RtlAddAuditAccessAceEx(pAcl, dwAceRevision, dwAceFlags, dwAccessMask, pSid,
2568                                               bAuditSuccess, bAuditFailure) );
2569 }
2570
2571 /******************************************************************************
2572  * LookupAccountNameA [ADVAPI32.@]
2573  */
2574 BOOL WINAPI
2575 LookupAccountNameA(
2576         IN LPCSTR system,
2577         IN LPCSTR account,
2578         OUT PSID sid,
2579         OUT LPDWORD cbSid,
2580         LPSTR ReferencedDomainName,
2581         IN OUT LPDWORD cbReferencedDomainName,
2582         OUT PSID_NAME_USE name_use )
2583 {
2584     BOOL ret;
2585     UNICODE_STRING lpSystemW;
2586     UNICODE_STRING lpAccountW;
2587     LPWSTR lpReferencedDomainNameW = NULL;
2588
2589     RtlCreateUnicodeStringFromAsciiz(&lpSystemW, system);
2590     RtlCreateUnicodeStringFromAsciiz(&lpAccountW, account);
2591
2592     if (ReferencedDomainName)
2593         lpReferencedDomainNameW = HeapAlloc(GetProcessHeap(), 0, *cbReferencedDomainName * sizeof(WCHAR));
2594
2595     ret = LookupAccountNameW(lpSystemW.Buffer, lpAccountW.Buffer, sid, cbSid, lpReferencedDomainNameW,
2596         cbReferencedDomainName, name_use);
2597
2598     if (ret && lpReferencedDomainNameW)
2599     {
2600         WideCharToMultiByte(CP_ACP, 0, lpReferencedDomainNameW, -1,
2601             ReferencedDomainName, *cbReferencedDomainName+1, NULL, NULL);
2602     }
2603
2604     RtlFreeUnicodeString(&lpSystemW);
2605     RtlFreeUnicodeString(&lpAccountW);
2606     HeapFree(GetProcessHeap(), 0, lpReferencedDomainNameW);
2607
2608     return ret;
2609 }
2610
2611 /******************************************************************************
2612  * lookup_user_account_name
2613  */
2614 static BOOL lookup_user_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2615                                      LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2616 {
2617     char buffer[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
2618     DWORD len = sizeof(buffer);
2619     HANDLE token;
2620     BOOL ret;
2621     PSID pSid;
2622     static const WCHAR dm[] = {'D','O','M','A','I','N',0};
2623     DWORD nameLen;
2624     LPCWSTR domainName;
2625
2626     if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
2627     {
2628         if (GetLastError() != ERROR_NO_TOKEN) return FALSE;
2629         if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) return FALSE;
2630     }
2631
2632     ret = GetTokenInformation(token, TokenUser, buffer, len, &len);
2633     CloseHandle( token );
2634
2635     if (!ret) return FALSE;
2636
2637     pSid = ((TOKEN_USER *)buffer)->User.Sid;
2638
2639     if (Sid != NULL && (*cbSid >= GetLengthSid(pSid)))
2640        CopySid(*cbSid, Sid, pSid);
2641     if (*cbSid < GetLengthSid(pSid))
2642     {
2643        SetLastError(ERROR_INSUFFICIENT_BUFFER);
2644        ret = FALSE;
2645     }
2646     *cbSid = GetLengthSid(pSid);
2647
2648     domainName = dm;
2649     nameLen = strlenW(domainName);
2650
2651     if (*cchReferencedDomainName <= nameLen || !ret)
2652     {
2653         SetLastError(ERROR_INSUFFICIENT_BUFFER);
2654         nameLen += 1;
2655         ret = FALSE;
2656     }
2657     else if (ReferencedDomainName)
2658         strcpyW(ReferencedDomainName, domainName);
2659
2660     *cchReferencedDomainName = nameLen;
2661
2662     if (ret)
2663         *peUse = SidTypeUser;
2664
2665     return ret;
2666 }
2667
2668 /******************************************************************************
2669  * lookup_computer_account_name
2670  */
2671 static BOOL lookup_computer_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2672                                          LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2673 {
2674     MAX_SID local;
2675     BOOL ret;
2676     static const WCHAR dm[] = {'D','O','M','A','I','N',0};
2677     DWORD nameLen;
2678     LPCWSTR domainName;
2679
2680     if ((ret = ADVAPI_GetComputerSid(&local)))
2681     {
2682         if (Sid != NULL && (*cbSid >= GetLengthSid(&local)))
2683            CopySid(*cbSid, Sid, &local);
2684         if (*cbSid < GetLengthSid(&local))
2685         {
2686            SetLastError(ERROR_INSUFFICIENT_BUFFER);
2687            ret = FALSE;
2688         }
2689         *cbSid = GetLengthSid(&local);
2690     }
2691
2692     domainName = dm;
2693     nameLen = strlenW(domainName);
2694
2695     if (*cchReferencedDomainName <= nameLen || !ret)
2696     {
2697         SetLastError(ERROR_INSUFFICIENT_BUFFER);
2698         nameLen += 1;
2699         ret = FALSE;
2700     }
2701     else if (ReferencedDomainName)
2702         strcpyW(ReferencedDomainName, domainName);
2703
2704     *cchReferencedDomainName = nameLen;
2705
2706     if (ret)
2707         *peUse = SidTypeDomain;
2708
2709     return ret;
2710 }
2711
2712 static void split_domain_account( const LSA_UNICODE_STRING *str, LSA_UNICODE_STRING *account,
2713                                   LSA_UNICODE_STRING *domain )
2714 {
2715     WCHAR *p = str->Buffer + str->Length / sizeof(WCHAR) - 1;
2716
2717     while (p > str->Buffer && *p != '\\') p--;
2718
2719     if (*p == '\\')
2720     {
2721         domain->Buffer = str->Buffer;
2722         domain->Length = (p - str->Buffer) * sizeof(WCHAR);
2723
2724         account->Buffer = p + 1;
2725         account->Length = str->Length - ((p - str->Buffer + 1) * sizeof(WCHAR));
2726     }
2727     else
2728     {
2729         domain->Buffer = NULL;
2730         domain->Length = 0;
2731
2732         account->Buffer = str->Buffer;
2733         account->Length = str->Length;
2734     }
2735 }
2736
2737 static BOOL match_domain( ULONG idx, LSA_UNICODE_STRING *domain )
2738 {
2739     ULONG len = strlenW( ACCOUNT_SIDS[idx].domain );
2740
2741     if (len == domain->Length / sizeof(WCHAR) && !strncmpiW( domain->Buffer, ACCOUNT_SIDS[idx].domain, len ))
2742         return TRUE;
2743
2744     return FALSE;
2745 }
2746
2747 static BOOL match_account( ULONG idx, LSA_UNICODE_STRING *account )
2748 {
2749     ULONG len = strlenW( ACCOUNT_SIDS[idx].account );
2750
2751     if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].account, len ))
2752         return TRUE;
2753
2754     if (ACCOUNT_SIDS[idx].alias)
2755     {
2756         len = strlenW( ACCOUNT_SIDS[idx].alias );
2757         if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].alias, len ))
2758             return TRUE;
2759     }
2760     return FALSE;
2761 }
2762
2763 /*
2764  * Helper function for LookupAccountNameW
2765  */
2766 BOOL lookup_local_wellknown_name( LSA_UNICODE_STRING *account_and_domain,
2767                                   PSID Sid, LPDWORD cbSid,
2768                                   LPWSTR ReferencedDomainName,
2769                                   LPDWORD cchReferencedDomainName,
2770                                   PSID_NAME_USE peUse, BOOL *handled )
2771 {
2772     PSID pSid;
2773     LSA_UNICODE_STRING account, domain;
2774     BOOL ret = TRUE;
2775     ULONG i;
2776
2777     *handled = FALSE;
2778     split_domain_account( account_and_domain, &account, &domain );
2779
2780     for (i = 0; i < sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0]); i++)
2781     {
2782         /* check domain first */
2783         if (domain.Buffer && !match_domain( i, &domain )) continue;
2784
2785         if (match_account( i, &account ))
2786         {
2787             DWORD len, sidLen = SECURITY_MAX_SID_SIZE;
2788
2789             if (!(pSid = HeapAlloc( GetProcessHeap(), 0, sidLen ))) return FALSE;
2790
2791             if ((ret = CreateWellKnownSid( ACCOUNT_SIDS[i].type, NULL, pSid, &sidLen )))
2792             {
2793                 if (*cbSid < sidLen)
2794                 {
2795                     SetLastError(ERROR_INSUFFICIENT_BUFFER);
2796                     ret = FALSE;
2797                 }
2798                 else if (Sid)
2799                 {
2800                     CopySid(*cbSid, Sid, pSid);
2801                 }
2802                 *cbSid = sidLen;
2803             }
2804
2805             len = strlenW( ACCOUNT_SIDS[i].domain );
2806             if (*cchReferencedDomainName <= len || !ret)
2807             {
2808                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2809                 len++;
2810                 ret = FALSE;
2811             }
2812             else if (ReferencedDomainName)
2813             {
2814                 strcpyW( ReferencedDomainName, ACCOUNT_SIDS[i].domain );
2815             }
2816
2817             *cchReferencedDomainName = len;
2818             if (ret)
2819                 *peUse = ACCOUNT_SIDS[i].name_use;
2820
2821             HeapFree(GetProcessHeap(), 0, pSid);
2822             *handled = TRUE;
2823             return ret;
2824         }
2825     }
2826     return ret;
2827 }
2828
2829 BOOL lookup_local_user_name( LSA_UNICODE_STRING *account_and_domain,
2830                              PSID Sid, LPDWORD cbSid,
2831                              LPWSTR ReferencedDomainName,
2832                              LPDWORD cchReferencedDomainName,
2833                              PSID_NAME_USE peUse, BOOL *handled )
2834 {
2835     DWORD nameLen;
2836     LPWSTR userName = NULL;
2837     LSA_UNICODE_STRING account, domain;
2838     BOOL ret = TRUE;
2839
2840     *handled = FALSE;
2841     split_domain_account( account_and_domain, &account, &domain );
2842
2843     /* Let the current Unix user id masquerade as first Windows user account */
2844
2845     nameLen = UNLEN + 1;
2846     if (!(userName = HeapAlloc( GetProcessHeap(), 0, nameLen * sizeof(WCHAR) ))) return FALSE;
2847
2848     if (domain.Buffer)
2849     {
2850         /* check to make sure this account is on this computer */
2851         if (GetComputerNameW( userName, &nameLen ) &&
2852             (domain.Length / sizeof(WCHAR) != nameLen || strncmpW( domain.Buffer, userName, nameLen )))
2853         {
2854             SetLastError(ERROR_NONE_MAPPED);
2855             ret = FALSE;
2856         }
2857         nameLen = UNLEN + 1;
2858     }
2859
2860     if (GetUserNameW( userName, &nameLen ) &&
2861         account.Length / sizeof(WCHAR) == nameLen - 1 && !strncmpW( account.Buffer, userName, nameLen - 1 ))
2862     {
2863             ret = lookup_user_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2864             *handled = TRUE;
2865     }
2866     else
2867     {
2868         nameLen = UNLEN + 1;
2869         if (GetComputerNameW( userName, &nameLen ) &&
2870             account.Length / sizeof(WCHAR) == nameLen && !strncmpW( account.Buffer, userName , nameLen ))
2871         {
2872             ret = lookup_computer_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2873             *handled = TRUE;
2874         }
2875     }
2876
2877     HeapFree(GetProcessHeap(), 0, userName);
2878     return ret;
2879 }
2880
2881 /******************************************************************************
2882  * LookupAccountNameW [ADVAPI32.@]
2883  */
2884 BOOL WINAPI LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid,
2885                                 LPDWORD cbSid, LPWSTR ReferencedDomainName,
2886                                 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2887 {
2888     BOOL ret, handled;
2889     LSA_UNICODE_STRING account;
2890
2891     FIXME("%s %s %p %p %p %p %p - stub\n", debugstr_w(lpSystemName), debugstr_w(lpAccountName),
2892           Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse);
2893
2894     if (!ADVAPI_IsLocalComputer( lpSystemName ))
2895     {
2896         SetLastError( RPC_S_SERVER_UNAVAILABLE );
2897         return FALSE;
2898     }
2899
2900     if (!lpAccountName || !strcmpW( lpAccountName, Blank ))
2901     {
2902         lpAccountName = BUILTIN;
2903     }
2904
2905     RtlInitUnicodeString( &account, lpAccountName );
2906
2907     /* Check well known SIDs first */
2908     ret = lookup_local_wellknown_name( &account, Sid, cbSid, ReferencedDomainName,
2909                                        cchReferencedDomainName, peUse, &handled );
2910     if (handled)
2911         return ret;
2912
2913     /* Check user names */
2914     ret = lookup_local_user_name( &account, Sid, cbSid, ReferencedDomainName,
2915                                   cchReferencedDomainName, peUse, &handled);
2916     if (handled)
2917         return ret;
2918
2919     SetLastError( ERROR_NONE_MAPPED );
2920     return FALSE;
2921 }
2922
2923 /******************************************************************************
2924  * PrivilegeCheck [ADVAPI32.@]
2925  */
2926 BOOL WINAPI PrivilegeCheck( HANDLE ClientToken, PPRIVILEGE_SET RequiredPrivileges, LPBOOL pfResult)
2927 {
2928     BOOL ret;
2929     BOOLEAN Result;
2930
2931     TRACE("%p %p %p\n", ClientToken, RequiredPrivileges, pfResult);
2932
2933     ret = set_ntstatus (NtPrivilegeCheck (ClientToken, RequiredPrivileges, &Result));
2934     if (ret)
2935         *pfResult = Result;
2936     return ret;
2937 }
2938
2939 /******************************************************************************
2940  * AccessCheckAndAuditAlarmA [ADVAPI32.@]
2941  */
2942 BOOL WINAPI AccessCheckAndAuditAlarmA(LPCSTR Subsystem, LPVOID HandleId, LPSTR ObjectTypeName,
2943   LPSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
2944   PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
2945   LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
2946 {
2947         FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_a(Subsystem),
2948                 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName),
2949                 SecurityDescriptor, DesiredAccess, GenericMapping,
2950                 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
2951         return TRUE;
2952 }
2953
2954 /******************************************************************************
2955  * AccessCheckAndAuditAlarmW [ADVAPI32.@]
2956  */
2957 BOOL WINAPI AccessCheckAndAuditAlarmW(LPCWSTR Subsystem, LPVOID HandleId, LPWSTR ObjectTypeName,
2958   LPWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
2959   PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
2960   LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
2961 {
2962         FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_w(Subsystem),
2963                 HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName),
2964                 SecurityDescriptor, DesiredAccess, GenericMapping,
2965                 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
2966         return TRUE;
2967 }
2968
2969 BOOL WINAPI ObjectCloseAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
2970 {
2971     FIXME("stub (%s,%p,%x)\n", debugstr_a(SubsystemName), HandleId, GenerateOnClose);
2972
2973     return TRUE;
2974 }
2975
2976 BOOL WINAPI ObjectCloseAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
2977 {
2978     FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
2979
2980     return TRUE;
2981 }
2982
2983 BOOL WINAPI ObjectDeleteAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
2984 {
2985     FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
2986
2987     return TRUE;
2988 }
2989
2990 BOOL WINAPI ObjectOpenAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, LPSTR ObjectTypeName,
2991   LPSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
2992   DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
2993   LPBOOL GenerateOnClose)
2994 {
2995         FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_a(SubsystemName),
2996                 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName), pSecurityDescriptor,
2997         ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
2998         GenerateOnClose);
2999
3000     return TRUE;
3001 }
3002
3003 BOOL WINAPI ObjectOpenAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, LPWSTR ObjectTypeName,
3004   LPWSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
3005   DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
3006   LPBOOL GenerateOnClose)
3007 {
3008     FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_w(SubsystemName),
3009         HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName), pSecurityDescriptor,
3010         ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
3011         GenerateOnClose);
3012
3013     return TRUE;
3014 }
3015
3016 BOOL WINAPI ObjectPrivilegeAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
3017   DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3018 {
3019     FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_a(SubsystemName), HandleId, ClientToken,
3020           DesiredAccess, Privileges, AccessGranted);
3021
3022     return TRUE;
3023 }
3024
3025 BOOL WINAPI ObjectPrivilegeAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
3026   DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3027 {
3028     FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_w(SubsystemName), HandleId, ClientToken,
3029           DesiredAccess, Privileges, AccessGranted);
3030
3031     return TRUE;
3032 }
3033
3034 BOOL WINAPI PrivilegedServiceAuditAlarmA( LPCSTR SubsystemName, LPCSTR ServiceName, HANDLE ClientToken,
3035                                    PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3036 {
3037     FIXME("stub (%s,%s,%p,%p,%x)\n", debugstr_a(SubsystemName), debugstr_a(ServiceName),
3038           ClientToken, Privileges, AccessGranted);
3039
3040     return TRUE;
3041 }
3042
3043 BOOL WINAPI PrivilegedServiceAuditAlarmW( LPCWSTR SubsystemName, LPCWSTR ServiceName, HANDLE ClientToken,
3044                                    PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3045 {
3046     FIXME("stub %s,%s,%p,%p,%x)\n", debugstr_w(SubsystemName), debugstr_w(ServiceName),
3047           ClientToken, Privileges, AccessGranted);
3048
3049     return TRUE;
3050 }
3051
3052 /******************************************************************************
3053  * GetSecurityInfo [ADVAPI32.@]
3054  *
3055  * Retrieves a copy of the security descriptor associated with an object.
3056  *
3057  * PARAMS
3058  *  hObject              [I] A handle for the object.
3059  *  ObjectType           [I] The type of object.
3060  *  SecurityInfo         [I] A bitmask indicating what info to retrieve.
3061  *  ppsidOwner           [O] If non-null, receives a pointer to the owner SID.
3062  *  ppsidGroup           [O] If non-null, receives a pointer to the group SID.
3063  *  ppDacl               [O] If non-null, receives a pointer to the DACL.
3064  *  ppSacl               [O] If non-null, receives a pointer to the SACL.
3065  *  ppSecurityDescriptor [O] Receives a pointer to the security descriptor,
3066  *                           which must be freed with LocalFree.
3067  *
3068  * RETURNS
3069  *  ERROR_SUCCESS if all's well, and a WIN32 error code otherwise.
3070  */
3071 DWORD WINAPI GetSecurityInfo(
3072     HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3073     SECURITY_INFORMATION SecurityInfo, PSID *ppsidOwner,
3074     PSID *ppsidGroup, PACL *ppDacl, PACL *ppSacl,
3075     PSECURITY_DESCRIPTOR *ppSecurityDescriptor
3076 )
3077 {
3078     PSECURITY_DESCRIPTOR sd;
3079     NTSTATUS status;
3080     ULONG n1, n2;
3081     BOOL present, defaulted;
3082
3083     status = NtQuerySecurityObject(hObject, SecurityInfo, NULL, 0, &n1);
3084     if (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_SUCCESS)
3085         return RtlNtStatusToDosError(status);
3086
3087     sd = LocalAlloc(0, n1);
3088     if (!sd)
3089         return ERROR_NOT_ENOUGH_MEMORY;
3090
3091     status = NtQuerySecurityObject(hObject, SecurityInfo, sd, n1, &n2);
3092     if (status != STATUS_SUCCESS)
3093     {
3094         LocalFree(sd);
3095         return RtlNtStatusToDosError(status);
3096     }
3097
3098     if (ppsidOwner)
3099     {
3100         *ppsidOwner = NULL;
3101         GetSecurityDescriptorOwner(sd, ppsidOwner, &defaulted);
3102     }
3103     if (ppsidGroup)
3104     {
3105         *ppsidGroup = NULL;
3106         GetSecurityDescriptorGroup(sd, ppsidGroup, &defaulted);
3107     }
3108     if (ppDacl)
3109     {
3110         *ppDacl = NULL;
3111         GetSecurityDescriptorDacl(sd, &present, ppDacl, &defaulted);
3112     }
3113     if (ppSacl)
3114     {
3115         *ppSacl = NULL;
3116         GetSecurityDescriptorSacl(sd, &present, ppSacl, &defaulted);
3117     }
3118     if (ppSecurityDescriptor)
3119         *ppSecurityDescriptor = sd;
3120
3121     return ERROR_SUCCESS;
3122 }
3123
3124 /******************************************************************************
3125  * GetSecurityInfoExA [ADVAPI32.@]
3126  */
3127 DWORD WINAPI GetSecurityInfoExA(
3128         HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3129         SECURITY_INFORMATION SecurityInfo, LPCSTR lpProvider,
3130         LPCSTR lpProperty, PACTRL_ACCESSA *ppAccessList,
3131         PACTRL_AUDITA *ppAuditList, LPSTR *lppOwner, LPSTR *lppGroup
3132 )
3133 {
3134   FIXME("stub!\n");
3135   return ERROR_BAD_PROVIDER;
3136 }
3137
3138 /******************************************************************************
3139  * GetSecurityInfoExW [ADVAPI32.@]
3140  */
3141 DWORD WINAPI GetSecurityInfoExW(
3142         HANDLE hObject, SE_OBJECT_TYPE ObjectType, 
3143         SECURITY_INFORMATION SecurityInfo, LPCWSTR lpProvider,
3144         LPCWSTR lpProperty, PACTRL_ACCESSW *ppAccessList, 
3145         PACTRL_AUDITW *ppAuditList, LPWSTR *lppOwner, LPWSTR *lppGroup
3146 )
3147 {
3148   FIXME("stub!\n");
3149   return ERROR_BAD_PROVIDER; 
3150 }
3151
3152 /******************************************************************************
3153  * BuildExplicitAccessWithNameA [ADVAPI32.@]
3154  */
3155 VOID WINAPI BuildExplicitAccessWithNameA( PEXPLICIT_ACCESSA pExplicitAccess,
3156                                           LPSTR pTrusteeName, DWORD AccessPermissions,
3157                                           ACCESS_MODE AccessMode, DWORD Inheritance )
3158 {
3159     TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_a(pTrusteeName),
3160           AccessPermissions, AccessMode, Inheritance);
3161
3162     pExplicitAccess->grfAccessPermissions = AccessPermissions;
3163     pExplicitAccess->grfAccessMode = AccessMode;
3164     pExplicitAccess->grfInheritance = Inheritance;
3165
3166     pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3167     pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3168     pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3169     pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3170     pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3171 }
3172
3173 /******************************************************************************
3174  * BuildExplicitAccessWithNameW [ADVAPI32.@]
3175  */
3176 VOID WINAPI BuildExplicitAccessWithNameW( PEXPLICIT_ACCESSW pExplicitAccess,
3177                                           LPWSTR pTrusteeName, DWORD AccessPermissions,
3178                                           ACCESS_MODE AccessMode, DWORD Inheritance )
3179 {
3180     TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_w(pTrusteeName),
3181           AccessPermissions, AccessMode, Inheritance);
3182
3183     pExplicitAccess->grfAccessPermissions = AccessPermissions;
3184     pExplicitAccess->grfAccessMode = AccessMode;
3185     pExplicitAccess->grfInheritance = Inheritance;
3186
3187     pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3188     pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3189     pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3190     pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3191     pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3192 }
3193
3194 /******************************************************************************
3195  * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
3196  */
3197 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
3198                                              SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
3199                                              LPSTR InheritedObjectTypeName, LPSTR Name )
3200 {
3201     DWORD ObjectsPresent = 0;
3202
3203     TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3204           ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
3205
3206     /* Fill the OBJECTS_AND_NAME structure */
3207     pObjName->ObjectType = ObjectType;
3208     if (ObjectTypeName != NULL)
3209     {
3210         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3211     }
3212
3213     pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3214     if (InheritedObjectTypeName != NULL)
3215     {
3216         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3217     }
3218
3219     pObjName->ObjectsPresent = ObjectsPresent;
3220     pObjName->ptstrName = Name;
3221
3222     /* Fill the TRUSTEE structure */
3223     pTrustee->pMultipleTrustee = NULL;
3224     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3225     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3226     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3227     pTrustee->ptstrName = (LPSTR)pObjName;
3228 }
3229
3230 /******************************************************************************
3231  * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
3232  */
3233 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
3234                                              SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
3235                                              LPWSTR InheritedObjectTypeName, LPWSTR Name )
3236 {
3237     DWORD ObjectsPresent = 0;
3238
3239     TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3240           ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
3241
3242     /* Fill the OBJECTS_AND_NAME structure */
3243     pObjName->ObjectType = ObjectType;
3244     if (ObjectTypeName != NULL)
3245     {
3246         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3247     }
3248
3249     pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3250     if (InheritedObjectTypeName != NULL)
3251     {
3252         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3253     }
3254
3255     pObjName->ObjectsPresent = ObjectsPresent;
3256     pObjName->ptstrName = Name;
3257
3258     /* Fill the TRUSTEE structure */
3259     pTrustee->pMultipleTrustee = NULL;
3260     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3261     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3262     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3263     pTrustee->ptstrName = (LPWSTR)pObjName;
3264 }
3265
3266 /******************************************************************************
3267  * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
3268  */
3269 VOID WINAPI BuildTrusteeWithObjectsAndSidA( PTRUSTEEA pTrustee, POBJECTS_AND_SID pObjSid,
3270                                             GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3271 {
3272     DWORD ObjectsPresent = 0;
3273
3274     TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3275
3276     /* Fill the OBJECTS_AND_SID structure */
3277     if (pObjectGuid != NULL)
3278     {
3279         pObjSid->ObjectTypeGuid = *pObjectGuid;
3280         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3281     }
3282     else
3283     {
3284         ZeroMemory(&pObjSid->ObjectTypeGuid,
3285                    sizeof(GUID));
3286     }
3287
3288     if (pInheritedObjectGuid != NULL)
3289     {
3290         pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3291         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3292     }
3293     else
3294     {
3295         ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3296                    sizeof(GUID));
3297     }
3298
3299     pObjSid->ObjectsPresent = ObjectsPresent;
3300     pObjSid->pSid = pSid;
3301
3302     /* Fill the TRUSTEE structure */
3303     pTrustee->pMultipleTrustee = NULL;
3304     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3305     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3306     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3307     pTrustee->ptstrName = (LPSTR) pObjSid;
3308 }
3309
3310 /******************************************************************************
3311  * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
3312  */
3313 VOID WINAPI BuildTrusteeWithObjectsAndSidW( PTRUSTEEW pTrustee, POBJECTS_AND_SID pObjSid,
3314                                             GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3315 {
3316     DWORD ObjectsPresent = 0;
3317
3318     TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3319
3320     /* Fill the OBJECTS_AND_SID structure */
3321     if (pObjectGuid != NULL)
3322     {
3323         pObjSid->ObjectTypeGuid = *pObjectGuid;
3324         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3325     }
3326     else
3327     {
3328         ZeroMemory(&pObjSid->ObjectTypeGuid,
3329                    sizeof(GUID));
3330     }
3331
3332     if (pInheritedObjectGuid != NULL)
3333     {
3334         pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3335         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3336     }
3337     else
3338     {
3339         ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3340                    sizeof(GUID));
3341     }
3342
3343     pObjSid->ObjectsPresent = ObjectsPresent;
3344     pObjSid->pSid = pSid;
3345
3346     /* Fill the TRUSTEE structure */
3347     pTrustee->pMultipleTrustee = NULL;
3348     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3349     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3350     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3351     pTrustee->ptstrName = (LPWSTR) pObjSid;
3352 }
3353
3354 /******************************************************************************
3355  * BuildTrusteeWithSidA [ADVAPI32.@]
3356  */
3357 VOID WINAPI BuildTrusteeWithSidA(PTRUSTEEA pTrustee, PSID pSid)
3358 {
3359     TRACE("%p %p\n", pTrustee, pSid);
3360
3361     pTrustee->pMultipleTrustee = NULL;
3362     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3363     pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3364     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3365     pTrustee->ptstrName = pSid;
3366 }
3367
3368 /******************************************************************************
3369  * BuildTrusteeWithSidW [ADVAPI32.@]
3370  */
3371 VOID WINAPI BuildTrusteeWithSidW(PTRUSTEEW pTrustee, PSID pSid)
3372 {
3373     TRACE("%p %p\n", pTrustee, pSid);
3374
3375     pTrustee->pMultipleTrustee = NULL;
3376     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3377     pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3378     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3379     pTrustee->ptstrName = pSid;
3380 }
3381
3382 /******************************************************************************
3383  * BuildTrusteeWithNameA [ADVAPI32.@]
3384  */
3385 VOID WINAPI BuildTrusteeWithNameA(PTRUSTEEA pTrustee, LPSTR name)
3386 {
3387     TRACE("%p %s\n", pTrustee, debugstr_a(name) );
3388
3389     pTrustee->pMultipleTrustee = NULL;
3390     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3391     pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3392     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3393     pTrustee->ptstrName = name;
3394 }
3395
3396 /******************************************************************************
3397  * BuildTrusteeWithNameW [ADVAPI32.@]
3398  */
3399 VOID WINAPI BuildTrusteeWithNameW(PTRUSTEEW pTrustee, LPWSTR name)
3400 {
3401     TRACE("%p %s\n", pTrustee, debugstr_w(name) );
3402
3403     pTrustee->pMultipleTrustee = NULL;
3404     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3405     pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3406     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3407     pTrustee->ptstrName = name;
3408 }
3409
3410 /****************************************************************************** 
3411  * GetTrusteeFormA [ADVAPI32.@] 
3412  */ 
3413 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee) 
3414 {  
3415     TRACE("(%p)\n", pTrustee); 
3416   
3417     if (!pTrustee) 
3418         return TRUSTEE_BAD_FORM; 
3419   
3420     return pTrustee->TrusteeForm; 
3421 }  
3422   
3423 /****************************************************************************** 
3424  * GetTrusteeFormW [ADVAPI32.@] 
3425  */ 
3426 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee) 
3427 {  
3428     TRACE("(%p)\n", pTrustee); 
3429   
3430     if (!pTrustee) 
3431         return TRUSTEE_BAD_FORM; 
3432   
3433     return pTrustee->TrusteeForm; 
3434 }  
3435   
3436 /****************************************************************************** 
3437  * GetTrusteeNameA [ADVAPI32.@] 
3438  */ 
3439 LPSTR WINAPI GetTrusteeNameA(PTRUSTEEA pTrustee) 
3440 {  
3441     TRACE("(%p)\n", pTrustee); 
3442   
3443     if (!pTrustee) 
3444         return NULL; 
3445   
3446     return pTrustee->ptstrName; 
3447 }  
3448   
3449 /****************************************************************************** 
3450  * GetTrusteeNameW [ADVAPI32.@] 
3451  */ 
3452 LPWSTR WINAPI GetTrusteeNameW(PTRUSTEEW pTrustee) 
3453 {  
3454     TRACE("(%p)\n", pTrustee); 
3455   
3456     if (!pTrustee) 
3457         return NULL; 
3458   
3459     return pTrustee->ptstrName; 
3460 }  
3461   
3462 /****************************************************************************** 
3463  * GetTrusteeTypeA [ADVAPI32.@] 
3464  */ 
3465 TRUSTEE_TYPE WINAPI GetTrusteeTypeA(PTRUSTEEA pTrustee) 
3466 {  
3467     TRACE("(%p)\n", pTrustee); 
3468   
3469     if (!pTrustee) 
3470         return TRUSTEE_IS_UNKNOWN; 
3471   
3472     return pTrustee->TrusteeType; 
3473 }  
3474   
3475 /****************************************************************************** 
3476  * GetTrusteeTypeW [ADVAPI32.@] 
3477  */ 
3478 TRUSTEE_TYPE WINAPI GetTrusteeTypeW(PTRUSTEEW pTrustee) 
3479 {  
3480     TRACE("(%p)\n", pTrustee); 
3481   
3482     if (!pTrustee) 
3483         return TRUSTEE_IS_UNKNOWN; 
3484   
3485     return pTrustee->TrusteeType; 
3486
3487  
3488 BOOL WINAPI SetAclInformation( PACL pAcl, LPVOID pAclInformation,
3489                                DWORD nAclInformationLength,
3490                                ACL_INFORMATION_CLASS dwAclInformationClass )
3491 {
3492     FIXME("%p %p 0x%08x 0x%08x - stub\n", pAcl, pAclInformation,
3493           nAclInformationLength, dwAclInformationClass);
3494
3495     return TRUE;
3496 }
3497
3498 /******************************************************************************
3499  * SetEntriesInAclA [ADVAPI32.@]
3500  */
3501 DWORD WINAPI SetEntriesInAclA( ULONG count, PEXPLICIT_ACCESSA pEntries,
3502                                PACL OldAcl, PACL* NewAcl )
3503 {
3504     FIXME("%d %p %p %p\n",count,pEntries,OldAcl,NewAcl);
3505     if (NewAcl)
3506          *NewAcl = NULL;
3507     return ERROR_SUCCESS;
3508 }
3509
3510 /******************************************************************************
3511  * SetEntriesInAclW [ADVAPI32.@]
3512  */
3513 DWORD WINAPI SetEntriesInAclW( ULONG count, PEXPLICIT_ACCESSW pEntries,
3514                                PACL OldAcl, PACL* NewAcl )
3515 {
3516     ULONG i;
3517     PSID *ppsid;
3518     DWORD ret = ERROR_SUCCESS;
3519     DWORD acl_size = sizeof(ACL);
3520     NTSTATUS status;
3521
3522     TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
3523
3524     *NewAcl = NULL;
3525
3526     if (!count && !OldAcl)
3527         return ERROR_SUCCESS;
3528
3529     /* allocate array of maximum sized sids allowed */
3530     ppsid = HeapAlloc(GetProcessHeap(), 0, count * (sizeof(SID *) + FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES])));
3531     if (!ppsid)
3532         return ERROR_OUTOFMEMORY;
3533
3534     for (i = 0; i < count; i++)
3535     {
3536         ppsid[i] = (char *)&ppsid[count] + i * FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3537
3538         TRACE("[%d]:\n\tgrfAccessPermissions = 0x%x\n\tgrfAccessMode = %d\n\tgrfInheritance = 0x%x\n\t"
3539               "Trustee.pMultipleTrustee = %p\n\tMultipleTrusteeOperation = %d\n\tTrusteeForm = %d\n\t"
3540               "Trustee.TrusteeType = %d\n\tptstrName = %p\n", i,
3541               pEntries[i].grfAccessPermissions, pEntries[i].grfAccessMode, pEntries[i].grfInheritance,
3542               pEntries[i].Trustee.pMultipleTrustee, pEntries[i].Trustee.MultipleTrusteeOperation,
3543               pEntries[i].Trustee.TrusteeForm, pEntries[i].Trustee.TrusteeType,
3544               pEntries[i].Trustee.ptstrName);
3545
3546         if (pEntries[i].Trustee.MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE)
3547         {
3548             WARN("bad multiple trustee operation %d for trustee %d\n", pEntries[i].Trustee.MultipleTrusteeOperation, i);
3549             ret = ERROR_INVALID_PARAMETER;
3550             goto exit;
3551         }
3552
3553         switch (pEntries[i].Trustee.TrusteeForm)
3554         {
3555         case TRUSTEE_IS_SID:
3556             if (!CopySid(FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]),
3557                          ppsid[i], pEntries[i].Trustee.ptstrName))
3558             {
3559                 WARN("bad sid %p for trustee %d\n", pEntries[i].Trustee.ptstrName, i);
3560                 ret = ERROR_INVALID_PARAMETER;
3561                 goto exit;
3562             }
3563             break;
3564         case TRUSTEE_IS_NAME:
3565         {
3566             DWORD sid_size = FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3567             DWORD domain_size = MAX_COMPUTERNAME_LENGTH + 1;
3568             SID_NAME_USE use;
3569             if (!strcmpW( pEntries[i].Trustee.ptstrName, CURRENT_USER ))
3570             {
3571                 if (!lookup_user_account_name( ppsid[i], &sid_size, NULL, &domain_size, &use ))
3572                 {
3573                     ret = GetLastError();
3574                     goto exit;
3575                 }
3576             }
3577             else if (!LookupAccountNameW(NULL, pEntries[i].Trustee.ptstrName, ppsid[i], &sid_size, NULL, &domain_size, &use))
3578             {
3579                 WARN("bad user name %s for trustee %d\n", debugstr_w(pEntries[i].Trustee.ptstrName), i);
3580                 ret = ERROR_INVALID_PARAMETER;
3581                 goto exit;
3582             }
3583             break;
3584         }
3585         case TRUSTEE_IS_OBJECTS_AND_SID:
3586             FIXME("TRUSTEE_IS_OBJECTS_AND_SID unimplemented\n");
3587             break;
3588         case TRUSTEE_IS_OBJECTS_AND_NAME:
3589             FIXME("TRUSTEE_IS_OBJECTS_AND_NAME unimplemented\n");
3590             break;
3591         default:
3592             WARN("bad trustee form %d for trustee %d\n", pEntries[i].Trustee.TrusteeForm, i);
3593             ret = ERROR_INVALID_PARAMETER;
3594             goto exit;
3595         }
3596
3597         /* Note: we overestimate the ACL size here as a tradeoff between
3598          * instructions (simplicity) and memory */
3599         switch (pEntries[i].grfAccessMode)
3600         {
3601         case GRANT_ACCESS:
3602         case SET_ACCESS:
3603             acl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3604             break;
3605         case DENY_ACCESS:
3606             acl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3607             break;
3608         case SET_AUDIT_SUCCESS:
3609         case SET_AUDIT_FAILURE:
3610             acl_size += FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart) + GetLengthSid(ppsid[i]);
3611             break;
3612         case REVOKE_ACCESS:
3613             break;
3614         default:
3615             WARN("bad access mode %d for trustee %d\n", pEntries[i].grfAccessMode, i);
3616             ret = ERROR_INVALID_PARAMETER;
3617             goto exit;
3618         }
3619     }
3620
3621     if (OldAcl)
3622     {
3623         ACL_SIZE_INFORMATION size_info;
3624
3625         status = RtlQueryInformationAcl(OldAcl, &size_info, sizeof(size_info), AclSizeInformation);
3626         if (status != STATUS_SUCCESS)
3627         {
3628             ret = RtlNtStatusToDosError(status);
3629             goto exit;
3630         }
3631         acl_size += size_info.AclBytesInUse - sizeof(ACL);
3632     }
3633
3634     *NewAcl = LocalAlloc(0, acl_size);
3635     if (!*NewAcl)
3636     {
3637         ret = ERROR_OUTOFMEMORY;
3638         goto exit;
3639     }
3640
3641     status = RtlCreateAcl( *NewAcl, acl_size, ACL_REVISION );
3642     if (status != STATUS_SUCCESS)
3643     {
3644         ret = RtlNtStatusToDosError(status);
3645         goto exit;
3646     }
3647
3648     for (i = 0; i < count; i++)
3649     {
3650         switch (pEntries[i].grfAccessMode)
3651         {
3652         case GRANT_ACCESS:
3653             status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3654                                               pEntries[i].grfInheritance,
3655                                               pEntries[i].grfAccessPermissions,
3656                                               ppsid[i]);
3657             break;
3658         case SET_ACCESS:
3659         {
3660             ULONG j;
3661             BOOL add = TRUE;
3662             if (OldAcl)
3663             {
3664                 for (j = 0; ; j++)
3665                 {
3666                     const ACE_HEADER *existing_ace_header;
3667                     status = RtlGetAce(OldAcl, j, (LPVOID *)&existing_ace_header);
3668                     if (status != STATUS_SUCCESS)
3669                         break;
3670                     if (pEntries[i].grfAccessMode == SET_ACCESS &&
3671                         existing_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3672                         EqualSid(ppsid[i], &((ACCESS_ALLOWED_ACE *)existing_ace_header)->SidStart))
3673                     {
3674                         add = FALSE;
3675                         break;
3676                     }
3677                 }
3678             }
3679             if (add)
3680                 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3681                                                   pEntries[i].grfInheritance,
3682                                                   pEntries[i].grfAccessPermissions,
3683                                                   ppsid[i]);
3684             break;
3685         }
3686         case DENY_ACCESS:
3687             status = RtlAddAccessDeniedAceEx(*NewAcl, ACL_REVISION,
3688                                              pEntries[i].grfInheritance,
3689                                              pEntries[i].grfAccessPermissions,
3690                                              ppsid[i]);
3691             break;
3692         case SET_AUDIT_SUCCESS:
3693             status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3694                                             pEntries[i].grfInheritance,
3695                                             pEntries[i].grfAccessPermissions,
3696                                             ppsid[i], TRUE, FALSE);
3697             break;
3698         case SET_AUDIT_FAILURE:
3699             status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3700                                             pEntries[i].grfInheritance,
3701                                             pEntries[i].grfAccessPermissions,
3702                                             ppsid[i], FALSE, TRUE);
3703             break;
3704         default:
3705             FIXME("unhandled access mode %d\n", pEntries[i].grfAccessMode);
3706         }
3707     }
3708
3709     if (OldAcl)
3710     {
3711         for (i = 0; ; i++)
3712         {
3713             BOOL add = TRUE;
3714             ULONG j;
3715             const ACE_HEADER *old_ace_header;
3716             status = RtlGetAce(OldAcl, i, (LPVOID *)&old_ace_header);
3717             if (status != STATUS_SUCCESS) break;
3718             for (j = 0; j < count; j++)
3719             {
3720                 if (pEntries[j].grfAccessMode == SET_ACCESS &&
3721                     old_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3722                     EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3723                 {
3724                     status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION, pEntries[j].grfInheritance, pEntries[j].grfAccessPermissions, ppsid[j]);
3725                     add = FALSE;
3726                     break;
3727                 }
3728                 else if (pEntries[j].grfAccessMode == REVOKE_ACCESS)
3729                 {
3730                     switch (old_ace_header->AceType)
3731                     {
3732                     case ACCESS_ALLOWED_ACE_TYPE:
3733                         if (EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3734                             add = FALSE;
3735                         break;
3736                     case ACCESS_DENIED_ACE_TYPE:
3737                         if (EqualSid(ppsid[j], &((ACCESS_DENIED_ACE *)old_ace_header)->SidStart))
3738                             add = FALSE;
3739                         break;
3740                     case SYSTEM_AUDIT_ACE_TYPE:
3741                         if (EqualSid(ppsid[j], &((SYSTEM_AUDIT_ACE *)old_ace_header)->SidStart))
3742                             add = FALSE;
3743                         break;
3744                     case SYSTEM_ALARM_ACE_TYPE:
3745                         if (EqualSid(ppsid[j], &((SYSTEM_ALARM_ACE *)old_ace_header)->SidStart))
3746                             add = FALSE;
3747                         break;
3748                     default:
3749                         FIXME("unhandled ace type %d\n", old_ace_header->AceType);
3750                     }
3751
3752                     if (!add)
3753                         break;
3754                 }
3755             }
3756             if (add)
3757                 status = RtlAddAce(*NewAcl, ACL_REVISION, 1, (PACE_HEADER)old_ace_header, old_ace_header->AceSize);
3758             if (status != STATUS_SUCCESS)
3759             {
3760                 WARN("RtlAddAce failed with error 0x%08x\n", status);
3761                 ret = RtlNtStatusToDosError(status);
3762                 break;
3763             }
3764         }
3765     }
3766
3767 exit:
3768     HeapFree(GetProcessHeap(), 0, ppsid);
3769     return ret;
3770 }
3771
3772 /******************************************************************************
3773  * SetNamedSecurityInfoA [ADVAPI32.@]
3774  */
3775 DWORD WINAPI SetNamedSecurityInfoA(LPSTR pObjectName,
3776         SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
3777         PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
3778 {
3779     DWORD len;
3780     LPWSTR wstr = NULL;
3781     DWORD r;
3782
3783     TRACE("%s %d %d %p %p %p %p\n", debugstr_a(pObjectName), ObjectType,
3784            SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
3785
3786     if( pObjectName )
3787     {
3788         len = MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, NULL, 0 );
3789         wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR));
3790         MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, wstr, len );
3791     }
3792
3793     r = SetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, psidOwner,
3794                            psidGroup, pDacl, pSacl );
3795
3796     HeapFree( GetProcessHeap(), 0, wstr );
3797
3798     return r;
3799 }
3800
3801 BOOL WINAPI SetPrivateObjectSecurity( SECURITY_INFORMATION SecurityInformation,
3802     PSECURITY_DESCRIPTOR ModificationDescriptor,
3803     PSECURITY_DESCRIPTOR* ObjectsSecurityDescriptor,
3804     PGENERIC_MAPPING GenericMapping,
3805     HANDLE Token )
3806 {
3807     FIXME("0x%08x %p %p %p %p - stub\n", SecurityInformation, ModificationDescriptor,
3808           ObjectsSecurityDescriptor, GenericMapping, Token);
3809
3810     return TRUE;
3811 }
3812
3813 BOOL WINAPI AreAllAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
3814 {
3815     return RtlAreAllAccessesGranted( GrantedAccess, DesiredAccess );
3816 }
3817
3818 /******************************************************************************
3819  * AreAnyAccessesGranted [ADVAPI32.@]
3820  *
3821  * Determines whether or not any of a set of specified access permissions have
3822  * been granted or not.
3823  *
3824  * PARAMS
3825  *   GrantedAccess [I] The permissions that have been granted.
3826  *   DesiredAccess [I] The permissions that you want to have.
3827  *
3828  * RETURNS
3829  *   Nonzero if any of the permissions have been granted, zero if none of the
3830  *   permissions have been granted.
3831  */
3832
3833 BOOL WINAPI AreAnyAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
3834 {
3835     return RtlAreAnyAccessesGranted( GrantedAccess, DesiredAccess );
3836 }
3837
3838 /******************************************************************************
3839  * SetNamedSecurityInfoW [ADVAPI32.@]
3840  */
3841 DWORD WINAPI SetNamedSecurityInfoW(LPWSTR pObjectName,
3842         SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
3843         PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
3844 {
3845     FIXME("%s %d %d %p %p %p %p\n", debugstr_w(pObjectName), ObjectType,
3846            SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
3847     return ERROR_SUCCESS;
3848 }
3849
3850 /******************************************************************************
3851  * GetExplicitEntriesFromAclA [ADVAPI32.@]
3852  */
3853 DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntries,
3854         PEXPLICIT_ACCESSA* pListOfExplicitEntries)
3855 {
3856     FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
3857     return ERROR_CALL_NOT_IMPLEMENTED;
3858 }
3859
3860 /******************************************************************************
3861  * GetExplicitEntriesFromAclW [ADVAPI32.@]
3862  */
3863 DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG pcCountOfExplicitEntries,
3864         PEXPLICIT_ACCESSW* pListOfExplicitEntries)
3865 {
3866     FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
3867     return ERROR_CALL_NOT_IMPLEMENTED;
3868 }
3869
3870 /******************************************************************************
3871  * GetAuditedPermissionsFromAclA [ADVAPI32.@]
3872  */
3873 DWORD WINAPI GetAuditedPermissionsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
3874         PACCESS_MASK pFailedAuditRights)
3875 {
3876     FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
3877     return ERROR_CALL_NOT_IMPLEMENTED;
3878
3879 }
3880
3881 /******************************************************************************
3882  * GetAuditedPermissionsFromAclW [ADVAPI32.@]
3883  */
3884 DWORD WINAPI GetAuditedPermissionsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
3885         PACCESS_MASK pFailedAuditRights)
3886 {
3887     FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
3888     return ERROR_CALL_NOT_IMPLEMENTED;
3889
3890 }
3891
3892 /******************************************************************************
3893  * ParseAclStringFlags
3894  */
3895 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
3896 {
3897     DWORD flags = 0;
3898     LPCWSTR szAcl = *StringAcl;
3899
3900     while (*szAcl != '(')
3901     {
3902         if (*szAcl == 'P')
3903         {
3904             flags |= SE_DACL_PROTECTED;
3905         }
3906         else if (*szAcl == 'A')
3907         {
3908             szAcl++;
3909             if (*szAcl == 'R')
3910                 flags |= SE_DACL_AUTO_INHERIT_REQ;
3911             else if (*szAcl == 'I')
3912                 flags |= SE_DACL_AUTO_INHERITED;
3913         }
3914         szAcl++;
3915     }
3916
3917     *StringAcl = szAcl;
3918     return flags;
3919 }
3920
3921 /******************************************************************************
3922  * ParseAceStringType
3923  */
3924 static const ACEFLAG AceType[] =
3925 {
3926     { SDDL_ALARM,          SYSTEM_ALARM_ACE_TYPE },
3927     { SDDL_AUDIT,          SYSTEM_AUDIT_ACE_TYPE },
3928     { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
3929     { SDDL_ACCESS_DENIED,  ACCESS_DENIED_ACE_TYPE },
3930     /*
3931     { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
3932     { SDDL_OBJECT_ACCESS_DENIED,  ACCESS_DENIED_OBJECT_ACE_TYPE },
3933     { SDDL_OBJECT_ALARM,          SYSTEM_ALARM_OBJECT_ACE_TYPE },
3934     { SDDL_OBJECT_AUDIT,          SYSTEM_AUDIT_OBJECT_ACE_TYPE },
3935     */
3936     { NULL, 0 },
3937 };
3938
3939 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
3940 {
3941     UINT len = 0;
3942     LPCWSTR szAcl = *StringAcl;
3943     const ACEFLAG *lpaf = AceType;
3944
3945     while (*szAcl == ' ')
3946         szAcl++;
3947
3948     while (lpaf->wstr &&
3949         (len = strlenW(lpaf->wstr)) &&
3950         strncmpW(lpaf->wstr, szAcl, len))
3951         lpaf++;
3952
3953     if (!lpaf->wstr)
3954         return 0;
3955
3956     *StringAcl = szAcl + len;
3957     return lpaf->value;
3958 }
3959
3960
3961 /******************************************************************************
3962  * ParseAceStringFlags
3963  */
3964 static const ACEFLAG AceFlags[] =
3965 {
3966     { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
3967     { SDDL_AUDIT_FAILURE,     FAILED_ACCESS_ACE_FLAG },
3968     { SDDL_INHERITED,         INHERITED_ACE },
3969     { SDDL_INHERIT_ONLY,      INHERIT_ONLY_ACE },
3970     { SDDL_NO_PROPAGATE,      NO_PROPAGATE_INHERIT_ACE },
3971     { SDDL_OBJECT_INHERIT,    OBJECT_INHERIT_ACE },
3972     { SDDL_AUDIT_SUCCESS,     SUCCESSFUL_ACCESS_ACE_FLAG },
3973     { NULL, 0 },
3974 };
3975
3976 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
3977 {
3978     UINT len = 0;
3979     BYTE flags = 0;
3980     LPCWSTR szAcl = *StringAcl;
3981
3982     while (*szAcl == ' ')
3983         szAcl++;
3984
3985     while (*szAcl != ';')
3986     {
3987         const ACEFLAG *lpaf = AceFlags;
3988
3989         while (lpaf->wstr &&
3990                (len = strlenW(lpaf->wstr)) &&
3991                strncmpW(lpaf->wstr, szAcl, len))
3992             lpaf++;
3993
3994         if (!lpaf->wstr)
3995             return 0;
3996
3997         flags |= lpaf->value;
3998         szAcl += len;
3999     }
4000
4001     *StringAcl = szAcl;
4002     return flags;
4003 }
4004
4005
4006 /******************************************************************************
4007  * ParseAceStringRights
4008  */
4009 static const ACEFLAG AceRights[] =
4010 {
4011     { SDDL_GENERIC_ALL,     GENERIC_ALL },
4012     { SDDL_GENERIC_READ,    GENERIC_READ },
4013     { SDDL_GENERIC_WRITE,   GENERIC_WRITE },
4014     { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
4015
4016     { SDDL_READ_CONTROL,    READ_CONTROL },
4017     { SDDL_STANDARD_DELETE, DELETE },
4018     { SDDL_WRITE_DAC,       WRITE_DAC },
4019     { SDDL_WRITE_OWNER,     WRITE_OWNER },
4020
4021     { SDDL_READ_PROPERTY,   ADS_RIGHT_DS_READ_PROP},
4022     { SDDL_WRITE_PROPERTY,  ADS_RIGHT_DS_WRITE_PROP},
4023     { SDDL_CREATE_CHILD,    ADS_RIGHT_DS_CREATE_CHILD},
4024     { SDDL_DELETE_CHILD,    ADS_RIGHT_DS_DELETE_CHILD},
4025     { SDDL_LIST_CHILDREN,   ADS_RIGHT_ACTRL_DS_LIST},
4026     { SDDL_SELF_WRITE,      ADS_RIGHT_DS_SELF},
4027     { SDDL_LIST_OBJECT,     ADS_RIGHT_DS_LIST_OBJECT},
4028     { SDDL_DELETE_TREE,     ADS_RIGHT_DS_DELETE_TREE},
4029     { SDDL_CONTROL_ACCESS,  ADS_RIGHT_DS_CONTROL_ACCESS},
4030
4031     { SDDL_FILE_ALL,        FILE_ALL_ACCESS },
4032     { SDDL_FILE_READ,       FILE_GENERIC_READ },
4033     { SDDL_FILE_WRITE,      FILE_GENERIC_WRITE },
4034     { SDDL_FILE_EXECUTE,    FILE_GENERIC_EXECUTE },
4035
4036     { SDDL_KEY_ALL,         KEY_ALL_ACCESS },
4037     { SDDL_KEY_READ,        KEY_READ },
4038     { SDDL_KEY_WRITE,       KEY_WRITE },
4039     { SDDL_KEY_EXECUTE,     KEY_EXECUTE },
4040     { NULL, 0 },
4041 };
4042
4043 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
4044 {
4045     UINT len = 0;
4046     DWORD rights = 0;
4047     LPCWSTR szAcl = *StringAcl;
4048
4049     while (*szAcl == ' ')
4050         szAcl++;
4051
4052     if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
4053     {
4054         LPCWSTR p = szAcl;
4055
4056         while (*p && *p != ';')
4057             p++;
4058
4059         if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
4060         {
4061             rights = strtoulW(szAcl, NULL, 16);
4062             szAcl = p;
4063         }
4064         else
4065             WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
4066     }
4067     else
4068     {
4069         while (*szAcl != ';')
4070         {
4071             const ACEFLAG *lpaf = AceRights;
4072
4073             while (lpaf->wstr &&
4074                (len = strlenW(lpaf->wstr)) &&
4075                strncmpW(lpaf->wstr, szAcl, len))
4076             {
4077                lpaf++;
4078             }
4079
4080             if (!lpaf->wstr)
4081                 return 0;
4082
4083             rights |= lpaf->value;
4084             szAcl += len;
4085         }
4086     }
4087
4088     *StringAcl = szAcl;
4089     return rights;
4090 }
4091
4092
4093 /******************************************************************************
4094  * ParseStringAclToAcl
4095  * 
4096  * dacl_flags(string_ace1)(string_ace2)... (string_acen) 
4097  */
4098 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags, 
4099     PACL pAcl, LPDWORD cBytes)
4100 {
4101     DWORD val;
4102     DWORD sidlen;
4103     DWORD length = sizeof(ACL);
4104     DWORD acesize = 0;
4105     DWORD acecount = 0;
4106     PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
4107     DWORD error = ERROR_INVALID_ACL;
4108
4109     TRACE("%s\n", debugstr_w(StringAcl));
4110
4111     if (!StringAcl)
4112         return FALSE;
4113
4114     if (pAcl) /* pAce is only useful if we're setting values */
4115         pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
4116
4117     /* Parse ACL flags */
4118     *lpdwFlags = ParseAclStringFlags(&StringAcl);
4119
4120     /* Parse ACE */
4121     while (*StringAcl == '(')
4122     {
4123         StringAcl++;
4124
4125         /* Parse ACE type */
4126         val = ParseAceStringType(&StringAcl);
4127         if (pAce)
4128             pAce->Header.AceType = (BYTE) val;
4129         if (*StringAcl != ';')
4130         {
4131             error = RPC_S_INVALID_STRING_UUID;
4132             goto lerr;
4133         }
4134         StringAcl++;
4135
4136         /* Parse ACE flags */
4137         val = ParseAceStringFlags(&StringAcl);
4138         if (pAce)
4139             pAce->Header.AceFlags = (BYTE) val;
4140         if (*StringAcl != ';')
4141             goto lerr;
4142         StringAcl++;
4143
4144         /* Parse ACE rights */
4145         val = ParseAceStringRights(&StringAcl);
4146         if (pAce)
4147             pAce->Mask = val;
4148         if (*StringAcl != ';')
4149             goto lerr;
4150         StringAcl++;
4151
4152         /* Parse ACE object guid */
4153         while (*StringAcl == ' ')
4154             StringAcl++;
4155         if (*StringAcl != ';')
4156         {
4157             FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4158             goto lerr;
4159         }
4160         StringAcl++;
4161
4162         /* Parse ACE inherit object guid */
4163         while (*StringAcl == ' ')
4164             StringAcl++;
4165         if (*StringAcl != ';')
4166         {
4167             FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4168             goto lerr;
4169         }
4170         StringAcl++;
4171
4172         /* Parse ACE account sid */
4173         if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
4174         {
4175             while (*StringAcl && *StringAcl != ')')
4176                 StringAcl++;
4177         }
4178
4179         if (*StringAcl != ')')
4180             goto lerr;
4181         StringAcl++;
4182
4183         acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
4184         length += acesize;
4185         if (pAce)
4186         {
4187             pAce->Header.AceSize = acesize;
4188             pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
4189         }
4190         acecount++;
4191     }
4192
4193     *cBytes = length;
4194
4195     if (length > 0xffff)
4196     {
4197         ERR("ACL too large\n");
4198         goto lerr;
4199     }
4200
4201     if (pAcl)
4202     {
4203         pAcl->AclRevision = ACL_REVISION;
4204         pAcl->Sbz1 = 0;
4205         pAcl->AclSize = length;
4206         pAcl->AceCount = acecount++;
4207         pAcl->Sbz2 = 0;
4208     }
4209     return TRUE;
4210
4211 lerr:
4212     SetLastError(error);
4213     WARN("Invalid ACE string format\n");
4214     return FALSE;
4215 }
4216
4217
4218 /******************************************************************************
4219  * ParseStringSecurityDescriptorToSecurityDescriptor
4220  */
4221 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
4222     LPCWSTR StringSecurityDescriptor,
4223     SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
4224     LPDWORD cBytes)
4225 {
4226     BOOL bret = FALSE;
4227     WCHAR toktype;
4228     WCHAR tok[MAX_PATH];
4229     LPCWSTR lptoken;
4230     LPBYTE lpNext = NULL;
4231     DWORD len;
4232
4233     *cBytes = sizeof(SECURITY_DESCRIPTOR);
4234
4235     if (SecurityDescriptor)
4236         lpNext = (LPBYTE)(SecurityDescriptor + 1);
4237
4238     while (*StringSecurityDescriptor == ' ')
4239         StringSecurityDescriptor++;
4240
4241     while (*StringSecurityDescriptor)
4242     {
4243         toktype = *StringSecurityDescriptor;
4244
4245         /* Expect char identifier followed by ':' */
4246         StringSecurityDescriptor++;
4247         if (*StringSecurityDescriptor != ':')
4248         {
4249             SetLastError(ERROR_INVALID_PARAMETER);
4250             goto lend;
4251         }
4252         StringSecurityDescriptor++;
4253
4254         /* Extract token */
4255         lptoken = StringSecurityDescriptor;
4256         while (*lptoken && *lptoken != ':')
4257             lptoken++;
4258
4259         if (*lptoken)
4260             lptoken--;
4261
4262         len = lptoken - StringSecurityDescriptor;
4263         memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
4264         tok[len] = 0;
4265
4266         switch (toktype)
4267         {
4268             case 'O':
4269             {
4270                 DWORD bytes;
4271
4272                 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4273                     goto lend;
4274
4275                 if (SecurityDescriptor)
4276                 {
4277                     SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
4278                     lpNext += bytes; /* Advance to next token */
4279                 }
4280
4281                 *cBytes += bytes;
4282
4283                 break;
4284             }
4285
4286             case 'G':
4287             {
4288                 DWORD bytes;
4289
4290                 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4291                     goto lend;
4292
4293                 if (SecurityDescriptor)
4294                 {
4295                     SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
4296                     lpNext += bytes; /* Advance to next token */
4297                 }
4298
4299                 *cBytes += bytes;
4300
4301                 break;
4302             }
4303
4304             case 'D':
4305             {
4306                 DWORD flags;
4307                 DWORD bytes;
4308
4309                 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4310                     goto lend;
4311
4312                 if (SecurityDescriptor)
4313                 {
4314                     SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
4315                     SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
4316                     lpNext += bytes; /* Advance to next token */
4317                 }
4318
4319                 *cBytes += bytes;
4320
4321                 break;
4322             }
4323
4324             case 'S':
4325             {
4326                 DWORD flags;
4327                 DWORD bytes;
4328
4329                 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4330                     goto lend;
4331
4332                 if (SecurityDescriptor)
4333                 {
4334                     SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
4335                     SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
4336                     lpNext += bytes; /* Advance to next token */
4337                 }
4338
4339                 *cBytes += bytes;
4340
4341                 break;
4342             }
4343
4344             default:
4345                 FIXME("Unknown token\n");
4346                 SetLastError(ERROR_INVALID_PARAMETER);
4347                 goto lend;
4348         }
4349
4350         StringSecurityDescriptor = lptoken;
4351     }
4352
4353     bret = TRUE;
4354
4355 lend:
4356     return bret;
4357 }
4358
4359 /******************************************************************************
4360  * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
4361  */
4362 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
4363         LPCSTR StringSecurityDescriptor,
4364         DWORD StringSDRevision,
4365         PSECURITY_DESCRIPTOR* SecurityDescriptor,
4366         PULONG SecurityDescriptorSize)
4367 {
4368     UINT len;
4369     BOOL ret = FALSE;
4370     LPWSTR StringSecurityDescriptorW;
4371
4372     len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
4373     StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
4374
4375     if (StringSecurityDescriptorW)
4376     {
4377         MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
4378
4379         ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
4380                                                                    StringSDRevision, SecurityDescriptor,
4381                                                                    SecurityDescriptorSize);
4382         HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
4383     }
4384
4385     return ret;
4386 }
4387
4388 /******************************************************************************
4389  * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
4390  */
4391 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
4392         LPCWSTR StringSecurityDescriptor,
4393         DWORD StringSDRevision,
4394         PSECURITY_DESCRIPTOR* SecurityDescriptor,
4395         PULONG SecurityDescriptorSize)
4396 {
4397     DWORD cBytes;
4398     SECURITY_DESCRIPTOR* psd;
4399     BOOL bret = FALSE;
4400
4401     TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
4402
4403     if (GetVersion() & 0x80000000)
4404     {
4405         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4406         goto lend;
4407     }
4408     else if (!StringSecurityDescriptor || !SecurityDescriptor)
4409     {
4410         SetLastError(ERROR_INVALID_PARAMETER);
4411         goto lend;
4412     }
4413     else if (StringSDRevision != SID_REVISION)
4414     {
4415         SetLastError(ERROR_UNKNOWN_REVISION);
4416         goto lend;
4417     }
4418
4419     /* Compute security descriptor length */
4420     if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4421         NULL, &cBytes))
4422         goto lend;
4423
4424     psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
4425     if (!psd) goto lend;
4426
4427     psd->Revision = SID_REVISION;
4428     psd->Control |= SE_SELF_RELATIVE;
4429
4430     if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4431              (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
4432     {
4433         LocalFree(psd);
4434         goto lend;
4435     }
4436
4437     if (SecurityDescriptorSize)
4438         *SecurityDescriptorSize = cBytes;
4439
4440     bret = TRUE;
4441  
4442 lend:
4443     TRACE(" ret=%d\n", bret);
4444     return bret;
4445 }
4446
4447 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
4448 {
4449     if (cch == -1)
4450         cch = strlenW(string);
4451
4452     if (plen)
4453         *plen += cch;
4454
4455     if (pwptr)
4456     {
4457         memcpy(*pwptr, string, sizeof(WCHAR)*cch);
4458         *pwptr += cch;
4459     }
4460 }
4461
4462 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
4463 {
4464     DWORD i;
4465     WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
4466     WCHAR subauthfmt[] = { '-','%','u',0 };
4467     WCHAR buf[26];
4468     SID *pisid = psid;
4469
4470     if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
4471     {
4472         SetLastError(ERROR_INVALID_SID);
4473         return FALSE;
4474     }
4475
4476     if (pisid->IdentifierAuthority.Value[0] ||
4477      pisid->IdentifierAuthority.Value[1])
4478     {
4479         FIXME("not matching MS' bugs\n");
4480         SetLastError(ERROR_INVALID_SID);
4481         return FALSE;
4482     }
4483
4484     sprintfW( buf, fmt, pisid->Revision,
4485         MAKELONG(
4486             MAKEWORD( pisid->IdentifierAuthority.Value[5],
4487                     pisid->IdentifierAuthority.Value[4] ),
4488             MAKEWORD( pisid->IdentifierAuthority.Value[3],
4489                     pisid->IdentifierAuthority.Value[2] )
4490         ) );
4491     DumpString(buf, -1, pwptr, plen);
4492
4493     for( i=0; i<pisid->SubAuthorityCount; i++ )
4494     {
4495         sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
4496         DumpString(buf, -1, pwptr, plen);
4497     }
4498     return TRUE;
4499 }
4500
4501 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
4502 {
4503     size_t i;
4504     for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
4505     {
4506         if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
4507         {
4508             DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
4509             return TRUE;
4510         }
4511     }
4512
4513     return DumpSidNumeric(psid, pwptr, plen);
4514 }
4515
4516 static const LPCWSTR AceRightBitNames[32] = {
4517         SDDL_CREATE_CHILD,        /*  0 */
4518         SDDL_DELETE_CHILD,
4519         SDDL_LIST_CHILDREN,
4520         SDDL_SELF_WRITE,
4521         SDDL_READ_PROPERTY,       /*  4 */
4522         SDDL_WRITE_PROPERTY,
4523         SDDL_DELETE_TREE,
4524         SDDL_LIST_OBJECT,
4525         SDDL_CONTROL_ACCESS,      /*  8 */
4526         NULL,
4527         NULL,
4528         NULL,
4529         NULL,                     /* 12 */
4530         NULL,
4531         NULL,
4532         NULL,
4533         SDDL_STANDARD_DELETE,     /* 16 */
4534         SDDL_READ_CONTROL,
4535         SDDL_WRITE_DAC,
4536         SDDL_WRITE_OWNER,
4537         NULL,                     /* 20 */
4538         NULL,
4539         NULL,
4540         NULL,
4541         NULL,                     /* 24 */
4542         NULL,
4543         NULL,
4544         NULL,
4545         SDDL_GENERIC_ALL,         /* 28 */
4546         SDDL_GENERIC_EXECUTE,
4547         SDDL_GENERIC_WRITE,
4548         SDDL_GENERIC_READ
4549 };
4550
4551 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
4552 {
4553     static const WCHAR fmtW[] = {'0','x','%','x',0};
4554     WCHAR buf[15];
4555     size_t i;
4556
4557     if (mask == 0)
4558         return;
4559
4560     /* first check if the right have name */
4561     for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
4562     {
4563         if (AceRights[i].wstr == NULL)
4564             break;
4565         if (mask == AceRights[i].value)
4566         {
4567             DumpString(AceRights[i].wstr, -1, pwptr, plen);
4568             return;
4569         }
4570     }
4571
4572     /* then check if it can be built from bit names */
4573     for (i = 0; i < 32; i++)
4574     {
4575         if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
4576         {
4577             /* can't be built from bit names */
4578             sprintfW(buf, fmtW, mask);
4579             DumpString(buf, -1, pwptr, plen);
4580             return;
4581         }
4582     }
4583
4584     /* build from bit names */
4585     for (i = 0; i < 32; i++)
4586         if (mask & (1 << i))
4587             DumpString(AceRightBitNames[i], -1, pwptr, plen);
4588 }
4589
4590 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
4591 {
4592     ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
4593     static const WCHAR openbr = '(';
4594     static const WCHAR closebr = ')';
4595     static const WCHAR semicolon = ';';
4596
4597     if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
4598     {
4599         SetLastError(ERROR_INVALID_ACL);
4600         return FALSE;
4601     }
4602
4603     piace = pace;
4604     DumpString(&openbr, 1, pwptr, plen);
4605     switch (piace->Header.AceType)
4606     {
4607         case ACCESS_ALLOWED_ACE_TYPE:
4608             DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
4609             break;
4610         case ACCESS_DENIED_ACE_TYPE:
4611             DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
4612             break;
4613         case SYSTEM_AUDIT_ACE_TYPE:
4614             DumpString(SDDL_AUDIT, -1, pwptr, plen);
4615             break;
4616         case SYSTEM_ALARM_ACE_TYPE:
4617             DumpString(SDDL_ALARM, -1, pwptr, plen);
4618             break;
4619     }
4620     DumpString(&semicolon, 1, pwptr, plen);
4621
4622     if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
4623         DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
4624     if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
4625         DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
4626     if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
4627         DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
4628     if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
4629         DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
4630     if (piace->Header.AceFlags & INHERITED_ACE)
4631         DumpString(SDDL_INHERITED, -1, pwptr, plen);
4632     if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
4633         DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
4634     if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
4635         DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
4636     DumpString(&semicolon, 1, pwptr, plen);
4637     DumpRights(piace->Mask, pwptr, plen);
4638     DumpString(&semicolon, 1, pwptr, plen);
4639     /* objects not supported */
4640     DumpString(&semicolon, 1, pwptr, plen);
4641     /* objects not supported */
4642     DumpString(&semicolon, 1, pwptr, plen);
4643     if (!DumpSid(&piace->SidStart, pwptr, plen))
4644         return FALSE;
4645     DumpString(&closebr, 1, pwptr, plen);
4646     return TRUE;
4647 }
4648
4649 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
4650 {
4651     WORD count;
4652     int i;
4653
4654     if (protected)
4655         DumpString(SDDL_PROTECTED, -1, pwptr, plen);
4656     if (autoInheritReq)
4657         DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
4658     if (autoInherited)
4659         DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
4660
4661     if (pacl == NULL)
4662         return TRUE;
4663
4664     if (!IsValidAcl(pacl))
4665         return FALSE;
4666
4667     count = pacl->AceCount;
4668     for (i = 0; i < count; i++)
4669     {
4670         LPVOID ace;
4671         if (!GetAce(pacl, i, &ace))
4672             return FALSE;
4673         if (!DumpAce(ace, pwptr, plen))
4674             return FALSE;
4675     }
4676
4677     return TRUE;
4678 }
4679
4680 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4681 {
4682     static const WCHAR prefix[] = {'O',':',0};
4683     BOOL bDefaulted;
4684     PSID psid;
4685
4686     if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
4687         return FALSE;
4688
4689     if (psid == NULL)
4690         return TRUE;
4691
4692     DumpString(prefix, -1, pwptr, plen);
4693     if (!DumpSid(psid, pwptr, plen))
4694         return FALSE;
4695     return TRUE;
4696 }
4697
4698 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4699 {
4700     static const WCHAR prefix[] = {'G',':',0};
4701     BOOL bDefaulted;
4702     PSID psid;
4703
4704     if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
4705         return FALSE;
4706
4707     if (psid == NULL)
4708         return TRUE;
4709
4710     DumpString(prefix, -1, pwptr, plen);
4711     if (!DumpSid(psid, pwptr, plen))
4712         return FALSE;
4713     return TRUE;
4714 }
4715
4716 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4717 {
4718     static const WCHAR dacl[] = {'D',':',0};
4719     SECURITY_DESCRIPTOR_CONTROL control;
4720     BOOL present, defaulted;
4721     DWORD revision;
4722     PACL pacl;
4723
4724     if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
4725         return FALSE;
4726
4727     if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
4728         return FALSE;
4729
4730     if (!present)
4731         return TRUE;
4732
4733     DumpString(dacl, 2, pwptr, plen);
4734     if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
4735         return FALSE;
4736     return TRUE;
4737 }
4738
4739 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4740 {
4741     static const WCHAR sacl[] = {'S',':',0};
4742     SECURITY_DESCRIPTOR_CONTROL control;
4743     BOOL present, defaulted;
4744     DWORD revision;
4745     PACL pacl;
4746
4747     if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
4748         return FALSE;
4749
4750     if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
4751         return FALSE;
4752
4753     if (!present)
4754         return TRUE;
4755
4756     DumpString(sacl, 2, pwptr, plen);
4757     if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
4758         return FALSE;
4759     return TRUE;
4760 }
4761
4762 /******************************************************************************
4763  * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
4764  */
4765 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen)
4766 {
4767     ULONG len;
4768     WCHAR *wptr, *wstr;
4769
4770     if (SDRevision != SDDL_REVISION_1)
4771     {
4772         ERR("Pogram requested unknown SDDL revision %d\n", SDRevision);
4773         SetLastError(ERROR_UNKNOWN_REVISION);
4774         return FALSE;
4775     }
4776
4777     len = 0;
4778     if (RequestedInformation & OWNER_SECURITY_INFORMATION)
4779         if (!DumpOwner(SecurityDescriptor, NULL, &len))
4780             return FALSE;
4781     if (RequestedInformation & GROUP_SECURITY_INFORMATION)
4782         if (!DumpGroup(SecurityDescriptor, NULL, &len))
4783             return FALSE;
4784     if (RequestedInformation & DACL_SECURITY_INFORMATION)
4785         if (!DumpDacl(SecurityDescriptor, NULL, &len))
4786             return FALSE;
4787     if (RequestedInformation & SACL_SECURITY_INFORMATION)
4788         if (!DumpSacl(SecurityDescriptor, NULL, &len))
4789             return FALSE;
4790
4791     wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
4792     if (RequestedInformation & OWNER_SECURITY_INFORMATION)
4793         if (!DumpOwner(SecurityDescriptor, &wptr, NULL))
4794             return FALSE;
4795     if (RequestedInformation & GROUP_SECURITY_INFORMATION)
4796         if (!DumpGroup(SecurityDescriptor, &wptr, NULL))
4797             return FALSE;
4798     if (RequestedInformation & DACL_SECURITY_INFORMATION)
4799         if (!DumpDacl(SecurityDescriptor, &wptr, NULL))
4800             return FALSE;
4801     if (RequestedInformation & SACL_SECURITY_INFORMATION)
4802         if (!DumpSacl(SecurityDescriptor, &wptr, NULL))
4803             return FALSE;
4804     *wptr = 0;
4805
4806     TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
4807     *OutputString = wstr;
4808     if (OutputLen)
4809         *OutputLen = strlenW(*OutputString)+1;
4810     return TRUE;
4811 }
4812
4813 /******************************************************************************
4814  * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
4815  */
4816 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen)
4817 {
4818     LPWSTR wstr;
4819     ULONG len;
4820     if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
4821     {
4822         int lenA;
4823
4824         lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
4825         *OutputString = HeapAlloc(GetProcessHeap(), 0, lenA);
4826         WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
4827         LocalFree(wstr);
4828
4829         if (OutputLen != NULL)
4830             *OutputLen = lenA;
4831         return TRUE;
4832     }
4833     else
4834     {
4835         *OutputString = NULL;
4836         if (OutputLen)
4837             *OutputLen = 0;
4838         return FALSE;
4839     }
4840 }
4841
4842 /******************************************************************************
4843  * ConvertStringSidToSidW [ADVAPI32.@]
4844  */
4845 BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid)
4846 {
4847     BOOL bret = FALSE;
4848     DWORD cBytes;
4849
4850     TRACE("%s, %p\n", debugstr_w(StringSid), Sid);
4851     if (GetVersion() & 0x80000000)
4852         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4853     else if (!StringSid || !Sid)
4854         SetLastError(ERROR_INVALID_PARAMETER);
4855     else if (ParseStringSidToSid(StringSid, NULL, &cBytes))
4856     {
4857         PSID pSid = *Sid = LocalAlloc(0, cBytes);
4858
4859         bret = ParseStringSidToSid(StringSid, pSid, &cBytes);
4860         if (!bret)
4861             LocalFree(*Sid); 
4862     }
4863     return bret;
4864 }
4865
4866 /******************************************************************************
4867  * ConvertStringSidToSidA [ADVAPI32.@]
4868  */
4869 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
4870 {
4871     BOOL bret = FALSE;
4872
4873     TRACE("%s, %p\n", debugstr_a(StringSid), Sid);
4874     if (GetVersion() & 0x80000000)
4875         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4876     else if (!StringSid || !Sid)
4877         SetLastError(ERROR_INVALID_PARAMETER);
4878     else
4879     {
4880         UINT len = MultiByteToWideChar(CP_ACP, 0, StringSid, -1, NULL, 0);
4881         LPWSTR wStringSid = HeapAlloc(GetProcessHeap(), 0,
4882          len * sizeof(WCHAR));
4883
4884         MultiByteToWideChar(CP_ACP, 0, StringSid, -1, wStringSid, len);
4885         bret = ConvertStringSidToSidW(wStringSid, Sid);
4886         HeapFree(GetProcessHeap(), 0, wStringSid);
4887     }
4888     return bret;
4889 }
4890
4891 /******************************************************************************
4892  * ConvertSidToStringSidW [ADVAPI32.@]
4893  *
4894  *  format of SID string is:
4895  *    S-<count>-<auth>-<subauth1>-<subauth2>-<subauth3>...
4896  *  where
4897  *    <rev> is the revision of the SID encoded as decimal
4898  *    <auth> is the identifier authority encoded as hex
4899  *    <subauthN> is the subauthority id encoded as decimal
4900  */
4901 BOOL WINAPI ConvertSidToStringSidW( PSID pSid, LPWSTR *pstr )
4902 {
4903     DWORD len = 0;
4904     LPWSTR wstr, wptr;
4905
4906     TRACE("%p %p\n", pSid, pstr );
4907
4908     len = 0;
4909     if (!DumpSidNumeric(pSid, NULL, &len))
4910         return FALSE;
4911     wstr = wptr = LocalAlloc(0, (len+1) * sizeof(WCHAR));
4912     DumpSidNumeric(pSid, &wptr, NULL);
4913     *wptr = 0;
4914
4915     *pstr = wstr;
4916     return TRUE;
4917 }
4918
4919 /******************************************************************************
4920  * ConvertSidToStringSidA [ADVAPI32.@]
4921  */
4922 BOOL WINAPI ConvertSidToStringSidA(PSID pSid, LPSTR *pstr)
4923 {
4924     LPWSTR wstr = NULL;
4925     LPSTR str;
4926     UINT len;
4927
4928     TRACE("%p %p\n", pSid, pstr );
4929
4930     if( !ConvertSidToStringSidW( pSid, &wstr ) )
4931         return FALSE;
4932
4933     len = WideCharToMultiByte( CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL );
4934     str = LocalAlloc( 0, len );
4935     WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, len, NULL, NULL );
4936     LocalFree( wstr );
4937
4938     *pstr = str;
4939
4940     return TRUE;
4941 }
4942
4943 BOOL WINAPI ConvertToAutoInheritPrivateObjectSecurity(
4944         PSECURITY_DESCRIPTOR pdesc,
4945         PSECURITY_DESCRIPTOR cdesc,
4946         PSECURITY_DESCRIPTOR* ndesc,
4947         GUID* objtype,
4948         BOOL isdir,
4949         PGENERIC_MAPPING genmap )
4950 {
4951     FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
4952
4953     return FALSE;
4954 }
4955
4956 BOOL WINAPI CreatePrivateObjectSecurity(
4957         PSECURITY_DESCRIPTOR ParentDescriptor,
4958         PSECURITY_DESCRIPTOR CreatorDescriptor,
4959         PSECURITY_DESCRIPTOR* NewDescriptor,
4960         BOOL IsDirectoryObject,
4961         HANDLE Token,
4962         PGENERIC_MAPPING GenericMapping )
4963 {
4964     FIXME("%p %p %p %d %p %p - stub\n", ParentDescriptor, CreatorDescriptor,
4965           NewDescriptor, IsDirectoryObject, Token, GenericMapping);
4966
4967     return FALSE;
4968 }
4969
4970 BOOL WINAPI DestroyPrivateObjectSecurity( PSECURITY_DESCRIPTOR* ObjectDescriptor )
4971 {
4972     FIXME("%p - stub\n", ObjectDescriptor);
4973
4974     return TRUE;
4975 }
4976
4977 BOOL WINAPI CreateProcessAsUserA(
4978         HANDLE hToken,
4979         LPCSTR lpApplicationName,
4980         LPSTR lpCommandLine,
4981         LPSECURITY_ATTRIBUTES lpProcessAttributes,
4982         LPSECURITY_ATTRIBUTES lpThreadAttributes,
4983         BOOL bInheritHandles,
4984         DWORD dwCreationFlags,
4985         LPVOID lpEnvironment,
4986         LPCSTR lpCurrentDirectory,
4987         LPSTARTUPINFOA lpStartupInfo,
4988         LPPROCESS_INFORMATION lpProcessInformation )
4989 {
4990     FIXME("%p %s %s %p %p %d 0x%08x %p %s %p %p - stub\n", hToken, debugstr_a(lpApplicationName),
4991           debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
4992           dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
4993
4994     return FALSE;
4995 }
4996
4997 BOOL WINAPI CreateProcessAsUserW(
4998         HANDLE hToken,
4999         LPCWSTR lpApplicationName,
5000         LPWSTR lpCommandLine,
5001         LPSECURITY_ATTRIBUTES lpProcessAttributes,
5002         LPSECURITY_ATTRIBUTES lpThreadAttributes,
5003         BOOL bInheritHandles,
5004         DWORD dwCreationFlags,
5005         LPVOID lpEnvironment,
5006         LPCWSTR lpCurrentDirectory,
5007         LPSTARTUPINFOW lpStartupInfo,
5008         LPPROCESS_INFORMATION lpProcessInformation )
5009 {
5010     FIXME("%p %s %s %p %p %d 0x%08x %p %s %p %p - semi- stub\n", hToken, 
5011           debugstr_w(lpApplicationName), debugstr_w(lpCommandLine), lpProcessAttributes,
5012           lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, 
5013           debugstr_w(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
5014
5015     /* We should create the process with a suspended main thread */
5016     if (!CreateProcessW (lpApplicationName,
5017                          lpCommandLine,
5018                          lpProcessAttributes,
5019                          lpThreadAttributes,
5020                          bInheritHandles,
5021                          dwCreationFlags, /* CREATE_SUSPENDED */
5022                          lpEnvironment,
5023                          lpCurrentDirectory,
5024                          lpStartupInfo,
5025                          lpProcessInformation))
5026     {
5027       return FALSE;
5028     }
5029
5030     return TRUE;
5031 }
5032
5033 /******************************************************************************
5034  * CreateProcessWithLogonW
5035  */
5036 BOOL WINAPI CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags,
5037     LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment,
5038     LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
5039 {
5040     FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
5041     debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
5042     debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
5043     lpStartupInfo, lpProcessInformation);
5044
5045     return FALSE;
5046 }
5047
5048 /******************************************************************************
5049  * DuplicateTokenEx [ADVAPI32.@]
5050  */
5051 BOOL WINAPI DuplicateTokenEx(
5052         HANDLE ExistingTokenHandle, DWORD dwDesiredAccess,
5053         LPSECURITY_ATTRIBUTES lpTokenAttributes,
5054         SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
5055         TOKEN_TYPE TokenType,
5056         PHANDLE DuplicateTokenHandle )
5057 {
5058     OBJECT_ATTRIBUTES ObjectAttributes;
5059
5060     TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
5061           ImpersonationLevel, TokenType, DuplicateTokenHandle);
5062
5063     InitializeObjectAttributes(
5064         &ObjectAttributes,
5065         NULL,
5066         (lpTokenAttributes && lpTokenAttributes->bInheritHandle) ? OBJ_INHERIT : 0,
5067         NULL,
5068         lpTokenAttributes ? lpTokenAttributes->lpSecurityDescriptor : NULL );
5069
5070     return set_ntstatus( NtDuplicateToken( ExistingTokenHandle,
5071                                            dwDesiredAccess,
5072                                            &ObjectAttributes,
5073                                            ImpersonationLevel,
5074                                            TokenType,
5075                                            DuplicateTokenHandle ) );
5076 }
5077
5078 BOOL WINAPI DuplicateToken(
5079         HANDLE ExistingTokenHandle,
5080         SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
5081         PHANDLE DuplicateTokenHandle )
5082 {
5083     return DuplicateTokenEx( ExistingTokenHandle, TOKEN_IMPERSONATE | TOKEN_QUERY,
5084                              NULL, ImpersonationLevel, TokenImpersonation,
5085                              DuplicateTokenHandle );
5086 }
5087
5088 /******************************************************************************
5089  * ComputeStringSidSize
5090  */
5091 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
5092 {
5093     if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
5094     {
5095         int ctok = 0;
5096         while (*StringSid)
5097         {
5098             if (*StringSid == '-')
5099                 ctok++;
5100             StringSid++;
5101         }
5102
5103         if (ctok >= 3)
5104             return GetSidLengthRequired(ctok - 2);
5105     }
5106     else /* String constant format  - Only available in winxp and above */
5107     {
5108         unsigned int i;
5109
5110         for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5111             if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5112                 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
5113     }
5114
5115     return GetSidLengthRequired(0);
5116 }
5117
5118 /******************************************************************************
5119  * ParseStringSidToSid
5120  */
5121 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
5122 {
5123     BOOL bret = FALSE;
5124     SID* pisid=pSid;
5125
5126     TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
5127     if (!StringSid)
5128     {
5129         SetLastError(ERROR_INVALID_PARAMETER);
5130         TRACE("StringSid is NULL, returning FALSE\n");
5131         return FALSE;
5132     }
5133
5134     while (*StringSid == ' ')
5135         StringSid++;
5136
5137     *cBytes = ComputeStringSidSize(StringSid);
5138     if (!pisid) /* Simply compute the size */
5139     {
5140         TRACE("only size requested, returning TRUE\n");
5141         return TRUE;
5142     }
5143
5144     if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
5145     {
5146         DWORD i = 0, identAuth;
5147         DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
5148
5149         StringSid += 2; /* Advance to Revision */
5150         pisid->Revision = atoiW(StringSid);
5151
5152         if (pisid->Revision != SDDL_REVISION)
5153         {
5154             TRACE("Revision %d is unknown\n", pisid->Revision);
5155             goto lend; /* ERROR_INVALID_SID */
5156         }
5157         if (csubauth == 0)
5158         {
5159             TRACE("SubAuthorityCount is 0\n");
5160             goto lend; /* ERROR_INVALID_SID */
5161         }
5162
5163         pisid->SubAuthorityCount = csubauth;
5164
5165         /* Advance to identifier authority */
5166         while (*StringSid && *StringSid != '-')
5167             StringSid++;
5168         if (*StringSid == '-')
5169             StringSid++;
5170
5171         /* MS' implementation can't handle values greater than 2^32 - 1, so
5172          * we don't either; assume most significant bytes are always 0
5173          */
5174         pisid->IdentifierAuthority.Value[0] = 0;
5175         pisid->IdentifierAuthority.Value[1] = 0;
5176         identAuth = atoiW(StringSid);
5177         pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
5178         pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
5179         pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
5180         pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
5181
5182         /* Advance to first sub authority */
5183         while (*StringSid && *StringSid != '-')
5184             StringSid++;
5185         if (*StringSid == '-')
5186             StringSid++;
5187
5188         while (*StringSid)
5189         {
5190             pisid->SubAuthority[i++] = atoiW(StringSid);
5191
5192             while (*StringSid && *StringSid != '-')
5193                 StringSid++;
5194             if (*StringSid == '-')
5195                 StringSid++;
5196         }
5197
5198         if (i != pisid->SubAuthorityCount)
5199             goto lend; /* ERROR_INVALID_SID */
5200
5201         bret = TRUE;
5202     }
5203     else /* String constant format  - Only available in winxp and above */
5204     {
5205         unsigned int i;
5206         pisid->Revision = SDDL_REVISION;
5207
5208         for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5209             if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5210             {
5211                 DWORD j;
5212                 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
5213                 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
5214                 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
5215                     pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
5216                 bret = TRUE;
5217             }
5218
5219         if (!bret)
5220             FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
5221     }
5222
5223 lend:
5224     if (!bret)
5225         SetLastError(ERROR_INVALID_SID);
5226
5227     TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
5228     return bret;
5229 }
5230
5231 /******************************************************************************
5232  * GetNamedSecurityInfoA [ADVAPI32.@]
5233  */
5234 DWORD WINAPI GetNamedSecurityInfoA(LPSTR pObjectName,
5235         SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5236         PSID* ppsidOwner, PSID* ppsidGroup, PACL* ppDacl, PACL* ppSacl,
5237         PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
5238 {
5239     DWORD len;
5240     LPWSTR wstr = NULL;
5241     DWORD r;
5242
5243     TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo,
5244         ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
5245
5246     if( pObjectName )
5247     {
5248         len = MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, NULL, 0 );
5249         wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR));
5250         MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, wstr, len );
5251     }
5252
5253     r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
5254                            ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
5255
5256     HeapFree( GetProcessHeap(), 0, wstr );
5257
5258     return r;
5259 }
5260
5261 /******************************************************************************
5262  * GetNamedSecurityInfoW [ADVAPI32.@]
5263  */
5264 DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type,
5265     SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl,
5266     PACL* sacl, PSECURITY_DESCRIPTOR* descriptor )
5267 {
5268     DWORD needed, offset;
5269     SECURITY_DESCRIPTOR_RELATIVE *relative;
5270     BYTE *buffer;
5271
5272     TRACE( "%s %d %d %p %p %p %p %p\n", debugstr_w(name), type, info, owner,
5273            group, dacl, sacl, descriptor );
5274
5275     if (!name || !descriptor) return ERROR_INVALID_PARAMETER;
5276
5277     needed = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5278     if (info & OWNER_SECURITY_INFORMATION)
5279         needed += sizeof(sidWorld);
5280     if (info & GROUP_SECURITY_INFORMATION)
5281         needed += sizeof(sidWorld);
5282     if (info & DACL_SECURITY_INFORMATION)
5283         needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5284     if (info & SACL_SECURITY_INFORMATION)
5285         needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5286
5287     /* must be freed by caller */
5288     *descriptor = HeapAlloc( GetProcessHeap(), 0, needed );
5289     if (!*descriptor) return ERROR_NOT_ENOUGH_MEMORY;
5290
5291     if (!InitializeSecurityDescriptor( *descriptor, SECURITY_DESCRIPTOR_REVISION ))
5292     {
5293         HeapFree( GetProcessHeap(), 0, *descriptor );
5294         return ERROR_INVALID_SECURITY_DESCR;
5295     }
5296
5297     relative = *descriptor;
5298     relative->Control |= SE_SELF_RELATIVE;
5299     buffer = (BYTE *)relative;
5300     offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5301
5302     if (info & OWNER_SECURITY_INFORMATION)
5303     {
5304         memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5305         relative->Owner = offset;
5306         if (owner)
5307             *owner = buffer + offset;
5308         offset += sizeof(sidWorld);
5309     }
5310     if (info & GROUP_SECURITY_INFORMATION)
5311     {
5312         memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5313         relative->Group = offset;
5314         if (group)
5315             *group = buffer + offset;
5316         offset += sizeof(sidWorld);
5317     }
5318     if (info & DACL_SECURITY_INFORMATION)
5319     {
5320         relative->Control |= SE_DACL_PRESENT;
5321         GetWorldAccessACL( (PACL)(buffer + offset) );
5322         relative->Dacl = offset;
5323         if (dacl)
5324             *dacl = (PACL)(buffer + offset);
5325         offset += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5326     }
5327     if (info & SACL_SECURITY_INFORMATION)
5328     {
5329         relative->Control |= SE_SACL_PRESENT;
5330         GetWorldAccessACL( (PACL)(buffer + offset) );
5331         relative->Sacl = offset;
5332         if (sacl)
5333             *sacl = (PACL)(buffer + offset);
5334     }
5335     return ERROR_SUCCESS;
5336 }
5337
5338 /******************************************************************************
5339  * DecryptFileW [ADVAPI32.@]
5340  */
5341 BOOL WINAPI DecryptFileW(LPCWSTR lpFileName, DWORD dwReserved)
5342 {
5343     FIXME("%s %08x\n", debugstr_w(lpFileName), dwReserved);
5344     return TRUE;
5345 }
5346
5347 /******************************************************************************
5348  * DecryptFileA [ADVAPI32.@]
5349  */
5350 BOOL WINAPI DecryptFileA(LPCSTR lpFileName, DWORD dwReserved)
5351 {
5352     FIXME("%s %08x\n", debugstr_a(lpFileName), dwReserved);
5353     return TRUE;
5354 }
5355
5356 /******************************************************************************
5357  * EncryptFileW [ADVAPI32.@]
5358  */
5359 BOOL WINAPI EncryptFileW(LPCWSTR lpFileName)
5360 {
5361     FIXME("%s\n", debugstr_w(lpFileName));
5362     return TRUE;
5363 }
5364
5365 /******************************************************************************
5366  * EncryptFileA [ADVAPI32.@]
5367  */
5368 BOOL WINAPI EncryptFileA(LPCSTR lpFileName)
5369 {
5370     FIXME("%s\n", debugstr_a(lpFileName));
5371     return TRUE;
5372 }
5373
5374 /******************************************************************************
5375  * FileEncryptionStatusW [ADVAPI32.@]
5376  */
5377 BOOL WINAPI FileEncryptionStatusW(LPCWSTR lpFileName, LPDWORD lpStatus)
5378 {
5379     FIXME("(%s %p): stub\n", debugstr_w(lpFileName), lpStatus);
5380     if (!lpStatus)
5381         return FALSE;
5382     *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5383     return TRUE;
5384 }
5385
5386 /******************************************************************************
5387  * FileEncryptionStatusA [ADVAPI32.@]
5388  */
5389 BOOL WINAPI FileEncryptionStatusA(LPCSTR lpFileName, LPDWORD lpStatus)
5390 {
5391     FIXME("(%s %p): stub\n", debugstr_a(lpFileName), lpStatus);
5392     if (!lpStatus)
5393         return FALSE;
5394     *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5395     return TRUE;
5396 }
5397
5398 /******************************************************************************
5399  * SetSecurityInfo [ADVAPI32.@]
5400  */
5401 DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType, 
5402                       SECURITY_INFORMATION SecurityInfo, PSID psidOwner,
5403                       PSID psidGroup, PACL pDacl, PACL pSacl) {
5404     FIXME("stub\n");
5405     return ERROR_SUCCESS;
5406 }
5407
5408 /******************************************************************************
5409  * SaferCreateLevel   [ADVAPI32.@]
5410  */
5411 BOOL WINAPI SaferCreateLevel(DWORD ScopeId, DWORD LevelId, DWORD OpenFlags,
5412                              SAFER_LEVEL_HANDLE* LevelHandle, LPVOID lpReserved)
5413 {
5414     FIXME("(%u, %x, %u, %p, %p) stub\n", ScopeId, LevelId, OpenFlags, LevelHandle, lpReserved);
5415     return FALSE;
5416 }
5417
5418 DWORD WINAPI TreeResetNamedSecurityInfoW( LPWSTR pObjectName,
5419                 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5420                 PSID pOwner, PSID pGroup, PACL pDacl, PACL pSacl,
5421                 BOOL KeepExplicit, FN_PROGRESS fnProgress,
5422                 PROG_INVOKE_SETTING ProgressInvokeSetting, PVOID Args)
5423 {
5424     FIXME("(%s, %i, %i, %p, %p, %p, %p, %i, %p, %i, %p  Stub\n",
5425         debugstr_w(pObjectName), ObjectType, SecurityInfo, pOwner, pGroup,
5426         pDacl, pSacl, KeepExplicit, fnProgress, ProgressInvokeSetting, Args);
5427
5428     return ERROR_SUCCESS;
5429 }
5430
5431 /******************************************************************************
5432  * SaferGetPolicyInformation   [ADVAPI32.@]
5433  */
5434 BOOL WINAPI SaferGetPolicyInformation(DWORD scope, SAFER_POLICY_INFO_CLASS class, DWORD size,
5435                                       PVOID buffer, PDWORD required, LPVOID lpReserved)
5436 {
5437     FIXME("(%u %u %u %p %p %p) stub\n", scope, class, size, buffer, required, lpReserved);
5438     return FALSE;
5439 }