Revert "explorerframe: Allow treeview expandos to open with a single click.".
[wine.git] / dlls / advapi32 / security.c
blob09dfdec1f43affba48bb17d6571c8c808a571bb5
1 /*
2 * Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net>
3 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
4 * Copyright 2006 Robert Reif
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.
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.
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
22 #include "config.h"
24 #include <stdarg.h>
25 #include <string.h>
27 #include "ntstatus.h"
28 #define WIN32_NO_STATUS
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winerror.h"
32 #include "winreg.h"
33 #include "winsafer.h"
34 #include "winternl.h"
35 #include "winioctl.h"
36 #include "accctrl.h"
37 #include "sddl.h"
38 #include "winsvc.h"
39 #include "aclapi.h"
40 #include "objbase.h"
41 #include "iads.h"
42 #include "advapi32_misc.h"
43 #include "lmcons.h"
45 #include "wine/debug.h"
46 #include "wine/unicode.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
50 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes);
51 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
52 PACL pAcl, LPDWORD cBytes);
53 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl);
54 static BYTE ParseAceStringType(LPCWSTR* StringAcl);
55 static DWORD ParseAceStringRights(LPCWSTR* StringAcl);
56 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
57 LPCWSTR StringSecurityDescriptor,
58 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
59 LPDWORD cBytes);
60 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl);
62 typedef struct _ACEFLAG
64 LPCWSTR wstr;
65 DWORD value;
66 } ACEFLAG, *LPACEFLAG;
68 typedef struct _MAX_SID
70 /* same fields as struct _SID */
71 BYTE Revision;
72 BYTE SubAuthorityCount;
73 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
74 DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
75 } MAX_SID;
77 typedef struct WELLKNOWNSID
79 WCHAR wstr[2];
80 WELL_KNOWN_SID_TYPE Type;
81 MAX_SID Sid;
82 } WELLKNOWNSID;
84 static const WELLKNOWNSID WellKnownSids[] =
86 { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } },
87 { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } },
88 { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } },
89 { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } },
90 { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } },
91 { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } },
92 { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } },
93 { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } },
94 { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } },
95 { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } },
96 { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } },
97 { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } },
98 { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } },
99 { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } },
100 { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } },
101 { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } },
102 { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } },
103 { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } },
104 { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } },
105 { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } },
106 { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } },
107 { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } },
108 { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } },
109 { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } },
110 { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } },
111 { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } },
112 { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } },
113 { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } },
114 { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } },
115 { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } },
116 { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } },
117 { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } },
118 { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } },
119 { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } },
120 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } },
121 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } },
122 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } },
123 { {0,0}, WinNTLMAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID } } },
124 { {0,0}, WinDigestAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID } } },
125 { {0,0}, WinSChannelAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID } } },
126 { {0,0}, WinThisOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_THIS_ORGANIZATION_RID } } },
127 { {0,0}, WinOtherOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_OTHER_ORGANIZATION_RID } } },
128 { {0,0}, WinBuiltinIncomingForestTrustBuildersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS } } },
129 { {0,0}, WinBuiltinPerfMonitoringUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS } } },
130 { {0,0}, WinBuiltinPerfLoggingUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS } } },
131 { {0,0}, WinBuiltinAuthorizationAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS } } },
132 { {0,0}, WinBuiltinTerminalServerLicenseServersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS } } },
133 { {0,0}, WinBuiltinDCOMUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS } } },
134 { {'L','W'}, WinLowLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_LOW_RID} } },
135 { {'M','E'}, WinMediumLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_MEDIUM_RID } } },
136 { {'H','I'}, WinHighLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_HIGH_RID } } },
137 { {'S','I'}, WinSystemLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_SYSTEM_RID } } },
138 { {0,0}, WinBuiltinAnyPackageSid, { SID_REVISION, 2, { SECURITY_APP_PACKAGE_AUTHORITY }, { SECURITY_APP_PACKAGE_BASE_RID, SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE } } },
141 /* these SIDs must be constructed as relative to some domain - only the RID is well-known */
142 typedef struct WELLKNOWNRID
144 WCHAR wstr[2];
145 WELL_KNOWN_SID_TYPE Type;
146 DWORD Rid;
147 } WELLKNOWNRID;
149 static const WELLKNOWNRID WellKnownRids[] = {
150 { {'L','A'}, WinAccountAdministratorSid, DOMAIN_USER_RID_ADMIN },
151 { {'L','G'}, WinAccountGuestSid, DOMAIN_USER_RID_GUEST },
152 { {0,0}, WinAccountKrbtgtSid, DOMAIN_USER_RID_KRBTGT },
153 { {'D','A'}, WinAccountDomainAdminsSid, DOMAIN_GROUP_RID_ADMINS },
154 { {'D','U'}, WinAccountDomainUsersSid, DOMAIN_GROUP_RID_USERS },
155 { {'D','G'}, WinAccountDomainGuestsSid, DOMAIN_GROUP_RID_GUESTS },
156 { {'D','C'}, WinAccountComputersSid, DOMAIN_GROUP_RID_COMPUTERS },
157 { {'D','D'}, WinAccountControllersSid, DOMAIN_GROUP_RID_CONTROLLERS },
158 { {'C','A'}, WinAccountCertAdminsSid, DOMAIN_GROUP_RID_CERT_ADMINS },
159 { {'S','A'}, WinAccountSchemaAdminsSid, DOMAIN_GROUP_RID_SCHEMA_ADMINS },
160 { {'E','A'}, WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS },
161 { {'P','A'}, WinAccountPolicyAdminsSid, DOMAIN_GROUP_RID_POLICY_ADMINS },
162 { {'R','S'}, WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS },
166 static SID const sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
168 typedef struct _AccountSid {
169 WELL_KNOWN_SID_TYPE type;
170 LPCWSTR account;
171 LPCWSTR domain;
172 SID_NAME_USE name_use;
173 LPCWSTR alias;
174 } AccountSid;
176 static const WCHAR Account_Operators[] = { 'A','c','c','o','u','n','t',' ','O','p','e','r','a','t','o','r','s',0 };
177 static const WCHAR Administrator[] = {'A','d','m','i','n','i','s','t','r','a','t','o','r',0 };
178 static const WCHAR Administrators[] = { 'A','d','m','i','n','i','s','t','r','a','t','o','r','s',0 };
179 static const WCHAR ALL_APPLICATION_PACKAGES[] = { 'A','L','L',' ','A','P','P','L','I','C','A','T','I','O','N',' ','P','A','C','K','A','G','E','S',0 };
180 static const WCHAR ANONYMOUS_LOGON[] = { 'A','N','O','N','Y','M','O','U','S',' ','L','O','G','O','N',0 };
181 static const WCHAR APPLICATION_PACKAGE_AUTHORITY[] = { 'A','P','P','L','I','C','A','T','I','O','N',' ','P','A','C','K','A','G','E',' ','A','U','T','H','O','R','I','T','Y',0 };
182 static const WCHAR Authenticated_Users[] = { 'A','u','t','h','e','n','t','i','c','a','t','e','d',' ','U','s','e','r','s',0 };
183 static const WCHAR Backup_Operators[] = { 'B','a','c','k','u','p',' ','O','p','e','r','a','t','o','r','s',0 };
184 static const WCHAR BATCH[] = { 'B','A','T','C','H',0 };
185 static const WCHAR Blank[] = { 0 };
186 static const WCHAR BUILTIN[] = { 'B','U','I','L','T','I','N',0 };
187 static const WCHAR Cert_Publishers[] = { 'C','e','r','t',' ','P','u','b','l','i','s','h','e','r','s',0 };
188 static const WCHAR CREATOR_GROUP[] = { 'C','R','E','A','T','O','R',' ','G','R','O','U','P',0 };
189 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 };
190 static const WCHAR CREATOR_OWNER[] = { 'C','R','E','A','T','O','R',' ','O','W','N','E','R',0 };
191 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 };
192 static const WCHAR CURRENT_USER[] = { 'C','U','R','R','E','N','T','_','U','S','E','R',0 };
193 static const WCHAR DIALUP[] = { 'D','I','A','L','U','P',0 };
194 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 };
195 static const WCHAR Domain_Admins[] = { 'D','o','m','a','i','n',' ','A','d','m','i','n','s',0 };
196 static const WCHAR Domain_Computers[] = { 'D','o','m','a','i','n',' ','C','o','m','p','u','t','e','r','s',0 };
197 static const WCHAR Domain_Controllers[] = { 'D','o','m','a','i','n',' ','C','o','n','t','r','o','l','l','e','r','s',0 };
198 static const WCHAR Domain_Guests[] = { 'D','o','m','a','i','n',' ','G','u','e','s','t','s',0 };
199 static const WCHAR Domain_Users[] = { 'D','o','m','a','i','n',' ','U','s','e','r','s',0 };
200 static const WCHAR Enterprise_Admins[] = { 'E','n','t','e','r','p','r','i','s','e',' ','A','d','m','i','n','s',0 };
201 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 };
202 static const WCHAR Everyone[] = { 'E','v','e','r','y','o','n','e',0 };
203 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 };
204 static const WCHAR Guest[] = { 'G','u','e','s','t',0 };
205 static const WCHAR Guests[] = { 'G','u','e','s','t','s',0 };
206 static const WCHAR INTERACTIVE[] = { 'I','N','T','E','R','A','C','T','I','V','E',0 };
207 static const WCHAR LOCAL[] = { 'L','O','C','A','L',0 };
208 static const WCHAR LOCAL_SERVICE[] = { 'L','O','C','A','L',' ','S','E','R','V','I','C','E',0 };
209 static const WCHAR LOCAL_SERVICE2[] = { 'L','O','C','A','L','S','E','R','V','I','C','E',0 };
210 static const WCHAR NETWORK[] = { 'N','E','T','W','O','R','K',0 };
211 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 };
212 static const WCHAR NETWORK_SERVICE[] = { 'N','E','T','W','O','R','K',' ','S','E','R','V','I','C','E',0 };
213 static const WCHAR NETWORK_SERVICE2[] = { 'N','E','T','W','O','R','K','S','E','R','V','I','C','E',0 };
214 static const WCHAR NT_AUTHORITY[] = { 'N','T',' ','A','U','T','H','O','R','I','T','Y',0 };
215 static const WCHAR NT_Pseudo_Domain[] = { 'N','T',' ','P','s','e','u','d','o',' ','D','o','m','a','i','n',0 };
216 static const WCHAR NTML_Authentication[] = { 'N','T','M','L',' ','A','u','t','h','e','n','t','i','c','a','t','i','o','n',0 };
217 static const WCHAR NULL_SID[] = { 'N','U','L','L',' ','S','I','D',0 };
218 static const WCHAR Other_Organization[] = { 'O','t','h','e','r',' ','O','r','g','a','n','i','z','a','t','i','o','n',0 };
219 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 };
220 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 };
221 static const WCHAR Power_Users[] = { 'P','o','w','e','r',' ','U','s','e','r','s',0 };
222 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 };
223 static const WCHAR Print_Operators[] = { 'P','r','i','n','t',' ','O','p','e','r','a','t','o','r','s',0 };
224 static const WCHAR PROXY[] = { 'P','R','O','X','Y',0 };
225 static const WCHAR RAS_and_IAS_Servers[] = { 'R','A','S',' ','a','n','d',' ','I','A','S',' ','S','e','r','v','e','r','s',0 };
226 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 };
227 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 };
228 static const WCHAR Replicators[] = { 'R','e','p','l','i','c','a','t','o','r','s',0 };
229 static const WCHAR RESTRICTED[] = { 'R','E','S','T','R','I','C','T','E','D',0 };
230 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 };
231 static const WCHAR Schema_Admins[] = { 'S','c','h','e','m','a',' ','A','d','m','i','n','s',0 };
232 static const WCHAR SELF[] = { 'S','E','L','F',0 };
233 static const WCHAR Server_Operators[] = { 'S','e','r','v','e','r',' ','O','p','e','r','a','t','o','r','s',0 };
234 static const WCHAR SERVICE[] = { 'S','E','R','V','I','C','E',0 };
235 static const WCHAR SYSTEM[] = { 'S','Y','S','T','E','M',0 };
236 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 };
237 static const WCHAR This_Organization[] = { 'T','h','i','s',' ','O','r','g','a','n','i','z','a','t','i','o','n',0 };
238 static const WCHAR Users[] = { 'U','s','e','r','s',0 };
240 static const AccountSid ACCOUNT_SIDS[] = {
241 { WinNullSid, NULL_SID, Blank, SidTypeWellKnownGroup },
242 { WinWorldSid, Everyone, Blank, SidTypeWellKnownGroup },
243 { WinLocalSid, LOCAL, Blank, SidTypeWellKnownGroup },
244 { WinCreatorOwnerSid, CREATOR_OWNER, Blank, SidTypeWellKnownGroup },
245 { WinCreatorGroupSid, CREATOR_GROUP, Blank, SidTypeWellKnownGroup },
246 { WinCreatorOwnerServerSid, CREATOR_OWNER_SERVER, Blank, SidTypeWellKnownGroup },
247 { WinCreatorGroupServerSid, CREATOR_GROUP_SERVER, Blank, SidTypeWellKnownGroup },
248 { WinNtAuthoritySid, NT_Pseudo_Domain, NT_Pseudo_Domain, SidTypeDomain },
249 { WinDialupSid, DIALUP, NT_AUTHORITY, SidTypeWellKnownGroup },
250 { WinNetworkSid, NETWORK, NT_AUTHORITY, SidTypeWellKnownGroup },
251 { WinBatchSid, BATCH, NT_AUTHORITY, SidTypeWellKnownGroup },
252 { WinInteractiveSid, INTERACTIVE, NT_AUTHORITY, SidTypeWellKnownGroup },
253 { WinServiceSid, SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup },
254 { WinAnonymousSid, ANONYMOUS_LOGON, NT_AUTHORITY, SidTypeWellKnownGroup },
255 { WinProxySid, PROXY, NT_AUTHORITY, SidTypeWellKnownGroup },
256 { WinEnterpriseControllersSid, ENTERPRISE_DOMAIN_CONTROLLERS, NT_AUTHORITY, SidTypeWellKnownGroup },
257 { WinSelfSid, SELF, NT_AUTHORITY, SidTypeWellKnownGroup },
258 { WinAuthenticatedUserSid, Authenticated_Users, NT_AUTHORITY, SidTypeWellKnownGroup },
259 { WinRestrictedCodeSid, RESTRICTED, NT_AUTHORITY, SidTypeWellKnownGroup },
260 { WinTerminalServerSid, TERMINAL_SERVER_USER, NT_AUTHORITY, SidTypeWellKnownGroup },
261 { WinRemoteLogonIdSid, REMOTE_INTERACTIVE_LOGON, NT_AUTHORITY, SidTypeWellKnownGroup },
262 { WinLocalSystemSid, SYSTEM, NT_AUTHORITY, SidTypeWellKnownGroup },
263 { WinLocalServiceSid, LOCAL_SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup, LOCAL_SERVICE2 },
264 { WinNetworkServiceSid, NETWORK_SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup , NETWORK_SERVICE2},
265 { WinBuiltinDomainSid, BUILTIN, BUILTIN, SidTypeDomain },
266 { WinBuiltinAdministratorsSid, Administrators, BUILTIN, SidTypeAlias },
267 { WinBuiltinUsersSid, Users, BUILTIN, SidTypeAlias },
268 { WinBuiltinGuestsSid, Guests, BUILTIN, SidTypeAlias },
269 { WinBuiltinPowerUsersSid, Power_Users, BUILTIN, SidTypeAlias },
270 { WinBuiltinAccountOperatorsSid, Account_Operators, BUILTIN, SidTypeAlias },
271 { WinBuiltinSystemOperatorsSid, Server_Operators, BUILTIN, SidTypeAlias },
272 { WinBuiltinPrintOperatorsSid, Print_Operators, BUILTIN, SidTypeAlias },
273 { WinBuiltinBackupOperatorsSid, Backup_Operators, BUILTIN, SidTypeAlias },
274 { WinBuiltinReplicatorSid, Replicators, BUILTIN, SidTypeAlias },
275 { WinBuiltinPreWindows2000CompatibleAccessSid, Pre_Windows_2000_Compatible_Access, BUILTIN, SidTypeAlias },
276 { WinBuiltinRemoteDesktopUsersSid, Remote_Desktop_Users, BUILTIN, SidTypeAlias },
277 { WinBuiltinNetworkConfigurationOperatorsSid, Network_Configuration_Operators, BUILTIN, SidTypeAlias },
278 { WinNTLMAuthenticationSid, NTML_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
279 { WinDigestAuthenticationSid, Digest_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
280 { WinSChannelAuthenticationSid, SChannel_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
281 { WinThisOrganizationSid, This_Organization, NT_AUTHORITY, SidTypeWellKnownGroup },
282 { WinOtherOrganizationSid, Other_Organization, NT_AUTHORITY, SidTypeWellKnownGroup },
283 { WinBuiltinPerfMonitoringUsersSid, Performance_Monitor_Users, BUILTIN, SidTypeAlias },
284 { WinBuiltinPerfLoggingUsersSid, Performance_Log_Users, BUILTIN, SidTypeAlias },
285 { WinBuiltinAnyPackageSid, ALL_APPLICATION_PACKAGES, APPLICATION_PACKAGE_AUTHORITY, SidTypeWellKnownGroup },
288 * ACE access rights
290 static const WCHAR SDDL_READ_CONTROL[] = {'R','C',0};
291 static const WCHAR SDDL_WRITE_DAC[] = {'W','D',0};
292 static const WCHAR SDDL_WRITE_OWNER[] = {'W','O',0};
293 static const WCHAR SDDL_STANDARD_DELETE[] = {'S','D',0};
295 static const WCHAR SDDL_READ_PROPERTY[] = {'R','P',0};
296 static const WCHAR SDDL_WRITE_PROPERTY[] = {'W','P',0};
297 static const WCHAR SDDL_CREATE_CHILD[] = {'C','C',0};
298 static const WCHAR SDDL_DELETE_CHILD[] = {'D','C',0};
299 static const WCHAR SDDL_LIST_CHILDREN[] = {'L','C',0};
300 static const WCHAR SDDL_SELF_WRITE[] = {'S','W',0};
301 static const WCHAR SDDL_LIST_OBJECT[] = {'L','O',0};
302 static const WCHAR SDDL_DELETE_TREE[] = {'D','T',0};
303 static const WCHAR SDDL_CONTROL_ACCESS[] = {'C','R',0};
305 static const WCHAR SDDL_FILE_ALL[] = {'F','A',0};
306 static const WCHAR SDDL_FILE_READ[] = {'F','R',0};
307 static const WCHAR SDDL_FILE_WRITE[] = {'F','W',0};
308 static const WCHAR SDDL_FILE_EXECUTE[] = {'F','X',0};
310 static const WCHAR SDDL_KEY_ALL[] = {'K','A',0};
311 static const WCHAR SDDL_KEY_READ[] = {'K','R',0};
312 static const WCHAR SDDL_KEY_WRITE[] = {'K','W',0};
313 static const WCHAR SDDL_KEY_EXECUTE[] = {'K','X',0};
315 static const WCHAR SDDL_GENERIC_ALL[] = {'G','A',0};
316 static const WCHAR SDDL_GENERIC_READ[] = {'G','R',0};
317 static const WCHAR SDDL_GENERIC_WRITE[] = {'G','W',0};
318 static const WCHAR SDDL_GENERIC_EXECUTE[] = {'G','X',0};
320 static const WCHAR SDDL_NO_READ_UP[] = {'N','R',0};
321 static const WCHAR SDDL_NO_WRITE_UP[] = {'N','W',0};
322 static const WCHAR SDDL_NO_EXECUTE_UP[] = {'N','X',0};
325 * ACL flags
327 static const WCHAR SDDL_PROTECTED[] = {'P',0};
328 static const WCHAR SDDL_AUTO_INHERIT_REQ[] = {'A','R',0};
329 static const WCHAR SDDL_AUTO_INHERITED[] = {'A','I',0};
332 * ACE types
334 static const WCHAR SDDL_ACCESS_ALLOWED[] = {'A',0};
335 static const WCHAR SDDL_ACCESS_DENIED[] = {'D',0};
336 static const WCHAR SDDL_AUDIT[] = {'A','U',0};
337 static const WCHAR SDDL_ALARM[] = {'A','L',0};
338 static const WCHAR SDDL_MANDATORY_LABEL[] = {'M','L',0};
341 * ACE flags
343 static const WCHAR SDDL_CONTAINER_INHERIT[] = {'C','I',0};
344 static const WCHAR SDDL_OBJECT_INHERIT[] = {'O','I',0};
345 static const WCHAR SDDL_NO_PROPAGATE[] = {'N','P',0};
346 static const WCHAR SDDL_INHERIT_ONLY[] = {'I','O',0};
347 static const WCHAR SDDL_INHERITED[] = {'I','D',0};
348 static const WCHAR SDDL_AUDIT_SUCCESS[] = {'S','A',0};
349 static const WCHAR SDDL_AUDIT_FAILURE[] = {'F','A',0};
351 const char * debugstr_sid(PSID sid)
353 int auth = 0;
354 SID * psid = sid;
356 if (psid == NULL)
357 return "(null)";
359 auth = psid->IdentifierAuthority.Value[5] +
360 (psid->IdentifierAuthority.Value[4] << 8) +
361 (psid->IdentifierAuthority.Value[3] << 16) +
362 (psid->IdentifierAuthority.Value[2] << 24);
364 switch (psid->SubAuthorityCount) {
365 case 0:
366 return wine_dbg_sprintf("S-%d-%d", psid->Revision, auth);
367 case 1:
368 return wine_dbg_sprintf("S-%d-%d-%u", psid->Revision, auth,
369 psid->SubAuthority[0]);
370 case 2:
371 return wine_dbg_sprintf("S-%d-%d-%u-%u", psid->Revision, auth,
372 psid->SubAuthority[0], psid->SubAuthority[1]);
373 case 3:
374 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u", psid->Revision, auth,
375 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]);
376 case 4:
377 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u", psid->Revision, auth,
378 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
379 psid->SubAuthority[3]);
380 case 5:
381 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u", psid->Revision, auth,
382 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
383 psid->SubAuthority[3], psid->SubAuthority[4]);
384 case 6:
385 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
386 psid->SubAuthority[3], psid->SubAuthority[1], psid->SubAuthority[2],
387 psid->SubAuthority[0], psid->SubAuthority[4], psid->SubAuthority[5]);
388 case 7:
389 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
390 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
391 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
392 psid->SubAuthority[6]);
393 case 8:
394 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
395 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
396 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
397 psid->SubAuthority[6], psid->SubAuthority[7]);
399 return "(too-big)";
402 /* set last error code from NT status and get the proper boolean return value */
403 /* used for functions that are a simple wrapper around the corresponding ntdll API */
404 static inline BOOL set_ntstatus( NTSTATUS status )
406 if (status) SetLastError( RtlNtStatusToDosError( status ));
407 return !status;
410 /* helper function for SE_FILE_OBJECT objects in [Get|Set]NamedSecurityInfo */
411 static inline DWORD get_security_file( LPCWSTR full_file_name, DWORD access, HANDLE *file )
413 UNICODE_STRING file_nameW;
414 OBJECT_ATTRIBUTES attr;
415 IO_STATUS_BLOCK io;
416 NTSTATUS status;
418 if (!RtlDosPathNameToNtPathName_U( full_file_name, &file_nameW, NULL, NULL ))
419 return ERROR_PATH_NOT_FOUND;
420 attr.Length = sizeof(attr);
421 attr.RootDirectory = 0;
422 attr.Attributes = OBJ_CASE_INSENSITIVE;
423 attr.ObjectName = &file_nameW;
424 attr.SecurityDescriptor = NULL;
425 status = NtCreateFile( file, access|SYNCHRONIZE, &attr, &io, NULL, FILE_FLAG_BACKUP_SEMANTICS,
426 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN,
427 FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0 );
428 RtlFreeUnicodeString( &file_nameW );
429 return RtlNtStatusToDosError( status );
432 /* helper function for SE_SERVICE objects in [Get|Set]NamedSecurityInfo */
433 static inline DWORD get_security_service( LPWSTR full_service_name, DWORD access, HANDLE *service )
435 SC_HANDLE manager = 0;
436 DWORD err;
438 err = SERV_OpenSCManagerW( NULL, NULL, access, (SC_HANDLE *)&manager );
439 if (err == ERROR_SUCCESS)
441 err = SERV_OpenServiceW( manager, full_service_name, access, (SC_HANDLE *)service );
442 CloseServiceHandle( manager );
444 return err;
447 /* helper function for SE_REGISTRY_KEY objects in [Get|Set]NamedSecurityInfo */
448 static inline DWORD get_security_regkey( LPWSTR full_key_name, DWORD access, HANDLE *key )
450 WCHAR classes_rootW[] = {'C','L','A','S','S','E','S','_','R','O','O','T',0};
451 WCHAR current_userW[] = {'C','U','R','R','E','N','T','_','U','S','E','R',0};
452 WCHAR machineW[] = {'M','A','C','H','I','N','E',0};
453 WCHAR usersW[] = {'U','S','E','R','S',0};
454 LPWSTR p = strchrW(full_key_name, '\\');
455 int len = p-full_key_name;
456 HKEY hParent;
458 if (!p) return ERROR_INVALID_PARAMETER;
459 if (strncmpW( full_key_name, classes_rootW, len ) == 0)
460 hParent = HKEY_CLASSES_ROOT;
461 else if (strncmpW( full_key_name, current_userW, len ) == 0)
462 hParent = HKEY_CURRENT_USER;
463 else if (strncmpW( full_key_name, machineW, len ) == 0)
464 hParent = HKEY_LOCAL_MACHINE;
465 else if (strncmpW( full_key_name, usersW, len ) == 0)
466 hParent = HKEY_USERS;
467 else
468 return ERROR_INVALID_PARAMETER;
469 return RegOpenKeyExW( hParent, p+1, 0, access, (HKEY *)key );
472 #define WINE_SIZE_OF_WORLD_ACCESS_ACL (sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD))
474 static void GetWorldAccessACL(PACL pACL)
476 PACCESS_ALLOWED_ACE pACE = (PACCESS_ALLOWED_ACE) (pACL + 1);
478 pACL->AclRevision = ACL_REVISION;
479 pACL->Sbz1 = 0;
480 pACL->AclSize = WINE_SIZE_OF_WORLD_ACCESS_ACL;
481 pACL->AceCount = 1;
482 pACL->Sbz2 = 0;
484 pACE->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
485 pACE->Header.AceFlags = CONTAINER_INHERIT_ACE;
486 pACE->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD);
487 pACE->Mask = 0xf3ffffff; /* Everything except reserved bits */
488 memcpy(&pACE->SidStart, &sidWorld, sizeof(sidWorld));
491 /************************************************************
492 * ADVAPI_IsLocalComputer
494 * Checks whether the server name indicates local machine.
496 BOOL ADVAPI_IsLocalComputer(LPCWSTR ServerName)
498 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
499 BOOL Result;
500 LPWSTR buf;
502 if (!ServerName || !ServerName[0])
503 return TRUE;
505 buf = heap_alloc(dwSize * sizeof(WCHAR));
506 Result = GetComputerNameW(buf, &dwSize);
507 if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\'))
508 ServerName += 2;
509 Result = Result && !lstrcmpW(ServerName, buf);
510 heap_free(buf);
512 return Result;
515 /************************************************************
516 * ADVAPI_GetComputerSid
518 BOOL ADVAPI_GetComputerSid(PSID sid)
520 static const struct /* same fields as struct SID */
522 BYTE Revision;
523 BYTE SubAuthorityCount;
524 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
525 DWORD SubAuthority[4];
526 } computer_sid =
527 { SID_REVISION, 4, { SECURITY_NT_AUTHORITY }, { SECURITY_NT_NON_UNIQUE, 0, 0, 0 } };
529 memcpy( sid, &computer_sid, sizeof(computer_sid) );
530 return TRUE;
533 /* ##############################
534 ###### TOKEN FUNCTIONS ######
535 ##############################
538 /******************************************************************************
539 * OpenProcessToken [ADVAPI32.@]
540 * Opens the access token associated with a process handle.
542 * PARAMS
543 * ProcessHandle [I] Handle to process
544 * DesiredAccess [I] Desired access to process
545 * TokenHandle [O] Pointer to handle of open access token
547 * RETURNS
548 * Success: TRUE. TokenHandle contains the access token.
549 * Failure: FALSE.
551 * NOTES
552 * See NtOpenProcessToken.
554 BOOL WINAPI
555 OpenProcessToken( HANDLE ProcessHandle, DWORD DesiredAccess,
556 HANDLE *TokenHandle )
558 return set_ntstatus(NtOpenProcessToken( ProcessHandle, DesiredAccess, TokenHandle ));
561 /******************************************************************************
562 * OpenThreadToken [ADVAPI32.@]
564 * Opens the access token associated with a thread handle.
566 * PARAMS
567 * ThreadHandle [I] Handle to process
568 * DesiredAccess [I] Desired access to the thread
569 * OpenAsSelf [I] ???
570 * TokenHandle [O] Destination for the token handle
572 * RETURNS
573 * Success: TRUE. TokenHandle contains the access token.
574 * Failure: FALSE.
576 * NOTES
577 * See NtOpenThreadToken.
579 BOOL WINAPI
580 OpenThreadToken( HANDLE ThreadHandle, DWORD DesiredAccess,
581 BOOL OpenAsSelf, HANDLE *TokenHandle)
583 return set_ntstatus( NtOpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf, TokenHandle));
586 BOOL WINAPI
587 AdjustTokenGroups( HANDLE TokenHandle, BOOL ResetToDefault, PTOKEN_GROUPS NewState,
588 DWORD BufferLength, PTOKEN_GROUPS PreviousState, PDWORD ReturnLength )
590 return set_ntstatus( NtAdjustGroupsToken(TokenHandle, ResetToDefault, NewState, BufferLength,
591 PreviousState, ReturnLength));
594 /******************************************************************************
595 * AdjustTokenPrivileges [ADVAPI32.@]
597 * Adjust the privileges of an open token handle.
599 * PARAMS
600 * TokenHandle [I] Handle from OpenProcessToken() or OpenThreadToken()
601 * DisableAllPrivileges [I] TRUE=Remove all privileges, FALSE=Use NewState
602 * NewState [I] Desired new privileges of the token
603 * BufferLength [I] Length of NewState
604 * PreviousState [O] Destination for the previous state
605 * ReturnLength [I/O] Size of PreviousState
608 * RETURNS
609 * Success: TRUE. Privileges are set to NewState and PreviousState is updated.
610 * Failure: FALSE.
612 * NOTES
613 * See NtAdjustPrivilegesToken.
615 BOOL WINAPI
616 AdjustTokenPrivileges( HANDLE TokenHandle, BOOL DisableAllPrivileges,
617 PTOKEN_PRIVILEGES NewState, DWORD BufferLength,
618 PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength )
620 NTSTATUS status;
622 TRACE("(%p %d %p %d %p %p)\n", TokenHandle, DisableAllPrivileges, NewState, BufferLength,
623 PreviousState, ReturnLength);
625 status = NtAdjustPrivilegesToken(TokenHandle, DisableAllPrivileges,
626 NewState, BufferLength, PreviousState,
627 ReturnLength);
628 SetLastError( RtlNtStatusToDosError( status ));
629 if ((status == STATUS_SUCCESS) || (status == STATUS_NOT_ALL_ASSIGNED))
630 return TRUE;
631 else
632 return FALSE;
635 /******************************************************************************
636 * CheckTokenMembership [ADVAPI32.@]
638 * Determine if an access token is a member of a SID.
640 * PARAMS
641 * TokenHandle [I] Handle from OpenProcessToken() or OpenThreadToken()
642 * SidToCheck [I] SID that possibly contains the token
643 * IsMember [O] Destination for result.
645 * RETURNS
646 * Success: TRUE. IsMember is TRUE if TokenHandle is a member, FALSE otherwise.
647 * Failure: FALSE.
649 BOOL WINAPI
650 CheckTokenMembership( HANDLE token, PSID sid_to_check,
651 PBOOL is_member )
653 PTOKEN_GROUPS token_groups = NULL;
654 HANDLE thread_token = NULL;
655 DWORD size, i;
656 BOOL ret;
658 TRACE("(%p %s %p)\n", token, debugstr_sid(sid_to_check), is_member);
660 *is_member = FALSE;
662 if (!token)
664 if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &thread_token))
666 HANDLE process_token;
667 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &process_token);
668 if (!ret)
669 goto exit;
670 ret = DuplicateTokenEx(process_token, TOKEN_QUERY,
671 NULL, SecurityImpersonation, TokenImpersonation,
672 &thread_token);
673 CloseHandle(process_token);
674 if (!ret)
675 goto exit;
677 token = thread_token;
679 else
681 TOKEN_TYPE type;
683 ret = GetTokenInformation(token, TokenType, &type, sizeof(TOKEN_TYPE), &size);
684 if (!ret) goto exit;
686 if (type == TokenPrimary)
688 SetLastError(ERROR_NO_IMPERSONATION_TOKEN);
689 return FALSE;
693 ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size);
694 if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
695 goto exit;
697 token_groups = heap_alloc(size);
698 if (!token_groups)
700 ret = FALSE;
701 goto exit;
704 ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size);
705 if (!ret)
706 goto exit;
708 for (i = 0; i < token_groups->GroupCount; i++)
710 TRACE("Groups[%d]: {0x%x, %s}\n", i,
711 token_groups->Groups[i].Attributes,
712 debugstr_sid(token_groups->Groups[i].Sid));
713 if ((token_groups->Groups[i].Attributes & SE_GROUP_ENABLED) &&
714 EqualSid(sid_to_check, token_groups->Groups[i].Sid))
716 *is_member = TRUE;
717 TRACE("sid enabled and found in token\n");
718 break;
722 exit:
723 heap_free(token_groups);
724 if (thread_token != NULL) CloseHandle(thread_token);
726 return ret;
729 /******************************************************************************
730 * GetTokenInformation [ADVAPI32.@]
732 * Get a type of information about an access token.
734 * PARAMS
735 * token [I] Handle from OpenProcessToken() or OpenThreadToken()
736 * tokeninfoclass [I] A TOKEN_INFORMATION_CLASS from "winnt.h"
737 * tokeninfo [O] Destination for token information
738 * tokeninfolength [I] Length of tokeninfo
739 * retlen [O] Destination for returned token information length
741 * RETURNS
742 * Success: TRUE. tokeninfo contains retlen bytes of token information
743 * Failure: FALSE.
745 * NOTES
746 * See NtQueryInformationToken.
748 BOOL WINAPI
749 GetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS tokeninfoclass,
750 LPVOID tokeninfo, DWORD tokeninfolength, LPDWORD retlen )
752 TRACE("(%p, %s, %p, %d, %p):\n",
753 token,
754 (tokeninfoclass == TokenUser) ? "TokenUser" :
755 (tokeninfoclass == TokenGroups) ? "TokenGroups" :
756 (tokeninfoclass == TokenPrivileges) ? "TokenPrivileges" :
757 (tokeninfoclass == TokenOwner) ? "TokenOwner" :
758 (tokeninfoclass == TokenPrimaryGroup) ? "TokenPrimaryGroup" :
759 (tokeninfoclass == TokenDefaultDacl) ? "TokenDefaultDacl" :
760 (tokeninfoclass == TokenSource) ? "TokenSource" :
761 (tokeninfoclass == TokenType) ? "TokenType" :
762 (tokeninfoclass == TokenImpersonationLevel) ? "TokenImpersonationLevel" :
763 (tokeninfoclass == TokenStatistics) ? "TokenStatistics" :
764 (tokeninfoclass == TokenRestrictedSids) ? "TokenRestrictedSids" :
765 (tokeninfoclass == TokenSessionId) ? "TokenSessionId" :
766 (tokeninfoclass == TokenGroupsAndPrivileges) ? "TokenGroupsAndPrivileges" :
767 (tokeninfoclass == TokenSessionReference) ? "TokenSessionReference" :
768 (tokeninfoclass == TokenSandBoxInert) ? "TokenSandBoxInert" :
769 "Unknown",
770 tokeninfo, tokeninfolength, retlen);
771 return set_ntstatus( NtQueryInformationToken( token, tokeninfoclass, tokeninfo,
772 tokeninfolength, retlen));
775 /******************************************************************************
776 * SetTokenInformation [ADVAPI32.@]
778 * Set information for an access token.
780 * PARAMS
781 * token [I] Handle from OpenProcessToken() or OpenThreadToken()
782 * tokeninfoclass [I] A TOKEN_INFORMATION_CLASS from "winnt.h"
783 * tokeninfo [I] Token information to set
784 * tokeninfolength [I] Length of tokeninfo
786 * RETURNS
787 * Success: TRUE. The information for the token is set to tokeninfo.
788 * Failure: FALSE.
790 BOOL WINAPI
791 SetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS tokeninfoclass,
792 LPVOID tokeninfo, DWORD tokeninfolength )
794 TRACE("(%p, %s, %p, %d): stub\n",
795 token,
796 (tokeninfoclass == TokenUser) ? "TokenUser" :
797 (tokeninfoclass == TokenGroups) ? "TokenGroups" :
798 (tokeninfoclass == TokenPrivileges) ? "TokenPrivileges" :
799 (tokeninfoclass == TokenOwner) ? "TokenOwner" :
800 (tokeninfoclass == TokenPrimaryGroup) ? "TokenPrimaryGroup" :
801 (tokeninfoclass == TokenDefaultDacl) ? "TokenDefaultDacl" :
802 (tokeninfoclass == TokenSource) ? "TokenSource" :
803 (tokeninfoclass == TokenType) ? "TokenType" :
804 (tokeninfoclass == TokenImpersonationLevel) ? "TokenImpersonationLevel" :
805 (tokeninfoclass == TokenStatistics) ? "TokenStatistics" :
806 (tokeninfoclass == TokenRestrictedSids) ? "TokenRestrictedSids" :
807 (tokeninfoclass == TokenSessionId) ? "TokenSessionId" :
808 (tokeninfoclass == TokenGroupsAndPrivileges) ? "TokenGroupsAndPrivileges" :
809 (tokeninfoclass == TokenSessionReference) ? "TokenSessionReference" :
810 (tokeninfoclass == TokenSandBoxInert) ? "TokenSandBoxInert" :
811 "Unknown",
812 tokeninfo, tokeninfolength);
814 return set_ntstatus( NtSetInformationToken( token, tokeninfoclass, tokeninfo, tokeninfolength ));
817 /*************************************************************************
818 * SetThreadToken [ADVAPI32.@]
820 * Assigns an 'impersonation token' to a thread so it can assume the
821 * security privileges of another thread or process. Can also remove
822 * a previously assigned token.
824 * PARAMS
825 * thread [O] Handle to thread to set the token for
826 * token [I] Token to set
828 * RETURNS
829 * Success: TRUE. The threads access token is set to token
830 * Failure: FALSE.
832 * NOTES
833 * Only supported on NT or higher. On Win9X this function does nothing.
834 * See SetTokenInformation.
836 BOOL WINAPI SetThreadToken(PHANDLE thread, HANDLE token)
838 return set_ntstatus( NtSetInformationThread( thread ? *thread : GetCurrentThread(),
839 ThreadImpersonationToken, &token, sizeof token ));
842 /*************************************************************************
843 * CreateRestrictedToken [ADVAPI32.@]
845 * Create a new more restricted token from an existing token.
847 * PARAMS
848 * baseToken [I] Token to base the new restricted token on
849 * flags [I] Options
850 * nDisableSids [I] Length of disableSids array
851 * disableSids [I] Array of SIDs to disable in the new token
852 * nDeletePrivs [I] Length of deletePrivs array
853 * deletePrivs [I] Array of privileges to delete in the new token
854 * nRestrictSids [I] Length of restrictSids array
855 * restrictSids [I] Array of SIDs to restrict in the new token
856 * newToken [O] Address where the new token is stored
858 * RETURNS
859 * Success: TRUE
860 * Failure: FALSE
862 BOOL WINAPI CreateRestrictedToken(
863 HANDLE baseToken,
864 DWORD flags,
865 DWORD nDisableSids,
866 PSID_AND_ATTRIBUTES disableSids,
867 DWORD nDeletePrivs,
868 PLUID_AND_ATTRIBUTES deletePrivs,
869 DWORD nRestrictSids,
870 PSID_AND_ATTRIBUTES restrictSids,
871 PHANDLE newToken)
873 TOKEN_TYPE type;
874 SECURITY_IMPERSONATION_LEVEL level = TokenImpersonationLevel;
875 DWORD size;
877 FIXME("(%p, 0x%x, %u, %p, %u, %p, %u, %p, %p): stub\n",
878 baseToken, flags, nDisableSids, disableSids,
879 nDeletePrivs, deletePrivs,
880 nRestrictSids, restrictSids,
881 newToken);
883 size = sizeof(type);
884 if (!GetTokenInformation( baseToken, TokenType, &type, size, &size )) return FALSE;
885 if (type == TokenImpersonation)
887 size = sizeof(level);
888 if (!GetTokenInformation( baseToken, TokenImpersonationLevel, &level, size, &size ))
889 return FALSE;
891 return DuplicateTokenEx( baseToken, MAXIMUM_ALLOWED, NULL, level, type, newToken );
894 /* ##############################
895 ###### SID FUNCTIONS ######
896 ##############################
899 /******************************************************************************
900 * AllocateAndInitializeSid [ADVAPI32.@]
902 * PARAMS
903 * pIdentifierAuthority []
904 * nSubAuthorityCount []
905 * nSubAuthority0 []
906 * nSubAuthority1 []
907 * nSubAuthority2 []
908 * nSubAuthority3 []
909 * nSubAuthority4 []
910 * nSubAuthority5 []
911 * nSubAuthority6 []
912 * nSubAuthority7 []
913 * pSid []
915 BOOL WINAPI
916 AllocateAndInitializeSid( PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
917 BYTE nSubAuthorityCount,
918 DWORD nSubAuthority0, DWORD nSubAuthority1,
919 DWORD nSubAuthority2, DWORD nSubAuthority3,
920 DWORD nSubAuthority4, DWORD nSubAuthority5,
921 DWORD nSubAuthority6, DWORD nSubAuthority7,
922 PSID *pSid )
924 return set_ntstatus( RtlAllocateAndInitializeSid(
925 pIdentifierAuthority, nSubAuthorityCount,
926 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
927 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7,
928 pSid ));
931 /******************************************************************************
932 * FreeSid [ADVAPI32.@]
934 * PARAMS
935 * pSid []
937 PVOID WINAPI
938 FreeSid( PSID pSid )
940 RtlFreeSid(pSid);
941 return NULL; /* is documented like this */
944 /******************************************************************************
945 * CopySid [ADVAPI32.@]
947 * PARAMS
948 * nDestinationSidLength []
949 * pDestinationSid []
950 * pSourceSid []
952 BOOL WINAPI
953 CopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
955 return RtlCopySid(nDestinationSidLength, pDestinationSid, pSourceSid);
958 /******************************************************************************
959 * CreateWellKnownSid [ADVAPI32.@]
961 BOOL WINAPI
962 CreateWellKnownSid( WELL_KNOWN_SID_TYPE WellKnownSidType,
963 PSID DomainSid,
964 PSID pSid,
965 DWORD* cbSid)
967 unsigned int i;
968 TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
970 if (cbSid == NULL || (DomainSid && !IsValidSid(DomainSid)))
972 SetLastError(ERROR_INVALID_PARAMETER);
973 return FALSE;
976 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) {
977 if (WellKnownSids[i].Type == WellKnownSidType) {
978 DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
980 if (*cbSid < length)
982 *cbSid = length;
983 SetLastError(ERROR_INSUFFICIENT_BUFFER);
984 return FALSE;
986 if (!pSid)
988 SetLastError(ERROR_INVALID_PARAMETER);
989 return FALSE;
991 CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
992 *cbSid = length;
993 return TRUE;
997 if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES)
999 SetLastError(ERROR_INVALID_PARAMETER);
1000 return FALSE;
1003 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
1004 if (WellKnownRids[i].Type == WellKnownSidType) {
1005 UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid);
1006 DWORD domain_sid_length = GetSidLengthRequired(domain_subauth);
1007 DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1);
1009 if (*cbSid < output_sid_length)
1011 *cbSid = output_sid_length;
1012 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1013 return FALSE;
1015 if (!pSid)
1017 SetLastError(ERROR_INVALID_PARAMETER);
1018 return FALSE;
1020 CopyMemory(pSid, DomainSid, domain_sid_length);
1021 (*GetSidSubAuthorityCount(pSid))++;
1022 (*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid;
1023 *cbSid = output_sid_length;
1024 return TRUE;
1027 SetLastError(ERROR_INVALID_PARAMETER);
1028 return FALSE;
1031 /******************************************************************************
1032 * IsWellKnownSid [ADVAPI32.@]
1034 BOOL WINAPI
1035 IsWellKnownSid( PSID pSid, WELL_KNOWN_SID_TYPE WellKnownSidType )
1037 unsigned int i;
1038 TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
1040 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
1041 if (WellKnownSids[i].Type == WellKnownSidType)
1042 if (EqualSid(pSid, (PSID)&(WellKnownSids[i].Sid.Revision)))
1043 return TRUE;
1045 return FALSE;
1048 BOOL WINAPI
1049 IsTokenRestricted( HANDLE TokenHandle )
1051 TOKEN_GROUPS *groups;
1052 DWORD size;
1053 NTSTATUS status;
1054 BOOL restricted;
1056 TRACE("(%p)\n", TokenHandle);
1058 status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, NULL, 0, &size);
1059 if (status != STATUS_BUFFER_TOO_SMALL)
1060 return FALSE;
1062 groups = heap_alloc(size);
1063 if (!groups)
1065 SetLastError(ERROR_OUTOFMEMORY);
1066 return FALSE;
1069 status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, groups, size, &size);
1070 if (status != STATUS_SUCCESS)
1072 heap_free(groups);
1073 return set_ntstatus(status);
1076 restricted = groups->GroupCount > 0;
1077 heap_free(groups);
1079 return restricted;
1082 /******************************************************************************
1083 * IsValidSid [ADVAPI32.@]
1085 * PARAMS
1086 * pSid []
1088 BOOL WINAPI
1089 IsValidSid( PSID pSid )
1091 return RtlValidSid( pSid );
1094 /******************************************************************************
1095 * EqualSid [ADVAPI32.@]
1097 * PARAMS
1098 * pSid1 []
1099 * pSid2 []
1101 BOOL WINAPI
1102 EqualSid( PSID pSid1, PSID pSid2 )
1104 BOOL ret = RtlEqualSid( pSid1, pSid2 );
1105 SetLastError(ERROR_SUCCESS);
1106 return ret;
1109 /******************************************************************************
1110 * EqualPrefixSid [ADVAPI32.@]
1112 BOOL WINAPI EqualPrefixSid (PSID pSid1, PSID pSid2)
1114 return RtlEqualPrefixSid(pSid1, pSid2);
1117 /******************************************************************************
1118 * GetSidLengthRequired [ADVAPI32.@]
1120 * PARAMS
1121 * nSubAuthorityCount []
1123 DWORD WINAPI
1124 GetSidLengthRequired( BYTE nSubAuthorityCount )
1126 return RtlLengthRequiredSid(nSubAuthorityCount);
1129 /******************************************************************************
1130 * InitializeSid [ADVAPI32.@]
1132 * PARAMS
1133 * pIdentifierAuthority []
1135 BOOL WINAPI
1136 InitializeSid (
1137 PSID pSid,
1138 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
1139 BYTE nSubAuthorityCount)
1141 return RtlInitializeSid(pSid, pIdentifierAuthority, nSubAuthorityCount);
1144 DWORD WINAPI
1145 GetEffectiveRightsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pAccessRights )
1147 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
1149 *pAccessRights = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
1150 return 0;
1153 DWORD WINAPI
1154 GetEffectiveRightsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pAccessRights )
1156 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
1158 return 1;
1161 /******************************************************************************
1162 * GetSidIdentifierAuthority [ADVAPI32.@]
1164 * PARAMS
1165 * pSid []
1167 PSID_IDENTIFIER_AUTHORITY WINAPI
1168 GetSidIdentifierAuthority( PSID pSid )
1170 return RtlIdentifierAuthoritySid(pSid);
1173 /******************************************************************************
1174 * GetSidSubAuthority [ADVAPI32.@]
1176 * PARAMS
1177 * pSid []
1178 * nSubAuthority []
1180 PDWORD WINAPI
1181 GetSidSubAuthority( PSID pSid, DWORD nSubAuthority )
1183 SetLastError(ERROR_SUCCESS);
1184 return RtlSubAuthoritySid(pSid, nSubAuthority);
1187 /******************************************************************************
1188 * GetSidSubAuthorityCount [ADVAPI32.@]
1190 * PARAMS
1191 * pSid []
1193 PUCHAR WINAPI
1194 GetSidSubAuthorityCount (PSID pSid)
1196 SetLastError(ERROR_SUCCESS);
1197 return RtlSubAuthorityCountSid(pSid);
1200 /******************************************************************************
1201 * GetLengthSid [ADVAPI32.@]
1203 * PARAMS
1204 * pSid []
1206 DWORD WINAPI
1207 GetLengthSid (PSID pSid)
1209 return RtlLengthSid(pSid);
1212 /* ##############################################
1213 ###### SECURITY DESCRIPTOR FUNCTIONS ######
1214 ##############################################
1217 /******************************************************************************
1218 * BuildSecurityDescriptorA [ADVAPI32.@]
1220 * Builds a SD from
1222 * PARAMS
1223 * pOwner [I]
1224 * pGroup [I]
1225 * cCountOfAccessEntries [I]
1226 * pListOfAccessEntries [I]
1227 * cCountOfAuditEntries [I]
1228 * pListofAuditEntries [I]
1229 * pOldSD [I]
1230 * lpdwBufferLength [I/O]
1231 * pNewSD [O]
1233 * RETURNS
1234 * Success: ERROR_SUCCESS
1235 * Failure: nonzero error code from Winerror.h
1237 DWORD WINAPI BuildSecurityDescriptorA(
1238 IN PTRUSTEEA pOwner,
1239 IN PTRUSTEEA pGroup,
1240 IN ULONG cCountOfAccessEntries,
1241 IN PEXPLICIT_ACCESSA pListOfAccessEntries,
1242 IN ULONG cCountOfAuditEntries,
1243 IN PEXPLICIT_ACCESSA pListofAuditEntries,
1244 IN PSECURITY_DESCRIPTOR pOldSD,
1245 IN OUT PULONG lpdwBufferLength,
1246 OUT PSECURITY_DESCRIPTOR* pNewSD)
1248 FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
1249 cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
1250 pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
1252 return ERROR_CALL_NOT_IMPLEMENTED;
1255 /******************************************************************************
1256 * BuildSecurityDescriptorW [ADVAPI32.@]
1258 * See BuildSecurityDescriptorA.
1260 DWORD WINAPI BuildSecurityDescriptorW(
1261 IN PTRUSTEEW pOwner,
1262 IN PTRUSTEEW pGroup,
1263 IN ULONG cCountOfAccessEntries,
1264 IN PEXPLICIT_ACCESSW pListOfAccessEntries,
1265 IN ULONG cCountOfAuditEntries,
1266 IN PEXPLICIT_ACCESSW pListofAuditEntries,
1267 IN PSECURITY_DESCRIPTOR pOldSD,
1268 IN OUT PULONG lpdwBufferLength,
1269 OUT PSECURITY_DESCRIPTOR* pNewSD)
1271 FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
1272 cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
1273 pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
1275 return ERROR_CALL_NOT_IMPLEMENTED;
1278 /******************************************************************************
1279 * InitializeSecurityDescriptor [ADVAPI32.@]
1281 * PARAMS
1282 * pDescr []
1283 * revision []
1285 BOOL WINAPI
1286 InitializeSecurityDescriptor( PSECURITY_DESCRIPTOR pDescr, DWORD revision )
1288 return set_ntstatus( RtlCreateSecurityDescriptor(pDescr, revision ));
1292 /******************************************************************************
1293 * MakeAbsoluteSD [ADVAPI32.@]
1295 BOOL WINAPI MakeAbsoluteSD (
1296 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
1297 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
1298 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
1299 OUT PACL pDacl,
1300 OUT LPDWORD lpdwDaclSize,
1301 OUT PACL pSacl,
1302 OUT LPDWORD lpdwSaclSize,
1303 OUT PSID pOwner,
1304 OUT LPDWORD lpdwOwnerSize,
1305 OUT PSID pPrimaryGroup,
1306 OUT LPDWORD lpdwPrimaryGroupSize)
1308 return set_ntstatus( RtlSelfRelativeToAbsoluteSD(pSelfRelativeSecurityDescriptor,
1309 pAbsoluteSecurityDescriptor,
1310 lpdwAbsoluteSecurityDescriptorSize,
1311 pDacl, lpdwDaclSize, pSacl, lpdwSaclSize,
1312 pOwner, lpdwOwnerSize,
1313 pPrimaryGroup, lpdwPrimaryGroupSize));
1316 /******************************************************************************
1317 * GetKernelObjectSecurity [ADVAPI32.@]
1319 BOOL WINAPI GetKernelObjectSecurity(
1320 HANDLE Handle,
1321 SECURITY_INFORMATION RequestedInformation,
1322 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1323 DWORD nLength,
1324 LPDWORD lpnLengthNeeded )
1326 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", Handle, RequestedInformation,
1327 pSecurityDescriptor, nLength, lpnLengthNeeded);
1329 return set_ntstatus( NtQuerySecurityObject(Handle, RequestedInformation, pSecurityDescriptor,
1330 nLength, lpnLengthNeeded ));
1333 /******************************************************************************
1334 * GetPrivateObjectSecurity [ADVAPI32.@]
1336 BOOL WINAPI GetPrivateObjectSecurity(
1337 PSECURITY_DESCRIPTOR ObjectDescriptor,
1338 SECURITY_INFORMATION SecurityInformation,
1339 PSECURITY_DESCRIPTOR ResultantDescriptor,
1340 DWORD DescriptorLength,
1341 PDWORD ReturnLength )
1343 SECURITY_DESCRIPTOR desc;
1344 BOOL defaulted, present;
1345 PACL pacl;
1346 PSID psid;
1348 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", ObjectDescriptor, SecurityInformation,
1349 ResultantDescriptor, DescriptorLength, ReturnLength);
1351 if (!InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION))
1352 return FALSE;
1354 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1356 if (!GetSecurityDescriptorOwner(ObjectDescriptor, &psid, &defaulted))
1357 return FALSE;
1358 SetSecurityDescriptorOwner(&desc, psid, defaulted);
1361 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1363 if (!GetSecurityDescriptorGroup(ObjectDescriptor, &psid, &defaulted))
1364 return FALSE;
1365 SetSecurityDescriptorGroup(&desc, psid, defaulted);
1368 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1370 if (!GetSecurityDescriptorDacl(ObjectDescriptor, &present, &pacl, &defaulted))
1371 return FALSE;
1372 SetSecurityDescriptorDacl(&desc, present, pacl, defaulted);
1375 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1377 if (!GetSecurityDescriptorSacl(ObjectDescriptor, &present, &pacl, &defaulted))
1378 return FALSE;
1379 SetSecurityDescriptorSacl(&desc, present, pacl, defaulted);
1382 *ReturnLength = DescriptorLength;
1383 return MakeSelfRelativeSD(&desc, ResultantDescriptor, ReturnLength);
1386 /******************************************************************************
1387 * GetSecurityDescriptorLength [ADVAPI32.@]
1389 DWORD WINAPI GetSecurityDescriptorLength( PSECURITY_DESCRIPTOR pDescr)
1391 return RtlLengthSecurityDescriptor(pDescr);
1394 /******************************************************************************
1395 * GetSecurityDescriptorOwner [ADVAPI32.@]
1397 * PARAMS
1398 * pOwner []
1399 * lpbOwnerDefaulted []
1401 BOOL WINAPI
1402 GetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pDescr, PSID *pOwner,
1403 LPBOOL lpbOwnerDefaulted )
1405 BOOLEAN defaulted;
1406 BOOL ret = set_ntstatus( RtlGetOwnerSecurityDescriptor( pDescr, pOwner, &defaulted ));
1407 *lpbOwnerDefaulted = defaulted;
1408 return ret;
1411 /******************************************************************************
1412 * SetSecurityDescriptorOwner [ADVAPI32.@]
1414 * PARAMS
1416 BOOL WINAPI SetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1417 PSID pOwner, BOOL bOwnerDefaulted)
1419 return set_ntstatus( RtlSetOwnerSecurityDescriptor(pSecurityDescriptor, pOwner, bOwnerDefaulted));
1421 /******************************************************************************
1422 * GetSecurityDescriptorGroup [ADVAPI32.@]
1424 BOOL WINAPI GetSecurityDescriptorGroup(
1425 PSECURITY_DESCRIPTOR SecurityDescriptor,
1426 PSID *Group,
1427 LPBOOL GroupDefaulted)
1429 BOOLEAN defaulted;
1430 BOOL ret = set_ntstatus( RtlGetGroupSecurityDescriptor(SecurityDescriptor, Group, &defaulted ));
1431 *GroupDefaulted = defaulted;
1432 return ret;
1434 /******************************************************************************
1435 * SetSecurityDescriptorGroup [ADVAPI32.@]
1437 BOOL WINAPI SetSecurityDescriptorGroup ( PSECURITY_DESCRIPTOR SecurityDescriptor,
1438 PSID Group, BOOL GroupDefaulted)
1440 return set_ntstatus( RtlSetGroupSecurityDescriptor( SecurityDescriptor, Group, GroupDefaulted));
1443 /******************************************************************************
1444 * IsValidSecurityDescriptor [ADVAPI32.@]
1446 * PARAMS
1447 * lpsecdesc []
1449 BOOL WINAPI
1450 IsValidSecurityDescriptor( PSECURITY_DESCRIPTOR SecurityDescriptor )
1452 return set_ntstatus( RtlValidSecurityDescriptor(SecurityDescriptor));
1455 /******************************************************************************
1456 * GetSecurityDescriptorDacl [ADVAPI32.@]
1458 BOOL WINAPI GetSecurityDescriptorDacl(
1459 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
1460 OUT LPBOOL lpbDaclPresent,
1461 OUT PACL *pDacl,
1462 OUT LPBOOL lpbDaclDefaulted)
1464 BOOLEAN present, defaulted;
1465 BOOL ret = set_ntstatus( RtlGetDaclSecurityDescriptor(pSecurityDescriptor, &present, pDacl, &defaulted));
1466 *lpbDaclPresent = present;
1467 *lpbDaclDefaulted = defaulted;
1468 return ret;
1471 /******************************************************************************
1472 * SetSecurityDescriptorDacl [ADVAPI32.@]
1474 BOOL WINAPI
1475 SetSecurityDescriptorDacl (
1476 PSECURITY_DESCRIPTOR lpsd,
1477 BOOL daclpresent,
1478 PACL dacl,
1479 BOOL dacldefaulted )
1481 return set_ntstatus( RtlSetDaclSecurityDescriptor (lpsd, daclpresent, dacl, dacldefaulted ) );
1483 /******************************************************************************
1484 * GetSecurityDescriptorSacl [ADVAPI32.@]
1486 BOOL WINAPI GetSecurityDescriptorSacl(
1487 IN PSECURITY_DESCRIPTOR lpsd,
1488 OUT LPBOOL lpbSaclPresent,
1489 OUT PACL *pSacl,
1490 OUT LPBOOL lpbSaclDefaulted)
1492 BOOLEAN present, defaulted;
1493 BOOL ret = set_ntstatus( RtlGetSaclSecurityDescriptor(lpsd, &present, pSacl, &defaulted) );
1494 *lpbSaclPresent = present;
1495 *lpbSaclDefaulted = defaulted;
1496 return ret;
1499 /**************************************************************************
1500 * SetSecurityDescriptorSacl [ADVAPI32.@]
1502 BOOL WINAPI SetSecurityDescriptorSacl (
1503 PSECURITY_DESCRIPTOR lpsd,
1504 BOOL saclpresent,
1505 PACL lpsacl,
1506 BOOL sacldefaulted)
1508 return set_ntstatus (RtlSetSaclSecurityDescriptor(lpsd, saclpresent, lpsacl, sacldefaulted));
1510 /******************************************************************************
1511 * MakeSelfRelativeSD [ADVAPI32.@]
1513 * PARAMS
1514 * lpabssecdesc []
1515 * lpselfsecdesc []
1516 * lpbuflen []
1518 BOOL WINAPI
1519 MakeSelfRelativeSD(
1520 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
1521 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
1522 IN OUT LPDWORD lpdwBufferLength)
1524 return set_ntstatus( RtlMakeSelfRelativeSD( pAbsoluteSecurityDescriptor,
1525 pSelfRelativeSecurityDescriptor, lpdwBufferLength));
1528 /******************************************************************************
1529 * GetSecurityDescriptorControl [ADVAPI32.@]
1532 BOOL WINAPI GetSecurityDescriptorControl ( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1533 PSECURITY_DESCRIPTOR_CONTROL pControl, LPDWORD lpdwRevision)
1535 return set_ntstatus( RtlGetControlSecurityDescriptor(pSecurityDescriptor,pControl,lpdwRevision));
1538 /******************************************************************************
1539 * SetSecurityDescriptorControl [ADVAPI32.@]
1541 BOOL WINAPI SetSecurityDescriptorControl( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1542 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1543 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet )
1545 return set_ntstatus( RtlSetControlSecurityDescriptor(
1546 pSecurityDescriptor, ControlBitsOfInterest, ControlBitsToSet ) );
1549 /******************************************************************************
1550 * GetWindowsAccountDomainSid [ADVAPI32.@]
1552 BOOL WINAPI GetWindowsAccountDomainSid( PSID sid, PSID domain_sid, DWORD *size )
1554 SID_IDENTIFIER_AUTHORITY domain_ident = { SECURITY_NT_AUTHORITY };
1555 DWORD required_size;
1556 int i;
1558 FIXME( "(%p %p %p): semi-stub\n", sid, domain_sid, size );
1560 if (!sid || !IsValidSid( sid ))
1562 SetLastError( ERROR_INVALID_SID );
1563 return FALSE;
1566 if (!size)
1568 SetLastError( ERROR_INVALID_PARAMETER );
1569 return FALSE;
1572 if (*GetSidSubAuthorityCount( sid ) < 4)
1574 SetLastError( ERROR_INVALID_SID );
1575 return FALSE;
1578 required_size = GetSidLengthRequired( 4 );
1579 if (*size < required_size || !domain_sid)
1581 *size = required_size;
1582 SetLastError( domain_sid ? ERROR_INSUFFICIENT_BUFFER :
1583 ERROR_INVALID_PARAMETER );
1584 return FALSE;
1587 InitializeSid( domain_sid, &domain_ident, 4 );
1588 for (i = 0; i < 4; i++)
1589 *GetSidSubAuthority( domain_sid, i ) = *GetSidSubAuthority( sid, i );
1591 *size = required_size;
1592 return TRUE;
1595 /* ##############################
1596 ###### ACL FUNCTIONS ######
1597 ##############################
1600 /*************************************************************************
1601 * InitializeAcl [ADVAPI32.@]
1603 BOOL WINAPI InitializeAcl(PACL acl, DWORD size, DWORD rev)
1605 return set_ntstatus( RtlCreateAcl(acl, size, rev));
1608 BOOL WINAPI ImpersonateNamedPipeClient( HANDLE hNamedPipe )
1610 IO_STATUS_BLOCK io_block;
1612 TRACE("(%p)\n", hNamedPipe);
1614 return set_ntstatus( NtFsControlFile(hNamedPipe, NULL, NULL, NULL,
1615 &io_block, FSCTL_PIPE_IMPERSONATE, NULL, 0, NULL, 0) );
1618 /******************************************************************************
1619 * AddAccessAllowedAce [ADVAPI32.@]
1621 BOOL WINAPI AddAccessAllowedAce(
1622 IN OUT PACL pAcl,
1623 IN DWORD dwAceRevision,
1624 IN DWORD AccessMask,
1625 IN PSID pSid)
1627 return set_ntstatus(RtlAddAccessAllowedAce(pAcl, dwAceRevision, AccessMask, pSid));
1630 /******************************************************************************
1631 * AddAccessAllowedAceEx [ADVAPI32.@]
1633 BOOL WINAPI AddAccessAllowedAceEx(
1634 IN OUT PACL pAcl,
1635 IN DWORD dwAceRevision,
1636 IN DWORD AceFlags,
1637 IN DWORD AccessMask,
1638 IN PSID pSid)
1640 return set_ntstatus(RtlAddAccessAllowedAceEx(pAcl, dwAceRevision, AceFlags, AccessMask, pSid));
1643 /******************************************************************************
1644 * AddAccessDeniedAce [ADVAPI32.@]
1646 BOOL WINAPI AddAccessDeniedAce(
1647 IN OUT PACL pAcl,
1648 IN DWORD dwAceRevision,
1649 IN DWORD AccessMask,
1650 IN PSID pSid)
1652 return set_ntstatus(RtlAddAccessDeniedAce(pAcl, dwAceRevision, AccessMask, pSid));
1655 /******************************************************************************
1656 * AddAccessDeniedAceEx [ADVAPI32.@]
1658 BOOL WINAPI AddAccessDeniedAceEx(
1659 IN OUT PACL pAcl,
1660 IN DWORD dwAceRevision,
1661 IN DWORD AceFlags,
1662 IN DWORD AccessMask,
1663 IN PSID pSid)
1665 return set_ntstatus(RtlAddAccessDeniedAceEx(pAcl, dwAceRevision, AceFlags, AccessMask, pSid));
1668 /******************************************************************************
1669 * AddAce [ADVAPI32.@]
1671 BOOL WINAPI AddAce(
1672 IN OUT PACL pAcl,
1673 IN DWORD dwAceRevision,
1674 IN DWORD dwStartingAceIndex,
1675 LPVOID pAceList,
1676 DWORD nAceListLength)
1678 return set_ntstatus(RtlAddAce(pAcl, dwAceRevision, dwStartingAceIndex, pAceList, nAceListLength));
1681 BOOL WINAPI AddMandatoryAce(ACL *acl, DWORD ace_revision, DWORD ace_flags, DWORD mandatory_policy, PSID label_sid)
1683 FIXME("%p %x %x %x %p - stub\n", acl, ace_revision, ace_flags, mandatory_policy, label_sid);
1684 return FALSE;
1687 /******************************************************************************
1688 * DeleteAce [ADVAPI32.@]
1690 BOOL WINAPI DeleteAce(PACL pAcl, DWORD dwAceIndex)
1692 return set_ntstatus(RtlDeleteAce(pAcl, dwAceIndex));
1695 /******************************************************************************
1696 * FindFirstFreeAce [ADVAPI32.@]
1698 BOOL WINAPI FindFirstFreeAce(IN PACL pAcl, LPVOID * pAce)
1700 return RtlFirstFreeAce(pAcl, (PACE_HEADER *)pAce);
1703 /******************************************************************************
1704 * GetAce [ADVAPI32.@]
1706 BOOL WINAPI GetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1708 return set_ntstatus(RtlGetAce(pAcl, dwAceIndex, pAce));
1711 /******************************************************************************
1712 * GetAclInformation [ADVAPI32.@]
1714 BOOL WINAPI GetAclInformation(
1715 PACL pAcl,
1716 LPVOID pAclInformation,
1717 DWORD nAclInformationLength,
1718 ACL_INFORMATION_CLASS dwAclInformationClass)
1720 return set_ntstatus(RtlQueryInformationAcl(pAcl, pAclInformation,
1721 nAclInformationLength, dwAclInformationClass));
1724 /******************************************************************************
1725 * IsValidAcl [ADVAPI32.@]
1727 BOOL WINAPI IsValidAcl(IN PACL pAcl)
1729 return RtlValidAcl(pAcl);
1732 /* ##############################
1733 ###### MISC FUNCTIONS ######
1734 ##############################
1737 /******************************************************************************
1738 * AllocateLocallyUniqueId [ADVAPI32.@]
1740 * PARAMS
1741 * lpLuid []
1743 BOOL WINAPI AllocateLocallyUniqueId( PLUID lpLuid )
1745 return set_ntstatus(NtAllocateLocallyUniqueId(lpLuid));
1748 static const WCHAR SE_CREATE_TOKEN_NAME_W[] =
1749 { 'S','e','C','r','e','a','t','e','T','o','k','e','n','P','r','i','v','i','l','e','g','e',0 };
1750 static const WCHAR SE_ASSIGNPRIMARYTOKEN_NAME_W[] =
1751 { '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 };
1752 static const WCHAR SE_LOCK_MEMORY_NAME_W[] =
1753 { 'S','e','L','o','c','k','M','e','m','o','r','y','P','r','i','v','i','l','e','g','e',0 };
1754 static const WCHAR SE_INCREASE_QUOTA_NAME_W[] =
1755 { '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 };
1756 static const WCHAR SE_MACHINE_ACCOUNT_NAME_W[] =
1757 { '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 };
1758 static const WCHAR SE_TCB_NAME_W[] =
1759 { 'S','e','T','c','b','P','r','i','v','i','l','e','g','e',0 };
1760 static const WCHAR SE_SECURITY_NAME_W[] =
1761 { 'S','e','S','e','c','u','r','i','t','y','P','r','i','v','i','l','e','g','e',0 };
1762 static const WCHAR SE_TAKE_OWNERSHIP_NAME_W[] =
1763 { '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 };
1764 static const WCHAR SE_LOAD_DRIVER_NAME_W[] =
1765 { 'S','e','L','o','a','d','D','r','i','v','e','r','P','r','i','v','i','l','e','g','e',0 };
1766 static const WCHAR SE_SYSTEM_PROFILE_NAME_W[] =
1767 { '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 };
1768 static const WCHAR SE_SYSTEMTIME_NAME_W[] =
1769 { 'S','e','S','y','s','t','e','m','t','i','m','e','P','r','i','v','i','l','e','g','e',0 };
1770 static const WCHAR SE_PROF_SINGLE_PROCESS_NAME_W[] =
1771 { '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 };
1772 static const WCHAR SE_INC_BASE_PRIORITY_NAME_W[] =
1773 { '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 };
1774 static const WCHAR SE_CREATE_PAGEFILE_NAME_W[] =
1775 { '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 };
1776 static const WCHAR SE_CREATE_PERMANENT_NAME_W[] =
1777 { '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 };
1778 static const WCHAR SE_BACKUP_NAME_W[] =
1779 { 'S','e','B','a','c','k','u','p','P','r','i','v','i','l','e','g','e',0 };
1780 static const WCHAR SE_RESTORE_NAME_W[] =
1781 { 'S','e','R','e','s','t','o','r','e','P','r','i','v','i','l','e','g','e',0 };
1782 static const WCHAR SE_SHUTDOWN_NAME_W[] =
1783 { 'S','e','S','h','u','t','d','o','w','n','P','r','i','v','i','l','e','g','e',0 };
1784 static const WCHAR SE_DEBUG_NAME_W[] =
1785 { 'S','e','D','e','b','u','g','P','r','i','v','i','l','e','g','e',0 };
1786 static const WCHAR SE_AUDIT_NAME_W[] =
1787 { 'S','e','A','u','d','i','t','P','r','i','v','i','l','e','g','e',0 };
1788 static const WCHAR SE_SYSTEM_ENVIRONMENT_NAME_W[] =
1789 { '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 };
1790 static const WCHAR SE_CHANGE_NOTIFY_NAME_W[] =
1791 { 'S','e','C','h','a','n','g','e','N','o','t','i','f','y','P','r','i','v','i','l','e','g','e',0 };
1792 static const WCHAR SE_REMOTE_SHUTDOWN_NAME_W[] =
1793 { '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 };
1794 static const WCHAR SE_UNDOCK_NAME_W[] =
1795 { 'S','e','U','n','d','o','c','k','P','r','i','v','i','l','e','g','e',0 };
1796 static const WCHAR SE_SYNC_AGENT_NAME_W[] =
1797 { 'S','e','S','y','n','c','A','g','e','n','t','P','r','i','v','i','l','e','g','e',0 };
1798 static const WCHAR SE_ENABLE_DELEGATION_NAME_W[] =
1799 { '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 };
1800 static const WCHAR SE_MANAGE_VOLUME_NAME_W[] =
1801 { 'S','e','M','a','n','a','g','e','V','o','l','u','m','e','P','r','i','v','i','l','e','g','e',0 };
1802 static const WCHAR SE_IMPERSONATE_NAME_W[] =
1803 { 'S','e','I','m','p','e','r','s','o','n','a','t','e','P','r','i','v','i','l','e','g','e',0 };
1804 static const WCHAR SE_CREATE_GLOBAL_NAME_W[] =
1805 { 'S','e','C','r','e','a','t','e','G','l','o','b','a','l','P','r','i','v','i','l','e','g','e',0 };
1807 static const WCHAR * const WellKnownPrivNames[SE_MAX_WELL_KNOWN_PRIVILEGE + 1] =
1809 NULL,
1810 NULL,
1811 SE_CREATE_TOKEN_NAME_W,
1812 SE_ASSIGNPRIMARYTOKEN_NAME_W,
1813 SE_LOCK_MEMORY_NAME_W,
1814 SE_INCREASE_QUOTA_NAME_W,
1815 SE_MACHINE_ACCOUNT_NAME_W,
1816 SE_TCB_NAME_W,
1817 SE_SECURITY_NAME_W,
1818 SE_TAKE_OWNERSHIP_NAME_W,
1819 SE_LOAD_DRIVER_NAME_W,
1820 SE_SYSTEM_PROFILE_NAME_W,
1821 SE_SYSTEMTIME_NAME_W,
1822 SE_PROF_SINGLE_PROCESS_NAME_W,
1823 SE_INC_BASE_PRIORITY_NAME_W,
1824 SE_CREATE_PAGEFILE_NAME_W,
1825 SE_CREATE_PERMANENT_NAME_W,
1826 SE_BACKUP_NAME_W,
1827 SE_RESTORE_NAME_W,
1828 SE_SHUTDOWN_NAME_W,
1829 SE_DEBUG_NAME_W,
1830 SE_AUDIT_NAME_W,
1831 SE_SYSTEM_ENVIRONMENT_NAME_W,
1832 SE_CHANGE_NOTIFY_NAME_W,
1833 SE_REMOTE_SHUTDOWN_NAME_W,
1834 SE_UNDOCK_NAME_W,
1835 SE_SYNC_AGENT_NAME_W,
1836 SE_ENABLE_DELEGATION_NAME_W,
1837 SE_MANAGE_VOLUME_NAME_W,
1838 SE_IMPERSONATE_NAME_W,
1839 SE_CREATE_GLOBAL_NAME_W,
1842 /******************************************************************************
1843 * LookupPrivilegeValueW [ADVAPI32.@]
1845 * See LookupPrivilegeValueA.
1847 BOOL WINAPI
1848 LookupPrivilegeValueW( LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid )
1850 UINT i;
1852 TRACE("%s,%s,%p\n",debugstr_w(lpSystemName), debugstr_w(lpName), lpLuid);
1854 if (!ADVAPI_IsLocalComputer(lpSystemName))
1856 SetLastError(RPC_S_SERVER_UNAVAILABLE);
1857 return FALSE;
1859 if (!lpName)
1861 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1862 return FALSE;
1864 for( i=SE_MIN_WELL_KNOWN_PRIVILEGE; i<=SE_MAX_WELL_KNOWN_PRIVILEGE; i++ )
1866 if( !WellKnownPrivNames[i] )
1867 continue;
1868 if( strcmpiW( WellKnownPrivNames[i], lpName) )
1869 continue;
1870 lpLuid->LowPart = i;
1871 lpLuid->HighPart = 0;
1872 TRACE( "%s -> %08x-%08x\n",debugstr_w( lpSystemName ),
1873 lpLuid->HighPart, lpLuid->LowPart );
1874 return TRUE;
1876 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1877 return FALSE;
1880 /******************************************************************************
1881 * LookupPrivilegeValueA [ADVAPI32.@]
1883 * Retrieves LUID used on a system to represent the privilege name.
1885 * PARAMS
1886 * lpSystemName [I] Name of the system
1887 * lpName [I] Name of the privilege
1888 * lpLuid [O] Destination for the resulting LUID
1890 * RETURNS
1891 * Success: TRUE. lpLuid contains the requested LUID.
1892 * Failure: FALSE.
1894 BOOL WINAPI
1895 LookupPrivilegeValueA( LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid )
1897 UNICODE_STRING lpSystemNameW;
1898 UNICODE_STRING lpNameW;
1899 BOOL ret;
1901 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1902 RtlCreateUnicodeStringFromAsciiz(&lpNameW,lpName);
1903 ret = LookupPrivilegeValueW(lpSystemNameW.Buffer, lpNameW.Buffer, lpLuid);
1904 RtlFreeUnicodeString(&lpNameW);
1905 RtlFreeUnicodeString(&lpSystemNameW);
1906 return ret;
1909 BOOL WINAPI LookupPrivilegeDisplayNameA( LPCSTR lpSystemName, LPCSTR lpName, LPSTR lpDisplayName,
1910 LPDWORD cchDisplayName, LPDWORD lpLanguageId )
1912 FIXME("%s %s %s %p %p - stub\n", debugstr_a(lpSystemName), debugstr_a(lpName),
1913 debugstr_a(lpDisplayName), cchDisplayName, lpLanguageId);
1915 return FALSE;
1918 BOOL WINAPI LookupPrivilegeDisplayNameW( LPCWSTR lpSystemName, LPCWSTR lpName, LPWSTR lpDisplayName,
1919 LPDWORD cchDisplayName, LPDWORD lpLanguageId )
1921 FIXME("%s %s %s %p %p - stub\n", debugstr_w(lpSystemName), debugstr_w(lpName),
1922 debugstr_w(lpDisplayName), cchDisplayName, lpLanguageId);
1924 return FALSE;
1927 /******************************************************************************
1928 * LookupPrivilegeNameA [ADVAPI32.@]
1930 * See LookupPrivilegeNameW.
1932 BOOL WINAPI
1933 LookupPrivilegeNameA( LPCSTR lpSystemName, PLUID lpLuid, LPSTR lpName,
1934 LPDWORD cchName)
1936 UNICODE_STRING lpSystemNameW;
1937 BOOL ret;
1938 DWORD wLen = 0;
1940 TRACE("%s %p %p %p\n", debugstr_a(lpSystemName), lpLuid, lpName, cchName);
1942 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1943 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, NULL, &wLen);
1944 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1946 LPWSTR lpNameW = heap_alloc(wLen * sizeof(WCHAR));
1948 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, lpNameW,
1949 &wLen);
1950 if (ret)
1952 /* Windows crashes if cchName is NULL, so will I */
1953 unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName,
1954 *cchName, NULL, NULL);
1956 if (len == 0)
1958 /* WideCharToMultiByte failed */
1959 ret = FALSE;
1961 else if (len > *cchName)
1963 *cchName = len;
1964 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1965 ret = FALSE;
1967 else
1969 /* WideCharToMultiByte succeeded, output length needs to be
1970 * length not including NULL terminator
1972 *cchName = len - 1;
1975 heap_free(lpNameW);
1977 RtlFreeUnicodeString(&lpSystemNameW);
1978 return ret;
1981 /******************************************************************************
1982 * LookupPrivilegeNameW [ADVAPI32.@]
1984 * Retrieves the privilege name referred to by the LUID lpLuid.
1986 * PARAMS
1987 * lpSystemName [I] Name of the system
1988 * lpLuid [I] Privilege value
1989 * lpName [O] Name of the privilege
1990 * cchName [I/O] Number of characters in lpName.
1992 * RETURNS
1993 * Success: TRUE. lpName contains the name of the privilege whose value is
1994 * *lpLuid.
1995 * Failure: FALSE.
1997 * REMARKS
1998 * Only well-known privilege names (those defined in winnt.h) can be retrieved
1999 * using this function.
2000 * If the length of lpName is too small, on return *cchName will contain the
2001 * number of WCHARs needed to contain the privilege, including the NULL
2002 * terminator, and GetLastError will return ERROR_INSUFFICIENT_BUFFER.
2003 * On success, *cchName will contain the number of characters stored in
2004 * lpName, NOT including the NULL terminator.
2006 BOOL WINAPI
2007 LookupPrivilegeNameW( LPCWSTR lpSystemName, PLUID lpLuid, LPWSTR lpName,
2008 LPDWORD cchName)
2010 size_t privNameLen;
2012 TRACE("%s,%p,%p,%p\n",debugstr_w(lpSystemName), lpLuid, lpName, cchName);
2014 if (!ADVAPI_IsLocalComputer(lpSystemName))
2016 SetLastError(RPC_S_SERVER_UNAVAILABLE);
2017 return FALSE;
2019 if (lpLuid->HighPart || (lpLuid->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
2020 lpLuid->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE))
2022 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
2023 return FALSE;
2025 privNameLen = strlenW(WellKnownPrivNames[lpLuid->LowPart]);
2026 /* Windows crashes if cchName is NULL, so will I */
2027 if (*cchName <= privNameLen)
2029 *cchName = privNameLen + 1;
2030 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2031 return FALSE;
2033 else
2035 strcpyW(lpName, WellKnownPrivNames[lpLuid->LowPart]);
2036 *cchName = privNameLen;
2037 return TRUE;
2041 /******************************************************************************
2042 * GetFileSecurityA [ADVAPI32.@]
2044 * Obtains Specified information about the security of a file or directory.
2046 * PARAMS
2047 * lpFileName [I] Name of the file to get info for
2048 * RequestedInformation [I] SE_ flags from "winnt.h"
2049 * pSecurityDescriptor [O] Destination for security information
2050 * nLength [I] Length of pSecurityDescriptor
2051 * lpnLengthNeeded [O] Destination for length of returned security information
2053 * RETURNS
2054 * Success: TRUE. pSecurityDescriptor contains the requested information.
2055 * Failure: FALSE. lpnLengthNeeded contains the required space to return the info.
2057 * NOTES
2058 * The information returned is constrained by the callers access rights and
2059 * privileges.
2061 BOOL WINAPI
2062 GetFileSecurityA( LPCSTR lpFileName,
2063 SECURITY_INFORMATION RequestedInformation,
2064 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2065 DWORD nLength, LPDWORD lpnLengthNeeded )
2067 BOOL r;
2068 LPWSTR name;
2070 name = SERV_dup(lpFileName);
2071 r = GetFileSecurityW( name, RequestedInformation, pSecurityDescriptor,
2072 nLength, lpnLengthNeeded );
2073 heap_free( name );
2075 return r;
2078 /******************************************************************************
2079 * GetFileSecurityW [ADVAPI32.@]
2081 * See GetFileSecurityA.
2083 BOOL WINAPI
2084 GetFileSecurityW( LPCWSTR lpFileName,
2085 SECURITY_INFORMATION RequestedInformation,
2086 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2087 DWORD nLength, LPDWORD lpnLengthNeeded )
2089 HANDLE hfile;
2090 NTSTATUS status;
2091 DWORD access = 0, err;
2093 TRACE("(%s,%d,%p,%d,%p)\n", debugstr_w(lpFileName),
2094 RequestedInformation, pSecurityDescriptor,
2095 nLength, lpnLengthNeeded);
2097 if (RequestedInformation & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|
2098 DACL_SECURITY_INFORMATION))
2099 access |= READ_CONTROL;
2100 if (RequestedInformation & SACL_SECURITY_INFORMATION)
2101 access |= ACCESS_SYSTEM_SECURITY;
2103 err = get_security_file( lpFileName, access, &hfile);
2104 if (err)
2106 SetLastError(err);
2107 return FALSE;
2110 status = NtQuerySecurityObject( hfile, RequestedInformation, pSecurityDescriptor,
2111 nLength, lpnLengthNeeded );
2112 CloseHandle( hfile );
2113 return set_ntstatus( status );
2117 /******************************************************************************
2118 * LookupAccountSidA [ADVAPI32.@]
2120 BOOL WINAPI
2121 LookupAccountSidA(
2122 IN LPCSTR system,
2123 IN PSID sid,
2124 OUT LPSTR account,
2125 IN OUT LPDWORD accountSize,
2126 OUT LPSTR domain,
2127 IN OUT LPDWORD domainSize,
2128 OUT PSID_NAME_USE name_use )
2130 DWORD len;
2131 BOOL r;
2132 LPWSTR systemW;
2133 LPWSTR accountW = NULL;
2134 LPWSTR domainW = NULL;
2135 DWORD accountSizeW = *accountSize;
2136 DWORD domainSizeW = *domainSize;
2138 systemW = SERV_dup(system);
2139 if (account)
2140 accountW = heap_alloc( accountSizeW * sizeof(WCHAR) );
2141 if (domain)
2142 domainW = heap_alloc( domainSizeW * sizeof(WCHAR) );
2144 r = LookupAccountSidW( systemW, sid, accountW, &accountSizeW, domainW, &domainSizeW, name_use );
2146 if (r) {
2147 if (accountW && *accountSize) {
2148 len = WideCharToMultiByte( CP_ACP, 0, accountW, -1, NULL, 0, NULL, NULL );
2149 WideCharToMultiByte( CP_ACP, 0, accountW, -1, account, len, NULL, NULL );
2150 *accountSize = len;
2151 } else
2152 *accountSize = accountSizeW + 1;
2154 if (domainW && *domainSize) {
2155 len = WideCharToMultiByte( CP_ACP, 0, domainW, -1, NULL, 0, NULL, NULL );
2156 WideCharToMultiByte( CP_ACP, 0, domainW, -1, domain, len, NULL, NULL );
2157 *domainSize = len;
2158 } else
2159 *domainSize = domainSizeW + 1;
2161 else
2163 *accountSize = accountSizeW + 1;
2164 *domainSize = domainSizeW + 1;
2167 heap_free( systemW );
2168 heap_free( accountW );
2169 heap_free( domainW );
2171 return r;
2174 /******************************************************************************
2175 * LookupAccountSidW [ADVAPI32.@]
2177 * PARAMS
2178 * system []
2179 * sid []
2180 * account []
2181 * accountSize []
2182 * domain []
2183 * domainSize []
2184 * name_use []
2187 BOOL WINAPI
2188 LookupAccountSidW(
2189 IN LPCWSTR system,
2190 IN PSID sid,
2191 OUT LPWSTR account,
2192 IN OUT LPDWORD accountSize,
2193 OUT LPWSTR domain,
2194 IN OUT LPDWORD domainSize,
2195 OUT PSID_NAME_USE name_use )
2197 unsigned int i, j;
2198 const WCHAR * ac = NULL;
2199 const WCHAR * dm = NULL;
2200 SID_NAME_USE use = 0;
2201 LPWSTR computer_name = NULL;
2202 LPWSTR account_name = NULL;
2204 TRACE("(%s,sid=%s,%p,%p(%u),%p,%p(%u),%p)\n",
2205 debugstr_w(system),debugstr_sid(sid),
2206 account,accountSize,accountSize?*accountSize:0,
2207 domain,domainSize,domainSize?*domainSize:0,
2208 name_use);
2210 if (!ADVAPI_IsLocalComputer(system)) {
2211 FIXME("Only local computer supported!\n");
2212 SetLastError(RPC_S_SERVER_UNAVAILABLE);
2213 return FALSE;
2216 /* check the well known SIDs first */
2217 for (i = 0; i <= WinAccountProtectedUsersSid; i++) {
2218 if (IsWellKnownSid(sid, i)) {
2219 for (j = 0; j < (sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0])); j++) {
2220 if (ACCOUNT_SIDS[j].type == i) {
2221 ac = ACCOUNT_SIDS[j].account;
2222 dm = ACCOUNT_SIDS[j].domain;
2223 use = ACCOUNT_SIDS[j].name_use;
2226 break;
2230 if (dm == NULL) {
2231 MAX_SID local;
2233 /* check for the local computer next */
2234 if (ADVAPI_GetComputerSid(&local)) {
2235 DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
2236 BOOL result;
2238 computer_name = heap_alloc(size * sizeof(WCHAR));
2239 result = GetComputerNameW(computer_name, &size);
2241 if (result) {
2242 if (EqualSid(sid, &local)) {
2243 dm = computer_name;
2244 ac = Blank;
2245 use = 3;
2246 } else {
2247 local.SubAuthorityCount++;
2249 if (EqualPrefixSid(sid, &local)) {
2250 dm = computer_name;
2251 use = 1;
2252 switch (((MAX_SID *)sid)->SubAuthority[4]) {
2253 case DOMAIN_USER_RID_ADMIN:
2254 ac = Administrator;
2255 break;
2256 case DOMAIN_USER_RID_GUEST:
2257 ac = Guest;
2258 break;
2259 case DOMAIN_GROUP_RID_ADMINS:
2260 ac = Domain_Admins;
2261 break;
2262 case DOMAIN_GROUP_RID_USERS:
2263 ac = Domain_Users;
2264 break;
2265 case DOMAIN_GROUP_RID_GUESTS:
2266 ac = Domain_Guests;
2267 break;
2268 case DOMAIN_GROUP_RID_COMPUTERS:
2269 ac = Domain_Computers;
2270 break;
2271 case DOMAIN_GROUP_RID_CONTROLLERS:
2272 ac = Domain_Controllers;
2273 break;
2274 case DOMAIN_GROUP_RID_CERT_ADMINS:
2275 ac = Cert_Publishers;
2276 break;
2277 case DOMAIN_GROUP_RID_SCHEMA_ADMINS:
2278 ac = Schema_Admins;
2279 break;
2280 case DOMAIN_GROUP_RID_ENTERPRISE_ADMINS:
2281 ac = Enterprise_Admins;
2282 break;
2283 case DOMAIN_GROUP_RID_POLICY_ADMINS:
2284 ac = Group_Policy_Creator_Owners;
2285 break;
2286 case DOMAIN_ALIAS_RID_RAS_SERVERS:
2287 ac = RAS_and_IAS_Servers;
2288 break;
2289 case 1000: /* first user account */
2290 size = UNLEN + 1;
2291 account_name = heap_alloc(size * sizeof(WCHAR));
2292 if (GetUserNameW(account_name, &size))
2293 ac = account_name;
2294 else
2295 dm = NULL;
2297 break;
2298 default:
2299 dm = NULL;
2300 break;
2308 if (dm) {
2309 DWORD ac_len = lstrlenW(ac);
2310 DWORD dm_len = lstrlenW(dm);
2311 BOOL status = TRUE;
2313 if (*accountSize > ac_len) {
2314 if (account)
2315 lstrcpyW(account, ac);
2317 if (*domainSize > dm_len) {
2318 if (domain)
2319 lstrcpyW(domain, dm);
2321 if ((*accountSize && *accountSize < ac_len) ||
2322 (!account && !*accountSize && ac_len) ||
2323 (*domainSize && *domainSize < dm_len) ||
2324 (!domain && !*domainSize && dm_len))
2326 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2327 status = FALSE;
2329 if (*domainSize)
2330 *domainSize = dm_len;
2331 else
2332 *domainSize = dm_len + 1;
2333 if (*accountSize)
2334 *accountSize = ac_len;
2335 else
2336 *accountSize = ac_len + 1;
2338 heap_free(account_name);
2339 heap_free(computer_name);
2340 if (status) *name_use = use;
2341 return status;
2344 heap_free(account_name);
2345 heap_free(computer_name);
2346 SetLastError(ERROR_NONE_MAPPED);
2347 return FALSE;
2350 /******************************************************************************
2351 * SetFileSecurityA [ADVAPI32.@]
2353 * See SetFileSecurityW.
2355 BOOL WINAPI SetFileSecurityA( LPCSTR lpFileName,
2356 SECURITY_INFORMATION RequestedInformation,
2357 PSECURITY_DESCRIPTOR pSecurityDescriptor)
2359 BOOL r;
2360 LPWSTR name;
2362 name = SERV_dup(lpFileName);
2363 r = SetFileSecurityW( name, RequestedInformation, pSecurityDescriptor );
2364 heap_free( name );
2366 return r;
2369 /******************************************************************************
2370 * SetFileSecurityW [ADVAPI32.@]
2372 * Sets the security of a file or directory.
2374 * PARAMS
2375 * lpFileName []
2376 * RequestedInformation []
2377 * pSecurityDescriptor []
2379 * RETURNS
2380 * Success: TRUE.
2381 * Failure: FALSE.
2383 BOOL WINAPI
2384 SetFileSecurityW( LPCWSTR lpFileName,
2385 SECURITY_INFORMATION RequestedInformation,
2386 PSECURITY_DESCRIPTOR pSecurityDescriptor )
2388 HANDLE file;
2389 DWORD access = 0, err;
2390 NTSTATUS status;
2392 TRACE("(%s, 0x%x, %p)\n", debugstr_w(lpFileName), RequestedInformation,
2393 pSecurityDescriptor );
2395 if (RequestedInformation & OWNER_SECURITY_INFORMATION ||
2396 RequestedInformation & GROUP_SECURITY_INFORMATION)
2397 access |= WRITE_OWNER;
2398 if (RequestedInformation & SACL_SECURITY_INFORMATION)
2399 access |= ACCESS_SYSTEM_SECURITY;
2400 if (RequestedInformation & DACL_SECURITY_INFORMATION)
2401 access |= WRITE_DAC;
2403 err = get_security_file( lpFileName, access, &file);
2404 if (err)
2406 SetLastError(err);
2407 return FALSE;
2410 status = NtSetSecurityObject( file, RequestedInformation, pSecurityDescriptor );
2411 CloseHandle( file );
2412 return set_ntstatus( status );
2415 /******************************************************************************
2416 * QueryWindows31FilesMigration [ADVAPI32.@]
2418 * PARAMS
2419 * x1 []
2421 BOOL WINAPI
2422 QueryWindows31FilesMigration( DWORD x1 )
2424 FIXME("(%d):stub\n",x1);
2425 return TRUE;
2428 /******************************************************************************
2429 * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@]
2431 * PARAMS
2432 * x1 []
2433 * x2 []
2434 * x3 []
2435 * x4 []
2437 BOOL WINAPI
2438 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3,
2439 DWORD x4 )
2441 FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4);
2442 return TRUE;
2445 /******************************************************************************
2446 * NotifyBootConfigStatus [ADVAPI32.@]
2448 * PARAMS
2449 * x1 []
2451 BOOL WINAPI
2452 NotifyBootConfigStatus( BOOL x1 )
2454 FIXME("(0x%08d):stub\n",x1);
2455 return TRUE;
2458 /******************************************************************************
2459 * RevertToSelf [ADVAPI32.@]
2461 * Ends the impersonation of a user.
2463 * PARAMS
2464 * void []
2466 * RETURNS
2467 * Success: TRUE.
2468 * Failure: FALSE.
2470 BOOL WINAPI
2471 RevertToSelf( void )
2473 HANDLE Token = NULL;
2474 return set_ntstatus( NtSetInformationThread( GetCurrentThread(),
2475 ThreadImpersonationToken, &Token, sizeof(Token) ) );
2478 /******************************************************************************
2479 * ImpersonateSelf [ADVAPI32.@]
2481 * Makes an impersonation token that represents the process user and assigns
2482 * to the current thread.
2484 * PARAMS
2485 * ImpersonationLevel [I] Level at which to impersonate.
2487 * RETURNS
2488 * Success: TRUE.
2489 * Failure: FALSE.
2491 BOOL WINAPI
2492 ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
2494 return set_ntstatus( RtlImpersonateSelf( ImpersonationLevel ) );
2497 /******************************************************************************
2498 * ImpersonateLoggedOnUser [ADVAPI32.@]
2500 BOOL WINAPI ImpersonateLoggedOnUser(HANDLE hToken)
2502 DWORD size;
2503 NTSTATUS Status;
2504 HANDLE ImpersonationToken;
2505 TOKEN_TYPE Type;
2506 static BOOL warn = TRUE;
2508 if (warn)
2510 FIXME( "(%p)\n", hToken );
2511 warn = FALSE;
2513 if (!GetTokenInformation( hToken, TokenType, &Type,
2514 sizeof(TOKEN_TYPE), &size ))
2515 return FALSE;
2517 if (Type == TokenPrimary)
2519 OBJECT_ATTRIBUTES ObjectAttributes;
2521 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
2523 Status = NtDuplicateToken( hToken,
2524 TOKEN_IMPERSONATE | TOKEN_QUERY,
2525 &ObjectAttributes,
2526 SecurityImpersonation,
2527 TokenImpersonation,
2528 &ImpersonationToken );
2529 if (Status != STATUS_SUCCESS)
2531 ERR( "NtDuplicateToken failed with error 0x%08x\n", Status );
2532 SetLastError( RtlNtStatusToDosError( Status ) );
2533 return FALSE;
2536 else
2537 ImpersonationToken = hToken;
2539 Status = NtSetInformationThread( GetCurrentThread(),
2540 ThreadImpersonationToken,
2541 &ImpersonationToken,
2542 sizeof(ImpersonationToken) );
2544 if (Type == TokenPrimary)
2545 NtClose( ImpersonationToken );
2547 if (Status != STATUS_SUCCESS)
2549 ERR( "NtSetInformationThread failed with error 0x%08x\n", Status );
2550 SetLastError( RtlNtStatusToDosError( Status ) );
2551 return FALSE;
2554 return TRUE;
2557 /******************************************************************************
2558 * ImpersonateAnonymousToken [ADVAPI32.@]
2560 BOOL WINAPI ImpersonateAnonymousToken( HANDLE thread )
2562 TRACE("(%p)\n", thread);
2563 return set_ntstatus( NtImpersonateAnonymousToken( thread ) );
2566 /******************************************************************************
2567 * AccessCheck [ADVAPI32.@]
2569 BOOL WINAPI
2570 AccessCheck(
2571 PSECURITY_DESCRIPTOR SecurityDescriptor,
2572 HANDLE ClientToken,
2573 DWORD DesiredAccess,
2574 PGENERIC_MAPPING GenericMapping,
2575 PPRIVILEGE_SET PrivilegeSet,
2576 LPDWORD PrivilegeSetLength,
2577 LPDWORD GrantedAccess,
2578 LPBOOL AccessStatus)
2580 NTSTATUS access_status;
2581 BOOL ret = set_ntstatus( NtAccessCheck(SecurityDescriptor, ClientToken, DesiredAccess,
2582 GenericMapping, PrivilegeSet, PrivilegeSetLength,
2583 GrantedAccess, &access_status) );
2584 if (ret) *AccessStatus = set_ntstatus( access_status );
2585 return ret;
2589 /******************************************************************************
2590 * AccessCheckByType [ADVAPI32.@]
2592 BOOL WINAPI AccessCheckByType(
2593 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2594 PSID PrincipalSelfSid,
2595 HANDLE ClientToken,
2596 DWORD DesiredAccess,
2597 POBJECT_TYPE_LIST ObjectTypeList,
2598 DWORD ObjectTypeListLength,
2599 PGENERIC_MAPPING GenericMapping,
2600 PPRIVILEGE_SET PrivilegeSet,
2601 LPDWORD PrivilegeSetLength,
2602 LPDWORD GrantedAccess,
2603 LPBOOL AccessStatus)
2605 FIXME("stub\n");
2607 *AccessStatus = TRUE;
2609 return !*AccessStatus;
2612 /******************************************************************************
2613 * MapGenericMask [ADVAPI32.@]
2615 * Maps generic access rights into specific access rights according to the
2616 * supplied mapping.
2618 * PARAMS
2619 * AccessMask [I/O] Access rights.
2620 * GenericMapping [I] The mapping between generic and specific rights.
2622 * RETURNS
2623 * Nothing.
2625 VOID WINAPI MapGenericMask( PDWORD AccessMask, PGENERIC_MAPPING GenericMapping )
2627 RtlMapGenericMask( AccessMask, GenericMapping );
2630 /*************************************************************************
2631 * SetKernelObjectSecurity [ADVAPI32.@]
2633 BOOL WINAPI SetKernelObjectSecurity (
2634 IN HANDLE Handle,
2635 IN SECURITY_INFORMATION SecurityInformation,
2636 IN PSECURITY_DESCRIPTOR SecurityDescriptor )
2638 return set_ntstatus (NtSetSecurityObject (Handle, SecurityInformation, SecurityDescriptor));
2642 /******************************************************************************
2643 * AddAuditAccessAce [ADVAPI32.@]
2645 BOOL WINAPI AddAuditAccessAce(
2646 IN OUT PACL pAcl,
2647 IN DWORD dwAceRevision,
2648 IN DWORD dwAccessMask,
2649 IN PSID pSid,
2650 IN BOOL bAuditSuccess,
2651 IN BOOL bAuditFailure)
2653 return set_ntstatus( RtlAddAuditAccessAce(pAcl, dwAceRevision, dwAccessMask, pSid,
2654 bAuditSuccess, bAuditFailure) );
2657 /******************************************************************************
2658 * AddAuditAccessAce [ADVAPI32.@]
2660 BOOL WINAPI AddAuditAccessAceEx(
2661 IN OUT PACL pAcl,
2662 IN DWORD dwAceRevision,
2663 IN DWORD dwAceFlags,
2664 IN DWORD dwAccessMask,
2665 IN PSID pSid,
2666 IN BOOL bAuditSuccess,
2667 IN BOOL bAuditFailure)
2669 return set_ntstatus( RtlAddAuditAccessAceEx(pAcl, dwAceRevision, dwAceFlags, dwAccessMask, pSid,
2670 bAuditSuccess, bAuditFailure) );
2673 /******************************************************************************
2674 * LookupAccountNameA [ADVAPI32.@]
2676 BOOL WINAPI
2677 LookupAccountNameA(
2678 IN LPCSTR system,
2679 IN LPCSTR account,
2680 OUT PSID sid,
2681 OUT LPDWORD cbSid,
2682 LPSTR ReferencedDomainName,
2683 IN OUT LPDWORD cbReferencedDomainName,
2684 OUT PSID_NAME_USE name_use )
2686 BOOL ret;
2687 UNICODE_STRING lpSystemW;
2688 UNICODE_STRING lpAccountW;
2689 LPWSTR lpReferencedDomainNameW = NULL;
2691 RtlCreateUnicodeStringFromAsciiz(&lpSystemW, system);
2692 RtlCreateUnicodeStringFromAsciiz(&lpAccountW, account);
2694 if (ReferencedDomainName)
2695 lpReferencedDomainNameW = heap_alloc(*cbReferencedDomainName * sizeof(WCHAR));
2697 ret = LookupAccountNameW(lpSystemW.Buffer, lpAccountW.Buffer, sid, cbSid, lpReferencedDomainNameW,
2698 cbReferencedDomainName, name_use);
2700 if (ret && lpReferencedDomainNameW)
2702 WideCharToMultiByte(CP_ACP, 0, lpReferencedDomainNameW, -1,
2703 ReferencedDomainName, *cbReferencedDomainName+1, NULL, NULL);
2706 RtlFreeUnicodeString(&lpSystemW);
2707 RtlFreeUnicodeString(&lpAccountW);
2708 heap_free(lpReferencedDomainNameW);
2710 return ret;
2713 /******************************************************************************
2714 * lookup_user_account_name
2716 static BOOL lookup_user_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2717 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2719 char buffer[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
2720 DWORD len = sizeof(buffer);
2721 HANDLE token;
2722 BOOL ret;
2723 PSID pSid;
2724 WCHAR domainName[MAX_COMPUTERNAME_LENGTH + 1];
2725 DWORD nameLen;
2727 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
2729 if (GetLastError() != ERROR_NO_TOKEN) return FALSE;
2730 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) return FALSE;
2733 ret = GetTokenInformation(token, TokenUser, buffer, len, &len);
2734 CloseHandle( token );
2736 if (!ret) return FALSE;
2738 pSid = ((TOKEN_USER *)buffer)->User.Sid;
2740 if (Sid != NULL && (*cbSid >= GetLengthSid(pSid)))
2741 CopySid(*cbSid, Sid, pSid);
2742 if (*cbSid < GetLengthSid(pSid))
2744 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2745 ret = FALSE;
2747 *cbSid = GetLengthSid(pSid);
2749 nameLen = MAX_COMPUTERNAME_LENGTH + 1;
2750 if (!GetComputerNameW(domainName, &nameLen))
2752 domainName[0] = 0;
2753 nameLen = 0;
2755 if (*cchReferencedDomainName <= nameLen || !ret)
2757 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2758 nameLen += 1;
2759 ret = FALSE;
2761 else if (ReferencedDomainName)
2762 strcpyW(ReferencedDomainName, domainName);
2764 *cchReferencedDomainName = nameLen;
2766 if (ret)
2767 *peUse = SidTypeUser;
2769 return ret;
2772 /******************************************************************************
2773 * lookup_computer_account_name
2775 static BOOL lookup_computer_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2776 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2778 MAX_SID local;
2779 BOOL ret;
2780 WCHAR domainName[MAX_COMPUTERNAME_LENGTH + 1];
2781 DWORD nameLen;
2783 if ((ret = ADVAPI_GetComputerSid(&local)))
2785 if (Sid != NULL && (*cbSid >= GetLengthSid(&local)))
2786 CopySid(*cbSid, Sid, &local);
2787 if (*cbSid < GetLengthSid(&local))
2789 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2790 ret = FALSE;
2792 *cbSid = GetLengthSid(&local);
2795 nameLen = MAX_COMPUTERNAME_LENGTH + 1;
2796 if (!GetComputerNameW(domainName, &nameLen))
2798 domainName[0] = 0;
2799 nameLen = 0;
2801 if (*cchReferencedDomainName <= nameLen || !ret)
2803 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2804 nameLen += 1;
2805 ret = FALSE;
2807 else if (ReferencedDomainName)
2808 strcpyW(ReferencedDomainName, domainName);
2810 *cchReferencedDomainName = nameLen;
2812 if (ret)
2813 *peUse = SidTypeDomain;
2815 return ret;
2818 static void split_domain_account( const LSA_UNICODE_STRING *str, LSA_UNICODE_STRING *account,
2819 LSA_UNICODE_STRING *domain )
2821 WCHAR *p = str->Buffer + str->Length / sizeof(WCHAR) - 1;
2823 while (p > str->Buffer && *p != '\\') p--;
2825 if (*p == '\\')
2827 domain->Buffer = str->Buffer;
2828 domain->Length = (p - str->Buffer) * sizeof(WCHAR);
2830 account->Buffer = p + 1;
2831 account->Length = str->Length - ((p - str->Buffer + 1) * sizeof(WCHAR));
2833 else
2835 domain->Buffer = NULL;
2836 domain->Length = 0;
2838 account->Buffer = str->Buffer;
2839 account->Length = str->Length;
2843 static BOOL match_domain( ULONG idx, const LSA_UNICODE_STRING *domain )
2845 ULONG len = strlenW( ACCOUNT_SIDS[idx].domain );
2847 if (len == domain->Length / sizeof(WCHAR) && !strncmpiW( domain->Buffer, ACCOUNT_SIDS[idx].domain, len ))
2848 return TRUE;
2850 return FALSE;
2853 static BOOL match_account( ULONG idx, const LSA_UNICODE_STRING *account )
2855 ULONG len = strlenW( ACCOUNT_SIDS[idx].account );
2857 if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].account, len ))
2858 return TRUE;
2860 if (ACCOUNT_SIDS[idx].alias)
2862 len = strlenW( ACCOUNT_SIDS[idx].alias );
2863 if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].alias, len ))
2864 return TRUE;
2866 return FALSE;
2870 * Helper function for LookupAccountNameW
2872 BOOL lookup_local_wellknown_name( const LSA_UNICODE_STRING *account_and_domain,
2873 PSID Sid, LPDWORD cbSid,
2874 LPWSTR ReferencedDomainName,
2875 LPDWORD cchReferencedDomainName,
2876 PSID_NAME_USE peUse, BOOL *handled )
2878 PSID pSid;
2879 LSA_UNICODE_STRING account, domain;
2880 BOOL ret = TRUE;
2881 ULONG i;
2883 *handled = FALSE;
2884 split_domain_account( account_and_domain, &account, &domain );
2886 for (i = 0; i < sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0]); i++)
2888 /* check domain first */
2889 if (domain.Buffer && !match_domain( i, &domain )) continue;
2891 if (match_account( i, &account ))
2893 DWORD len, sidLen = SECURITY_MAX_SID_SIZE;
2895 if (!(pSid = heap_alloc( sidLen ))) return FALSE;
2897 if ((ret = CreateWellKnownSid( ACCOUNT_SIDS[i].type, NULL, pSid, &sidLen )))
2899 if (*cbSid < sidLen)
2901 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2902 ret = FALSE;
2904 else if (Sid)
2906 CopySid(*cbSid, Sid, pSid);
2908 *cbSid = sidLen;
2911 len = strlenW( ACCOUNT_SIDS[i].domain );
2912 if (*cchReferencedDomainName <= len || !ret)
2914 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2915 len++;
2916 ret = FALSE;
2918 else if (ReferencedDomainName)
2920 strcpyW( ReferencedDomainName, ACCOUNT_SIDS[i].domain );
2923 *cchReferencedDomainName = len;
2924 if (ret)
2925 *peUse = ACCOUNT_SIDS[i].name_use;
2927 heap_free(pSid);
2928 *handled = TRUE;
2929 return ret;
2932 return ret;
2935 BOOL lookup_local_user_name( const LSA_UNICODE_STRING *account_and_domain,
2936 PSID Sid, LPDWORD cbSid,
2937 LPWSTR ReferencedDomainName,
2938 LPDWORD cchReferencedDomainName,
2939 PSID_NAME_USE peUse, BOOL *handled )
2941 DWORD nameLen;
2942 LPWSTR userName = NULL;
2943 LSA_UNICODE_STRING account, domain;
2944 BOOL ret = TRUE;
2946 *handled = FALSE;
2947 split_domain_account( account_and_domain, &account, &domain );
2949 /* Let the current Unix user id masquerade as first Windows user account */
2951 nameLen = UNLEN + 1;
2952 if (!(userName = heap_alloc( nameLen * sizeof(WCHAR) ))) return FALSE;
2954 if (domain.Buffer)
2956 /* check to make sure this account is on this computer */
2957 if (GetComputerNameW( userName, &nameLen ) &&
2958 (domain.Length / sizeof(WCHAR) != nameLen || strncmpW( domain.Buffer, userName, nameLen )))
2960 SetLastError(ERROR_NONE_MAPPED);
2961 ret = FALSE;
2963 nameLen = UNLEN + 1;
2966 if (GetUserNameW( userName, &nameLen ) &&
2967 account.Length / sizeof(WCHAR) == nameLen - 1 && !strncmpW( account.Buffer, userName, nameLen - 1 ))
2969 ret = lookup_user_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2970 *handled = TRUE;
2972 else
2974 nameLen = UNLEN + 1;
2975 if (GetComputerNameW( userName, &nameLen ) &&
2976 account.Length / sizeof(WCHAR) == nameLen && !strncmpW( account.Buffer, userName , nameLen ))
2978 ret = lookup_computer_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2979 *handled = TRUE;
2983 heap_free(userName);
2984 return ret;
2987 /******************************************************************************
2988 * LookupAccountNameW [ADVAPI32.@]
2990 BOOL WINAPI LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid,
2991 LPDWORD cbSid, LPWSTR ReferencedDomainName,
2992 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2994 BOOL ret, handled;
2995 LSA_UNICODE_STRING account;
2997 TRACE("%s %s %p %p %p %p %p\n", debugstr_w(lpSystemName), debugstr_w(lpAccountName),
2998 Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse);
3000 if (!ADVAPI_IsLocalComputer( lpSystemName ))
3002 FIXME("remote computer not supported\n");
3003 SetLastError( RPC_S_SERVER_UNAVAILABLE );
3004 return FALSE;
3007 if (!lpAccountName || !strcmpW( lpAccountName, Blank ))
3009 lpAccountName = BUILTIN;
3012 RtlInitUnicodeString( &account, lpAccountName );
3014 /* Check well known SIDs first */
3015 ret = lookup_local_wellknown_name( &account, Sid, cbSid, ReferencedDomainName,
3016 cchReferencedDomainName, peUse, &handled );
3017 if (handled)
3018 return ret;
3020 /* Check user names */
3021 ret = lookup_local_user_name( &account, Sid, cbSid, ReferencedDomainName,
3022 cchReferencedDomainName, peUse, &handled);
3023 if (handled)
3024 return ret;
3026 SetLastError( ERROR_NONE_MAPPED );
3027 return FALSE;
3030 /******************************************************************************
3031 * PrivilegeCheck [ADVAPI32.@]
3033 BOOL WINAPI PrivilegeCheck( HANDLE ClientToken, PPRIVILEGE_SET RequiredPrivileges, LPBOOL pfResult)
3035 BOOL ret;
3036 BOOLEAN Result;
3038 TRACE("%p %p %p\n", ClientToken, RequiredPrivileges, pfResult);
3040 ret = set_ntstatus (NtPrivilegeCheck (ClientToken, RequiredPrivileges, &Result));
3041 if (ret)
3042 *pfResult = Result;
3043 return ret;
3046 /******************************************************************************
3047 * AccessCheckAndAuditAlarmA [ADVAPI32.@]
3049 BOOL WINAPI AccessCheckAndAuditAlarmA(LPCSTR Subsystem, LPVOID HandleId, LPSTR ObjectTypeName,
3050 LPSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
3051 PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
3052 LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
3054 FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_a(Subsystem),
3055 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName),
3056 SecurityDescriptor, DesiredAccess, GenericMapping,
3057 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
3058 return TRUE;
3061 /******************************************************************************
3062 * AccessCheckAndAuditAlarmW [ADVAPI32.@]
3064 BOOL WINAPI AccessCheckAndAuditAlarmW(LPCWSTR Subsystem, LPVOID HandleId, LPWSTR ObjectTypeName,
3065 LPWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
3066 PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
3067 LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
3069 FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_w(Subsystem),
3070 HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName),
3071 SecurityDescriptor, DesiredAccess, GenericMapping,
3072 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
3073 return TRUE;
3076 BOOL WINAPI ObjectCloseAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3078 FIXME("stub (%s,%p,%x)\n", debugstr_a(SubsystemName), HandleId, GenerateOnClose);
3080 return TRUE;
3083 BOOL WINAPI ObjectCloseAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3085 FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
3087 return TRUE;
3090 BOOL WINAPI ObjectDeleteAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3092 FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
3094 return TRUE;
3097 BOOL WINAPI ObjectOpenAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, LPSTR ObjectTypeName,
3098 LPSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
3099 DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
3100 LPBOOL GenerateOnClose)
3102 FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_a(SubsystemName),
3103 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName), pSecurityDescriptor,
3104 ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
3105 GenerateOnClose);
3107 return TRUE;
3110 BOOL WINAPI ObjectOpenAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, LPWSTR ObjectTypeName,
3111 LPWSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
3112 DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
3113 LPBOOL GenerateOnClose)
3115 FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_w(SubsystemName),
3116 HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName), pSecurityDescriptor,
3117 ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
3118 GenerateOnClose);
3120 return TRUE;
3123 BOOL WINAPI ObjectPrivilegeAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
3124 DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3126 FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_a(SubsystemName), HandleId, ClientToken,
3127 DesiredAccess, Privileges, AccessGranted);
3129 return TRUE;
3132 BOOL WINAPI ObjectPrivilegeAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
3133 DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3135 FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_w(SubsystemName), HandleId, ClientToken,
3136 DesiredAccess, Privileges, AccessGranted);
3138 return TRUE;
3141 BOOL WINAPI PrivilegedServiceAuditAlarmA( LPCSTR SubsystemName, LPCSTR ServiceName, HANDLE ClientToken,
3142 PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3144 FIXME("stub (%s,%s,%p,%p,%x)\n", debugstr_a(SubsystemName), debugstr_a(ServiceName),
3145 ClientToken, Privileges, AccessGranted);
3147 return TRUE;
3150 BOOL WINAPI PrivilegedServiceAuditAlarmW( LPCWSTR SubsystemName, LPCWSTR ServiceName, HANDLE ClientToken,
3151 PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3153 FIXME("stub %s,%s,%p,%p,%x)\n", debugstr_w(SubsystemName), debugstr_w(ServiceName),
3154 ClientToken, Privileges, AccessGranted);
3156 return TRUE;
3159 /******************************************************************************
3160 * GetSecurityInfo [ADVAPI32.@]
3162 * Retrieves a copy of the security descriptor associated with an object.
3164 * PARAMS
3165 * hObject [I] A handle for the object.
3166 * ObjectType [I] The type of object.
3167 * SecurityInfo [I] A bitmask indicating what info to retrieve.
3168 * ppsidOwner [O] If non-null, receives a pointer to the owner SID.
3169 * ppsidGroup [O] If non-null, receives a pointer to the group SID.
3170 * ppDacl [O] If non-null, receives a pointer to the DACL.
3171 * ppSacl [O] If non-null, receives a pointer to the SACL.
3172 * ppSecurityDescriptor [O] Receives a pointer to the security descriptor,
3173 * which must be freed with LocalFree.
3175 * RETURNS
3176 * ERROR_SUCCESS if all's well, and a WIN32 error code otherwise.
3178 DWORD WINAPI GetSecurityInfo(
3179 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3180 SECURITY_INFORMATION SecurityInfo, PSID *ppsidOwner,
3181 PSID *ppsidGroup, PACL *ppDacl, PACL *ppSacl,
3182 PSECURITY_DESCRIPTOR *ppSecurityDescriptor
3185 PSECURITY_DESCRIPTOR sd;
3186 NTSTATUS status;
3187 ULONG n1, n2;
3188 BOOL present, defaulted;
3190 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
3191 if (!(ppsidOwner||ppsidGroup||ppDacl||ppSacl||ppSecurityDescriptor)) return ERROR_INVALID_PARAMETER;
3193 /* If no descriptor, we have to check that there's a pointer for the requested information */
3194 if( !ppSecurityDescriptor && (
3195 ((SecurityInfo & OWNER_SECURITY_INFORMATION) && !ppsidOwner)
3196 || ((SecurityInfo & GROUP_SECURITY_INFORMATION) && !ppsidGroup)
3197 || ((SecurityInfo & DACL_SECURITY_INFORMATION) && !ppDacl)
3198 || ((SecurityInfo & SACL_SECURITY_INFORMATION) && !ppSacl) ))
3199 return ERROR_INVALID_PARAMETER;
3201 switch (ObjectType)
3203 case SE_SERVICE:
3204 status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, NULL, 0, &n1);
3205 break;
3206 default:
3207 status = NtQuerySecurityObject(hObject, SecurityInfo, NULL, 0, &n1);
3208 break;
3210 if (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_SUCCESS)
3211 return RtlNtStatusToDosError(status);
3213 sd = LocalAlloc(0, n1);
3214 if (!sd)
3215 return ERROR_NOT_ENOUGH_MEMORY;
3217 switch (ObjectType)
3219 case SE_SERVICE:
3220 status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, sd, n1, &n2);
3221 break;
3222 default:
3223 status = NtQuerySecurityObject(hObject, SecurityInfo, sd, n1, &n2);
3224 break;
3226 if (status != STATUS_SUCCESS)
3228 LocalFree(sd);
3229 return RtlNtStatusToDosError(status);
3232 if (ppsidOwner)
3234 *ppsidOwner = NULL;
3235 GetSecurityDescriptorOwner(sd, ppsidOwner, &defaulted);
3237 if (ppsidGroup)
3239 *ppsidGroup = NULL;
3240 GetSecurityDescriptorGroup(sd, ppsidGroup, &defaulted);
3242 if (ppDacl)
3244 *ppDacl = NULL;
3245 GetSecurityDescriptorDacl(sd, &present, ppDacl, &defaulted);
3247 if (ppSacl)
3249 *ppSacl = NULL;
3250 GetSecurityDescriptorSacl(sd, &present, ppSacl, &defaulted);
3252 if (ppSecurityDescriptor)
3253 *ppSecurityDescriptor = sd;
3255 /* The security descriptor (sd) cannot be freed if ppSecurityDescriptor is
3256 * NULL, because native happily returns the SIDs and ACLs that are requested
3257 * in this case.
3260 return ERROR_SUCCESS;
3263 /******************************************************************************
3264 * GetSecurityInfoExA [ADVAPI32.@]
3266 DWORD WINAPI GetSecurityInfoExA(
3267 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3268 SECURITY_INFORMATION SecurityInfo, LPCSTR lpProvider,
3269 LPCSTR lpProperty, PACTRL_ACCESSA *ppAccessList,
3270 PACTRL_AUDITA *ppAuditList, LPSTR *lppOwner, LPSTR *lppGroup
3273 FIXME("stub!\n");
3274 return ERROR_BAD_PROVIDER;
3277 /******************************************************************************
3278 * GetSecurityInfoExW [ADVAPI32.@]
3280 DWORD WINAPI GetSecurityInfoExW(
3281 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3282 SECURITY_INFORMATION SecurityInfo, LPCWSTR lpProvider,
3283 LPCWSTR lpProperty, PACTRL_ACCESSW *ppAccessList,
3284 PACTRL_AUDITW *ppAuditList, LPWSTR *lppOwner, LPWSTR *lppGroup
3287 FIXME("stub!\n");
3288 return ERROR_BAD_PROVIDER;
3291 /******************************************************************************
3292 * BuildExplicitAccessWithNameA [ADVAPI32.@]
3294 VOID WINAPI BuildExplicitAccessWithNameA( PEXPLICIT_ACCESSA pExplicitAccess,
3295 LPSTR pTrusteeName, DWORD AccessPermissions,
3296 ACCESS_MODE AccessMode, DWORD Inheritance )
3298 TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_a(pTrusteeName),
3299 AccessPermissions, AccessMode, Inheritance);
3301 pExplicitAccess->grfAccessPermissions = AccessPermissions;
3302 pExplicitAccess->grfAccessMode = AccessMode;
3303 pExplicitAccess->grfInheritance = Inheritance;
3305 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3306 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3307 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3308 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3309 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3312 /******************************************************************************
3313 * BuildExplicitAccessWithNameW [ADVAPI32.@]
3315 VOID WINAPI BuildExplicitAccessWithNameW( PEXPLICIT_ACCESSW pExplicitAccess,
3316 LPWSTR pTrusteeName, DWORD AccessPermissions,
3317 ACCESS_MODE AccessMode, DWORD Inheritance )
3319 TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_w(pTrusteeName),
3320 AccessPermissions, AccessMode, Inheritance);
3322 pExplicitAccess->grfAccessPermissions = AccessPermissions;
3323 pExplicitAccess->grfAccessMode = AccessMode;
3324 pExplicitAccess->grfInheritance = Inheritance;
3326 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3327 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3328 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3329 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3330 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3333 /******************************************************************************
3334 * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
3336 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
3337 SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
3338 LPSTR InheritedObjectTypeName, LPSTR Name )
3340 DWORD ObjectsPresent = 0;
3342 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3343 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
3345 /* Fill the OBJECTS_AND_NAME structure */
3346 pObjName->ObjectType = ObjectType;
3347 if (ObjectTypeName != NULL)
3349 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3352 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3353 if (InheritedObjectTypeName != NULL)
3355 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3358 pObjName->ObjectsPresent = ObjectsPresent;
3359 pObjName->ptstrName = Name;
3361 /* Fill the TRUSTEE structure */
3362 pTrustee->pMultipleTrustee = NULL;
3363 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3364 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3365 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3366 pTrustee->ptstrName = (LPSTR)pObjName;
3369 /******************************************************************************
3370 * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
3372 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
3373 SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
3374 LPWSTR InheritedObjectTypeName, LPWSTR Name )
3376 DWORD ObjectsPresent = 0;
3378 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3379 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
3381 /* Fill the OBJECTS_AND_NAME structure */
3382 pObjName->ObjectType = ObjectType;
3383 if (ObjectTypeName != NULL)
3385 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3388 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3389 if (InheritedObjectTypeName != NULL)
3391 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3394 pObjName->ObjectsPresent = ObjectsPresent;
3395 pObjName->ptstrName = Name;
3397 /* Fill the TRUSTEE structure */
3398 pTrustee->pMultipleTrustee = NULL;
3399 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3400 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3401 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3402 pTrustee->ptstrName = (LPWSTR)pObjName;
3405 /******************************************************************************
3406 * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
3408 VOID WINAPI BuildTrusteeWithObjectsAndSidA( PTRUSTEEA pTrustee, POBJECTS_AND_SID pObjSid,
3409 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3411 DWORD ObjectsPresent = 0;
3413 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3415 /* Fill the OBJECTS_AND_SID structure */
3416 if (pObjectGuid != NULL)
3418 pObjSid->ObjectTypeGuid = *pObjectGuid;
3419 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3421 else
3423 ZeroMemory(&pObjSid->ObjectTypeGuid,
3424 sizeof(GUID));
3427 if (pInheritedObjectGuid != NULL)
3429 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3430 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3432 else
3434 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3435 sizeof(GUID));
3438 pObjSid->ObjectsPresent = ObjectsPresent;
3439 pObjSid->pSid = pSid;
3441 /* Fill the TRUSTEE structure */
3442 pTrustee->pMultipleTrustee = NULL;
3443 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3444 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3445 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3446 pTrustee->ptstrName = (LPSTR) pObjSid;
3449 /******************************************************************************
3450 * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
3452 VOID WINAPI BuildTrusteeWithObjectsAndSidW( PTRUSTEEW pTrustee, POBJECTS_AND_SID pObjSid,
3453 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3455 DWORD ObjectsPresent = 0;
3457 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3459 /* Fill the OBJECTS_AND_SID structure */
3460 if (pObjectGuid != NULL)
3462 pObjSid->ObjectTypeGuid = *pObjectGuid;
3463 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3465 else
3467 ZeroMemory(&pObjSid->ObjectTypeGuid,
3468 sizeof(GUID));
3471 if (pInheritedObjectGuid != NULL)
3473 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3474 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3476 else
3478 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3479 sizeof(GUID));
3482 pObjSid->ObjectsPresent = ObjectsPresent;
3483 pObjSid->pSid = pSid;
3485 /* Fill the TRUSTEE structure */
3486 pTrustee->pMultipleTrustee = NULL;
3487 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3488 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3489 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3490 pTrustee->ptstrName = (LPWSTR) pObjSid;
3493 /******************************************************************************
3494 * BuildTrusteeWithSidA [ADVAPI32.@]
3496 VOID WINAPI BuildTrusteeWithSidA(PTRUSTEEA pTrustee, PSID pSid)
3498 TRACE("%p %p\n", pTrustee, pSid);
3500 pTrustee->pMultipleTrustee = NULL;
3501 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3502 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3503 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3504 pTrustee->ptstrName = pSid;
3507 /******************************************************************************
3508 * BuildTrusteeWithSidW [ADVAPI32.@]
3510 VOID WINAPI BuildTrusteeWithSidW(PTRUSTEEW pTrustee, PSID pSid)
3512 TRACE("%p %p\n", pTrustee, pSid);
3514 pTrustee->pMultipleTrustee = NULL;
3515 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3516 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3517 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3518 pTrustee->ptstrName = pSid;
3521 /******************************************************************************
3522 * BuildTrusteeWithNameA [ADVAPI32.@]
3524 VOID WINAPI BuildTrusteeWithNameA(PTRUSTEEA pTrustee, LPSTR name)
3526 TRACE("%p %s\n", pTrustee, debugstr_a(name) );
3528 pTrustee->pMultipleTrustee = NULL;
3529 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3530 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3531 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3532 pTrustee->ptstrName = name;
3535 /******************************************************************************
3536 * BuildTrusteeWithNameW [ADVAPI32.@]
3538 VOID WINAPI BuildTrusteeWithNameW(PTRUSTEEW pTrustee, LPWSTR name)
3540 TRACE("%p %s\n", pTrustee, debugstr_w(name) );
3542 pTrustee->pMultipleTrustee = NULL;
3543 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3544 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3545 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3546 pTrustee->ptstrName = name;
3549 /******************************************************************************
3550 * GetTrusteeFormA [ADVAPI32.@]
3552 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee)
3554 TRACE("(%p)\n", pTrustee);
3556 if (!pTrustee)
3557 return TRUSTEE_BAD_FORM;
3559 return pTrustee->TrusteeForm;
3562 /******************************************************************************
3563 * GetTrusteeFormW [ADVAPI32.@]
3565 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee)
3567 TRACE("(%p)\n", pTrustee);
3569 if (!pTrustee)
3570 return TRUSTEE_BAD_FORM;
3572 return pTrustee->TrusteeForm;
3575 /******************************************************************************
3576 * GetTrusteeNameA [ADVAPI32.@]
3578 LPSTR WINAPI GetTrusteeNameA(PTRUSTEEA pTrustee)
3580 TRACE("(%p)\n", pTrustee);
3582 if (!pTrustee)
3583 return NULL;
3585 return pTrustee->ptstrName;
3588 /******************************************************************************
3589 * GetTrusteeNameW [ADVAPI32.@]
3591 LPWSTR WINAPI GetTrusteeNameW(PTRUSTEEW pTrustee)
3593 TRACE("(%p)\n", pTrustee);
3595 if (!pTrustee)
3596 return NULL;
3598 return pTrustee->ptstrName;
3601 /******************************************************************************
3602 * GetTrusteeTypeA [ADVAPI32.@]
3604 TRUSTEE_TYPE WINAPI GetTrusteeTypeA(PTRUSTEEA pTrustee)
3606 TRACE("(%p)\n", pTrustee);
3608 if (!pTrustee)
3609 return TRUSTEE_IS_UNKNOWN;
3611 return pTrustee->TrusteeType;
3614 /******************************************************************************
3615 * GetTrusteeTypeW [ADVAPI32.@]
3617 TRUSTEE_TYPE WINAPI GetTrusteeTypeW(PTRUSTEEW pTrustee)
3619 TRACE("(%p)\n", pTrustee);
3621 if (!pTrustee)
3622 return TRUSTEE_IS_UNKNOWN;
3624 return pTrustee->TrusteeType;
3627 BOOL WINAPI SetAclInformation( PACL pAcl, LPVOID pAclInformation,
3628 DWORD nAclInformationLength,
3629 ACL_INFORMATION_CLASS dwAclInformationClass )
3631 FIXME("%p %p 0x%08x 0x%08x - stub\n", pAcl, pAclInformation,
3632 nAclInformationLength, dwAclInformationClass);
3634 return TRUE;
3637 static DWORD trustee_name_A_to_W(TRUSTEE_FORM form, char *trustee_nameA, WCHAR **ptrustee_nameW)
3639 switch (form)
3641 case TRUSTEE_IS_NAME:
3643 *ptrustee_nameW = SERV_dup(trustee_nameA);
3644 return ERROR_SUCCESS;
3646 case TRUSTEE_IS_OBJECTS_AND_NAME:
3648 OBJECTS_AND_NAME_A *objA = (OBJECTS_AND_NAME_A *)trustee_nameA;
3649 OBJECTS_AND_NAME_W *objW = NULL;
3651 if (objA)
3653 if (!(objW = heap_alloc( sizeof(OBJECTS_AND_NAME_W) )))
3654 return ERROR_NOT_ENOUGH_MEMORY;
3656 objW->ObjectsPresent = objA->ObjectsPresent;
3657 objW->ObjectType = objA->ObjectType;
3658 objW->ObjectTypeName = SERV_dup(objA->ObjectTypeName);
3659 objW->InheritedObjectTypeName = SERV_dup(objA->InheritedObjectTypeName);
3660 objW->ptstrName = SERV_dup(objA->ptstrName);
3663 *ptrustee_nameW = (WCHAR *)objW;
3664 return ERROR_SUCCESS;
3666 /* These forms do not require conversion. */
3667 case TRUSTEE_IS_SID:
3668 case TRUSTEE_IS_OBJECTS_AND_SID:
3669 *ptrustee_nameW = (WCHAR *)trustee_nameA;
3670 return ERROR_SUCCESS;
3671 default:
3672 return ERROR_INVALID_PARAMETER;
3676 static void free_trustee_name(TRUSTEE_FORM form, WCHAR *trustee_nameW)
3678 switch (form)
3680 case TRUSTEE_IS_NAME:
3681 heap_free( trustee_nameW );
3682 break;
3683 case TRUSTEE_IS_OBJECTS_AND_NAME:
3685 OBJECTS_AND_NAME_W *objW = (OBJECTS_AND_NAME_W *)trustee_nameW;
3687 if (objW)
3689 heap_free( objW->ptstrName );
3690 heap_free( objW->InheritedObjectTypeName );
3691 heap_free( objW->ObjectTypeName );
3692 heap_free( objW );
3695 break;
3697 /* Other forms did not require allocation, so no freeing is necessary. */
3698 default:
3699 break;
3703 /******************************************************************************
3704 * SetEntriesInAclA [ADVAPI32.@]
3706 DWORD WINAPI SetEntriesInAclA( ULONG count, PEXPLICIT_ACCESSA pEntries,
3707 PACL OldAcl, PACL* NewAcl )
3709 DWORD err = ERROR_SUCCESS;
3710 EXPLICIT_ACCESSW *pEntriesW;
3711 UINT alloc_index, free_index;
3713 TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
3715 if (NewAcl)
3716 *NewAcl = NULL;
3718 if (!count && !OldAcl)
3719 return ERROR_SUCCESS;
3721 pEntriesW = heap_alloc( count * sizeof(EXPLICIT_ACCESSW) );
3722 if (!pEntriesW)
3723 return ERROR_NOT_ENOUGH_MEMORY;
3725 for (alloc_index = 0; alloc_index < count; ++alloc_index)
3727 pEntriesW[alloc_index].grfAccessPermissions = pEntries[alloc_index].grfAccessPermissions;
3728 pEntriesW[alloc_index].grfAccessMode = pEntries[alloc_index].grfAccessMode;
3729 pEntriesW[alloc_index].grfInheritance = pEntries[alloc_index].grfInheritance;
3730 pEntriesW[alloc_index].Trustee.pMultipleTrustee = NULL; /* currently not supported */
3731 pEntriesW[alloc_index].Trustee.MultipleTrusteeOperation = pEntries[alloc_index].Trustee.MultipleTrusteeOperation;
3732 pEntriesW[alloc_index].Trustee.TrusteeForm = pEntries[alloc_index].Trustee.TrusteeForm;
3733 pEntriesW[alloc_index].Trustee.TrusteeType = pEntries[alloc_index].Trustee.TrusteeType;
3735 err = trustee_name_A_to_W( pEntries[alloc_index].Trustee.TrusteeForm,
3736 pEntries[alloc_index].Trustee.ptstrName,
3737 &pEntriesW[alloc_index].Trustee.ptstrName );
3738 if (err != ERROR_SUCCESS)
3740 if (err == ERROR_INVALID_PARAMETER)
3741 WARN("bad trustee form %d for trustee %d\n",
3742 pEntries[alloc_index].Trustee.TrusteeForm, alloc_index);
3744 goto cleanup;
3748 err = SetEntriesInAclW( count, pEntriesW, OldAcl, NewAcl );
3750 cleanup:
3751 /* Free any previously allocated trustee name buffers, taking into account
3752 * a possible out-of-memory condition while building the EXPLICIT_ACCESSW
3753 * list. */
3754 for (free_index = 0; free_index < alloc_index; ++free_index)
3755 free_trustee_name( pEntriesW[free_index].Trustee.TrusteeForm, pEntriesW[free_index].Trustee.ptstrName );
3757 heap_free( pEntriesW );
3758 return err;
3761 /******************************************************************************
3762 * SetEntriesInAclW [ADVAPI32.@]
3764 DWORD WINAPI SetEntriesInAclW( ULONG count, PEXPLICIT_ACCESSW pEntries,
3765 PACL OldAcl, PACL* NewAcl )
3767 ULONG i;
3768 PSID *ppsid;
3769 DWORD ret = ERROR_SUCCESS;
3770 DWORD acl_size = sizeof(ACL);
3771 NTSTATUS status;
3773 TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
3775 if (NewAcl)
3776 *NewAcl = NULL;
3778 if (!count && !OldAcl)
3779 return ERROR_SUCCESS;
3781 /* allocate array of maximum sized sids allowed */
3782 ppsid = heap_alloc(count * (sizeof(SID *) + FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES])));
3783 if (!ppsid)
3784 return ERROR_OUTOFMEMORY;
3786 for (i = 0; i < count; i++)
3788 ppsid[i] = (char *)&ppsid[count] + i * FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3790 TRACE("[%d]:\n\tgrfAccessPermissions = 0x%x\n\tgrfAccessMode = %d\n\tgrfInheritance = 0x%x\n\t"
3791 "Trustee.pMultipleTrustee = %p\n\tMultipleTrusteeOperation = %d\n\tTrusteeForm = %d\n\t"
3792 "Trustee.TrusteeType = %d\n\tptstrName = %p\n", i,
3793 pEntries[i].grfAccessPermissions, pEntries[i].grfAccessMode, pEntries[i].grfInheritance,
3794 pEntries[i].Trustee.pMultipleTrustee, pEntries[i].Trustee.MultipleTrusteeOperation,
3795 pEntries[i].Trustee.TrusteeForm, pEntries[i].Trustee.TrusteeType,
3796 pEntries[i].Trustee.ptstrName);
3798 if (pEntries[i].Trustee.MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE)
3800 WARN("bad multiple trustee operation %d for trustee %d\n", pEntries[i].Trustee.MultipleTrusteeOperation, i);
3801 ret = ERROR_INVALID_PARAMETER;
3802 goto exit;
3805 switch (pEntries[i].Trustee.TrusteeForm)
3807 case TRUSTEE_IS_SID:
3808 if (!CopySid(FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]),
3809 ppsid[i], pEntries[i].Trustee.ptstrName))
3811 WARN("bad sid %p for trustee %d\n", pEntries[i].Trustee.ptstrName, i);
3812 ret = ERROR_INVALID_PARAMETER;
3813 goto exit;
3815 break;
3816 case TRUSTEE_IS_NAME:
3818 DWORD sid_size = FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3819 DWORD domain_size = MAX_COMPUTERNAME_LENGTH + 1;
3820 SID_NAME_USE use;
3821 if (!strcmpW( pEntries[i].Trustee.ptstrName, CURRENT_USER ))
3823 if (!lookup_user_account_name( ppsid[i], &sid_size, NULL, &domain_size, &use ))
3825 ret = GetLastError();
3826 goto exit;
3829 else if (!LookupAccountNameW(NULL, pEntries[i].Trustee.ptstrName, ppsid[i], &sid_size, NULL, &domain_size, &use))
3831 WARN("bad user name %s for trustee %d\n", debugstr_w(pEntries[i].Trustee.ptstrName), i);
3832 ret = ERROR_INVALID_PARAMETER;
3833 goto exit;
3835 break;
3837 case TRUSTEE_IS_OBJECTS_AND_SID:
3838 FIXME("TRUSTEE_IS_OBJECTS_AND_SID unimplemented\n");
3839 break;
3840 case TRUSTEE_IS_OBJECTS_AND_NAME:
3841 FIXME("TRUSTEE_IS_OBJECTS_AND_NAME unimplemented\n");
3842 break;
3843 default:
3844 WARN("bad trustee form %d for trustee %d\n", pEntries[i].Trustee.TrusteeForm, i);
3845 ret = ERROR_INVALID_PARAMETER;
3846 goto exit;
3849 /* Note: we overestimate the ACL size here as a tradeoff between
3850 * instructions (simplicity) and memory */
3851 switch (pEntries[i].grfAccessMode)
3853 case GRANT_ACCESS:
3854 case SET_ACCESS:
3855 acl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3856 break;
3857 case DENY_ACCESS:
3858 acl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3859 break;
3860 case SET_AUDIT_SUCCESS:
3861 case SET_AUDIT_FAILURE:
3862 acl_size += FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart) + GetLengthSid(ppsid[i]);
3863 break;
3864 case REVOKE_ACCESS:
3865 break;
3866 default:
3867 WARN("bad access mode %d for trustee %d\n", pEntries[i].grfAccessMode, i);
3868 ret = ERROR_INVALID_PARAMETER;
3869 goto exit;
3873 if (OldAcl)
3875 ACL_SIZE_INFORMATION size_info;
3877 status = RtlQueryInformationAcl(OldAcl, &size_info, sizeof(size_info), AclSizeInformation);
3878 if (status != STATUS_SUCCESS)
3880 ret = RtlNtStatusToDosError(status);
3881 goto exit;
3883 acl_size += size_info.AclBytesInUse - sizeof(ACL);
3886 *NewAcl = LocalAlloc(0, acl_size);
3887 if (!*NewAcl)
3889 ret = ERROR_OUTOFMEMORY;
3890 goto exit;
3893 status = RtlCreateAcl( *NewAcl, acl_size, ACL_REVISION );
3894 if (status != STATUS_SUCCESS)
3896 ret = RtlNtStatusToDosError(status);
3897 goto exit;
3900 for (i = 0; i < count; i++)
3902 switch (pEntries[i].grfAccessMode)
3904 case GRANT_ACCESS:
3905 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3906 pEntries[i].grfInheritance,
3907 pEntries[i].grfAccessPermissions,
3908 ppsid[i]);
3909 break;
3910 case SET_ACCESS:
3912 ULONG j;
3913 BOOL add = TRUE;
3914 if (OldAcl)
3916 for (j = 0; ; j++)
3918 const ACE_HEADER *existing_ace_header;
3919 status = RtlGetAce(OldAcl, j, (LPVOID *)&existing_ace_header);
3920 if (status != STATUS_SUCCESS)
3921 break;
3922 if (pEntries[i].grfAccessMode == SET_ACCESS &&
3923 existing_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3924 EqualSid(ppsid[i], &((ACCESS_ALLOWED_ACE *)existing_ace_header)->SidStart))
3926 add = FALSE;
3927 break;
3931 if (add)
3932 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3933 pEntries[i].grfInheritance,
3934 pEntries[i].grfAccessPermissions,
3935 ppsid[i]);
3936 break;
3938 case DENY_ACCESS:
3939 status = RtlAddAccessDeniedAceEx(*NewAcl, ACL_REVISION,
3940 pEntries[i].grfInheritance,
3941 pEntries[i].grfAccessPermissions,
3942 ppsid[i]);
3943 break;
3944 case SET_AUDIT_SUCCESS:
3945 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3946 pEntries[i].grfInheritance,
3947 pEntries[i].grfAccessPermissions,
3948 ppsid[i], TRUE, FALSE);
3949 break;
3950 case SET_AUDIT_FAILURE:
3951 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3952 pEntries[i].grfInheritance,
3953 pEntries[i].grfAccessPermissions,
3954 ppsid[i], FALSE, TRUE);
3955 break;
3956 default:
3957 FIXME("unhandled access mode %d\n", pEntries[i].grfAccessMode);
3961 if (OldAcl)
3963 for (i = 0; ; i++)
3965 BOOL add = TRUE;
3966 ULONG j;
3967 const ACE_HEADER *old_ace_header;
3968 status = RtlGetAce(OldAcl, i, (LPVOID *)&old_ace_header);
3969 if (status != STATUS_SUCCESS) break;
3970 for (j = 0; j < count; j++)
3972 if (pEntries[j].grfAccessMode == SET_ACCESS &&
3973 old_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3974 EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3976 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION, pEntries[j].grfInheritance, pEntries[j].grfAccessPermissions, ppsid[j]);
3977 add = FALSE;
3978 break;
3980 else if (pEntries[j].grfAccessMode == REVOKE_ACCESS)
3982 switch (old_ace_header->AceType)
3984 case ACCESS_ALLOWED_ACE_TYPE:
3985 if (EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3986 add = FALSE;
3987 break;
3988 case ACCESS_DENIED_ACE_TYPE:
3989 if (EqualSid(ppsid[j], &((ACCESS_DENIED_ACE *)old_ace_header)->SidStart))
3990 add = FALSE;
3991 break;
3992 case SYSTEM_AUDIT_ACE_TYPE:
3993 if (EqualSid(ppsid[j], &((SYSTEM_AUDIT_ACE *)old_ace_header)->SidStart))
3994 add = FALSE;
3995 break;
3996 case SYSTEM_ALARM_ACE_TYPE:
3997 if (EqualSid(ppsid[j], &((SYSTEM_ALARM_ACE *)old_ace_header)->SidStart))
3998 add = FALSE;
3999 break;
4000 default:
4001 FIXME("unhandled ace type %d\n", old_ace_header->AceType);
4004 if (!add)
4005 break;
4008 if (add)
4009 status = RtlAddAce(*NewAcl, ACL_REVISION, 1, (PACE_HEADER)old_ace_header, old_ace_header->AceSize);
4010 if (status != STATUS_SUCCESS)
4012 WARN("RtlAddAce failed with error 0x%08x\n", status);
4013 ret = RtlNtStatusToDosError(status);
4014 break;
4019 exit:
4020 heap_free(ppsid);
4021 return ret;
4024 /******************************************************************************
4025 * SetNamedSecurityInfoA [ADVAPI32.@]
4027 DWORD WINAPI SetNamedSecurityInfoA(LPSTR pObjectName,
4028 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
4029 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
4031 LPWSTR wstr;
4032 DWORD r;
4034 TRACE("%s %d %d %p %p %p %p\n", debugstr_a(pObjectName), ObjectType,
4035 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
4037 wstr = SERV_dup(pObjectName);
4038 r = SetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, psidOwner,
4039 psidGroup, pDacl, pSacl );
4041 heap_free( wstr );
4043 return r;
4046 BOOL WINAPI SetPrivateObjectSecurity( SECURITY_INFORMATION SecurityInformation,
4047 PSECURITY_DESCRIPTOR ModificationDescriptor,
4048 PSECURITY_DESCRIPTOR* ObjectsSecurityDescriptor,
4049 PGENERIC_MAPPING GenericMapping,
4050 HANDLE Token )
4052 FIXME("0x%08x %p %p %p %p - stub\n", SecurityInformation, ModificationDescriptor,
4053 ObjectsSecurityDescriptor, GenericMapping, Token);
4055 return TRUE;
4058 BOOL WINAPI AreAllAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
4060 return RtlAreAllAccessesGranted( GrantedAccess, DesiredAccess );
4063 /******************************************************************************
4064 * AreAnyAccessesGranted [ADVAPI32.@]
4066 * Determines whether or not any of a set of specified access permissions have
4067 * been granted or not.
4069 * PARAMS
4070 * GrantedAccess [I] The permissions that have been granted.
4071 * DesiredAccess [I] The permissions that you want to have.
4073 * RETURNS
4074 * Nonzero if any of the permissions have been granted, zero if none of the
4075 * permissions have been granted.
4078 BOOL WINAPI AreAnyAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
4080 return RtlAreAnyAccessesGranted( GrantedAccess, DesiredAccess );
4083 /******************************************************************************
4084 * SetNamedSecurityInfoW [ADVAPI32.@]
4086 DWORD WINAPI SetNamedSecurityInfoW(LPWSTR pObjectName,
4087 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
4088 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
4090 DWORD access = 0;
4091 HANDLE handle;
4092 DWORD err;
4094 TRACE( "%s %d %d %p %p %p %p\n", debugstr_w(pObjectName), ObjectType,
4095 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
4097 if (!pObjectName) return ERROR_INVALID_PARAMETER;
4099 if (SecurityInfo & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION))
4100 access |= WRITE_OWNER;
4101 if (SecurityInfo & DACL_SECURITY_INFORMATION)
4102 access |= WRITE_DAC;
4103 if (SecurityInfo & SACL_SECURITY_INFORMATION)
4104 access |= ACCESS_SYSTEM_SECURITY;
4106 switch (ObjectType)
4108 case SE_SERVICE:
4109 if (!(err = get_security_service( pObjectName, access, &handle )))
4111 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4112 CloseServiceHandle( handle );
4114 break;
4115 case SE_REGISTRY_KEY:
4116 if (!(err = get_security_regkey( pObjectName, access, &handle )))
4118 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4119 RegCloseKey( handle );
4121 break;
4122 case SE_FILE_OBJECT:
4123 if (SecurityInfo & DACL_SECURITY_INFORMATION)
4124 access |= READ_CONTROL;
4125 if (!(err = get_security_file( pObjectName, access, &handle )))
4127 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4128 CloseHandle( handle );
4130 break;
4131 default:
4132 FIXME( "Object type %d is not currently supported.\n", ObjectType );
4133 return ERROR_SUCCESS;
4135 return err;
4138 /******************************************************************************
4139 * GetExplicitEntriesFromAclA [ADVAPI32.@]
4141 DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntries,
4142 PEXPLICIT_ACCESSA* pListOfExplicitEntries)
4144 FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
4145 return ERROR_CALL_NOT_IMPLEMENTED;
4148 /******************************************************************************
4149 * GetExplicitEntriesFromAclW [ADVAPI32.@]
4151 DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG pcCountOfExplicitEntries,
4152 PEXPLICIT_ACCESSW* pListOfExplicitEntries)
4154 FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
4155 return ERROR_CALL_NOT_IMPLEMENTED;
4158 /******************************************************************************
4159 * GetAuditedPermissionsFromAclA [ADVAPI32.@]
4161 DWORD WINAPI GetAuditedPermissionsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
4162 PACCESS_MASK pFailedAuditRights)
4164 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
4165 return ERROR_CALL_NOT_IMPLEMENTED;
4169 /******************************************************************************
4170 * GetAuditedPermissionsFromAclW [ADVAPI32.@]
4172 DWORD WINAPI GetAuditedPermissionsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
4173 PACCESS_MASK pFailedAuditRights)
4175 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
4176 return ERROR_CALL_NOT_IMPLEMENTED;
4180 /******************************************************************************
4181 * ParseAclStringFlags
4183 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
4185 DWORD flags = 0;
4186 LPCWSTR szAcl = *StringAcl;
4188 while (*szAcl != '(')
4190 if (*szAcl == 'P')
4192 flags |= SE_DACL_PROTECTED;
4194 else if (*szAcl == 'A')
4196 szAcl++;
4197 if (*szAcl == 'R')
4198 flags |= SE_DACL_AUTO_INHERIT_REQ;
4199 else if (*szAcl == 'I')
4200 flags |= SE_DACL_AUTO_INHERITED;
4202 szAcl++;
4205 *StringAcl = szAcl;
4206 return flags;
4209 /******************************************************************************
4210 * ParseAceStringType
4212 static const ACEFLAG AceType[] =
4214 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
4215 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
4216 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
4217 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
4218 { SDDL_MANDATORY_LABEL,SYSTEM_MANDATORY_LABEL_ACE_TYPE },
4220 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
4221 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
4222 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
4223 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
4225 { NULL, 0 },
4228 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
4230 UINT len = 0;
4231 LPCWSTR szAcl = *StringAcl;
4232 const ACEFLAG *lpaf = AceType;
4234 while (*szAcl == ' ')
4235 szAcl++;
4237 while (lpaf->wstr &&
4238 (len = strlenW(lpaf->wstr)) &&
4239 strncmpW(lpaf->wstr, szAcl, len))
4240 lpaf++;
4242 if (!lpaf->wstr)
4243 return 0;
4245 *StringAcl = szAcl + len;
4246 return lpaf->value;
4250 /******************************************************************************
4251 * ParseAceStringFlags
4253 static const ACEFLAG AceFlags[] =
4255 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
4256 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
4257 { SDDL_INHERITED, INHERITED_ACE },
4258 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
4259 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
4260 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
4261 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
4262 { NULL, 0 },
4265 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
4267 UINT len = 0;
4268 BYTE flags = 0;
4269 LPCWSTR szAcl = *StringAcl;
4271 while (*szAcl == ' ')
4272 szAcl++;
4274 while (*szAcl != ';')
4276 const ACEFLAG *lpaf = AceFlags;
4278 while (lpaf->wstr &&
4279 (len = strlenW(lpaf->wstr)) &&
4280 strncmpW(lpaf->wstr, szAcl, len))
4281 lpaf++;
4283 if (!lpaf->wstr)
4284 return 0;
4286 flags |= lpaf->value;
4287 szAcl += len;
4290 *StringAcl = szAcl;
4291 return flags;
4295 /******************************************************************************
4296 * ParseAceStringRights
4298 static const ACEFLAG AceRights[] =
4300 { SDDL_GENERIC_ALL, GENERIC_ALL },
4301 { SDDL_GENERIC_READ, GENERIC_READ },
4302 { SDDL_GENERIC_WRITE, GENERIC_WRITE },
4303 { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
4305 { SDDL_READ_CONTROL, READ_CONTROL },
4306 { SDDL_STANDARD_DELETE, DELETE },
4307 { SDDL_WRITE_DAC, WRITE_DAC },
4308 { SDDL_WRITE_OWNER, WRITE_OWNER },
4310 { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP},
4311 { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP},
4312 { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD},
4313 { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD},
4314 { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST},
4315 { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF},
4316 { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT},
4317 { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE},
4318 { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS},
4320 { SDDL_FILE_ALL, FILE_ALL_ACCESS },
4321 { SDDL_FILE_READ, FILE_GENERIC_READ },
4322 { SDDL_FILE_WRITE, FILE_GENERIC_WRITE },
4323 { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE },
4325 { SDDL_KEY_ALL, KEY_ALL_ACCESS },
4326 { SDDL_KEY_READ, KEY_READ },
4327 { SDDL_KEY_WRITE, KEY_WRITE },
4328 { SDDL_KEY_EXECUTE, KEY_EXECUTE },
4330 { SDDL_NO_READ_UP, SYSTEM_MANDATORY_LABEL_NO_READ_UP },
4331 { SDDL_NO_WRITE_UP, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP },
4332 { SDDL_NO_EXECUTE_UP, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP },
4333 { NULL, 0 },
4336 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
4338 UINT len = 0;
4339 DWORD rights = 0;
4340 LPCWSTR szAcl = *StringAcl;
4342 while (*szAcl == ' ')
4343 szAcl++;
4345 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
4347 LPCWSTR p = szAcl;
4349 while (*p && *p != ';')
4350 p++;
4352 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
4354 rights = strtoulW(szAcl, NULL, 16);
4355 szAcl = p;
4357 else
4358 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
4360 else
4362 while (*szAcl != ';')
4364 const ACEFLAG *lpaf = AceRights;
4366 while (lpaf->wstr &&
4367 (len = strlenW(lpaf->wstr)) &&
4368 strncmpW(lpaf->wstr, szAcl, len))
4370 lpaf++;
4373 if (!lpaf->wstr)
4374 return 0;
4376 rights |= lpaf->value;
4377 szAcl += len;
4381 *StringAcl = szAcl;
4382 return rights;
4386 /******************************************************************************
4387 * ParseStringAclToAcl
4389 * dacl_flags(string_ace1)(string_ace2)... (string_acen)
4391 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
4392 PACL pAcl, LPDWORD cBytes)
4394 DWORD val;
4395 DWORD sidlen;
4396 DWORD length = sizeof(ACL);
4397 DWORD acesize = 0;
4398 DWORD acecount = 0;
4399 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
4400 DWORD error = ERROR_INVALID_ACL;
4402 TRACE("%s\n", debugstr_w(StringAcl));
4404 if (!StringAcl)
4405 return FALSE;
4407 if (pAcl) /* pAce is only useful if we're setting values */
4408 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
4410 /* Parse ACL flags */
4411 *lpdwFlags = ParseAclStringFlags(&StringAcl);
4413 /* Parse ACE */
4414 while (*StringAcl == '(')
4416 StringAcl++;
4418 /* Parse ACE type */
4419 val = ParseAceStringType(&StringAcl);
4420 if (pAce)
4421 pAce->Header.AceType = (BYTE) val;
4422 if (*StringAcl != ';')
4424 error = RPC_S_INVALID_STRING_UUID;
4425 goto lerr;
4427 StringAcl++;
4429 /* Parse ACE flags */
4430 val = ParseAceStringFlags(&StringAcl);
4431 if (pAce)
4432 pAce->Header.AceFlags = (BYTE) val;
4433 if (*StringAcl != ';')
4434 goto lerr;
4435 StringAcl++;
4437 /* Parse ACE rights */
4438 val = ParseAceStringRights(&StringAcl);
4439 if (pAce)
4440 pAce->Mask = val;
4441 if (*StringAcl != ';')
4442 goto lerr;
4443 StringAcl++;
4445 /* Parse ACE object guid */
4446 while (*StringAcl == ' ')
4447 StringAcl++;
4448 if (*StringAcl != ';')
4450 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4451 goto lerr;
4453 StringAcl++;
4455 /* Parse ACE inherit object guid */
4456 while (*StringAcl == ' ')
4457 StringAcl++;
4458 if (*StringAcl != ';')
4460 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4461 goto lerr;
4463 StringAcl++;
4465 /* Parse ACE account sid */
4466 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
4468 while (*StringAcl && *StringAcl != ')')
4469 StringAcl++;
4472 if (*StringAcl != ')')
4473 goto lerr;
4474 StringAcl++;
4476 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
4477 length += acesize;
4478 if (pAce)
4480 pAce->Header.AceSize = acesize;
4481 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
4483 acecount++;
4486 *cBytes = length;
4488 if (length > 0xffff)
4490 ERR("ACL too large\n");
4491 goto lerr;
4494 if (pAcl)
4496 pAcl->AclRevision = ACL_REVISION;
4497 pAcl->Sbz1 = 0;
4498 pAcl->AclSize = length;
4499 pAcl->AceCount = acecount++;
4500 pAcl->Sbz2 = 0;
4502 return TRUE;
4504 lerr:
4505 SetLastError(error);
4506 WARN("Invalid ACE string format\n");
4507 return FALSE;
4511 /******************************************************************************
4512 * ParseStringSecurityDescriptorToSecurityDescriptor
4514 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
4515 LPCWSTR StringSecurityDescriptor,
4516 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
4517 LPDWORD cBytes)
4519 BOOL bret = FALSE;
4520 WCHAR toktype;
4521 WCHAR *tok;
4522 LPCWSTR lptoken;
4523 LPBYTE lpNext = NULL;
4524 DWORD len;
4526 *cBytes = sizeof(SECURITY_DESCRIPTOR);
4528 tok = heap_alloc( (lstrlenW(StringSecurityDescriptor) + 1) * sizeof(WCHAR));
4530 if (SecurityDescriptor)
4531 lpNext = (LPBYTE)(SecurityDescriptor + 1);
4533 while (*StringSecurityDescriptor == ' ')
4534 StringSecurityDescriptor++;
4536 while (*StringSecurityDescriptor)
4538 toktype = *StringSecurityDescriptor;
4540 /* Expect char identifier followed by ':' */
4541 StringSecurityDescriptor++;
4542 if (*StringSecurityDescriptor != ':')
4544 SetLastError(ERROR_INVALID_PARAMETER);
4545 goto lend;
4547 StringSecurityDescriptor++;
4549 /* Extract token */
4550 lptoken = StringSecurityDescriptor;
4551 while (*lptoken && *lptoken != ':')
4552 lptoken++;
4554 if (*lptoken)
4555 lptoken--;
4557 len = lptoken - StringSecurityDescriptor;
4558 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
4559 tok[len] = 0;
4561 switch (toktype)
4563 case 'O':
4565 DWORD bytes;
4567 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4568 goto lend;
4570 if (SecurityDescriptor)
4572 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
4573 lpNext += bytes; /* Advance to next token */
4576 *cBytes += bytes;
4578 break;
4581 case 'G':
4583 DWORD bytes;
4585 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4586 goto lend;
4588 if (SecurityDescriptor)
4590 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
4591 lpNext += bytes; /* Advance to next token */
4594 *cBytes += bytes;
4596 break;
4599 case 'D':
4601 DWORD flags;
4602 DWORD bytes;
4604 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4605 goto lend;
4607 if (SecurityDescriptor)
4609 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
4610 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
4611 lpNext += bytes; /* Advance to next token */
4614 *cBytes += bytes;
4616 break;
4619 case 'S':
4621 DWORD flags;
4622 DWORD bytes;
4624 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4625 goto lend;
4627 if (SecurityDescriptor)
4629 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
4630 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
4631 lpNext += bytes; /* Advance to next token */
4634 *cBytes += bytes;
4636 break;
4639 default:
4640 FIXME("Unknown token\n");
4641 SetLastError(ERROR_INVALID_PARAMETER);
4642 goto lend;
4645 StringSecurityDescriptor = lptoken;
4648 bret = TRUE;
4650 lend:
4651 heap_free(tok);
4652 return bret;
4655 /******************************************************************************
4656 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
4658 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
4659 LPCSTR StringSecurityDescriptor,
4660 DWORD StringSDRevision,
4661 PSECURITY_DESCRIPTOR* SecurityDescriptor,
4662 PULONG SecurityDescriptorSize)
4664 BOOL ret;
4665 LPWSTR StringSecurityDescriptorW;
4667 if(!StringSecurityDescriptor)
4668 return FALSE;
4670 StringSecurityDescriptorW = SERV_dup(StringSecurityDescriptor);
4671 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
4672 StringSDRevision, SecurityDescriptor,
4673 SecurityDescriptorSize);
4674 heap_free(StringSecurityDescriptorW);
4676 return ret;
4679 /******************************************************************************
4680 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
4682 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
4683 LPCWSTR StringSecurityDescriptor,
4684 DWORD StringSDRevision,
4685 PSECURITY_DESCRIPTOR* SecurityDescriptor,
4686 PULONG SecurityDescriptorSize)
4688 DWORD cBytes;
4689 SECURITY_DESCRIPTOR* psd;
4690 BOOL bret = FALSE;
4692 TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
4694 if (GetVersion() & 0x80000000)
4696 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4697 goto lend;
4699 else if (!StringSecurityDescriptor || !SecurityDescriptor)
4701 SetLastError(ERROR_INVALID_PARAMETER);
4702 goto lend;
4704 else if (StringSDRevision != SID_REVISION)
4706 SetLastError(ERROR_UNKNOWN_REVISION);
4707 goto lend;
4710 /* Compute security descriptor length */
4711 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4712 NULL, &cBytes))
4713 goto lend;
4715 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
4716 if (!psd) goto lend;
4718 psd->Revision = SID_REVISION;
4719 psd->Control |= SE_SELF_RELATIVE;
4721 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4722 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
4724 LocalFree(psd);
4725 goto lend;
4728 if (SecurityDescriptorSize)
4729 *SecurityDescriptorSize = cBytes;
4731 bret = TRUE;
4733 lend:
4734 TRACE(" ret=%d\n", bret);
4735 return bret;
4738 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
4740 if (cch == -1)
4741 cch = strlenW(string);
4743 if (plen)
4744 *plen += cch;
4746 if (pwptr)
4748 memcpy(*pwptr, string, sizeof(WCHAR)*cch);
4749 *pwptr += cch;
4753 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
4755 DWORD i;
4756 WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
4757 WCHAR subauthfmt[] = { '-','%','u',0 };
4758 WCHAR buf[26];
4759 SID *pisid = psid;
4761 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
4763 SetLastError(ERROR_INVALID_SID);
4764 return FALSE;
4767 if (pisid->IdentifierAuthority.Value[0] ||
4768 pisid->IdentifierAuthority.Value[1])
4770 FIXME("not matching MS' bugs\n");
4771 SetLastError(ERROR_INVALID_SID);
4772 return FALSE;
4775 sprintfW( buf, fmt, pisid->Revision,
4776 MAKELONG(
4777 MAKEWORD( pisid->IdentifierAuthority.Value[5],
4778 pisid->IdentifierAuthority.Value[4] ),
4779 MAKEWORD( pisid->IdentifierAuthority.Value[3],
4780 pisid->IdentifierAuthority.Value[2] )
4781 ) );
4782 DumpString(buf, -1, pwptr, plen);
4784 for( i=0; i<pisid->SubAuthorityCount; i++ )
4786 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
4787 DumpString(buf, -1, pwptr, plen);
4789 return TRUE;
4792 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
4794 size_t i;
4795 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
4797 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
4799 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
4800 return TRUE;
4804 return DumpSidNumeric(psid, pwptr, plen);
4807 static const LPCWSTR AceRightBitNames[32] = {
4808 SDDL_CREATE_CHILD, /* 0 */
4809 SDDL_DELETE_CHILD,
4810 SDDL_LIST_CHILDREN,
4811 SDDL_SELF_WRITE,
4812 SDDL_READ_PROPERTY, /* 4 */
4813 SDDL_WRITE_PROPERTY,
4814 SDDL_DELETE_TREE,
4815 SDDL_LIST_OBJECT,
4816 SDDL_CONTROL_ACCESS, /* 8 */
4817 NULL,
4818 NULL,
4819 NULL,
4820 NULL, /* 12 */
4821 NULL,
4822 NULL,
4823 NULL,
4824 SDDL_STANDARD_DELETE, /* 16 */
4825 SDDL_READ_CONTROL,
4826 SDDL_WRITE_DAC,
4827 SDDL_WRITE_OWNER,
4828 NULL, /* 20 */
4829 NULL,
4830 NULL,
4831 NULL,
4832 NULL, /* 24 */
4833 NULL,
4834 NULL,
4835 NULL,
4836 SDDL_GENERIC_ALL, /* 28 */
4837 SDDL_GENERIC_EXECUTE,
4838 SDDL_GENERIC_WRITE,
4839 SDDL_GENERIC_READ
4842 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
4844 static const WCHAR fmtW[] = {'0','x','%','x',0};
4845 WCHAR buf[15];
4846 size_t i;
4848 if (mask == 0)
4849 return;
4851 /* first check if the right have name */
4852 for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
4854 if (AceRights[i].wstr == NULL)
4855 break;
4856 if (mask == AceRights[i].value)
4858 DumpString(AceRights[i].wstr, -1, pwptr, plen);
4859 return;
4863 /* then check if it can be built from bit names */
4864 for (i = 0; i < 32; i++)
4866 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
4868 /* can't be built from bit names */
4869 sprintfW(buf, fmtW, mask);
4870 DumpString(buf, -1, pwptr, plen);
4871 return;
4875 /* build from bit names */
4876 for (i = 0; i < 32; i++)
4877 if (mask & (1 << i))
4878 DumpString(AceRightBitNames[i], -1, pwptr, plen);
4881 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
4883 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
4884 static const WCHAR openbr = '(';
4885 static const WCHAR closebr = ')';
4886 static const WCHAR semicolon = ';';
4888 if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
4890 SetLastError(ERROR_INVALID_ACL);
4891 return FALSE;
4894 piace = pace;
4895 DumpString(&openbr, 1, pwptr, plen);
4896 switch (piace->Header.AceType)
4898 case ACCESS_ALLOWED_ACE_TYPE:
4899 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
4900 break;
4901 case ACCESS_DENIED_ACE_TYPE:
4902 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
4903 break;
4904 case SYSTEM_AUDIT_ACE_TYPE:
4905 DumpString(SDDL_AUDIT, -1, pwptr, plen);
4906 break;
4907 case SYSTEM_ALARM_ACE_TYPE:
4908 DumpString(SDDL_ALARM, -1, pwptr, plen);
4909 break;
4911 DumpString(&semicolon, 1, pwptr, plen);
4913 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
4914 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
4915 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
4916 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
4917 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
4918 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
4919 if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
4920 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
4921 if (piace->Header.AceFlags & INHERITED_ACE)
4922 DumpString(SDDL_INHERITED, -1, pwptr, plen);
4923 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
4924 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
4925 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
4926 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
4927 DumpString(&semicolon, 1, pwptr, plen);
4928 DumpRights(piace->Mask, pwptr, plen);
4929 DumpString(&semicolon, 1, pwptr, plen);
4930 /* objects not supported */
4931 DumpString(&semicolon, 1, pwptr, plen);
4932 /* objects not supported */
4933 DumpString(&semicolon, 1, pwptr, plen);
4934 if (!DumpSid(&piace->SidStart, pwptr, plen))
4935 return FALSE;
4936 DumpString(&closebr, 1, pwptr, plen);
4937 return TRUE;
4940 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
4942 WORD count;
4943 UINT i;
4945 if (protected)
4946 DumpString(SDDL_PROTECTED, -1, pwptr, plen);
4947 if (autoInheritReq)
4948 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
4949 if (autoInherited)
4950 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
4952 if (pacl == NULL)
4953 return TRUE;
4955 if (!IsValidAcl(pacl))
4956 return FALSE;
4958 count = pacl->AceCount;
4959 for (i = 0; i < count; i++)
4961 LPVOID ace;
4962 if (!GetAce(pacl, i, &ace))
4963 return FALSE;
4964 if (!DumpAce(ace, pwptr, plen))
4965 return FALSE;
4968 return TRUE;
4971 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4973 static const WCHAR prefix[] = {'O',':',0};
4974 BOOL bDefaulted;
4975 PSID psid;
4977 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
4978 return FALSE;
4980 if (psid == NULL)
4981 return TRUE;
4983 DumpString(prefix, -1, pwptr, plen);
4984 if (!DumpSid(psid, pwptr, plen))
4985 return FALSE;
4986 return TRUE;
4989 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4991 static const WCHAR prefix[] = {'G',':',0};
4992 BOOL bDefaulted;
4993 PSID psid;
4995 if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
4996 return FALSE;
4998 if (psid == NULL)
4999 return TRUE;
5001 DumpString(prefix, -1, pwptr, plen);
5002 if (!DumpSid(psid, pwptr, plen))
5003 return FALSE;
5004 return TRUE;
5007 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
5009 static const WCHAR dacl[] = {'D',':',0};
5010 SECURITY_DESCRIPTOR_CONTROL control;
5011 BOOL present, defaulted;
5012 DWORD revision;
5013 PACL pacl;
5015 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
5016 return FALSE;
5018 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
5019 return FALSE;
5021 if (!present)
5022 return TRUE;
5024 DumpString(dacl, 2, pwptr, plen);
5025 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
5026 return FALSE;
5027 return TRUE;
5030 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
5032 static const WCHAR sacl[] = {'S',':',0};
5033 SECURITY_DESCRIPTOR_CONTROL control;
5034 BOOL present, defaulted;
5035 DWORD revision;
5036 PACL pacl;
5038 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
5039 return FALSE;
5041 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
5042 return FALSE;
5044 if (!present)
5045 return TRUE;
5047 DumpString(sacl, 2, pwptr, plen);
5048 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
5049 return FALSE;
5050 return TRUE;
5053 /******************************************************************************
5054 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
5056 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen)
5058 ULONG len;
5059 WCHAR *wptr, *wstr;
5061 if (SDRevision != SDDL_REVISION_1)
5063 ERR("Program requested unknown SDDL revision %d\n", SDRevision);
5064 SetLastError(ERROR_UNKNOWN_REVISION);
5065 return FALSE;
5068 len = 0;
5069 if (RequestedInformation & OWNER_SECURITY_INFORMATION)
5070 if (!DumpOwner(SecurityDescriptor, NULL, &len))
5071 return FALSE;
5072 if (RequestedInformation & GROUP_SECURITY_INFORMATION)
5073 if (!DumpGroup(SecurityDescriptor, NULL, &len))
5074 return FALSE;
5075 if (RequestedInformation & DACL_SECURITY_INFORMATION)
5076 if (!DumpDacl(SecurityDescriptor, NULL, &len))
5077 return FALSE;
5078 if (RequestedInformation & SACL_SECURITY_INFORMATION)
5079 if (!DumpSacl(SecurityDescriptor, NULL, &len))
5080 return FALSE;
5082 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
5083 if (RequestedInformation & OWNER_SECURITY_INFORMATION)
5084 if (!DumpOwner(SecurityDescriptor, &wptr, NULL)) {
5085 LocalFree (wstr);
5086 return FALSE;
5088 if (RequestedInformation & GROUP_SECURITY_INFORMATION)
5089 if (!DumpGroup(SecurityDescriptor, &wptr, NULL)) {
5090 LocalFree (wstr);
5091 return FALSE;
5093 if (RequestedInformation & DACL_SECURITY_INFORMATION)
5094 if (!DumpDacl(SecurityDescriptor, &wptr, NULL)) {
5095 LocalFree (wstr);
5096 return FALSE;
5098 if (RequestedInformation & SACL_SECURITY_INFORMATION)
5099 if (!DumpSacl(SecurityDescriptor, &wptr, NULL)) {
5100 LocalFree (wstr);
5101 return FALSE;
5103 *wptr = 0;
5105 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
5106 *OutputString = wstr;
5107 if (OutputLen)
5108 *OutputLen = strlenW(*OutputString)+1;
5109 return TRUE;
5112 /******************************************************************************
5113 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
5115 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen)
5117 LPWSTR wstr;
5118 ULONG len;
5119 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
5121 int lenA;
5123 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
5124 *OutputString = heap_alloc(lenA);
5125 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
5126 LocalFree(wstr);
5128 if (OutputLen != NULL)
5129 *OutputLen = lenA;
5130 return TRUE;
5132 else
5134 *OutputString = NULL;
5135 if (OutputLen)
5136 *OutputLen = 0;
5137 return FALSE;
5141 /******************************************************************************
5142 * ConvertStringSidToSidW [ADVAPI32.@]
5144 BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid)
5146 BOOL bret = FALSE;
5147 DWORD cBytes;
5149 TRACE("%s, %p\n", debugstr_w(StringSid), Sid);
5150 if (GetVersion() & 0x80000000)
5151 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5152 else if (!StringSid || !Sid)
5153 SetLastError(ERROR_INVALID_PARAMETER);
5154 else if (ParseStringSidToSid(StringSid, NULL, &cBytes))
5156 PSID pSid = *Sid = LocalAlloc(0, cBytes);
5158 bret = ParseStringSidToSid(StringSid, pSid, &cBytes);
5159 if (!bret)
5160 LocalFree(*Sid);
5162 return bret;
5165 /******************************************************************************
5166 * ConvertStringSidToSidA [ADVAPI32.@]
5168 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
5170 BOOL bret = FALSE;
5172 TRACE("%s, %p\n", debugstr_a(StringSid), Sid);
5173 if (GetVersion() & 0x80000000)
5174 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5175 else if (!StringSid || !Sid)
5176 SetLastError(ERROR_INVALID_PARAMETER);
5177 else
5179 WCHAR *wStringSid = SERV_dup(StringSid);
5180 bret = ConvertStringSidToSidW(wStringSid, Sid);
5181 heap_free(wStringSid);
5183 return bret;
5186 /******************************************************************************
5187 * ConvertSidToStringSidW [ADVAPI32.@]
5189 * format of SID string is:
5190 * S-<count>-<auth>-<subauth1>-<subauth2>-<subauth3>...
5191 * where
5192 * <rev> is the revision of the SID encoded as decimal
5193 * <auth> is the identifier authority encoded as hex
5194 * <subauthN> is the subauthority id encoded as decimal
5196 BOOL WINAPI ConvertSidToStringSidW( PSID pSid, LPWSTR *pstr )
5198 DWORD len = 0;
5199 LPWSTR wstr, wptr;
5201 TRACE("%p %p\n", pSid, pstr );
5203 len = 0;
5204 if (!DumpSidNumeric(pSid, NULL, &len))
5205 return FALSE;
5206 wstr = wptr = LocalAlloc(0, (len+1) * sizeof(WCHAR));
5207 DumpSidNumeric(pSid, &wptr, NULL);
5208 *wptr = 0;
5210 *pstr = wstr;
5211 return TRUE;
5214 /******************************************************************************
5215 * ConvertSidToStringSidA [ADVAPI32.@]
5217 BOOL WINAPI ConvertSidToStringSidA(PSID pSid, LPSTR *pstr)
5219 LPWSTR wstr = NULL;
5220 LPSTR str;
5221 UINT len;
5223 TRACE("%p %p\n", pSid, pstr );
5225 if( !ConvertSidToStringSidW( pSid, &wstr ) )
5226 return FALSE;
5228 len = WideCharToMultiByte( CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL );
5229 str = LocalAlloc( 0, len );
5230 WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, len, NULL, NULL );
5231 LocalFree( wstr );
5233 *pstr = str;
5235 return TRUE;
5238 BOOL WINAPI ConvertToAutoInheritPrivateObjectSecurity(
5239 PSECURITY_DESCRIPTOR pdesc,
5240 PSECURITY_DESCRIPTOR cdesc,
5241 PSECURITY_DESCRIPTOR* ndesc,
5242 GUID* objtype,
5243 BOOL isdir,
5244 PGENERIC_MAPPING genmap )
5246 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
5248 return FALSE;
5251 BOOL WINAPI CreatePrivateObjectSecurity(
5252 PSECURITY_DESCRIPTOR ParentDescriptor,
5253 PSECURITY_DESCRIPTOR CreatorDescriptor,
5254 PSECURITY_DESCRIPTOR* NewDescriptor,
5255 BOOL IsDirectoryObject,
5256 HANDLE Token,
5257 PGENERIC_MAPPING GenericMapping )
5259 SECURITY_DESCRIPTOR_RELATIVE *relative;
5260 DWORD needed, offset;
5261 BYTE *buffer;
5263 FIXME("%p %p %p %d %p %p - returns fake SECURITY_DESCRIPTOR\n", ParentDescriptor,
5264 CreatorDescriptor, NewDescriptor, IsDirectoryObject, Token, GenericMapping);
5266 needed = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5267 needed += sizeof(sidWorld);
5268 needed += sizeof(sidWorld);
5269 needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5270 needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5272 if (!(buffer = heap_alloc( needed ))) return FALSE;
5273 relative = (SECURITY_DESCRIPTOR_RELATIVE *)buffer;
5274 if (!InitializeSecurityDescriptor( relative, SECURITY_DESCRIPTOR_REVISION ))
5276 heap_free( buffer );
5277 return FALSE;
5279 relative->Control |= SE_SELF_RELATIVE;
5280 offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5282 memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5283 relative->Owner = offset;
5284 offset += sizeof(sidWorld);
5286 memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5287 relative->Group = offset;
5288 offset += sizeof(sidWorld);
5290 GetWorldAccessACL( (ACL *)(buffer + offset) );
5291 relative->Dacl = offset;
5292 offset += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5294 GetWorldAccessACL( (ACL *)(buffer + offset) );
5295 relative->Sacl = offset;
5297 *NewDescriptor = relative;
5298 return TRUE;
5301 BOOL WINAPI CreatePrivateObjectSecurityWithMultipleInheritance(
5302 PSECURITY_DESCRIPTOR parent, PSECURITY_DESCRIPTOR creator, PSECURITY_DESCRIPTOR *out,
5303 GUID **types, ULONG count, BOOL is_container, ULONG flags, HANDLE token, PGENERIC_MAPPING mapping)
5305 FIXME(": semi-stub\n");
5306 return CreatePrivateObjectSecurity(parent, creator, out, is_container, token, mapping);
5309 BOOL WINAPI DestroyPrivateObjectSecurity( PSECURITY_DESCRIPTOR* ObjectDescriptor )
5311 FIXME("%p - stub\n", ObjectDescriptor);
5313 heap_free( *ObjectDescriptor );
5314 return TRUE;
5317 BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessAsUserA(
5318 HANDLE hToken,
5319 LPCSTR lpApplicationName,
5320 LPSTR lpCommandLine,
5321 LPSECURITY_ATTRIBUTES lpProcessAttributes,
5322 LPSECURITY_ATTRIBUTES lpThreadAttributes,
5323 BOOL bInheritHandles,
5324 DWORD dwCreationFlags,
5325 LPVOID lpEnvironment,
5326 LPCSTR lpCurrentDirectory,
5327 LPSTARTUPINFOA lpStartupInfo,
5328 LPPROCESS_INFORMATION lpProcessInformation )
5330 BOOL ret;
5331 WCHAR *appW, *cmdlnW, *cwdW;
5332 STARTUPINFOW sinfo;
5334 TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken, debugstr_a(lpApplicationName),
5335 debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
5336 dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
5338 appW = SERV_dup(lpApplicationName);
5339 cmdlnW = SERV_dup(lpCommandLine);
5340 cwdW = SERV_dup(lpCurrentDirectory);
5341 sinfo.cb = sizeof(sinfo);
5342 sinfo.lpReserved = SERV_dup(lpStartupInfo->lpReserved);
5343 sinfo.lpDesktop = SERV_dup(lpStartupInfo->lpDesktop);
5344 sinfo.lpTitle = SERV_dup(lpStartupInfo->lpTitle);
5345 sinfo.dwX = lpStartupInfo->dwX;
5346 sinfo.dwY = lpStartupInfo->dwY;
5347 sinfo.dwXSize = lpStartupInfo->dwXSize;
5348 sinfo.dwYSize = lpStartupInfo->dwYSize;
5349 sinfo.dwXCountChars = lpStartupInfo->dwXCountChars;
5350 sinfo.dwYCountChars = lpStartupInfo->dwYCountChars;
5351 sinfo.dwFillAttribute = lpStartupInfo->dwFillAttribute;
5352 sinfo.dwFlags = lpStartupInfo->dwFlags;
5353 sinfo.wShowWindow = lpStartupInfo->wShowWindow;
5354 sinfo.cbReserved2 = lpStartupInfo->cbReserved2;
5355 sinfo.lpReserved2 = lpStartupInfo->lpReserved2;
5356 sinfo.hStdInput = lpStartupInfo->hStdInput;
5357 sinfo.hStdOutput = lpStartupInfo->hStdOutput;
5358 sinfo.hStdError = lpStartupInfo->hStdError;
5359 ret = CreateProcessAsUserW(hToken, appW, cmdlnW, lpProcessAttributes,
5360 lpThreadAttributes, bInheritHandles, dwCreationFlags,
5361 lpEnvironment, cwdW, &sinfo, lpProcessInformation);
5362 heap_free(appW);
5363 heap_free(cmdlnW);
5364 heap_free(cwdW);
5365 heap_free(sinfo.lpReserved);
5366 heap_free(sinfo.lpDesktop);
5367 heap_free(sinfo.lpTitle);
5369 return ret;
5372 BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessAsUserW(
5373 HANDLE hToken,
5374 LPCWSTR lpApplicationName,
5375 LPWSTR lpCommandLine,
5376 LPSECURITY_ATTRIBUTES lpProcessAttributes,
5377 LPSECURITY_ATTRIBUTES lpThreadAttributes,
5378 BOOL bInheritHandles,
5379 DWORD dwCreationFlags,
5380 LPVOID lpEnvironment,
5381 LPCWSTR lpCurrentDirectory,
5382 LPSTARTUPINFOW lpStartupInfo,
5383 LPPROCESS_INFORMATION lpProcessInformation )
5385 FIXME("%p %s %s %p %p %d 0x%08x %p %s %p %p - semi-stub\n", hToken,
5386 debugstr_w(lpApplicationName), debugstr_w(lpCommandLine), lpProcessAttributes,
5387 lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
5388 debugstr_w(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
5390 /* We should create the process with a suspended main thread */
5391 if (!CreateProcessW (lpApplicationName,
5392 lpCommandLine,
5393 lpProcessAttributes,
5394 lpThreadAttributes,
5395 bInheritHandles,
5396 dwCreationFlags, /* CREATE_SUSPENDED */
5397 lpEnvironment,
5398 lpCurrentDirectory,
5399 lpStartupInfo,
5400 lpProcessInformation))
5402 return FALSE;
5405 return TRUE;
5408 /******************************************************************************
5409 * CreateProcessWithLogonW
5411 BOOL WINAPI CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags,
5412 LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment,
5413 LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
5415 FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
5416 debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
5417 debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
5418 lpStartupInfo, lpProcessInformation);
5420 return FALSE;
5423 BOOL WINAPI CreateProcessWithTokenW(HANDLE token, DWORD logon_flags, LPCWSTR application_name, LPWSTR command_line,
5424 DWORD creation_flags, void *environment, LPCWSTR current_directory, STARTUPINFOW *startup_info,
5425 PROCESS_INFORMATION *process_information )
5427 FIXME("%p 0x%08x %s %s 0x%08x %p %s %p %p - semi-stub\n", token,
5428 logon_flags, debugstr_w(application_name), debugstr_w(command_line),
5429 creation_flags, environment, debugstr_w(current_directory),
5430 startup_info, process_information);
5432 /* FIXME: check if handles should be inherited */
5433 return CreateProcessW( application_name, command_line, NULL, NULL, FALSE, creation_flags, environment,
5434 current_directory, startup_info, process_information );
5437 /******************************************************************************
5438 * DuplicateTokenEx [ADVAPI32.@]
5440 BOOL WINAPI DuplicateTokenEx(
5441 HANDLE ExistingTokenHandle, DWORD dwDesiredAccess,
5442 LPSECURITY_ATTRIBUTES lpTokenAttributes,
5443 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
5444 TOKEN_TYPE TokenType,
5445 PHANDLE DuplicateTokenHandle )
5447 OBJECT_ATTRIBUTES ObjectAttributes;
5449 TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
5450 ImpersonationLevel, TokenType, DuplicateTokenHandle);
5452 InitializeObjectAttributes(
5453 &ObjectAttributes,
5454 NULL,
5455 (lpTokenAttributes && lpTokenAttributes->bInheritHandle) ? OBJ_INHERIT : 0,
5456 NULL,
5457 lpTokenAttributes ? lpTokenAttributes->lpSecurityDescriptor : NULL );
5459 return set_ntstatus( NtDuplicateToken( ExistingTokenHandle,
5460 dwDesiredAccess,
5461 &ObjectAttributes,
5462 ImpersonationLevel,
5463 TokenType,
5464 DuplicateTokenHandle ) );
5467 BOOL WINAPI DuplicateToken(
5468 HANDLE ExistingTokenHandle,
5469 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
5470 PHANDLE DuplicateTokenHandle )
5472 return DuplicateTokenEx( ExistingTokenHandle, TOKEN_IMPERSONATE | TOKEN_QUERY,
5473 NULL, ImpersonationLevel, TokenImpersonation,
5474 DuplicateTokenHandle );
5477 /******************************************************************************
5478 * ComputeStringSidSize
5480 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
5482 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
5484 int ctok = 0;
5485 while (*StringSid)
5487 if (*StringSid == '-')
5488 ctok++;
5489 StringSid++;
5492 if (ctok >= 3)
5493 return GetSidLengthRequired(ctok - 2);
5495 else /* String constant format - Only available in winxp and above */
5497 unsigned int i;
5499 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5500 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5501 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
5503 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
5504 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
5506 MAX_SID local;
5507 ADVAPI_GetComputerSid(&local);
5508 return GetSidLengthRequired(*GetSidSubAuthorityCount(&local) + 1);
5513 return GetSidLengthRequired(0);
5516 /******************************************************************************
5517 * ParseStringSidToSid
5519 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
5521 BOOL bret = FALSE;
5522 SID* pisid=pSid;
5524 TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
5525 if (!StringSid)
5527 SetLastError(ERROR_INVALID_PARAMETER);
5528 TRACE("StringSid is NULL, returning FALSE\n");
5529 return FALSE;
5532 while (*StringSid == ' ')
5533 StringSid++;
5535 *cBytes = ComputeStringSidSize(StringSid);
5536 if (!pisid) /* Simply compute the size */
5538 TRACE("only size requested, returning TRUE with %d\n", *cBytes);
5539 return TRUE;
5542 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
5544 DWORD i = 0, identAuth;
5545 DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
5547 StringSid += 2; /* Advance to Revision */
5548 pisid->Revision = atoiW(StringSid);
5550 if (pisid->Revision != SDDL_REVISION)
5552 TRACE("Revision %d is unknown\n", pisid->Revision);
5553 goto lend; /* ERROR_INVALID_SID */
5555 if (csubauth == 0)
5557 TRACE("SubAuthorityCount is 0\n");
5558 goto lend; /* ERROR_INVALID_SID */
5561 pisid->SubAuthorityCount = csubauth;
5563 /* Advance to identifier authority */
5564 while (*StringSid && *StringSid != '-')
5565 StringSid++;
5566 if (*StringSid == '-')
5567 StringSid++;
5569 /* MS' implementation can't handle values greater than 2^32 - 1, so
5570 * we don't either; assume most significant bytes are always 0
5572 pisid->IdentifierAuthority.Value[0] = 0;
5573 pisid->IdentifierAuthority.Value[1] = 0;
5574 identAuth = atoiW(StringSid);
5575 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
5576 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
5577 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
5578 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
5580 /* Advance to first sub authority */
5581 while (*StringSid && *StringSid != '-')
5582 StringSid++;
5583 if (*StringSid == '-')
5584 StringSid++;
5586 while (*StringSid)
5588 pisid->SubAuthority[i++] = atoiW(StringSid);
5590 while (*StringSid && *StringSid != '-')
5591 StringSid++;
5592 if (*StringSid == '-')
5593 StringSid++;
5596 if (i != pisid->SubAuthorityCount)
5597 goto lend; /* ERROR_INVALID_SID */
5599 bret = TRUE;
5601 else /* String constant format - Only available in winxp and above */
5603 unsigned int i;
5604 pisid->Revision = SDDL_REVISION;
5606 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5607 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5609 DWORD j;
5610 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
5611 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
5612 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
5613 pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
5614 bret = TRUE;
5617 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
5618 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
5620 ADVAPI_GetComputerSid(pisid);
5621 pisid->SubAuthority[pisid->SubAuthorityCount] = WellKnownRids[i].Rid;
5622 pisid->SubAuthorityCount++;
5623 bret = TRUE;
5626 if (!bret)
5627 FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
5630 lend:
5631 if (!bret)
5632 SetLastError(ERROR_INVALID_SID);
5634 TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
5635 return bret;
5638 /******************************************************************************
5639 * GetNamedSecurityInfoA [ADVAPI32.@]
5641 DWORD WINAPI GetNamedSecurityInfoA(LPSTR pObjectName,
5642 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5643 PSID* ppsidOwner, PSID* ppsidGroup, PACL* ppDacl, PACL* ppSacl,
5644 PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
5646 LPWSTR wstr;
5647 DWORD r;
5649 TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo,
5650 ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
5652 wstr = SERV_dup(pObjectName);
5653 r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
5654 ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
5656 heap_free( wstr );
5658 return r;
5661 /******************************************************************************
5662 * GetNamedSecurityInfoW [ADVAPI32.@]
5664 DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type,
5665 SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl,
5666 PACL* sacl, PSECURITY_DESCRIPTOR* descriptor )
5668 DWORD access = 0;
5669 HANDLE handle;
5670 DWORD err;
5672 TRACE( "%s %d %d %p %p %p %p %p\n", debugstr_w(name), type, info, owner,
5673 group, dacl, sacl, descriptor );
5675 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
5676 if (!name || !(owner||group||dacl||sacl||descriptor) ) return ERROR_INVALID_PARAMETER;
5678 /* If no descriptor, we have to check that there's a pointer for the requested information */
5679 if( !descriptor && (
5680 ((info & OWNER_SECURITY_INFORMATION) && !owner)
5681 || ((info & GROUP_SECURITY_INFORMATION) && !group)
5682 || ((info & DACL_SECURITY_INFORMATION) && !dacl)
5683 || ((info & SACL_SECURITY_INFORMATION) && !sacl) ))
5684 return ERROR_INVALID_PARAMETER;
5686 if (info & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION))
5687 access |= READ_CONTROL;
5688 if (info & SACL_SECURITY_INFORMATION)
5689 access |= ACCESS_SYSTEM_SECURITY;
5691 switch (type)
5693 case SE_SERVICE:
5694 if (!(err = get_security_service( name, access, &handle )))
5696 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5697 CloseServiceHandle( handle );
5699 break;
5700 case SE_REGISTRY_KEY:
5701 if (!(err = get_security_regkey( name, access, &handle )))
5703 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5704 RegCloseKey( handle );
5706 break;
5707 case SE_FILE_OBJECT:
5708 if (!(err = get_security_file( name, access, &handle )))
5710 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5711 CloseHandle( handle );
5713 break;
5714 default:
5715 FIXME( "Object type %d is not currently supported.\n", type );
5716 if (owner) *owner = NULL;
5717 if (group) *group = NULL;
5718 if (dacl) *dacl = NULL;
5719 if (sacl) *sacl = NULL;
5720 if (descriptor) *descriptor = NULL;
5721 return ERROR_SUCCESS;
5723 return err;
5726 /******************************************************************************
5727 * GetNamedSecurityInfoExW [ADVAPI32.@]
5729 DWORD WINAPI GetNamedSecurityInfoExW( LPCWSTR object, SE_OBJECT_TYPE type,
5730 SECURITY_INFORMATION info, LPCWSTR provider, LPCWSTR property,
5731 PACTRL_ACCESSW* access_list, PACTRL_AUDITW* audit_list, LPWSTR* owner, LPWSTR* group )
5733 FIXME("(%s, %d, %d, %s, %s, %p, %p, %p, %p) stub\n", debugstr_w(object), type, info,
5734 debugstr_w(provider), debugstr_w(property), access_list, audit_list, owner, group);
5735 return ERROR_CALL_NOT_IMPLEMENTED;
5738 /******************************************************************************
5739 * GetNamedSecurityInfoExA [ADVAPI32.@]
5741 DWORD WINAPI GetNamedSecurityInfoExA( LPCSTR object, SE_OBJECT_TYPE type,
5742 SECURITY_INFORMATION info, LPCSTR provider, LPCSTR property,
5743 PACTRL_ACCESSA* access_list, PACTRL_AUDITA* audit_list, LPSTR* owner, LPSTR* group )
5745 FIXME("(%s, %d, %d, %s, %s, %p, %p, %p, %p) stub\n", debugstr_a(object), type, info,
5746 debugstr_a(provider), debugstr_a(property), access_list, audit_list, owner, group);
5747 return ERROR_CALL_NOT_IMPLEMENTED;
5750 /******************************************************************************
5751 * DecryptFileW [ADVAPI32.@]
5753 BOOL WINAPI DecryptFileW(LPCWSTR lpFileName, DWORD dwReserved)
5755 FIXME("(%s, %08x): stub\n", debugstr_w(lpFileName), dwReserved);
5756 return TRUE;
5759 /******************************************************************************
5760 * DecryptFileA [ADVAPI32.@]
5762 BOOL WINAPI DecryptFileA(LPCSTR lpFileName, DWORD dwReserved)
5764 FIXME("(%s, %08x): stub\n", debugstr_a(lpFileName), dwReserved);
5765 return TRUE;
5768 /******************************************************************************
5769 * EncryptFileW [ADVAPI32.@]
5771 BOOL WINAPI EncryptFileW(LPCWSTR lpFileName)
5773 FIXME("(%s): stub\n", debugstr_w(lpFileName));
5774 return TRUE;
5777 /******************************************************************************
5778 * EncryptFileA [ADVAPI32.@]
5780 BOOL WINAPI EncryptFileA(LPCSTR lpFileName)
5782 FIXME("(%s): stub\n", debugstr_a(lpFileName));
5783 return TRUE;
5786 /******************************************************************************
5787 * FileEncryptionStatusW [ADVAPI32.@]
5789 BOOL WINAPI FileEncryptionStatusW(LPCWSTR lpFileName, LPDWORD lpStatus)
5791 FIXME("(%s %p): stub\n", debugstr_w(lpFileName), lpStatus);
5792 if (!lpStatus)
5793 return FALSE;
5794 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5795 return TRUE;
5798 /******************************************************************************
5799 * FileEncryptionStatusA [ADVAPI32.@]
5801 BOOL WINAPI FileEncryptionStatusA(LPCSTR lpFileName, LPDWORD lpStatus)
5803 FIXME("(%s %p): stub\n", debugstr_a(lpFileName), lpStatus);
5804 if (!lpStatus)
5805 return FALSE;
5806 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5807 return TRUE;
5810 /******************************************************************************
5811 * SetSecurityInfo [ADVAPI32.@]
5813 DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType,
5814 SECURITY_INFORMATION SecurityInfo, PSID psidOwner,
5815 PSID psidGroup, PACL pDacl, PACL pSacl)
5817 SECURITY_DESCRIPTOR sd;
5818 PACL dacl = pDacl;
5819 NTSTATUS status;
5821 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
5822 return ERROR_INVALID_SECURITY_DESCR;
5824 if (SecurityInfo & OWNER_SECURITY_INFORMATION)
5825 SetSecurityDescriptorOwner(&sd, psidOwner, FALSE);
5826 if (SecurityInfo & GROUP_SECURITY_INFORMATION)
5827 SetSecurityDescriptorGroup(&sd, psidGroup, FALSE);
5828 if (SecurityInfo & DACL_SECURITY_INFORMATION)
5830 if (ObjectType == SE_FILE_OBJECT && pDacl)
5832 SECURITY_DESCRIPTOR_CONTROL control;
5833 PSECURITY_DESCRIPTOR psd;
5834 OBJECT_NAME_INFORMATION *name_info;
5835 DWORD size, rev;
5837 status = NtQuerySecurityObject(handle, SecurityInfo, NULL, 0, &size);
5838 if (status != STATUS_BUFFER_TOO_SMALL)
5839 return RtlNtStatusToDosError(status);
5841 psd = heap_alloc(size);
5842 if (!psd)
5843 return ERROR_NOT_ENOUGH_MEMORY;
5845 status = NtQuerySecurityObject(handle, SecurityInfo, psd, size, &size);
5846 if (status)
5848 heap_free(psd);
5849 return RtlNtStatusToDosError(status);
5852 status = RtlGetControlSecurityDescriptor(psd, &control, &rev);
5853 heap_free(psd);
5854 if (status)
5855 return RtlNtStatusToDosError(status);
5856 /* TODO: copy some control flags to new sd */
5858 /* inherit parent directory DACL */
5859 if (!(control & SE_DACL_PROTECTED))
5861 status = NtQueryObject(handle, ObjectNameInformation, NULL, 0, &size);
5862 if (status != STATUS_INFO_LENGTH_MISMATCH)
5863 return RtlNtStatusToDosError(status);
5865 name_info = heap_alloc(size);
5866 if (!name_info)
5867 return ERROR_NOT_ENOUGH_MEMORY;
5869 status = NtQueryObject(handle, ObjectNameInformation, name_info, size, NULL);
5870 if (status)
5872 heap_free(name_info);
5873 return RtlNtStatusToDosError(status);
5876 for (name_info->Name.Length-=2; name_info->Name.Length>0; name_info->Name.Length-=2)
5877 if (name_info->Name.Buffer[name_info->Name.Length/2-1]=='\\' ||
5878 name_info->Name.Buffer[name_info->Name.Length/2-1]=='/')
5879 break;
5880 if (name_info->Name.Length)
5882 OBJECT_ATTRIBUTES attr;
5883 IO_STATUS_BLOCK io;
5884 HANDLE parent;
5885 PSECURITY_DESCRIPTOR parent_sd;
5886 ACL *parent_dacl;
5887 DWORD err = ERROR_ACCESS_DENIED;
5889 name_info->Name.Buffer[name_info->Name.Length/2] = 0;
5891 attr.Length = sizeof(attr);
5892 attr.RootDirectory = 0;
5893 attr.Attributes = 0;
5894 attr.ObjectName = &name_info->Name;
5895 attr.SecurityDescriptor = NULL;
5896 status = NtOpenFile(&parent, READ_CONTROL|SYNCHRONIZE, &attr, &io,
5897 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5898 FILE_OPEN_FOR_BACKUP_INTENT);
5899 heap_free(name_info);
5900 if (!status)
5902 err = GetSecurityInfo(parent, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
5903 NULL, NULL, &parent_dacl, NULL, &parent_sd);
5904 CloseHandle(parent);
5907 if (!err)
5909 int i;
5911 dacl = heap_alloc_zero(pDacl->AclSize+parent_dacl->AclSize);
5912 if (!dacl)
5914 LocalFree(parent_sd);
5915 return ERROR_NOT_ENOUGH_MEMORY;
5917 memcpy(dacl, pDacl, pDacl->AclSize);
5918 dacl->AclSize = pDacl->AclSize+parent_dacl->AclSize;
5920 for (i=0; i<parent_dacl->AceCount; i++)
5922 ACE_HEADER *ace;
5924 if (!GetAce(parent_dacl, i, (void*)&ace))
5925 continue;
5926 if (!(ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)))
5927 continue;
5928 if ((ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)) !=
5929 (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE))
5931 FIXME("unsupported flags: %x\n", ace->AceFlags);
5932 continue;
5935 if (ace->AceFlags & NO_PROPAGATE_INHERIT_ACE)
5936 ace->AceFlags &= ~(OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE|NO_PROPAGATE_INHERIT_ACE);
5937 ace->AceFlags &= ~INHERIT_ONLY_ACE;
5938 ace->AceFlags |= INHERITED_ACE;
5940 if(!AddAce(dacl, ACL_REVISION, MAXDWORD, ace, ace->AceSize))
5941 WARN("error adding inherited ACE\n");
5943 LocalFree(parent_sd);
5946 else
5947 heap_free(name_info);
5951 SetSecurityDescriptorDacl(&sd, TRUE, dacl, FALSE);
5953 if (SecurityInfo & SACL_SECURITY_INFORMATION)
5954 SetSecurityDescriptorSacl(&sd, TRUE, pSacl, FALSE);
5956 switch (ObjectType)
5958 case SE_SERVICE:
5959 FIXME("stub: Service objects are not supported at this time.\n");
5960 status = STATUS_SUCCESS; /* Implement SetServiceObjectSecurity */
5961 break;
5962 default:
5963 status = NtSetSecurityObject(handle, SecurityInfo, &sd);
5964 break;
5966 if (dacl != pDacl)
5967 heap_free(dacl);
5968 return RtlNtStatusToDosError(status);
5971 /******************************************************************************
5972 * SaferCreateLevel [ADVAPI32.@]
5974 BOOL WINAPI SaferCreateLevel(DWORD ScopeId, DWORD LevelId, DWORD OpenFlags,
5975 SAFER_LEVEL_HANDLE* LevelHandle, LPVOID lpReserved)
5977 FIXME("(%u, %x, %u, %p, %p) stub\n", ScopeId, LevelId, OpenFlags, LevelHandle, lpReserved);
5979 *LevelHandle = (SAFER_LEVEL_HANDLE)0xdeadbeef;
5980 return TRUE;
5983 /******************************************************************************
5984 * SaferComputeTokenFromLevel [ADVAPI32.@]
5986 BOOL WINAPI SaferComputeTokenFromLevel(SAFER_LEVEL_HANDLE handle, HANDLE token, PHANDLE access_token,
5987 DWORD flags, LPVOID reserved)
5989 FIXME("(%p, %p, %p, %x, %p) stub\n", handle, token, access_token, flags, reserved);
5991 *access_token = (HANDLE)0xdeadbeef;
5992 return TRUE;
5995 /******************************************************************************
5996 * SaferCloseLevel [ADVAPI32.@]
5998 BOOL WINAPI SaferCloseLevel(SAFER_LEVEL_HANDLE handle)
6000 FIXME("(%p) stub\n", handle);
6001 return TRUE;
6004 DWORD WINAPI TreeResetNamedSecurityInfoW( LPWSTR pObjectName,
6005 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
6006 PSID pOwner, PSID pGroup, PACL pDacl, PACL pSacl,
6007 BOOL KeepExplicit, FN_PROGRESS fnProgress,
6008 PROG_INVOKE_SETTING ProgressInvokeSetting, PVOID Args)
6010 FIXME("(%s, %i, %i, %p, %p, %p, %p, %i, %p, %i, %p) stub\n",
6011 debugstr_w(pObjectName), ObjectType, SecurityInfo, pOwner, pGroup,
6012 pDacl, pSacl, KeepExplicit, fnProgress, ProgressInvokeSetting, Args);
6014 return ERROR_SUCCESS;
6017 /******************************************************************************
6018 * SaferGetPolicyInformation [ADVAPI32.@]
6020 BOOL WINAPI SaferGetPolicyInformation(DWORD scope, SAFER_POLICY_INFO_CLASS class, DWORD size,
6021 PVOID buffer, PDWORD required, LPVOID lpReserved)
6023 FIXME("(%u %u %u %p %p %p) stub\n", scope, class, size, buffer, required, lpReserved);
6024 return FALSE;
6027 /******************************************************************************
6028 * SaferSetLevelInformation [ADVAPI32.@]
6030 BOOL WINAPI SaferSetLevelInformation(SAFER_LEVEL_HANDLE handle, SAFER_OBJECT_INFO_CLASS infotype,
6031 LPVOID buffer, DWORD size)
6033 FIXME("(%p %u %p %u) stub\n", handle, infotype, buffer, size);
6034 return FALSE;