winejoystick.drv: Use CP_UNIXCP instead of CP_ACP when converting a string that comes...
[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;
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 = 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 = 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 ? &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, 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, 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 = LocalAlloc(GMEM_ZEROINIT, cBytes);
4207     if (!psd) goto lend;
4208
4209     psd->Revision = SID_REVISION;
4210     psd->Control |= SE_SELF_RELATIVE;
4211
4212     if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4213         psd, &cBytes))
4214     {
4215         LocalFree(psd);
4216         goto lend;
4217     }
4218
4219     if (SecurityDescriptorSize)
4220         *SecurityDescriptorSize = cBytes;
4221
4222     bret = TRUE;
4223  
4224 lend:
4225     TRACE(" ret=%d\n", bret);
4226     return bret;
4227 }
4228
4229 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
4230 {
4231     if (cch == -1)
4232         cch = strlenW(string);
4233
4234     if (plen)
4235         *plen += cch;
4236
4237     if (pwptr)
4238     {
4239         memcpy(*pwptr, string, sizeof(WCHAR)*cch);
4240         *pwptr += cch;
4241     }
4242 }
4243
4244 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
4245 {
4246     DWORD i;
4247     WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
4248     WCHAR subauthfmt[] = { '-','%','u',0 };
4249     WCHAR buf[26];
4250     SID *pisid = psid;
4251
4252     if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
4253     {
4254         SetLastError(ERROR_INVALID_SID);
4255         return FALSE;
4256     }
4257
4258     if (pisid->IdentifierAuthority.Value[0] ||
4259      pisid->IdentifierAuthority.Value[1])
4260     {
4261         FIXME("not matching MS' bugs\n");
4262         SetLastError(ERROR_INVALID_SID);
4263         return FALSE;
4264     }
4265
4266     sprintfW( buf, fmt, pisid->Revision,
4267         MAKELONG(
4268             MAKEWORD( pisid->IdentifierAuthority.Value[5],
4269                     pisid->IdentifierAuthority.Value[4] ),
4270             MAKEWORD( pisid->IdentifierAuthority.Value[3],
4271                     pisid->IdentifierAuthority.Value[2] )
4272         ) );
4273     DumpString(buf, -1, pwptr, plen);
4274
4275     for( i=0; i<pisid->SubAuthorityCount; i++ )
4276     {
4277         sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
4278         DumpString(buf, -1, pwptr, plen);
4279     }
4280     return TRUE;
4281 }
4282
4283 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
4284 {
4285     size_t i;
4286     for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
4287     {
4288         if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
4289         {
4290             DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
4291             return TRUE;
4292         }
4293     }
4294
4295     return DumpSidNumeric(psid, pwptr, plen);
4296 }
4297
4298 static const LPCWSTR AceRightBitNames[32] = {
4299         SDDL_CREATE_CHILD,        /*  0 */
4300         SDDL_DELETE_CHILD,
4301         SDDL_LIST_CHILDREN,
4302         SDDL_SELF_WRITE,
4303         SDDL_READ_PROPERTY,       /*  4 */
4304         SDDL_WRITE_PROPERTY,
4305         SDDL_DELETE_TREE,
4306         SDDL_LIST_OBJECT,
4307         SDDL_CONTROL_ACCESS,      /*  8 */
4308         NULL,
4309         NULL,
4310         NULL,
4311         NULL,                     /* 12 */
4312         NULL,
4313         NULL,
4314         NULL,
4315         SDDL_STANDARD_DELETE,     /* 16 */
4316         SDDL_READ_CONTROL,
4317         SDDL_WRITE_DAC,
4318         SDDL_WRITE_OWNER,
4319         NULL,                     /* 20 */
4320         NULL,
4321         NULL,
4322         NULL,
4323         NULL,                     /* 24 */
4324         NULL,
4325         NULL,
4326         NULL,
4327         SDDL_GENERIC_ALL,         /* 28 */
4328         SDDL_GENERIC_EXECUTE,
4329         SDDL_GENERIC_WRITE,
4330         SDDL_GENERIC_READ
4331 };
4332
4333 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
4334 {
4335     static const WCHAR fmtW[] = {'0','x','%','x',0};
4336     WCHAR buf[15];
4337     size_t i;
4338
4339     if (mask == 0)
4340         return;
4341
4342     /* first check if the right have name */
4343     for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
4344     {
4345         if (AceRights[i].wstr == NULL)
4346             break;
4347         if (mask == AceRights[i].value)
4348         {
4349             DumpString(AceRights[i].wstr, -1, pwptr, plen);
4350             return;
4351         }
4352     }
4353
4354     /* then check if it can be built from bit names */
4355     for (i = 0; i < 32; i++)
4356     {
4357         if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
4358         {
4359             /* can't be built from bit names */
4360             sprintfW(buf, fmtW, mask);
4361             DumpString(buf, -1, pwptr, plen);
4362             return;
4363         }
4364     }
4365
4366     /* build from bit names */
4367     for (i = 0; i < 32; i++)
4368         if (mask & (1 << i))
4369             DumpString(AceRightBitNames[i], -1, pwptr, plen);
4370 }
4371
4372 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
4373 {
4374     ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
4375     static const WCHAR openbr = '(';
4376     static const WCHAR closebr = ')';
4377     static const WCHAR semicolon = ';';
4378
4379     if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
4380     {
4381         SetLastError(ERROR_INVALID_ACL);
4382         return FALSE;
4383     }
4384
4385     piace = pace;
4386     DumpString(&openbr, 1, pwptr, plen);
4387     switch (piace->Header.AceType)
4388     {
4389         case ACCESS_ALLOWED_ACE_TYPE:
4390             DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
4391             break;
4392         case ACCESS_DENIED_ACE_TYPE:
4393             DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
4394             break;
4395         case SYSTEM_AUDIT_ACE_TYPE:
4396             DumpString(SDDL_AUDIT, -1, pwptr, plen);
4397             break;
4398         case SYSTEM_ALARM_ACE_TYPE:
4399             DumpString(SDDL_ALARM, -1, pwptr, plen);
4400             break;
4401     }
4402     DumpString(&semicolon, 1, pwptr, plen);
4403
4404     if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
4405         DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
4406     if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
4407         DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
4408     if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
4409         DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
4410     if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
4411         DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
4412     if (piace->Header.AceFlags & INHERITED_ACE)
4413         DumpString(SDDL_INHERITED, -1, pwptr, plen);
4414     if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
4415         DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
4416     if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
4417         DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
4418     DumpString(&semicolon, 1, pwptr, plen);
4419     DumpRights(piace->Mask, pwptr, plen);
4420     DumpString(&semicolon, 1, pwptr, plen);
4421     /* objects not supported */
4422     DumpString(&semicolon, 1, pwptr, plen);
4423     /* objects not supported */
4424     DumpString(&semicolon, 1, pwptr, plen);
4425     if (!DumpSid(&piace->SidStart, pwptr, plen))
4426         return FALSE;
4427     DumpString(&closebr, 1, pwptr, plen);
4428     return TRUE;
4429 }
4430
4431 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
4432 {
4433     WORD count;
4434     int i;
4435
4436     if (protected)
4437         DumpString(SDDL_PROTECTED, -1, pwptr, plen);
4438     if (autoInheritReq)
4439         DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
4440     if (autoInherited)
4441         DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
4442
4443     if (pacl == NULL)
4444         return TRUE;
4445
4446     if (!IsValidAcl(pacl))
4447         return FALSE;
4448
4449     count = pacl->AceCount;
4450     for (i = 0; i < count; i++)
4451     {
4452         LPVOID ace;
4453         if (!GetAce(pacl, i, &ace))
4454             return FALSE;
4455         if (!DumpAce(ace, pwptr, plen))
4456             return FALSE;
4457     }
4458
4459     return TRUE;
4460 }
4461
4462 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4463 {
4464     static const WCHAR prefix[] = {'O',':',0};
4465     BOOL bDefaulted;
4466     PSID psid;
4467
4468     if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
4469         return FALSE;
4470
4471     if (psid == NULL)
4472         return TRUE;
4473
4474     DumpString(prefix, -1, pwptr, plen);
4475     if (!DumpSid(psid, pwptr, plen))
4476         return FALSE;
4477     return TRUE;
4478 }
4479
4480 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4481 {
4482     static const WCHAR prefix[] = {'G',':',0};
4483     BOOL bDefaulted;
4484     PSID psid;
4485
4486     if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
4487         return FALSE;
4488
4489     if (psid == NULL)
4490         return TRUE;
4491
4492     DumpString(prefix, -1, pwptr, plen);
4493     if (!DumpSid(psid, pwptr, plen))
4494         return FALSE;
4495     return TRUE;
4496 }
4497
4498 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4499 {
4500     static const WCHAR dacl[] = {'D',':',0};
4501     SECURITY_DESCRIPTOR_CONTROL control;
4502     BOOL present, defaulted;
4503     DWORD revision;
4504     PACL pacl;
4505
4506     if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
4507         return FALSE;
4508
4509     if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
4510         return FALSE;
4511
4512     if (!present)
4513         return TRUE;
4514
4515     DumpString(dacl, 2, pwptr, plen);
4516     if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
4517         return FALSE;
4518     return TRUE;
4519 }
4520
4521 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4522 {
4523     static const WCHAR sacl[] = {'S',':',0};
4524     SECURITY_DESCRIPTOR_CONTROL control;
4525     BOOL present, defaulted;
4526     DWORD revision;
4527     PACL pacl;
4528
4529     if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
4530         return FALSE;
4531
4532     if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
4533         return FALSE;
4534
4535     if (!present)
4536         return TRUE;
4537
4538     DumpString(sacl, 2, pwptr, plen);
4539     if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
4540         return FALSE;
4541     return TRUE;
4542 }
4543
4544 /******************************************************************************
4545  * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
4546  */
4547 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen)
4548 {
4549     ULONG len;
4550     WCHAR *wptr, *wstr;
4551
4552     if (SDRevision != SDDL_REVISION_1)
4553     {
4554         ERR("Pogram requested unknown SDDL revision %d\n", SDRevision);
4555         SetLastError(ERROR_UNKNOWN_REVISION);
4556         return FALSE;
4557     }
4558
4559     len = 0;
4560     if (RequestedInformation & OWNER_SECURITY_INFORMATION)
4561         if (!DumpOwner(SecurityDescriptor, NULL, &len))
4562             return FALSE;
4563     if (RequestedInformation & GROUP_SECURITY_INFORMATION)
4564         if (!DumpGroup(SecurityDescriptor, NULL, &len))
4565             return FALSE;
4566     if (RequestedInformation & DACL_SECURITY_INFORMATION)
4567         if (!DumpDacl(SecurityDescriptor, NULL, &len))
4568             return FALSE;
4569     if (RequestedInformation & SACL_SECURITY_INFORMATION)
4570         if (!DumpSacl(SecurityDescriptor, NULL, &len))
4571             return FALSE;
4572
4573     wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
4574     if (RequestedInformation & OWNER_SECURITY_INFORMATION)
4575         if (!DumpOwner(SecurityDescriptor, &wptr, NULL))
4576             return FALSE;
4577     if (RequestedInformation & GROUP_SECURITY_INFORMATION)
4578         if (!DumpGroup(SecurityDescriptor, &wptr, NULL))
4579             return FALSE;
4580     if (RequestedInformation & DACL_SECURITY_INFORMATION)
4581         if (!DumpDacl(SecurityDescriptor, &wptr, NULL))
4582             return FALSE;
4583     if (RequestedInformation & SACL_SECURITY_INFORMATION)
4584         if (!DumpSacl(SecurityDescriptor, &wptr, NULL))
4585             return FALSE;
4586     *wptr = 0;
4587
4588     TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
4589     *OutputString = wstr;
4590     if (OutputLen)
4591         *OutputLen = strlenW(*OutputString)+1;
4592     return TRUE;
4593 }
4594
4595 /******************************************************************************
4596  * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
4597  */
4598 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen)
4599 {
4600     LPWSTR wstr;
4601     ULONG len;
4602     if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
4603     {
4604         int lenA;
4605
4606         lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
4607         *OutputString = HeapAlloc(GetProcessHeap(), 0, lenA);
4608         WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
4609         LocalFree(wstr);
4610
4611         if (OutputLen != NULL)
4612             *OutputLen = lenA;
4613         return TRUE;
4614     }
4615     else
4616     {
4617         *OutputString = NULL;
4618         if (OutputLen)
4619             *OutputLen = 0;
4620         return FALSE;
4621     }
4622 }
4623
4624 /******************************************************************************
4625  * ConvertStringSidToSidW [ADVAPI32.@]
4626  */
4627 BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid)
4628 {
4629     BOOL bret = FALSE;
4630     DWORD cBytes;
4631
4632     TRACE("%s, %p\n", debugstr_w(StringSid), Sid);
4633     if (GetVersion() & 0x80000000)
4634         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4635     else if (!StringSid || !Sid)
4636         SetLastError(ERROR_INVALID_PARAMETER);
4637     else if (ParseStringSidToSid(StringSid, NULL, &cBytes))
4638     {
4639         PSID pSid = *Sid = LocalAlloc(0, cBytes);
4640
4641         bret = ParseStringSidToSid(StringSid, pSid, &cBytes);
4642         if (!bret)
4643             LocalFree(*Sid); 
4644     }
4645     return bret;
4646 }
4647
4648 /******************************************************************************
4649  * ConvertStringSidToSidA [ADVAPI32.@]
4650  */
4651 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
4652 {
4653     BOOL bret = FALSE;
4654
4655     TRACE("%s, %p\n", debugstr_a(StringSid), Sid);
4656     if (GetVersion() & 0x80000000)
4657         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4658     else if (!StringSid || !Sid)
4659         SetLastError(ERROR_INVALID_PARAMETER);
4660     else
4661     {
4662         UINT len = MultiByteToWideChar(CP_ACP, 0, StringSid, -1, NULL, 0);
4663         LPWSTR wStringSid = HeapAlloc(GetProcessHeap(), 0,
4664          len * sizeof(WCHAR));
4665
4666         MultiByteToWideChar(CP_ACP, 0, StringSid, -1, wStringSid, len);
4667         bret = ConvertStringSidToSidW(wStringSid, Sid);
4668         HeapFree(GetProcessHeap(), 0, wStringSid);
4669     }
4670     return bret;
4671 }
4672
4673 /******************************************************************************
4674  * ConvertSidToStringSidW [ADVAPI32.@]
4675  *
4676  *  format of SID string is:
4677  *    S-<count>-<auth>-<subauth1>-<subauth2>-<subauth3>...
4678  *  where
4679  *    <rev> is the revision of the SID encoded as decimal
4680  *    <auth> is the identifier authority encoded as hex
4681  *    <subauthN> is the subauthority id encoded as decimal
4682  */
4683 BOOL WINAPI ConvertSidToStringSidW( PSID pSid, LPWSTR *pstr )
4684 {
4685     DWORD len = 0;
4686     LPWSTR wstr, wptr;
4687
4688     TRACE("%p %p\n", pSid, pstr );
4689
4690     len = 0;
4691     if (!DumpSidNumeric(pSid, NULL, &len))
4692         return FALSE;
4693     wstr = wptr = LocalAlloc(0, (len+1) * sizeof(WCHAR));
4694     DumpSidNumeric(pSid, &wptr, NULL);
4695     *wptr = 0;
4696
4697     *pstr = wstr;
4698     return TRUE;
4699 }
4700
4701 /******************************************************************************
4702  * ConvertSidToStringSidA [ADVAPI32.@]
4703  */
4704 BOOL WINAPI ConvertSidToStringSidA(PSID pSid, LPSTR *pstr)
4705 {
4706     LPWSTR wstr = NULL;
4707     LPSTR str;
4708     UINT len;
4709
4710     TRACE("%p %p\n", pSid, pstr );
4711
4712     if( !ConvertSidToStringSidW( pSid, &wstr ) )
4713         return FALSE;
4714
4715     len = WideCharToMultiByte( CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL );
4716     str = LocalAlloc( 0, len );
4717     WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, len, NULL, NULL );
4718     LocalFree( wstr );
4719
4720     *pstr = str;
4721
4722     return TRUE;
4723 }
4724
4725 BOOL WINAPI ConvertToAutoInheritPrivateObjectSecurity(
4726         PSECURITY_DESCRIPTOR pdesc,
4727         PSECURITY_DESCRIPTOR cdesc,
4728         PSECURITY_DESCRIPTOR* ndesc,
4729         GUID* objtype,
4730         BOOL isdir,
4731         PGENERIC_MAPPING genmap )
4732 {
4733     FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
4734
4735     return FALSE;
4736 }
4737
4738 BOOL WINAPI CreatePrivateObjectSecurity(
4739         PSECURITY_DESCRIPTOR ParentDescriptor,
4740         PSECURITY_DESCRIPTOR CreatorDescriptor,
4741         PSECURITY_DESCRIPTOR* NewDescriptor,
4742         BOOL IsDirectoryObject,
4743         HANDLE Token,
4744         PGENERIC_MAPPING GenericMapping )
4745 {
4746     FIXME("%p %p %p %d %p %p - stub\n", ParentDescriptor, CreatorDescriptor,
4747           NewDescriptor, IsDirectoryObject, Token, GenericMapping);
4748
4749     return FALSE;
4750 }
4751
4752 BOOL WINAPI DestroyPrivateObjectSecurity( PSECURITY_DESCRIPTOR* ObjectDescriptor )
4753 {
4754     FIXME("%p - stub\n", ObjectDescriptor);
4755
4756     return TRUE;
4757 }
4758
4759 BOOL WINAPI CreateProcessAsUserA(
4760         HANDLE hToken,
4761         LPCSTR lpApplicationName,
4762         LPSTR lpCommandLine,
4763         LPSECURITY_ATTRIBUTES lpProcessAttributes,
4764         LPSECURITY_ATTRIBUTES lpThreadAttributes,
4765         BOOL bInheritHandles,
4766         DWORD dwCreationFlags,
4767         LPVOID lpEnvironment,
4768         LPCSTR lpCurrentDirectory,
4769         LPSTARTUPINFOA lpStartupInfo,
4770         LPPROCESS_INFORMATION lpProcessInformation )
4771 {
4772     FIXME("%p %s %s %p %p %d 0x%08x %p %s %p %p - stub\n", hToken, debugstr_a(lpApplicationName),
4773           debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
4774           dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
4775
4776     return FALSE;
4777 }
4778
4779 BOOL WINAPI CreateProcessAsUserW(
4780         HANDLE hToken,
4781         LPCWSTR lpApplicationName,
4782         LPWSTR lpCommandLine,
4783         LPSECURITY_ATTRIBUTES lpProcessAttributes,
4784         LPSECURITY_ATTRIBUTES lpThreadAttributes,
4785         BOOL bInheritHandles,
4786         DWORD dwCreationFlags,
4787         LPVOID lpEnvironment,
4788         LPCWSTR lpCurrentDirectory,
4789         LPSTARTUPINFOW lpStartupInfo,
4790         LPPROCESS_INFORMATION lpProcessInformation )
4791 {
4792     FIXME("%p %s %s %p %p %d 0x%08x %p %s %p %p - semi- stub\n", hToken, 
4793           debugstr_w(lpApplicationName), debugstr_w(lpCommandLine), lpProcessAttributes,
4794           lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, 
4795           debugstr_w(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
4796
4797     /* We should create the process with a suspended main thread */
4798     if (!CreateProcessW (lpApplicationName,
4799                          lpCommandLine,
4800                          lpProcessAttributes,
4801                          lpThreadAttributes,
4802                          bInheritHandles,
4803                          dwCreationFlags, /* CREATE_SUSPENDED */
4804                          lpEnvironment,
4805                          lpCurrentDirectory,
4806                          lpStartupInfo,
4807                          lpProcessInformation))
4808     {
4809       return FALSE;
4810     }
4811
4812     return TRUE;
4813 }
4814
4815 /******************************************************************************
4816  * CreateProcessWithLogonW
4817  */
4818 BOOL WINAPI CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags,
4819     LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment,
4820     LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
4821 {
4822     FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
4823     debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
4824     debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
4825     lpStartupInfo, lpProcessInformation);
4826
4827     return FALSE;
4828 }
4829
4830 /******************************************************************************
4831  * DuplicateTokenEx [ADVAPI32.@]
4832  */
4833 BOOL WINAPI DuplicateTokenEx(
4834         HANDLE ExistingTokenHandle, DWORD dwDesiredAccess,
4835         LPSECURITY_ATTRIBUTES lpTokenAttributes,
4836         SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
4837         TOKEN_TYPE TokenType,
4838         PHANDLE DuplicateTokenHandle )
4839 {
4840     OBJECT_ATTRIBUTES ObjectAttributes;
4841
4842     TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
4843           ImpersonationLevel, TokenType, DuplicateTokenHandle);
4844
4845     InitializeObjectAttributes(
4846         &ObjectAttributes,
4847         NULL,
4848         (lpTokenAttributes && lpTokenAttributes->bInheritHandle) ? OBJ_INHERIT : 0,
4849         NULL,
4850         lpTokenAttributes ? lpTokenAttributes->lpSecurityDescriptor : NULL );
4851
4852     return set_ntstatus( NtDuplicateToken( ExistingTokenHandle,
4853                                            dwDesiredAccess,
4854                                            &ObjectAttributes,
4855                                            ImpersonationLevel,
4856                                            TokenType,
4857                                            DuplicateTokenHandle ) );
4858 }
4859
4860 BOOL WINAPI DuplicateToken(
4861         HANDLE ExistingTokenHandle,
4862         SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
4863         PHANDLE DuplicateTokenHandle )
4864 {
4865     return DuplicateTokenEx( ExistingTokenHandle, TOKEN_IMPERSONATE | TOKEN_QUERY,
4866                              NULL, ImpersonationLevel, TokenImpersonation,
4867                              DuplicateTokenHandle );
4868 }
4869
4870 /******************************************************************************
4871  * ComputeStringSidSize
4872  */
4873 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
4874 {
4875     if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
4876     {
4877         int ctok = 0;
4878         while (*StringSid)
4879         {
4880             if (*StringSid == '-')
4881                 ctok++;
4882             StringSid++;
4883         }
4884
4885         if (ctok >= 3)
4886             return GetSidLengthRequired(ctok - 2);
4887     }
4888     else /* String constant format  - Only available in winxp and above */
4889     {
4890         unsigned int i;
4891
4892         for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
4893             if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
4894                 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
4895     }
4896
4897     return GetSidLengthRequired(0);
4898 }
4899
4900 /******************************************************************************
4901  * ParseStringSidToSid
4902  */
4903 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
4904 {
4905     BOOL bret = FALSE;
4906     SID* pisid=pSid;
4907
4908     TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
4909     if (!StringSid)
4910     {
4911         SetLastError(ERROR_INVALID_PARAMETER);
4912         TRACE("StringSid is NULL, returning FALSE\n");
4913         return FALSE;
4914     }
4915
4916     *cBytes = ComputeStringSidSize(StringSid);
4917     if (!pisid) /* Simply compute the size */
4918     {
4919         TRACE("only size requested, returning TRUE\n");
4920         return TRUE;
4921     }
4922
4923     if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
4924     {
4925         DWORD i = 0, identAuth;
4926         DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
4927
4928         StringSid += 2; /* Advance to Revision */
4929         pisid->Revision = atoiW(StringSid);
4930
4931         if (pisid->Revision != SDDL_REVISION)
4932         {
4933             TRACE("Revision %d is unknown\n", pisid->Revision);
4934             goto lend; /* ERROR_INVALID_SID */
4935         }
4936         if (csubauth == 0)
4937         {
4938             TRACE("SubAuthorityCount is 0\n");
4939             goto lend; /* ERROR_INVALID_SID */
4940         }
4941
4942         pisid->SubAuthorityCount = csubauth;
4943
4944         /* Advance to identifier authority */
4945         while (*StringSid && *StringSid != '-')
4946             StringSid++;
4947         if (*StringSid == '-')
4948             StringSid++;
4949
4950         /* MS' implementation can't handle values greater than 2^32 - 1, so
4951          * we don't either; assume most significant bytes are always 0
4952          */
4953         pisid->IdentifierAuthority.Value[0] = 0;
4954         pisid->IdentifierAuthority.Value[1] = 0;
4955         identAuth = atoiW(StringSid);
4956         pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
4957         pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
4958         pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
4959         pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
4960
4961         /* Advance to first sub authority */
4962         while (*StringSid && *StringSid != '-')
4963             StringSid++;
4964         if (*StringSid == '-')
4965             StringSid++;
4966
4967         while (*StringSid)
4968         {
4969             pisid->SubAuthority[i++] = atoiW(StringSid);
4970
4971             while (*StringSid && *StringSid != '-')
4972                 StringSid++;
4973             if (*StringSid == '-')
4974                 StringSid++;
4975         }
4976
4977         if (i != pisid->SubAuthorityCount)
4978             goto lend; /* ERROR_INVALID_SID */
4979
4980         bret = TRUE;
4981     }
4982     else /* String constant format  - Only available in winxp and above */
4983     {
4984         unsigned int i;
4985         pisid->Revision = SDDL_REVISION;
4986
4987         for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
4988             if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
4989             {
4990                 DWORD j;
4991                 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
4992                 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
4993                 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
4994                     pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
4995                 bret = TRUE;
4996             }
4997
4998         if (!bret)
4999             FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
5000     }
5001
5002 lend:
5003     if (!bret)
5004         SetLastError(ERROR_INVALID_SID);
5005
5006     TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
5007     return bret;
5008 }
5009
5010 /******************************************************************************
5011  * GetNamedSecurityInfoA [ADVAPI32.@]
5012  */
5013 DWORD WINAPI GetNamedSecurityInfoA(LPSTR pObjectName,
5014         SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5015         PSID* ppsidOwner, PSID* ppsidGroup, PACL* ppDacl, PACL* ppSacl,
5016         PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
5017 {
5018     DWORD len;
5019     LPWSTR wstr = NULL;
5020     DWORD r;
5021
5022     TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo,
5023         ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
5024
5025     if( pObjectName )
5026     {
5027         len = MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, NULL, 0 );
5028         wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR));
5029         MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, wstr, len );
5030     }
5031
5032     r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
5033                            ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
5034
5035     HeapFree( GetProcessHeap(), 0, wstr );
5036
5037     return r;
5038 }
5039
5040 /******************************************************************************
5041  * GetNamedSecurityInfoW [ADVAPI32.@]
5042  */
5043 DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type,
5044     SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl,
5045     PACL* sacl, PSECURITY_DESCRIPTOR* descriptor )
5046 {
5047     DWORD needed, offset;
5048     SECURITY_DESCRIPTOR_RELATIVE *relative;
5049     BYTE *buffer;
5050
5051     TRACE( "%s %d %d %p %p %p %p %p\n", debugstr_w(name), type, info, owner,
5052            group, dacl, sacl, descriptor );
5053
5054     if (!name || !descriptor) return ERROR_INVALID_PARAMETER;
5055
5056     needed = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5057     if (info & OWNER_SECURITY_INFORMATION)
5058         needed += sizeof(sidWorld);
5059     if (info & GROUP_SECURITY_INFORMATION)
5060         needed += sizeof(sidWorld);
5061     if (info & DACL_SECURITY_INFORMATION)
5062         needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5063     if (info & SACL_SECURITY_INFORMATION)
5064         needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5065
5066     /* must be freed by caller */
5067     *descriptor = HeapAlloc( GetProcessHeap(), 0, needed );
5068     if (!*descriptor) return ERROR_NOT_ENOUGH_MEMORY;
5069
5070     if (!InitializeSecurityDescriptor( *descriptor, SECURITY_DESCRIPTOR_REVISION ))
5071     {
5072         HeapFree( GetProcessHeap(), 0, *descriptor );
5073         return ERROR_INVALID_SECURITY_DESCR;
5074     }
5075
5076     relative = *descriptor;
5077     relative->Control |= SE_SELF_RELATIVE;
5078     buffer = (BYTE *)relative;
5079     offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5080
5081     if (info & OWNER_SECURITY_INFORMATION)
5082     {
5083         memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5084         relative->Owner = offset;
5085         if (owner)
5086             *owner = buffer + offset;
5087         offset += sizeof(sidWorld);
5088     }
5089     if (info & GROUP_SECURITY_INFORMATION)
5090     {
5091         memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5092         relative->Group = offset;
5093         if (group)
5094             *group = buffer + offset;
5095         offset += sizeof(sidWorld);
5096     }
5097     if (info & DACL_SECURITY_INFORMATION)
5098     {
5099         relative->Control |= SE_DACL_PRESENT;
5100         GetWorldAccessACL( (PACL)(buffer + offset) );
5101         relative->Dacl = offset;
5102         if (dacl)
5103             *dacl = (PACL)(buffer + offset);
5104         offset += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5105     }
5106     if (info & SACL_SECURITY_INFORMATION)
5107     {
5108         relative->Control |= SE_SACL_PRESENT;
5109         GetWorldAccessACL( (PACL)(buffer + offset) );
5110         relative->Sacl = offset;
5111         if (sacl)
5112             *sacl = (PACL)(buffer + offset);
5113     }
5114     return ERROR_SUCCESS;
5115 }
5116
5117 /******************************************************************************
5118  * DecryptFileW [ADVAPI32.@]
5119  */
5120 BOOL WINAPI DecryptFileW(LPCWSTR lpFileName, DWORD dwReserved)
5121 {
5122     FIXME("%s %08x\n", debugstr_w(lpFileName), dwReserved);
5123     return TRUE;
5124 }
5125
5126 /******************************************************************************
5127  * DecryptFileA [ADVAPI32.@]
5128  */
5129 BOOL WINAPI DecryptFileA(LPCSTR lpFileName, DWORD dwReserved)
5130 {
5131     FIXME("%s %08x\n", debugstr_a(lpFileName), dwReserved);
5132     return TRUE;
5133 }
5134
5135 /******************************************************************************
5136  * EncryptFileW [ADVAPI32.@]
5137  */
5138 BOOL WINAPI EncryptFileW(LPCWSTR lpFileName)
5139 {
5140     FIXME("%s\n", debugstr_w(lpFileName));
5141     return TRUE;
5142 }
5143
5144 /******************************************************************************
5145  * EncryptFileA [ADVAPI32.@]
5146  */
5147 BOOL WINAPI EncryptFileA(LPCSTR lpFileName)
5148 {
5149     FIXME("%s\n", debugstr_a(lpFileName));
5150     return TRUE;
5151 }
5152
5153 /******************************************************************************
5154  * FileEncryptionStatusW [ADVAPI32.@]
5155  */
5156 BOOL WINAPI FileEncryptionStatusW(LPCWSTR lpFileName, LPDWORD lpStatus)
5157 {
5158     FIXME("(%s %p): stub\n", debugstr_w(lpFileName), lpStatus);
5159     if (!lpStatus)
5160         return FALSE;
5161     *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5162     return TRUE;
5163 }
5164
5165 /******************************************************************************
5166  * FileEncryptionStatusA [ADVAPI32.@]
5167  */
5168 BOOL WINAPI FileEncryptionStatusA(LPCSTR lpFileName, LPDWORD lpStatus)
5169 {
5170     FIXME("(%s %p): stub\n", debugstr_a(lpFileName), lpStatus);
5171     if (!lpStatus)
5172         return FALSE;
5173     *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5174     return TRUE;
5175 }
5176
5177 /******************************************************************************
5178  * SetSecurityInfo [ADVAPI32.@]
5179  */
5180 DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType, 
5181                       SECURITY_INFORMATION SecurityInfo, PSID psidOwner,
5182                       PSID psidGroup, PACL pDacl, PACL pSacl) {
5183     FIXME("stub\n");
5184     return ERROR_SUCCESS;
5185 }
5186
5187 /******************************************************************************
5188  * SaferCreateLevel   [ADVAPI32.@]
5189  */
5190 BOOL WINAPI SaferCreateLevel(DWORD ScopeId, DWORD LevelId, DWORD OpenFlags,
5191                              SAFER_LEVEL_HANDLE* LevelHandle, LPVOID lpReserved)
5192 {
5193     FIXME("(%u, %x, %u, %p, %p) stub\n", ScopeId, LevelId, OpenFlags, LevelHandle, lpReserved);
5194     return FALSE;
5195 }