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