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