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