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