msvcr90: Added __clean_type_info_names_internal stub.
[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
2073     HeapFree( GetProcessHeap(), 0, systemW );
2074     HeapFree( GetProcessHeap(), 0, accountW );
2075     HeapFree( GetProcessHeap(), 0, domainW );
2076
2077     return r;
2078 }
2079
2080 /******************************************************************************
2081  * LookupAccountSidW [ADVAPI32.@]
2082  *
2083  * PARAMS
2084  *   system      []
2085  *   sid         []
2086  *   account     []
2087  *   accountSize []
2088  *   domain      []
2089  *   domainSize  []
2090  *   name_use    []
2091  */
2092
2093 BOOL WINAPI
2094 LookupAccountSidW(
2095         IN LPCWSTR system,
2096         IN PSID sid,
2097         OUT LPWSTR account,
2098         IN OUT LPDWORD accountSize,
2099         OUT LPWSTR domain,
2100         IN OUT LPDWORD domainSize,
2101         OUT PSID_NAME_USE name_use )
2102 {
2103     unsigned int i, j;
2104     const WCHAR * ac = NULL;
2105     const WCHAR * dm = NULL;
2106     SID_NAME_USE use = 0;
2107     LPWSTR computer_name = NULL;
2108     LPWSTR account_name = NULL;
2109
2110     TRACE("(%s,sid=%s,%p,%p(%u),%p,%p(%u),%p)\n",
2111           debugstr_w(system),debugstr_sid(sid),
2112           account,accountSize,accountSize?*accountSize:0,
2113           domain,domainSize,domainSize?*domainSize:0,
2114           name_use);
2115
2116     if (!ADVAPI_IsLocalComputer(system)) {
2117         FIXME("Only local computer supported!\n");
2118         SetLastError(RPC_S_SERVER_UNAVAILABLE);
2119         return FALSE;
2120     }
2121
2122     /* check the well known SIDs first */
2123     for (i = 0; i <= 60; i++) {
2124         if (IsWellKnownSid(sid, i)) {
2125             for (j = 0; j < (sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0])); j++) {
2126                 if (ACCOUNT_SIDS[j].type == i) {
2127                     ac = ACCOUNT_SIDS[j].account;
2128                     dm = ACCOUNT_SIDS[j].domain;
2129                     use = ACCOUNT_SIDS[j].name_use;
2130                 }
2131             }
2132             break;
2133         }
2134     }
2135
2136     if (dm == NULL) {
2137         MAX_SID local;
2138
2139         /* check for the local computer next */
2140         if (ADVAPI_GetComputerSid(&local)) {
2141             DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
2142             BOOL result;
2143
2144             computer_name = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
2145             result = GetComputerNameW(computer_name,  &size);
2146
2147             if (result) {
2148                 if (EqualSid(sid, &local)) {
2149                     dm = computer_name;
2150                     ac = Blank;
2151                     use = 3;
2152                 } else {
2153                     local.SubAuthorityCount++;
2154
2155                     if (EqualPrefixSid(sid, &local)) {
2156                         dm = computer_name;
2157                         use = 1;
2158                         switch (((MAX_SID *)sid)->SubAuthority[4]) {
2159                         case DOMAIN_USER_RID_ADMIN:
2160                             ac = Administrator;
2161                             break;
2162                         case DOMAIN_USER_RID_GUEST:
2163                             ac = Guest;
2164                             break;
2165                         case DOMAIN_GROUP_RID_ADMINS:
2166                             ac = Domain_Admins;
2167                             break;
2168                         case DOMAIN_GROUP_RID_USERS:
2169                             ac = Domain_Users;
2170                             break;
2171                         case DOMAIN_GROUP_RID_GUESTS:
2172                             ac = Domain_Guests;
2173                             break;
2174                         case DOMAIN_GROUP_RID_COMPUTERS:
2175                             ac = Domain_Computers;
2176                             break;
2177                         case DOMAIN_GROUP_RID_CONTROLLERS:
2178                             ac = Domain_Controllers;
2179                             break;
2180                         case DOMAIN_GROUP_RID_CERT_ADMINS:
2181                             ac = Cert_Publishers;
2182                             break;
2183                         case DOMAIN_GROUP_RID_SCHEMA_ADMINS:
2184                             ac = Schema_Admins;
2185                             break;
2186                         case DOMAIN_GROUP_RID_ENTERPRISE_ADMINS:
2187                             ac = Enterprise_Admins;
2188                             break;
2189                         case DOMAIN_GROUP_RID_POLICY_ADMINS:
2190                             ac = Group_Policy_Creator_Owners;
2191                             break;
2192                         case DOMAIN_ALIAS_RID_RAS_SERVERS:
2193                             ac = RAS_and_IAS_Servers;
2194                             break;
2195                         case 1000:      /* first user account */
2196                             size = UNLEN + 1;
2197                             account_name = HeapAlloc(
2198                                 GetProcessHeap(), 0, size * sizeof(WCHAR));
2199                             if (GetUserNameW(account_name, &size))
2200                                 ac = account_name;
2201                             else
2202                                 dm = NULL;
2203
2204                             break;
2205                         default:
2206                             dm = NULL;
2207                             break;
2208                         }
2209                     }
2210                 }
2211             }
2212         }
2213     }
2214
2215     if (dm) {
2216         DWORD ac_len = lstrlenW(ac);
2217         DWORD dm_len = lstrlenW(dm);
2218         BOOL status = TRUE;
2219
2220         if (*accountSize > ac_len) {
2221             if (account)
2222                 lstrcpyW(account, ac);
2223         }
2224         if (*domainSize > dm_len) {
2225             if (domain)
2226                 lstrcpyW(domain, dm);
2227         }
2228         if (((*accountSize != 0) && (*accountSize < ac_len)) ||
2229             ((*domainSize != 0) && (*domainSize < dm_len))) {
2230             SetLastError(ERROR_INSUFFICIENT_BUFFER);
2231             status = FALSE;
2232         }
2233         if (*domainSize)
2234             *domainSize = dm_len;
2235         else
2236             *domainSize = dm_len + 1;
2237         if (*accountSize)
2238             *accountSize = ac_len;
2239         else
2240             *accountSize = ac_len + 1;
2241         *name_use = use;
2242         HeapFree(GetProcessHeap(), 0, account_name);
2243         HeapFree(GetProcessHeap(), 0, computer_name);
2244         return status;
2245     }
2246
2247     HeapFree(GetProcessHeap(), 0, account_name);
2248     HeapFree(GetProcessHeap(), 0, computer_name);
2249     SetLastError(ERROR_NONE_MAPPED);
2250     return FALSE;
2251 }
2252
2253 /******************************************************************************
2254  * SetFileSecurityA [ADVAPI32.@]
2255  *
2256  * See SetFileSecurityW.
2257  */
2258 BOOL WINAPI SetFileSecurityA( LPCSTR lpFileName,
2259                                 SECURITY_INFORMATION RequestedInformation,
2260                                 PSECURITY_DESCRIPTOR pSecurityDescriptor)
2261 {
2262     DWORD len;
2263     BOOL r;
2264     LPWSTR name = NULL;
2265
2266     if( lpFileName )
2267     {
2268         len = MultiByteToWideChar( CP_ACP, 0, lpFileName, -1, NULL, 0 );
2269         name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
2270         MultiByteToWideChar( CP_ACP, 0, lpFileName, -1, name, len );
2271     }
2272
2273     r = SetFileSecurityW( name, RequestedInformation, pSecurityDescriptor );
2274     HeapFree( GetProcessHeap(), 0, name );
2275
2276     return r;
2277 }
2278
2279 /******************************************************************************
2280  * SetFileSecurityW [ADVAPI32.@]
2281  *
2282  * Sets the security of a file or directory.
2283  *
2284  * PARAMS
2285  *   lpFileName           []
2286  *   RequestedInformation []
2287  *   pSecurityDescriptor  []
2288  *
2289  * RETURNS
2290  *  Success: TRUE.
2291  *  Failure: FALSE.
2292  */
2293 BOOL WINAPI
2294 SetFileSecurityW( LPCWSTR lpFileName,
2295                     SECURITY_INFORMATION RequestedInformation,
2296                     PSECURITY_DESCRIPTOR pSecurityDescriptor )
2297 {
2298     HANDLE file;
2299     DWORD access = 0;
2300     NTSTATUS status;
2301
2302     TRACE("(%s, 0x%x, %p)\n", debugstr_w(lpFileName), RequestedInformation,
2303           pSecurityDescriptor );
2304
2305     if (RequestedInformation & OWNER_SECURITY_INFORMATION ||
2306         RequestedInformation & GROUP_SECURITY_INFORMATION)
2307         access |= WRITE_OWNER;
2308     if (RequestedInformation & SACL_SECURITY_INFORMATION)
2309         access |= ACCESS_SYSTEM_SECURITY;
2310     if (RequestedInformation & DACL_SECURITY_INFORMATION)
2311         access |= WRITE_DAC;
2312
2313     file = CreateFileW( lpFileName, access, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
2314                         NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL );
2315     if (file == INVALID_HANDLE_VALUE)
2316         return FALSE;
2317
2318     status = NtSetSecurityObject( file, RequestedInformation, pSecurityDescriptor );
2319     CloseHandle( file );
2320     return set_ntstatus( status );
2321 }
2322
2323 /******************************************************************************
2324  * QueryWindows31FilesMigration [ADVAPI32.@]
2325  *
2326  * PARAMS
2327  *   x1 []
2328  */
2329 BOOL WINAPI
2330 QueryWindows31FilesMigration( DWORD x1 )
2331 {
2332         FIXME("(%d):stub\n",x1);
2333         return TRUE;
2334 }
2335
2336 /******************************************************************************
2337  * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@]
2338  *
2339  * PARAMS
2340  *   x1 []
2341  *   x2 []
2342  *   x3 []
2343  *   x4 []
2344  */
2345 BOOL WINAPI
2346 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3,
2347                                                DWORD x4 )
2348 {
2349         FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4);
2350         return TRUE;
2351 }
2352
2353 /******************************************************************************
2354  * NotifyBootConfigStatus [ADVAPI32.@]
2355  *
2356  * PARAMS
2357  *   x1 []
2358  */
2359 BOOL WINAPI
2360 NotifyBootConfigStatus( BOOL x1 )
2361 {
2362         FIXME("(0x%08d):stub\n",x1);
2363         return 1;
2364 }
2365
2366 /******************************************************************************
2367  * RevertToSelf [ADVAPI32.@]
2368  *
2369  * Ends the impersonation of a user.
2370  *
2371  * PARAMS
2372  *   void []
2373  *
2374  * RETURNS
2375  *  Success: TRUE.
2376  *  Failure: FALSE.
2377  */
2378 BOOL WINAPI
2379 RevertToSelf( void )
2380 {
2381     HANDLE Token = NULL;
2382     return set_ntstatus( NtSetInformationThread( GetCurrentThread(),
2383         ThreadImpersonationToken, &Token, sizeof(Token) ) );
2384 }
2385
2386 /******************************************************************************
2387  * ImpersonateSelf [ADVAPI32.@]
2388  *
2389  * Makes an impersonation token that represents the process user and assigns
2390  * to the current thread.
2391  *
2392  * PARAMS
2393  *  ImpersonationLevel [I] Level at which to impersonate.
2394  *
2395  * RETURNS
2396  *  Success: TRUE.
2397  *  Failure: FALSE.
2398  */
2399 BOOL WINAPI
2400 ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
2401 {
2402     return set_ntstatus( RtlImpersonateSelf( ImpersonationLevel ) );
2403 }
2404
2405 /******************************************************************************
2406  * ImpersonateLoggedOnUser [ADVAPI32.@]
2407  */
2408 BOOL WINAPI ImpersonateLoggedOnUser(HANDLE hToken)
2409 {
2410     DWORD size;
2411     NTSTATUS Status;
2412     HANDLE ImpersonationToken;
2413     TOKEN_TYPE Type;
2414     static BOOL warn = TRUE;
2415
2416     if (warn)
2417     {
2418         FIXME( "(%p)\n", hToken );
2419         warn = FALSE;
2420     }
2421     if (!GetTokenInformation( hToken, TokenType, &Type,
2422                               sizeof(TOKEN_TYPE), &size ))
2423         return FALSE;
2424
2425     if (Type == TokenPrimary)
2426     {
2427         OBJECT_ATTRIBUTES ObjectAttributes;
2428
2429         InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
2430
2431         Status = NtDuplicateToken( hToken,
2432                                    TOKEN_IMPERSONATE | TOKEN_QUERY,
2433                                    &ObjectAttributes,
2434                                    SecurityImpersonation,
2435                                    TokenImpersonation,
2436                                    &ImpersonationToken );
2437         if (Status != STATUS_SUCCESS)
2438         {
2439             ERR( "NtDuplicateToken failed with error 0x%08x\n", Status );
2440             SetLastError( RtlNtStatusToDosError( Status ) );
2441             return FALSE;
2442         }
2443     }
2444     else
2445         ImpersonationToken = hToken;
2446
2447     Status = NtSetInformationThread( GetCurrentThread(),
2448                                      ThreadImpersonationToken,
2449                                      &ImpersonationToken,
2450                                      sizeof(ImpersonationToken) );
2451
2452     if (Type == TokenPrimary)
2453         NtClose( ImpersonationToken );
2454
2455     if (Status != STATUS_SUCCESS)
2456     {
2457         ERR( "NtSetInformationThread failed with error 0x%08x\n", Status );
2458         SetLastError( RtlNtStatusToDosError( Status ) );
2459         return FALSE;
2460     }
2461
2462     return TRUE;
2463 }
2464
2465 /******************************************************************************
2466  * AccessCheck [ADVAPI32.@]
2467  */
2468 BOOL WINAPI
2469 AccessCheck(
2470         PSECURITY_DESCRIPTOR SecurityDescriptor,
2471         HANDLE ClientToken,
2472         DWORD DesiredAccess,
2473         PGENERIC_MAPPING GenericMapping,
2474         PPRIVILEGE_SET PrivilegeSet,
2475         LPDWORD PrivilegeSetLength,
2476         LPDWORD GrantedAccess,
2477         LPBOOL AccessStatus)
2478 {
2479     NTSTATUS access_status;
2480     BOOL ret = set_ntstatus( NtAccessCheck(SecurityDescriptor, ClientToken, DesiredAccess,
2481                                            GenericMapping, PrivilegeSet, PrivilegeSetLength,
2482                                            GrantedAccess, &access_status) );
2483     if (ret) *AccessStatus = set_ntstatus( access_status );
2484     return ret;
2485 }
2486
2487
2488 /******************************************************************************
2489  * AccessCheckByType [ADVAPI32.@]
2490  */
2491 BOOL WINAPI AccessCheckByType(
2492     PSECURITY_DESCRIPTOR pSecurityDescriptor, 
2493     PSID PrincipalSelfSid,
2494     HANDLE ClientToken, 
2495     DWORD DesiredAccess, 
2496     POBJECT_TYPE_LIST ObjectTypeList,
2497     DWORD ObjectTypeListLength,
2498     PGENERIC_MAPPING GenericMapping,
2499     PPRIVILEGE_SET PrivilegeSet,
2500     LPDWORD PrivilegeSetLength, 
2501     LPDWORD GrantedAccess,
2502     LPBOOL AccessStatus)
2503 {
2504         FIXME("stub\n");
2505
2506         *AccessStatus = TRUE;
2507
2508         return !*AccessStatus;
2509 }
2510
2511 /******************************************************************************
2512  * MapGenericMask [ADVAPI32.@]
2513  *
2514  * Maps generic access rights into specific access rights according to the
2515  * supplied mapping.
2516  *
2517  * PARAMS
2518  *  AccessMask     [I/O] Access rights.
2519  *  GenericMapping [I] The mapping between generic and specific rights.
2520  *
2521  * RETURNS
2522  *  Nothing.
2523  */
2524 VOID WINAPI MapGenericMask( PDWORD AccessMask, PGENERIC_MAPPING GenericMapping )
2525 {
2526     RtlMapGenericMask( AccessMask, GenericMapping );
2527 }
2528
2529 /*************************************************************************
2530  * SetKernelObjectSecurity [ADVAPI32.@]
2531  */
2532 BOOL WINAPI SetKernelObjectSecurity (
2533         IN HANDLE Handle,
2534         IN SECURITY_INFORMATION SecurityInformation,
2535         IN PSECURITY_DESCRIPTOR SecurityDescriptor )
2536 {
2537     return set_ntstatus (NtSetSecurityObject (Handle, SecurityInformation, SecurityDescriptor));
2538 }
2539
2540
2541 /******************************************************************************
2542  *  AddAuditAccessAce [ADVAPI32.@]
2543  */
2544 BOOL WINAPI AddAuditAccessAce(
2545     IN OUT PACL pAcl, 
2546     IN DWORD dwAceRevision, 
2547     IN DWORD dwAccessMask, 
2548     IN PSID pSid, 
2549     IN BOOL bAuditSuccess, 
2550     IN BOOL bAuditFailure) 
2551 {
2552     return set_ntstatus( RtlAddAuditAccessAce(pAcl, dwAceRevision, dwAccessMask, pSid, 
2553                                               bAuditSuccess, bAuditFailure) ); 
2554 }
2555
2556 /******************************************************************************
2557  *  AddAuditAccessAce [ADVAPI32.@]
2558  */
2559 BOOL WINAPI AddAuditAccessAceEx(
2560     IN OUT PACL pAcl,
2561     IN DWORD dwAceRevision,
2562     IN DWORD dwAceFlags,
2563     IN DWORD dwAccessMask,
2564     IN PSID pSid,
2565     IN BOOL bAuditSuccess,
2566     IN BOOL bAuditFailure)
2567 {
2568     return set_ntstatus( RtlAddAuditAccessAceEx(pAcl, dwAceRevision, dwAceFlags, dwAccessMask, pSid,
2569                                               bAuditSuccess, bAuditFailure) );
2570 }
2571
2572 /******************************************************************************
2573  * LookupAccountNameA [ADVAPI32.@]
2574  */
2575 BOOL WINAPI
2576 LookupAccountNameA(
2577         IN LPCSTR system,
2578         IN LPCSTR account,
2579         OUT PSID sid,
2580         OUT LPDWORD cbSid,
2581         LPSTR ReferencedDomainName,
2582         IN OUT LPDWORD cbReferencedDomainName,
2583         OUT PSID_NAME_USE name_use )
2584 {
2585     BOOL ret;
2586     UNICODE_STRING lpSystemW;
2587     UNICODE_STRING lpAccountW;
2588     LPWSTR lpReferencedDomainNameW = NULL;
2589
2590     RtlCreateUnicodeStringFromAsciiz(&lpSystemW, system);
2591     RtlCreateUnicodeStringFromAsciiz(&lpAccountW, account);
2592
2593     if (ReferencedDomainName)
2594         lpReferencedDomainNameW = HeapAlloc(GetProcessHeap(), 0, *cbReferencedDomainName * sizeof(WCHAR));
2595
2596     ret = LookupAccountNameW(lpSystemW.Buffer, lpAccountW.Buffer, sid, cbSid, lpReferencedDomainNameW,
2597         cbReferencedDomainName, name_use);
2598
2599     if (ret && lpReferencedDomainNameW)
2600     {
2601         WideCharToMultiByte(CP_ACP, 0, lpReferencedDomainNameW, -1,
2602             ReferencedDomainName, *cbReferencedDomainName+1, NULL, NULL);
2603     }
2604
2605     RtlFreeUnicodeString(&lpSystemW);
2606     RtlFreeUnicodeString(&lpAccountW);
2607     HeapFree(GetProcessHeap(), 0, lpReferencedDomainNameW);
2608
2609     return ret;
2610 }
2611
2612 /******************************************************************************
2613  * lookup_user_account_name
2614  */
2615 static BOOL lookup_user_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2616                                      LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2617 {
2618     char buffer[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
2619     DWORD len = sizeof(buffer);
2620     HANDLE token;
2621     BOOL ret;
2622     PSID pSid;
2623     static const WCHAR dm[] = {'D','O','M','A','I','N',0};
2624     DWORD nameLen;
2625     LPCWSTR domainName;
2626
2627     if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
2628     {
2629         if (GetLastError() != ERROR_NO_TOKEN) return FALSE;
2630         if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) return FALSE;
2631     }
2632
2633     ret = GetTokenInformation(token, TokenUser, buffer, len, &len);
2634     CloseHandle( token );
2635
2636     if (!ret) return FALSE;
2637
2638     pSid = ((TOKEN_USER *)buffer)->User.Sid;
2639
2640     if (Sid != NULL && (*cbSid >= GetLengthSid(pSid)))
2641        CopySid(*cbSid, Sid, pSid);
2642     if (*cbSid < GetLengthSid(pSid))
2643     {
2644        SetLastError(ERROR_INSUFFICIENT_BUFFER);
2645        ret = FALSE;
2646     }
2647     *cbSid = GetLengthSid(pSid);
2648
2649     domainName = dm;
2650     nameLen = strlenW(domainName);
2651
2652     if (*cchReferencedDomainName <= nameLen || !ret)
2653     {
2654         SetLastError(ERROR_INSUFFICIENT_BUFFER);
2655         nameLen += 1;
2656         ret = FALSE;
2657     }
2658     else if (ReferencedDomainName)
2659         strcpyW(ReferencedDomainName, domainName);
2660
2661     *cchReferencedDomainName = nameLen;
2662
2663     if (ret)
2664         *peUse = SidTypeUser;
2665
2666     return ret;
2667 }
2668
2669 /******************************************************************************
2670  * lookup_computer_account_name
2671  */
2672 static BOOL lookup_computer_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2673                                          LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2674 {
2675     MAX_SID local;
2676     BOOL ret;
2677     static const WCHAR dm[] = {'D','O','M','A','I','N',0};
2678     DWORD nameLen;
2679     LPCWSTR domainName;
2680
2681     if ((ret = ADVAPI_GetComputerSid(&local)))
2682     {
2683         if (Sid != NULL && (*cbSid >= GetLengthSid(&local)))
2684            CopySid(*cbSid, Sid, &local);
2685         if (*cbSid < GetLengthSid(&local))
2686         {
2687            SetLastError(ERROR_INSUFFICIENT_BUFFER);
2688            ret = FALSE;
2689         }
2690         *cbSid = GetLengthSid(&local);
2691     }
2692
2693     domainName = dm;
2694     nameLen = strlenW(domainName);
2695
2696     if (*cchReferencedDomainName <= nameLen || !ret)
2697     {
2698         SetLastError(ERROR_INSUFFICIENT_BUFFER);
2699         nameLen += 1;
2700         ret = FALSE;
2701     }
2702     else if (ReferencedDomainName)
2703         strcpyW(ReferencedDomainName, domainName);
2704
2705     *cchReferencedDomainName = nameLen;
2706
2707     if (ret)
2708         *peUse = SidTypeDomain;
2709
2710     return ret;
2711 }
2712
2713 static void split_domain_account( const LSA_UNICODE_STRING *str, LSA_UNICODE_STRING *account,
2714                                   LSA_UNICODE_STRING *domain )
2715 {
2716     WCHAR *p = str->Buffer + str->Length / sizeof(WCHAR) - 1;
2717
2718     while (p > str->Buffer && *p != '\\') p--;
2719
2720     if (*p == '\\')
2721     {
2722         domain->Buffer = str->Buffer;
2723         domain->Length = (p - str->Buffer) * sizeof(WCHAR);
2724
2725         account->Buffer = p + 1;
2726         account->Length = str->Length - ((p - str->Buffer + 1) * sizeof(WCHAR));
2727     }
2728     else
2729     {
2730         domain->Buffer = NULL;
2731         domain->Length = 0;
2732
2733         account->Buffer = str->Buffer;
2734         account->Length = str->Length;
2735     }
2736 }
2737
2738 static BOOL match_domain( ULONG idx, LSA_UNICODE_STRING *domain )
2739 {
2740     ULONG len = strlenW( ACCOUNT_SIDS[idx].domain );
2741
2742     if (len == domain->Length / sizeof(WCHAR) && !strncmpiW( domain->Buffer, ACCOUNT_SIDS[idx].domain, len ))
2743         return TRUE;
2744
2745     return FALSE;
2746 }
2747
2748 static BOOL match_account( ULONG idx, LSA_UNICODE_STRING *account )
2749 {
2750     ULONG len = strlenW( ACCOUNT_SIDS[idx].account );
2751
2752     if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].account, len ))
2753         return TRUE;
2754
2755     if (ACCOUNT_SIDS[idx].alias)
2756     {
2757         len = strlenW( ACCOUNT_SIDS[idx].alias );
2758         if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].alias, len ))
2759             return TRUE;
2760     }
2761     return FALSE;
2762 }
2763
2764 /*
2765  * Helper function for LookupAccountNameW
2766  */
2767 BOOL lookup_local_wellknown_name( LSA_UNICODE_STRING *account_and_domain,
2768                                   PSID Sid, LPDWORD cbSid,
2769                                   LPWSTR ReferencedDomainName,
2770                                   LPDWORD cchReferencedDomainName,
2771                                   PSID_NAME_USE peUse, BOOL *handled )
2772 {
2773     PSID pSid;
2774     LSA_UNICODE_STRING account, domain;
2775     BOOL ret = TRUE;
2776     ULONG i;
2777
2778     *handled = FALSE;
2779     split_domain_account( account_and_domain, &account, &domain );
2780
2781     for (i = 0; i < sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0]); i++)
2782     {
2783         /* check domain first */
2784         if (domain.Buffer && !match_domain( i, &domain )) continue;
2785
2786         if (match_account( i, &account ))
2787         {
2788             DWORD len, sidLen = SECURITY_MAX_SID_SIZE;
2789
2790             if (!(pSid = HeapAlloc( GetProcessHeap(), 0, sidLen ))) return FALSE;
2791
2792             if ((ret = CreateWellKnownSid( ACCOUNT_SIDS[i].type, NULL, pSid, &sidLen )))
2793             {
2794                 if (*cbSid < sidLen)
2795                 {
2796                     SetLastError(ERROR_INSUFFICIENT_BUFFER);
2797                     ret = FALSE;
2798                 }
2799                 else if (Sid)
2800                 {
2801                     CopySid(*cbSid, Sid, pSid);
2802                 }
2803                 *cbSid = sidLen;
2804             }
2805
2806             len = strlenW( ACCOUNT_SIDS[i].domain );
2807             if (*cchReferencedDomainName <= len || !ret)
2808             {
2809                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2810                 len++;
2811                 ret = FALSE;
2812             }
2813             else if (ReferencedDomainName)
2814             {
2815                 strcpyW( ReferencedDomainName, ACCOUNT_SIDS[i].domain );
2816             }
2817
2818             *cchReferencedDomainName = len;
2819             if (ret)
2820                 *peUse = ACCOUNT_SIDS[i].name_use;
2821
2822             HeapFree(GetProcessHeap(), 0, pSid);
2823             *handled = TRUE;
2824             return ret;
2825         }
2826     }
2827     return ret;
2828 }
2829
2830 BOOL lookup_local_user_name( LSA_UNICODE_STRING *account_and_domain,
2831                              PSID Sid, LPDWORD cbSid,
2832                              LPWSTR ReferencedDomainName,
2833                              LPDWORD cchReferencedDomainName,
2834                              PSID_NAME_USE peUse, BOOL *handled )
2835 {
2836     DWORD nameLen;
2837     LPWSTR userName = NULL;
2838     LSA_UNICODE_STRING account, domain;
2839     BOOL ret = TRUE;
2840
2841     *handled = FALSE;
2842     split_domain_account( account_and_domain, &account, &domain );
2843
2844     /* Let the current Unix user id masquerade as first Windows user account */
2845
2846     nameLen = UNLEN + 1;
2847     if (!(userName = HeapAlloc( GetProcessHeap(), 0, nameLen * sizeof(WCHAR) ))) return FALSE;
2848
2849     if (domain.Buffer)
2850     {
2851         /* check to make sure this account is on this computer */
2852         if (GetComputerNameW( userName, &nameLen ) &&
2853             (domain.Length / sizeof(WCHAR) != nameLen || strncmpW( domain.Buffer, userName, nameLen )))
2854         {
2855             SetLastError(ERROR_NONE_MAPPED);
2856             ret = FALSE;
2857         }
2858         nameLen = UNLEN + 1;
2859     }
2860
2861     if (GetUserNameW( userName, &nameLen ) &&
2862         account.Length / sizeof(WCHAR) == nameLen - 1 && !strncmpW( account.Buffer, userName, nameLen - 1 ))
2863     {
2864             ret = lookup_user_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2865             *handled = TRUE;
2866     }
2867     else
2868     {
2869         nameLen = UNLEN + 1;
2870         if (GetComputerNameW( userName, &nameLen ) &&
2871             account.Length / sizeof(WCHAR) == nameLen && !strncmpW( account.Buffer, userName , nameLen ))
2872         {
2873             ret = lookup_computer_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2874             *handled = TRUE;
2875         }
2876     }
2877
2878     HeapFree(GetProcessHeap(), 0, userName);
2879     return ret;
2880 }
2881
2882 /******************************************************************************
2883  * LookupAccountNameW [ADVAPI32.@]
2884  */
2885 BOOL WINAPI LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid,
2886                                 LPDWORD cbSid, LPWSTR ReferencedDomainName,
2887                                 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2888 {
2889     BOOL ret, handled;
2890     LSA_UNICODE_STRING account;
2891
2892     FIXME("%s %s %p %p %p %p %p - stub\n", debugstr_w(lpSystemName), debugstr_w(lpAccountName),
2893           Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse);
2894
2895     if (!ADVAPI_IsLocalComputer( lpSystemName ))
2896     {
2897         SetLastError( RPC_S_SERVER_UNAVAILABLE );
2898         return FALSE;
2899     }
2900
2901     if (!lpAccountName || !strcmpW( lpAccountName, Blank ))
2902     {
2903         lpAccountName = BUILTIN;
2904     }
2905
2906     RtlInitUnicodeString( &account, lpAccountName );
2907
2908     /* Check well known SIDs first */
2909     ret = lookup_local_wellknown_name( &account, Sid, cbSid, ReferencedDomainName,
2910                                        cchReferencedDomainName, peUse, &handled );
2911     if (handled)
2912         return ret;
2913
2914     /* Check user names */
2915     ret = lookup_local_user_name( &account, Sid, cbSid, ReferencedDomainName,
2916                                   cchReferencedDomainName, peUse, &handled);
2917     if (handled)
2918         return ret;
2919
2920     SetLastError( ERROR_NONE_MAPPED );
2921     return FALSE;
2922 }
2923
2924 /******************************************************************************
2925  * PrivilegeCheck [ADVAPI32.@]
2926  */
2927 BOOL WINAPI PrivilegeCheck( HANDLE ClientToken, PPRIVILEGE_SET RequiredPrivileges, LPBOOL pfResult)
2928 {
2929     BOOL ret;
2930     BOOLEAN Result;
2931
2932     TRACE("%p %p %p\n", ClientToken, RequiredPrivileges, pfResult);
2933
2934     ret = set_ntstatus (NtPrivilegeCheck (ClientToken, RequiredPrivileges, &Result));
2935     if (ret)
2936         *pfResult = Result;
2937     return ret;
2938 }
2939
2940 /******************************************************************************
2941  * AccessCheckAndAuditAlarmA [ADVAPI32.@]
2942  */
2943 BOOL WINAPI AccessCheckAndAuditAlarmA(LPCSTR Subsystem, LPVOID HandleId, LPSTR ObjectTypeName,
2944   LPSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
2945   PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
2946   LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
2947 {
2948         FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_a(Subsystem),
2949                 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName),
2950                 SecurityDescriptor, DesiredAccess, GenericMapping,
2951                 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
2952         return TRUE;
2953 }
2954
2955 /******************************************************************************
2956  * AccessCheckAndAuditAlarmW [ADVAPI32.@]
2957  */
2958 BOOL WINAPI AccessCheckAndAuditAlarmW(LPCWSTR Subsystem, LPVOID HandleId, LPWSTR ObjectTypeName,
2959   LPWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
2960   PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
2961   LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
2962 {
2963         FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_w(Subsystem),
2964                 HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName),
2965                 SecurityDescriptor, DesiredAccess, GenericMapping,
2966                 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
2967         return TRUE;
2968 }
2969
2970 BOOL WINAPI ObjectCloseAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
2971 {
2972     FIXME("stub (%s,%p,%x)\n", debugstr_a(SubsystemName), HandleId, GenerateOnClose);
2973
2974     return TRUE;
2975 }
2976
2977 BOOL WINAPI ObjectCloseAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
2978 {
2979     FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
2980
2981     return TRUE;
2982 }
2983
2984 BOOL WINAPI ObjectDeleteAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
2985 {
2986     FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
2987
2988     return TRUE;
2989 }
2990
2991 BOOL WINAPI ObjectOpenAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, LPSTR ObjectTypeName,
2992   LPSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
2993   DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
2994   LPBOOL GenerateOnClose)
2995 {
2996         FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_a(SubsystemName),
2997                 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName), pSecurityDescriptor,
2998         ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
2999         GenerateOnClose);
3000
3001     return TRUE;
3002 }
3003
3004 BOOL WINAPI ObjectOpenAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, LPWSTR ObjectTypeName,
3005   LPWSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
3006   DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
3007   LPBOOL GenerateOnClose)
3008 {
3009     FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_w(SubsystemName),
3010         HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName), pSecurityDescriptor,
3011         ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
3012         GenerateOnClose);
3013
3014     return TRUE;
3015 }
3016
3017 BOOL WINAPI ObjectPrivilegeAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
3018   DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3019 {
3020     FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_a(SubsystemName), HandleId, ClientToken,
3021           DesiredAccess, Privileges, AccessGranted);
3022
3023     return TRUE;
3024 }
3025
3026 BOOL WINAPI ObjectPrivilegeAuditAlarmW( LPCWSTR 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_w(SubsystemName), HandleId, ClientToken,
3030           DesiredAccess, Privileges, AccessGranted);
3031
3032     return TRUE;
3033 }
3034
3035 BOOL WINAPI PrivilegedServiceAuditAlarmA( LPCSTR SubsystemName, LPCSTR ServiceName, HANDLE ClientToken,
3036                                    PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3037 {
3038     FIXME("stub (%s,%s,%p,%p,%x)\n", debugstr_a(SubsystemName), debugstr_a(ServiceName),
3039           ClientToken, Privileges, AccessGranted);
3040
3041     return TRUE;
3042 }
3043
3044 BOOL WINAPI PrivilegedServiceAuditAlarmW( LPCWSTR SubsystemName, LPCWSTR ServiceName, HANDLE ClientToken,
3045                                    PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3046 {
3047     FIXME("stub %s,%s,%p,%p,%x)\n", debugstr_w(SubsystemName), debugstr_w(ServiceName),
3048           ClientToken, Privileges, AccessGranted);
3049
3050     return TRUE;
3051 }
3052
3053 /******************************************************************************
3054  * GetSecurityInfo [ADVAPI32.@]
3055  *
3056  * Retrieves a copy of the security descriptor associated with an object.
3057  *
3058  * PARAMS
3059  *  hObject              [I] A handle for the object.
3060  *  ObjectType           [I] The type of object.
3061  *  SecurityInfo         [I] A bitmask indicating what info to retrieve.
3062  *  ppsidOwner           [O] If non-null, receives a pointer to the owner SID.
3063  *  ppsidGroup           [O] If non-null, receives a pointer to the group SID.
3064  *  ppDacl               [O] If non-null, receives a pointer to the DACL.
3065  *  ppSacl               [O] If non-null, receives a pointer to the SACL.
3066  *  ppSecurityDescriptor [O] Receives a pointer to the security descriptor,
3067  *                           which must be freed with LocalFree.
3068  *
3069  * RETURNS
3070  *  ERROR_SUCCESS if all's well, and a WIN32 error code otherwise.
3071  */
3072 DWORD WINAPI GetSecurityInfo(
3073     HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3074     SECURITY_INFORMATION SecurityInfo, PSID *ppsidOwner,
3075     PSID *ppsidGroup, PACL *ppDacl, PACL *ppSacl,
3076     PSECURITY_DESCRIPTOR *ppSecurityDescriptor
3077 )
3078 {
3079     PSECURITY_DESCRIPTOR sd;
3080     NTSTATUS status;
3081     ULONG n1, n2;
3082     BOOL present, defaulted;
3083
3084     status = NtQuerySecurityObject(hObject, SecurityInfo, NULL, 0, &n1);
3085     if (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_SUCCESS)
3086         return RtlNtStatusToDosError(status);
3087
3088     sd = LocalAlloc(0, n1);
3089     if (!sd)
3090         return ERROR_NOT_ENOUGH_MEMORY;
3091
3092     status = NtQuerySecurityObject(hObject, SecurityInfo, sd, n1, &n2);
3093     if (status != STATUS_SUCCESS)
3094     {
3095         LocalFree(sd);
3096         return RtlNtStatusToDosError(status);
3097     }
3098
3099     if (ppsidOwner)
3100     {
3101         *ppsidOwner = NULL;
3102         GetSecurityDescriptorOwner(sd, ppsidOwner, &defaulted);
3103     }
3104     if (ppsidGroup)
3105     {
3106         *ppsidGroup = NULL;
3107         GetSecurityDescriptorGroup(sd, ppsidGroup, &defaulted);
3108     }
3109     if (ppDacl)
3110     {
3111         *ppDacl = NULL;
3112         GetSecurityDescriptorDacl(sd, &present, ppDacl, &defaulted);
3113     }
3114     if (ppSacl)
3115     {
3116         *ppSacl = NULL;
3117         GetSecurityDescriptorSacl(sd, &present, ppSacl, &defaulted);
3118     }
3119     if (ppSecurityDescriptor)
3120         *ppSecurityDescriptor = sd;
3121
3122     /* The security descriptor (sd) cannot be freed if ppSecurityDescriptor is
3123      * NULL, because native happily returns the SIDs and ACLs that are requested
3124      * in this case.
3125      */
3126
3127     return ERROR_SUCCESS;
3128 }
3129
3130 /******************************************************************************
3131  * GetSecurityInfoExA [ADVAPI32.@]
3132  */
3133 DWORD WINAPI GetSecurityInfoExA(
3134         HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3135         SECURITY_INFORMATION SecurityInfo, LPCSTR lpProvider,
3136         LPCSTR lpProperty, PACTRL_ACCESSA *ppAccessList,
3137         PACTRL_AUDITA *ppAuditList, LPSTR *lppOwner, LPSTR *lppGroup
3138 )
3139 {
3140   FIXME("stub!\n");
3141   return ERROR_BAD_PROVIDER;
3142 }
3143
3144 /******************************************************************************
3145  * GetSecurityInfoExW [ADVAPI32.@]
3146  */
3147 DWORD WINAPI GetSecurityInfoExW(
3148         HANDLE hObject, SE_OBJECT_TYPE ObjectType, 
3149         SECURITY_INFORMATION SecurityInfo, LPCWSTR lpProvider,
3150         LPCWSTR lpProperty, PACTRL_ACCESSW *ppAccessList, 
3151         PACTRL_AUDITW *ppAuditList, LPWSTR *lppOwner, LPWSTR *lppGroup
3152 )
3153 {
3154   FIXME("stub!\n");
3155   return ERROR_BAD_PROVIDER; 
3156 }
3157
3158 /******************************************************************************
3159  * BuildExplicitAccessWithNameA [ADVAPI32.@]
3160  */
3161 VOID WINAPI BuildExplicitAccessWithNameA( PEXPLICIT_ACCESSA pExplicitAccess,
3162                                           LPSTR pTrusteeName, DWORD AccessPermissions,
3163                                           ACCESS_MODE AccessMode, DWORD Inheritance )
3164 {
3165     TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_a(pTrusteeName),
3166           AccessPermissions, AccessMode, Inheritance);
3167
3168     pExplicitAccess->grfAccessPermissions = AccessPermissions;
3169     pExplicitAccess->grfAccessMode = AccessMode;
3170     pExplicitAccess->grfInheritance = Inheritance;
3171
3172     pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3173     pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3174     pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3175     pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3176     pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3177 }
3178
3179 /******************************************************************************
3180  * BuildExplicitAccessWithNameW [ADVAPI32.@]
3181  */
3182 VOID WINAPI BuildExplicitAccessWithNameW( PEXPLICIT_ACCESSW pExplicitAccess,
3183                                           LPWSTR pTrusteeName, DWORD AccessPermissions,
3184                                           ACCESS_MODE AccessMode, DWORD Inheritance )
3185 {
3186     TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_w(pTrusteeName),
3187           AccessPermissions, AccessMode, Inheritance);
3188
3189     pExplicitAccess->grfAccessPermissions = AccessPermissions;
3190     pExplicitAccess->grfAccessMode = AccessMode;
3191     pExplicitAccess->grfInheritance = Inheritance;
3192
3193     pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3194     pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3195     pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3196     pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3197     pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3198 }
3199
3200 /******************************************************************************
3201  * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
3202  */
3203 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
3204                                              SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
3205                                              LPSTR InheritedObjectTypeName, LPSTR Name )
3206 {
3207     DWORD ObjectsPresent = 0;
3208
3209     TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3210           ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
3211
3212     /* Fill the OBJECTS_AND_NAME structure */
3213     pObjName->ObjectType = ObjectType;
3214     if (ObjectTypeName != NULL)
3215     {
3216         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3217     }
3218
3219     pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3220     if (InheritedObjectTypeName != NULL)
3221     {
3222         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3223     }
3224
3225     pObjName->ObjectsPresent = ObjectsPresent;
3226     pObjName->ptstrName = Name;
3227
3228     /* Fill the TRUSTEE structure */
3229     pTrustee->pMultipleTrustee = NULL;
3230     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3231     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3232     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3233     pTrustee->ptstrName = (LPSTR)pObjName;
3234 }
3235
3236 /******************************************************************************
3237  * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
3238  */
3239 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
3240                                              SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
3241                                              LPWSTR InheritedObjectTypeName, LPWSTR Name )
3242 {
3243     DWORD ObjectsPresent = 0;
3244
3245     TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3246           ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
3247
3248     /* Fill the OBJECTS_AND_NAME structure */
3249     pObjName->ObjectType = ObjectType;
3250     if (ObjectTypeName != NULL)
3251     {
3252         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3253     }
3254
3255     pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3256     if (InheritedObjectTypeName != NULL)
3257     {
3258         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3259     }
3260
3261     pObjName->ObjectsPresent = ObjectsPresent;
3262     pObjName->ptstrName = Name;
3263
3264     /* Fill the TRUSTEE structure */
3265     pTrustee->pMultipleTrustee = NULL;
3266     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3267     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3268     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3269     pTrustee->ptstrName = (LPWSTR)pObjName;
3270 }
3271
3272 /******************************************************************************
3273  * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
3274  */
3275 VOID WINAPI BuildTrusteeWithObjectsAndSidA( PTRUSTEEA pTrustee, POBJECTS_AND_SID pObjSid,
3276                                             GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3277 {
3278     DWORD ObjectsPresent = 0;
3279
3280     TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3281
3282     /* Fill the OBJECTS_AND_SID structure */
3283     if (pObjectGuid != NULL)
3284     {
3285         pObjSid->ObjectTypeGuid = *pObjectGuid;
3286         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3287     }
3288     else
3289     {
3290         ZeroMemory(&pObjSid->ObjectTypeGuid,
3291                    sizeof(GUID));
3292     }
3293
3294     if (pInheritedObjectGuid != NULL)
3295     {
3296         pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3297         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3298     }
3299     else
3300     {
3301         ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3302                    sizeof(GUID));
3303     }
3304
3305     pObjSid->ObjectsPresent = ObjectsPresent;
3306     pObjSid->pSid = pSid;
3307
3308     /* Fill the TRUSTEE structure */
3309     pTrustee->pMultipleTrustee = NULL;
3310     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3311     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3312     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3313     pTrustee->ptstrName = (LPSTR) pObjSid;
3314 }
3315
3316 /******************************************************************************
3317  * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
3318  */
3319 VOID WINAPI BuildTrusteeWithObjectsAndSidW( PTRUSTEEW pTrustee, POBJECTS_AND_SID pObjSid,
3320                                             GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3321 {
3322     DWORD ObjectsPresent = 0;
3323
3324     TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3325
3326     /* Fill the OBJECTS_AND_SID structure */
3327     if (pObjectGuid != NULL)
3328     {
3329         pObjSid->ObjectTypeGuid = *pObjectGuid;
3330         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3331     }
3332     else
3333     {
3334         ZeroMemory(&pObjSid->ObjectTypeGuid,
3335                    sizeof(GUID));
3336     }
3337
3338     if (pInheritedObjectGuid != NULL)
3339     {
3340         pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3341         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3342     }
3343     else
3344     {
3345         ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3346                    sizeof(GUID));
3347     }
3348
3349     pObjSid->ObjectsPresent = ObjectsPresent;
3350     pObjSid->pSid = pSid;
3351
3352     /* Fill the TRUSTEE structure */
3353     pTrustee->pMultipleTrustee = NULL;
3354     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3355     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3356     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3357     pTrustee->ptstrName = (LPWSTR) pObjSid;
3358 }
3359
3360 /******************************************************************************
3361  * BuildTrusteeWithSidA [ADVAPI32.@]
3362  */
3363 VOID WINAPI BuildTrusteeWithSidA(PTRUSTEEA pTrustee, PSID pSid)
3364 {
3365     TRACE("%p %p\n", pTrustee, pSid);
3366
3367     pTrustee->pMultipleTrustee = NULL;
3368     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3369     pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3370     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3371     pTrustee->ptstrName = pSid;
3372 }
3373
3374 /******************************************************************************
3375  * BuildTrusteeWithSidW [ADVAPI32.@]
3376  */
3377 VOID WINAPI BuildTrusteeWithSidW(PTRUSTEEW pTrustee, PSID pSid)
3378 {
3379     TRACE("%p %p\n", pTrustee, pSid);
3380
3381     pTrustee->pMultipleTrustee = NULL;
3382     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3383     pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3384     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3385     pTrustee->ptstrName = pSid;
3386 }
3387
3388 /******************************************************************************
3389  * BuildTrusteeWithNameA [ADVAPI32.@]
3390  */
3391 VOID WINAPI BuildTrusteeWithNameA(PTRUSTEEA pTrustee, LPSTR name)
3392 {
3393     TRACE("%p %s\n", pTrustee, debugstr_a(name) );
3394
3395     pTrustee->pMultipleTrustee = NULL;
3396     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3397     pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3398     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3399     pTrustee->ptstrName = name;
3400 }
3401
3402 /******************************************************************************
3403  * BuildTrusteeWithNameW [ADVAPI32.@]
3404  */
3405 VOID WINAPI BuildTrusteeWithNameW(PTRUSTEEW pTrustee, LPWSTR name)
3406 {
3407     TRACE("%p %s\n", pTrustee, debugstr_w(name) );
3408
3409     pTrustee->pMultipleTrustee = NULL;
3410     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3411     pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3412     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3413     pTrustee->ptstrName = name;
3414 }
3415
3416 /****************************************************************************** 
3417  * GetTrusteeFormA [ADVAPI32.@] 
3418  */ 
3419 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee) 
3420 {  
3421     TRACE("(%p)\n", pTrustee); 
3422   
3423     if (!pTrustee) 
3424         return TRUSTEE_BAD_FORM; 
3425   
3426     return pTrustee->TrusteeForm; 
3427 }  
3428   
3429 /****************************************************************************** 
3430  * GetTrusteeFormW [ADVAPI32.@] 
3431  */ 
3432 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee) 
3433 {  
3434     TRACE("(%p)\n", pTrustee); 
3435   
3436     if (!pTrustee) 
3437         return TRUSTEE_BAD_FORM; 
3438   
3439     return pTrustee->TrusteeForm; 
3440 }  
3441   
3442 /****************************************************************************** 
3443  * GetTrusteeNameA [ADVAPI32.@] 
3444  */ 
3445 LPSTR WINAPI GetTrusteeNameA(PTRUSTEEA pTrustee) 
3446 {  
3447     TRACE("(%p)\n", pTrustee); 
3448   
3449     if (!pTrustee) 
3450         return NULL; 
3451   
3452     return pTrustee->ptstrName; 
3453 }  
3454   
3455 /****************************************************************************** 
3456  * GetTrusteeNameW [ADVAPI32.@] 
3457  */ 
3458 LPWSTR WINAPI GetTrusteeNameW(PTRUSTEEW pTrustee) 
3459 {  
3460     TRACE("(%p)\n", pTrustee); 
3461   
3462     if (!pTrustee) 
3463         return NULL; 
3464   
3465     return pTrustee->ptstrName; 
3466 }  
3467   
3468 /****************************************************************************** 
3469  * GetTrusteeTypeA [ADVAPI32.@] 
3470  */ 
3471 TRUSTEE_TYPE WINAPI GetTrusteeTypeA(PTRUSTEEA pTrustee) 
3472 {  
3473     TRACE("(%p)\n", pTrustee); 
3474   
3475     if (!pTrustee) 
3476         return TRUSTEE_IS_UNKNOWN; 
3477   
3478     return pTrustee->TrusteeType; 
3479 }  
3480   
3481 /****************************************************************************** 
3482  * GetTrusteeTypeW [ADVAPI32.@] 
3483  */ 
3484 TRUSTEE_TYPE WINAPI GetTrusteeTypeW(PTRUSTEEW pTrustee) 
3485 {  
3486     TRACE("(%p)\n", pTrustee); 
3487   
3488     if (!pTrustee) 
3489         return TRUSTEE_IS_UNKNOWN; 
3490   
3491     return pTrustee->TrusteeType; 
3492
3493  
3494 BOOL WINAPI SetAclInformation( PACL pAcl, LPVOID pAclInformation,
3495                                DWORD nAclInformationLength,
3496                                ACL_INFORMATION_CLASS dwAclInformationClass )
3497 {
3498     FIXME("%p %p 0x%08x 0x%08x - stub\n", pAcl, pAclInformation,
3499           nAclInformationLength, dwAclInformationClass);
3500
3501     return TRUE;
3502 }
3503
3504 /******************************************************************************
3505  * SetEntriesInAclA [ADVAPI32.@]
3506  */
3507 DWORD WINAPI SetEntriesInAclA( ULONG count, PEXPLICIT_ACCESSA pEntries,
3508                                PACL OldAcl, PACL* NewAcl )
3509 {
3510     FIXME("%d %p %p %p\n",count,pEntries,OldAcl,NewAcl);
3511     if (NewAcl)
3512          *NewAcl = NULL;
3513     return ERROR_SUCCESS;
3514 }
3515
3516 /******************************************************************************
3517  * SetEntriesInAclW [ADVAPI32.@]
3518  */
3519 DWORD WINAPI SetEntriesInAclW( ULONG count, PEXPLICIT_ACCESSW pEntries,
3520                                PACL OldAcl, PACL* NewAcl )
3521 {
3522     ULONG i;
3523     PSID *ppsid;
3524     DWORD ret = ERROR_SUCCESS;
3525     DWORD acl_size = sizeof(ACL);
3526     NTSTATUS status;
3527
3528     TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
3529
3530     *NewAcl = NULL;
3531
3532     if (!count && !OldAcl)
3533         return ERROR_SUCCESS;
3534
3535     /* allocate array of maximum sized sids allowed */
3536     ppsid = HeapAlloc(GetProcessHeap(), 0, count * (sizeof(SID *) + FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES])));
3537     if (!ppsid)
3538         return ERROR_OUTOFMEMORY;
3539
3540     for (i = 0; i < count; i++)
3541     {
3542         ppsid[i] = (char *)&ppsid[count] + i * FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3543
3544         TRACE("[%d]:\n\tgrfAccessPermissions = 0x%x\n\tgrfAccessMode = %d\n\tgrfInheritance = 0x%x\n\t"
3545               "Trustee.pMultipleTrustee = %p\n\tMultipleTrusteeOperation = %d\n\tTrusteeForm = %d\n\t"
3546               "Trustee.TrusteeType = %d\n\tptstrName = %p\n", i,
3547               pEntries[i].grfAccessPermissions, pEntries[i].grfAccessMode, pEntries[i].grfInheritance,
3548               pEntries[i].Trustee.pMultipleTrustee, pEntries[i].Trustee.MultipleTrusteeOperation,
3549               pEntries[i].Trustee.TrusteeForm, pEntries[i].Trustee.TrusteeType,
3550               pEntries[i].Trustee.ptstrName);
3551
3552         if (pEntries[i].Trustee.MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE)
3553         {
3554             WARN("bad multiple trustee operation %d for trustee %d\n", pEntries[i].Trustee.MultipleTrusteeOperation, i);
3555             ret = ERROR_INVALID_PARAMETER;
3556             goto exit;
3557         }
3558
3559         switch (pEntries[i].Trustee.TrusteeForm)
3560         {
3561         case TRUSTEE_IS_SID:
3562             if (!CopySid(FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]),
3563                          ppsid[i], pEntries[i].Trustee.ptstrName))
3564             {
3565                 WARN("bad sid %p for trustee %d\n", pEntries[i].Trustee.ptstrName, i);
3566                 ret = ERROR_INVALID_PARAMETER;
3567                 goto exit;
3568             }
3569             break;
3570         case TRUSTEE_IS_NAME:
3571         {
3572             DWORD sid_size = FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3573             DWORD domain_size = MAX_COMPUTERNAME_LENGTH + 1;
3574             SID_NAME_USE use;
3575             if (!strcmpW( pEntries[i].Trustee.ptstrName, CURRENT_USER ))
3576             {
3577                 if (!lookup_user_account_name( ppsid[i], &sid_size, NULL, &domain_size, &use ))
3578                 {
3579                     ret = GetLastError();
3580                     goto exit;
3581                 }
3582             }
3583             else if (!LookupAccountNameW(NULL, pEntries[i].Trustee.ptstrName, ppsid[i], &sid_size, NULL, &domain_size, &use))
3584             {
3585                 WARN("bad user name %s for trustee %d\n", debugstr_w(pEntries[i].Trustee.ptstrName), i);
3586                 ret = ERROR_INVALID_PARAMETER;
3587                 goto exit;
3588             }
3589             break;
3590         }
3591         case TRUSTEE_IS_OBJECTS_AND_SID:
3592             FIXME("TRUSTEE_IS_OBJECTS_AND_SID unimplemented\n");
3593             break;
3594         case TRUSTEE_IS_OBJECTS_AND_NAME:
3595             FIXME("TRUSTEE_IS_OBJECTS_AND_NAME unimplemented\n");
3596             break;
3597         default:
3598             WARN("bad trustee form %d for trustee %d\n", pEntries[i].Trustee.TrusteeForm, i);
3599             ret = ERROR_INVALID_PARAMETER;
3600             goto exit;
3601         }
3602
3603         /* Note: we overestimate the ACL size here as a tradeoff between
3604          * instructions (simplicity) and memory */
3605         switch (pEntries[i].grfAccessMode)
3606         {
3607         case GRANT_ACCESS:
3608         case SET_ACCESS:
3609             acl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3610             break;
3611         case DENY_ACCESS:
3612             acl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3613             break;
3614         case SET_AUDIT_SUCCESS:
3615         case SET_AUDIT_FAILURE:
3616             acl_size += FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart) + GetLengthSid(ppsid[i]);
3617             break;
3618         case REVOKE_ACCESS:
3619             break;
3620         default:
3621             WARN("bad access mode %d for trustee %d\n", pEntries[i].grfAccessMode, i);
3622             ret = ERROR_INVALID_PARAMETER;
3623             goto exit;
3624         }
3625     }
3626
3627     if (OldAcl)
3628     {
3629         ACL_SIZE_INFORMATION size_info;
3630
3631         status = RtlQueryInformationAcl(OldAcl, &size_info, sizeof(size_info), AclSizeInformation);
3632         if (status != STATUS_SUCCESS)
3633         {
3634             ret = RtlNtStatusToDosError(status);
3635             goto exit;
3636         }
3637         acl_size += size_info.AclBytesInUse - sizeof(ACL);
3638     }
3639
3640     *NewAcl = LocalAlloc(0, acl_size);
3641     if (!*NewAcl)
3642     {
3643         ret = ERROR_OUTOFMEMORY;
3644         goto exit;
3645     }
3646
3647     status = RtlCreateAcl( *NewAcl, acl_size, ACL_REVISION );
3648     if (status != STATUS_SUCCESS)
3649     {
3650         ret = RtlNtStatusToDosError(status);
3651         goto exit;
3652     }
3653
3654     for (i = 0; i < count; i++)
3655     {
3656         switch (pEntries[i].grfAccessMode)
3657         {
3658         case GRANT_ACCESS:
3659             status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3660                                               pEntries[i].grfInheritance,
3661                                               pEntries[i].grfAccessPermissions,
3662                                               ppsid[i]);
3663             break;
3664         case SET_ACCESS:
3665         {
3666             ULONG j;
3667             BOOL add = TRUE;
3668             if (OldAcl)
3669             {
3670                 for (j = 0; ; j++)
3671                 {
3672                     const ACE_HEADER *existing_ace_header;
3673                     status = RtlGetAce(OldAcl, j, (LPVOID *)&existing_ace_header);
3674                     if (status != STATUS_SUCCESS)
3675                         break;
3676                     if (pEntries[i].grfAccessMode == SET_ACCESS &&
3677                         existing_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3678                         EqualSid(ppsid[i], &((ACCESS_ALLOWED_ACE *)existing_ace_header)->SidStart))
3679                     {
3680                         add = FALSE;
3681                         break;
3682                     }
3683                 }
3684             }
3685             if (add)
3686                 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3687                                                   pEntries[i].grfInheritance,
3688                                                   pEntries[i].grfAccessPermissions,
3689                                                   ppsid[i]);
3690             break;
3691         }
3692         case DENY_ACCESS:
3693             status = RtlAddAccessDeniedAceEx(*NewAcl, ACL_REVISION,
3694                                              pEntries[i].grfInheritance,
3695                                              pEntries[i].grfAccessPermissions,
3696                                              ppsid[i]);
3697             break;
3698         case SET_AUDIT_SUCCESS:
3699             status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3700                                             pEntries[i].grfInheritance,
3701                                             pEntries[i].grfAccessPermissions,
3702                                             ppsid[i], TRUE, FALSE);
3703             break;
3704         case SET_AUDIT_FAILURE:
3705             status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3706                                             pEntries[i].grfInheritance,
3707                                             pEntries[i].grfAccessPermissions,
3708                                             ppsid[i], FALSE, TRUE);
3709             break;
3710         default:
3711             FIXME("unhandled access mode %d\n", pEntries[i].grfAccessMode);
3712         }
3713     }
3714
3715     if (OldAcl)
3716     {
3717         for (i = 0; ; i++)
3718         {
3719             BOOL add = TRUE;
3720             ULONG j;
3721             const ACE_HEADER *old_ace_header;
3722             status = RtlGetAce(OldAcl, i, (LPVOID *)&old_ace_header);
3723             if (status != STATUS_SUCCESS) break;
3724             for (j = 0; j < count; j++)
3725             {
3726                 if (pEntries[j].grfAccessMode == SET_ACCESS &&
3727                     old_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3728                     EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3729                 {
3730                     status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION, pEntries[j].grfInheritance, pEntries[j].grfAccessPermissions, ppsid[j]);
3731                     add = FALSE;
3732                     break;
3733                 }
3734                 else if (pEntries[j].grfAccessMode == REVOKE_ACCESS)
3735                 {
3736                     switch (old_ace_header->AceType)
3737                     {
3738                     case ACCESS_ALLOWED_ACE_TYPE:
3739                         if (EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3740                             add = FALSE;
3741                         break;
3742                     case ACCESS_DENIED_ACE_TYPE:
3743                         if (EqualSid(ppsid[j], &((ACCESS_DENIED_ACE *)old_ace_header)->SidStart))
3744                             add = FALSE;
3745                         break;
3746                     case SYSTEM_AUDIT_ACE_TYPE:
3747                         if (EqualSid(ppsid[j], &((SYSTEM_AUDIT_ACE *)old_ace_header)->SidStart))
3748                             add = FALSE;
3749                         break;
3750                     case SYSTEM_ALARM_ACE_TYPE:
3751                         if (EqualSid(ppsid[j], &((SYSTEM_ALARM_ACE *)old_ace_header)->SidStart))
3752                             add = FALSE;
3753                         break;
3754                     default:
3755                         FIXME("unhandled ace type %d\n", old_ace_header->AceType);
3756                     }
3757
3758                     if (!add)
3759                         break;
3760                 }
3761             }
3762             if (add)
3763                 status = RtlAddAce(*NewAcl, ACL_REVISION, 1, (PACE_HEADER)old_ace_header, old_ace_header->AceSize);
3764             if (status != STATUS_SUCCESS)
3765             {
3766                 WARN("RtlAddAce failed with error 0x%08x\n", status);
3767                 ret = RtlNtStatusToDosError(status);
3768                 break;
3769             }
3770         }
3771     }
3772
3773 exit:
3774     HeapFree(GetProcessHeap(), 0, ppsid);
3775     return ret;
3776 }
3777
3778 /******************************************************************************
3779  * SetNamedSecurityInfoA [ADVAPI32.@]
3780  */
3781 DWORD WINAPI SetNamedSecurityInfoA(LPSTR pObjectName,
3782         SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
3783         PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
3784 {
3785     DWORD len;
3786     LPWSTR wstr = NULL;
3787     DWORD r;
3788
3789     TRACE("%s %d %d %p %p %p %p\n", debugstr_a(pObjectName), ObjectType,
3790            SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
3791
3792     if( pObjectName )
3793     {
3794         len = MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, NULL, 0 );
3795         wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR));
3796         MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, wstr, len );
3797     }
3798
3799     r = SetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, psidOwner,
3800                            psidGroup, pDacl, pSacl );
3801
3802     HeapFree( GetProcessHeap(), 0, wstr );
3803
3804     return r;
3805 }
3806
3807 BOOL WINAPI SetPrivateObjectSecurity( SECURITY_INFORMATION SecurityInformation,
3808     PSECURITY_DESCRIPTOR ModificationDescriptor,
3809     PSECURITY_DESCRIPTOR* ObjectsSecurityDescriptor,
3810     PGENERIC_MAPPING GenericMapping,
3811     HANDLE Token )
3812 {
3813     FIXME("0x%08x %p %p %p %p - stub\n", SecurityInformation, ModificationDescriptor,
3814           ObjectsSecurityDescriptor, GenericMapping, Token);
3815
3816     return TRUE;
3817 }
3818
3819 BOOL WINAPI AreAllAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
3820 {
3821     return RtlAreAllAccessesGranted( GrantedAccess, DesiredAccess );
3822 }
3823
3824 /******************************************************************************
3825  * AreAnyAccessesGranted [ADVAPI32.@]
3826  *
3827  * Determines whether or not any of a set of specified access permissions have
3828  * been granted or not.
3829  *
3830  * PARAMS
3831  *   GrantedAccess [I] The permissions that have been granted.
3832  *   DesiredAccess [I] The permissions that you want to have.
3833  *
3834  * RETURNS
3835  *   Nonzero if any of the permissions have been granted, zero if none of the
3836  *   permissions have been granted.
3837  */
3838
3839 BOOL WINAPI AreAnyAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
3840 {
3841     return RtlAreAnyAccessesGranted( GrantedAccess, DesiredAccess );
3842 }
3843
3844 /******************************************************************************
3845  * SetNamedSecurityInfoW [ADVAPI32.@]
3846  */
3847 DWORD WINAPI SetNamedSecurityInfoW(LPWSTR pObjectName,
3848         SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
3849         PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
3850 {
3851     FIXME("%s %d %d %p %p %p %p\n", debugstr_w(pObjectName), ObjectType,
3852            SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
3853     return ERROR_SUCCESS;
3854 }
3855
3856 /******************************************************************************
3857  * GetExplicitEntriesFromAclA [ADVAPI32.@]
3858  */
3859 DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntries,
3860         PEXPLICIT_ACCESSA* pListOfExplicitEntries)
3861 {
3862     FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
3863     return ERROR_CALL_NOT_IMPLEMENTED;
3864 }
3865
3866 /******************************************************************************
3867  * GetExplicitEntriesFromAclW [ADVAPI32.@]
3868  */
3869 DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG pcCountOfExplicitEntries,
3870         PEXPLICIT_ACCESSW* pListOfExplicitEntries)
3871 {
3872     FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
3873     return ERROR_CALL_NOT_IMPLEMENTED;
3874 }
3875
3876 /******************************************************************************
3877  * GetAuditedPermissionsFromAclA [ADVAPI32.@]
3878  */
3879 DWORD WINAPI GetAuditedPermissionsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
3880         PACCESS_MASK pFailedAuditRights)
3881 {
3882     FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
3883     return ERROR_CALL_NOT_IMPLEMENTED;
3884
3885 }
3886
3887 /******************************************************************************
3888  * GetAuditedPermissionsFromAclW [ADVAPI32.@]
3889  */
3890 DWORD WINAPI GetAuditedPermissionsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
3891         PACCESS_MASK pFailedAuditRights)
3892 {
3893     FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
3894     return ERROR_CALL_NOT_IMPLEMENTED;
3895
3896 }
3897
3898 /******************************************************************************
3899  * ParseAclStringFlags
3900  */
3901 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
3902 {
3903     DWORD flags = 0;
3904     LPCWSTR szAcl = *StringAcl;
3905
3906     while (*szAcl != '(')
3907     {
3908         if (*szAcl == 'P')
3909         {
3910             flags |= SE_DACL_PROTECTED;
3911         }
3912         else if (*szAcl == 'A')
3913         {
3914             szAcl++;
3915             if (*szAcl == 'R')
3916                 flags |= SE_DACL_AUTO_INHERIT_REQ;
3917             else if (*szAcl == 'I')
3918                 flags |= SE_DACL_AUTO_INHERITED;
3919         }
3920         szAcl++;
3921     }
3922
3923     *StringAcl = szAcl;
3924     return flags;
3925 }
3926
3927 /******************************************************************************
3928  * ParseAceStringType
3929  */
3930 static const ACEFLAG AceType[] =
3931 {
3932     { SDDL_ALARM,          SYSTEM_ALARM_ACE_TYPE },
3933     { SDDL_AUDIT,          SYSTEM_AUDIT_ACE_TYPE },
3934     { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
3935     { SDDL_ACCESS_DENIED,  ACCESS_DENIED_ACE_TYPE },
3936     /*
3937     { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
3938     { SDDL_OBJECT_ACCESS_DENIED,  ACCESS_DENIED_OBJECT_ACE_TYPE },
3939     { SDDL_OBJECT_ALARM,          SYSTEM_ALARM_OBJECT_ACE_TYPE },
3940     { SDDL_OBJECT_AUDIT,          SYSTEM_AUDIT_OBJECT_ACE_TYPE },
3941     */
3942     { NULL, 0 },
3943 };
3944
3945 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
3946 {
3947     UINT len = 0;
3948     LPCWSTR szAcl = *StringAcl;
3949     const ACEFLAG *lpaf = AceType;
3950
3951     while (*szAcl == ' ')
3952         szAcl++;
3953
3954     while (lpaf->wstr &&
3955         (len = strlenW(lpaf->wstr)) &&
3956         strncmpW(lpaf->wstr, szAcl, len))
3957         lpaf++;
3958
3959     if (!lpaf->wstr)
3960         return 0;
3961
3962     *StringAcl = szAcl + len;
3963     return lpaf->value;
3964 }
3965
3966
3967 /******************************************************************************
3968  * ParseAceStringFlags
3969  */
3970 static const ACEFLAG AceFlags[] =
3971 {
3972     { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
3973     { SDDL_AUDIT_FAILURE,     FAILED_ACCESS_ACE_FLAG },
3974     { SDDL_INHERITED,         INHERITED_ACE },
3975     { SDDL_INHERIT_ONLY,      INHERIT_ONLY_ACE },
3976     { SDDL_NO_PROPAGATE,      NO_PROPAGATE_INHERIT_ACE },
3977     { SDDL_OBJECT_INHERIT,    OBJECT_INHERIT_ACE },
3978     { SDDL_AUDIT_SUCCESS,     SUCCESSFUL_ACCESS_ACE_FLAG },
3979     { NULL, 0 },
3980 };
3981
3982 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
3983 {
3984     UINT len = 0;
3985     BYTE flags = 0;
3986     LPCWSTR szAcl = *StringAcl;
3987
3988     while (*szAcl == ' ')
3989         szAcl++;
3990
3991     while (*szAcl != ';')
3992     {
3993         const ACEFLAG *lpaf = AceFlags;
3994
3995         while (lpaf->wstr &&
3996                (len = strlenW(lpaf->wstr)) &&
3997                strncmpW(lpaf->wstr, szAcl, len))
3998             lpaf++;
3999
4000         if (!lpaf->wstr)
4001             return 0;
4002
4003         flags |= lpaf->value;
4004         szAcl += len;
4005     }
4006
4007     *StringAcl = szAcl;
4008     return flags;
4009 }
4010
4011
4012 /******************************************************************************
4013  * ParseAceStringRights
4014  */
4015 static const ACEFLAG AceRights[] =
4016 {
4017     { SDDL_GENERIC_ALL,     GENERIC_ALL },
4018     { SDDL_GENERIC_READ,    GENERIC_READ },
4019     { SDDL_GENERIC_WRITE,   GENERIC_WRITE },
4020     { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
4021
4022     { SDDL_READ_CONTROL,    READ_CONTROL },
4023     { SDDL_STANDARD_DELETE, DELETE },
4024     { SDDL_WRITE_DAC,       WRITE_DAC },
4025     { SDDL_WRITE_OWNER,     WRITE_OWNER },
4026
4027     { SDDL_READ_PROPERTY,   ADS_RIGHT_DS_READ_PROP},
4028     { SDDL_WRITE_PROPERTY,  ADS_RIGHT_DS_WRITE_PROP},
4029     { SDDL_CREATE_CHILD,    ADS_RIGHT_DS_CREATE_CHILD},
4030     { SDDL_DELETE_CHILD,    ADS_RIGHT_DS_DELETE_CHILD},
4031     { SDDL_LIST_CHILDREN,   ADS_RIGHT_ACTRL_DS_LIST},
4032     { SDDL_SELF_WRITE,      ADS_RIGHT_DS_SELF},
4033     { SDDL_LIST_OBJECT,     ADS_RIGHT_DS_LIST_OBJECT},
4034     { SDDL_DELETE_TREE,     ADS_RIGHT_DS_DELETE_TREE},
4035     { SDDL_CONTROL_ACCESS,  ADS_RIGHT_DS_CONTROL_ACCESS},
4036
4037     { SDDL_FILE_ALL,        FILE_ALL_ACCESS },
4038     { SDDL_FILE_READ,       FILE_GENERIC_READ },
4039     { SDDL_FILE_WRITE,      FILE_GENERIC_WRITE },
4040     { SDDL_FILE_EXECUTE,    FILE_GENERIC_EXECUTE },
4041
4042     { SDDL_KEY_ALL,         KEY_ALL_ACCESS },
4043     { SDDL_KEY_READ,        KEY_READ },
4044     { SDDL_KEY_WRITE,       KEY_WRITE },
4045     { SDDL_KEY_EXECUTE,     KEY_EXECUTE },
4046     { NULL, 0 },
4047 };
4048
4049 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
4050 {
4051     UINT len = 0;
4052     DWORD rights = 0;
4053     LPCWSTR szAcl = *StringAcl;
4054
4055     while (*szAcl == ' ')
4056         szAcl++;
4057
4058     if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
4059     {
4060         LPCWSTR p = szAcl;
4061
4062         while (*p && *p != ';')
4063             p++;
4064
4065         if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
4066         {
4067             rights = strtoulW(szAcl, NULL, 16);
4068             szAcl = p;
4069         }
4070         else
4071             WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
4072     }
4073     else
4074     {
4075         while (*szAcl != ';')
4076         {
4077             const ACEFLAG *lpaf = AceRights;
4078
4079             while (lpaf->wstr &&
4080                (len = strlenW(lpaf->wstr)) &&
4081                strncmpW(lpaf->wstr, szAcl, len))
4082             {
4083                lpaf++;
4084             }
4085
4086             if (!lpaf->wstr)
4087                 return 0;
4088
4089             rights |= lpaf->value;
4090             szAcl += len;
4091         }
4092     }
4093
4094     *StringAcl = szAcl;
4095     return rights;
4096 }
4097
4098
4099 /******************************************************************************
4100  * ParseStringAclToAcl
4101  * 
4102  * dacl_flags(string_ace1)(string_ace2)... (string_acen) 
4103  */
4104 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags, 
4105     PACL pAcl, LPDWORD cBytes)
4106 {
4107     DWORD val;
4108     DWORD sidlen;
4109     DWORD length = sizeof(ACL);
4110     DWORD acesize = 0;
4111     DWORD acecount = 0;
4112     PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
4113     DWORD error = ERROR_INVALID_ACL;
4114
4115     TRACE("%s\n", debugstr_w(StringAcl));
4116
4117     if (!StringAcl)
4118         return FALSE;
4119
4120     if (pAcl) /* pAce is only useful if we're setting values */
4121         pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
4122
4123     /* Parse ACL flags */
4124     *lpdwFlags = ParseAclStringFlags(&StringAcl);
4125
4126     /* Parse ACE */
4127     while (*StringAcl == '(')
4128     {
4129         StringAcl++;
4130
4131         /* Parse ACE type */
4132         val = ParseAceStringType(&StringAcl);
4133         if (pAce)
4134             pAce->Header.AceType = (BYTE) val;
4135         if (*StringAcl != ';')
4136         {
4137             error = RPC_S_INVALID_STRING_UUID;
4138             goto lerr;
4139         }
4140         StringAcl++;
4141
4142         /* Parse ACE flags */
4143         val = ParseAceStringFlags(&StringAcl);
4144         if (pAce)
4145             pAce->Header.AceFlags = (BYTE) val;
4146         if (*StringAcl != ';')
4147             goto lerr;
4148         StringAcl++;
4149
4150         /* Parse ACE rights */
4151         val = ParseAceStringRights(&StringAcl);
4152         if (pAce)
4153             pAce->Mask = val;
4154         if (*StringAcl != ';')
4155             goto lerr;
4156         StringAcl++;
4157
4158         /* Parse ACE object guid */
4159         while (*StringAcl == ' ')
4160             StringAcl++;
4161         if (*StringAcl != ';')
4162         {
4163             FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4164             goto lerr;
4165         }
4166         StringAcl++;
4167
4168         /* Parse ACE inherit object guid */
4169         while (*StringAcl == ' ')
4170             StringAcl++;
4171         if (*StringAcl != ';')
4172         {
4173             FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4174             goto lerr;
4175         }
4176         StringAcl++;
4177
4178         /* Parse ACE account sid */
4179         if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
4180         {
4181             while (*StringAcl && *StringAcl != ')')
4182                 StringAcl++;
4183         }
4184
4185         if (*StringAcl != ')')
4186             goto lerr;
4187         StringAcl++;
4188
4189         acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
4190         length += acesize;
4191         if (pAce)
4192         {
4193             pAce->Header.AceSize = acesize;
4194             pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
4195         }
4196         acecount++;
4197     }
4198
4199     *cBytes = length;
4200
4201     if (length > 0xffff)
4202     {
4203         ERR("ACL too large\n");
4204         goto lerr;
4205     }
4206
4207     if (pAcl)
4208     {
4209         pAcl->AclRevision = ACL_REVISION;
4210         pAcl->Sbz1 = 0;
4211         pAcl->AclSize = length;
4212         pAcl->AceCount = acecount++;
4213         pAcl->Sbz2 = 0;
4214     }
4215     return TRUE;
4216
4217 lerr:
4218     SetLastError(error);
4219     WARN("Invalid ACE string format\n");
4220     return FALSE;
4221 }
4222
4223
4224 /******************************************************************************
4225  * ParseStringSecurityDescriptorToSecurityDescriptor
4226  */
4227 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
4228     LPCWSTR StringSecurityDescriptor,
4229     SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
4230     LPDWORD cBytes)
4231 {
4232     BOOL bret = FALSE;
4233     WCHAR toktype;
4234     WCHAR tok[MAX_PATH];
4235     LPCWSTR lptoken;
4236     LPBYTE lpNext = NULL;
4237     DWORD len;
4238
4239     *cBytes = sizeof(SECURITY_DESCRIPTOR);
4240
4241     if (SecurityDescriptor)
4242         lpNext = (LPBYTE)(SecurityDescriptor + 1);
4243
4244     while (*StringSecurityDescriptor == ' ')
4245         StringSecurityDescriptor++;
4246
4247     while (*StringSecurityDescriptor)
4248     {
4249         toktype = *StringSecurityDescriptor;
4250
4251         /* Expect char identifier followed by ':' */
4252         StringSecurityDescriptor++;
4253         if (*StringSecurityDescriptor != ':')
4254         {
4255             SetLastError(ERROR_INVALID_PARAMETER);
4256             goto lend;
4257         }
4258         StringSecurityDescriptor++;
4259
4260         /* Extract token */
4261         lptoken = StringSecurityDescriptor;
4262         while (*lptoken && *lptoken != ':')
4263             lptoken++;
4264
4265         if (*lptoken)
4266             lptoken--;
4267
4268         len = lptoken - StringSecurityDescriptor;
4269         memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
4270         tok[len] = 0;
4271
4272         switch (toktype)
4273         {
4274             case 'O':
4275             {
4276                 DWORD bytes;
4277
4278                 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4279                     goto lend;
4280
4281                 if (SecurityDescriptor)
4282                 {
4283                     SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
4284                     lpNext += bytes; /* Advance to next token */
4285                 }
4286
4287                 *cBytes += bytes;
4288
4289                 break;
4290             }
4291
4292             case 'G':
4293             {
4294                 DWORD bytes;
4295
4296                 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4297                     goto lend;
4298
4299                 if (SecurityDescriptor)
4300                 {
4301                     SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
4302                     lpNext += bytes; /* Advance to next token */
4303                 }
4304
4305                 *cBytes += bytes;
4306
4307                 break;
4308             }
4309
4310             case 'D':
4311             {
4312                 DWORD flags;
4313                 DWORD bytes;
4314
4315                 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4316                     goto lend;
4317
4318                 if (SecurityDescriptor)
4319                 {
4320                     SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
4321                     SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
4322                     lpNext += bytes; /* Advance to next token */
4323                 }
4324
4325                 *cBytes += bytes;
4326
4327                 break;
4328             }
4329
4330             case 'S':
4331             {
4332                 DWORD flags;
4333                 DWORD bytes;
4334
4335                 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4336                     goto lend;
4337
4338                 if (SecurityDescriptor)
4339                 {
4340                     SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
4341                     SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
4342                     lpNext += bytes; /* Advance to next token */
4343                 }
4344
4345                 *cBytes += bytes;
4346
4347                 break;
4348             }
4349
4350             default:
4351                 FIXME("Unknown token\n");
4352                 SetLastError(ERROR_INVALID_PARAMETER);
4353                 goto lend;
4354         }
4355
4356         StringSecurityDescriptor = lptoken;
4357     }
4358
4359     bret = TRUE;
4360
4361 lend:
4362     return bret;
4363 }
4364
4365 /******************************************************************************
4366  * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
4367  */
4368 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
4369         LPCSTR StringSecurityDescriptor,
4370         DWORD StringSDRevision,
4371         PSECURITY_DESCRIPTOR* SecurityDescriptor,
4372         PULONG SecurityDescriptorSize)
4373 {
4374     UINT len;
4375     BOOL ret = FALSE;
4376     LPWSTR StringSecurityDescriptorW;
4377
4378     len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
4379     StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
4380
4381     if (StringSecurityDescriptorW)
4382     {
4383         MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
4384
4385         ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
4386                                                                    StringSDRevision, SecurityDescriptor,
4387                                                                    SecurityDescriptorSize);
4388         HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
4389     }
4390
4391     return ret;
4392 }
4393
4394 /******************************************************************************
4395  * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
4396  */
4397 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
4398         LPCWSTR StringSecurityDescriptor,
4399         DWORD StringSDRevision,
4400         PSECURITY_DESCRIPTOR* SecurityDescriptor,
4401         PULONG SecurityDescriptorSize)
4402 {
4403     DWORD cBytes;
4404     SECURITY_DESCRIPTOR* psd;
4405     BOOL bret = FALSE;
4406
4407     TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
4408
4409     if (GetVersion() & 0x80000000)
4410     {
4411         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4412         goto lend;
4413     }
4414     else if (!StringSecurityDescriptor || !SecurityDescriptor)
4415     {
4416         SetLastError(ERROR_INVALID_PARAMETER);
4417         goto lend;
4418     }
4419     else if (StringSDRevision != SID_REVISION)
4420     {
4421         SetLastError(ERROR_UNKNOWN_REVISION);
4422         goto lend;
4423     }
4424
4425     /* Compute security descriptor length */
4426     if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4427         NULL, &cBytes))
4428         goto lend;
4429
4430     psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
4431     if (!psd) goto lend;
4432
4433     psd->Revision = SID_REVISION;
4434     psd->Control |= SE_SELF_RELATIVE;
4435
4436     if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4437              (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
4438     {
4439         LocalFree(psd);
4440         goto lend;
4441     }
4442
4443     if (SecurityDescriptorSize)
4444         *SecurityDescriptorSize = cBytes;
4445
4446     bret = TRUE;
4447  
4448 lend:
4449     TRACE(" ret=%d\n", bret);
4450     return bret;
4451 }
4452
4453 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
4454 {
4455     if (cch == -1)
4456         cch = strlenW(string);
4457
4458     if (plen)
4459         *plen += cch;
4460
4461     if (pwptr)
4462     {
4463         memcpy(*pwptr, string, sizeof(WCHAR)*cch);
4464         *pwptr += cch;
4465     }
4466 }
4467
4468 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
4469 {
4470     DWORD i;
4471     WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
4472     WCHAR subauthfmt[] = { '-','%','u',0 };
4473     WCHAR buf[26];
4474     SID *pisid = psid;
4475
4476     if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
4477     {
4478         SetLastError(ERROR_INVALID_SID);
4479         return FALSE;
4480     }
4481
4482     if (pisid->IdentifierAuthority.Value[0] ||
4483      pisid->IdentifierAuthority.Value[1])
4484     {
4485         FIXME("not matching MS' bugs\n");
4486         SetLastError(ERROR_INVALID_SID);
4487         return FALSE;
4488     }
4489
4490     sprintfW( buf, fmt, pisid->Revision,
4491         MAKELONG(
4492             MAKEWORD( pisid->IdentifierAuthority.Value[5],
4493                     pisid->IdentifierAuthority.Value[4] ),
4494             MAKEWORD( pisid->IdentifierAuthority.Value[3],
4495                     pisid->IdentifierAuthority.Value[2] )
4496         ) );
4497     DumpString(buf, -1, pwptr, plen);
4498
4499     for( i=0; i<pisid->SubAuthorityCount; i++ )
4500     {
4501         sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
4502         DumpString(buf, -1, pwptr, plen);
4503     }
4504     return TRUE;
4505 }
4506
4507 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
4508 {
4509     size_t i;
4510     for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
4511     {
4512         if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
4513         {
4514             DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
4515             return TRUE;
4516         }
4517     }
4518
4519     return DumpSidNumeric(psid, pwptr, plen);
4520 }
4521
4522 static const LPCWSTR AceRightBitNames[32] = {
4523         SDDL_CREATE_CHILD,        /*  0 */
4524         SDDL_DELETE_CHILD,
4525         SDDL_LIST_CHILDREN,
4526         SDDL_SELF_WRITE,
4527         SDDL_READ_PROPERTY,       /*  4 */
4528         SDDL_WRITE_PROPERTY,
4529         SDDL_DELETE_TREE,
4530         SDDL_LIST_OBJECT,
4531         SDDL_CONTROL_ACCESS,      /*  8 */
4532         NULL,
4533         NULL,
4534         NULL,
4535         NULL,                     /* 12 */
4536         NULL,
4537         NULL,
4538         NULL,
4539         SDDL_STANDARD_DELETE,     /* 16 */
4540         SDDL_READ_CONTROL,
4541         SDDL_WRITE_DAC,
4542         SDDL_WRITE_OWNER,
4543         NULL,                     /* 20 */
4544         NULL,
4545         NULL,
4546         NULL,
4547         NULL,                     /* 24 */
4548         NULL,
4549         NULL,
4550         NULL,
4551         SDDL_GENERIC_ALL,         /* 28 */
4552         SDDL_GENERIC_EXECUTE,
4553         SDDL_GENERIC_WRITE,
4554         SDDL_GENERIC_READ
4555 };
4556
4557 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
4558 {
4559     static const WCHAR fmtW[] = {'0','x','%','x',0};
4560     WCHAR buf[15];
4561     size_t i;
4562
4563     if (mask == 0)
4564         return;
4565
4566     /* first check if the right have name */
4567     for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
4568     {
4569         if (AceRights[i].wstr == NULL)
4570             break;
4571         if (mask == AceRights[i].value)
4572         {
4573             DumpString(AceRights[i].wstr, -1, pwptr, plen);
4574             return;
4575         }
4576     }
4577
4578     /* then check if it can be built from bit names */
4579     for (i = 0; i < 32; i++)
4580     {
4581         if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
4582         {
4583             /* can't be built from bit names */
4584             sprintfW(buf, fmtW, mask);
4585             DumpString(buf, -1, pwptr, plen);
4586             return;
4587         }
4588     }
4589
4590     /* build from bit names */
4591     for (i = 0; i < 32; i++)
4592         if (mask & (1 << i))
4593             DumpString(AceRightBitNames[i], -1, pwptr, plen);
4594 }
4595
4596 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
4597 {
4598     ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
4599     static const WCHAR openbr = '(';
4600     static const WCHAR closebr = ')';
4601     static const WCHAR semicolon = ';';
4602
4603     if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
4604     {
4605         SetLastError(ERROR_INVALID_ACL);
4606         return FALSE;
4607     }
4608
4609     piace = pace;
4610     DumpString(&openbr, 1, pwptr, plen);
4611     switch (piace->Header.AceType)
4612     {
4613         case ACCESS_ALLOWED_ACE_TYPE:
4614             DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
4615             break;
4616         case ACCESS_DENIED_ACE_TYPE:
4617             DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
4618             break;
4619         case SYSTEM_AUDIT_ACE_TYPE:
4620             DumpString(SDDL_AUDIT, -1, pwptr, plen);
4621             break;
4622         case SYSTEM_ALARM_ACE_TYPE:
4623             DumpString(SDDL_ALARM, -1, pwptr, plen);
4624             break;
4625     }
4626     DumpString(&semicolon, 1, pwptr, plen);
4627
4628     if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
4629         DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
4630     if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
4631         DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
4632     if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
4633         DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
4634     if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
4635         DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
4636     if (piace->Header.AceFlags & INHERITED_ACE)
4637         DumpString(SDDL_INHERITED, -1, pwptr, plen);
4638     if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
4639         DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
4640     if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
4641         DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
4642     DumpString(&semicolon, 1, pwptr, plen);
4643     DumpRights(piace->Mask, pwptr, plen);
4644     DumpString(&semicolon, 1, pwptr, plen);
4645     /* objects not supported */
4646     DumpString(&semicolon, 1, pwptr, plen);
4647     /* objects not supported */
4648     DumpString(&semicolon, 1, pwptr, plen);
4649     if (!DumpSid(&piace->SidStart, pwptr, plen))
4650         return FALSE;
4651     DumpString(&closebr, 1, pwptr, plen);
4652     return TRUE;
4653 }
4654
4655 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
4656 {
4657     WORD count;
4658     int i;
4659
4660     if (protected)
4661         DumpString(SDDL_PROTECTED, -1, pwptr, plen);
4662     if (autoInheritReq)
4663         DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
4664     if (autoInherited)
4665         DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
4666
4667     if (pacl == NULL)
4668         return TRUE;
4669
4670     if (!IsValidAcl(pacl))
4671         return FALSE;
4672
4673     count = pacl->AceCount;
4674     for (i = 0; i < count; i++)
4675     {
4676         LPVOID ace;
4677         if (!GetAce(pacl, i, &ace))
4678             return FALSE;
4679         if (!DumpAce(ace, pwptr, plen))
4680             return FALSE;
4681     }
4682
4683     return TRUE;
4684 }
4685
4686 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4687 {
4688     static const WCHAR prefix[] = {'O',':',0};
4689     BOOL bDefaulted;
4690     PSID psid;
4691
4692     if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
4693         return FALSE;
4694
4695     if (psid == NULL)
4696         return TRUE;
4697
4698     DumpString(prefix, -1, pwptr, plen);
4699     if (!DumpSid(psid, pwptr, plen))
4700         return FALSE;
4701     return TRUE;
4702 }
4703
4704 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4705 {
4706     static const WCHAR prefix[] = {'G',':',0};
4707     BOOL bDefaulted;
4708     PSID psid;
4709
4710     if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
4711         return FALSE;
4712
4713     if (psid == NULL)
4714         return TRUE;
4715
4716     DumpString(prefix, -1, pwptr, plen);
4717     if (!DumpSid(psid, pwptr, plen))
4718         return FALSE;
4719     return TRUE;
4720 }
4721
4722 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4723 {
4724     static const WCHAR dacl[] = {'D',':',0};
4725     SECURITY_DESCRIPTOR_CONTROL control;
4726     BOOL present, defaulted;
4727     DWORD revision;
4728     PACL pacl;
4729
4730     if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
4731         return FALSE;
4732
4733     if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
4734         return FALSE;
4735
4736     if (!present)
4737         return TRUE;
4738
4739     DumpString(dacl, 2, pwptr, plen);
4740     if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
4741         return FALSE;
4742     return TRUE;
4743 }
4744
4745 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4746 {
4747     static const WCHAR sacl[] = {'S',':',0};
4748     SECURITY_DESCRIPTOR_CONTROL control;
4749     BOOL present, defaulted;
4750     DWORD revision;
4751     PACL pacl;
4752
4753     if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
4754         return FALSE;
4755
4756     if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
4757         return FALSE;
4758
4759     if (!present)
4760         return TRUE;
4761
4762     DumpString(sacl, 2, pwptr, plen);
4763     if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
4764         return FALSE;
4765     return TRUE;
4766 }
4767
4768 /******************************************************************************
4769  * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
4770  */
4771 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen)
4772 {
4773     ULONG len;
4774     WCHAR *wptr, *wstr;
4775
4776     if (SDRevision != SDDL_REVISION_1)
4777     {
4778         ERR("Pogram requested unknown SDDL revision %d\n", SDRevision);
4779         SetLastError(ERROR_UNKNOWN_REVISION);
4780         return FALSE;
4781     }
4782
4783     len = 0;
4784     if (RequestedInformation & OWNER_SECURITY_INFORMATION)
4785         if (!DumpOwner(SecurityDescriptor, NULL, &len))
4786             return FALSE;
4787     if (RequestedInformation & GROUP_SECURITY_INFORMATION)
4788         if (!DumpGroup(SecurityDescriptor, NULL, &len))
4789             return FALSE;
4790     if (RequestedInformation & DACL_SECURITY_INFORMATION)
4791         if (!DumpDacl(SecurityDescriptor, NULL, &len))
4792             return FALSE;
4793     if (RequestedInformation & SACL_SECURITY_INFORMATION)
4794         if (!DumpSacl(SecurityDescriptor, NULL, &len))
4795             return FALSE;
4796
4797     wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
4798     if (RequestedInformation & OWNER_SECURITY_INFORMATION)
4799         if (!DumpOwner(SecurityDescriptor, &wptr, NULL))
4800             return FALSE;
4801     if (RequestedInformation & GROUP_SECURITY_INFORMATION)
4802         if (!DumpGroup(SecurityDescriptor, &wptr, NULL))
4803             return FALSE;
4804     if (RequestedInformation & DACL_SECURITY_INFORMATION)
4805         if (!DumpDacl(SecurityDescriptor, &wptr, NULL))
4806             return FALSE;
4807     if (RequestedInformation & SACL_SECURITY_INFORMATION)
4808         if (!DumpSacl(SecurityDescriptor, &wptr, NULL))
4809             return FALSE;
4810     *wptr = 0;
4811
4812     TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
4813     *OutputString = wstr;
4814     if (OutputLen)
4815         *OutputLen = strlenW(*OutputString)+1;
4816     return TRUE;
4817 }
4818
4819 /******************************************************************************
4820  * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
4821  */
4822 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen)
4823 {
4824     LPWSTR wstr;
4825     ULONG len;
4826     if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
4827     {
4828         int lenA;
4829
4830         lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
4831         *OutputString = HeapAlloc(GetProcessHeap(), 0, lenA);
4832         WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
4833         LocalFree(wstr);
4834
4835         if (OutputLen != NULL)
4836             *OutputLen = lenA;
4837         return TRUE;
4838     }
4839     else
4840     {
4841         *OutputString = NULL;
4842         if (OutputLen)
4843             *OutputLen = 0;
4844         return FALSE;
4845     }
4846 }
4847
4848 /******************************************************************************
4849  * ConvertStringSidToSidW [ADVAPI32.@]
4850  */
4851 BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid)
4852 {
4853     BOOL bret = FALSE;
4854     DWORD cBytes;
4855
4856     TRACE("%s, %p\n", debugstr_w(StringSid), Sid);
4857     if (GetVersion() & 0x80000000)
4858         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4859     else if (!StringSid || !Sid)
4860         SetLastError(ERROR_INVALID_PARAMETER);
4861     else if (ParseStringSidToSid(StringSid, NULL, &cBytes))
4862     {
4863         PSID pSid = *Sid = LocalAlloc(0, cBytes);
4864
4865         bret = ParseStringSidToSid(StringSid, pSid, &cBytes);
4866         if (!bret)
4867             LocalFree(*Sid); 
4868     }
4869     return bret;
4870 }
4871
4872 /******************************************************************************
4873  * ConvertStringSidToSidA [ADVAPI32.@]
4874  */
4875 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
4876 {
4877     BOOL bret = FALSE;
4878
4879     TRACE("%s, %p\n", debugstr_a(StringSid), Sid);
4880     if (GetVersion() & 0x80000000)
4881         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4882     else if (!StringSid || !Sid)
4883         SetLastError(ERROR_INVALID_PARAMETER);
4884     else
4885     {
4886         UINT len = MultiByteToWideChar(CP_ACP, 0, StringSid, -1, NULL, 0);
4887         LPWSTR wStringSid = HeapAlloc(GetProcessHeap(), 0,
4888          len * sizeof(WCHAR));
4889
4890         MultiByteToWideChar(CP_ACP, 0, StringSid, -1, wStringSid, len);
4891         bret = ConvertStringSidToSidW(wStringSid, Sid);
4892         HeapFree(GetProcessHeap(), 0, wStringSid);
4893     }
4894     return bret;
4895 }
4896
4897 /******************************************************************************
4898  * ConvertSidToStringSidW [ADVAPI32.@]
4899  *
4900  *  format of SID string is:
4901  *    S-<count>-<auth>-<subauth1>-<subauth2>-<subauth3>...
4902  *  where
4903  *    <rev> is the revision of the SID encoded as decimal
4904  *    <auth> is the identifier authority encoded as hex
4905  *    <subauthN> is the subauthority id encoded as decimal
4906  */
4907 BOOL WINAPI ConvertSidToStringSidW( PSID pSid, LPWSTR *pstr )
4908 {
4909     DWORD len = 0;
4910     LPWSTR wstr, wptr;
4911
4912     TRACE("%p %p\n", pSid, pstr );
4913
4914     len = 0;
4915     if (!DumpSidNumeric(pSid, NULL, &len))
4916         return FALSE;
4917     wstr = wptr = LocalAlloc(0, (len+1) * sizeof(WCHAR));
4918     DumpSidNumeric(pSid, &wptr, NULL);
4919     *wptr = 0;
4920
4921     *pstr = wstr;
4922     return TRUE;
4923 }
4924
4925 /******************************************************************************
4926  * ConvertSidToStringSidA [ADVAPI32.@]
4927  */
4928 BOOL WINAPI ConvertSidToStringSidA(PSID pSid, LPSTR *pstr)
4929 {
4930     LPWSTR wstr = NULL;
4931     LPSTR str;
4932     UINT len;
4933
4934     TRACE("%p %p\n", pSid, pstr );
4935
4936     if( !ConvertSidToStringSidW( pSid, &wstr ) )
4937         return FALSE;
4938
4939     len = WideCharToMultiByte( CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL );
4940     str = LocalAlloc( 0, len );
4941     WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, len, NULL, NULL );
4942     LocalFree( wstr );
4943
4944     *pstr = str;
4945
4946     return TRUE;
4947 }
4948
4949 BOOL WINAPI ConvertToAutoInheritPrivateObjectSecurity(
4950         PSECURITY_DESCRIPTOR pdesc,
4951         PSECURITY_DESCRIPTOR cdesc,
4952         PSECURITY_DESCRIPTOR* ndesc,
4953         GUID* objtype,
4954         BOOL isdir,
4955         PGENERIC_MAPPING genmap )
4956 {
4957     FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
4958
4959     return FALSE;
4960 }
4961
4962 BOOL WINAPI CreatePrivateObjectSecurity(
4963         PSECURITY_DESCRIPTOR ParentDescriptor,
4964         PSECURITY_DESCRIPTOR CreatorDescriptor,
4965         PSECURITY_DESCRIPTOR* NewDescriptor,
4966         BOOL IsDirectoryObject,
4967         HANDLE Token,
4968         PGENERIC_MAPPING GenericMapping )
4969 {
4970     FIXME("%p %p %p %d %p %p - stub\n", ParentDescriptor, CreatorDescriptor,
4971           NewDescriptor, IsDirectoryObject, Token, GenericMapping);
4972
4973     return FALSE;
4974 }
4975
4976 BOOL WINAPI DestroyPrivateObjectSecurity( PSECURITY_DESCRIPTOR* ObjectDescriptor )
4977 {
4978     FIXME("%p - stub\n", ObjectDescriptor);
4979
4980     return TRUE;
4981 }
4982
4983 BOOL WINAPI CreateProcessAsUserA(
4984         HANDLE hToken,
4985         LPCSTR lpApplicationName,
4986         LPSTR lpCommandLine,
4987         LPSECURITY_ATTRIBUTES lpProcessAttributes,
4988         LPSECURITY_ATTRIBUTES lpThreadAttributes,
4989         BOOL bInheritHandles,
4990         DWORD dwCreationFlags,
4991         LPVOID lpEnvironment,
4992         LPCSTR lpCurrentDirectory,
4993         LPSTARTUPINFOA lpStartupInfo,
4994         LPPROCESS_INFORMATION lpProcessInformation )
4995 {
4996     FIXME("%p %s %s %p %p %d 0x%08x %p %s %p %p - stub\n", hToken, debugstr_a(lpApplicationName),
4997           debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
4998           dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
4999
5000     return FALSE;
5001 }
5002
5003 BOOL WINAPI CreateProcessAsUserW(
5004         HANDLE hToken,
5005         LPCWSTR lpApplicationName,
5006         LPWSTR lpCommandLine,
5007         LPSECURITY_ATTRIBUTES lpProcessAttributes,
5008         LPSECURITY_ATTRIBUTES lpThreadAttributes,
5009         BOOL bInheritHandles,
5010         DWORD dwCreationFlags,
5011         LPVOID lpEnvironment,
5012         LPCWSTR lpCurrentDirectory,
5013         LPSTARTUPINFOW lpStartupInfo,
5014         LPPROCESS_INFORMATION lpProcessInformation )
5015 {
5016     FIXME("%p %s %s %p %p %d 0x%08x %p %s %p %p - semi- stub\n", hToken, 
5017           debugstr_w(lpApplicationName), debugstr_w(lpCommandLine), lpProcessAttributes,
5018           lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, 
5019           debugstr_w(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
5020
5021     /* We should create the process with a suspended main thread */
5022     if (!CreateProcessW (lpApplicationName,
5023                          lpCommandLine,
5024                          lpProcessAttributes,
5025                          lpThreadAttributes,
5026                          bInheritHandles,
5027                          dwCreationFlags, /* CREATE_SUSPENDED */
5028                          lpEnvironment,
5029                          lpCurrentDirectory,
5030                          lpStartupInfo,
5031                          lpProcessInformation))
5032     {
5033       return FALSE;
5034     }
5035
5036     return TRUE;
5037 }
5038
5039 /******************************************************************************
5040  * CreateProcessWithLogonW
5041  */
5042 BOOL WINAPI CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags,
5043     LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment,
5044     LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
5045 {
5046     FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
5047     debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
5048     debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
5049     lpStartupInfo, lpProcessInformation);
5050
5051     return FALSE;
5052 }
5053
5054 /******************************************************************************
5055  * DuplicateTokenEx [ADVAPI32.@]
5056  */
5057 BOOL WINAPI DuplicateTokenEx(
5058         HANDLE ExistingTokenHandle, DWORD dwDesiredAccess,
5059         LPSECURITY_ATTRIBUTES lpTokenAttributes,
5060         SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
5061         TOKEN_TYPE TokenType,
5062         PHANDLE DuplicateTokenHandle )
5063 {
5064     OBJECT_ATTRIBUTES ObjectAttributes;
5065
5066     TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
5067           ImpersonationLevel, TokenType, DuplicateTokenHandle);
5068
5069     InitializeObjectAttributes(
5070         &ObjectAttributes,
5071         NULL,
5072         (lpTokenAttributes && lpTokenAttributes->bInheritHandle) ? OBJ_INHERIT : 0,
5073         NULL,
5074         lpTokenAttributes ? lpTokenAttributes->lpSecurityDescriptor : NULL );
5075
5076     return set_ntstatus( NtDuplicateToken( ExistingTokenHandle,
5077                                            dwDesiredAccess,
5078                                            &ObjectAttributes,
5079                                            ImpersonationLevel,
5080                                            TokenType,
5081                                            DuplicateTokenHandle ) );
5082 }
5083
5084 BOOL WINAPI DuplicateToken(
5085         HANDLE ExistingTokenHandle,
5086         SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
5087         PHANDLE DuplicateTokenHandle )
5088 {
5089     return DuplicateTokenEx( ExistingTokenHandle, TOKEN_IMPERSONATE | TOKEN_QUERY,
5090                              NULL, ImpersonationLevel, TokenImpersonation,
5091                              DuplicateTokenHandle );
5092 }
5093
5094 /******************************************************************************
5095  * ComputeStringSidSize
5096  */
5097 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
5098 {
5099     if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
5100     {
5101         int ctok = 0;
5102         while (*StringSid)
5103         {
5104             if (*StringSid == '-')
5105                 ctok++;
5106             StringSid++;
5107         }
5108
5109         if (ctok >= 3)
5110             return GetSidLengthRequired(ctok - 2);
5111     }
5112     else /* String constant format  - Only available in winxp and above */
5113     {
5114         unsigned int i;
5115
5116         for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5117             if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5118                 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
5119     }
5120
5121     return GetSidLengthRequired(0);
5122 }
5123
5124 /******************************************************************************
5125  * ParseStringSidToSid
5126  */
5127 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
5128 {
5129     BOOL bret = FALSE;
5130     SID* pisid=pSid;
5131
5132     TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
5133     if (!StringSid)
5134     {
5135         SetLastError(ERROR_INVALID_PARAMETER);
5136         TRACE("StringSid is NULL, returning FALSE\n");
5137         return FALSE;
5138     }
5139
5140     while (*StringSid == ' ')
5141         StringSid++;
5142
5143     *cBytes = ComputeStringSidSize(StringSid);
5144     if (!pisid) /* Simply compute the size */
5145     {
5146         TRACE("only size requested, returning TRUE\n");
5147         return TRUE;
5148     }
5149
5150     if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
5151     {
5152         DWORD i = 0, identAuth;
5153         DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
5154
5155         StringSid += 2; /* Advance to Revision */
5156         pisid->Revision = atoiW(StringSid);
5157
5158         if (pisid->Revision != SDDL_REVISION)
5159         {
5160             TRACE("Revision %d is unknown\n", pisid->Revision);
5161             goto lend; /* ERROR_INVALID_SID */
5162         }
5163         if (csubauth == 0)
5164         {
5165             TRACE("SubAuthorityCount is 0\n");
5166             goto lend; /* ERROR_INVALID_SID */
5167         }
5168
5169         pisid->SubAuthorityCount = csubauth;
5170
5171         /* Advance to identifier authority */
5172         while (*StringSid && *StringSid != '-')
5173             StringSid++;
5174         if (*StringSid == '-')
5175             StringSid++;
5176
5177         /* MS' implementation can't handle values greater than 2^32 - 1, so
5178          * we don't either; assume most significant bytes are always 0
5179          */
5180         pisid->IdentifierAuthority.Value[0] = 0;
5181         pisid->IdentifierAuthority.Value[1] = 0;
5182         identAuth = atoiW(StringSid);
5183         pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
5184         pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
5185         pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
5186         pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
5187
5188         /* Advance to first sub authority */
5189         while (*StringSid && *StringSid != '-')
5190             StringSid++;
5191         if (*StringSid == '-')
5192             StringSid++;
5193
5194         while (*StringSid)
5195         {
5196             pisid->SubAuthority[i++] = atoiW(StringSid);
5197
5198             while (*StringSid && *StringSid != '-')
5199                 StringSid++;
5200             if (*StringSid == '-')
5201                 StringSid++;
5202         }
5203
5204         if (i != pisid->SubAuthorityCount)
5205             goto lend; /* ERROR_INVALID_SID */
5206
5207         bret = TRUE;
5208     }
5209     else /* String constant format  - Only available in winxp and above */
5210     {
5211         unsigned int i;
5212         pisid->Revision = SDDL_REVISION;
5213
5214         for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5215             if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5216             {
5217                 DWORD j;
5218                 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
5219                 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
5220                 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
5221                     pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
5222                 bret = TRUE;
5223             }
5224
5225         if (!bret)
5226             FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
5227     }
5228
5229 lend:
5230     if (!bret)
5231         SetLastError(ERROR_INVALID_SID);
5232
5233     TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
5234     return bret;
5235 }
5236
5237 /******************************************************************************
5238  * GetNamedSecurityInfoA [ADVAPI32.@]
5239  */
5240 DWORD WINAPI GetNamedSecurityInfoA(LPSTR pObjectName,
5241         SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5242         PSID* ppsidOwner, PSID* ppsidGroup, PACL* ppDacl, PACL* ppSacl,
5243         PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
5244 {
5245     DWORD len;
5246     LPWSTR wstr = NULL;
5247     DWORD r;
5248
5249     TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo,
5250         ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
5251
5252     if( pObjectName )
5253     {
5254         len = MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, NULL, 0 );
5255         wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR));
5256         MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, wstr, len );
5257     }
5258
5259     r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
5260                            ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
5261
5262     HeapFree( GetProcessHeap(), 0, wstr );
5263
5264     return r;
5265 }
5266
5267 /******************************************************************************
5268  * GetNamedSecurityInfoW [ADVAPI32.@]
5269  */
5270 DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type,
5271     SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl,
5272     PACL* sacl, PSECURITY_DESCRIPTOR* descriptor )
5273 {
5274     DWORD needed, offset;
5275     SECURITY_DESCRIPTOR_RELATIVE *relative;
5276     BYTE *buffer;
5277
5278     TRACE( "%s %d %d %p %p %p %p %p\n", debugstr_w(name), type, info, owner,
5279            group, dacl, sacl, descriptor );
5280
5281     if (!name || !descriptor) return ERROR_INVALID_PARAMETER;
5282
5283     needed = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5284     if (info & OWNER_SECURITY_INFORMATION)
5285         needed += sizeof(sidWorld);
5286     if (info & GROUP_SECURITY_INFORMATION)
5287         needed += sizeof(sidWorld);
5288     if (info & DACL_SECURITY_INFORMATION)
5289         needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5290     if (info & SACL_SECURITY_INFORMATION)
5291         needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5292
5293     /* must be freed by caller */
5294     *descriptor = HeapAlloc( GetProcessHeap(), 0, needed );
5295     if (!*descriptor) return ERROR_NOT_ENOUGH_MEMORY;
5296
5297     if (!InitializeSecurityDescriptor( *descriptor, SECURITY_DESCRIPTOR_REVISION ))
5298     {
5299         HeapFree( GetProcessHeap(), 0, *descriptor );
5300         return ERROR_INVALID_SECURITY_DESCR;
5301     }
5302
5303     relative = *descriptor;
5304     relative->Control |= SE_SELF_RELATIVE;
5305     buffer = (BYTE *)relative;
5306     offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5307
5308     if (info & OWNER_SECURITY_INFORMATION)
5309     {
5310         memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5311         relative->Owner = offset;
5312         if (owner)
5313             *owner = buffer + offset;
5314         offset += sizeof(sidWorld);
5315     }
5316     if (info & GROUP_SECURITY_INFORMATION)
5317     {
5318         memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5319         relative->Group = offset;
5320         if (group)
5321             *group = buffer + offset;
5322         offset += sizeof(sidWorld);
5323     }
5324     if (info & DACL_SECURITY_INFORMATION)
5325     {
5326         relative->Control |= SE_DACL_PRESENT;
5327         GetWorldAccessACL( (PACL)(buffer + offset) );
5328         relative->Dacl = offset;
5329         if (dacl)
5330             *dacl = (PACL)(buffer + offset);
5331         offset += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5332     }
5333     if (info & SACL_SECURITY_INFORMATION)
5334     {
5335         relative->Control |= SE_SACL_PRESENT;
5336         GetWorldAccessACL( (PACL)(buffer + offset) );
5337         relative->Sacl = offset;
5338         if (sacl)
5339             *sacl = (PACL)(buffer + offset);
5340     }
5341     return ERROR_SUCCESS;
5342 }
5343
5344 /******************************************************************************
5345  * DecryptFileW [ADVAPI32.@]
5346  */
5347 BOOL WINAPI DecryptFileW(LPCWSTR lpFileName, DWORD dwReserved)
5348 {
5349     FIXME("%s %08x\n", debugstr_w(lpFileName), dwReserved);
5350     return TRUE;
5351 }
5352
5353 /******************************************************************************
5354  * DecryptFileA [ADVAPI32.@]
5355  */
5356 BOOL WINAPI DecryptFileA(LPCSTR lpFileName, DWORD dwReserved)
5357 {
5358     FIXME("%s %08x\n", debugstr_a(lpFileName), dwReserved);
5359     return TRUE;
5360 }
5361
5362 /******************************************************************************
5363  * EncryptFileW [ADVAPI32.@]
5364  */
5365 BOOL WINAPI EncryptFileW(LPCWSTR lpFileName)
5366 {
5367     FIXME("%s\n", debugstr_w(lpFileName));
5368     return TRUE;
5369 }
5370
5371 /******************************************************************************
5372  * EncryptFileA [ADVAPI32.@]
5373  */
5374 BOOL WINAPI EncryptFileA(LPCSTR lpFileName)
5375 {
5376     FIXME("%s\n", debugstr_a(lpFileName));
5377     return TRUE;
5378 }
5379
5380 /******************************************************************************
5381  * FileEncryptionStatusW [ADVAPI32.@]
5382  */
5383 BOOL WINAPI FileEncryptionStatusW(LPCWSTR lpFileName, LPDWORD lpStatus)
5384 {
5385     FIXME("(%s %p): stub\n", debugstr_w(lpFileName), lpStatus);
5386     if (!lpStatus)
5387         return FALSE;
5388     *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5389     return TRUE;
5390 }
5391
5392 /******************************************************************************
5393  * FileEncryptionStatusA [ADVAPI32.@]
5394  */
5395 BOOL WINAPI FileEncryptionStatusA(LPCSTR lpFileName, LPDWORD lpStatus)
5396 {
5397     FIXME("(%s %p): stub\n", debugstr_a(lpFileName), lpStatus);
5398     if (!lpStatus)
5399         return FALSE;
5400     *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5401     return TRUE;
5402 }
5403
5404 /******************************************************************************
5405  * SetSecurityInfo [ADVAPI32.@]
5406  */
5407 DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType, 
5408                       SECURITY_INFORMATION SecurityInfo, PSID psidOwner,
5409                       PSID psidGroup, PACL pDacl, PACL pSacl) {
5410     FIXME("stub\n");
5411     return ERROR_SUCCESS;
5412 }
5413
5414 /******************************************************************************
5415  * SaferCreateLevel   [ADVAPI32.@]
5416  */
5417 BOOL WINAPI SaferCreateLevel(DWORD ScopeId, DWORD LevelId, DWORD OpenFlags,
5418                              SAFER_LEVEL_HANDLE* LevelHandle, LPVOID lpReserved)
5419 {
5420     FIXME("(%u, %x, %u, %p, %p) stub\n", ScopeId, LevelId, OpenFlags, LevelHandle, lpReserved);
5421     return FALSE;
5422 }
5423
5424 DWORD WINAPI TreeResetNamedSecurityInfoW( LPWSTR pObjectName,
5425                 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5426                 PSID pOwner, PSID pGroup, PACL pDacl, PACL pSacl,
5427                 BOOL KeepExplicit, FN_PROGRESS fnProgress,
5428                 PROG_INVOKE_SETTING ProgressInvokeSetting, PVOID Args)
5429 {
5430     FIXME("(%s, %i, %i, %p, %p, %p, %p, %i, %p, %i, %p  Stub\n",
5431         debugstr_w(pObjectName), ObjectType, SecurityInfo, pOwner, pGroup,
5432         pDacl, pSacl, KeepExplicit, fnProgress, ProgressInvokeSetting, Args);
5433
5434     return ERROR_SUCCESS;
5435 }
5436
5437 /******************************************************************************
5438  * SaferGetPolicyInformation   [ADVAPI32.@]
5439  */
5440 BOOL WINAPI SaferGetPolicyInformation(DWORD scope, SAFER_POLICY_INFO_CLASS class, DWORD size,
5441                                       PVOID buffer, PDWORD required, LPVOID lpReserved)
5442 {
5443     FIXME("(%u %u %u %p %p %p) stub\n", scope, class, size, buffer, required, lpReserved);
5444     return FALSE;
5445 }