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