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