winhttp, wininet: Load i2d_X509 from libcrypto.so.
[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  * GetSecurityInfoExA [ADVAPI32.@]
2950  */
2951 DWORD WINAPI GetSecurityInfoExA(
2952         HANDLE hObject, SE_OBJECT_TYPE ObjectType,
2953         SECURITY_INFORMATION SecurityInfo, LPCSTR lpProvider,
2954         LPCSTR lpProperty, PACTRL_ACCESSA *ppAccessList,
2955         PACTRL_AUDITA *ppAuditList, LPSTR *lppOwner, LPSTR *lppGroup
2956 )
2957 {
2958   FIXME("stub!\n");
2959   return ERROR_BAD_PROVIDER;
2960 }
2961
2962 /******************************************************************************
2963  * GetSecurityInfoExW [ADVAPI32.@]
2964  */
2965 DWORD WINAPI GetSecurityInfoExW(
2966         HANDLE hObject, SE_OBJECT_TYPE ObjectType, 
2967         SECURITY_INFORMATION SecurityInfo, LPCWSTR lpProvider,
2968         LPCWSTR lpProperty, PACTRL_ACCESSW *ppAccessList, 
2969         PACTRL_AUDITW *ppAuditList, LPWSTR *lppOwner, LPWSTR *lppGroup
2970 )
2971 {
2972   FIXME("stub!\n");
2973   return ERROR_BAD_PROVIDER; 
2974 }
2975
2976 /******************************************************************************
2977  * BuildExplicitAccessWithNameA [ADVAPI32.@]
2978  */
2979 VOID WINAPI BuildExplicitAccessWithNameA( PEXPLICIT_ACCESSA pExplicitAccess,
2980                                           LPSTR pTrusteeName, DWORD AccessPermissions,
2981                                           ACCESS_MODE AccessMode, DWORD Inheritance )
2982 {
2983     TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_a(pTrusteeName),
2984           AccessPermissions, AccessMode, Inheritance);
2985
2986     pExplicitAccess->grfAccessPermissions = AccessPermissions;
2987     pExplicitAccess->grfAccessMode = AccessMode;
2988     pExplicitAccess->grfInheritance = Inheritance;
2989
2990     pExplicitAccess->Trustee.pMultipleTrustee = NULL;
2991     pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2992     pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
2993     pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
2994     pExplicitAccess->Trustee.ptstrName = pTrusteeName;
2995 }
2996
2997 /******************************************************************************
2998  * BuildExplicitAccessWithNameW [ADVAPI32.@]
2999  */
3000 VOID WINAPI BuildExplicitAccessWithNameW( PEXPLICIT_ACCESSW pExplicitAccess,
3001                                           LPWSTR pTrusteeName, DWORD AccessPermissions,
3002                                           ACCESS_MODE AccessMode, DWORD Inheritance )
3003 {
3004     TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_w(pTrusteeName),
3005           AccessPermissions, AccessMode, Inheritance);
3006
3007     pExplicitAccess->grfAccessPermissions = AccessPermissions;
3008     pExplicitAccess->grfAccessMode = AccessMode;
3009     pExplicitAccess->grfInheritance = Inheritance;
3010
3011     pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3012     pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3013     pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3014     pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3015     pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3016 }
3017
3018 /******************************************************************************
3019  * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
3020  */
3021 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
3022                                              SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
3023                                              LPSTR InheritedObjectTypeName, LPSTR Name )
3024 {
3025     DWORD ObjectsPresent = 0;
3026
3027     TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3028           ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
3029
3030     /* Fill the OBJECTS_AND_NAME structure */
3031     pObjName->ObjectType = ObjectType;
3032     if (ObjectTypeName != NULL)
3033     {
3034         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3035     }
3036
3037     pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3038     if (InheritedObjectTypeName != NULL)
3039     {
3040         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3041     }
3042
3043     pObjName->ObjectsPresent = ObjectsPresent;
3044     pObjName->ptstrName = Name;
3045
3046     /* Fill the TRUSTEE structure */
3047     pTrustee->pMultipleTrustee = NULL;
3048     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3049     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3050     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3051     pTrustee->ptstrName = (LPSTR)pObjName;
3052 }
3053
3054 /******************************************************************************
3055  * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
3056  */
3057 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
3058                                              SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
3059                                              LPWSTR InheritedObjectTypeName, LPWSTR Name )
3060 {
3061     DWORD ObjectsPresent = 0;
3062
3063     TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3064           ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
3065
3066     /* Fill the OBJECTS_AND_NAME structure */
3067     pObjName->ObjectType = ObjectType;
3068     if (ObjectTypeName != NULL)
3069     {
3070         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3071     }
3072
3073     pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3074     if (InheritedObjectTypeName != NULL)
3075     {
3076         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3077     }
3078
3079     pObjName->ObjectsPresent = ObjectsPresent;
3080     pObjName->ptstrName = Name;
3081
3082     /* Fill the TRUSTEE structure */
3083     pTrustee->pMultipleTrustee = NULL;
3084     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3085     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3086     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3087     pTrustee->ptstrName = (LPWSTR)pObjName;
3088 }
3089
3090 /******************************************************************************
3091  * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
3092  */
3093 VOID WINAPI BuildTrusteeWithObjectsAndSidA( PTRUSTEEA pTrustee, POBJECTS_AND_SID pObjSid,
3094                                             GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3095 {
3096     DWORD ObjectsPresent = 0;
3097
3098     TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3099
3100     /* Fill the OBJECTS_AND_SID structure */
3101     if (pObjectGuid != NULL)
3102     {
3103         pObjSid->ObjectTypeGuid = *pObjectGuid;
3104         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3105     }
3106     else
3107     {
3108         ZeroMemory(&pObjSid->ObjectTypeGuid,
3109                    sizeof(GUID));
3110     }
3111
3112     if (pInheritedObjectGuid != NULL)
3113     {
3114         pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3115         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3116     }
3117     else
3118     {
3119         ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3120                    sizeof(GUID));
3121     }
3122
3123     pObjSid->ObjectsPresent = ObjectsPresent;
3124     pObjSid->pSid = pSid;
3125
3126     /* Fill the TRUSTEE structure */
3127     pTrustee->pMultipleTrustee = NULL;
3128     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3129     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3130     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3131     pTrustee->ptstrName = (LPSTR) pObjSid;
3132 }
3133
3134 /******************************************************************************
3135  * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
3136  */
3137 VOID WINAPI BuildTrusteeWithObjectsAndSidW( PTRUSTEEW pTrustee, POBJECTS_AND_SID pObjSid,
3138                                             GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3139 {
3140     DWORD ObjectsPresent = 0;
3141
3142     TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3143
3144     /* Fill the OBJECTS_AND_SID structure */
3145     if (pObjectGuid != NULL)
3146     {
3147         pObjSid->ObjectTypeGuid = *pObjectGuid;
3148         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3149     }
3150     else
3151     {
3152         ZeroMemory(&pObjSid->ObjectTypeGuid,
3153                    sizeof(GUID));
3154     }
3155
3156     if (pInheritedObjectGuid != NULL)
3157     {
3158         pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3159         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3160     }
3161     else
3162     {
3163         ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3164                    sizeof(GUID));
3165     }
3166
3167     pObjSid->ObjectsPresent = ObjectsPresent;
3168     pObjSid->pSid = pSid;
3169
3170     /* Fill the TRUSTEE structure */
3171     pTrustee->pMultipleTrustee = NULL;
3172     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3173     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3174     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3175     pTrustee->ptstrName = (LPWSTR) pObjSid;
3176 }
3177
3178 /******************************************************************************
3179  * BuildTrusteeWithSidA [ADVAPI32.@]
3180  */
3181 VOID WINAPI BuildTrusteeWithSidA(PTRUSTEEA 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  * BuildTrusteeWithSidW [ADVAPI32.@]
3194  */
3195 VOID WINAPI BuildTrusteeWithSidW(PTRUSTEEW pTrustee, PSID pSid)
3196 {
3197     TRACE("%p %p\n", pTrustee, pSid);
3198
3199     pTrustee->pMultipleTrustee = NULL;
3200     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3201     pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3202     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3203     pTrustee->ptstrName = pSid;
3204 }
3205
3206 /******************************************************************************
3207  * BuildTrusteeWithNameA [ADVAPI32.@]
3208  */
3209 VOID WINAPI BuildTrusteeWithNameA(PTRUSTEEA pTrustee, LPSTR name)
3210 {
3211     TRACE("%p %s\n", pTrustee, debugstr_a(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  * BuildTrusteeWithNameW [ADVAPI32.@]
3222  */
3223 VOID WINAPI BuildTrusteeWithNameW(PTRUSTEEW pTrustee, LPWSTR name)
3224 {
3225     TRACE("%p %s\n", pTrustee, debugstr_w(name) );
3226
3227     pTrustee->pMultipleTrustee = NULL;
3228     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3229     pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3230     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3231     pTrustee->ptstrName = name;
3232 }
3233
3234 /****************************************************************************** 
3235  * GetTrusteeFormA [ADVAPI32.@] 
3236  */ 
3237 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee) 
3238 {  
3239     TRACE("(%p)\n", pTrustee); 
3240   
3241     if (!pTrustee) 
3242         return TRUSTEE_BAD_FORM; 
3243   
3244     return pTrustee->TrusteeForm; 
3245 }  
3246   
3247 /****************************************************************************** 
3248  * GetTrusteeFormW [ADVAPI32.@] 
3249  */ 
3250 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee) 
3251 {  
3252     TRACE("(%p)\n", pTrustee); 
3253   
3254     if (!pTrustee) 
3255         return TRUSTEE_BAD_FORM; 
3256   
3257     return pTrustee->TrusteeForm; 
3258 }  
3259   
3260 /****************************************************************************** 
3261  * GetTrusteeNameA [ADVAPI32.@] 
3262  */ 
3263 LPSTR WINAPI GetTrusteeNameA(PTRUSTEEA pTrustee) 
3264 {  
3265     TRACE("(%p)\n", pTrustee); 
3266   
3267     if (!pTrustee) 
3268         return NULL; 
3269   
3270     return pTrustee->ptstrName; 
3271 }  
3272   
3273 /****************************************************************************** 
3274  * GetTrusteeNameW [ADVAPI32.@] 
3275  */ 
3276 LPWSTR WINAPI GetTrusteeNameW(PTRUSTEEW pTrustee) 
3277 {  
3278     TRACE("(%p)\n", pTrustee); 
3279   
3280     if (!pTrustee) 
3281         return NULL; 
3282   
3283     return pTrustee->ptstrName; 
3284 }  
3285   
3286 /****************************************************************************** 
3287  * GetTrusteeTypeA [ADVAPI32.@] 
3288  */ 
3289 TRUSTEE_TYPE WINAPI GetTrusteeTypeA(PTRUSTEEA pTrustee) 
3290 {  
3291     TRACE("(%p)\n", pTrustee); 
3292   
3293     if (!pTrustee) 
3294         return TRUSTEE_IS_UNKNOWN; 
3295   
3296     return pTrustee->TrusteeType; 
3297 }  
3298   
3299 /****************************************************************************** 
3300  * GetTrusteeTypeW [ADVAPI32.@] 
3301  */ 
3302 TRUSTEE_TYPE WINAPI GetTrusteeTypeW(PTRUSTEEW pTrustee) 
3303 {  
3304     TRACE("(%p)\n", pTrustee); 
3305   
3306     if (!pTrustee) 
3307         return TRUSTEE_IS_UNKNOWN; 
3308   
3309     return pTrustee->TrusteeType; 
3310
3311  
3312 BOOL WINAPI SetAclInformation( PACL pAcl, LPVOID pAclInformation,
3313                                DWORD nAclInformationLength,
3314                                ACL_INFORMATION_CLASS dwAclInformationClass )
3315 {
3316     FIXME("%p %p 0x%08x 0x%08x - stub\n", pAcl, pAclInformation,
3317           nAclInformationLength, dwAclInformationClass);
3318
3319     return TRUE;
3320 }
3321
3322 /******************************************************************************
3323  * SetEntriesInAclA [ADVAPI32.@]
3324  */
3325 DWORD WINAPI SetEntriesInAclA( ULONG count, PEXPLICIT_ACCESSA pEntries,
3326                                PACL OldAcl, PACL* NewAcl )
3327 {
3328     FIXME("%d %p %p %p\n",count,pEntries,OldAcl,NewAcl);
3329     if (NewAcl)
3330          *NewAcl = NULL;
3331     return ERROR_SUCCESS;
3332 }
3333
3334 /******************************************************************************
3335  * SetEntriesInAclW [ADVAPI32.@]
3336  */
3337 DWORD WINAPI SetEntriesInAclW( ULONG count, PEXPLICIT_ACCESSW pEntries,
3338                                PACL OldAcl, PACL* NewAcl )
3339 {
3340     ULONG i;
3341     PSID *ppsid;
3342     DWORD ret = ERROR_SUCCESS;
3343     DWORD acl_size = sizeof(ACL);
3344     NTSTATUS status;
3345
3346     TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
3347
3348     *NewAcl = NULL;
3349
3350     if (!count && !OldAcl)
3351         return ERROR_SUCCESS;
3352
3353     /* allocate array of maximum sized sids allowed */
3354     ppsid = HeapAlloc(GetProcessHeap(), 0, count * (sizeof(SID *) + FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES])));
3355     if (!ppsid)
3356         return ERROR_OUTOFMEMORY;
3357
3358     for (i = 0; i < count; i++)
3359     {
3360         ppsid[i] = (char *)&ppsid[count] + i * FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3361
3362         TRACE("[%d]:\n\tgrfAccessPermissions = 0x%x\n\tgrfAccessMode = %d\n\tgrfInheritance = 0x%x\n\t"
3363               "Trustee.pMultipleTrustee = %p\n\tMultipleTrusteeOperation = %d\n\tTrusteeForm = %d\n\t"
3364               "Trustee.TrusteeType = %d\n\tptstrName = %p\n", i,
3365               pEntries[i].grfAccessPermissions, pEntries[i].grfAccessMode, pEntries[i].grfInheritance,
3366               pEntries[i].Trustee.pMultipleTrustee, pEntries[i].Trustee.MultipleTrusteeOperation,
3367               pEntries[i].Trustee.TrusteeForm, pEntries[i].Trustee.TrusteeType,
3368               pEntries[i].Trustee.ptstrName);
3369
3370         if (pEntries[i].Trustee.MultipleTrusteeOperation != NO_MULTIPLE_TRUSTEE)
3371         {
3372             WARN("bad multiple trustee operation %d for trustee %d\n", pEntries[i].Trustee.MultipleTrusteeOperation, i);
3373             ret = ERROR_INVALID_PARAMETER;
3374             goto exit;
3375         }
3376
3377         switch (pEntries[i].Trustee.TrusteeForm)
3378         {
3379         case TRUSTEE_IS_SID:
3380             if (!CopySid(FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]),
3381                          ppsid[i], pEntries[i].Trustee.ptstrName))
3382             {
3383                 WARN("bad sid %p for trustee %d\n", pEntries[i].Trustee.ptstrName, i);
3384                 ret = ERROR_INVALID_PARAMETER;
3385                 goto exit;
3386             }
3387             break;
3388         case TRUSTEE_IS_NAME:
3389         {
3390             DWORD sid_size = FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3391             DWORD domain_size = MAX_COMPUTERNAME_LENGTH + 1;
3392             SID_NAME_USE use;
3393             if (!LookupAccountNameW(NULL, pEntries[i].Trustee.ptstrName, ppsid[i], &sid_size, NULL, &domain_size, &use))
3394             {
3395                 WARN("bad user name %s for trustee %d\n", debugstr_w(pEntries[i].Trustee.ptstrName), i);
3396                 ret = ERROR_INVALID_PARAMETER;
3397                 goto exit;
3398             }
3399             break;
3400         }
3401         case TRUSTEE_IS_OBJECTS_AND_SID:
3402             FIXME("TRUSTEE_IS_OBJECTS_AND_SID unimplemented\n");
3403             break;
3404         case TRUSTEE_IS_OBJECTS_AND_NAME:
3405             FIXME("TRUSTEE_IS_OBJECTS_AND_NAME unimplemented\n");
3406             break;
3407         default:
3408             WARN("bad trustee form %d for trustee %d\n", pEntries[i].Trustee.TrusteeForm, i);
3409             ret = ERROR_INVALID_PARAMETER;
3410             goto exit;
3411         }
3412
3413         /* Note: we overestimate the ACL size here as a tradeoff between
3414          * instructions (simplicity) and memory */
3415         switch (pEntries[i].grfAccessMode)
3416         {
3417         case GRANT_ACCESS:
3418         case SET_ACCESS:
3419             acl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3420             break;
3421         case DENY_ACCESS:
3422             acl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3423             break;
3424         case SET_AUDIT_SUCCESS:
3425         case SET_AUDIT_FAILURE:
3426             acl_size += FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart) + GetLengthSid(ppsid[i]);
3427             break;
3428         case REVOKE_ACCESS:
3429             break;
3430         default:
3431             WARN("bad access mode %d for trustee %d\n", pEntries[i].grfAccessMode, i);
3432             ret = ERROR_INVALID_PARAMETER;
3433             goto exit;
3434         }
3435     }
3436
3437     if (OldAcl)
3438     {
3439         ACL_SIZE_INFORMATION size_info;
3440
3441         status = RtlQueryInformationAcl(OldAcl, &size_info, sizeof(size_info), AclSizeInformation);
3442         if (status != STATUS_SUCCESS)
3443         {
3444             ret = RtlNtStatusToDosError(status);
3445             goto exit;
3446         }
3447         acl_size += size_info.AclBytesInUse - sizeof(ACL);
3448     }
3449
3450     *NewAcl = LocalAlloc(0, acl_size);
3451     if (!*NewAcl)
3452     {
3453         ret = ERROR_OUTOFMEMORY;
3454         goto exit;
3455     }
3456
3457     status = RtlCreateAcl( *NewAcl, acl_size, ACL_REVISION );
3458     if (status != STATUS_SUCCESS)
3459     {
3460         ret = RtlNtStatusToDosError(status);
3461         goto exit;
3462     }
3463
3464     for (i = 0; i < count; i++)
3465     {
3466         switch (pEntries[i].grfAccessMode)
3467         {
3468         case GRANT_ACCESS:
3469             status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3470                                               pEntries[i].grfInheritance,
3471                                               pEntries[i].grfAccessPermissions,
3472                                               ppsid[i]);
3473             break;
3474         case SET_ACCESS:
3475         {
3476             ULONG j;
3477             BOOL add = TRUE;
3478             if (OldAcl)
3479             {
3480                 for (j = 0; ; j++)
3481                 {
3482                     const ACE_HEADER *existing_ace_header;
3483                     status = RtlGetAce(OldAcl, j, (LPVOID *)&existing_ace_header);
3484                     if (status != STATUS_SUCCESS)
3485                         break;
3486                     if (pEntries[i].grfAccessMode == SET_ACCESS &&
3487                         existing_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3488                         EqualSid(ppsid[i], &((ACCESS_ALLOWED_ACE *)existing_ace_header)->SidStart))
3489                     {
3490                         add = FALSE;
3491                         break;
3492                     }
3493                 }
3494             }
3495             if (add)
3496                 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3497                                                   pEntries[i].grfInheritance,
3498                                                   pEntries[i].grfAccessPermissions,
3499                                                   ppsid[i]);
3500             break;
3501         }
3502         case DENY_ACCESS:
3503             status = RtlAddAccessDeniedAceEx(*NewAcl, ACL_REVISION,
3504                                              pEntries[i].grfInheritance,
3505                                              pEntries[i].grfAccessPermissions,
3506                                              ppsid[i]);
3507             break;
3508         case SET_AUDIT_SUCCESS:
3509             status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3510                                             pEntries[i].grfInheritance,
3511                                             pEntries[i].grfAccessPermissions,
3512                                             ppsid[i], TRUE, FALSE);
3513             break;
3514         case SET_AUDIT_FAILURE:
3515             status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3516                                             pEntries[i].grfInheritance,
3517                                             pEntries[i].grfAccessPermissions,
3518                                             ppsid[i], FALSE, TRUE);
3519             break;
3520         default:
3521             FIXME("unhandled access mode %d\n", pEntries[i].grfAccessMode);
3522         }
3523     }
3524
3525     if (OldAcl)
3526     {
3527         for (i = 0; ; i++)
3528         {
3529             BOOL add = TRUE;
3530             ULONG j;
3531             const ACE_HEADER *old_ace_header;
3532             status = RtlGetAce(OldAcl, i, (LPVOID *)&old_ace_header);
3533             if (status != STATUS_SUCCESS) break;
3534             for (j = 0; j < count; j++)
3535             {
3536                 if (pEntries[j].grfAccessMode == SET_ACCESS &&
3537                     old_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3538                     EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3539                 {
3540                     status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION, pEntries[j].grfInheritance, pEntries[j].grfAccessPermissions, ppsid[j]);
3541                     add = FALSE;
3542                     break;
3543                 }
3544                 else if (pEntries[j].grfAccessMode == REVOKE_ACCESS)
3545                 {
3546                     switch (old_ace_header->AceType)
3547                     {
3548                     case ACCESS_ALLOWED_ACE_TYPE:
3549                         if (EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3550                             add = FALSE;
3551                         break;
3552                     case ACCESS_DENIED_ACE_TYPE:
3553                         if (EqualSid(ppsid[j], &((ACCESS_DENIED_ACE *)old_ace_header)->SidStart))
3554                             add = FALSE;
3555                         break;
3556                     case SYSTEM_AUDIT_ACE_TYPE:
3557                         if (EqualSid(ppsid[j], &((SYSTEM_AUDIT_ACE *)old_ace_header)->SidStart))
3558                             add = FALSE;
3559                         break;
3560                     case SYSTEM_ALARM_ACE_TYPE:
3561                         if (EqualSid(ppsid[j], &((SYSTEM_ALARM_ACE *)old_ace_header)->SidStart))
3562                             add = FALSE;
3563                         break;
3564                     default:
3565                         FIXME("unhandled ace type %d\n", old_ace_header->AceType);
3566                     }
3567
3568                     if (!add)
3569                         break;
3570                 }
3571             }
3572             if (add)
3573                 status = RtlAddAce(*NewAcl, ACL_REVISION, 1, (PACE_HEADER)old_ace_header, old_ace_header->AceSize);
3574             if (status != STATUS_SUCCESS)
3575             {
3576                 WARN("RtlAddAce failed with error 0x%08x\n", status);
3577                 ret = RtlNtStatusToDosError(status);
3578                 break;
3579             }
3580         }
3581     }
3582
3583 exit:
3584     HeapFree(GetProcessHeap(), 0, ppsid);
3585     return ret;
3586 }
3587
3588 /******************************************************************************
3589  * SetNamedSecurityInfoA [ADVAPI32.@]
3590  */
3591 DWORD WINAPI SetNamedSecurityInfoA(LPSTR pObjectName,
3592         SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
3593         PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
3594 {
3595     DWORD len;
3596     LPWSTR wstr = NULL;
3597     DWORD r;
3598
3599     TRACE("%s %d %d %p %p %p %p\n", debugstr_a(pObjectName), ObjectType,
3600            SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
3601
3602     if( pObjectName )
3603     {
3604         len = MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, NULL, 0 );
3605         wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR));
3606         MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, wstr, len );
3607     }
3608
3609     r = SetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, psidOwner,
3610                            psidGroup, pDacl, pSacl );
3611
3612     HeapFree( GetProcessHeap(), 0, wstr );
3613
3614     return r;
3615 }
3616
3617 BOOL WINAPI SetPrivateObjectSecurity( SECURITY_INFORMATION SecurityInformation,
3618     PSECURITY_DESCRIPTOR ModificationDescriptor,
3619     PSECURITY_DESCRIPTOR* ObjectsSecurityDescriptor,
3620     PGENERIC_MAPPING GenericMapping,
3621     HANDLE Token )
3622 {
3623     FIXME("0x%08x %p %p %p %p - stub\n", SecurityInformation, ModificationDescriptor,
3624           ObjectsSecurityDescriptor, GenericMapping, Token);
3625
3626     return TRUE;
3627 }
3628
3629 BOOL WINAPI AreAllAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
3630 {
3631     return RtlAreAllAccessesGranted( GrantedAccess, DesiredAccess );
3632 }
3633
3634 /******************************************************************************
3635  * AreAnyAccessesGranted [ADVAPI32.@]
3636  *
3637  * Determines whether or not any of a set of specified access permissions have
3638  * been granted or not.
3639  *
3640  * PARAMS
3641  *   GrantedAccess [I] The permissions that have been granted.
3642  *   DesiredAccess [I] The permissions that you want to have.
3643  *
3644  * RETURNS
3645  *   Nonzero if any of the permissions have been granted, zero if none of the
3646  *   permissions have been granted.
3647  */
3648
3649 BOOL WINAPI AreAnyAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
3650 {
3651     return RtlAreAnyAccessesGranted( GrantedAccess, DesiredAccess );
3652 }
3653
3654 /******************************************************************************
3655  * SetNamedSecurityInfoW [ADVAPI32.@]
3656  */
3657 DWORD WINAPI SetNamedSecurityInfoW(LPWSTR pObjectName,
3658         SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
3659         PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
3660 {
3661     FIXME("%s %d %d %p %p %p %p\n", debugstr_w(pObjectName), ObjectType,
3662            SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
3663     return ERROR_SUCCESS;
3664 }
3665
3666 /******************************************************************************
3667  * GetExplicitEntriesFromAclA [ADVAPI32.@]
3668  */
3669 DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntries,
3670         PEXPLICIT_ACCESSA* pListOfExplicitEntries)
3671 {
3672     FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
3673     return ERROR_CALL_NOT_IMPLEMENTED;
3674 }
3675
3676 /******************************************************************************
3677  * GetExplicitEntriesFromAclW [ADVAPI32.@]
3678  */
3679 DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG pcCountOfExplicitEntries,
3680         PEXPLICIT_ACCESSW* pListOfExplicitEntries)
3681 {
3682     FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
3683     return ERROR_CALL_NOT_IMPLEMENTED;
3684 }
3685
3686 /******************************************************************************
3687  * GetAuditedPermissionsFromAclA [ADVAPI32.@]
3688  */
3689 DWORD WINAPI GetAuditedPermissionsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
3690         PACCESS_MASK pFailedAuditRights)
3691 {
3692     FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
3693     return ERROR_CALL_NOT_IMPLEMENTED;
3694
3695 }
3696
3697 /******************************************************************************
3698  * GetAuditedPermissionsFromAclW [ADVAPI32.@]
3699  */
3700 DWORD WINAPI GetAuditedPermissionsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
3701         PACCESS_MASK pFailedAuditRights)
3702 {
3703     FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
3704     return ERROR_CALL_NOT_IMPLEMENTED;
3705
3706 }
3707
3708 /******************************************************************************
3709  * ParseAclStringFlags
3710  */
3711 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
3712 {
3713     DWORD flags = 0;
3714     LPCWSTR szAcl = *StringAcl;
3715
3716     while (*szAcl != '(')
3717     {
3718         if (*szAcl == 'P')
3719         {
3720             flags |= SE_DACL_PROTECTED;
3721         }
3722         else if (*szAcl == 'A')
3723         {
3724             szAcl++;
3725             if (*szAcl == 'R')
3726                 flags |= SE_DACL_AUTO_INHERIT_REQ;
3727             else if (*szAcl == 'I')
3728                 flags |= SE_DACL_AUTO_INHERITED;
3729         }
3730         szAcl++;
3731     }
3732
3733     *StringAcl = szAcl;
3734     return flags;
3735 }
3736
3737 /******************************************************************************
3738  * ParseAceStringType
3739  */
3740 static const ACEFLAG AceType[] =
3741 {
3742     { SDDL_ALARM,          SYSTEM_ALARM_ACE_TYPE },
3743     { SDDL_AUDIT,          SYSTEM_AUDIT_ACE_TYPE },
3744     { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
3745     { SDDL_ACCESS_DENIED,  ACCESS_DENIED_ACE_TYPE },
3746     /*
3747     { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
3748     { SDDL_OBJECT_ACCESS_DENIED,  ACCESS_DENIED_OBJECT_ACE_TYPE },
3749     { SDDL_OBJECT_ALARM,          SYSTEM_ALARM_OBJECT_ACE_TYPE },
3750     { SDDL_OBJECT_AUDIT,          SYSTEM_AUDIT_OBJECT_ACE_TYPE },
3751     */
3752     { NULL, 0 },
3753 };
3754
3755 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
3756 {
3757     UINT len = 0;
3758     LPCWSTR szAcl = *StringAcl;
3759     const ACEFLAG *lpaf = AceType;
3760
3761     while (lpaf->wstr &&
3762         (len = strlenW(lpaf->wstr)) &&
3763         strncmpW(lpaf->wstr, szAcl, len))
3764         lpaf++;
3765
3766     if (!lpaf->wstr)
3767         return 0;
3768
3769     *StringAcl += len;
3770     return lpaf->value;
3771 }
3772
3773
3774 /******************************************************************************
3775  * ParseAceStringFlags
3776  */
3777 static const ACEFLAG AceFlags[] =
3778 {
3779     { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
3780     { SDDL_AUDIT_FAILURE,     FAILED_ACCESS_ACE_FLAG },
3781     { SDDL_INHERITED,         INHERITED_ACE },
3782     { SDDL_INHERIT_ONLY,      INHERIT_ONLY_ACE },
3783     { SDDL_NO_PROPAGATE,      NO_PROPAGATE_INHERIT_ACE },
3784     { SDDL_OBJECT_INHERIT,    OBJECT_INHERIT_ACE },
3785     { SDDL_AUDIT_SUCCESS,     SUCCESSFUL_ACCESS_ACE_FLAG },
3786     { NULL, 0 },
3787 };
3788
3789 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
3790 {
3791     UINT len = 0;
3792     BYTE flags = 0;
3793     LPCWSTR szAcl = *StringAcl;
3794
3795     while (*szAcl != ';')
3796     {
3797         const ACEFLAG *lpaf = AceFlags;
3798
3799         while (lpaf->wstr &&
3800                (len = strlenW(lpaf->wstr)) &&
3801                strncmpW(lpaf->wstr, szAcl, len))
3802             lpaf++;
3803
3804         if (!lpaf->wstr)
3805             return 0;
3806
3807         flags |= lpaf->value;
3808         szAcl += len;
3809     }
3810
3811     *StringAcl = szAcl;
3812     return flags;
3813 }
3814
3815
3816 /******************************************************************************
3817  * ParseAceStringRights
3818  */
3819 static const ACEFLAG AceRights[] =
3820 {
3821     { SDDL_GENERIC_ALL,     GENERIC_ALL },
3822     { SDDL_GENERIC_READ,    GENERIC_READ },
3823     { SDDL_GENERIC_WRITE,   GENERIC_WRITE },
3824     { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
3825
3826     { SDDL_READ_CONTROL,    READ_CONTROL },
3827     { SDDL_STANDARD_DELETE, DELETE },
3828     { SDDL_WRITE_DAC,       WRITE_DAC },
3829     { SDDL_WRITE_OWNER,     WRITE_OWNER },
3830
3831     { SDDL_READ_PROPERTY,   ADS_RIGHT_DS_READ_PROP},
3832     { SDDL_WRITE_PROPERTY,  ADS_RIGHT_DS_WRITE_PROP},
3833     { SDDL_CREATE_CHILD,    ADS_RIGHT_DS_CREATE_CHILD},
3834     { SDDL_DELETE_CHILD,    ADS_RIGHT_DS_DELETE_CHILD},
3835     { SDDL_LIST_CHILDREN,   ADS_RIGHT_ACTRL_DS_LIST},
3836     { SDDL_SELF_WRITE,      ADS_RIGHT_DS_SELF},
3837     { SDDL_LIST_OBJECT,     ADS_RIGHT_DS_LIST_OBJECT},
3838     { SDDL_DELETE_TREE,     ADS_RIGHT_DS_DELETE_TREE},
3839     { SDDL_CONTROL_ACCESS,  ADS_RIGHT_DS_CONTROL_ACCESS},
3840
3841     { SDDL_FILE_ALL,        FILE_ALL_ACCESS },
3842     { SDDL_FILE_READ,       FILE_GENERIC_READ },
3843     { SDDL_FILE_WRITE,      FILE_GENERIC_WRITE },
3844     { SDDL_FILE_EXECUTE,    FILE_GENERIC_EXECUTE },
3845
3846     { SDDL_KEY_ALL,         KEY_ALL_ACCESS },
3847     { SDDL_KEY_READ,        KEY_READ },
3848     { SDDL_KEY_WRITE,       KEY_WRITE },
3849     { SDDL_KEY_EXECUTE,     KEY_EXECUTE },
3850     { NULL, 0 },
3851 };
3852
3853 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
3854 {
3855     UINT len = 0;
3856     DWORD rights = 0;
3857     LPCWSTR szAcl = *StringAcl;
3858
3859     if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
3860     {
3861         LPCWSTR p = szAcl;
3862
3863         while (*p && *p != ';')
3864             p++;
3865
3866         if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
3867         {
3868             rights = strtoulW(szAcl, NULL, 16);
3869             szAcl = p;
3870         }
3871         else
3872             WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
3873     }
3874     else
3875     {
3876         while (*szAcl != ';')
3877         {
3878             const ACEFLAG *lpaf = AceRights;
3879
3880             while (lpaf->wstr &&
3881                (len = strlenW(lpaf->wstr)) &&
3882                strncmpW(lpaf->wstr, szAcl, len))
3883             {
3884                lpaf++;
3885             }
3886
3887             if (!lpaf->wstr)
3888                 return 0;
3889
3890             rights |= lpaf->value;
3891             szAcl += len;
3892         }
3893     }
3894
3895     *StringAcl = szAcl;
3896     return rights;
3897 }
3898
3899
3900 /******************************************************************************
3901  * ParseStringAclToAcl
3902  * 
3903  * dacl_flags(string_ace1)(string_ace2)... (string_acen) 
3904  */
3905 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags, 
3906     PACL pAcl, LPDWORD cBytes)
3907 {
3908     DWORD val;
3909     DWORD sidlen;
3910     DWORD length = sizeof(ACL);
3911     DWORD acesize = 0;
3912     DWORD acecount = 0;
3913     PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
3914
3915     TRACE("%s\n", debugstr_w(StringAcl));
3916
3917     if (!StringAcl)
3918         return FALSE;
3919
3920     if (pAcl) /* pAce is only useful if we're setting values */
3921         pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
3922
3923     /* Parse ACL flags */
3924     *lpdwFlags = ParseAclStringFlags(&StringAcl);
3925
3926     /* Parse ACE */
3927     while (*StringAcl == '(')
3928     {
3929         StringAcl++;
3930
3931         /* Parse ACE type */
3932         val = ParseAceStringType(&StringAcl);
3933         if (pAce)
3934             pAce->Header.AceType = (BYTE) val;
3935         if (*StringAcl != ';')
3936             goto lerr;
3937         StringAcl++;
3938
3939         /* Parse ACE flags */
3940         val = ParseAceStringFlags(&StringAcl);
3941         if (pAce)
3942             pAce->Header.AceFlags = (BYTE) val;
3943         if (*StringAcl != ';')
3944             goto lerr;
3945         StringAcl++;
3946
3947         /* Parse ACE rights */
3948         val = ParseAceStringRights(&StringAcl);
3949         if (pAce)
3950             pAce->Mask = val;
3951         if (*StringAcl != ';')
3952             goto lerr;
3953         StringAcl++;
3954
3955         /* Parse ACE object guid */
3956         if (*StringAcl != ';')
3957         {
3958             FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
3959             goto lerr;
3960         }
3961         StringAcl++;
3962
3963         /* Parse ACE inherit object guid */
3964         if (*StringAcl != ';')
3965         {
3966             FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
3967             goto lerr;
3968         }
3969         StringAcl++;
3970
3971         /* Parse ACE account sid */
3972         if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
3973         {
3974             while (*StringAcl && *StringAcl != ')')
3975                 StringAcl++;
3976         }
3977
3978         if (*StringAcl != ')')
3979             goto lerr;
3980         StringAcl++;
3981
3982         acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
3983         length += acesize;
3984         if (pAce)
3985         {
3986             pAce->Header.AceSize = acesize;
3987             pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
3988         }
3989         acecount++;
3990     }
3991
3992     *cBytes = length;
3993
3994     if (length > 0xffff)
3995     {
3996         ERR("ACL too large\n");
3997         goto lerr;
3998     }
3999
4000     if (pAcl)
4001     {
4002         pAcl->AclRevision = ACL_REVISION;
4003         pAcl->Sbz1 = 0;
4004         pAcl->AclSize = length;
4005         pAcl->AceCount = acecount++;
4006         pAcl->Sbz2 = 0;
4007     }
4008     return TRUE;
4009
4010 lerr:
4011     SetLastError(ERROR_INVALID_ACL);
4012     WARN("Invalid ACE string format\n");
4013     return FALSE;
4014 }
4015
4016
4017 /******************************************************************************
4018  * ParseStringSecurityDescriptorToSecurityDescriptor
4019  */
4020 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
4021     LPCWSTR StringSecurityDescriptor,
4022     SECURITY_DESCRIPTOR* SecurityDescriptor,
4023     LPDWORD cBytes)
4024 {
4025     BOOL bret = FALSE;
4026     WCHAR toktype;
4027     WCHAR tok[MAX_PATH];
4028     LPCWSTR lptoken;
4029     LPBYTE lpNext = NULL;
4030     DWORD len;
4031
4032     *cBytes = sizeof(SECURITY_DESCRIPTOR);
4033
4034     if (SecurityDescriptor)
4035         lpNext = ((LPBYTE) SecurityDescriptor) + sizeof(SECURITY_DESCRIPTOR);
4036
4037     while (*StringSecurityDescriptor)
4038     {
4039         toktype = *StringSecurityDescriptor;
4040
4041         /* Expect char identifier followed by ':' */
4042         StringSecurityDescriptor++;
4043         if (*StringSecurityDescriptor != ':')
4044         {
4045             SetLastError(ERROR_INVALID_PARAMETER);
4046             goto lend;
4047         }
4048         StringSecurityDescriptor++;
4049
4050         /* Extract token */
4051         lptoken = StringSecurityDescriptor;
4052         while (*lptoken && *lptoken != ':')
4053             lptoken++;
4054
4055         if (*lptoken)
4056             lptoken--;
4057
4058         len = lptoken - StringSecurityDescriptor;
4059         memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
4060         tok[len] = 0;
4061
4062         switch (toktype)
4063         {
4064             case 'O':
4065             {
4066                 DWORD bytes;
4067
4068                 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4069                     goto lend;
4070
4071                 if (SecurityDescriptor)
4072                 {
4073                     SecurityDescriptor->Owner = (PSID)(lpNext - (LPBYTE)SecurityDescriptor);
4074                     lpNext += bytes; /* Advance to next token */
4075                 }
4076
4077                 *cBytes += bytes;
4078
4079                 break;
4080             }
4081
4082             case 'G':
4083             {
4084                 DWORD bytes;
4085
4086                 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4087                     goto lend;
4088
4089                 if (SecurityDescriptor)
4090                 {
4091                     SecurityDescriptor->Group = (PSID)(lpNext - (LPBYTE)SecurityDescriptor);
4092                     lpNext += bytes; /* Advance to next token */
4093                 }
4094
4095                 *cBytes += bytes;
4096
4097                 break;
4098             }
4099
4100             case 'D':
4101             {
4102                 DWORD flags;
4103                 DWORD bytes;
4104
4105                 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4106                     goto lend;
4107
4108                 if (SecurityDescriptor)
4109                 {
4110                     SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
4111                     SecurityDescriptor->Dacl = (PACL)(lpNext - (LPBYTE)SecurityDescriptor);
4112                     lpNext += bytes; /* Advance to next token */
4113                 }
4114
4115                 *cBytes += bytes;
4116
4117                 break;
4118             }
4119
4120             case 'S':
4121             {
4122                 DWORD flags;
4123                 DWORD bytes;
4124
4125                 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4126                     goto lend;
4127
4128                 if (SecurityDescriptor)
4129                 {
4130                     SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
4131                     SecurityDescriptor->Sacl = (PACL)(lpNext - (LPBYTE)SecurityDescriptor);
4132                     lpNext += bytes; /* Advance to next token */
4133                 }
4134
4135                 *cBytes += bytes;
4136
4137                 break;
4138             }
4139
4140             default:
4141                 FIXME("Unknown token\n");
4142                 SetLastError(ERROR_INVALID_PARAMETER);
4143                 goto lend;
4144         }
4145
4146         StringSecurityDescriptor = lptoken;
4147     }
4148
4149     bret = TRUE;
4150
4151 lend:
4152     return bret;
4153 }
4154
4155 /******************************************************************************
4156  * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
4157  */
4158 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
4159         LPCSTR StringSecurityDescriptor,
4160         DWORD StringSDRevision,
4161         PSECURITY_DESCRIPTOR* SecurityDescriptor,
4162         PULONG SecurityDescriptorSize)
4163 {
4164     UINT len;
4165     BOOL ret = FALSE;
4166     LPWSTR StringSecurityDescriptorW;
4167
4168     len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
4169     StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
4170
4171     if (StringSecurityDescriptorW)
4172     {
4173         MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
4174
4175         ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
4176                                                                    StringSDRevision, SecurityDescriptor,
4177                                                                    SecurityDescriptorSize);
4178         HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
4179     }
4180
4181     return ret;
4182 }
4183
4184 /******************************************************************************
4185  * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
4186  */
4187 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
4188         LPCWSTR StringSecurityDescriptor,
4189         DWORD StringSDRevision,
4190         PSECURITY_DESCRIPTOR* SecurityDescriptor,
4191         PULONG SecurityDescriptorSize)
4192 {
4193     DWORD cBytes;
4194     SECURITY_DESCRIPTOR* psd;
4195     BOOL bret = FALSE;
4196
4197     TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
4198
4199     if (GetVersion() & 0x80000000)
4200     {
4201         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4202         goto lend;
4203     }
4204     else if (!StringSecurityDescriptor || !SecurityDescriptor)
4205     {
4206         SetLastError(ERROR_INVALID_PARAMETER);
4207         goto lend;
4208     }
4209     else if (StringSDRevision != SID_REVISION)
4210     {
4211         SetLastError(ERROR_UNKNOWN_REVISION);
4212         goto lend;
4213     }
4214
4215     /* Compute security descriptor length */
4216     if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4217         NULL, &cBytes))
4218         goto lend;
4219
4220     psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
4221     if (!psd) goto lend;
4222
4223     psd->Revision = SID_REVISION;
4224     psd->Control |= SE_SELF_RELATIVE;
4225
4226     if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4227         psd, &cBytes))
4228     {
4229         LocalFree(psd);
4230         goto lend;
4231     }
4232
4233     if (SecurityDescriptorSize)
4234         *SecurityDescriptorSize = cBytes;
4235
4236     bret = TRUE;
4237  
4238 lend:
4239     TRACE(" ret=%d\n", bret);
4240     return bret;
4241 }
4242
4243 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
4244 {
4245     if (cch == -1)
4246         cch = strlenW(string);
4247
4248     if (plen)
4249         *plen += cch;
4250
4251     if (pwptr)
4252     {
4253         memcpy(*pwptr, string, sizeof(WCHAR)*cch);
4254         *pwptr += cch;
4255     }
4256 }
4257
4258 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
4259 {
4260     DWORD i;
4261     WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
4262     WCHAR subauthfmt[] = { '-','%','u',0 };
4263     WCHAR buf[26];
4264     SID *pisid = psid;
4265
4266     if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
4267     {
4268         SetLastError(ERROR_INVALID_SID);
4269         return FALSE;
4270     }
4271
4272     if (pisid->IdentifierAuthority.Value[0] ||
4273      pisid->IdentifierAuthority.Value[1])
4274     {
4275         FIXME("not matching MS' bugs\n");
4276         SetLastError(ERROR_INVALID_SID);
4277         return FALSE;
4278     }
4279
4280     sprintfW( buf, fmt, pisid->Revision,
4281         MAKELONG(
4282             MAKEWORD( pisid->IdentifierAuthority.Value[5],
4283                     pisid->IdentifierAuthority.Value[4] ),
4284             MAKEWORD( pisid->IdentifierAuthority.Value[3],
4285                     pisid->IdentifierAuthority.Value[2] )
4286         ) );
4287     DumpString(buf, -1, pwptr, plen);
4288
4289     for( i=0; i<pisid->SubAuthorityCount; i++ )
4290     {
4291         sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
4292         DumpString(buf, -1, pwptr, plen);
4293     }
4294     return TRUE;
4295 }
4296
4297 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
4298 {
4299     size_t i;
4300     for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
4301     {
4302         if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
4303         {
4304             DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
4305             return TRUE;
4306         }
4307     }
4308
4309     return DumpSidNumeric(psid, pwptr, plen);
4310 }
4311
4312 static const LPCWSTR AceRightBitNames[32] = {
4313         SDDL_CREATE_CHILD,        /*  0 */
4314         SDDL_DELETE_CHILD,
4315         SDDL_LIST_CHILDREN,
4316         SDDL_SELF_WRITE,
4317         SDDL_READ_PROPERTY,       /*  4 */
4318         SDDL_WRITE_PROPERTY,
4319         SDDL_DELETE_TREE,
4320         SDDL_LIST_OBJECT,
4321         SDDL_CONTROL_ACCESS,      /*  8 */
4322         NULL,
4323         NULL,
4324         NULL,
4325         NULL,                     /* 12 */
4326         NULL,
4327         NULL,
4328         NULL,
4329         SDDL_STANDARD_DELETE,     /* 16 */
4330         SDDL_READ_CONTROL,
4331         SDDL_WRITE_DAC,
4332         SDDL_WRITE_OWNER,
4333         NULL,                     /* 20 */
4334         NULL,
4335         NULL,
4336         NULL,
4337         NULL,                     /* 24 */
4338         NULL,
4339         NULL,
4340         NULL,
4341         SDDL_GENERIC_ALL,         /* 28 */
4342         SDDL_GENERIC_EXECUTE,
4343         SDDL_GENERIC_WRITE,
4344         SDDL_GENERIC_READ
4345 };
4346
4347 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
4348 {
4349     static const WCHAR fmtW[] = {'0','x','%','x',0};
4350     WCHAR buf[15];
4351     size_t i;
4352
4353     if (mask == 0)
4354         return;
4355
4356     /* first check if the right have name */
4357     for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
4358     {
4359         if (AceRights[i].wstr == NULL)
4360             break;
4361         if (mask == AceRights[i].value)
4362         {
4363             DumpString(AceRights[i].wstr, -1, pwptr, plen);
4364             return;
4365         }
4366     }
4367
4368     /* then check if it can be built from bit names */
4369     for (i = 0; i < 32; i++)
4370     {
4371         if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
4372         {
4373             /* can't be built from bit names */
4374             sprintfW(buf, fmtW, mask);
4375             DumpString(buf, -1, pwptr, plen);
4376             return;
4377         }
4378     }
4379
4380     /* build from bit names */
4381     for (i = 0; i < 32; i++)
4382         if (mask & (1 << i))
4383             DumpString(AceRightBitNames[i], -1, pwptr, plen);
4384 }
4385
4386 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
4387 {
4388     ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
4389     static const WCHAR openbr = '(';
4390     static const WCHAR closebr = ')';
4391     static const WCHAR semicolon = ';';
4392
4393     if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
4394     {
4395         SetLastError(ERROR_INVALID_ACL);
4396         return FALSE;
4397     }
4398
4399     piace = pace;
4400     DumpString(&openbr, 1, pwptr, plen);
4401     switch (piace->Header.AceType)
4402     {
4403         case ACCESS_ALLOWED_ACE_TYPE:
4404             DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
4405             break;
4406         case ACCESS_DENIED_ACE_TYPE:
4407             DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
4408             break;
4409         case SYSTEM_AUDIT_ACE_TYPE:
4410             DumpString(SDDL_AUDIT, -1, pwptr, plen);
4411             break;
4412         case SYSTEM_ALARM_ACE_TYPE:
4413             DumpString(SDDL_ALARM, -1, pwptr, plen);
4414             break;
4415     }
4416     DumpString(&semicolon, 1, pwptr, plen);
4417
4418     if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
4419         DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
4420     if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
4421         DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
4422     if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
4423         DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
4424     if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
4425         DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
4426     if (piace->Header.AceFlags & INHERITED_ACE)
4427         DumpString(SDDL_INHERITED, -1, pwptr, plen);
4428     if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
4429         DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
4430     if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
4431         DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
4432     DumpString(&semicolon, 1, pwptr, plen);
4433     DumpRights(piace->Mask, pwptr, plen);
4434     DumpString(&semicolon, 1, pwptr, plen);
4435     /* objects not supported */
4436     DumpString(&semicolon, 1, pwptr, plen);
4437     /* objects not supported */
4438     DumpString(&semicolon, 1, pwptr, plen);
4439     if (!DumpSid(&piace->SidStart, pwptr, plen))
4440         return FALSE;
4441     DumpString(&closebr, 1, pwptr, plen);
4442     return TRUE;
4443 }
4444
4445 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
4446 {
4447     WORD count;
4448     int i;
4449
4450     if (protected)
4451         DumpString(SDDL_PROTECTED, -1, pwptr, plen);
4452     if (autoInheritReq)
4453         DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
4454     if (autoInherited)
4455         DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
4456
4457     if (pacl == NULL)
4458         return TRUE;
4459
4460     if (!IsValidAcl(pacl))
4461         return FALSE;
4462
4463     count = pacl->AceCount;
4464     for (i = 0; i < count; i++)
4465     {
4466         LPVOID ace;
4467         if (!GetAce(pacl, i, &ace))
4468             return FALSE;
4469         if (!DumpAce(ace, pwptr, plen))
4470             return FALSE;
4471     }
4472
4473     return TRUE;
4474 }
4475
4476 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4477 {
4478     static const WCHAR prefix[] = {'O',':',0};
4479     BOOL bDefaulted;
4480     PSID psid;
4481
4482     if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
4483         return FALSE;
4484
4485     if (psid == NULL)
4486         return TRUE;
4487
4488     DumpString(prefix, -1, pwptr, plen);
4489     if (!DumpSid(psid, pwptr, plen))
4490         return FALSE;
4491     return TRUE;
4492 }
4493
4494 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4495 {
4496     static const WCHAR prefix[] = {'G',':',0};
4497     BOOL bDefaulted;
4498     PSID psid;
4499
4500     if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
4501         return FALSE;
4502
4503     if (psid == NULL)
4504         return TRUE;
4505
4506     DumpString(prefix, -1, pwptr, plen);
4507     if (!DumpSid(psid, pwptr, plen))
4508         return FALSE;
4509     return TRUE;
4510 }
4511
4512 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4513 {
4514     static const WCHAR dacl[] = {'D',':',0};
4515     SECURITY_DESCRIPTOR_CONTROL control;
4516     BOOL present, defaulted;
4517     DWORD revision;
4518     PACL pacl;
4519
4520     if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
4521         return FALSE;
4522
4523     if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
4524         return FALSE;
4525
4526     if (!present)
4527         return TRUE;
4528
4529     DumpString(dacl, 2, pwptr, plen);
4530     if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
4531         return FALSE;
4532     return TRUE;
4533 }
4534
4535 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4536 {
4537     static const WCHAR sacl[] = {'S',':',0};
4538     SECURITY_DESCRIPTOR_CONTROL control;
4539     BOOL present, defaulted;
4540     DWORD revision;
4541     PACL pacl;
4542
4543     if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
4544         return FALSE;
4545
4546     if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
4547         return FALSE;
4548
4549     if (!present)
4550         return TRUE;
4551
4552     DumpString(sacl, 2, pwptr, plen);
4553     if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
4554         return FALSE;
4555     return TRUE;
4556 }
4557
4558 /******************************************************************************
4559  * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
4560  */
4561 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen)
4562 {
4563     ULONG len;
4564     WCHAR *wptr, *wstr;
4565
4566     if (SDRevision != SDDL_REVISION_1)
4567     {
4568         ERR("Pogram requested unknown SDDL revision %d\n", SDRevision);
4569         SetLastError(ERROR_UNKNOWN_REVISION);
4570         return FALSE;
4571     }
4572
4573     len = 0;
4574     if (RequestedInformation & OWNER_SECURITY_INFORMATION)
4575         if (!DumpOwner(SecurityDescriptor, NULL, &len))
4576             return FALSE;
4577     if (RequestedInformation & GROUP_SECURITY_INFORMATION)
4578         if (!DumpGroup(SecurityDescriptor, NULL, &len))
4579             return FALSE;
4580     if (RequestedInformation & DACL_SECURITY_INFORMATION)
4581         if (!DumpDacl(SecurityDescriptor, NULL, &len))
4582             return FALSE;
4583     if (RequestedInformation & SACL_SECURITY_INFORMATION)
4584         if (!DumpSacl(SecurityDescriptor, NULL, &len))
4585             return FALSE;
4586
4587     wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
4588     if (RequestedInformation & OWNER_SECURITY_INFORMATION)
4589         if (!DumpOwner(SecurityDescriptor, &wptr, NULL))
4590             return FALSE;
4591     if (RequestedInformation & GROUP_SECURITY_INFORMATION)
4592         if (!DumpGroup(SecurityDescriptor, &wptr, NULL))
4593             return FALSE;
4594     if (RequestedInformation & DACL_SECURITY_INFORMATION)
4595         if (!DumpDacl(SecurityDescriptor, &wptr, NULL))
4596             return FALSE;
4597     if (RequestedInformation & SACL_SECURITY_INFORMATION)
4598         if (!DumpSacl(SecurityDescriptor, &wptr, NULL))
4599             return FALSE;
4600     *wptr = 0;
4601
4602     TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
4603     *OutputString = wstr;
4604     if (OutputLen)
4605         *OutputLen = strlenW(*OutputString)+1;
4606     return TRUE;
4607 }
4608
4609 /******************************************************************************
4610  * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
4611  */
4612 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen)
4613 {
4614     LPWSTR wstr;
4615     ULONG len;
4616     if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
4617     {
4618         int lenA;
4619
4620         lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
4621         *OutputString = HeapAlloc(GetProcessHeap(), 0, lenA);
4622         WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
4623         LocalFree(wstr);
4624
4625         if (OutputLen != NULL)
4626             *OutputLen = lenA;
4627         return TRUE;
4628     }
4629     else
4630     {
4631         *OutputString = NULL;
4632         if (OutputLen)
4633             *OutputLen = 0;
4634         return FALSE;
4635     }
4636 }
4637
4638 /******************************************************************************
4639  * ConvertStringSidToSidW [ADVAPI32.@]
4640  */
4641 BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid)
4642 {
4643     BOOL bret = FALSE;
4644     DWORD cBytes;
4645
4646     TRACE("%s, %p\n", debugstr_w(StringSid), Sid);
4647     if (GetVersion() & 0x80000000)
4648         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4649     else if (!StringSid || !Sid)
4650         SetLastError(ERROR_INVALID_PARAMETER);
4651     else if (ParseStringSidToSid(StringSid, NULL, &cBytes))
4652     {
4653         PSID pSid = *Sid = LocalAlloc(0, cBytes);
4654
4655         bret = ParseStringSidToSid(StringSid, pSid, &cBytes);
4656         if (!bret)
4657             LocalFree(*Sid); 
4658     }
4659     return bret;
4660 }
4661
4662 /******************************************************************************
4663  * ConvertStringSidToSidA [ADVAPI32.@]
4664  */
4665 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
4666 {
4667     BOOL bret = FALSE;
4668
4669     TRACE("%s, %p\n", debugstr_a(StringSid), Sid);
4670     if (GetVersion() & 0x80000000)
4671         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4672     else if (!StringSid || !Sid)
4673         SetLastError(ERROR_INVALID_PARAMETER);
4674     else
4675     {
4676         UINT len = MultiByteToWideChar(CP_ACP, 0, StringSid, -1, NULL, 0);
4677         LPWSTR wStringSid = HeapAlloc(GetProcessHeap(), 0,
4678          len * sizeof(WCHAR));
4679
4680         MultiByteToWideChar(CP_ACP, 0, StringSid, -1, wStringSid, len);
4681         bret = ConvertStringSidToSidW(wStringSid, Sid);
4682         HeapFree(GetProcessHeap(), 0, wStringSid);
4683     }
4684     return bret;
4685 }
4686
4687 /******************************************************************************
4688  * ConvertSidToStringSidW [ADVAPI32.@]
4689  *
4690  *  format of SID string is:
4691  *    S-<count>-<auth>-<subauth1>-<subauth2>-<subauth3>...
4692  *  where
4693  *    <rev> is the revision of the SID encoded as decimal
4694  *    <auth> is the identifier authority encoded as hex
4695  *    <subauthN> is the subauthority id encoded as decimal
4696  */
4697 BOOL WINAPI ConvertSidToStringSidW( PSID pSid, LPWSTR *pstr )
4698 {
4699     DWORD len = 0;
4700     LPWSTR wstr, wptr;
4701
4702     TRACE("%p %p\n", pSid, pstr );
4703
4704     len = 0;
4705     if (!DumpSidNumeric(pSid, NULL, &len))
4706         return FALSE;
4707     wstr = wptr = LocalAlloc(0, (len+1) * sizeof(WCHAR));
4708     DumpSidNumeric(pSid, &wptr, NULL);
4709     *wptr = 0;
4710
4711     *pstr = wstr;
4712     return TRUE;
4713 }
4714
4715 /******************************************************************************
4716  * ConvertSidToStringSidA [ADVAPI32.@]
4717  */
4718 BOOL WINAPI ConvertSidToStringSidA(PSID pSid, LPSTR *pstr)
4719 {
4720     LPWSTR wstr = NULL;
4721     LPSTR str;
4722     UINT len;
4723
4724     TRACE("%p %p\n", pSid, pstr );
4725
4726     if( !ConvertSidToStringSidW( pSid, &wstr ) )
4727         return FALSE;
4728
4729     len = WideCharToMultiByte( CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL );
4730     str = LocalAlloc( 0, len );
4731     WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, len, NULL, NULL );
4732     LocalFree( wstr );
4733
4734     *pstr = str;
4735
4736     return TRUE;
4737 }
4738
4739 BOOL WINAPI ConvertToAutoInheritPrivateObjectSecurity(
4740         PSECURITY_DESCRIPTOR pdesc,
4741         PSECURITY_DESCRIPTOR cdesc,
4742         PSECURITY_DESCRIPTOR* ndesc,
4743         GUID* objtype,
4744         BOOL isdir,
4745         PGENERIC_MAPPING genmap )
4746 {
4747     FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
4748
4749     return FALSE;
4750 }
4751
4752 BOOL WINAPI CreatePrivateObjectSecurity(
4753         PSECURITY_DESCRIPTOR ParentDescriptor,
4754         PSECURITY_DESCRIPTOR CreatorDescriptor,
4755         PSECURITY_DESCRIPTOR* NewDescriptor,
4756         BOOL IsDirectoryObject,
4757         HANDLE Token,
4758         PGENERIC_MAPPING GenericMapping )
4759 {
4760     FIXME("%p %p %p %d %p %p - stub\n", ParentDescriptor, CreatorDescriptor,
4761           NewDescriptor, IsDirectoryObject, Token, GenericMapping);
4762
4763     return FALSE;
4764 }
4765
4766 BOOL WINAPI DestroyPrivateObjectSecurity( PSECURITY_DESCRIPTOR* ObjectDescriptor )
4767 {
4768     FIXME("%p - stub\n", ObjectDescriptor);
4769
4770     return TRUE;
4771 }
4772
4773 BOOL WINAPI CreateProcessAsUserA(
4774         HANDLE hToken,
4775         LPCSTR lpApplicationName,
4776         LPSTR lpCommandLine,
4777         LPSECURITY_ATTRIBUTES lpProcessAttributes,
4778         LPSECURITY_ATTRIBUTES lpThreadAttributes,
4779         BOOL bInheritHandles,
4780         DWORD dwCreationFlags,
4781         LPVOID lpEnvironment,
4782         LPCSTR lpCurrentDirectory,
4783         LPSTARTUPINFOA lpStartupInfo,
4784         LPPROCESS_INFORMATION lpProcessInformation )
4785 {
4786     FIXME("%p %s %s %p %p %d 0x%08x %p %s %p %p - stub\n", hToken, debugstr_a(lpApplicationName),
4787           debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
4788           dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
4789
4790     return FALSE;
4791 }
4792
4793 BOOL WINAPI CreateProcessAsUserW(
4794         HANDLE hToken,
4795         LPCWSTR lpApplicationName,
4796         LPWSTR lpCommandLine,
4797         LPSECURITY_ATTRIBUTES lpProcessAttributes,
4798         LPSECURITY_ATTRIBUTES lpThreadAttributes,
4799         BOOL bInheritHandles,
4800         DWORD dwCreationFlags,
4801         LPVOID lpEnvironment,
4802         LPCWSTR lpCurrentDirectory,
4803         LPSTARTUPINFOW lpStartupInfo,
4804         LPPROCESS_INFORMATION lpProcessInformation )
4805 {
4806     FIXME("%p %s %s %p %p %d 0x%08x %p %s %p %p - semi- stub\n", hToken, 
4807           debugstr_w(lpApplicationName), debugstr_w(lpCommandLine), lpProcessAttributes,
4808           lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, 
4809           debugstr_w(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
4810
4811     /* We should create the process with a suspended main thread */
4812     if (!CreateProcessW (lpApplicationName,
4813                          lpCommandLine,
4814                          lpProcessAttributes,
4815                          lpThreadAttributes,
4816                          bInheritHandles,
4817                          dwCreationFlags, /* CREATE_SUSPENDED */
4818                          lpEnvironment,
4819                          lpCurrentDirectory,
4820                          lpStartupInfo,
4821                          lpProcessInformation))
4822     {
4823       return FALSE;
4824     }
4825
4826     return TRUE;
4827 }
4828
4829 /******************************************************************************
4830  * CreateProcessWithLogonW
4831  */
4832 BOOL WINAPI CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags,
4833     LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment,
4834     LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
4835 {
4836     FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
4837     debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
4838     debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
4839     lpStartupInfo, lpProcessInformation);
4840
4841     return FALSE;
4842 }
4843
4844 /******************************************************************************
4845  * DuplicateTokenEx [ADVAPI32.@]
4846  */
4847 BOOL WINAPI DuplicateTokenEx(
4848         HANDLE ExistingTokenHandle, DWORD dwDesiredAccess,
4849         LPSECURITY_ATTRIBUTES lpTokenAttributes,
4850         SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
4851         TOKEN_TYPE TokenType,
4852         PHANDLE DuplicateTokenHandle )
4853 {
4854     OBJECT_ATTRIBUTES ObjectAttributes;
4855
4856     TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
4857           ImpersonationLevel, TokenType, DuplicateTokenHandle);
4858
4859     InitializeObjectAttributes(
4860         &ObjectAttributes,
4861         NULL,
4862         (lpTokenAttributes && lpTokenAttributes->bInheritHandle) ? OBJ_INHERIT : 0,
4863         NULL,
4864         lpTokenAttributes ? lpTokenAttributes->lpSecurityDescriptor : NULL );
4865
4866     return set_ntstatus( NtDuplicateToken( ExistingTokenHandle,
4867                                            dwDesiredAccess,
4868                                            &ObjectAttributes,
4869                                            ImpersonationLevel,
4870                                            TokenType,
4871                                            DuplicateTokenHandle ) );
4872 }
4873
4874 BOOL WINAPI DuplicateToken(
4875         HANDLE ExistingTokenHandle,
4876         SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
4877         PHANDLE DuplicateTokenHandle )
4878 {
4879     return DuplicateTokenEx( ExistingTokenHandle, TOKEN_IMPERSONATE | TOKEN_QUERY,
4880                              NULL, ImpersonationLevel, TokenImpersonation,
4881                              DuplicateTokenHandle );
4882 }
4883
4884 /******************************************************************************
4885  * ComputeStringSidSize
4886  */
4887 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
4888 {
4889     if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
4890     {
4891         int ctok = 0;
4892         while (*StringSid)
4893         {
4894             if (*StringSid == '-')
4895                 ctok++;
4896             StringSid++;
4897         }
4898
4899         if (ctok >= 3)
4900             return GetSidLengthRequired(ctok - 2);
4901     }
4902     else /* String constant format  - Only available in winxp and above */
4903     {
4904         unsigned int i;
4905
4906         for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
4907             if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
4908                 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
4909     }
4910
4911     return GetSidLengthRequired(0);
4912 }
4913
4914 /******************************************************************************
4915  * ParseStringSidToSid
4916  */
4917 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
4918 {
4919     BOOL bret = FALSE;
4920     SID* pisid=pSid;
4921
4922     TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
4923     if (!StringSid)
4924     {
4925         SetLastError(ERROR_INVALID_PARAMETER);
4926         TRACE("StringSid is NULL, returning FALSE\n");
4927         return FALSE;
4928     }
4929
4930     *cBytes = ComputeStringSidSize(StringSid);
4931     if (!pisid) /* Simply compute the size */
4932     {
4933         TRACE("only size requested, returning TRUE\n");
4934         return TRUE;
4935     }
4936
4937     if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
4938     {
4939         DWORD i = 0, identAuth;
4940         DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
4941
4942         StringSid += 2; /* Advance to Revision */
4943         pisid->Revision = atoiW(StringSid);
4944
4945         if (pisid->Revision != SDDL_REVISION)
4946         {
4947             TRACE("Revision %d is unknown\n", pisid->Revision);
4948             goto lend; /* ERROR_INVALID_SID */
4949         }
4950         if (csubauth == 0)
4951         {
4952             TRACE("SubAuthorityCount is 0\n");
4953             goto lend; /* ERROR_INVALID_SID */
4954         }
4955
4956         pisid->SubAuthorityCount = csubauth;
4957
4958         /* Advance to identifier authority */
4959         while (*StringSid && *StringSid != '-')
4960             StringSid++;
4961         if (*StringSid == '-')
4962             StringSid++;
4963
4964         /* MS' implementation can't handle values greater than 2^32 - 1, so
4965          * we don't either; assume most significant bytes are always 0
4966          */
4967         pisid->IdentifierAuthority.Value[0] = 0;
4968         pisid->IdentifierAuthority.Value[1] = 0;
4969         identAuth = atoiW(StringSid);
4970         pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
4971         pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
4972         pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
4973         pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
4974
4975         /* Advance to first sub authority */
4976         while (*StringSid && *StringSid != '-')
4977             StringSid++;
4978         if (*StringSid == '-')
4979             StringSid++;
4980
4981         while (*StringSid)
4982         {
4983             pisid->SubAuthority[i++] = atoiW(StringSid);
4984
4985             while (*StringSid && *StringSid != '-')
4986                 StringSid++;
4987             if (*StringSid == '-')
4988                 StringSid++;
4989         }
4990
4991         if (i != pisid->SubAuthorityCount)
4992             goto lend; /* ERROR_INVALID_SID */
4993
4994         bret = TRUE;
4995     }
4996     else /* String constant format  - Only available in winxp and above */
4997     {
4998         unsigned int i;
4999         pisid->Revision = SDDL_REVISION;
5000
5001         for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5002             if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5003             {
5004                 DWORD j;
5005                 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
5006                 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
5007                 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
5008                     pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
5009                 bret = TRUE;
5010             }
5011
5012         if (!bret)
5013             FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
5014     }
5015
5016 lend:
5017     if (!bret)
5018         SetLastError(ERROR_INVALID_SID);
5019
5020     TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
5021     return bret;
5022 }
5023
5024 /******************************************************************************
5025  * GetNamedSecurityInfoA [ADVAPI32.@]
5026  */
5027 DWORD WINAPI GetNamedSecurityInfoA(LPSTR pObjectName,
5028         SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5029         PSID* ppsidOwner, PSID* ppsidGroup, PACL* ppDacl, PACL* ppSacl,
5030         PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
5031 {
5032     DWORD len;
5033     LPWSTR wstr = NULL;
5034     DWORD r;
5035
5036     TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo,
5037         ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
5038
5039     if( pObjectName )
5040     {
5041         len = MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, NULL, 0 );
5042         wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR));
5043         MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, wstr, len );
5044     }
5045
5046     r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
5047                            ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
5048
5049     HeapFree( GetProcessHeap(), 0, wstr );
5050
5051     return r;
5052 }
5053
5054 /******************************************************************************
5055  * GetNamedSecurityInfoW [ADVAPI32.@]
5056  */
5057 DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type,
5058     SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl,
5059     PACL* sacl, PSECURITY_DESCRIPTOR* descriptor )
5060 {
5061     DWORD needed, offset;
5062     SECURITY_DESCRIPTOR_RELATIVE *relative;
5063     BYTE *buffer;
5064
5065     TRACE( "%s %d %d %p %p %p %p %p\n", debugstr_w(name), type, info, owner,
5066            group, dacl, sacl, descriptor );
5067
5068     if (!name || !descriptor) return ERROR_INVALID_PARAMETER;
5069
5070     needed = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5071     if (info & OWNER_SECURITY_INFORMATION)
5072         needed += sizeof(sidWorld);
5073     if (info & GROUP_SECURITY_INFORMATION)
5074         needed += sizeof(sidWorld);
5075     if (info & DACL_SECURITY_INFORMATION)
5076         needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5077     if (info & SACL_SECURITY_INFORMATION)
5078         needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5079
5080     /* must be freed by caller */
5081     *descriptor = HeapAlloc( GetProcessHeap(), 0, needed );
5082     if (!*descriptor) return ERROR_NOT_ENOUGH_MEMORY;
5083
5084     if (!InitializeSecurityDescriptor( *descriptor, SECURITY_DESCRIPTOR_REVISION ))
5085     {
5086         HeapFree( GetProcessHeap(), 0, *descriptor );
5087         return ERROR_INVALID_SECURITY_DESCR;
5088     }
5089
5090     relative = *descriptor;
5091     relative->Control |= SE_SELF_RELATIVE;
5092     buffer = (BYTE *)relative;
5093     offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5094
5095     if (info & OWNER_SECURITY_INFORMATION)
5096     {
5097         memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5098         relative->Owner = offset;
5099         if (owner)
5100             *owner = buffer + offset;
5101         offset += sizeof(sidWorld);
5102     }
5103     if (info & GROUP_SECURITY_INFORMATION)
5104     {
5105         memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5106         relative->Group = offset;
5107         if (group)
5108             *group = buffer + offset;
5109         offset += sizeof(sidWorld);
5110     }
5111     if (info & DACL_SECURITY_INFORMATION)
5112     {
5113         relative->Control |= SE_DACL_PRESENT;
5114         GetWorldAccessACL( (PACL)(buffer + offset) );
5115         relative->Dacl = offset;
5116         if (dacl)
5117             *dacl = (PACL)(buffer + offset);
5118         offset += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5119     }
5120     if (info & SACL_SECURITY_INFORMATION)
5121     {
5122         relative->Control |= SE_SACL_PRESENT;
5123         GetWorldAccessACL( (PACL)(buffer + offset) );
5124         relative->Sacl = offset;
5125         if (sacl)
5126             *sacl = (PACL)(buffer + offset);
5127     }
5128     return ERROR_SUCCESS;
5129 }
5130
5131 /******************************************************************************
5132  * DecryptFileW [ADVAPI32.@]
5133  */
5134 BOOL WINAPI DecryptFileW(LPCWSTR lpFileName, DWORD dwReserved)
5135 {
5136     FIXME("%s %08x\n", debugstr_w(lpFileName), dwReserved);
5137     return TRUE;
5138 }
5139
5140 /******************************************************************************
5141  * DecryptFileA [ADVAPI32.@]
5142  */
5143 BOOL WINAPI DecryptFileA(LPCSTR lpFileName, DWORD dwReserved)
5144 {
5145     FIXME("%s %08x\n", debugstr_a(lpFileName), dwReserved);
5146     return TRUE;
5147 }
5148
5149 /******************************************************************************
5150  * EncryptFileW [ADVAPI32.@]
5151  */
5152 BOOL WINAPI EncryptFileW(LPCWSTR lpFileName)
5153 {
5154     FIXME("%s\n", debugstr_w(lpFileName));
5155     return TRUE;
5156 }
5157
5158 /******************************************************************************
5159  * EncryptFileA [ADVAPI32.@]
5160  */
5161 BOOL WINAPI EncryptFileA(LPCSTR lpFileName)
5162 {
5163     FIXME("%s\n", debugstr_a(lpFileName));
5164     return TRUE;
5165 }
5166
5167 /******************************************************************************
5168  * FileEncryptionStatusW [ADVAPI32.@]
5169  */
5170 BOOL WINAPI FileEncryptionStatusW(LPCWSTR lpFileName, LPDWORD lpStatus)
5171 {
5172     FIXME("(%s %p): stub\n", debugstr_w(lpFileName), lpStatus);
5173     if (!lpStatus)
5174         return FALSE;
5175     *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5176     return TRUE;
5177 }
5178
5179 /******************************************************************************
5180  * FileEncryptionStatusA [ADVAPI32.@]
5181  */
5182 BOOL WINAPI FileEncryptionStatusA(LPCSTR lpFileName, LPDWORD lpStatus)
5183 {
5184     FIXME("(%s %p): stub\n", debugstr_a(lpFileName), lpStatus);
5185     if (!lpStatus)
5186         return FALSE;
5187     *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5188     return TRUE;
5189 }
5190
5191 /******************************************************************************
5192  * SetSecurityInfo [ADVAPI32.@]
5193  */
5194 DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType, 
5195                       SECURITY_INFORMATION SecurityInfo, PSID psidOwner,
5196                       PSID psidGroup, PACL pDacl, PACL pSacl) {
5197     FIXME("stub\n");
5198     return ERROR_SUCCESS;
5199 }
5200
5201 /******************************************************************************
5202  * SaferCreateLevel   [ADVAPI32.@]
5203  */
5204 BOOL WINAPI SaferCreateLevel(DWORD ScopeId, DWORD LevelId, DWORD OpenFlags,
5205                              SAFER_LEVEL_HANDLE* LevelHandle, LPVOID lpReserved)
5206 {
5207     FIXME("(%u, %x, %u, %p, %p) stub\n", ScopeId, LevelId, OpenFlags, LevelHandle, lpReserved);
5208     return FALSE;
5209 }