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