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