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