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