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