advapi32: Factor out lookup of local usernames and well-known SIDs.
[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         SetLastError(ERROR_SUCCESS);
1077         return RtlSubAuthoritySid(pSid, nSubAuthority);
1078 }
1079
1080 /******************************************************************************
1081  * GetSidSubAuthorityCount [ADVAPI32.@]
1082  *
1083  * PARAMS
1084  *   pSid []
1085  */
1086 PUCHAR WINAPI
1087 GetSidSubAuthorityCount (PSID pSid)
1088 {
1089         SetLastError(ERROR_SUCCESS);
1090         return RtlSubAuthorityCountSid(pSid);
1091 }
1092
1093 /******************************************************************************
1094  * GetLengthSid [ADVAPI32.@]
1095  *
1096  * PARAMS
1097  *   pSid []
1098  */
1099 DWORD WINAPI
1100 GetLengthSid (PSID pSid)
1101 {
1102         return RtlLengthSid(pSid);
1103 }
1104
1105 /*      ##############################################
1106         ######  SECURITY DESCRIPTOR FUNCTIONS   ######
1107         ##############################################
1108 */
1109
1110  /****************************************************************************** 
1111  * BuildSecurityDescriptorA [ADVAPI32.@]
1112  *
1113  * Builds a SD from 
1114  *
1115  * PARAMS
1116  *  pOwner                [I]
1117  *  pGroup                [I]
1118  *  cCountOfAccessEntries [I]
1119  *  pListOfAccessEntries  [I]
1120  *  cCountOfAuditEntries  [I]
1121  *  pListofAuditEntries   [I]
1122  *  pOldSD                [I]
1123  *  lpdwBufferLength      [I/O]
1124  *  pNewSD                [O]
1125  *
1126  * RETURNS
1127  *  Success: ERROR_SUCCESS
1128  *  Failure: nonzero error code from Winerror.h
1129  */
1130 DWORD WINAPI BuildSecurityDescriptorA(
1131     IN PTRUSTEEA pOwner,
1132     IN PTRUSTEEA pGroup,
1133     IN ULONG cCountOfAccessEntries,
1134     IN PEXPLICIT_ACCESSA pListOfAccessEntries,
1135     IN ULONG cCountOfAuditEntries,
1136     IN PEXPLICIT_ACCESSA pListofAuditEntries,
1137     IN PSECURITY_DESCRIPTOR pOldSD,
1138     IN OUT PULONG lpdwBufferLength,
1139     OUT PSECURITY_DESCRIPTOR* pNewSD)
1140
1141     FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
1142           cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
1143           pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
1144  
1145     return ERROR_CALL_NOT_IMPLEMENTED;
1146
1147  
1148 /******************************************************************************
1149  * BuildSecurityDescriptorW [ADVAPI32.@]
1150  *
1151  * See BuildSecurityDescriptorA.
1152  */
1153 DWORD WINAPI BuildSecurityDescriptorW(
1154     IN PTRUSTEEW pOwner,
1155     IN PTRUSTEEW pGroup,
1156     IN ULONG cCountOfAccessEntries,
1157     IN PEXPLICIT_ACCESSW pListOfAccessEntries,
1158     IN ULONG cCountOfAuditEntries,
1159     IN PEXPLICIT_ACCESSW pListofAuditEntries,
1160     IN PSECURITY_DESCRIPTOR pOldSD,
1161     IN OUT PULONG lpdwBufferLength,
1162     OUT PSECURITY_DESCRIPTOR* pNewSD)
1163
1164     FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
1165           cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
1166           pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
1167  
1168     return ERROR_CALL_NOT_IMPLEMENTED;
1169
1170
1171 /******************************************************************************
1172  * InitializeSecurityDescriptor [ADVAPI32.@]
1173  *
1174  * PARAMS
1175  *   pDescr   []
1176  *   revision []
1177  */
1178 BOOL WINAPI
1179 InitializeSecurityDescriptor( PSECURITY_DESCRIPTOR pDescr, DWORD revision )
1180 {
1181         return set_ntstatus( RtlCreateSecurityDescriptor(pDescr, revision ));
1182 }
1183
1184
1185 /******************************************************************************
1186  * MakeAbsoluteSD [ADVAPI32.@]
1187  */
1188 BOOL WINAPI MakeAbsoluteSD (
1189         IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
1190         OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
1191         OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
1192         OUT PACL pDacl,
1193         OUT LPDWORD lpdwDaclSize,
1194         OUT PACL pSacl,
1195         OUT LPDWORD lpdwSaclSize,
1196         OUT PSID pOwner,
1197         OUT LPDWORD lpdwOwnerSize,
1198         OUT PSID pPrimaryGroup,
1199         OUT LPDWORD lpdwPrimaryGroupSize)
1200 {
1201     return set_ntstatus( RtlSelfRelativeToAbsoluteSD(pSelfRelativeSecurityDescriptor,
1202                                                      pAbsoluteSecurityDescriptor,
1203                                                      lpdwAbsoluteSecurityDescriptorSize,
1204                                                      pDacl, lpdwDaclSize, pSacl, lpdwSaclSize,
1205                                                      pOwner, lpdwOwnerSize,
1206                                                      pPrimaryGroup, lpdwPrimaryGroupSize));
1207 }
1208
1209 /******************************************************************************
1210  * GetKernelObjectSecurity [ADVAPI32.@]
1211  */
1212 BOOL WINAPI GetKernelObjectSecurity(
1213         HANDLE Handle,
1214         SECURITY_INFORMATION RequestedInformation,
1215         PSECURITY_DESCRIPTOR pSecurityDescriptor,
1216         DWORD nLength,
1217         LPDWORD lpnLengthNeeded )
1218 {
1219     TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", Handle, RequestedInformation,
1220           pSecurityDescriptor, nLength, lpnLengthNeeded);
1221
1222     return set_ntstatus( NtQuerySecurityObject(Handle, RequestedInformation, pSecurityDescriptor,
1223                                                nLength, lpnLengthNeeded ));
1224 }
1225
1226 /******************************************************************************
1227  * GetPrivateObjectSecurity [ADVAPI32.@]
1228  */
1229 BOOL WINAPI GetPrivateObjectSecurity(
1230         PSECURITY_DESCRIPTOR ObjectDescriptor,
1231         SECURITY_INFORMATION SecurityInformation,
1232         PSECURITY_DESCRIPTOR ResultantDescriptor,
1233         DWORD DescriptorLength,
1234         PDWORD ReturnLength )
1235 {
1236     SECURITY_DESCRIPTOR desc;
1237     BOOL defaulted, present;
1238     PACL pacl;
1239     PSID psid;
1240
1241     TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", ObjectDescriptor, SecurityInformation,
1242           ResultantDescriptor, DescriptorLength, ReturnLength);
1243
1244     if (!InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION))
1245         return FALSE;
1246
1247     if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1248     {
1249         if (!GetSecurityDescriptorOwner(ObjectDescriptor, &psid, &defaulted))
1250             return FALSE;
1251         SetSecurityDescriptorOwner(&desc, psid, defaulted);
1252     }
1253
1254     if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1255     {
1256         if (!GetSecurityDescriptorGroup(ObjectDescriptor, &psid, &defaulted))
1257             return FALSE;
1258         SetSecurityDescriptorGroup(&desc, psid, defaulted);
1259     }
1260
1261     if (SecurityInformation & DACL_SECURITY_INFORMATION)
1262     {
1263         if (!GetSecurityDescriptorDacl(ObjectDescriptor, &present, &pacl, &defaulted))
1264             return FALSE;
1265         SetSecurityDescriptorDacl(&desc, present, pacl, defaulted);
1266     }
1267
1268     if (SecurityInformation & SACL_SECURITY_INFORMATION)
1269     {
1270         if (!GetSecurityDescriptorSacl(ObjectDescriptor, &present, &pacl, &defaulted))
1271             return FALSE;
1272         SetSecurityDescriptorSacl(&desc, present, pacl, defaulted);
1273     }
1274
1275     *ReturnLength = DescriptorLength;
1276     return MakeSelfRelativeSD(&desc, ResultantDescriptor, ReturnLength);
1277 }
1278
1279 /******************************************************************************
1280  * GetSecurityDescriptorLength [ADVAPI32.@]
1281  */
1282 DWORD WINAPI GetSecurityDescriptorLength( PSECURITY_DESCRIPTOR pDescr)
1283 {
1284         return RtlLengthSecurityDescriptor(pDescr);
1285 }
1286
1287 /******************************************************************************
1288  * GetSecurityDescriptorOwner [ADVAPI32.@]
1289  *
1290  * PARAMS
1291  *   pOwner            []
1292  *   lpbOwnerDefaulted []
1293  */
1294 BOOL WINAPI
1295 GetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pDescr, PSID *pOwner,
1296                             LPBOOL lpbOwnerDefaulted )
1297 {
1298     BOOLEAN defaulted;
1299     BOOL ret = set_ntstatus( RtlGetOwnerSecurityDescriptor( pDescr, pOwner, &defaulted ));
1300     *lpbOwnerDefaulted = defaulted;
1301     return ret;
1302 }
1303
1304 /******************************************************************************
1305  * SetSecurityDescriptorOwner [ADVAPI32.@]
1306  *
1307  * PARAMS
1308  */
1309 BOOL WINAPI SetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1310                                    PSID pOwner, BOOL bOwnerDefaulted)
1311 {
1312     return set_ntstatus( RtlSetOwnerSecurityDescriptor(pSecurityDescriptor, pOwner, bOwnerDefaulted));
1313 }
1314 /******************************************************************************
1315  * GetSecurityDescriptorGroup                   [ADVAPI32.@]
1316  */
1317 BOOL WINAPI GetSecurityDescriptorGroup(
1318         PSECURITY_DESCRIPTOR SecurityDescriptor,
1319         PSID *Group,
1320         LPBOOL GroupDefaulted)
1321 {
1322     BOOLEAN defaulted;
1323     BOOL ret = set_ntstatus( RtlGetGroupSecurityDescriptor(SecurityDescriptor, Group, &defaulted ));
1324     *GroupDefaulted = defaulted;
1325     return ret;
1326 }
1327 /******************************************************************************
1328  * SetSecurityDescriptorGroup [ADVAPI32.@]
1329  */
1330 BOOL WINAPI SetSecurityDescriptorGroup ( PSECURITY_DESCRIPTOR SecurityDescriptor,
1331                                            PSID Group, BOOL GroupDefaulted)
1332 {
1333     return set_ntstatus( RtlSetGroupSecurityDescriptor( SecurityDescriptor, Group, GroupDefaulted));
1334 }
1335
1336 /******************************************************************************
1337  * IsValidSecurityDescriptor [ADVAPI32.@]
1338  *
1339  * PARAMS
1340  *   lpsecdesc []
1341  */
1342 BOOL WINAPI
1343 IsValidSecurityDescriptor( PSECURITY_DESCRIPTOR SecurityDescriptor )
1344 {
1345     return set_ntstatus( RtlValidSecurityDescriptor(SecurityDescriptor));
1346 }
1347
1348 /******************************************************************************
1349  *  GetSecurityDescriptorDacl                   [ADVAPI32.@]
1350  */
1351 BOOL WINAPI GetSecurityDescriptorDacl(
1352         IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
1353         OUT LPBOOL lpbDaclPresent,
1354         OUT PACL *pDacl,
1355         OUT LPBOOL lpbDaclDefaulted)
1356 {
1357     BOOLEAN present, defaulted;
1358     BOOL ret = set_ntstatus( RtlGetDaclSecurityDescriptor(pSecurityDescriptor, &present, pDacl, &defaulted));
1359     *lpbDaclPresent = present;
1360     *lpbDaclDefaulted = defaulted;
1361     return ret;
1362 }
1363
1364 /******************************************************************************
1365  *  SetSecurityDescriptorDacl                   [ADVAPI32.@]
1366  */
1367 BOOL WINAPI
1368 SetSecurityDescriptorDacl (
1369         PSECURITY_DESCRIPTOR lpsd,
1370         BOOL daclpresent,
1371         PACL dacl,
1372         BOOL dacldefaulted )
1373 {
1374     return set_ntstatus( RtlSetDaclSecurityDescriptor (lpsd, daclpresent, dacl, dacldefaulted ) );
1375 }
1376 /******************************************************************************
1377  *  GetSecurityDescriptorSacl                   [ADVAPI32.@]
1378  */
1379 BOOL WINAPI GetSecurityDescriptorSacl(
1380         IN PSECURITY_DESCRIPTOR lpsd,
1381         OUT LPBOOL lpbSaclPresent,
1382         OUT PACL *pSacl,
1383         OUT LPBOOL lpbSaclDefaulted)
1384 {
1385     BOOLEAN present, defaulted;
1386     BOOL ret = set_ntstatus( RtlGetSaclSecurityDescriptor(lpsd, &present, pSacl, &defaulted) );
1387     *lpbSaclPresent = present;
1388     *lpbSaclDefaulted = defaulted;
1389     return ret;
1390 }
1391
1392 /**************************************************************************
1393  * SetSecurityDescriptorSacl                    [ADVAPI32.@]
1394  */
1395 BOOL WINAPI SetSecurityDescriptorSacl (
1396         PSECURITY_DESCRIPTOR lpsd,
1397         BOOL saclpresent,
1398         PACL lpsacl,
1399         BOOL sacldefaulted)
1400 {
1401     return set_ntstatus (RtlSetSaclSecurityDescriptor(lpsd, saclpresent, lpsacl, sacldefaulted));
1402 }
1403 /******************************************************************************
1404  * MakeSelfRelativeSD [ADVAPI32.@]
1405  *
1406  * PARAMS
1407  *   lpabssecdesc  []
1408  *   lpselfsecdesc []
1409  *   lpbuflen      []
1410  */
1411 BOOL WINAPI
1412 MakeSelfRelativeSD(
1413         IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
1414         IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
1415         IN OUT LPDWORD lpdwBufferLength)
1416 {
1417     return set_ntstatus( RtlMakeSelfRelativeSD( pAbsoluteSecurityDescriptor,
1418                                                 pSelfRelativeSecurityDescriptor, lpdwBufferLength));
1419 }
1420
1421 /******************************************************************************
1422  * GetSecurityDescriptorControl                 [ADVAPI32.@]
1423  */
1424
1425 BOOL WINAPI GetSecurityDescriptorControl ( PSECURITY_DESCRIPTOR  pSecurityDescriptor,
1426                  PSECURITY_DESCRIPTOR_CONTROL pControl, LPDWORD lpdwRevision)
1427 {
1428     return set_ntstatus( RtlGetControlSecurityDescriptor(pSecurityDescriptor,pControl,lpdwRevision));
1429 }
1430
1431 /******************************************************************************
1432  * SetSecurityDescriptorControl                 [ADVAPI32.@]
1433  */
1434 BOOL WINAPI SetSecurityDescriptorControl( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1435   SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1436   SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet )
1437 {
1438     return set_ntstatus( RtlSetControlSecurityDescriptor(
1439         pSecurityDescriptor, ControlBitsOfInterest, ControlBitsToSet ) );
1440 }
1441
1442 /*      ##############################
1443         ######  ACL FUNCTIONS   ######
1444         ##############################
1445 */
1446
1447 /*************************************************************************
1448  * InitializeAcl [ADVAPI32.@]
1449  */
1450 BOOL WINAPI InitializeAcl(PACL acl, DWORD size, DWORD rev)
1451 {
1452     return set_ntstatus( RtlCreateAcl(acl, size, rev));
1453 }
1454
1455 BOOL WINAPI ImpersonateNamedPipeClient( HANDLE hNamedPipe )
1456 {
1457     IO_STATUS_BLOCK io_block;
1458
1459     TRACE("(%p)\n", hNamedPipe);
1460
1461     return set_ntstatus( NtFsControlFile(hNamedPipe, NULL, NULL, NULL,
1462                          &io_block, FSCTL_PIPE_IMPERSONATE, NULL, 0, NULL, 0) );
1463 }
1464
1465 /******************************************************************************
1466  *  AddAccessAllowedAce [ADVAPI32.@]
1467  */
1468 BOOL WINAPI AddAccessAllowedAce(
1469         IN OUT PACL pAcl,
1470         IN DWORD dwAceRevision,
1471         IN DWORD AccessMask,
1472         IN PSID pSid)
1473 {
1474     return set_ntstatus(RtlAddAccessAllowedAce(pAcl, dwAceRevision, AccessMask, pSid));
1475 }
1476
1477 /******************************************************************************
1478  *  AddAccessAllowedAceEx [ADVAPI32.@]
1479  */
1480 BOOL WINAPI AddAccessAllowedAceEx(
1481         IN OUT PACL pAcl,
1482         IN DWORD dwAceRevision,
1483         IN DWORD AceFlags,
1484         IN DWORD AccessMask,
1485         IN PSID pSid)
1486 {
1487     return set_ntstatus(RtlAddAccessAllowedAceEx(pAcl, dwAceRevision, AceFlags, AccessMask, pSid));
1488 }
1489
1490 /******************************************************************************
1491  *  AddAccessDeniedAce [ADVAPI32.@]
1492  */
1493 BOOL WINAPI AddAccessDeniedAce(
1494         IN OUT PACL pAcl,
1495         IN DWORD dwAceRevision,
1496         IN DWORD AccessMask,
1497         IN PSID pSid)
1498 {
1499     return set_ntstatus(RtlAddAccessDeniedAce(pAcl, dwAceRevision, AccessMask, pSid));
1500 }
1501
1502 /******************************************************************************
1503  *  AddAccessDeniedAceEx [ADVAPI32.@]
1504  */
1505 BOOL WINAPI AddAccessDeniedAceEx(
1506         IN OUT PACL pAcl,
1507         IN DWORD dwAceRevision,
1508         IN DWORD AceFlags,
1509         IN DWORD AccessMask,
1510         IN PSID pSid)
1511 {
1512     return set_ntstatus(RtlAddAccessDeniedAceEx(pAcl, dwAceRevision, AceFlags, AccessMask, pSid));
1513 }
1514
1515 /******************************************************************************
1516  *  AddAce [ADVAPI32.@]
1517  */
1518 BOOL WINAPI AddAce(
1519         IN OUT PACL pAcl,
1520         IN DWORD dwAceRevision,
1521         IN DWORD dwStartingAceIndex,
1522         LPVOID pAceList,
1523         DWORD nAceListLength)
1524 {
1525     return set_ntstatus(RtlAddAce(pAcl, dwAceRevision, dwStartingAceIndex, pAceList, nAceListLength));
1526 }
1527
1528 /******************************************************************************
1529  * DeleteAce [ADVAPI32.@]
1530  */
1531 BOOL WINAPI DeleteAce(PACL pAcl, DWORD dwAceIndex)
1532 {
1533     return set_ntstatus(RtlDeleteAce(pAcl, dwAceIndex));
1534 }
1535
1536 /******************************************************************************
1537  *  FindFirstFreeAce [ADVAPI32.@]
1538  */
1539 BOOL WINAPI FindFirstFreeAce(IN PACL pAcl, LPVOID * pAce)
1540 {
1541         return RtlFirstFreeAce(pAcl, (PACE_HEADER *)pAce);
1542 }
1543
1544 /******************************************************************************
1545  * GetAce [ADVAPI32.@]
1546  */
1547 BOOL WINAPI GetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1548 {
1549     return set_ntstatus(RtlGetAce(pAcl, dwAceIndex, pAce));
1550 }
1551
1552 /******************************************************************************
1553  * GetAclInformation [ADVAPI32.@]
1554  */
1555 BOOL WINAPI GetAclInformation(
1556   PACL pAcl,
1557   LPVOID pAclInformation,
1558   DWORD nAclInformationLength,
1559   ACL_INFORMATION_CLASS dwAclInformationClass)
1560 {
1561     return set_ntstatus(RtlQueryInformationAcl(pAcl, pAclInformation,
1562                                                nAclInformationLength, dwAclInformationClass));
1563 }
1564
1565 /******************************************************************************
1566  *  IsValidAcl [ADVAPI32.@]
1567  */
1568 BOOL WINAPI IsValidAcl(IN PACL pAcl)
1569 {
1570         return RtlValidAcl(pAcl);
1571 }
1572
1573 /*      ##############################
1574         ######  MISC FUNCTIONS  ######
1575         ##############################
1576 */
1577
1578 /******************************************************************************
1579  * AllocateLocallyUniqueId [ADVAPI32.@]
1580  *
1581  * PARAMS
1582  *   lpLuid []
1583  */
1584 BOOL WINAPI AllocateLocallyUniqueId( PLUID lpLuid )
1585 {
1586     return set_ntstatus(NtAllocateLocallyUniqueId(lpLuid));
1587 }
1588
1589 static const WCHAR SE_CREATE_TOKEN_NAME_W[] =
1590  { 'S','e','C','r','e','a','t','e','T','o','k','e','n','P','r','i','v','i','l','e','g','e',0 };
1591 static const WCHAR SE_ASSIGNPRIMARYTOKEN_NAME_W[] =
1592  { '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 };
1593 static const WCHAR SE_LOCK_MEMORY_NAME_W[] =
1594  { 'S','e','L','o','c','k','M','e','m','o','r','y','P','r','i','v','i','l','e','g','e',0 };
1595 static const WCHAR SE_INCREASE_QUOTA_NAME_W[] =
1596  { '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 };
1597 static const WCHAR SE_MACHINE_ACCOUNT_NAME_W[] =
1598  { '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 };
1599 static const WCHAR SE_TCB_NAME_W[] =
1600  { 'S','e','T','c','b','P','r','i','v','i','l','e','g','e',0 };
1601 static const WCHAR SE_SECURITY_NAME_W[] =
1602  { 'S','e','S','e','c','u','r','i','t','y','P','r','i','v','i','l','e','g','e',0 };
1603 static const WCHAR SE_TAKE_OWNERSHIP_NAME_W[] =
1604  { '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 };
1605 static const WCHAR SE_LOAD_DRIVER_NAME_W[] =
1606  { 'S','e','L','o','a','d','D','r','i','v','e','r','P','r','i','v','i','l','e','g','e',0 };
1607 static const WCHAR SE_SYSTEM_PROFILE_NAME_W[] =
1608  { '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 };
1609 static const WCHAR SE_SYSTEMTIME_NAME_W[] =
1610  { 'S','e','S','y','s','t','e','m','t','i','m','e','P','r','i','v','i','l','e','g','e',0 };
1611 static const WCHAR SE_PROF_SINGLE_PROCESS_NAME_W[] =
1612  { '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 };
1613 static const WCHAR SE_INC_BASE_PRIORITY_NAME_W[] =
1614  { '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 };
1615 static const WCHAR SE_CREATE_PAGEFILE_NAME_W[] =
1616  { '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 };
1617 static const WCHAR SE_CREATE_PERMANENT_NAME_W[] =
1618  { '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 };
1619 static const WCHAR SE_BACKUP_NAME_W[] =
1620  { 'S','e','B','a','c','k','u','p','P','r','i','v','i','l','e','g','e',0 };
1621 static const WCHAR SE_RESTORE_NAME_W[] =
1622  { 'S','e','R','e','s','t','o','r','e','P','r','i','v','i','l','e','g','e',0 };
1623 static const WCHAR SE_SHUTDOWN_NAME_W[] =
1624  { 'S','e','S','h','u','t','d','o','w','n','P','r','i','v','i','l','e','g','e',0 };
1625 static const WCHAR SE_DEBUG_NAME_W[] =
1626  { 'S','e','D','e','b','u','g','P','r','i','v','i','l','e','g','e',0 };
1627 static const WCHAR SE_AUDIT_NAME_W[] =
1628  { 'S','e','A','u','d','i','t','P','r','i','v','i','l','e','g','e',0 };
1629 static const WCHAR SE_SYSTEM_ENVIRONMENT_NAME_W[] =
1630  { '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 };
1631 static const WCHAR SE_CHANGE_NOTIFY_NAME_W[] =
1632  { 'S','e','C','h','a','n','g','e','N','o','t','i','f','y','P','r','i','v','i','l','e','g','e',0 };
1633 static const WCHAR SE_REMOTE_SHUTDOWN_NAME_W[] =
1634  { '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 };
1635 static const WCHAR SE_UNDOCK_NAME_W[] =
1636  { 'S','e','U','n','d','o','c','k','P','r','i','v','i','l','e','g','e',0 };
1637 static const WCHAR SE_SYNC_AGENT_NAME_W[] =
1638  { 'S','e','S','y','n','c','A','g','e','n','t','P','r','i','v','i','l','e','g','e',0 };
1639 static const WCHAR SE_ENABLE_DELEGATION_NAME_W[] =
1640  { '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 };
1641 static const WCHAR SE_MANAGE_VOLUME_NAME_W[] =
1642  { 'S','e','M','a','n','a','g','e','V','o','l','u','m','e','P','r','i','v','i','l','e','g','e',0 };
1643 static const WCHAR SE_IMPERSONATE_NAME_W[] =
1644  { 'S','e','I','m','p','e','r','s','o','n','a','t','e','P','r','i','v','i','l','e','g','e',0 };
1645 static const WCHAR SE_CREATE_GLOBAL_NAME_W[] =
1646  { 'S','e','C','r','e','a','t','e','G','l','o','b','a','l','P','r','i','v','i','l','e','g','e',0 };
1647
1648 static const WCHAR * const WellKnownPrivNames[SE_MAX_WELL_KNOWN_PRIVILEGE + 1] =
1649 {
1650     NULL,
1651     NULL,
1652     SE_CREATE_TOKEN_NAME_W,
1653     SE_ASSIGNPRIMARYTOKEN_NAME_W,
1654     SE_LOCK_MEMORY_NAME_W,
1655     SE_INCREASE_QUOTA_NAME_W,
1656     SE_MACHINE_ACCOUNT_NAME_W,
1657     SE_TCB_NAME_W,
1658     SE_SECURITY_NAME_W,
1659     SE_TAKE_OWNERSHIP_NAME_W,
1660     SE_LOAD_DRIVER_NAME_W,
1661     SE_SYSTEM_PROFILE_NAME_W,
1662     SE_SYSTEMTIME_NAME_W,
1663     SE_PROF_SINGLE_PROCESS_NAME_W,
1664     SE_INC_BASE_PRIORITY_NAME_W,
1665     SE_CREATE_PAGEFILE_NAME_W,
1666     SE_CREATE_PERMANENT_NAME_W,
1667     SE_BACKUP_NAME_W,
1668     SE_RESTORE_NAME_W,
1669     SE_SHUTDOWN_NAME_W,
1670     SE_DEBUG_NAME_W,
1671     SE_AUDIT_NAME_W,
1672     SE_SYSTEM_ENVIRONMENT_NAME_W,
1673     SE_CHANGE_NOTIFY_NAME_W,
1674     SE_REMOTE_SHUTDOWN_NAME_W,
1675     SE_UNDOCK_NAME_W,
1676     SE_SYNC_AGENT_NAME_W,
1677     SE_ENABLE_DELEGATION_NAME_W,
1678     SE_MANAGE_VOLUME_NAME_W,
1679     SE_IMPERSONATE_NAME_W,
1680     SE_CREATE_GLOBAL_NAME_W,
1681 };
1682
1683 /******************************************************************************
1684  * LookupPrivilegeValueW                        [ADVAPI32.@]
1685  *
1686  * See LookupPrivilegeValueA.
1687  */
1688 BOOL WINAPI
1689 LookupPrivilegeValueW( LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid )
1690 {
1691     UINT i;
1692
1693     TRACE("%s,%s,%p\n",debugstr_w(lpSystemName), debugstr_w(lpName), lpLuid);
1694
1695     if (!ADVAPI_IsLocalComputer(lpSystemName))
1696     {
1697         SetLastError(RPC_S_SERVER_UNAVAILABLE);
1698         return FALSE;
1699     }
1700     if (!lpName)
1701     {
1702         SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1703         return FALSE;
1704     }
1705     for( i=SE_MIN_WELL_KNOWN_PRIVILEGE; i<=SE_MAX_WELL_KNOWN_PRIVILEGE; i++ )
1706     {
1707         if( !WellKnownPrivNames[i] )
1708             continue;
1709         if( strcmpiW( WellKnownPrivNames[i], lpName) )
1710             continue;
1711         lpLuid->LowPart = i;
1712         lpLuid->HighPart = 0;
1713         TRACE( "%s -> %08x-%08x\n",debugstr_w( lpSystemName ),
1714                lpLuid->HighPart, lpLuid->LowPart );
1715         return TRUE;
1716     }
1717     SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1718     return FALSE;
1719 }
1720
1721 /******************************************************************************
1722  * LookupPrivilegeValueA                        [ADVAPI32.@]
1723  *
1724  * Retrieves LUID used on a system to represent the privilege name.
1725  *
1726  * PARAMS
1727  *  lpSystemName [I] Name of the system
1728  *  lpName       [I] Name of the privilege
1729  *  lpLuid       [O] Destination for the resulting LUID
1730  *
1731  * RETURNS
1732  *  Success: TRUE. lpLuid contains the requested LUID.
1733  *  Failure: FALSE.
1734  */
1735 BOOL WINAPI
1736 LookupPrivilegeValueA( LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid )
1737 {
1738     UNICODE_STRING lpSystemNameW;
1739     UNICODE_STRING lpNameW;
1740     BOOL ret;
1741
1742     RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1743     RtlCreateUnicodeStringFromAsciiz(&lpNameW,lpName);
1744     ret = LookupPrivilegeValueW(lpSystemNameW.Buffer, lpNameW.Buffer, lpLuid);
1745     RtlFreeUnicodeString(&lpNameW);
1746     RtlFreeUnicodeString(&lpSystemNameW);
1747     return ret;
1748 }
1749
1750 BOOL WINAPI LookupPrivilegeDisplayNameA( LPCSTR lpSystemName, LPCSTR lpName, LPSTR lpDisplayName,
1751                                          LPDWORD cchDisplayName, LPDWORD lpLanguageId )
1752 {
1753     FIXME("%s %s %s %p %p - stub\n", debugstr_a(lpSystemName), debugstr_a(lpName),
1754           debugstr_a(lpDisplayName), cchDisplayName, lpLanguageId);
1755
1756     return FALSE;
1757 }
1758
1759 BOOL WINAPI LookupPrivilegeDisplayNameW( LPCWSTR lpSystemName, LPCWSTR lpName, LPWSTR lpDisplayName,
1760                                          LPDWORD cchDisplayName, LPDWORD lpLanguageId )
1761 {
1762     FIXME("%s %s %s %p %p - stub\n", debugstr_w(lpSystemName), debugstr_w(lpName),
1763           debugstr_w(lpDisplayName), cchDisplayName, lpLanguageId);
1764
1765     return FALSE;
1766 }
1767
1768 /******************************************************************************
1769  * LookupPrivilegeNameA                 [ADVAPI32.@]
1770  *
1771  * See LookupPrivilegeNameW.
1772  */
1773 BOOL WINAPI
1774 LookupPrivilegeNameA( LPCSTR lpSystemName, PLUID lpLuid, LPSTR lpName,
1775  LPDWORD cchName)
1776 {
1777     UNICODE_STRING lpSystemNameW;
1778     BOOL ret;
1779     DWORD wLen = 0;
1780
1781     TRACE("%s %p %p %p\n", debugstr_a(lpSystemName), lpLuid, lpName, cchName);
1782
1783     RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1784     ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, NULL, &wLen);
1785     if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1786     {
1787         LPWSTR lpNameW = HeapAlloc(GetProcessHeap(), 0, wLen * sizeof(WCHAR));
1788
1789         ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, lpNameW,
1790          &wLen);
1791         if (ret)
1792         {
1793             /* Windows crashes if cchName is NULL, so will I */
1794             unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName,
1795              *cchName, NULL, NULL);
1796
1797             if (len == 0)
1798             {
1799                 /* WideCharToMultiByte failed */
1800                 ret = FALSE;
1801             }
1802             else if (len > *cchName)
1803             {
1804                 *cchName = len;
1805                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1806                 ret = FALSE;
1807             }
1808             else
1809             {
1810                 /* WideCharToMultiByte succeeded, output length needs to be
1811                  * length not including NULL terminator
1812                  */
1813                 *cchName = len - 1;
1814             }
1815         }
1816         HeapFree(GetProcessHeap(), 0, lpNameW);
1817     }
1818     RtlFreeUnicodeString(&lpSystemNameW);
1819     return ret;
1820 }
1821
1822 /******************************************************************************
1823  * LookupPrivilegeNameW                 [ADVAPI32.@]
1824  *
1825  * Retrieves the privilege name referred to by the LUID lpLuid.
1826  *
1827  * PARAMS
1828  *  lpSystemName [I]   Name of the system
1829  *  lpLuid       [I]   Privilege value
1830  *  lpName       [O]   Name of the privilege
1831  *  cchName      [I/O] Number of characters in lpName.
1832  *
1833  * RETURNS
1834  *  Success: TRUE. lpName contains the name of the privilege whose value is
1835  *  *lpLuid.
1836  *  Failure: FALSE.
1837  *
1838  * REMARKS
1839  *  Only well-known privilege names (those defined in winnt.h) can be retrieved
1840  *  using this function.
1841  *  If the length of lpName is too small, on return *cchName will contain the
1842  *  number of WCHARs needed to contain the privilege, including the NULL
1843  *  terminator, and GetLastError will return ERROR_INSUFFICIENT_BUFFER.
1844  *  On success, *cchName will contain the number of characters stored in
1845  *  lpName, NOT including the NULL terminator.
1846  */
1847 BOOL WINAPI
1848 LookupPrivilegeNameW( LPCWSTR lpSystemName, PLUID lpLuid, LPWSTR lpName,
1849  LPDWORD cchName)
1850 {
1851     size_t privNameLen;
1852
1853     TRACE("%s,%p,%p,%p\n",debugstr_w(lpSystemName), lpLuid, lpName, cchName);
1854
1855     if (!ADVAPI_IsLocalComputer(lpSystemName))
1856     {
1857         SetLastError(RPC_S_SERVER_UNAVAILABLE);
1858         return FALSE;
1859     }
1860     if (lpLuid->HighPart || (lpLuid->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
1861      lpLuid->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE))
1862     {
1863         SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1864         return FALSE;
1865     }
1866     privNameLen = strlenW(WellKnownPrivNames[lpLuid->LowPart]);
1867     /* Windows crashes if cchName is NULL, so will I */
1868     if (*cchName <= privNameLen)
1869     {
1870         *cchName = privNameLen + 1;
1871         SetLastError(ERROR_INSUFFICIENT_BUFFER);
1872         return FALSE;
1873     }
1874     else
1875     {
1876         strcpyW(lpName, WellKnownPrivNames[lpLuid->LowPart]);
1877         *cchName = privNameLen;
1878         return TRUE;
1879     }
1880 }
1881
1882 /******************************************************************************
1883  * GetFileSecurityA [ADVAPI32.@]
1884  *
1885  * Obtains Specified information about the security of a file or directory.
1886  *
1887  * PARAMS
1888  *  lpFileName           [I] Name of the file to get info for
1889  *  RequestedInformation [I] SE_ flags from "winnt.h"
1890  *  pSecurityDescriptor  [O] Destination for security information
1891  *  nLength              [I] Length of pSecurityDescriptor
1892  *  lpnLengthNeeded      [O] Destination for length of returned security information
1893  *
1894  * RETURNS
1895  *  Success: TRUE. pSecurityDescriptor contains the requested information.
1896  *  Failure: FALSE. lpnLengthNeeded contains the required space to return the info. 
1897  *
1898  * NOTES
1899  *  The information returned is constrained by the callers access rights and
1900  *  privileges.
1901  */
1902 BOOL WINAPI
1903 GetFileSecurityA( LPCSTR lpFileName,
1904                     SECURITY_INFORMATION RequestedInformation,
1905                     PSECURITY_DESCRIPTOR pSecurityDescriptor,
1906                     DWORD nLength, LPDWORD lpnLengthNeeded )
1907 {
1908     DWORD len;
1909     BOOL r;
1910     LPWSTR name = NULL;
1911
1912     if( lpFileName )
1913     {
1914         len = MultiByteToWideChar( CP_ACP, 0, lpFileName, -1, NULL, 0 );
1915         name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1916         MultiByteToWideChar( CP_ACP, 0, lpFileName, -1, name, len );
1917     }
1918
1919     r = GetFileSecurityW( name, RequestedInformation, pSecurityDescriptor,
1920                           nLength, lpnLengthNeeded );
1921     HeapFree( GetProcessHeap(), 0, name );
1922
1923     return r;
1924 }
1925
1926 /******************************************************************************
1927  * GetFileSecurityW [ADVAPI32.@]
1928  *
1929  * See GetFileSecurityA.
1930  */
1931 BOOL WINAPI
1932 GetFileSecurityW( LPCWSTR lpFileName,
1933                     SECURITY_INFORMATION RequestedInformation,
1934                     PSECURITY_DESCRIPTOR pSecurityDescriptor,
1935                     DWORD nLength, LPDWORD lpnLengthNeeded )
1936 {
1937     HANDLE hfile;
1938     NTSTATUS status;
1939     DWORD access = 0;
1940
1941     TRACE("(%s,%d,%p,%d,%p)\n", debugstr_w(lpFileName),
1942           RequestedInformation, pSecurityDescriptor,
1943           nLength, lpnLengthNeeded);
1944
1945     if (RequestedInformation & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|
1946                                 DACL_SECURITY_INFORMATION))
1947         access |= READ_CONTROL;
1948     if (RequestedInformation & SACL_SECURITY_INFORMATION)
1949         access |= ACCESS_SYSTEM_SECURITY;
1950
1951     hfile = CreateFileW( lpFileName, access, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
1952                          NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1953     if ( hfile == INVALID_HANDLE_VALUE )
1954         return FALSE;
1955
1956     status = NtQuerySecurityObject( hfile, RequestedInformation, pSecurityDescriptor,
1957                                     nLength, lpnLengthNeeded );
1958     CloseHandle( hfile );
1959     return set_ntstatus( status );
1960 }
1961
1962
1963 /******************************************************************************
1964  * LookupAccountSidA [ADVAPI32.@]
1965  */
1966 BOOL WINAPI
1967 LookupAccountSidA(
1968         IN LPCSTR system,
1969         IN PSID sid,
1970         OUT LPSTR account,
1971         IN OUT LPDWORD accountSize,
1972         OUT LPSTR domain,
1973         IN OUT LPDWORD domainSize,
1974         OUT PSID_NAME_USE name_use )
1975 {
1976     DWORD len;
1977     BOOL r;
1978     LPWSTR systemW = NULL;
1979     LPWSTR accountW = NULL;
1980     LPWSTR domainW = NULL;
1981     DWORD accountSizeW = *accountSize;
1982     DWORD domainSizeW = *domainSize;
1983
1984     if (system) {
1985         len = MultiByteToWideChar( CP_ACP, 0, system, -1, NULL, 0 );
1986         systemW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
1987         MultiByteToWideChar( CP_ACP, 0, system, -1, systemW, len );
1988     }
1989     if (account)
1990         accountW = HeapAlloc( GetProcessHeap(), 0, accountSizeW * sizeof(WCHAR) );
1991     if (domain)
1992         domainW = HeapAlloc( GetProcessHeap(), 0, domainSizeW * sizeof(WCHAR) );
1993
1994     r = LookupAccountSidW( systemW, sid, accountW, &accountSizeW, domainW, &domainSizeW, name_use );
1995
1996     if (r) {
1997         if (accountW && *accountSize) {
1998             len = WideCharToMultiByte( CP_ACP, 0, accountW, -1, NULL, 0, NULL, NULL );
1999             WideCharToMultiByte( CP_ACP, 0, accountW, -1, account, len, NULL, NULL );
2000             *accountSize = len;
2001         } else
2002             *accountSize = accountSizeW + 1;
2003
2004         if (domainW && *domainSize) {
2005             len = WideCharToMultiByte( CP_ACP, 0, domainW, -1, NULL, 0, NULL, NULL );
2006             WideCharToMultiByte( CP_ACP, 0, domainW, -1, domain, len, NULL, NULL );
2007             *domainSize = len;
2008         } else
2009             *domainSize = domainSizeW + 1;
2010     }
2011
2012     HeapFree( GetProcessHeap(), 0, systemW );
2013     HeapFree( GetProcessHeap(), 0, accountW );
2014     HeapFree( GetProcessHeap(), 0, domainW );
2015
2016     return r;
2017 }
2018
2019 /******************************************************************************
2020  * LookupAccountSidW [ADVAPI32.@]
2021  *
2022  * PARAMS
2023  *   system      []
2024  *   sid         []
2025  *   account     []
2026  *   accountSize []
2027  *   domain      []
2028  *   domainSize  []
2029  *   name_use    []
2030  */
2031
2032 BOOL WINAPI
2033 LookupAccountSidW(
2034         IN LPCWSTR system,
2035         IN PSID sid,
2036         OUT LPWSTR account,
2037         IN OUT LPDWORD accountSize,
2038         OUT LPWSTR domain,
2039         IN OUT LPDWORD domainSize,
2040         OUT PSID_NAME_USE name_use )
2041 {
2042     unsigned int i, j;
2043     const WCHAR * ac = NULL;
2044     const WCHAR * dm = NULL;
2045     SID_NAME_USE use = 0;
2046     LPWSTR computer_name = NULL;
2047     LPWSTR account_name = NULL;
2048
2049     TRACE("(%s,sid=%s,%p,%p(%u),%p,%p(%u),%p)\n",
2050           debugstr_w(system),debugstr_sid(sid),
2051           account,accountSize,accountSize?*accountSize:0,
2052           domain,domainSize,domainSize?*domainSize:0,
2053           name_use);
2054
2055     if (!ADVAPI_IsLocalComputer(system)) {
2056         FIXME("Only local computer supported!\n");
2057         SetLastError(RPC_S_SERVER_UNAVAILABLE);
2058         return FALSE;
2059     }
2060
2061     /* check the well known SIDs first */
2062     for (i = 0; i <= 60; i++) {
2063         if (IsWellKnownSid(sid, i)) {
2064             for (j = 0; j < (sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0])); j++) {
2065                 if (ACCOUNT_SIDS[j].type == i) {
2066                     ac = ACCOUNT_SIDS[j].account;
2067                     dm = ACCOUNT_SIDS[j].domain;
2068                     use = ACCOUNT_SIDS[j].name_use;
2069                 }
2070             }
2071             break;
2072         }
2073     }
2074
2075     if (dm == NULL) {
2076         MAX_SID local;
2077
2078         /* check for the local computer next */
2079         if (ADVAPI_GetComputerSid(&local)) {
2080             DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
2081             BOOL result;
2082
2083             computer_name = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
2084             result = GetComputerNameW(computer_name,  &size);
2085
2086             if (result) {
2087                 if (EqualSid(sid, &local)) {
2088                     dm = computer_name;
2089                     ac = Blank;
2090                     use = 3;
2091                 } else {
2092                     local.SubAuthorityCount++;
2093
2094                     if (EqualPrefixSid(sid, &local)) {
2095                         dm = computer_name;
2096                         use = 1;
2097                         switch (((MAX_SID *)sid)->SubAuthority[4]) {
2098                         case DOMAIN_USER_RID_ADMIN:
2099                             ac = Administrator;
2100                             break;
2101                         case DOMAIN_USER_RID_GUEST:
2102                             ac = Guest;
2103                             break;
2104                         case DOMAIN_GROUP_RID_ADMINS:
2105                             ac = Domain_Admins;
2106                             break;
2107                         case DOMAIN_GROUP_RID_USERS:
2108                             ac = Domain_Users;
2109                             break;
2110                         case DOMAIN_GROUP_RID_GUESTS:
2111                             ac = Domain_Guests;
2112                             break;
2113                         case DOMAIN_GROUP_RID_COMPUTERS:
2114                             ac = Domain_Computers;
2115                             break;
2116                         case DOMAIN_GROUP_RID_CONTROLLERS:
2117                             ac = Domain_Controllers;
2118                             break;
2119                         case DOMAIN_GROUP_RID_CERT_ADMINS:
2120                             ac = Cert_Publishers;
2121                             break;
2122                         case DOMAIN_GROUP_RID_SCHEMA_ADMINS:
2123                             ac = Schema_Admins;
2124                             break;
2125                         case DOMAIN_GROUP_RID_ENTERPRISE_ADMINS:
2126                             ac = Enterprise_Admins;
2127                             break;
2128                         case DOMAIN_GROUP_RID_POLICY_ADMINS:
2129                             ac = Group_Policy_Creator_Owners;
2130                             break;
2131                         case DOMAIN_ALIAS_RID_RAS_SERVERS:
2132                             ac = RAS_and_IAS_Servers;
2133                             break;
2134                         case 1000:      /* first user account */
2135                             size = UNLEN + 1;
2136                             account_name = HeapAlloc(
2137                                 GetProcessHeap(), 0, size * sizeof(WCHAR));
2138                             if (GetUserNameW(account_name, &size))
2139                                 ac = account_name;
2140                             else
2141                                 dm = NULL;
2142
2143                             break;
2144                         default:
2145                             dm = NULL;
2146                             break;
2147                         }
2148                     }
2149                 }
2150             }
2151         }
2152     }
2153
2154     if (dm) {
2155         DWORD ac_len = lstrlenW(ac);
2156         DWORD dm_len = lstrlenW(dm);
2157         BOOL status = TRUE;
2158
2159         if (*accountSize > ac_len) {
2160             if (account)
2161                 lstrcpyW(account, ac);
2162         }
2163         if (*domainSize > dm_len) {
2164             if (domain)
2165                 lstrcpyW(domain, dm);
2166         }
2167         if (((*accountSize != 0) && (*accountSize < ac_len)) ||
2168             ((*domainSize != 0) && (*domainSize < dm_len))) {
2169             SetLastError(ERROR_INSUFFICIENT_BUFFER);
2170             status = FALSE;
2171         }
2172         if (*domainSize)
2173             *domainSize = dm_len;
2174         else
2175             *domainSize = dm_len + 1;
2176         if (*accountSize)
2177             *accountSize = ac_len;
2178         else
2179             *accountSize = ac_len + 1;
2180         *name_use = use;
2181         HeapFree(GetProcessHeap(), 0, account_name);
2182         HeapFree(GetProcessHeap(), 0, computer_name);
2183         return status;
2184     }
2185
2186     HeapFree(GetProcessHeap(), 0, account_name);
2187     HeapFree(GetProcessHeap(), 0, computer_name);
2188     SetLastError(ERROR_NONE_MAPPED);
2189     return FALSE;
2190 }
2191
2192 /******************************************************************************
2193  * SetFileSecurityA [ADVAPI32.@]
2194  *
2195  * See SetFileSecurityW.
2196  */
2197 BOOL WINAPI SetFileSecurityA( LPCSTR lpFileName,
2198                                 SECURITY_INFORMATION RequestedInformation,
2199                                 PSECURITY_DESCRIPTOR pSecurityDescriptor)
2200 {
2201     DWORD len;
2202     BOOL r;
2203     LPWSTR name = NULL;
2204
2205     if( lpFileName )
2206     {
2207         len = MultiByteToWideChar( CP_ACP, 0, lpFileName, -1, NULL, 0 );
2208         name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
2209         MultiByteToWideChar( CP_ACP, 0, lpFileName, -1, name, len );
2210     }
2211
2212     r = SetFileSecurityW( name, RequestedInformation, pSecurityDescriptor );
2213     HeapFree( GetProcessHeap(), 0, name );
2214
2215     return r;
2216 }
2217
2218 /******************************************************************************
2219  * SetFileSecurityW [ADVAPI32.@]
2220  *
2221  * Sets the security of a file or directory.
2222  *
2223  * PARAMS
2224  *   lpFileName           []
2225  *   RequestedInformation []
2226  *   pSecurityDescriptor  []
2227  *
2228  * RETURNS
2229  *  Success: TRUE.
2230  *  Failure: FALSE.
2231  */
2232 BOOL WINAPI
2233 SetFileSecurityW( LPCWSTR lpFileName,
2234                     SECURITY_INFORMATION RequestedInformation,
2235                     PSECURITY_DESCRIPTOR pSecurityDescriptor )
2236 {
2237     HANDLE file;
2238     DWORD access = 0;
2239     NTSTATUS status;
2240
2241     TRACE("(%s, 0x%x, %p)\n", debugstr_w(lpFileName), RequestedInformation,
2242           pSecurityDescriptor );
2243
2244     if (RequestedInformation & OWNER_SECURITY_INFORMATION ||
2245         RequestedInformation & GROUP_SECURITY_INFORMATION)
2246         access |= WRITE_OWNER;
2247     if (RequestedInformation & SACL_SECURITY_INFORMATION)
2248         access |= ACCESS_SYSTEM_SECURITY;
2249     if (RequestedInformation & DACL_SECURITY_INFORMATION)
2250         access |= WRITE_DAC;
2251
2252     file = CreateFileW( lpFileName, access, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
2253                         NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL );
2254     if (file == INVALID_HANDLE_VALUE)
2255         return FALSE;
2256
2257     status = NtSetSecurityObject( file, RequestedInformation, pSecurityDescriptor );
2258     CloseHandle( file );
2259     return set_ntstatus( status );
2260 }
2261
2262 /******************************************************************************
2263  * QueryWindows31FilesMigration [ADVAPI32.@]
2264  *
2265  * PARAMS
2266  *   x1 []
2267  */
2268 BOOL WINAPI
2269 QueryWindows31FilesMigration( DWORD x1 )
2270 {
2271         FIXME("(%d):stub\n",x1);
2272         return TRUE;
2273 }
2274
2275 /******************************************************************************
2276  * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@]
2277  *
2278  * PARAMS
2279  *   x1 []
2280  *   x2 []
2281  *   x3 []
2282  *   x4 []
2283  */
2284 BOOL WINAPI
2285 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3,
2286                                                DWORD x4 )
2287 {
2288         FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4);
2289         return TRUE;
2290 }
2291
2292 /******************************************************************************
2293  * NotifyBootConfigStatus [ADVAPI32.@]
2294  *
2295  * PARAMS
2296  *   x1 []
2297  */
2298 BOOL WINAPI
2299 NotifyBootConfigStatus( BOOL x1 )
2300 {
2301         FIXME("(0x%08d):stub\n",x1);
2302         return 1;
2303 }
2304
2305 /******************************************************************************
2306  * RevertToSelf [ADVAPI32.@]
2307  *
2308  * Ends the impersonation of a user.
2309  *
2310  * PARAMS
2311  *   void []
2312  *
2313  * RETURNS
2314  *  Success: TRUE.
2315  *  Failure: FALSE.
2316  */
2317 BOOL WINAPI
2318 RevertToSelf( void )
2319 {
2320     HANDLE Token = NULL;
2321     return set_ntstatus( NtSetInformationThread( GetCurrentThread(),
2322         ThreadImpersonationToken, &Token, sizeof(Token) ) );
2323 }
2324
2325 /******************************************************************************
2326  * ImpersonateSelf [ADVAPI32.@]
2327  *
2328  * Makes an impersonation token that represents the process user and assigns
2329  * to the current thread.
2330  *
2331  * PARAMS
2332  *  ImpersonationLevel [I] Level at which to impersonate.
2333  *
2334  * RETURNS
2335  *  Success: TRUE.
2336  *  Failure: FALSE.
2337  */
2338 BOOL WINAPI
2339 ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
2340 {
2341     return set_ntstatus( RtlImpersonateSelf( ImpersonationLevel ) );
2342 }
2343
2344 /******************************************************************************
2345  * ImpersonateLoggedOnUser [ADVAPI32.@]
2346  */
2347 BOOL WINAPI ImpersonateLoggedOnUser(HANDLE hToken)
2348 {
2349     DWORD size;
2350     NTSTATUS Status;
2351     HANDLE ImpersonationToken;
2352     TOKEN_TYPE Type;
2353     static BOOL warn = TRUE;
2354
2355     if (warn)
2356     {
2357         FIXME( "(%p)\n", hToken );
2358         warn = FALSE;
2359     }
2360     if (!GetTokenInformation( hToken, TokenType, &Type,
2361                               sizeof(TOKEN_TYPE), &size ))
2362         return FALSE;
2363
2364     if (Type == TokenPrimary)
2365     {
2366         OBJECT_ATTRIBUTES ObjectAttributes;
2367
2368         InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
2369
2370         Status = NtDuplicateToken( hToken,
2371                                    TOKEN_IMPERSONATE | TOKEN_QUERY,
2372                                    &ObjectAttributes,
2373                                    SecurityImpersonation,
2374                                    TokenImpersonation,
2375                                    &ImpersonationToken );
2376         if (Status != STATUS_SUCCESS)
2377         {
2378             ERR( "NtDuplicateToken failed with error 0x%08x\n", Status );
2379             SetLastError( RtlNtStatusToDosError( Status ) );
2380             return FALSE;
2381         }
2382     }
2383     else
2384         ImpersonationToken = hToken;
2385
2386     Status = NtSetInformationThread( GetCurrentThread(),
2387                                      ThreadImpersonationToken,
2388                                      &ImpersonationToken,
2389                                      sizeof(ImpersonationToken) );
2390
2391     if (Type == TokenPrimary)
2392         NtClose( ImpersonationToken );
2393
2394     if (Status != STATUS_SUCCESS)
2395     {
2396         ERR( "NtSetInformationThread failed with error 0x%08x\n", Status );
2397         SetLastError( RtlNtStatusToDosError( Status ) );
2398         return FALSE;
2399     }
2400
2401     return TRUE;
2402 }
2403
2404 /******************************************************************************
2405  * AccessCheck [ADVAPI32.@]
2406  */
2407 BOOL WINAPI
2408 AccessCheck(
2409         PSECURITY_DESCRIPTOR SecurityDescriptor,
2410         HANDLE ClientToken,
2411         DWORD DesiredAccess,
2412         PGENERIC_MAPPING GenericMapping,
2413         PPRIVILEGE_SET PrivilegeSet,
2414         LPDWORD PrivilegeSetLength,
2415         LPDWORD GrantedAccess,
2416         LPBOOL AccessStatus)
2417 {
2418     NTSTATUS access_status;
2419     BOOL ret = set_ntstatus( NtAccessCheck(SecurityDescriptor, ClientToken, DesiredAccess,
2420                                            GenericMapping, PrivilegeSet, PrivilegeSetLength,
2421                                            GrantedAccess, &access_status) );
2422     if (ret) *AccessStatus = set_ntstatus( access_status );
2423     return ret;
2424 }
2425
2426
2427 /******************************************************************************
2428  * AccessCheckByType [ADVAPI32.@]
2429  */
2430 BOOL WINAPI AccessCheckByType(
2431     PSECURITY_DESCRIPTOR pSecurityDescriptor, 
2432     PSID PrincipalSelfSid,
2433     HANDLE ClientToken, 
2434     DWORD DesiredAccess, 
2435     POBJECT_TYPE_LIST ObjectTypeList,
2436     DWORD ObjectTypeListLength,
2437     PGENERIC_MAPPING GenericMapping,
2438     PPRIVILEGE_SET PrivilegeSet,
2439     LPDWORD PrivilegeSetLength, 
2440     LPDWORD GrantedAccess,
2441     LPBOOL AccessStatus)
2442 {
2443         FIXME("stub\n");
2444
2445         *AccessStatus = TRUE;
2446
2447         return !*AccessStatus;
2448 }
2449
2450 /******************************************************************************
2451  * MapGenericMask [ADVAPI32.@]
2452  *
2453  * Maps generic access rights into specific access rights according to the
2454  * supplied mapping.
2455  *
2456  * PARAMS
2457  *  AccessMask     [I/O] Access rights.
2458  *  GenericMapping [I] The mapping between generic and specific rights.
2459  *
2460  * RETURNS
2461  *  Nothing.
2462  */
2463 VOID WINAPI MapGenericMask( PDWORD AccessMask, PGENERIC_MAPPING GenericMapping )
2464 {
2465     RtlMapGenericMask( AccessMask, GenericMapping );
2466 }
2467
2468 /*************************************************************************
2469  * SetKernelObjectSecurity [ADVAPI32.@]
2470  */
2471 BOOL WINAPI SetKernelObjectSecurity (
2472         IN HANDLE Handle,
2473         IN SECURITY_INFORMATION SecurityInformation,
2474         IN PSECURITY_DESCRIPTOR SecurityDescriptor )
2475 {
2476     return set_ntstatus (NtSetSecurityObject (Handle, SecurityInformation, SecurityDescriptor));
2477 }
2478
2479
2480 /******************************************************************************
2481  *  AddAuditAccessAce [ADVAPI32.@]
2482  */
2483 BOOL WINAPI AddAuditAccessAce(
2484     IN OUT PACL pAcl, 
2485     IN DWORD dwAceRevision, 
2486     IN DWORD dwAccessMask, 
2487     IN PSID pSid, 
2488     IN BOOL bAuditSuccess, 
2489     IN BOOL bAuditFailure) 
2490 {
2491     return set_ntstatus( RtlAddAuditAccessAce(pAcl, dwAceRevision, dwAccessMask, pSid, 
2492                                               bAuditSuccess, bAuditFailure) ); 
2493 }
2494
2495 /******************************************************************************
2496  *  AddAuditAccessAce [ADVAPI32.@]
2497  */
2498 BOOL WINAPI AddAuditAccessAceEx(
2499     IN OUT PACL pAcl,
2500     IN DWORD dwAceRevision,
2501     IN DWORD dwAceFlags,
2502     IN DWORD dwAccessMask,
2503     IN PSID pSid,
2504     IN BOOL bAuditSuccess,
2505     IN BOOL bAuditFailure)
2506 {
2507     return set_ntstatus( RtlAddAuditAccessAceEx(pAcl, dwAceRevision, dwAceFlags, dwAccessMask, pSid,
2508                                               bAuditSuccess, bAuditFailure) );
2509 }
2510
2511 /******************************************************************************
2512  * LookupAccountNameA [ADVAPI32.@]
2513  */
2514 BOOL WINAPI
2515 LookupAccountNameA(
2516         IN LPCSTR system,
2517         IN LPCSTR account,
2518         OUT PSID sid,
2519         OUT LPDWORD cbSid,
2520         LPSTR ReferencedDomainName,
2521         IN OUT LPDWORD cbReferencedDomainName,
2522         OUT PSID_NAME_USE name_use )
2523 {
2524     BOOL ret;
2525     UNICODE_STRING lpSystemW;
2526     UNICODE_STRING lpAccountW;
2527     LPWSTR lpReferencedDomainNameW = NULL;
2528
2529     RtlCreateUnicodeStringFromAsciiz(&lpSystemW, system);
2530     RtlCreateUnicodeStringFromAsciiz(&lpAccountW, account);
2531
2532     if (ReferencedDomainName)
2533         lpReferencedDomainNameW = HeapAlloc(GetProcessHeap(), 0, *cbReferencedDomainName * sizeof(WCHAR));
2534
2535     ret = LookupAccountNameW(lpSystemW.Buffer, lpAccountW.Buffer, sid, cbSid, lpReferencedDomainNameW,
2536         cbReferencedDomainName, name_use);
2537
2538     if (ret && lpReferencedDomainNameW)
2539     {
2540         WideCharToMultiByte(CP_ACP, 0, lpReferencedDomainNameW, -1,
2541             ReferencedDomainName, *cbReferencedDomainName+1, NULL, NULL);
2542     }
2543
2544     RtlFreeUnicodeString(&lpSystemW);
2545     RtlFreeUnicodeString(&lpAccountW);
2546     HeapFree(GetProcessHeap(), 0, lpReferencedDomainNameW);
2547
2548     return ret;
2549 }
2550
2551 /******************************************************************************
2552  * lookup_user_account_name
2553  */
2554 static BOOL lookup_user_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2555                                      LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2556 {
2557     /* Default implementation: Always return a default SID */
2558     SID_IDENTIFIER_AUTHORITY identifierAuthority = {SECURITY_NT_AUTHORITY};
2559     BOOL ret;
2560     PSID pSid;
2561     static const WCHAR dm[] = {'D','O','M','A','I','N',0};
2562     DWORD nameLen;
2563     LPCWSTR domainName;
2564
2565     ret = AllocateAndInitializeSid(&identifierAuthority,
2566         2,
2567         SECURITY_BUILTIN_DOMAIN_RID,
2568         DOMAIN_ALIAS_RID_ADMINS,
2569         0, 0, 0, 0, 0, 0,
2570         &pSid);
2571
2572     if (!ret)
2573        return FALSE;
2574
2575     if (!RtlValidSid(pSid))
2576     {
2577        FreeSid(pSid);
2578        return FALSE;
2579     }
2580
2581     if (Sid != NULL && (*cbSid >= GetLengthSid(pSid)))
2582        CopySid(*cbSid, Sid, pSid);
2583     if (*cbSid < GetLengthSid(pSid))
2584     {
2585        SetLastError(ERROR_INSUFFICIENT_BUFFER);
2586        ret = FALSE;
2587     }
2588     *cbSid = GetLengthSid(pSid);
2589
2590     domainName = dm;
2591     nameLen = strlenW(domainName);
2592
2593     if (*cchReferencedDomainName <= nameLen || !ret)
2594     {
2595         SetLastError(ERROR_INSUFFICIENT_BUFFER);
2596         nameLen += 1;
2597         ret = FALSE;
2598     }
2599     else if (ReferencedDomainName)
2600         strcpyW(ReferencedDomainName, domainName);
2601
2602     *cchReferencedDomainName = nameLen;
2603
2604     if (ret)
2605         *peUse = SidTypeUser;
2606
2607     FreeSid(pSid);
2608
2609     return ret;
2610 }
2611
2612 /******************************************************************************
2613  * lookup_computer_account_name
2614  */
2615 static BOOL lookup_computer_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2616                                          LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2617 {
2618     MAX_SID local;
2619     BOOL ret;
2620     static const WCHAR dm[] = {'D','O','M','A','I','N',0};
2621     DWORD nameLen;
2622     LPCWSTR domainName;
2623
2624     if ((ret = ADVAPI_GetComputerSid(&local)))
2625     {
2626         if (Sid != NULL && (*cbSid >= GetLengthSid(&local)))
2627            CopySid(*cbSid, Sid, &local);
2628         if (*cbSid < GetLengthSid(&local))
2629         {
2630            SetLastError(ERROR_INSUFFICIENT_BUFFER);
2631            ret = FALSE;
2632         }
2633         *cbSid = GetLengthSid(&local);
2634     }
2635
2636     domainName = dm;
2637     nameLen = strlenW(domainName);
2638
2639     if (*cchReferencedDomainName <= nameLen || !ret)
2640     {
2641         SetLastError(ERROR_INSUFFICIENT_BUFFER);
2642         nameLen += 1;
2643         ret = FALSE;
2644     }
2645     else if (ReferencedDomainName)
2646         strcpyW(ReferencedDomainName, domainName);
2647
2648     *cchReferencedDomainName = nameLen;
2649
2650     if (ret)
2651         *peUse = SidTypeDomain;
2652
2653     return ret;
2654 }
2655
2656 static void split_domain_account( const LSA_UNICODE_STRING *str, LSA_UNICODE_STRING *account,
2657                                   LSA_UNICODE_STRING *domain )
2658 {
2659     WCHAR *p = str->Buffer + str->Length / sizeof(WCHAR) - 1;
2660
2661     while (p > str->Buffer && *p != '\\') p--;
2662
2663     if (*p == '\\')
2664     {
2665         domain->Buffer = str->Buffer;
2666         domain->Length = (p - str->Buffer) * sizeof(WCHAR);
2667
2668         account->Buffer = p + 1;
2669         account->Length = str->Length - ((p - str->Buffer + 1) * sizeof(WCHAR));
2670     }
2671     else
2672     {
2673         domain->Buffer = NULL;
2674         domain->Length = 0;
2675
2676         account->Buffer = str->Buffer;
2677         account->Length = str->Length;
2678     }
2679 }
2680
2681 static BOOL match_domain( ULONG idx, LSA_UNICODE_STRING *domain )
2682 {
2683     ULONG len = strlenW( ACCOUNT_SIDS[idx].domain );
2684
2685     if (len == domain->Length / sizeof(WCHAR) && !strncmpiW( domain->Buffer, ACCOUNT_SIDS[idx].domain, len ))
2686         return TRUE;
2687
2688     return FALSE;
2689 }
2690
2691 static BOOL match_account( ULONG idx, LSA_UNICODE_STRING *account )
2692 {
2693     ULONG len = strlenW( ACCOUNT_SIDS[idx].account );
2694
2695     if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].account, len ))
2696         return TRUE;
2697
2698     if (ACCOUNT_SIDS[idx].alias)
2699     {
2700         len = strlenW( ACCOUNT_SIDS[idx].alias );
2701         if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].alias, len ))
2702             return TRUE;
2703     }
2704     return FALSE;
2705 }
2706
2707 /*
2708  * Helper function for LookupAccountNameW
2709  */
2710 BOOL lookup_local_wellknown_name( LSA_UNICODE_STRING *account_and_domain,
2711                                   PSID Sid, LPDWORD cbSid,
2712                                   LPWSTR ReferencedDomainName,
2713                                   LPDWORD cchReferencedDomainName,
2714                                   PSID_NAME_USE peUse, BOOL *handled )
2715 {
2716     PSID pSid;
2717     LSA_UNICODE_STRING account, domain;
2718     BOOL ret = TRUE;
2719     ULONG i;
2720
2721     *handled = FALSE;
2722     split_domain_account( account_and_domain, &account, &domain );
2723
2724     for (i = 0; i < sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0]); i++)
2725     {
2726         /* check domain first */
2727         if (domain.Buffer && !match_domain( i, &domain )) continue;
2728
2729         if (match_account( i, &account ))
2730         {
2731             DWORD len, sidLen = SECURITY_MAX_SID_SIZE;
2732
2733             if (!(pSid = HeapAlloc( GetProcessHeap(), 0, sidLen ))) return FALSE;
2734
2735             if ((ret = CreateWellKnownSid( ACCOUNT_SIDS[i].type, NULL, pSid, &sidLen )))
2736             {
2737                 if (*cbSid < sidLen)
2738                 {
2739                     SetLastError(ERROR_INSUFFICIENT_BUFFER);
2740                     ret = FALSE;
2741                 }
2742                 else if (Sid)
2743                 {
2744                     CopySid(*cbSid, Sid, pSid);
2745                 }
2746                 *cbSid = sidLen;
2747             }
2748
2749             len = strlenW( ACCOUNT_SIDS[i].domain );
2750             if (*cchReferencedDomainName <= len || !ret)
2751             {
2752                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2753                 len++;
2754                 ret = FALSE;
2755             }
2756             else if (ReferencedDomainName)
2757             {
2758                 strcpyW( ReferencedDomainName, ACCOUNT_SIDS[i].domain );
2759             }
2760
2761             *cchReferencedDomainName = len;
2762             if (ret)
2763                 *peUse = ACCOUNT_SIDS[i].name_use;
2764
2765             HeapFree(GetProcessHeap(), 0, pSid);
2766             *handled = TRUE;
2767             return ret;
2768         }
2769     }
2770     return ret;
2771 }
2772
2773 BOOL lookup_local_user_name( LSA_UNICODE_STRING *account_and_domain,
2774                              PSID Sid, LPDWORD cbSid,
2775                              LPWSTR ReferencedDomainName,
2776                              LPDWORD cchReferencedDomainName,
2777                              PSID_NAME_USE peUse, BOOL *handled )
2778 {
2779     DWORD nameLen;
2780     LPWSTR userName = NULL;
2781     LSA_UNICODE_STRING account, domain;
2782     BOOL ret = TRUE;
2783
2784     *handled = FALSE;
2785     split_domain_account( account_and_domain, &account, &domain );
2786
2787     /* Let the current Unix user id masquerade as first Windows user account */
2788
2789     nameLen = UNLEN + 1;
2790     if (!(userName = HeapAlloc( GetProcessHeap(), 0, nameLen * sizeof(WCHAR) ))) return FALSE;
2791
2792     if (domain.Buffer)
2793     {
2794         /* check to make sure this account is on this computer */
2795         if (GetComputerNameW( userName, &nameLen ) &&
2796             (domain.Length / sizeof(WCHAR) != nameLen || strncmpW( domain.Buffer, userName, nameLen )))
2797         {
2798             SetLastError(ERROR_NONE_MAPPED);
2799             ret = FALSE;
2800         }
2801         nameLen = UNLEN + 1;
2802     }
2803
2804     if (GetUserNameW( userName, &nameLen ) &&
2805         account.Length / sizeof(WCHAR) == nameLen - 1 && !strncmpW( account.Buffer, userName, nameLen - 1 ))
2806     {
2807             ret = lookup_user_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2808             *handled = TRUE;
2809     }
2810     else
2811     {
2812         nameLen = UNLEN + 1;
2813         if (GetComputerNameW( userName, &nameLen ) &&
2814             account.Length / sizeof(WCHAR) == nameLen && !strncmpW( account.Buffer, userName , nameLen ))
2815         {
2816             ret = lookup_computer_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2817             *handled = TRUE;
2818         }
2819     }
2820
2821     HeapFree(GetProcessHeap(), 0, userName);
2822     return ret;
2823 }
2824
2825 /******************************************************************************
2826  * LookupAccountNameW [ADVAPI32.@]
2827  */
2828 BOOL WINAPI LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid,
2829                                 LPDWORD cbSid, LPWSTR ReferencedDomainName,
2830                                 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2831 {
2832     BOOL ret, handled;
2833     LSA_UNICODE_STRING account;
2834
2835     FIXME("%s %s %p %p %p %p %p - stub\n", debugstr_w(lpSystemName), debugstr_w(lpAccountName),
2836           Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse);
2837
2838     if (!ADVAPI_IsLocalComputer( lpSystemName ))
2839     {
2840         SetLastError( RPC_S_SERVER_UNAVAILABLE );
2841         return FALSE;
2842     }
2843
2844     if (!lpAccountName || !strcmpW( lpAccountName, Blank ))
2845     {
2846         lpAccountName = BUILTIN;
2847     }
2848
2849     RtlInitUnicodeString( &account, lpAccountName );
2850
2851     /* Check well known SIDs first */
2852     ret = lookup_local_wellknown_name( &account, Sid, cbSid, ReferencedDomainName,
2853                                        cchReferencedDomainName, peUse, &handled );
2854     if (handled)
2855         return ret;
2856
2857     /* Check user names */
2858     ret = lookup_local_user_name( &account, Sid, cbSid, ReferencedDomainName,
2859                                   cchReferencedDomainName, peUse, &handled);
2860     if (handled)
2861         return ret;
2862
2863     SetLastError( ERROR_NONE_MAPPED );
2864     return FALSE;
2865 }
2866
2867 /******************************************************************************
2868  * PrivilegeCheck [ADVAPI32.@]
2869  */
2870 BOOL WINAPI PrivilegeCheck( HANDLE ClientToken, PPRIVILEGE_SET RequiredPrivileges, LPBOOL pfResult)
2871 {
2872     BOOL ret;
2873     BOOLEAN Result;
2874
2875     TRACE("%p %p %p\n", ClientToken, RequiredPrivileges, pfResult);
2876
2877     ret = set_ntstatus (NtPrivilegeCheck (ClientToken, RequiredPrivileges, &Result));
2878     if (ret)
2879         *pfResult = Result;
2880     return ret;
2881 }
2882
2883 /******************************************************************************
2884  * AccessCheckAndAuditAlarmA [ADVAPI32.@]
2885  */
2886 BOOL WINAPI AccessCheckAndAuditAlarmA(LPCSTR Subsystem, LPVOID HandleId, LPSTR ObjectTypeName,
2887   LPSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
2888   PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
2889   LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
2890 {
2891         FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_a(Subsystem),
2892                 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName),
2893                 SecurityDescriptor, DesiredAccess, GenericMapping,
2894                 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
2895         return TRUE;
2896 }
2897
2898 /******************************************************************************
2899  * AccessCheckAndAuditAlarmW [ADVAPI32.@]
2900  */
2901 BOOL WINAPI AccessCheckAndAuditAlarmW(LPCWSTR Subsystem, LPVOID HandleId, LPWSTR ObjectTypeName,
2902   LPWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
2903   PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
2904   LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
2905 {
2906         FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_w(Subsystem),
2907                 HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName),
2908                 SecurityDescriptor, DesiredAccess, GenericMapping,
2909                 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
2910         return TRUE;
2911 }
2912
2913 BOOL WINAPI ObjectCloseAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
2914 {
2915     FIXME("stub (%s,%p,%x)\n", debugstr_a(SubsystemName), HandleId, GenerateOnClose);
2916
2917     return TRUE;
2918 }
2919
2920 BOOL WINAPI ObjectCloseAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
2921 {
2922     FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
2923
2924     return TRUE;
2925 }
2926
2927 BOOL WINAPI ObjectDeleteAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
2928 {
2929     FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
2930
2931     return TRUE;
2932 }
2933
2934 BOOL WINAPI ObjectOpenAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, LPSTR ObjectTypeName,
2935   LPSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
2936   DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
2937   LPBOOL GenerateOnClose)
2938 {
2939         FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_a(SubsystemName),
2940                 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName), pSecurityDescriptor,
2941         ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
2942         GenerateOnClose);
2943
2944     return TRUE;
2945 }
2946
2947 BOOL WINAPI ObjectOpenAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, LPWSTR ObjectTypeName,
2948   LPWSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
2949   DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
2950   LPBOOL GenerateOnClose)
2951 {
2952     FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_w(SubsystemName),
2953         HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName), pSecurityDescriptor,
2954         ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
2955         GenerateOnClose);
2956
2957     return TRUE;
2958 }
2959
2960 BOOL WINAPI ObjectPrivilegeAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
2961   DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
2962 {
2963     FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_a(SubsystemName), HandleId, ClientToken,
2964           DesiredAccess, Privileges, AccessGranted);
2965
2966     return TRUE;
2967 }
2968
2969 BOOL WINAPI ObjectPrivilegeAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
2970   DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
2971 {
2972     FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_w(SubsystemName), HandleId, ClientToken,
2973           DesiredAccess, Privileges, AccessGranted);
2974
2975     return TRUE;
2976 }
2977
2978 BOOL WINAPI PrivilegedServiceAuditAlarmA( LPCSTR SubsystemName, LPCSTR ServiceName, HANDLE ClientToken,
2979                                    PPRIVILEGE_SET Privileges, BOOL AccessGranted)
2980 {
2981     FIXME("stub (%s,%s,%p,%p,%x)\n", debugstr_a(SubsystemName), debugstr_a(ServiceName),
2982           ClientToken, Privileges, AccessGranted);
2983
2984     return TRUE;
2985 }
2986
2987 BOOL WINAPI PrivilegedServiceAuditAlarmW( LPCWSTR SubsystemName, LPCWSTR ServiceName, HANDLE ClientToken,
2988                                    PPRIVILEGE_SET Privileges, BOOL AccessGranted)
2989 {
2990     FIXME("stub %s,%s,%p,%p,%x)\n", debugstr_w(SubsystemName), debugstr_w(ServiceName),
2991           ClientToken, Privileges, AccessGranted);
2992
2993     return TRUE;
2994 }
2995
2996 /******************************************************************************
2997  * GetSecurityInfo [ADVAPI32.@]
2998  *
2999  * Retrieves a copy of the security descriptor associated with an object.
3000  *
3001  * PARAMS
3002  *  hObject              [I] A handle for the object.
3003  *  ObjectType           [I] The type of object.
3004  *  SecurityInfo         [I] A bitmask indicating what info to retrieve.
3005  *  ppsidOwner           [O] If non-null, receives a pointer to the owner SID.
3006  *  ppsidGroup           [O] If non-null, receives a pointer to the group SID.
3007  *  ppDacl               [O] If non-null, receives a pointer to the DACL.
3008  *  ppSacl               [O] If non-null, receives a pointer to the SACL.
3009  *  ppSecurityDescriptor [O] Receives a pointer to the security descriptor,
3010  *                           which must be freed with LocalFree.
3011  *
3012  * RETURNS
3013  *  ERROR_SUCCESS if all's well, and a WIN32 error code otherwise.
3014  */
3015 DWORD WINAPI GetSecurityInfo(
3016     HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3017     SECURITY_INFORMATION SecurityInfo, PSID *ppsidOwner,
3018     PSID *ppsidGroup, PACL *ppDacl, PACL *ppSacl,
3019     PSECURITY_DESCRIPTOR *ppSecurityDescriptor
3020 )
3021 {
3022     PSECURITY_DESCRIPTOR sd;
3023     NTSTATUS status;
3024     ULONG n1, n2;
3025     BOOL present, defaulted;
3026
3027     status = NtQuerySecurityObject(hObject, SecurityInfo, NULL, 0, &n1);
3028     if (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_SUCCESS)
3029         return RtlNtStatusToDosError(status);
3030
3031     sd = LocalAlloc(0, n1);
3032     if (!sd)
3033         return ERROR_NOT_ENOUGH_MEMORY;
3034
3035     status = NtQuerySecurityObject(hObject, SecurityInfo, sd, n1, &n2);
3036     if (status != STATUS_SUCCESS)
3037     {
3038         LocalFree(sd);
3039         return RtlNtStatusToDosError(status);
3040     }
3041
3042     if (ppsidOwner)
3043     {
3044         *ppsidOwner = NULL;
3045         GetSecurityDescriptorOwner(sd, ppsidOwner, &defaulted);
3046     }
3047     if (ppsidGroup)
3048     {
3049         *ppsidGroup = NULL;
3050         GetSecurityDescriptorGroup(sd, ppsidGroup, &defaulted);
3051     }
3052     if (ppDacl)
3053     {
3054         *ppDacl = NULL;
3055         GetSecurityDescriptorDacl(sd, &present, ppDacl, &defaulted);
3056     }
3057     if (ppSacl)
3058     {
3059         *ppSacl = NULL;
3060         GetSecurityDescriptorSacl(sd, &present, ppSacl, &defaulted);
3061     }
3062     if (ppSecurityDescriptor)
3063         *ppSecurityDescriptor = sd;
3064
3065     return ERROR_SUCCESS;
3066 }
3067
3068 /******************************************************************************
3069  * GetSecurityInfoExA [ADVAPI32.@]
3070  */
3071 DWORD WINAPI GetSecurityInfoExA(
3072         HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3073         SECURITY_INFORMATION SecurityInfo, LPCSTR lpProvider,
3074         LPCSTR lpProperty, PACTRL_ACCESSA *ppAccessList,
3075         PACTRL_AUDITA *ppAuditList, LPSTR *lppOwner, LPSTR *lppGroup
3076 )
3077 {
3078   FIXME("stub!\n");
3079   return ERROR_BAD_PROVIDER;
3080 }
3081
3082 /******************************************************************************
3083  * GetSecurityInfoExW [ADVAPI32.@]
3084  */
3085 DWORD WINAPI GetSecurityInfoExW(
3086         HANDLE hObject, SE_OBJECT_TYPE ObjectType, 
3087         SECURITY_INFORMATION SecurityInfo, LPCWSTR lpProvider,
3088         LPCWSTR lpProperty, PACTRL_ACCESSW *ppAccessList, 
3089         PACTRL_AUDITW *ppAuditList, LPWSTR *lppOwner, LPWSTR *lppGroup
3090 )
3091 {
3092   FIXME("stub!\n");
3093   return ERROR_BAD_PROVIDER; 
3094 }
3095
3096 /******************************************************************************
3097  * BuildExplicitAccessWithNameA [ADVAPI32.@]
3098  */
3099 VOID WINAPI BuildExplicitAccessWithNameA( PEXPLICIT_ACCESSA pExplicitAccess,
3100                                           LPSTR pTrusteeName, DWORD AccessPermissions,
3101                                           ACCESS_MODE AccessMode, DWORD Inheritance )
3102 {
3103     TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_a(pTrusteeName),
3104           AccessPermissions, AccessMode, Inheritance);
3105
3106     pExplicitAccess->grfAccessPermissions = AccessPermissions;
3107     pExplicitAccess->grfAccessMode = AccessMode;
3108     pExplicitAccess->grfInheritance = Inheritance;
3109
3110     pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3111     pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3112     pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3113     pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3114     pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3115 }
3116
3117 /******************************************************************************
3118  * BuildExplicitAccessWithNameW [ADVAPI32.@]
3119  */
3120 VOID WINAPI BuildExplicitAccessWithNameW( PEXPLICIT_ACCESSW pExplicitAccess,
3121                                           LPWSTR pTrusteeName, DWORD AccessPermissions,
3122                                           ACCESS_MODE AccessMode, DWORD Inheritance )
3123 {
3124     TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_w(pTrusteeName),
3125           AccessPermissions, AccessMode, Inheritance);
3126
3127     pExplicitAccess->grfAccessPermissions = AccessPermissions;
3128     pExplicitAccess->grfAccessMode = AccessMode;
3129     pExplicitAccess->grfInheritance = Inheritance;
3130
3131     pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3132     pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3133     pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3134     pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3135     pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3136 }
3137
3138 /******************************************************************************
3139  * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
3140  */
3141 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
3142                                              SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
3143                                              LPSTR InheritedObjectTypeName, LPSTR Name )
3144 {
3145     DWORD ObjectsPresent = 0;
3146
3147     TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3148           ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
3149
3150     /* Fill the OBJECTS_AND_NAME structure */
3151     pObjName->ObjectType = ObjectType;
3152     if (ObjectTypeName != NULL)
3153     {
3154         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3155     }
3156
3157     pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3158     if (InheritedObjectTypeName != NULL)
3159     {
3160         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3161     }
3162
3163     pObjName->ObjectsPresent = ObjectsPresent;
3164     pObjName->ptstrName = Name;
3165
3166     /* Fill the TRUSTEE structure */
3167     pTrustee->pMultipleTrustee = NULL;
3168     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3169     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3170     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3171     pTrustee->ptstrName = (LPSTR)pObjName;
3172 }
3173
3174 /******************************************************************************
3175  * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
3176  */
3177 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
3178                                              SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
3179                                              LPWSTR InheritedObjectTypeName, LPWSTR Name )
3180 {
3181     DWORD ObjectsPresent = 0;
3182
3183     TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3184           ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
3185
3186     /* Fill the OBJECTS_AND_NAME structure */
3187     pObjName->ObjectType = ObjectType;
3188     if (ObjectTypeName != NULL)
3189     {
3190         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3191     }
3192
3193     pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3194     if (InheritedObjectTypeName != NULL)
3195     {
3196         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3197     }
3198
3199     pObjName->ObjectsPresent = ObjectsPresent;
3200     pObjName->ptstrName = Name;
3201
3202     /* Fill the TRUSTEE structure */
3203     pTrustee->pMultipleTrustee = NULL;
3204     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3205     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3206     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3207     pTrustee->ptstrName = (LPWSTR)pObjName;
3208 }
3209
3210 /******************************************************************************
3211  * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
3212  */
3213 VOID WINAPI BuildTrusteeWithObjectsAndSidA( PTRUSTEEA pTrustee, POBJECTS_AND_SID pObjSid,
3214                                             GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3215 {
3216     DWORD ObjectsPresent = 0;
3217
3218     TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3219
3220     /* Fill the OBJECTS_AND_SID structure */
3221     if (pObjectGuid != NULL)
3222     {
3223         pObjSid->ObjectTypeGuid = *pObjectGuid;
3224         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3225     }
3226     else
3227     {
3228         ZeroMemory(&pObjSid->ObjectTypeGuid,
3229                    sizeof(GUID));
3230     }
3231
3232     if (pInheritedObjectGuid != NULL)
3233     {
3234         pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3235         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3236     }
3237     else
3238     {
3239         ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3240                    sizeof(GUID));
3241     }
3242
3243     pObjSid->ObjectsPresent = ObjectsPresent;
3244     pObjSid->pSid = pSid;
3245
3246     /* Fill the TRUSTEE structure */
3247     pTrustee->pMultipleTrustee = NULL;
3248     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3249     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3250     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3251     pTrustee->ptstrName = (LPSTR) pObjSid;
3252 }
3253
3254 /******************************************************************************
3255  * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
3256  */
3257 VOID WINAPI BuildTrusteeWithObjectsAndSidW( PTRUSTEEW pTrustee, POBJECTS_AND_SID pObjSid,
3258                                             GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3259 {
3260     DWORD ObjectsPresent = 0;
3261
3262     TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3263
3264     /* Fill the OBJECTS_AND_SID structure */
3265     if (pObjectGuid != NULL)
3266     {
3267         pObjSid->ObjectTypeGuid = *pObjectGuid;
3268         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3269     }
3270     else
3271     {
3272         ZeroMemory(&pObjSid->ObjectTypeGuid,
3273                    sizeof(GUID));
3274     }
3275
3276     if (pInheritedObjectGuid != NULL)
3277     {
3278         pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3279         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3280     }
3281     else
3282     {
3283         ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3284                    sizeof(GUID));
3285     }
3286
3287     pObjSid->ObjectsPresent = ObjectsPresent;
3288     pObjSid->pSid = pSid;
3289
3290     /* Fill the TRUSTEE structure */
3291     pTrustee->pMultipleTrustee = NULL;
3292     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3293     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3294     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3295     pTrustee->ptstrName = (LPWSTR) pObjSid;
3296 }
3297
3298 /******************************************************************************
3299  * BuildTrusteeWithSidA [ADVAPI32.@]
3300  */
3301 VOID WINAPI BuildTrusteeWithSidA(PTRUSTEEA pTrustee, PSID pSid)
3302 {
3303     TRACE("%p %p\n", pTrustee, pSid);
3304
3305     pTrustee->pMultipleTrustee = NULL;
3306     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3307     pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3308     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3309     pTrustee->ptstrName = pSid;
3310 }
3311
3312 /******************************************************************************
3313  * BuildTrusteeWithSidW [ADVAPI32.@]
3314  */
3315 VOID WINAPI BuildTrusteeWithSidW(PTRUSTEEW pTrustee, PSID pSid)
3316 {
3317     TRACE("%p %p\n", pTrustee, pSid);
3318
3319     pTrustee->pMultipleTrustee = NULL;
3320     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3321     pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3322     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3323     pTrustee->ptstrName = pSid;
3324 }
3325
3326 /******************************************************************************
3327  * BuildTrusteeWithNameA [ADVAPI32.@]
3328  */
3329 VOID WINAPI BuildTrusteeWithNameA(PTRUSTEEA pTrustee, LPSTR name)
3330 {
3331     TRACE("%p %s\n", pTrustee, debugstr_a(name) );
3332
3333     pTrustee->pMultipleTrustee = NULL;
3334     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3335     pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3336     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3337     pTrustee->ptstrName = name;
3338 }
3339
3340 /******************************************************************************
3341  * BuildTrusteeWithNameW [ADVAPI32.@]
3342  */
3343 VOID WINAPI BuildTrusteeWithNameW(PTRUSTEEW pTrustee, LPWSTR name)
3344 {
3345     TRACE("%p %s\n", pTrustee, debugstr_w(name) );
3346
3347     pTrustee->pMultipleTrustee = NULL;
3348     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3349     pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3350     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3351     pTrustee->ptstrName = name;
3352 }
3353
3354 /****************************************************************************** 
3355  * GetTrusteeFormA [ADVAPI32.@] 
3356  */ 
3357 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee) 
3358 {  
3359     TRACE("(%p)\n", pTrustee); 
3360   
3361     if (!pTrustee) 
3362         return TRUSTEE_BAD_FORM; 
3363   
3364     return pTrustee->TrusteeForm; 
3365 }  
3366   
3367 /****************************************************************************** 
3368  * GetTrusteeFormW [ADVAPI32.@] 
3369  */ 
3370 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee) 
3371 {  
3372     TRACE("(%p)\n", pTrustee); 
3373   
3374     if (!pTrustee) 
3375         return TRUSTEE_BAD_FORM; 
3376   
3377     return pTrustee->TrusteeForm; 
3378 }  
3379   
3380 /****************************************************************************** 
3381  * GetTrusteeNameA [ADVAPI32.@] 
3382  */ 
3383 LPSTR WINAPI GetTrusteeNameA(PTRUSTEEA pTrustee) 
3384 {  
3385     TRACE("(%p)\n", pTrustee); 
3386   
3387     if (!pTrustee) 
3388         return NULL; 
3389   
3390     return pTrustee->ptstrName; 
3391 }  
3392   
3393 /****************************************************************************** 
3394  * GetTrusteeNameW [ADVAPI32.@] 
3395  */ 
3396 LPWSTR WINAPI GetTrusteeNameW(PTRUSTEEW pTrustee) 
3397 {  
3398     TRACE("(%p)\n", pTrustee); 
3399   
3400     if (!pTrustee) 
3401         return NULL; 
3402   
3403     return pTrustee->ptstrName; 
3404 }  
3405   
3406 /****************************************************************************** 
3407  * GetTrusteeTypeA [ADVAPI32.@] 
3408  */ 
3409 TRUSTEE_TYPE WINAPI GetTrusteeTypeA(PTRUSTEEA pTrustee) 
3410 {  
3411     TRACE("(%p)\n", pTrustee); 
3412   
3413     if (!pTrustee) 
3414         return TRUSTEE_IS_UNKNOWN; 
3415   
3416     return pTrustee->TrusteeType; 
3417 }  
3418   
3419 /****************************************************************************** 
3420  * GetTrusteeTypeW [ADVAPI32.@] 
3421  */ 
3422 TRUSTEE_TYPE WINAPI GetTrusteeTypeW(PTRUSTEEW pTrustee) 
3423 {  
3424     TRACE("(%p)\n", pTrustee); 
3425   
3426     if (!pTrustee) 
3427         return TRUSTEE_IS_UNKNOWN; 
3428   
3429     return pTrustee->TrusteeType; 
3430
3431  
3432 BOOL WINAPI SetAclInformation( PACL pAcl, LPVOID pAclInformation,
3433                                DWORD nAclInformationLength,
3434                                ACL_INFORMATION_CLASS dwAclInformationClass )
3435 {
3436     FIXME("%p %p 0x%08x 0x%08x - stub\n", pAcl, pAclInformation,
3437           nAclInformationLength, dwAclInformationClass);
3438
3439     return TRUE;
3440 }
3441
3442 /******************************************************************************
3443  * SetEntriesInAclA [ADVAPI32.@]
3444  */
3445 DWORD WINAPI SetEntriesInAclA( ULONG count, PEXPLICIT_ACCESSA pEntries,
3446                                PACL OldAcl, PACL* NewAcl )
3447 {
3448     FIXME("%d %p %p %p\n",count,pEntries,OldAcl,NewAcl);
3449     if (NewAcl)
3450          *NewAcl = NULL;
3451     return ERROR_SUCCESS;
3452 }
3453
3454 /******************************************************************************
3455  * SetEntriesInAclW [ADVAPI32.@]
3456  */
3457 DWORD WINAPI SetEntriesInAclW( ULONG count, PEXPLICIT_ACCESSW pEntries,
3458                                PACL OldAcl, PACL* NewAcl )
3459 {
3460     ULONG i;
3461     PSID *ppsid;
3462     DWORD ret = ERROR_SUCCESS;
3463     DWORD acl_size = sizeof(ACL);
3464     NTSTATUS status;
3465
3466     TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
3467
3468     *NewAcl = NULL;
3469
3470     if (!count && !OldAcl)
3471         return ERROR_SUCCESS;
3472
3473     /* allocate array of maximum sized sids allowed */
3474     ppsid = HeapAlloc(GetProcessHeap(), 0, count * (sizeof(SID *) + FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES])));
3475     if (!ppsid)
3476         return ERROR_OUTOFMEMORY;
3477
3478     for (i = 0; i < count; i++)
3479     {
3480         ppsid[i] = (char *)&ppsid[count] + i * FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3481
3482         TRACE("[%d]:\n\tgrfAccessPermissions = 0x%x\n\tgrfAccessMode = %d\n\tgrfInheritance = 0x%x\n\t"
3483               "Trustee.pMultipleTrustee = %p\n\tMultipleTrusteeOperation = %d\n\tTrusteeForm = %d\n\t"
3484               "Trustee.TrusteeType = %d\n\tptstrName = %p\n", i,
3485               pEntries[i].grfAccessPermissions, pEntries[i].grfAccessMode, pEntries[i].grfInheritance,
3486               pEntries[i].Trustee.pMultipleTrustee, pEntries[i].Trustee.MultipleTrusteeOperation,
3487               pEntries[i].Trustee.TrusteeForm, pEntries[i].Trustee.TrusteeType,
3488               pEntries[i].Trustee.ptstrName);
3489
3490         if (pEntries[i].Trustee.MultipleTrusteeOperation != NO_MULTIPLE_TRUSTEE)
3491         {
3492             WARN("bad multiple trustee operation %d for trustee %d\n", pEntries[i].Trustee.MultipleTrusteeOperation, i);
3493             ret = ERROR_INVALID_PARAMETER;
3494             goto exit;
3495         }
3496
3497         switch (pEntries[i].Trustee.TrusteeForm)
3498         {
3499         case TRUSTEE_IS_SID:
3500             if (!CopySid(FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]),
3501                          ppsid[i], pEntries[i].Trustee.ptstrName))
3502             {
3503                 WARN("bad sid %p for trustee %d\n", pEntries[i].Trustee.ptstrName, i);
3504                 ret = ERROR_INVALID_PARAMETER;
3505                 goto exit;
3506             }
3507             break;
3508         case TRUSTEE_IS_NAME:
3509         {
3510             DWORD sid_size = FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3511             DWORD domain_size = MAX_COMPUTERNAME_LENGTH + 1;
3512             SID_NAME_USE use;
3513             if (!LookupAccountNameW(NULL, pEntries[i].Trustee.ptstrName, ppsid[i], &sid_size, NULL, &domain_size, &use))
3514             {
3515                 WARN("bad user name %s for trustee %d\n", debugstr_w(pEntries[i].Trustee.ptstrName), i);
3516                 ret = ERROR_INVALID_PARAMETER;
3517                 goto exit;
3518             }
3519             break;
3520         }
3521         case TRUSTEE_IS_OBJECTS_AND_SID:
3522             FIXME("TRUSTEE_IS_OBJECTS_AND_SID unimplemented\n");
3523             break;
3524         case TRUSTEE_IS_OBJECTS_AND_NAME:
3525             FIXME("TRUSTEE_IS_OBJECTS_AND_NAME unimplemented\n");
3526             break;
3527         default:
3528             WARN("bad trustee form %d for trustee %d\n", pEntries[i].Trustee.TrusteeForm, i);
3529             ret = ERROR_INVALID_PARAMETER;
3530             goto exit;
3531         }
3532
3533         /* Note: we overestimate the ACL size here as a tradeoff between
3534          * instructions (simplicity) and memory */
3535         switch (pEntries[i].grfAccessMode)
3536         {
3537         case GRANT_ACCESS:
3538         case SET_ACCESS:
3539             acl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3540             break;
3541         case DENY_ACCESS:
3542             acl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3543             break;
3544         case SET_AUDIT_SUCCESS:
3545         case SET_AUDIT_FAILURE:
3546             acl_size += FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart) + GetLengthSid(ppsid[i]);
3547             break;
3548         case REVOKE_ACCESS:
3549             break;
3550         default:
3551             WARN("bad access mode %d for trustee %d\n", pEntries[i].grfAccessMode, i);
3552             ret = ERROR_INVALID_PARAMETER;
3553             goto exit;
3554         }
3555     }
3556
3557     if (OldAcl)
3558     {
3559         ACL_SIZE_INFORMATION size_info;
3560
3561         status = RtlQueryInformationAcl(OldAcl, &size_info, sizeof(size_info), AclSizeInformation);
3562         if (status != STATUS_SUCCESS)
3563         {
3564             ret = RtlNtStatusToDosError(status);
3565             goto exit;
3566         }
3567         acl_size += size_info.AclBytesInUse - sizeof(ACL);
3568     }
3569
3570     *NewAcl = LocalAlloc(0, acl_size);
3571     if (!*NewAcl)
3572     {
3573         ret = ERROR_OUTOFMEMORY;
3574         goto exit;
3575     }
3576
3577     status = RtlCreateAcl( *NewAcl, acl_size, ACL_REVISION );
3578     if (status != STATUS_SUCCESS)
3579     {
3580         ret = RtlNtStatusToDosError(status);
3581         goto exit;
3582     }
3583
3584     for (i = 0; i < count; i++)
3585     {
3586         switch (pEntries[i].grfAccessMode)
3587         {
3588         case GRANT_ACCESS:
3589             status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3590                                               pEntries[i].grfInheritance,
3591                                               pEntries[i].grfAccessPermissions,
3592                                               ppsid[i]);
3593             break;
3594         case SET_ACCESS:
3595         {
3596             ULONG j;
3597             BOOL add = TRUE;
3598             if (OldAcl)
3599             {
3600                 for (j = 0; ; j++)
3601                 {
3602                     const ACE_HEADER *existing_ace_header;
3603                     status = RtlGetAce(OldAcl, j, (LPVOID *)&existing_ace_header);
3604                     if (status != STATUS_SUCCESS)
3605                         break;
3606                     if (pEntries[i].grfAccessMode == SET_ACCESS &&
3607                         existing_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3608                         EqualSid(ppsid[i], &((ACCESS_ALLOWED_ACE *)existing_ace_header)->SidStart))
3609                     {
3610                         add = FALSE;
3611                         break;
3612                     }
3613                 }
3614             }
3615             if (add)
3616                 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3617                                                   pEntries[i].grfInheritance,
3618                                                   pEntries[i].grfAccessPermissions,
3619                                                   ppsid[i]);
3620             break;
3621         }
3622         case DENY_ACCESS:
3623             status = RtlAddAccessDeniedAceEx(*NewAcl, ACL_REVISION,
3624                                              pEntries[i].grfInheritance,
3625                                              pEntries[i].grfAccessPermissions,
3626                                              ppsid[i]);
3627             break;
3628         case SET_AUDIT_SUCCESS:
3629             status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3630                                             pEntries[i].grfInheritance,
3631                                             pEntries[i].grfAccessPermissions,
3632                                             ppsid[i], TRUE, FALSE);
3633             break;
3634         case SET_AUDIT_FAILURE:
3635             status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3636                                             pEntries[i].grfInheritance,
3637                                             pEntries[i].grfAccessPermissions,
3638                                             ppsid[i], FALSE, TRUE);
3639             break;
3640         default:
3641             FIXME("unhandled access mode %d\n", pEntries[i].grfAccessMode);
3642         }
3643     }
3644
3645     if (OldAcl)
3646     {
3647         for (i = 0; ; i++)
3648         {
3649             BOOL add = TRUE;
3650             ULONG j;
3651             const ACE_HEADER *old_ace_header;
3652             status = RtlGetAce(OldAcl, i, (LPVOID *)&old_ace_header);
3653             if (status != STATUS_SUCCESS) break;
3654             for (j = 0; j < count; j++)
3655             {
3656                 if (pEntries[j].grfAccessMode == SET_ACCESS &&
3657                     old_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3658                     EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3659                 {
3660                     status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION, pEntries[j].grfInheritance, pEntries[j].grfAccessPermissions, ppsid[j]);
3661                     add = FALSE;
3662                     break;
3663                 }
3664                 else if (pEntries[j].grfAccessMode == REVOKE_ACCESS)
3665                 {
3666                     switch (old_ace_header->AceType)
3667                     {
3668                     case ACCESS_ALLOWED_ACE_TYPE:
3669                         if (EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3670                             add = FALSE;
3671                         break;
3672                     case ACCESS_DENIED_ACE_TYPE:
3673                         if (EqualSid(ppsid[j], &((ACCESS_DENIED_ACE *)old_ace_header)->SidStart))
3674                             add = FALSE;
3675                         break;
3676                     case SYSTEM_AUDIT_ACE_TYPE:
3677                         if (EqualSid(ppsid[j], &((SYSTEM_AUDIT_ACE *)old_ace_header)->SidStart))
3678                             add = FALSE;
3679                         break;
3680                     case SYSTEM_ALARM_ACE_TYPE:
3681                         if (EqualSid(ppsid[j], &((SYSTEM_ALARM_ACE *)old_ace_header)->SidStart))
3682                             add = FALSE;
3683                         break;
3684                     default:
3685                         FIXME("unhandled ace type %d\n", old_ace_header->AceType);
3686                     }
3687
3688                     if (!add)
3689                         break;
3690                 }
3691             }
3692             if (add)
3693                 status = RtlAddAce(*NewAcl, ACL_REVISION, 1, (PACE_HEADER)old_ace_header, old_ace_header->AceSize);
3694             if (status != STATUS_SUCCESS)
3695             {
3696                 WARN("RtlAddAce failed with error 0x%08x\n", status);
3697                 ret = RtlNtStatusToDosError(status);
3698                 break;
3699             }
3700         }
3701     }
3702
3703 exit:
3704     HeapFree(GetProcessHeap(), 0, ppsid);
3705     return ret;
3706 }
3707
3708 /******************************************************************************
3709  * SetNamedSecurityInfoA [ADVAPI32.@]
3710  */
3711 DWORD WINAPI SetNamedSecurityInfoA(LPSTR pObjectName,
3712         SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
3713         PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
3714 {
3715     DWORD len;
3716     LPWSTR wstr = NULL;
3717     DWORD r;
3718
3719     TRACE("%s %d %d %p %p %p %p\n", debugstr_a(pObjectName), ObjectType,
3720            SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
3721
3722     if( pObjectName )
3723     {
3724         len = MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, NULL, 0 );
3725         wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR));
3726         MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, wstr, len );
3727     }
3728
3729     r = SetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, psidOwner,
3730                            psidGroup, pDacl, pSacl );
3731
3732     HeapFree( GetProcessHeap(), 0, wstr );
3733
3734     return r;
3735 }
3736
3737 BOOL WINAPI SetPrivateObjectSecurity( SECURITY_INFORMATION SecurityInformation,
3738     PSECURITY_DESCRIPTOR ModificationDescriptor,
3739     PSECURITY_DESCRIPTOR* ObjectsSecurityDescriptor,
3740     PGENERIC_MAPPING GenericMapping,
3741     HANDLE Token )
3742 {
3743     FIXME("0x%08x %p %p %p %p - stub\n", SecurityInformation, ModificationDescriptor,
3744           ObjectsSecurityDescriptor, GenericMapping, Token);
3745
3746     return TRUE;
3747 }
3748
3749 BOOL WINAPI AreAllAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
3750 {
3751     return RtlAreAllAccessesGranted( GrantedAccess, DesiredAccess );
3752 }
3753
3754 /******************************************************************************
3755  * AreAnyAccessesGranted [ADVAPI32.@]
3756  *
3757  * Determines whether or not any of a set of specified access permissions have
3758  * been granted or not.
3759  *
3760  * PARAMS
3761  *   GrantedAccess [I] The permissions that have been granted.
3762  *   DesiredAccess [I] The permissions that you want to have.
3763  *
3764  * RETURNS
3765  *   Nonzero if any of the permissions have been granted, zero if none of the
3766  *   permissions have been granted.
3767  */
3768
3769 BOOL WINAPI AreAnyAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
3770 {
3771     return RtlAreAnyAccessesGranted( GrantedAccess, DesiredAccess );
3772 }
3773
3774 /******************************************************************************
3775  * SetNamedSecurityInfoW [ADVAPI32.@]
3776  */
3777 DWORD WINAPI SetNamedSecurityInfoW(LPWSTR pObjectName,
3778         SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
3779         PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
3780 {
3781     FIXME("%s %d %d %p %p %p %p\n", debugstr_w(pObjectName), ObjectType,
3782            SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
3783     return ERROR_SUCCESS;
3784 }
3785
3786 /******************************************************************************
3787  * GetExplicitEntriesFromAclA [ADVAPI32.@]
3788  */
3789 DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntries,
3790         PEXPLICIT_ACCESSA* pListOfExplicitEntries)
3791 {
3792     FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
3793     return ERROR_CALL_NOT_IMPLEMENTED;
3794 }
3795
3796 /******************************************************************************
3797  * GetExplicitEntriesFromAclW [ADVAPI32.@]
3798  */
3799 DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG pcCountOfExplicitEntries,
3800         PEXPLICIT_ACCESSW* pListOfExplicitEntries)
3801 {
3802     FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
3803     return ERROR_CALL_NOT_IMPLEMENTED;
3804 }
3805
3806 /******************************************************************************
3807  * GetAuditedPermissionsFromAclA [ADVAPI32.@]
3808  */
3809 DWORD WINAPI GetAuditedPermissionsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
3810         PACCESS_MASK pFailedAuditRights)
3811 {
3812     FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
3813     return ERROR_CALL_NOT_IMPLEMENTED;
3814
3815 }
3816
3817 /******************************************************************************
3818  * GetAuditedPermissionsFromAclW [ADVAPI32.@]
3819  */
3820 DWORD WINAPI GetAuditedPermissionsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
3821         PACCESS_MASK pFailedAuditRights)
3822 {
3823     FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
3824     return ERROR_CALL_NOT_IMPLEMENTED;
3825
3826 }
3827
3828 /******************************************************************************
3829  * ParseAclStringFlags
3830  */
3831 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
3832 {
3833     DWORD flags = 0;
3834     LPCWSTR szAcl = *StringAcl;
3835
3836     while (*szAcl != '(')
3837     {
3838         if (*szAcl == 'P')
3839         {
3840             flags |= SE_DACL_PROTECTED;
3841         }
3842         else if (*szAcl == 'A')
3843         {
3844             szAcl++;
3845             if (*szAcl == 'R')
3846                 flags |= SE_DACL_AUTO_INHERIT_REQ;
3847             else if (*szAcl == 'I')
3848                 flags |= SE_DACL_AUTO_INHERITED;
3849         }
3850         szAcl++;
3851     }
3852
3853     *StringAcl = szAcl;
3854     return flags;
3855 }
3856
3857 /******************************************************************************
3858  * ParseAceStringType
3859  */
3860 static const ACEFLAG AceType[] =
3861 {
3862     { SDDL_ALARM,          SYSTEM_ALARM_ACE_TYPE },
3863     { SDDL_AUDIT,          SYSTEM_AUDIT_ACE_TYPE },
3864     { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
3865     { SDDL_ACCESS_DENIED,  ACCESS_DENIED_ACE_TYPE },
3866     /*
3867     { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
3868     { SDDL_OBJECT_ACCESS_DENIED,  ACCESS_DENIED_OBJECT_ACE_TYPE },
3869     { SDDL_OBJECT_ALARM,          SYSTEM_ALARM_OBJECT_ACE_TYPE },
3870     { SDDL_OBJECT_AUDIT,          SYSTEM_AUDIT_OBJECT_ACE_TYPE },
3871     */
3872     { NULL, 0 },
3873 };
3874
3875 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
3876 {
3877     UINT len = 0;
3878     LPCWSTR szAcl = *StringAcl;
3879     const ACEFLAG *lpaf = AceType;
3880
3881     while (lpaf->wstr &&
3882         (len = strlenW(lpaf->wstr)) &&
3883         strncmpW(lpaf->wstr, szAcl, len))
3884         lpaf++;
3885
3886     if (!lpaf->wstr)
3887         return 0;
3888
3889     *StringAcl += len;
3890     return lpaf->value;
3891 }
3892
3893
3894 /******************************************************************************
3895  * ParseAceStringFlags
3896  */
3897 static const ACEFLAG AceFlags[] =
3898 {
3899     { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
3900     { SDDL_AUDIT_FAILURE,     FAILED_ACCESS_ACE_FLAG },
3901     { SDDL_INHERITED,         INHERITED_ACE },
3902     { SDDL_INHERIT_ONLY,      INHERIT_ONLY_ACE },
3903     { SDDL_NO_PROPAGATE,      NO_PROPAGATE_INHERIT_ACE },
3904     { SDDL_OBJECT_INHERIT,    OBJECT_INHERIT_ACE },
3905     { SDDL_AUDIT_SUCCESS,     SUCCESSFUL_ACCESS_ACE_FLAG },
3906     { NULL, 0 },
3907 };
3908
3909 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
3910 {
3911     UINT len = 0;
3912     BYTE flags = 0;
3913     LPCWSTR szAcl = *StringAcl;
3914
3915     while (*szAcl != ';')
3916     {
3917         const ACEFLAG *lpaf = AceFlags;
3918
3919         while (lpaf->wstr &&
3920                (len = strlenW(lpaf->wstr)) &&
3921                strncmpW(lpaf->wstr, szAcl, len))
3922             lpaf++;
3923
3924         if (!lpaf->wstr)
3925             return 0;
3926
3927         flags |= lpaf->value;
3928         szAcl += len;
3929     }
3930
3931     *StringAcl = szAcl;
3932     return flags;
3933 }
3934
3935
3936 /******************************************************************************
3937  * ParseAceStringRights
3938  */
3939 static const ACEFLAG AceRights[] =
3940 {
3941     { SDDL_GENERIC_ALL,     GENERIC_ALL },
3942     { SDDL_GENERIC_READ,    GENERIC_READ },
3943     { SDDL_GENERIC_WRITE,   GENERIC_WRITE },
3944     { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
3945
3946     { SDDL_READ_CONTROL,    READ_CONTROL },
3947     { SDDL_STANDARD_DELETE, DELETE },
3948     { SDDL_WRITE_DAC,       WRITE_DAC },
3949     { SDDL_WRITE_OWNER,     WRITE_OWNER },
3950
3951     { SDDL_READ_PROPERTY,   ADS_RIGHT_DS_READ_PROP},
3952     { SDDL_WRITE_PROPERTY,  ADS_RIGHT_DS_WRITE_PROP},
3953     { SDDL_CREATE_CHILD,    ADS_RIGHT_DS_CREATE_CHILD},
3954     { SDDL_DELETE_CHILD,    ADS_RIGHT_DS_DELETE_CHILD},
3955     { SDDL_LIST_CHILDREN,   ADS_RIGHT_ACTRL_DS_LIST},
3956     { SDDL_SELF_WRITE,      ADS_RIGHT_DS_SELF},
3957     { SDDL_LIST_OBJECT,     ADS_RIGHT_DS_LIST_OBJECT},
3958     { SDDL_DELETE_TREE,     ADS_RIGHT_DS_DELETE_TREE},
3959     { SDDL_CONTROL_ACCESS,  ADS_RIGHT_DS_CONTROL_ACCESS},
3960
3961     { SDDL_FILE_ALL,        FILE_ALL_ACCESS },
3962     { SDDL_FILE_READ,       FILE_GENERIC_READ },
3963     { SDDL_FILE_WRITE,      FILE_GENERIC_WRITE },
3964     { SDDL_FILE_EXECUTE,    FILE_GENERIC_EXECUTE },
3965
3966     { SDDL_KEY_ALL,         KEY_ALL_ACCESS },
3967     { SDDL_KEY_READ,        KEY_READ },
3968     { SDDL_KEY_WRITE,       KEY_WRITE },
3969     { SDDL_KEY_EXECUTE,     KEY_EXECUTE },
3970     { NULL, 0 },
3971 };
3972
3973 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
3974 {
3975     UINT len = 0;
3976     DWORD rights = 0;
3977     LPCWSTR szAcl = *StringAcl;
3978
3979     if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
3980     {
3981         LPCWSTR p = szAcl;
3982
3983         while (*p && *p != ';')
3984             p++;
3985
3986         if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
3987         {
3988             rights = strtoulW(szAcl, NULL, 16);
3989             szAcl = p;
3990         }
3991         else
3992             WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
3993     }
3994     else
3995     {
3996         while (*szAcl != ';')
3997         {
3998             const ACEFLAG *lpaf = AceRights;
3999
4000             while (lpaf->wstr &&
4001                (len = strlenW(lpaf->wstr)) &&
4002                strncmpW(lpaf->wstr, szAcl, len))
4003             {
4004                lpaf++;
4005             }
4006
4007             if (!lpaf->wstr)
4008                 return 0;
4009
4010             rights |= lpaf->value;
4011             szAcl += len;
4012         }
4013     }
4014
4015     *StringAcl = szAcl;
4016     return rights;
4017 }
4018
4019
4020 /******************************************************************************
4021  * ParseStringAclToAcl
4022  * 
4023  * dacl_flags(string_ace1)(string_ace2)... (string_acen) 
4024  */
4025 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags, 
4026     PACL pAcl, LPDWORD cBytes)
4027 {
4028     DWORD val;
4029     DWORD sidlen;
4030     DWORD length = sizeof(ACL);
4031     DWORD acesize = 0;
4032     DWORD acecount = 0;
4033     PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
4034
4035     TRACE("%s\n", debugstr_w(StringAcl));
4036
4037     if (!StringAcl)
4038         return FALSE;
4039
4040     if (pAcl) /* pAce is only useful if we're setting values */
4041         pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
4042
4043     /* Parse ACL flags */
4044     *lpdwFlags = ParseAclStringFlags(&StringAcl);
4045
4046     /* Parse ACE */
4047     while (*StringAcl == '(')
4048     {
4049         StringAcl++;
4050
4051         /* Parse ACE type */
4052         val = ParseAceStringType(&StringAcl);
4053         if (pAce)
4054             pAce->Header.AceType = (BYTE) val;
4055         if (*StringAcl != ';')
4056             goto lerr;
4057         StringAcl++;
4058
4059         /* Parse ACE flags */
4060         val = ParseAceStringFlags(&StringAcl);
4061         if (pAce)
4062             pAce->Header.AceFlags = (BYTE) val;
4063         if (*StringAcl != ';')
4064             goto lerr;
4065         StringAcl++;
4066
4067         /* Parse ACE rights */
4068         val = ParseAceStringRights(&StringAcl);
4069         if (pAce)
4070             pAce->Mask = val;
4071         if (*StringAcl != ';')
4072             goto lerr;
4073         StringAcl++;
4074
4075         /* Parse ACE object guid */
4076         if (*StringAcl != ';')
4077         {
4078             FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4079             goto lerr;
4080         }
4081         StringAcl++;
4082
4083         /* Parse ACE inherit object guid */
4084         if (*StringAcl != ';')
4085         {
4086             FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4087             goto lerr;
4088         }
4089         StringAcl++;
4090
4091         /* Parse ACE account sid */
4092         if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
4093         {
4094             while (*StringAcl && *StringAcl != ')')
4095                 StringAcl++;
4096         }
4097
4098         if (*StringAcl != ')')
4099             goto lerr;
4100         StringAcl++;
4101
4102         acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
4103         length += acesize;
4104         if (pAce)
4105         {
4106             pAce->Header.AceSize = acesize;
4107             pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
4108         }
4109         acecount++;
4110     }
4111
4112     *cBytes = length;
4113
4114     if (length > 0xffff)
4115     {
4116         ERR("ACL too large\n");
4117         goto lerr;
4118     }
4119
4120     if (pAcl)
4121     {
4122         pAcl->AclRevision = ACL_REVISION;
4123         pAcl->Sbz1 = 0;
4124         pAcl->AclSize = length;
4125         pAcl->AceCount = acecount++;
4126         pAcl->Sbz2 = 0;
4127     }
4128     return TRUE;
4129
4130 lerr:
4131     SetLastError(ERROR_INVALID_ACL);
4132     WARN("Invalid ACE string format\n");
4133     return FALSE;
4134 }
4135
4136
4137 /******************************************************************************
4138  * ParseStringSecurityDescriptorToSecurityDescriptor
4139  */
4140 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
4141     LPCWSTR StringSecurityDescriptor,
4142     SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
4143     LPDWORD cBytes)
4144 {
4145     BOOL bret = FALSE;
4146     WCHAR toktype;
4147     WCHAR tok[MAX_PATH];
4148     LPCWSTR lptoken;
4149     LPBYTE lpNext = NULL;
4150     DWORD len;
4151
4152     *cBytes = sizeof(SECURITY_DESCRIPTOR);
4153
4154     if (SecurityDescriptor)
4155         lpNext = (LPBYTE)(SecurityDescriptor + 1);
4156
4157     while (*StringSecurityDescriptor)
4158     {
4159         toktype = *StringSecurityDescriptor;
4160
4161         /* Expect char identifier followed by ':' */
4162         StringSecurityDescriptor++;
4163         if (*StringSecurityDescriptor != ':')
4164         {
4165             SetLastError(ERROR_INVALID_PARAMETER);
4166             goto lend;
4167         }
4168         StringSecurityDescriptor++;
4169
4170         /* Extract token */
4171         lptoken = StringSecurityDescriptor;
4172         while (*lptoken && *lptoken != ':')
4173             lptoken++;
4174
4175         if (*lptoken)
4176             lptoken--;
4177
4178         len = lptoken - StringSecurityDescriptor;
4179         memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
4180         tok[len] = 0;
4181
4182         switch (toktype)
4183         {
4184             case 'O':
4185             {
4186                 DWORD bytes;
4187
4188                 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4189                     goto lend;
4190
4191                 if (SecurityDescriptor)
4192                 {
4193                     SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
4194                     lpNext += bytes; /* Advance to next token */
4195                 }
4196
4197                 *cBytes += bytes;
4198
4199                 break;
4200             }
4201
4202             case 'G':
4203             {
4204                 DWORD bytes;
4205
4206                 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4207                     goto lend;
4208
4209                 if (SecurityDescriptor)
4210                 {
4211                     SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
4212                     lpNext += bytes; /* Advance to next token */
4213                 }
4214
4215                 *cBytes += bytes;
4216
4217                 break;
4218             }
4219
4220             case 'D':
4221             {
4222                 DWORD flags;
4223                 DWORD bytes;
4224
4225                 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4226                     goto lend;
4227
4228                 if (SecurityDescriptor)
4229                 {
4230                     SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
4231                     SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
4232                     lpNext += bytes; /* Advance to next token */
4233                 }
4234
4235                 *cBytes += bytes;
4236
4237                 break;
4238             }
4239
4240             case 'S':
4241             {
4242                 DWORD flags;
4243                 DWORD bytes;
4244
4245                 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4246                     goto lend;
4247
4248                 if (SecurityDescriptor)
4249                 {
4250                     SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
4251                     SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
4252                     lpNext += bytes; /* Advance to next token */
4253                 }
4254
4255                 *cBytes += bytes;
4256
4257                 break;
4258             }
4259
4260             default:
4261                 FIXME("Unknown token\n");
4262                 SetLastError(ERROR_INVALID_PARAMETER);
4263                 goto lend;
4264         }
4265
4266         StringSecurityDescriptor = lptoken;
4267     }
4268
4269     bret = TRUE;
4270
4271 lend:
4272     return bret;
4273 }
4274
4275 /******************************************************************************
4276  * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
4277  */
4278 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
4279         LPCSTR StringSecurityDescriptor,
4280         DWORD StringSDRevision,
4281         PSECURITY_DESCRIPTOR* SecurityDescriptor,
4282         PULONG SecurityDescriptorSize)
4283 {
4284     UINT len;
4285     BOOL ret = FALSE;
4286     LPWSTR StringSecurityDescriptorW;
4287
4288     len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
4289     StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
4290
4291     if (StringSecurityDescriptorW)
4292     {
4293         MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
4294
4295         ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
4296                                                                    StringSDRevision, SecurityDescriptor,
4297                                                                    SecurityDescriptorSize);
4298         HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
4299     }
4300
4301     return ret;
4302 }
4303
4304 /******************************************************************************
4305  * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
4306  */
4307 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
4308         LPCWSTR StringSecurityDescriptor,
4309         DWORD StringSDRevision,
4310         PSECURITY_DESCRIPTOR* SecurityDescriptor,
4311         PULONG SecurityDescriptorSize)
4312 {
4313     DWORD cBytes;
4314     SECURITY_DESCRIPTOR* psd;
4315     BOOL bret = FALSE;
4316
4317     TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
4318
4319     if (GetVersion() & 0x80000000)
4320     {
4321         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4322         goto lend;
4323     }
4324     else if (!StringSecurityDescriptor || !SecurityDescriptor)
4325     {
4326         SetLastError(ERROR_INVALID_PARAMETER);
4327         goto lend;
4328     }
4329     else if (StringSDRevision != SID_REVISION)
4330     {
4331         SetLastError(ERROR_UNKNOWN_REVISION);
4332         goto lend;
4333     }
4334
4335     /* Compute security descriptor length */
4336     if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4337         NULL, &cBytes))
4338         goto lend;
4339
4340     psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
4341     if (!psd) goto lend;
4342
4343     psd->Revision = SID_REVISION;
4344     psd->Control |= SE_SELF_RELATIVE;
4345
4346     if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4347              (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
4348     {
4349         LocalFree(psd);
4350         goto lend;
4351     }
4352
4353     if (SecurityDescriptorSize)
4354         *SecurityDescriptorSize = cBytes;
4355
4356     bret = TRUE;
4357  
4358 lend:
4359     TRACE(" ret=%d\n", bret);
4360     return bret;
4361 }
4362
4363 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
4364 {
4365     if (cch == -1)
4366         cch = strlenW(string);
4367
4368     if (plen)
4369         *plen += cch;
4370
4371     if (pwptr)
4372     {
4373         memcpy(*pwptr, string, sizeof(WCHAR)*cch);
4374         *pwptr += cch;
4375     }
4376 }
4377
4378 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
4379 {
4380     DWORD i;
4381     WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
4382     WCHAR subauthfmt[] = { '-','%','u',0 };
4383     WCHAR buf[26];
4384     SID *pisid = psid;
4385
4386     if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
4387     {
4388         SetLastError(ERROR_INVALID_SID);
4389         return FALSE;
4390     }
4391
4392     if (pisid->IdentifierAuthority.Value[0] ||
4393      pisid->IdentifierAuthority.Value[1])
4394     {
4395         FIXME("not matching MS' bugs\n");
4396         SetLastError(ERROR_INVALID_SID);
4397         return FALSE;
4398     }
4399
4400     sprintfW( buf, fmt, pisid->Revision,
4401         MAKELONG(
4402             MAKEWORD( pisid->IdentifierAuthority.Value[5],
4403                     pisid->IdentifierAuthority.Value[4] ),
4404             MAKEWORD( pisid->IdentifierAuthority.Value[3],
4405                     pisid->IdentifierAuthority.Value[2] )
4406         ) );
4407     DumpString(buf, -1, pwptr, plen);
4408
4409     for( i=0; i<pisid->SubAuthorityCount; i++ )
4410     {
4411         sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
4412         DumpString(buf, -1, pwptr, plen);
4413     }
4414     return TRUE;
4415 }
4416
4417 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
4418 {
4419     size_t i;
4420     for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
4421     {
4422         if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
4423         {
4424             DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
4425             return TRUE;
4426         }
4427     }
4428
4429     return DumpSidNumeric(psid, pwptr, plen);
4430 }
4431
4432 static const LPCWSTR AceRightBitNames[32] = {
4433         SDDL_CREATE_CHILD,        /*  0 */
4434         SDDL_DELETE_CHILD,
4435         SDDL_LIST_CHILDREN,
4436         SDDL_SELF_WRITE,
4437         SDDL_READ_PROPERTY,       /*  4 */
4438         SDDL_WRITE_PROPERTY,
4439         SDDL_DELETE_TREE,
4440         SDDL_LIST_OBJECT,
4441         SDDL_CONTROL_ACCESS,      /*  8 */
4442         NULL,
4443         NULL,
4444         NULL,
4445         NULL,                     /* 12 */
4446         NULL,
4447         NULL,
4448         NULL,
4449         SDDL_STANDARD_DELETE,     /* 16 */
4450         SDDL_READ_CONTROL,
4451         SDDL_WRITE_DAC,
4452         SDDL_WRITE_OWNER,
4453         NULL,                     /* 20 */
4454         NULL,
4455         NULL,
4456         NULL,
4457         NULL,                     /* 24 */
4458         NULL,
4459         NULL,
4460         NULL,
4461         SDDL_GENERIC_ALL,         /* 28 */
4462         SDDL_GENERIC_EXECUTE,
4463         SDDL_GENERIC_WRITE,
4464         SDDL_GENERIC_READ
4465 };
4466
4467 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
4468 {
4469     static const WCHAR fmtW[] = {'0','x','%','x',0};
4470     WCHAR buf[15];
4471     size_t i;
4472
4473     if (mask == 0)
4474         return;
4475
4476     /* first check if the right have name */
4477     for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
4478     {
4479         if (AceRights[i].wstr == NULL)
4480             break;
4481         if (mask == AceRights[i].value)
4482         {
4483             DumpString(AceRights[i].wstr, -1, pwptr, plen);
4484             return;
4485         }
4486     }
4487
4488     /* then check if it can be built from bit names */
4489     for (i = 0; i < 32; i++)
4490     {
4491         if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
4492         {
4493             /* can't be built from bit names */
4494             sprintfW(buf, fmtW, mask);
4495             DumpString(buf, -1, pwptr, plen);
4496             return;
4497         }
4498     }
4499
4500     /* build from bit names */
4501     for (i = 0; i < 32; i++)
4502         if (mask & (1 << i))
4503             DumpString(AceRightBitNames[i], -1, pwptr, plen);
4504 }
4505
4506 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
4507 {
4508     ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
4509     static const WCHAR openbr = '(';
4510     static const WCHAR closebr = ')';
4511     static const WCHAR semicolon = ';';
4512
4513     if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
4514     {
4515         SetLastError(ERROR_INVALID_ACL);
4516         return FALSE;
4517     }
4518
4519     piace = pace;
4520     DumpString(&openbr, 1, pwptr, plen);
4521     switch (piace->Header.AceType)
4522     {
4523         case ACCESS_ALLOWED_ACE_TYPE:
4524             DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
4525             break;
4526         case ACCESS_DENIED_ACE_TYPE:
4527             DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
4528             break;
4529         case SYSTEM_AUDIT_ACE_TYPE:
4530             DumpString(SDDL_AUDIT, -1, pwptr, plen);
4531             break;
4532         case SYSTEM_ALARM_ACE_TYPE:
4533             DumpString(SDDL_ALARM, -1, pwptr, plen);
4534             break;
4535     }
4536     DumpString(&semicolon, 1, pwptr, plen);
4537
4538     if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
4539         DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
4540     if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
4541         DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
4542     if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
4543         DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
4544     if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
4545         DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
4546     if (piace->Header.AceFlags & INHERITED_ACE)
4547         DumpString(SDDL_INHERITED, -1, pwptr, plen);
4548     if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
4549         DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
4550     if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
4551         DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
4552     DumpString(&semicolon, 1, pwptr, plen);
4553     DumpRights(piace->Mask, pwptr, plen);
4554     DumpString(&semicolon, 1, pwptr, plen);
4555     /* objects not supported */
4556     DumpString(&semicolon, 1, pwptr, plen);
4557     /* objects not supported */
4558     DumpString(&semicolon, 1, pwptr, plen);
4559     if (!DumpSid(&piace->SidStart, pwptr, plen))
4560         return FALSE;
4561     DumpString(&closebr, 1, pwptr, plen);
4562     return TRUE;
4563 }
4564
4565 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
4566 {
4567     WORD count;
4568     int i;
4569
4570     if (protected)
4571         DumpString(SDDL_PROTECTED, -1, pwptr, plen);
4572     if (autoInheritReq)
4573         DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
4574     if (autoInherited)
4575         DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
4576
4577     if (pacl == NULL)
4578         return TRUE;
4579
4580     if (!IsValidAcl(pacl))
4581         return FALSE;
4582
4583     count = pacl->AceCount;
4584     for (i = 0; i < count; i++)
4585     {
4586         LPVOID ace;
4587         if (!GetAce(pacl, i, &ace))
4588             return FALSE;
4589         if (!DumpAce(ace, pwptr, plen))
4590             return FALSE;
4591     }
4592
4593     return TRUE;
4594 }
4595
4596 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4597 {
4598     static const WCHAR prefix[] = {'O',':',0};
4599     BOOL bDefaulted;
4600     PSID psid;
4601
4602     if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
4603         return FALSE;
4604
4605     if (psid == NULL)
4606         return TRUE;
4607
4608     DumpString(prefix, -1, pwptr, plen);
4609     if (!DumpSid(psid, pwptr, plen))
4610         return FALSE;
4611     return TRUE;
4612 }
4613
4614 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4615 {
4616     static const WCHAR prefix[] = {'G',':',0};
4617     BOOL bDefaulted;
4618     PSID psid;
4619
4620     if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
4621         return FALSE;
4622
4623     if (psid == NULL)
4624         return TRUE;
4625
4626     DumpString(prefix, -1, pwptr, plen);
4627     if (!DumpSid(psid, pwptr, plen))
4628         return FALSE;
4629     return TRUE;
4630 }
4631
4632 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4633 {
4634     static const WCHAR dacl[] = {'D',':',0};
4635     SECURITY_DESCRIPTOR_CONTROL control;
4636     BOOL present, defaulted;
4637     DWORD revision;
4638     PACL pacl;
4639
4640     if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
4641         return FALSE;
4642
4643     if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
4644         return FALSE;
4645
4646     if (!present)
4647         return TRUE;
4648
4649     DumpString(dacl, 2, pwptr, plen);
4650     if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
4651         return FALSE;
4652     return TRUE;
4653 }
4654
4655 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4656 {
4657     static const WCHAR sacl[] = {'S',':',0};
4658     SECURITY_DESCRIPTOR_CONTROL control;
4659     BOOL present, defaulted;
4660     DWORD revision;
4661     PACL pacl;
4662
4663     if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
4664         return FALSE;
4665
4666     if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
4667         return FALSE;
4668
4669     if (!present)
4670         return TRUE;
4671
4672     DumpString(sacl, 2, pwptr, plen);
4673     if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
4674         return FALSE;
4675     return TRUE;
4676 }
4677
4678 /******************************************************************************
4679  * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
4680  */
4681 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen)
4682 {
4683     ULONG len;
4684     WCHAR *wptr, *wstr;
4685
4686     if (SDRevision != SDDL_REVISION_1)
4687     {
4688         ERR("Pogram requested unknown SDDL revision %d\n", SDRevision);
4689         SetLastError(ERROR_UNKNOWN_REVISION);
4690         return FALSE;
4691     }
4692
4693     len = 0;
4694     if (RequestedInformation & OWNER_SECURITY_INFORMATION)
4695         if (!DumpOwner(SecurityDescriptor, NULL, &len))
4696             return FALSE;
4697     if (RequestedInformation & GROUP_SECURITY_INFORMATION)
4698         if (!DumpGroup(SecurityDescriptor, NULL, &len))
4699             return FALSE;
4700     if (RequestedInformation & DACL_SECURITY_INFORMATION)
4701         if (!DumpDacl(SecurityDescriptor, NULL, &len))
4702             return FALSE;
4703     if (RequestedInformation & SACL_SECURITY_INFORMATION)
4704         if (!DumpSacl(SecurityDescriptor, NULL, &len))
4705             return FALSE;
4706
4707     wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
4708     if (RequestedInformation & OWNER_SECURITY_INFORMATION)
4709         if (!DumpOwner(SecurityDescriptor, &wptr, NULL))
4710             return FALSE;
4711     if (RequestedInformation & GROUP_SECURITY_INFORMATION)
4712         if (!DumpGroup(SecurityDescriptor, &wptr, NULL))
4713             return FALSE;
4714     if (RequestedInformation & DACL_SECURITY_INFORMATION)
4715         if (!DumpDacl(SecurityDescriptor, &wptr, NULL))
4716             return FALSE;
4717     if (RequestedInformation & SACL_SECURITY_INFORMATION)
4718         if (!DumpSacl(SecurityDescriptor, &wptr, NULL))
4719             return FALSE;
4720     *wptr = 0;
4721
4722     TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
4723     *OutputString = wstr;
4724     if (OutputLen)
4725         *OutputLen = strlenW(*OutputString)+1;
4726     return TRUE;
4727 }
4728
4729 /******************************************************************************
4730  * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
4731  */
4732 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen)
4733 {
4734     LPWSTR wstr;
4735     ULONG len;
4736     if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
4737     {
4738         int lenA;
4739
4740         lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
4741         *OutputString = HeapAlloc(GetProcessHeap(), 0, lenA);
4742         WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
4743         LocalFree(wstr);
4744
4745         if (OutputLen != NULL)
4746             *OutputLen = lenA;
4747         return TRUE;
4748     }
4749     else
4750     {
4751         *OutputString = NULL;
4752         if (OutputLen)
4753             *OutputLen = 0;
4754         return FALSE;
4755     }
4756 }
4757
4758 /******************************************************************************
4759  * ConvertStringSidToSidW [ADVAPI32.@]
4760  */
4761 BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid)
4762 {
4763     BOOL bret = FALSE;
4764     DWORD cBytes;
4765
4766     TRACE("%s, %p\n", debugstr_w(StringSid), Sid);
4767     if (GetVersion() & 0x80000000)
4768         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4769     else if (!StringSid || !Sid)
4770         SetLastError(ERROR_INVALID_PARAMETER);
4771     else if (ParseStringSidToSid(StringSid, NULL, &cBytes))
4772     {
4773         PSID pSid = *Sid = LocalAlloc(0, cBytes);
4774
4775         bret = ParseStringSidToSid(StringSid, pSid, &cBytes);
4776         if (!bret)
4777             LocalFree(*Sid); 
4778     }
4779     return bret;
4780 }
4781
4782 /******************************************************************************
4783  * ConvertStringSidToSidA [ADVAPI32.@]
4784  */
4785 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
4786 {
4787     BOOL bret = FALSE;
4788
4789     TRACE("%s, %p\n", debugstr_a(StringSid), Sid);
4790     if (GetVersion() & 0x80000000)
4791         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4792     else if (!StringSid || !Sid)
4793         SetLastError(ERROR_INVALID_PARAMETER);
4794     else
4795     {
4796         UINT len = MultiByteToWideChar(CP_ACP, 0, StringSid, -1, NULL, 0);
4797         LPWSTR wStringSid = HeapAlloc(GetProcessHeap(), 0,
4798          len * sizeof(WCHAR));
4799
4800         MultiByteToWideChar(CP_ACP, 0, StringSid, -1, wStringSid, len);
4801         bret = ConvertStringSidToSidW(wStringSid, Sid);
4802         HeapFree(GetProcessHeap(), 0, wStringSid);
4803     }
4804     return bret;
4805 }
4806
4807 /******************************************************************************
4808  * ConvertSidToStringSidW [ADVAPI32.@]
4809  *
4810  *  format of SID string is:
4811  *    S-<count>-<auth>-<subauth1>-<subauth2>-<subauth3>...
4812  *  where
4813  *    <rev> is the revision of the SID encoded as decimal
4814  *    <auth> is the identifier authority encoded as hex
4815  *    <subauthN> is the subauthority id encoded as decimal
4816  */
4817 BOOL WINAPI ConvertSidToStringSidW( PSID pSid, LPWSTR *pstr )
4818 {
4819     DWORD len = 0;
4820     LPWSTR wstr, wptr;
4821
4822     TRACE("%p %p\n", pSid, pstr );
4823
4824     len = 0;
4825     if (!DumpSidNumeric(pSid, NULL, &len))
4826         return FALSE;
4827     wstr = wptr = LocalAlloc(0, (len+1) * sizeof(WCHAR));
4828     DumpSidNumeric(pSid, &wptr, NULL);
4829     *wptr = 0;
4830
4831     *pstr = wstr;
4832     return TRUE;
4833 }
4834
4835 /******************************************************************************
4836  * ConvertSidToStringSidA [ADVAPI32.@]
4837  */
4838 BOOL WINAPI ConvertSidToStringSidA(PSID pSid, LPSTR *pstr)
4839 {
4840     LPWSTR wstr = NULL;
4841     LPSTR str;
4842     UINT len;
4843
4844     TRACE("%p %p\n", pSid, pstr );
4845
4846     if( !ConvertSidToStringSidW( pSid, &wstr ) )
4847         return FALSE;
4848
4849     len = WideCharToMultiByte( CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL );
4850     str = LocalAlloc( 0, len );
4851     WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, len, NULL, NULL );
4852     LocalFree( wstr );
4853
4854     *pstr = str;
4855
4856     return TRUE;
4857 }
4858
4859 BOOL WINAPI ConvertToAutoInheritPrivateObjectSecurity(
4860         PSECURITY_DESCRIPTOR pdesc,
4861         PSECURITY_DESCRIPTOR cdesc,
4862         PSECURITY_DESCRIPTOR* ndesc,
4863         GUID* objtype,
4864         BOOL isdir,
4865         PGENERIC_MAPPING genmap )
4866 {
4867     FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
4868
4869     return FALSE;
4870 }
4871
4872 BOOL WINAPI CreatePrivateObjectSecurity(
4873         PSECURITY_DESCRIPTOR ParentDescriptor,
4874         PSECURITY_DESCRIPTOR CreatorDescriptor,
4875         PSECURITY_DESCRIPTOR* NewDescriptor,
4876         BOOL IsDirectoryObject,
4877         HANDLE Token,
4878         PGENERIC_MAPPING GenericMapping )
4879 {
4880     FIXME("%p %p %p %d %p %p - stub\n", ParentDescriptor, CreatorDescriptor,
4881           NewDescriptor, IsDirectoryObject, Token, GenericMapping);
4882
4883     return FALSE;
4884 }
4885
4886 BOOL WINAPI DestroyPrivateObjectSecurity( PSECURITY_DESCRIPTOR* ObjectDescriptor )
4887 {
4888     FIXME("%p - stub\n", ObjectDescriptor);
4889
4890     return TRUE;
4891 }
4892
4893 BOOL WINAPI CreateProcessAsUserA(
4894         HANDLE hToken,
4895         LPCSTR lpApplicationName,
4896         LPSTR lpCommandLine,
4897         LPSECURITY_ATTRIBUTES lpProcessAttributes,
4898         LPSECURITY_ATTRIBUTES lpThreadAttributes,
4899         BOOL bInheritHandles,
4900         DWORD dwCreationFlags,
4901         LPVOID lpEnvironment,
4902         LPCSTR lpCurrentDirectory,
4903         LPSTARTUPINFOA lpStartupInfo,
4904         LPPROCESS_INFORMATION lpProcessInformation )
4905 {
4906     FIXME("%p %s %s %p %p %d 0x%08x %p %s %p %p - stub\n", hToken, debugstr_a(lpApplicationName),
4907           debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
4908           dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
4909
4910     return FALSE;
4911 }
4912
4913 BOOL WINAPI CreateProcessAsUserW(
4914         HANDLE hToken,
4915         LPCWSTR lpApplicationName,
4916         LPWSTR lpCommandLine,
4917         LPSECURITY_ATTRIBUTES lpProcessAttributes,
4918         LPSECURITY_ATTRIBUTES lpThreadAttributes,
4919         BOOL bInheritHandles,
4920         DWORD dwCreationFlags,
4921         LPVOID lpEnvironment,
4922         LPCWSTR lpCurrentDirectory,
4923         LPSTARTUPINFOW lpStartupInfo,
4924         LPPROCESS_INFORMATION lpProcessInformation )
4925 {
4926     FIXME("%p %s %s %p %p %d 0x%08x %p %s %p %p - semi- stub\n", hToken, 
4927           debugstr_w(lpApplicationName), debugstr_w(lpCommandLine), lpProcessAttributes,
4928           lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, 
4929           debugstr_w(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
4930
4931     /* We should create the process with a suspended main thread */
4932     if (!CreateProcessW (lpApplicationName,
4933                          lpCommandLine,
4934                          lpProcessAttributes,
4935                          lpThreadAttributes,
4936                          bInheritHandles,
4937                          dwCreationFlags, /* CREATE_SUSPENDED */
4938                          lpEnvironment,
4939                          lpCurrentDirectory,
4940                          lpStartupInfo,
4941                          lpProcessInformation))
4942     {
4943       return FALSE;
4944     }
4945
4946     return TRUE;
4947 }
4948
4949 /******************************************************************************
4950  * CreateProcessWithLogonW
4951  */
4952 BOOL WINAPI CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags,
4953     LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment,
4954     LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
4955 {
4956     FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
4957     debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
4958     debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
4959     lpStartupInfo, lpProcessInformation);
4960
4961     return FALSE;
4962 }
4963
4964 /******************************************************************************
4965  * DuplicateTokenEx [ADVAPI32.@]
4966  */
4967 BOOL WINAPI DuplicateTokenEx(
4968         HANDLE ExistingTokenHandle, DWORD dwDesiredAccess,
4969         LPSECURITY_ATTRIBUTES lpTokenAttributes,
4970         SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
4971         TOKEN_TYPE TokenType,
4972         PHANDLE DuplicateTokenHandle )
4973 {
4974     OBJECT_ATTRIBUTES ObjectAttributes;
4975
4976     TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
4977           ImpersonationLevel, TokenType, DuplicateTokenHandle);
4978
4979     InitializeObjectAttributes(
4980         &ObjectAttributes,
4981         NULL,
4982         (lpTokenAttributes && lpTokenAttributes->bInheritHandle) ? OBJ_INHERIT : 0,
4983         NULL,
4984         lpTokenAttributes ? lpTokenAttributes->lpSecurityDescriptor : NULL );
4985
4986     return set_ntstatus( NtDuplicateToken( ExistingTokenHandle,
4987                                            dwDesiredAccess,
4988                                            &ObjectAttributes,
4989                                            ImpersonationLevel,
4990                                            TokenType,
4991                                            DuplicateTokenHandle ) );
4992 }
4993
4994 BOOL WINAPI DuplicateToken(
4995         HANDLE ExistingTokenHandle,
4996         SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
4997         PHANDLE DuplicateTokenHandle )
4998 {
4999     return DuplicateTokenEx( ExistingTokenHandle, TOKEN_IMPERSONATE | TOKEN_QUERY,
5000                              NULL, ImpersonationLevel, TokenImpersonation,
5001                              DuplicateTokenHandle );
5002 }
5003
5004 /******************************************************************************
5005  * ComputeStringSidSize
5006  */
5007 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
5008 {
5009     if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
5010     {
5011         int ctok = 0;
5012         while (*StringSid)
5013         {
5014             if (*StringSid == '-')
5015                 ctok++;
5016             StringSid++;
5017         }
5018
5019         if (ctok >= 3)
5020             return GetSidLengthRequired(ctok - 2);
5021     }
5022     else /* String constant format  - Only available in winxp and above */
5023     {
5024         unsigned int i;
5025
5026         for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5027             if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5028                 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
5029     }
5030
5031     return GetSidLengthRequired(0);
5032 }
5033
5034 /******************************************************************************
5035  * ParseStringSidToSid
5036  */
5037 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
5038 {
5039     BOOL bret = FALSE;
5040     SID* pisid=pSid;
5041
5042     TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
5043     if (!StringSid)
5044     {
5045         SetLastError(ERROR_INVALID_PARAMETER);
5046         TRACE("StringSid is NULL, returning FALSE\n");
5047         return FALSE;
5048     }
5049
5050     *cBytes = ComputeStringSidSize(StringSid);
5051     if (!pisid) /* Simply compute the size */
5052     {
5053         TRACE("only size requested, returning TRUE\n");
5054         return TRUE;
5055     }
5056
5057     if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
5058     {
5059         DWORD i = 0, identAuth;
5060         DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
5061
5062         StringSid += 2; /* Advance to Revision */
5063         pisid->Revision = atoiW(StringSid);
5064
5065         if (pisid->Revision != SDDL_REVISION)
5066         {
5067             TRACE("Revision %d is unknown\n", pisid->Revision);
5068             goto lend; /* ERROR_INVALID_SID */
5069         }
5070         if (csubauth == 0)
5071         {
5072             TRACE("SubAuthorityCount is 0\n");
5073             goto lend; /* ERROR_INVALID_SID */
5074         }
5075
5076         pisid->SubAuthorityCount = csubauth;
5077
5078         /* Advance to identifier authority */
5079         while (*StringSid && *StringSid != '-')
5080             StringSid++;
5081         if (*StringSid == '-')
5082             StringSid++;
5083
5084         /* MS' implementation can't handle values greater than 2^32 - 1, so
5085          * we don't either; assume most significant bytes are always 0
5086          */
5087         pisid->IdentifierAuthority.Value[0] = 0;
5088         pisid->IdentifierAuthority.Value[1] = 0;
5089         identAuth = atoiW(StringSid);
5090         pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
5091         pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
5092         pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
5093         pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
5094
5095         /* Advance to first sub authority */
5096         while (*StringSid && *StringSid != '-')
5097             StringSid++;
5098         if (*StringSid == '-')
5099             StringSid++;
5100
5101         while (*StringSid)
5102         {
5103             pisid->SubAuthority[i++] = atoiW(StringSid);
5104
5105             while (*StringSid && *StringSid != '-')
5106                 StringSid++;
5107             if (*StringSid == '-')
5108                 StringSid++;
5109         }
5110
5111         if (i != pisid->SubAuthorityCount)
5112             goto lend; /* ERROR_INVALID_SID */
5113
5114         bret = TRUE;
5115     }
5116     else /* String constant format  - Only available in winxp and above */
5117     {
5118         unsigned int i;
5119         pisid->Revision = SDDL_REVISION;
5120
5121         for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5122             if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5123             {
5124                 DWORD j;
5125                 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
5126                 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
5127                 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
5128                     pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
5129                 bret = TRUE;
5130             }
5131
5132         if (!bret)
5133             FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
5134     }
5135
5136 lend:
5137     if (!bret)
5138         SetLastError(ERROR_INVALID_SID);
5139
5140     TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
5141     return bret;
5142 }
5143
5144 /******************************************************************************
5145  * GetNamedSecurityInfoA [ADVAPI32.@]
5146  */
5147 DWORD WINAPI GetNamedSecurityInfoA(LPSTR pObjectName,
5148         SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5149         PSID* ppsidOwner, PSID* ppsidGroup, PACL* ppDacl, PACL* ppSacl,
5150         PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
5151 {
5152     DWORD len;
5153     LPWSTR wstr = NULL;
5154     DWORD r;
5155
5156     TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo,
5157         ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
5158
5159     if( pObjectName )
5160     {
5161         len = MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, NULL, 0 );
5162         wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR));
5163         MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, wstr, len );
5164     }
5165
5166     r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
5167                            ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
5168
5169     HeapFree( GetProcessHeap(), 0, wstr );
5170
5171     return r;
5172 }
5173
5174 /******************************************************************************
5175  * GetNamedSecurityInfoW [ADVAPI32.@]
5176  */
5177 DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type,
5178     SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl,
5179     PACL* sacl, PSECURITY_DESCRIPTOR* descriptor )
5180 {
5181     DWORD needed, offset;
5182     SECURITY_DESCRIPTOR_RELATIVE *relative;
5183     BYTE *buffer;
5184
5185     TRACE( "%s %d %d %p %p %p %p %p\n", debugstr_w(name), type, info, owner,
5186            group, dacl, sacl, descriptor );
5187
5188     if (!name || !descriptor) return ERROR_INVALID_PARAMETER;
5189
5190     needed = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5191     if (info & OWNER_SECURITY_INFORMATION)
5192         needed += sizeof(sidWorld);
5193     if (info & GROUP_SECURITY_INFORMATION)
5194         needed += sizeof(sidWorld);
5195     if (info & DACL_SECURITY_INFORMATION)
5196         needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5197     if (info & SACL_SECURITY_INFORMATION)
5198         needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5199
5200     /* must be freed by caller */
5201     *descriptor = HeapAlloc( GetProcessHeap(), 0, needed );
5202     if (!*descriptor) return ERROR_NOT_ENOUGH_MEMORY;
5203
5204     if (!InitializeSecurityDescriptor( *descriptor, SECURITY_DESCRIPTOR_REVISION ))
5205     {
5206         HeapFree( GetProcessHeap(), 0, *descriptor );
5207         return ERROR_INVALID_SECURITY_DESCR;
5208     }
5209
5210     relative = *descriptor;
5211     relative->Control |= SE_SELF_RELATIVE;
5212     buffer = (BYTE *)relative;
5213     offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5214
5215     if (info & OWNER_SECURITY_INFORMATION)
5216     {
5217         memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5218         relative->Owner = offset;
5219         if (owner)
5220             *owner = buffer + offset;
5221         offset += sizeof(sidWorld);
5222     }
5223     if (info & GROUP_SECURITY_INFORMATION)
5224     {
5225         memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5226         relative->Group = offset;
5227         if (group)
5228             *group = buffer + offset;
5229         offset += sizeof(sidWorld);
5230     }
5231     if (info & DACL_SECURITY_INFORMATION)
5232     {
5233         relative->Control |= SE_DACL_PRESENT;
5234         GetWorldAccessACL( (PACL)(buffer + offset) );
5235         relative->Dacl = offset;
5236         if (dacl)
5237             *dacl = (PACL)(buffer + offset);
5238         offset += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5239     }
5240     if (info & SACL_SECURITY_INFORMATION)
5241     {
5242         relative->Control |= SE_SACL_PRESENT;
5243         GetWorldAccessACL( (PACL)(buffer + offset) );
5244         relative->Sacl = offset;
5245         if (sacl)
5246             *sacl = (PACL)(buffer + offset);
5247     }
5248     return ERROR_SUCCESS;
5249 }
5250
5251 /******************************************************************************
5252  * DecryptFileW [ADVAPI32.@]
5253  */
5254 BOOL WINAPI DecryptFileW(LPCWSTR lpFileName, DWORD dwReserved)
5255 {
5256     FIXME("%s %08x\n", debugstr_w(lpFileName), dwReserved);
5257     return TRUE;
5258 }
5259
5260 /******************************************************************************
5261  * DecryptFileA [ADVAPI32.@]
5262  */
5263 BOOL WINAPI DecryptFileA(LPCSTR lpFileName, DWORD dwReserved)
5264 {
5265     FIXME("%s %08x\n", debugstr_a(lpFileName), dwReserved);
5266     return TRUE;
5267 }
5268
5269 /******************************************************************************
5270  * EncryptFileW [ADVAPI32.@]
5271  */
5272 BOOL WINAPI EncryptFileW(LPCWSTR lpFileName)
5273 {
5274     FIXME("%s\n", debugstr_w(lpFileName));
5275     return TRUE;
5276 }
5277
5278 /******************************************************************************
5279  * EncryptFileA [ADVAPI32.@]
5280  */
5281 BOOL WINAPI EncryptFileA(LPCSTR lpFileName)
5282 {
5283     FIXME("%s\n", debugstr_a(lpFileName));
5284     return TRUE;
5285 }
5286
5287 /******************************************************************************
5288  * FileEncryptionStatusW [ADVAPI32.@]
5289  */
5290 BOOL WINAPI FileEncryptionStatusW(LPCWSTR lpFileName, LPDWORD lpStatus)
5291 {
5292     FIXME("(%s %p): stub\n", debugstr_w(lpFileName), lpStatus);
5293     if (!lpStatus)
5294         return FALSE;
5295     *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5296     return TRUE;
5297 }
5298
5299 /******************************************************************************
5300  * FileEncryptionStatusA [ADVAPI32.@]
5301  */
5302 BOOL WINAPI FileEncryptionStatusA(LPCSTR lpFileName, LPDWORD lpStatus)
5303 {
5304     FIXME("(%s %p): stub\n", debugstr_a(lpFileName), lpStatus);
5305     if (!lpStatus)
5306         return FALSE;
5307     *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5308     return TRUE;
5309 }
5310
5311 /******************************************************************************
5312  * SetSecurityInfo [ADVAPI32.@]
5313  */
5314 DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType, 
5315                       SECURITY_INFORMATION SecurityInfo, PSID psidOwner,
5316                       PSID psidGroup, PACL pDacl, PACL pSacl) {
5317     FIXME("stub\n");
5318     return ERROR_SUCCESS;
5319 }
5320
5321 /******************************************************************************
5322  * SaferCreateLevel   [ADVAPI32.@]
5323  */
5324 BOOL WINAPI SaferCreateLevel(DWORD ScopeId, DWORD LevelId, DWORD OpenFlags,
5325                              SAFER_LEVEL_HANDLE* LevelHandle, LPVOID lpReserved)
5326 {
5327     FIXME("(%u, %x, %u, %p, %p) stub\n", ScopeId, LevelId, OpenFlags, LevelHandle, lpReserved);
5328     return FALSE;
5329 }
5330
5331 DWORD WINAPI TreeResetNamedSecurityInfoW( LPWSTR pObjectName,
5332                 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5333                 PSID pOwner, PSID pGroup, PACL pDacl, PACL pSacl,
5334                 BOOL KeepExplicit, FN_PROGRESS fnProgress,
5335                 PROG_INVOKE_SETTING ProgressInvokeSetting, PVOID Args)
5336 {
5337     FIXME("(%s, %i, %i, %p, %p, %p, %p, %i, %p, %i, %p  Stub\n",
5338         debugstr_w(pObjectName), ObjectType, SecurityInfo, pOwner, pGroup,
5339         pDacl, pSacl, KeepExplicit, fnProgress, ProgressInvokeSetting, Args);
5340
5341     return ERROR_SUCCESS;
5342 }