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