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