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