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