d3d8/tests: Test presentation parameter combinations.
[wine.git] / dlls / advapi32 / security.c
blobe8f64d5219d71316c8f546fccdeadde73381d86e
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 <stdarg.h>
23 #include <string.h>
25 #include "ntstatus.h"
26 #define WIN32_NO_STATUS
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "winreg.h"
31 #include "winsafer.h"
32 #include "winternl.h"
33 #include "winioctl.h"
34 #include "accctrl.h"
35 #include "sddl.h"
36 #include "winsvc.h"
37 #include "aclapi.h"
38 #include "objbase.h"
39 #include "iads.h"
40 #include "advapi32_misc.h"
41 #include "lmcons.h"
43 #include "wine/debug.h"
44 #include "wine/unicode.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
48 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes);
49 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
50 PACL pAcl, LPDWORD cBytes);
51 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl);
52 static BYTE ParseAceStringType(LPCWSTR* StringAcl);
53 static DWORD ParseAceStringRights(LPCWSTR* StringAcl);
54 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
55 LPCWSTR StringSecurityDescriptor,
56 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
57 LPDWORD cBytes);
58 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl);
60 typedef struct _ACEFLAG
62 LPCWSTR wstr;
63 DWORD value;
64 } ACEFLAG, *LPACEFLAG;
66 typedef struct _MAX_SID
68 /* same fields as struct _SID */
69 BYTE Revision;
70 BYTE SubAuthorityCount;
71 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
72 DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
73 } MAX_SID;
75 typedef struct WELLKNOWNSID
77 WCHAR wstr[2];
78 WELL_KNOWN_SID_TYPE Type;
79 MAX_SID Sid;
80 } WELLKNOWNSID;
82 static const WELLKNOWNSID WellKnownSids[] =
84 { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } },
85 { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } },
86 { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } },
87 { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } },
88 { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } },
89 { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } },
90 { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } },
91 { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } },
92 { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } },
93 { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } },
94 { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } },
95 { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } },
96 { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } },
97 { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } },
98 { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } },
99 { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } },
100 { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } },
101 { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } },
102 { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } },
103 { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } },
104 { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } },
105 { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } },
106 { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } },
107 { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } },
108 { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } },
109 { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } },
110 { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } },
111 { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } },
112 { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } },
113 { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } },
114 { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } },
115 { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } },
116 { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } },
117 { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } },
118 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } },
119 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } },
120 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } },
121 { {0,0}, WinNTLMAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID } } },
122 { {0,0}, WinDigestAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID } } },
123 { {0,0}, WinSChannelAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID } } },
124 { {0,0}, WinThisOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_THIS_ORGANIZATION_RID } } },
125 { {0,0}, WinOtherOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_OTHER_ORGANIZATION_RID } } },
126 { {0,0}, WinBuiltinIncomingForestTrustBuildersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS } } },
127 { {0,0}, WinBuiltinPerfMonitoringUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS } } },
128 { {0,0}, WinBuiltinPerfLoggingUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS } } },
129 { {0,0}, WinBuiltinAuthorizationAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS } } },
130 { {0,0}, WinBuiltinTerminalServerLicenseServersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS } } },
131 { {0,0}, WinBuiltinDCOMUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS } } },
132 { {'L','W'}, WinLowLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_LOW_RID} } },
133 { {'M','E'}, WinMediumLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_MEDIUM_RID } } },
134 { {'H','I'}, WinHighLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_HIGH_RID } } },
135 { {'S','I'}, WinSystemLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_SYSTEM_RID } } },
136 { {0,0}, WinBuiltinAnyPackageSid, { SID_REVISION, 2, { SECURITY_APP_PACKAGE_AUTHORITY }, { SECURITY_APP_PACKAGE_BASE_RID, SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE } } },
139 /* these SIDs must be constructed as relative to some domain - only the RID is well-known */
140 typedef struct WELLKNOWNRID
142 WCHAR wstr[2];
143 WELL_KNOWN_SID_TYPE Type;
144 DWORD Rid;
145 } WELLKNOWNRID;
147 static const WELLKNOWNRID WellKnownRids[] = {
148 { {'L','A'}, WinAccountAdministratorSid, DOMAIN_USER_RID_ADMIN },
149 { {'L','G'}, WinAccountGuestSid, DOMAIN_USER_RID_GUEST },
150 { {0,0}, WinAccountKrbtgtSid, DOMAIN_USER_RID_KRBTGT },
151 { {'D','A'}, WinAccountDomainAdminsSid, DOMAIN_GROUP_RID_ADMINS },
152 { {'D','U'}, WinAccountDomainUsersSid, DOMAIN_GROUP_RID_USERS },
153 { {'D','G'}, WinAccountDomainGuestsSid, DOMAIN_GROUP_RID_GUESTS },
154 { {'D','C'}, WinAccountComputersSid, DOMAIN_GROUP_RID_COMPUTERS },
155 { {'D','D'}, WinAccountControllersSid, DOMAIN_GROUP_RID_CONTROLLERS },
156 { {'C','A'}, WinAccountCertAdminsSid, DOMAIN_GROUP_RID_CERT_ADMINS },
157 { {'S','A'}, WinAccountSchemaAdminsSid, DOMAIN_GROUP_RID_SCHEMA_ADMINS },
158 { {'E','A'}, WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS },
159 { {'P','A'}, WinAccountPolicyAdminsSid, DOMAIN_GROUP_RID_POLICY_ADMINS },
160 { {'R','S'}, WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS },
164 static SID const sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
166 typedef struct _AccountSid {
167 WELL_KNOWN_SID_TYPE type;
168 LPCWSTR account;
169 LPCWSTR domain;
170 SID_NAME_USE name_use;
171 LPCWSTR alias;
172 } AccountSid;
174 static const WCHAR Account_Operators[] = { 'A','c','c','o','u','n','t',' ','O','p','e','r','a','t','o','r','s',0 };
175 static const WCHAR Administrator[] = {'A','d','m','i','n','i','s','t','r','a','t','o','r',0 };
176 static const WCHAR Administrators[] = { 'A','d','m','i','n','i','s','t','r','a','t','o','r','s',0 };
177 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 };
178 static const WCHAR ANONYMOUS_LOGON[] = { 'A','N','O','N','Y','M','O','U','S',' ','L','O','G','O','N',0 };
179 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 };
180 static const WCHAR Authenticated_Users[] = { 'A','u','t','h','e','n','t','i','c','a','t','e','d',' ','U','s','e','r','s',0 };
181 static const WCHAR Backup_Operators[] = { 'B','a','c','k','u','p',' ','O','p','e','r','a','t','o','r','s',0 };
182 static const WCHAR BATCH[] = { 'B','A','T','C','H',0 };
183 static const WCHAR Blank[] = { 0 };
184 static const WCHAR BUILTIN[] = { 'B','U','I','L','T','I','N',0 };
185 static const WCHAR Cert_Publishers[] = { 'C','e','r','t',' ','P','u','b','l','i','s','h','e','r','s',0 };
186 static const WCHAR CREATOR_GROUP[] = { 'C','R','E','A','T','O','R',' ','G','R','O','U','P',0 };
187 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 };
188 static const WCHAR CREATOR_OWNER[] = { 'C','R','E','A','T','O','R',' ','O','W','N','E','R',0 };
189 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 };
190 static const WCHAR CURRENT_USER[] = { 'C','U','R','R','E','N','T','_','U','S','E','R',0 };
191 static const WCHAR DIALUP[] = { 'D','I','A','L','U','P',0 };
192 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 };
193 static const WCHAR Domain_Admins[] = { 'D','o','m','a','i','n',' ','A','d','m','i','n','s',0 };
194 static const WCHAR Domain_Computers[] = { 'D','o','m','a','i','n',' ','C','o','m','p','u','t','e','r','s',0 };
195 static const WCHAR Domain_Controllers[] = { 'D','o','m','a','i','n',' ','C','o','n','t','r','o','l','l','e','r','s',0 };
196 static const WCHAR Domain_Guests[] = { 'D','o','m','a','i','n',' ','G','u','e','s','t','s',0 };
197 static const WCHAR Domain_Users[] = { 'D','o','m','a','i','n',' ','U','s','e','r','s',0 };
198 static const WCHAR Enterprise_Admins[] = { 'E','n','t','e','r','p','r','i','s','e',' ','A','d','m','i','n','s',0 };
199 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 };
200 static const WCHAR Everyone[] = { 'E','v','e','r','y','o','n','e',0 };
201 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 };
202 static const WCHAR Guest[] = { 'G','u','e','s','t',0 };
203 static const WCHAR Guests[] = { 'G','u','e','s','t','s',0 };
204 static const WCHAR INTERACTIVE[] = { 'I','N','T','E','R','A','C','T','I','V','E',0 };
205 static const WCHAR LOCAL[] = { 'L','O','C','A','L',0 };
206 static const WCHAR LOCAL_SERVICE[] = { 'L','O','C','A','L',' ','S','E','R','V','I','C','E',0 };
207 static const WCHAR LOCAL_SERVICE2[] = { 'L','O','C','A','L','S','E','R','V','I','C','E',0 };
208 static const WCHAR NETWORK[] = { 'N','E','T','W','O','R','K',0 };
209 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 };
210 static const WCHAR NETWORK_SERVICE[] = { 'N','E','T','W','O','R','K',' ','S','E','R','V','I','C','E',0 };
211 static const WCHAR NETWORK_SERVICE2[] = { 'N','E','T','W','O','R','K','S','E','R','V','I','C','E',0 };
212 static const WCHAR NT_AUTHORITY[] = { 'N','T',' ','A','U','T','H','O','R','I','T','Y',0 };
213 static const WCHAR NT_Pseudo_Domain[] = { 'N','T',' ','P','s','e','u','d','o',' ','D','o','m','a','i','n',0 };
214 static const WCHAR NTML_Authentication[] = { 'N','T','M','L',' ','A','u','t','h','e','n','t','i','c','a','t','i','o','n',0 };
215 static const WCHAR NULL_SID[] = { 'N','U','L','L',' ','S','I','D',0 };
216 static const WCHAR Other_Organization[] = { 'O','t','h','e','r',' ','O','r','g','a','n','i','z','a','t','i','o','n',0 };
217 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 };
218 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 };
219 static const WCHAR Power_Users[] = { 'P','o','w','e','r',' ','U','s','e','r','s',0 };
220 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 };
221 static const WCHAR Print_Operators[] = { 'P','r','i','n','t',' ','O','p','e','r','a','t','o','r','s',0 };
222 static const WCHAR PROXY[] = { 'P','R','O','X','Y',0 };
223 static const WCHAR RAS_and_IAS_Servers[] = { 'R','A','S',' ','a','n','d',' ','I','A','S',' ','S','e','r','v','e','r','s',0 };
224 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 };
225 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 };
226 static const WCHAR Replicators[] = { 'R','e','p','l','i','c','a','t','o','r','s',0 };
227 static const WCHAR RESTRICTED[] = { 'R','E','S','T','R','I','C','T','E','D',0 };
228 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 };
229 static const WCHAR Schema_Admins[] = { 'S','c','h','e','m','a',' ','A','d','m','i','n','s',0 };
230 static const WCHAR SELF[] = { 'S','E','L','F',0 };
231 static const WCHAR Server_Operators[] = { 'S','e','r','v','e','r',' ','O','p','e','r','a','t','o','r','s',0 };
232 static const WCHAR SERVICE[] = { 'S','E','R','V','I','C','E',0 };
233 static const WCHAR SYSTEM[] = { 'S','Y','S','T','E','M',0 };
234 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 };
235 static const WCHAR This_Organization[] = { 'T','h','i','s',' ','O','r','g','a','n','i','z','a','t','i','o','n',0 };
236 static const WCHAR Users[] = { 'U','s','e','r','s',0 };
238 static const AccountSid ACCOUNT_SIDS[] = {
239 { WinNullSid, NULL_SID, Blank, SidTypeWellKnownGroup },
240 { WinWorldSid, Everyone, Blank, SidTypeWellKnownGroup },
241 { WinLocalSid, LOCAL, Blank, SidTypeWellKnownGroup },
242 { WinCreatorOwnerSid, CREATOR_OWNER, Blank, SidTypeWellKnownGroup },
243 { WinCreatorGroupSid, CREATOR_GROUP, Blank, SidTypeWellKnownGroup },
244 { WinCreatorOwnerServerSid, CREATOR_OWNER_SERVER, Blank, SidTypeWellKnownGroup },
245 { WinCreatorGroupServerSid, CREATOR_GROUP_SERVER, Blank, SidTypeWellKnownGroup },
246 { WinNtAuthoritySid, NT_Pseudo_Domain, NT_Pseudo_Domain, SidTypeDomain },
247 { WinDialupSid, DIALUP, NT_AUTHORITY, SidTypeWellKnownGroup },
248 { WinNetworkSid, NETWORK, NT_AUTHORITY, SidTypeWellKnownGroup },
249 { WinBatchSid, BATCH, NT_AUTHORITY, SidTypeWellKnownGroup },
250 { WinInteractiveSid, INTERACTIVE, NT_AUTHORITY, SidTypeWellKnownGroup },
251 { WinServiceSid, SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup },
252 { WinAnonymousSid, ANONYMOUS_LOGON, NT_AUTHORITY, SidTypeWellKnownGroup },
253 { WinProxySid, PROXY, NT_AUTHORITY, SidTypeWellKnownGroup },
254 { WinEnterpriseControllersSid, ENTERPRISE_DOMAIN_CONTROLLERS, NT_AUTHORITY, SidTypeWellKnownGroup },
255 { WinSelfSid, SELF, NT_AUTHORITY, SidTypeWellKnownGroup },
256 { WinAuthenticatedUserSid, Authenticated_Users, NT_AUTHORITY, SidTypeWellKnownGroup },
257 { WinRestrictedCodeSid, RESTRICTED, NT_AUTHORITY, SidTypeWellKnownGroup },
258 { WinTerminalServerSid, TERMINAL_SERVER_USER, NT_AUTHORITY, SidTypeWellKnownGroup },
259 { WinRemoteLogonIdSid, REMOTE_INTERACTIVE_LOGON, NT_AUTHORITY, SidTypeWellKnownGroup },
260 { WinLocalSystemSid, SYSTEM, NT_AUTHORITY, SidTypeWellKnownGroup },
261 { WinLocalServiceSid, LOCAL_SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup, LOCAL_SERVICE2 },
262 { WinNetworkServiceSid, NETWORK_SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup , NETWORK_SERVICE2},
263 { WinBuiltinDomainSid, BUILTIN, BUILTIN, SidTypeDomain },
264 { WinBuiltinAdministratorsSid, Administrators, BUILTIN, SidTypeAlias },
265 { WinBuiltinUsersSid, Users, BUILTIN, SidTypeAlias },
266 { WinBuiltinGuestsSid, Guests, BUILTIN, SidTypeAlias },
267 { WinBuiltinPowerUsersSid, Power_Users, BUILTIN, SidTypeAlias },
268 { WinBuiltinAccountOperatorsSid, Account_Operators, BUILTIN, SidTypeAlias },
269 { WinBuiltinSystemOperatorsSid, Server_Operators, BUILTIN, SidTypeAlias },
270 { WinBuiltinPrintOperatorsSid, Print_Operators, BUILTIN, SidTypeAlias },
271 { WinBuiltinBackupOperatorsSid, Backup_Operators, BUILTIN, SidTypeAlias },
272 { WinBuiltinReplicatorSid, Replicators, BUILTIN, SidTypeAlias },
273 { WinBuiltinPreWindows2000CompatibleAccessSid, Pre_Windows_2000_Compatible_Access, BUILTIN, SidTypeAlias },
274 { WinBuiltinRemoteDesktopUsersSid, Remote_Desktop_Users, BUILTIN, SidTypeAlias },
275 { WinBuiltinNetworkConfigurationOperatorsSid, Network_Configuration_Operators, BUILTIN, SidTypeAlias },
276 { WinNTLMAuthenticationSid, NTML_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
277 { WinDigestAuthenticationSid, Digest_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
278 { WinSChannelAuthenticationSid, SChannel_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
279 { WinThisOrganizationSid, This_Organization, NT_AUTHORITY, SidTypeWellKnownGroup },
280 { WinOtherOrganizationSid, Other_Organization, NT_AUTHORITY, SidTypeWellKnownGroup },
281 { WinBuiltinPerfMonitoringUsersSid, Performance_Monitor_Users, BUILTIN, SidTypeAlias },
282 { WinBuiltinPerfLoggingUsersSid, Performance_Log_Users, BUILTIN, SidTypeAlias },
283 { WinBuiltinAnyPackageSid, ALL_APPLICATION_PACKAGES, APPLICATION_PACKAGE_AUTHORITY, SidTypeWellKnownGroup },
286 * ACE access rights
288 static const WCHAR SDDL_READ_CONTROL[] = {'R','C',0};
289 static const WCHAR SDDL_WRITE_DAC[] = {'W','D',0};
290 static const WCHAR SDDL_WRITE_OWNER[] = {'W','O',0};
291 static const WCHAR SDDL_STANDARD_DELETE[] = {'S','D',0};
293 static const WCHAR SDDL_READ_PROPERTY[] = {'R','P',0};
294 static const WCHAR SDDL_WRITE_PROPERTY[] = {'W','P',0};
295 static const WCHAR SDDL_CREATE_CHILD[] = {'C','C',0};
296 static const WCHAR SDDL_DELETE_CHILD[] = {'D','C',0};
297 static const WCHAR SDDL_LIST_CHILDREN[] = {'L','C',0};
298 static const WCHAR SDDL_SELF_WRITE[] = {'S','W',0};
299 static const WCHAR SDDL_LIST_OBJECT[] = {'L','O',0};
300 static const WCHAR SDDL_DELETE_TREE[] = {'D','T',0};
301 static const WCHAR SDDL_CONTROL_ACCESS[] = {'C','R',0};
303 static const WCHAR SDDL_FILE_ALL[] = {'F','A',0};
304 static const WCHAR SDDL_FILE_READ[] = {'F','R',0};
305 static const WCHAR SDDL_FILE_WRITE[] = {'F','W',0};
306 static const WCHAR SDDL_FILE_EXECUTE[] = {'F','X',0};
308 static const WCHAR SDDL_KEY_ALL[] = {'K','A',0};
309 static const WCHAR SDDL_KEY_READ[] = {'K','R',0};
310 static const WCHAR SDDL_KEY_WRITE[] = {'K','W',0};
311 static const WCHAR SDDL_KEY_EXECUTE[] = {'K','X',0};
313 static const WCHAR SDDL_GENERIC_ALL[] = {'G','A',0};
314 static const WCHAR SDDL_GENERIC_READ[] = {'G','R',0};
315 static const WCHAR SDDL_GENERIC_WRITE[] = {'G','W',0};
316 static const WCHAR SDDL_GENERIC_EXECUTE[] = {'G','X',0};
318 static const WCHAR SDDL_NO_READ_UP[] = {'N','R',0};
319 static const WCHAR SDDL_NO_WRITE_UP[] = {'N','W',0};
320 static const WCHAR SDDL_NO_EXECUTE_UP[] = {'N','X',0};
323 * ACL flags
325 static const WCHAR SDDL_PROTECTED[] = {'P',0};
326 static const WCHAR SDDL_AUTO_INHERIT_REQ[] = {'A','R',0};
327 static const WCHAR SDDL_AUTO_INHERITED[] = {'A','I',0};
330 * ACE types
332 static const WCHAR SDDL_ACCESS_ALLOWED[] = {'A',0};
333 static const WCHAR SDDL_ACCESS_DENIED[] = {'D',0};
334 static const WCHAR SDDL_AUDIT[] = {'A','U',0};
335 static const WCHAR SDDL_ALARM[] = {'A','L',0};
336 static const WCHAR SDDL_MANDATORY_LABEL[] = {'M','L',0};
339 * ACE flags
341 static const WCHAR SDDL_CONTAINER_INHERIT[] = {'C','I',0};
342 static const WCHAR SDDL_OBJECT_INHERIT[] = {'O','I',0};
343 static const WCHAR SDDL_NO_PROPAGATE[] = {'N','P',0};
344 static const WCHAR SDDL_INHERIT_ONLY[] = {'I','O',0};
345 static const WCHAR SDDL_INHERITED[] = {'I','D',0};
346 static const WCHAR SDDL_AUDIT_SUCCESS[] = {'S','A',0};
347 static const WCHAR SDDL_AUDIT_FAILURE[] = {'F','A',0};
349 const char * debugstr_sid(PSID sid)
351 int auth = 0;
352 SID * psid = sid;
354 if (psid == NULL)
355 return "(null)";
357 auth = psid->IdentifierAuthority.Value[5] +
358 (psid->IdentifierAuthority.Value[4] << 8) +
359 (psid->IdentifierAuthority.Value[3] << 16) +
360 (psid->IdentifierAuthority.Value[2] << 24);
362 switch (psid->SubAuthorityCount) {
363 case 0:
364 return wine_dbg_sprintf("S-%d-%d", psid->Revision, auth);
365 case 1:
366 return wine_dbg_sprintf("S-%d-%d-%u", psid->Revision, auth,
367 psid->SubAuthority[0]);
368 case 2:
369 return wine_dbg_sprintf("S-%d-%d-%u-%u", psid->Revision, auth,
370 psid->SubAuthority[0], psid->SubAuthority[1]);
371 case 3:
372 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u", psid->Revision, auth,
373 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]);
374 case 4:
375 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u", psid->Revision, auth,
376 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
377 psid->SubAuthority[3]);
378 case 5:
379 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u", psid->Revision, auth,
380 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
381 psid->SubAuthority[3], psid->SubAuthority[4]);
382 case 6:
383 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
384 psid->SubAuthority[3], psid->SubAuthority[1], psid->SubAuthority[2],
385 psid->SubAuthority[0], psid->SubAuthority[4], psid->SubAuthority[5]);
386 case 7:
387 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
388 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
389 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
390 psid->SubAuthority[6]);
391 case 8:
392 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
393 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
394 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
395 psid->SubAuthority[6], psid->SubAuthority[7]);
397 return "(too-big)";
400 /* set last error code from NT status and get the proper boolean return value */
401 /* used for functions that are a simple wrapper around the corresponding ntdll API */
402 static inline BOOL set_ntstatus( NTSTATUS status )
404 if (status) SetLastError( RtlNtStatusToDosError( status ));
405 return !status;
408 /* helper function for SE_FILE_OBJECT objects in [Get|Set]NamedSecurityInfo */
409 static inline DWORD get_security_file( LPCWSTR full_file_name, DWORD access, HANDLE *file )
411 UNICODE_STRING file_nameW;
412 OBJECT_ATTRIBUTES attr;
413 IO_STATUS_BLOCK io;
414 NTSTATUS status;
416 if (!RtlDosPathNameToNtPathName_U( full_file_name, &file_nameW, NULL, NULL ))
417 return ERROR_PATH_NOT_FOUND;
418 attr.Length = sizeof(attr);
419 attr.RootDirectory = 0;
420 attr.Attributes = OBJ_CASE_INSENSITIVE;
421 attr.ObjectName = &file_nameW;
422 attr.SecurityDescriptor = NULL;
423 status = NtCreateFile( file, access, &attr, &io, NULL, FILE_FLAG_BACKUP_SEMANTICS,
424 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN,
425 FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0 );
426 RtlFreeUnicodeString( &file_nameW );
427 return RtlNtStatusToDosError( status );
430 /* helper function for SE_SERVICE objects in [Get|Set]NamedSecurityInfo */
431 static inline DWORD get_security_service( LPWSTR full_service_name, DWORD access, HANDLE *service )
433 SC_HANDLE manager = 0;
434 DWORD err;
436 err = SERV_OpenSCManagerW( NULL, NULL, access, (SC_HANDLE *)&manager );
437 if (err == ERROR_SUCCESS)
439 err = SERV_OpenServiceW( manager, full_service_name, access, (SC_HANDLE *)service );
440 CloseServiceHandle( manager );
442 return err;
445 /* helper function for SE_REGISTRY_KEY objects in [Get|Set]NamedSecurityInfo */
446 static inline DWORD get_security_regkey( LPWSTR full_key_name, DWORD access, HANDLE *key )
448 WCHAR classes_rootW[] = {'C','L','A','S','S','E','S','_','R','O','O','T',0};
449 WCHAR current_userW[] = {'C','U','R','R','E','N','T','_','U','S','E','R',0};
450 WCHAR machineW[] = {'M','A','C','H','I','N','E',0};
451 WCHAR usersW[] = {'U','S','E','R','S',0};
452 LPWSTR p = strchrW(full_key_name, '\\');
453 int len = p-full_key_name;
454 HKEY hParent;
456 if (!p) return ERROR_INVALID_PARAMETER;
457 if (strncmpW( full_key_name, classes_rootW, len ) == 0)
458 hParent = HKEY_CLASSES_ROOT;
459 else if (strncmpW( full_key_name, current_userW, len ) == 0)
460 hParent = HKEY_CURRENT_USER;
461 else if (strncmpW( full_key_name, machineW, len ) == 0)
462 hParent = HKEY_LOCAL_MACHINE;
463 else if (strncmpW( full_key_name, usersW, len ) == 0)
464 hParent = HKEY_USERS;
465 else
466 return ERROR_INVALID_PARAMETER;
467 return RegOpenKeyExW( hParent, p+1, 0, access, (HKEY *)key );
470 #define WINE_SIZE_OF_WORLD_ACCESS_ACL (sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD))
472 static void GetWorldAccessACL(PACL pACL)
474 PACCESS_ALLOWED_ACE pACE = (PACCESS_ALLOWED_ACE) (pACL + 1);
476 pACL->AclRevision = ACL_REVISION;
477 pACL->Sbz1 = 0;
478 pACL->AclSize = WINE_SIZE_OF_WORLD_ACCESS_ACL;
479 pACL->AceCount = 1;
480 pACL->Sbz2 = 0;
482 pACE->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
483 pACE->Header.AceFlags = CONTAINER_INHERIT_ACE;
484 pACE->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD);
485 pACE->Mask = 0xf3ffffff; /* Everything except reserved bits */
486 memcpy(&pACE->SidStart, &sidWorld, sizeof(sidWorld));
489 /************************************************************
490 * ADVAPI_IsLocalComputer
492 * Checks whether the server name indicates local machine.
494 BOOL ADVAPI_IsLocalComputer(LPCWSTR ServerName)
496 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
497 BOOL Result;
498 LPWSTR buf;
500 if (!ServerName || !ServerName[0])
501 return TRUE;
503 buf = heap_alloc(dwSize * sizeof(WCHAR));
504 Result = GetComputerNameW(buf, &dwSize);
505 if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\'))
506 ServerName += 2;
507 Result = Result && !lstrcmpW(ServerName, buf);
508 heap_free(buf);
510 return Result;
513 /************************************************************
514 * ADVAPI_GetComputerSid
516 BOOL ADVAPI_GetComputerSid(PSID sid)
518 static const struct /* same fields as struct SID */
520 BYTE Revision;
521 BYTE SubAuthorityCount;
522 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
523 DWORD SubAuthority[4];
524 } computer_sid =
525 { SID_REVISION, 4, { SECURITY_NT_AUTHORITY }, { SECURITY_NT_NON_UNIQUE, 0, 0, 0 } };
527 memcpy( sid, &computer_sid, sizeof(computer_sid) );
528 return TRUE;
531 /* ##############################
532 ###### TOKEN FUNCTIONS ######
533 ##############################
536 /******************************************************************************
537 * OpenProcessToken [ADVAPI32.@]
538 * Opens the access token associated with a process handle.
540 * PARAMS
541 * ProcessHandle [I] Handle to process
542 * DesiredAccess [I] Desired access to process
543 * TokenHandle [O] Pointer to handle of open access token
545 * RETURNS
546 * Success: TRUE. TokenHandle contains the access token.
547 * Failure: FALSE.
549 * NOTES
550 * See NtOpenProcessToken.
552 BOOL WINAPI
553 OpenProcessToken( HANDLE ProcessHandle, DWORD DesiredAccess,
554 HANDLE *TokenHandle )
556 return set_ntstatus(NtOpenProcessToken( ProcessHandle, DesiredAccess, TokenHandle ));
559 /******************************************************************************
560 * OpenThreadToken [ADVAPI32.@]
562 * Opens the access token associated with a thread handle.
564 * PARAMS
565 * ThreadHandle [I] Handle to process
566 * DesiredAccess [I] Desired access to the thread
567 * OpenAsSelf [I] ???
568 * TokenHandle [O] Destination for the token handle
570 * RETURNS
571 * Success: TRUE. TokenHandle contains the access token.
572 * Failure: FALSE.
574 * NOTES
575 * See NtOpenThreadToken.
577 BOOL WINAPI
578 OpenThreadToken( HANDLE ThreadHandle, DWORD DesiredAccess,
579 BOOL OpenAsSelf, HANDLE *TokenHandle)
581 return set_ntstatus( NtOpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf, TokenHandle));
584 BOOL WINAPI
585 AdjustTokenGroups( HANDLE TokenHandle, BOOL ResetToDefault, PTOKEN_GROUPS NewState,
586 DWORD BufferLength, PTOKEN_GROUPS PreviousState, PDWORD ReturnLength )
588 return set_ntstatus( NtAdjustGroupsToken(TokenHandle, ResetToDefault, NewState, BufferLength,
589 PreviousState, ReturnLength));
592 /******************************************************************************
593 * AdjustTokenPrivileges [ADVAPI32.@]
595 * Adjust the privileges of an open token handle.
597 * PARAMS
598 * TokenHandle [I] Handle from OpenProcessToken() or OpenThreadToken()
599 * DisableAllPrivileges [I] TRUE=Remove all privileges, FALSE=Use NewState
600 * NewState [I] Desired new privileges of the token
601 * BufferLength [I] Length of NewState
602 * PreviousState [O] Destination for the previous state
603 * ReturnLength [I/O] Size of PreviousState
606 * RETURNS
607 * Success: TRUE. Privileges are set to NewState and PreviousState is updated.
608 * Failure: FALSE.
610 * NOTES
611 * See NtAdjustPrivilegesToken.
613 BOOL WINAPI
614 AdjustTokenPrivileges( HANDLE TokenHandle, BOOL DisableAllPrivileges,
615 PTOKEN_PRIVILEGES NewState, DWORD BufferLength,
616 PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength )
618 NTSTATUS status;
620 TRACE("(%p %d %p %d %p %p)\n", TokenHandle, DisableAllPrivileges, NewState, BufferLength,
621 PreviousState, ReturnLength);
623 status = NtAdjustPrivilegesToken(TokenHandle, DisableAllPrivileges,
624 NewState, BufferLength, PreviousState,
625 ReturnLength);
626 SetLastError( RtlNtStatusToDosError( status ));
627 if ((status == STATUS_SUCCESS) || (status == STATUS_NOT_ALL_ASSIGNED))
628 return TRUE;
629 else
630 return FALSE;
633 /******************************************************************************
634 * CheckTokenMembership [ADVAPI32.@]
636 * Determine if an access token is a member of a SID.
638 * PARAMS
639 * TokenHandle [I] Handle from OpenProcessToken() or OpenThreadToken()
640 * SidToCheck [I] SID that possibly contains the token
641 * IsMember [O] Destination for result.
643 * RETURNS
644 * Success: TRUE. IsMember is TRUE if TokenHandle is a member, FALSE otherwise.
645 * Failure: FALSE.
647 BOOL WINAPI
648 CheckTokenMembership( HANDLE token, PSID sid_to_check,
649 PBOOL is_member )
651 PTOKEN_GROUPS token_groups = NULL;
652 HANDLE thread_token = NULL;
653 DWORD size, i;
654 BOOL ret;
656 TRACE("(%p %s %p)\n", token, debugstr_sid(sid_to_check), is_member);
658 *is_member = FALSE;
660 if (!token)
662 if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &thread_token))
664 HANDLE process_token;
665 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &process_token);
666 if (!ret)
667 goto exit;
668 ret = DuplicateTokenEx(process_token, TOKEN_QUERY,
669 NULL, SecurityImpersonation, TokenImpersonation,
670 &thread_token);
671 CloseHandle(process_token);
672 if (!ret)
673 goto exit;
675 token = thread_token;
677 else
679 TOKEN_TYPE type;
681 ret = GetTokenInformation(token, TokenType, &type, sizeof(TOKEN_TYPE), &size);
682 if (!ret) goto exit;
684 if (type == TokenPrimary)
686 SetLastError(ERROR_NO_IMPERSONATION_TOKEN);
687 return FALSE;
691 ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size);
692 if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
693 goto exit;
695 token_groups = heap_alloc(size);
696 if (!token_groups)
698 ret = FALSE;
699 goto exit;
702 ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size);
703 if (!ret)
704 goto exit;
706 for (i = 0; i < token_groups->GroupCount; i++)
708 TRACE("Groups[%d]: {0x%x, %s}\n", i,
709 token_groups->Groups[i].Attributes,
710 debugstr_sid(token_groups->Groups[i].Sid));
711 if ((token_groups->Groups[i].Attributes & SE_GROUP_ENABLED) &&
712 EqualSid(sid_to_check, token_groups->Groups[i].Sid))
714 *is_member = TRUE;
715 TRACE("sid enabled and found in token\n");
716 break;
720 exit:
721 heap_free(token_groups);
722 if (thread_token != NULL) CloseHandle(thread_token);
724 return ret;
727 /******************************************************************************
728 * GetTokenInformation [ADVAPI32.@]
730 * Get a type of information about an access token.
732 * PARAMS
733 * token [I] Handle from OpenProcessToken() or OpenThreadToken()
734 * tokeninfoclass [I] A TOKEN_INFORMATION_CLASS from "winnt.h"
735 * tokeninfo [O] Destination for token information
736 * tokeninfolength [I] Length of tokeninfo
737 * retlen [O] Destination for returned token information length
739 * RETURNS
740 * Success: TRUE. tokeninfo contains retlen bytes of token information
741 * Failure: FALSE.
743 * NOTES
744 * See NtQueryInformationToken.
746 BOOL WINAPI
747 GetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS tokeninfoclass,
748 LPVOID tokeninfo, DWORD tokeninfolength, LPDWORD retlen )
750 TRACE("(%p, %s, %p, %d, %p):\n",
751 token,
752 (tokeninfoclass == TokenUser) ? "TokenUser" :
753 (tokeninfoclass == TokenGroups) ? "TokenGroups" :
754 (tokeninfoclass == TokenPrivileges) ? "TokenPrivileges" :
755 (tokeninfoclass == TokenOwner) ? "TokenOwner" :
756 (tokeninfoclass == TokenPrimaryGroup) ? "TokenPrimaryGroup" :
757 (tokeninfoclass == TokenDefaultDacl) ? "TokenDefaultDacl" :
758 (tokeninfoclass == TokenSource) ? "TokenSource" :
759 (tokeninfoclass == TokenType) ? "TokenType" :
760 (tokeninfoclass == TokenImpersonationLevel) ? "TokenImpersonationLevel" :
761 (tokeninfoclass == TokenStatistics) ? "TokenStatistics" :
762 (tokeninfoclass == TokenRestrictedSids) ? "TokenRestrictedSids" :
763 (tokeninfoclass == TokenSessionId) ? "TokenSessionId" :
764 (tokeninfoclass == TokenGroupsAndPrivileges) ? "TokenGroupsAndPrivileges" :
765 (tokeninfoclass == TokenSessionReference) ? "TokenSessionReference" :
766 (tokeninfoclass == TokenSandBoxInert) ? "TokenSandBoxInert" :
767 "Unknown",
768 tokeninfo, tokeninfolength, retlen);
769 return set_ntstatus( NtQueryInformationToken( token, tokeninfoclass, tokeninfo,
770 tokeninfolength, retlen));
773 /******************************************************************************
774 * SetTokenInformation [ADVAPI32.@]
776 * Set information for an access token.
778 * PARAMS
779 * token [I] Handle from OpenProcessToken() or OpenThreadToken()
780 * tokeninfoclass [I] A TOKEN_INFORMATION_CLASS from "winnt.h"
781 * tokeninfo [I] Token information to set
782 * tokeninfolength [I] Length of tokeninfo
784 * RETURNS
785 * Success: TRUE. The information for the token is set to tokeninfo.
786 * Failure: FALSE.
788 BOOL WINAPI
789 SetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS tokeninfoclass,
790 LPVOID tokeninfo, DWORD tokeninfolength )
792 TRACE("(%p, %s, %p, %d): stub\n",
793 token,
794 (tokeninfoclass == TokenUser) ? "TokenUser" :
795 (tokeninfoclass == TokenGroups) ? "TokenGroups" :
796 (tokeninfoclass == TokenPrivileges) ? "TokenPrivileges" :
797 (tokeninfoclass == TokenOwner) ? "TokenOwner" :
798 (tokeninfoclass == TokenPrimaryGroup) ? "TokenPrimaryGroup" :
799 (tokeninfoclass == TokenDefaultDacl) ? "TokenDefaultDacl" :
800 (tokeninfoclass == TokenSource) ? "TokenSource" :
801 (tokeninfoclass == TokenType) ? "TokenType" :
802 (tokeninfoclass == TokenImpersonationLevel) ? "TokenImpersonationLevel" :
803 (tokeninfoclass == TokenStatistics) ? "TokenStatistics" :
804 (tokeninfoclass == TokenRestrictedSids) ? "TokenRestrictedSids" :
805 (tokeninfoclass == TokenSessionId) ? "TokenSessionId" :
806 (tokeninfoclass == TokenGroupsAndPrivileges) ? "TokenGroupsAndPrivileges" :
807 (tokeninfoclass == TokenSessionReference) ? "TokenSessionReference" :
808 (tokeninfoclass == TokenSandBoxInert) ? "TokenSandBoxInert" :
809 "Unknown",
810 tokeninfo, tokeninfolength);
812 return set_ntstatus( NtSetInformationToken( token, tokeninfoclass, tokeninfo, tokeninfolength ));
815 /*************************************************************************
816 * SetThreadToken [ADVAPI32.@]
818 * Assigns an 'impersonation token' to a thread so it can assume the
819 * security privileges of another thread or process. Can also remove
820 * a previously assigned token.
822 * PARAMS
823 * thread [O] Handle to thread to set the token for
824 * token [I] Token to set
826 * RETURNS
827 * Success: TRUE. The threads access token is set to token
828 * Failure: FALSE.
830 * NOTES
831 * Only supported on NT or higher. On Win9X this function does nothing.
832 * See SetTokenInformation.
834 BOOL WINAPI SetThreadToken(PHANDLE thread, HANDLE token)
836 return set_ntstatus( NtSetInformationThread( thread ? *thread : GetCurrentThread(),
837 ThreadImpersonationToken, &token, sizeof token ));
840 /*************************************************************************
841 * CreateRestrictedToken [ADVAPI32.@]
843 * Create a new more restricted token from an existing token.
845 * PARAMS
846 * baseToken [I] Token to base the new restricted token on
847 * flags [I] Options
848 * nDisableSids [I] Length of disableSids array
849 * disableSids [I] Array of SIDs to disable in the new token
850 * nDeletePrivs [I] Length of deletePrivs array
851 * deletePrivs [I] Array of privileges to delete in the new token
852 * nRestrictSids [I] Length of restrictSids array
853 * restrictSids [I] Array of SIDs to restrict in the new token
854 * newToken [O] Address where the new token is stored
856 * RETURNS
857 * Success: TRUE
858 * Failure: FALSE
860 BOOL WINAPI CreateRestrictedToken(
861 HANDLE baseToken,
862 DWORD flags,
863 DWORD nDisableSids,
864 PSID_AND_ATTRIBUTES disableSids,
865 DWORD nDeletePrivs,
866 PLUID_AND_ATTRIBUTES deletePrivs,
867 DWORD nRestrictSids,
868 PSID_AND_ATTRIBUTES restrictSids,
869 PHANDLE newToken)
871 TOKEN_TYPE type;
872 SECURITY_IMPERSONATION_LEVEL level = TokenImpersonationLevel;
873 DWORD size;
875 FIXME("(%p, 0x%x, %u, %p, %u, %p, %u, %p, %p): stub\n",
876 baseToken, flags, nDisableSids, disableSids,
877 nDeletePrivs, deletePrivs,
878 nRestrictSids, restrictSids,
879 newToken);
881 size = sizeof(type);
882 if (!GetTokenInformation( baseToken, TokenType, &type, size, &size )) return FALSE;
883 if (type == TokenImpersonation)
885 size = sizeof(level);
886 if (!GetTokenInformation( baseToken, TokenImpersonationLevel, &level, size, &size ))
887 return FALSE;
889 return DuplicateTokenEx( baseToken, MAXIMUM_ALLOWED, NULL, level, type, newToken );
892 /* ##############################
893 ###### SID FUNCTIONS ######
894 ##############################
897 /******************************************************************************
898 * AllocateAndInitializeSid [ADVAPI32.@]
900 * PARAMS
901 * pIdentifierAuthority []
902 * nSubAuthorityCount []
903 * nSubAuthority0 []
904 * nSubAuthority1 []
905 * nSubAuthority2 []
906 * nSubAuthority3 []
907 * nSubAuthority4 []
908 * nSubAuthority5 []
909 * nSubAuthority6 []
910 * nSubAuthority7 []
911 * pSid []
913 BOOL WINAPI
914 AllocateAndInitializeSid( PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
915 BYTE nSubAuthorityCount,
916 DWORD nSubAuthority0, DWORD nSubAuthority1,
917 DWORD nSubAuthority2, DWORD nSubAuthority3,
918 DWORD nSubAuthority4, DWORD nSubAuthority5,
919 DWORD nSubAuthority6, DWORD nSubAuthority7,
920 PSID *pSid )
922 return set_ntstatus( RtlAllocateAndInitializeSid(
923 pIdentifierAuthority, nSubAuthorityCount,
924 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
925 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7,
926 pSid ));
929 /******************************************************************************
930 * FreeSid [ADVAPI32.@]
932 * PARAMS
933 * pSid []
935 PVOID WINAPI
936 FreeSid( PSID pSid )
938 RtlFreeSid(pSid);
939 return NULL; /* is documented like this */
942 /******************************************************************************
943 * CopySid [ADVAPI32.@]
945 * PARAMS
946 * nDestinationSidLength []
947 * pDestinationSid []
948 * pSourceSid []
950 BOOL WINAPI
951 CopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
953 return RtlCopySid(nDestinationSidLength, pDestinationSid, pSourceSid);
956 /******************************************************************************
957 * CreateWellKnownSid [ADVAPI32.@]
959 BOOL WINAPI
960 CreateWellKnownSid( WELL_KNOWN_SID_TYPE WellKnownSidType,
961 PSID DomainSid,
962 PSID pSid,
963 DWORD* cbSid)
965 unsigned int i;
966 TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
968 if (cbSid == NULL || (DomainSid && !IsValidSid(DomainSid)))
970 SetLastError(ERROR_INVALID_PARAMETER);
971 return FALSE;
974 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) {
975 if (WellKnownSids[i].Type == WellKnownSidType) {
976 DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
978 if (*cbSid < length)
980 *cbSid = length;
981 SetLastError(ERROR_INSUFFICIENT_BUFFER);
982 return FALSE;
984 if (!pSid)
986 SetLastError(ERROR_INVALID_PARAMETER);
987 return FALSE;
989 CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
990 *cbSid = length;
991 return TRUE;
995 if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES)
997 SetLastError(ERROR_INVALID_PARAMETER);
998 return FALSE;
1001 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
1002 if (WellKnownRids[i].Type == WellKnownSidType) {
1003 UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid);
1004 DWORD domain_sid_length = GetSidLengthRequired(domain_subauth);
1005 DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1);
1007 if (*cbSid < output_sid_length)
1009 *cbSid = output_sid_length;
1010 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1011 return FALSE;
1013 if (!pSid)
1015 SetLastError(ERROR_INVALID_PARAMETER);
1016 return FALSE;
1018 CopyMemory(pSid, DomainSid, domain_sid_length);
1019 (*GetSidSubAuthorityCount(pSid))++;
1020 (*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid;
1021 *cbSid = output_sid_length;
1022 return TRUE;
1025 SetLastError(ERROR_INVALID_PARAMETER);
1026 return FALSE;
1029 /******************************************************************************
1030 * IsWellKnownSid [ADVAPI32.@]
1032 BOOL WINAPI
1033 IsWellKnownSid( PSID pSid, WELL_KNOWN_SID_TYPE WellKnownSidType )
1035 unsigned int i;
1036 TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
1038 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
1039 if (WellKnownSids[i].Type == WellKnownSidType)
1040 if (EqualSid(pSid, (PSID)&(WellKnownSids[i].Sid.Revision)))
1041 return TRUE;
1043 return FALSE;
1046 BOOL WINAPI
1047 IsTokenRestricted( HANDLE TokenHandle )
1049 TOKEN_GROUPS *groups;
1050 DWORD size;
1051 NTSTATUS status;
1052 BOOL restricted;
1054 TRACE("(%p)\n", TokenHandle);
1056 status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, NULL, 0, &size);
1057 if (status != STATUS_BUFFER_TOO_SMALL)
1058 return FALSE;
1060 groups = heap_alloc(size);
1061 if (!groups)
1063 SetLastError(ERROR_OUTOFMEMORY);
1064 return FALSE;
1067 status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, groups, size, &size);
1068 if (status != STATUS_SUCCESS)
1070 heap_free(groups);
1071 return set_ntstatus(status);
1074 restricted = groups->GroupCount > 0;
1075 heap_free(groups);
1077 return restricted;
1080 /******************************************************************************
1081 * IsValidSid [ADVAPI32.@]
1083 * PARAMS
1084 * pSid []
1086 BOOL WINAPI
1087 IsValidSid( PSID pSid )
1089 return RtlValidSid( pSid );
1092 /******************************************************************************
1093 * EqualSid [ADVAPI32.@]
1095 * PARAMS
1096 * pSid1 []
1097 * pSid2 []
1099 BOOL WINAPI
1100 EqualSid( PSID pSid1, PSID pSid2 )
1102 BOOL ret = RtlEqualSid( pSid1, pSid2 );
1103 SetLastError(ERROR_SUCCESS);
1104 return ret;
1107 /******************************************************************************
1108 * EqualPrefixSid [ADVAPI32.@]
1110 BOOL WINAPI EqualPrefixSid (PSID pSid1, PSID pSid2)
1112 return RtlEqualPrefixSid(pSid1, pSid2);
1115 /******************************************************************************
1116 * GetSidLengthRequired [ADVAPI32.@]
1118 * PARAMS
1119 * nSubAuthorityCount []
1121 DWORD WINAPI
1122 GetSidLengthRequired( BYTE nSubAuthorityCount )
1124 return RtlLengthRequiredSid(nSubAuthorityCount);
1127 /******************************************************************************
1128 * InitializeSid [ADVAPI32.@]
1130 * PARAMS
1131 * pIdentifierAuthority []
1133 BOOL WINAPI
1134 InitializeSid (
1135 PSID pSid,
1136 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
1137 BYTE nSubAuthorityCount)
1139 return RtlInitializeSid(pSid, pIdentifierAuthority, nSubAuthorityCount);
1142 DWORD WINAPI
1143 GetEffectiveRightsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pAccessRights )
1145 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
1147 *pAccessRights = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
1148 return 0;
1151 DWORD WINAPI
1152 GetEffectiveRightsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pAccessRights )
1154 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
1156 return 1;
1159 /******************************************************************************
1160 * GetSidIdentifierAuthority [ADVAPI32.@]
1162 * PARAMS
1163 * pSid []
1165 PSID_IDENTIFIER_AUTHORITY WINAPI
1166 GetSidIdentifierAuthority( PSID pSid )
1168 return RtlIdentifierAuthoritySid(pSid);
1171 /******************************************************************************
1172 * GetSidSubAuthority [ADVAPI32.@]
1174 * PARAMS
1175 * pSid []
1176 * nSubAuthority []
1178 PDWORD WINAPI
1179 GetSidSubAuthority( PSID pSid, DWORD nSubAuthority )
1181 SetLastError(ERROR_SUCCESS);
1182 return RtlSubAuthoritySid(pSid, nSubAuthority);
1185 /******************************************************************************
1186 * GetSidSubAuthorityCount [ADVAPI32.@]
1188 * PARAMS
1189 * pSid []
1191 PUCHAR WINAPI
1192 GetSidSubAuthorityCount (PSID pSid)
1194 SetLastError(ERROR_SUCCESS);
1195 return RtlSubAuthorityCountSid(pSid);
1198 /******************************************************************************
1199 * GetLengthSid [ADVAPI32.@]
1201 * PARAMS
1202 * pSid []
1204 DWORD WINAPI
1205 GetLengthSid (PSID pSid)
1207 return RtlLengthSid(pSid);
1210 /* ##############################################
1211 ###### SECURITY DESCRIPTOR FUNCTIONS ######
1212 ##############################################
1215 /******************************************************************************
1216 * BuildSecurityDescriptorA [ADVAPI32.@]
1218 * Builds a SD from
1220 * PARAMS
1221 * pOwner [I]
1222 * pGroup [I]
1223 * cCountOfAccessEntries [I]
1224 * pListOfAccessEntries [I]
1225 * cCountOfAuditEntries [I]
1226 * pListofAuditEntries [I]
1227 * pOldSD [I]
1228 * lpdwBufferLength [I/O]
1229 * pNewSD [O]
1231 * RETURNS
1232 * Success: ERROR_SUCCESS
1233 * Failure: nonzero error code from Winerror.h
1235 DWORD WINAPI BuildSecurityDescriptorA(
1236 IN PTRUSTEEA pOwner,
1237 IN PTRUSTEEA pGroup,
1238 IN ULONG cCountOfAccessEntries,
1239 IN PEXPLICIT_ACCESSA pListOfAccessEntries,
1240 IN ULONG cCountOfAuditEntries,
1241 IN PEXPLICIT_ACCESSA pListofAuditEntries,
1242 IN PSECURITY_DESCRIPTOR pOldSD,
1243 IN OUT PULONG lpdwBufferLength,
1244 OUT PSECURITY_DESCRIPTOR* pNewSD)
1246 FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
1247 cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
1248 pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
1250 return ERROR_CALL_NOT_IMPLEMENTED;
1253 /******************************************************************************
1254 * BuildSecurityDescriptorW [ADVAPI32.@]
1256 * See BuildSecurityDescriptorA.
1258 DWORD WINAPI BuildSecurityDescriptorW(
1259 IN PTRUSTEEW pOwner,
1260 IN PTRUSTEEW pGroup,
1261 IN ULONG cCountOfAccessEntries,
1262 IN PEXPLICIT_ACCESSW pListOfAccessEntries,
1263 IN ULONG cCountOfAuditEntries,
1264 IN PEXPLICIT_ACCESSW pListofAuditEntries,
1265 IN PSECURITY_DESCRIPTOR pOldSD,
1266 IN OUT PULONG lpdwBufferLength,
1267 OUT PSECURITY_DESCRIPTOR* pNewSD)
1269 FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
1270 cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
1271 pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
1273 return ERROR_CALL_NOT_IMPLEMENTED;
1276 /******************************************************************************
1277 * InitializeSecurityDescriptor [ADVAPI32.@]
1279 * PARAMS
1280 * pDescr []
1281 * revision []
1283 BOOL WINAPI
1284 InitializeSecurityDescriptor( PSECURITY_DESCRIPTOR pDescr, DWORD revision )
1286 return set_ntstatus( RtlCreateSecurityDescriptor(pDescr, revision ));
1290 /******************************************************************************
1291 * MakeAbsoluteSD [ADVAPI32.@]
1293 BOOL WINAPI MakeAbsoluteSD (
1294 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
1295 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
1296 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
1297 OUT PACL pDacl,
1298 OUT LPDWORD lpdwDaclSize,
1299 OUT PACL pSacl,
1300 OUT LPDWORD lpdwSaclSize,
1301 OUT PSID pOwner,
1302 OUT LPDWORD lpdwOwnerSize,
1303 OUT PSID pPrimaryGroup,
1304 OUT LPDWORD lpdwPrimaryGroupSize)
1306 return set_ntstatus( RtlSelfRelativeToAbsoluteSD(pSelfRelativeSecurityDescriptor,
1307 pAbsoluteSecurityDescriptor,
1308 lpdwAbsoluteSecurityDescriptorSize,
1309 pDacl, lpdwDaclSize, pSacl, lpdwSaclSize,
1310 pOwner, lpdwOwnerSize,
1311 pPrimaryGroup, lpdwPrimaryGroupSize));
1314 /******************************************************************************
1315 * GetKernelObjectSecurity [ADVAPI32.@]
1317 BOOL WINAPI GetKernelObjectSecurity(
1318 HANDLE Handle,
1319 SECURITY_INFORMATION RequestedInformation,
1320 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1321 DWORD nLength,
1322 LPDWORD lpnLengthNeeded )
1324 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", Handle, RequestedInformation,
1325 pSecurityDescriptor, nLength, lpnLengthNeeded);
1327 return set_ntstatus( NtQuerySecurityObject(Handle, RequestedInformation, pSecurityDescriptor,
1328 nLength, lpnLengthNeeded ));
1331 /******************************************************************************
1332 * GetPrivateObjectSecurity [ADVAPI32.@]
1334 BOOL WINAPI GetPrivateObjectSecurity(
1335 PSECURITY_DESCRIPTOR ObjectDescriptor,
1336 SECURITY_INFORMATION SecurityInformation,
1337 PSECURITY_DESCRIPTOR ResultantDescriptor,
1338 DWORD DescriptorLength,
1339 PDWORD ReturnLength )
1341 SECURITY_DESCRIPTOR desc;
1342 BOOL defaulted, present;
1343 PACL pacl;
1344 PSID psid;
1346 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", ObjectDescriptor, SecurityInformation,
1347 ResultantDescriptor, DescriptorLength, ReturnLength);
1349 if (!InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION))
1350 return FALSE;
1352 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1354 if (!GetSecurityDescriptorOwner(ObjectDescriptor, &psid, &defaulted))
1355 return FALSE;
1356 SetSecurityDescriptorOwner(&desc, psid, defaulted);
1359 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1361 if (!GetSecurityDescriptorGroup(ObjectDescriptor, &psid, &defaulted))
1362 return FALSE;
1363 SetSecurityDescriptorGroup(&desc, psid, defaulted);
1366 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1368 if (!GetSecurityDescriptorDacl(ObjectDescriptor, &present, &pacl, &defaulted))
1369 return FALSE;
1370 SetSecurityDescriptorDacl(&desc, present, pacl, defaulted);
1373 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1375 if (!GetSecurityDescriptorSacl(ObjectDescriptor, &present, &pacl, &defaulted))
1376 return FALSE;
1377 SetSecurityDescriptorSacl(&desc, present, pacl, defaulted);
1380 *ReturnLength = DescriptorLength;
1381 return MakeSelfRelativeSD(&desc, ResultantDescriptor, ReturnLength);
1384 /******************************************************************************
1385 * GetSecurityDescriptorLength [ADVAPI32.@]
1387 DWORD WINAPI GetSecurityDescriptorLength( PSECURITY_DESCRIPTOR pDescr)
1389 return RtlLengthSecurityDescriptor(pDescr);
1392 /******************************************************************************
1393 * GetSecurityDescriptorOwner [ADVAPI32.@]
1395 * PARAMS
1396 * pOwner []
1397 * lpbOwnerDefaulted []
1399 BOOL WINAPI
1400 GetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pDescr, PSID *pOwner,
1401 LPBOOL lpbOwnerDefaulted )
1403 BOOLEAN defaulted;
1404 BOOL ret = set_ntstatus( RtlGetOwnerSecurityDescriptor( pDescr, pOwner, &defaulted ));
1405 *lpbOwnerDefaulted = defaulted;
1406 return ret;
1409 /******************************************************************************
1410 * SetSecurityDescriptorOwner [ADVAPI32.@]
1412 * PARAMS
1414 BOOL WINAPI SetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1415 PSID pOwner, BOOL bOwnerDefaulted)
1417 return set_ntstatus( RtlSetOwnerSecurityDescriptor(pSecurityDescriptor, pOwner, bOwnerDefaulted));
1419 /******************************************************************************
1420 * GetSecurityDescriptorGroup [ADVAPI32.@]
1422 BOOL WINAPI GetSecurityDescriptorGroup(
1423 PSECURITY_DESCRIPTOR SecurityDescriptor,
1424 PSID *Group,
1425 LPBOOL GroupDefaulted)
1427 BOOLEAN defaulted;
1428 BOOL ret = set_ntstatus( RtlGetGroupSecurityDescriptor(SecurityDescriptor, Group, &defaulted ));
1429 *GroupDefaulted = defaulted;
1430 return ret;
1432 /******************************************************************************
1433 * SetSecurityDescriptorGroup [ADVAPI32.@]
1435 BOOL WINAPI SetSecurityDescriptorGroup ( PSECURITY_DESCRIPTOR SecurityDescriptor,
1436 PSID Group, BOOL GroupDefaulted)
1438 return set_ntstatus( RtlSetGroupSecurityDescriptor( SecurityDescriptor, Group, GroupDefaulted));
1441 /******************************************************************************
1442 * IsValidSecurityDescriptor [ADVAPI32.@]
1444 * PARAMS
1445 * lpsecdesc []
1447 BOOL WINAPI
1448 IsValidSecurityDescriptor( PSECURITY_DESCRIPTOR SecurityDescriptor )
1450 return set_ntstatus( RtlValidSecurityDescriptor(SecurityDescriptor));
1453 /******************************************************************************
1454 * GetSecurityDescriptorDacl [ADVAPI32.@]
1456 BOOL WINAPI GetSecurityDescriptorDacl(
1457 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
1458 OUT LPBOOL lpbDaclPresent,
1459 OUT PACL *pDacl,
1460 OUT LPBOOL lpbDaclDefaulted)
1462 BOOLEAN present, defaulted;
1463 BOOL ret = set_ntstatus( RtlGetDaclSecurityDescriptor(pSecurityDescriptor, &present, pDacl, &defaulted));
1464 *lpbDaclPresent = present;
1465 *lpbDaclDefaulted = defaulted;
1466 return ret;
1469 /******************************************************************************
1470 * SetSecurityDescriptorDacl [ADVAPI32.@]
1472 BOOL WINAPI
1473 SetSecurityDescriptorDacl (
1474 PSECURITY_DESCRIPTOR lpsd,
1475 BOOL daclpresent,
1476 PACL dacl,
1477 BOOL dacldefaulted )
1479 return set_ntstatus( RtlSetDaclSecurityDescriptor (lpsd, daclpresent, dacl, dacldefaulted ) );
1481 /******************************************************************************
1482 * GetSecurityDescriptorSacl [ADVAPI32.@]
1484 BOOL WINAPI GetSecurityDescriptorSacl(
1485 IN PSECURITY_DESCRIPTOR lpsd,
1486 OUT LPBOOL lpbSaclPresent,
1487 OUT PACL *pSacl,
1488 OUT LPBOOL lpbSaclDefaulted)
1490 BOOLEAN present, defaulted;
1491 BOOL ret = set_ntstatus( RtlGetSaclSecurityDescriptor(lpsd, &present, pSacl, &defaulted) );
1492 *lpbSaclPresent = present;
1493 *lpbSaclDefaulted = defaulted;
1494 return ret;
1497 /**************************************************************************
1498 * SetSecurityDescriptorSacl [ADVAPI32.@]
1500 BOOL WINAPI SetSecurityDescriptorSacl (
1501 PSECURITY_DESCRIPTOR lpsd,
1502 BOOL saclpresent,
1503 PACL lpsacl,
1504 BOOL sacldefaulted)
1506 return set_ntstatus (RtlSetSaclSecurityDescriptor(lpsd, saclpresent, lpsacl, sacldefaulted));
1508 /******************************************************************************
1509 * MakeSelfRelativeSD [ADVAPI32.@]
1511 * PARAMS
1512 * lpabssecdesc []
1513 * lpselfsecdesc []
1514 * lpbuflen []
1516 BOOL WINAPI
1517 MakeSelfRelativeSD(
1518 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
1519 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
1520 IN OUT LPDWORD lpdwBufferLength)
1522 return set_ntstatus( RtlMakeSelfRelativeSD( pAbsoluteSecurityDescriptor,
1523 pSelfRelativeSecurityDescriptor, lpdwBufferLength));
1526 /******************************************************************************
1527 * GetSecurityDescriptorControl [ADVAPI32.@]
1530 BOOL WINAPI GetSecurityDescriptorControl ( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1531 PSECURITY_DESCRIPTOR_CONTROL pControl, LPDWORD lpdwRevision)
1533 return set_ntstatus( RtlGetControlSecurityDescriptor(pSecurityDescriptor,pControl,lpdwRevision));
1536 /******************************************************************************
1537 * SetSecurityDescriptorControl [ADVAPI32.@]
1539 BOOL WINAPI SetSecurityDescriptorControl( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1540 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1541 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet )
1543 return set_ntstatus( RtlSetControlSecurityDescriptor(
1544 pSecurityDescriptor, ControlBitsOfInterest, ControlBitsToSet ) );
1547 /******************************************************************************
1548 * GetWindowsAccountDomainSid [ADVAPI32.@]
1550 BOOL WINAPI GetWindowsAccountDomainSid( PSID sid, PSID domain_sid, DWORD *size )
1552 SID_IDENTIFIER_AUTHORITY domain_ident = { SECURITY_NT_AUTHORITY };
1553 DWORD required_size;
1554 int i;
1556 FIXME( "(%p %p %p): semi-stub\n", sid, domain_sid, size );
1558 if (!sid || !IsValidSid( sid ))
1560 SetLastError( ERROR_INVALID_SID );
1561 return FALSE;
1564 if (!size)
1566 SetLastError( ERROR_INVALID_PARAMETER );
1567 return FALSE;
1570 if (*GetSidSubAuthorityCount( sid ) < 4)
1572 SetLastError( ERROR_INVALID_SID );
1573 return FALSE;
1576 required_size = GetSidLengthRequired( 4 );
1577 if (*size < required_size || !domain_sid)
1579 *size = required_size;
1580 SetLastError( domain_sid ? ERROR_INSUFFICIENT_BUFFER :
1581 ERROR_INVALID_PARAMETER );
1582 return FALSE;
1585 InitializeSid( domain_sid, &domain_ident, 4 );
1586 for (i = 0; i < 4; i++)
1587 *GetSidSubAuthority( domain_sid, i ) = *GetSidSubAuthority( sid, i );
1589 *size = required_size;
1590 return TRUE;
1593 /* ##############################
1594 ###### ACL FUNCTIONS ######
1595 ##############################
1598 /*************************************************************************
1599 * InitializeAcl [ADVAPI32.@]
1601 BOOL WINAPI InitializeAcl(PACL acl, DWORD size, DWORD rev)
1603 return set_ntstatus( RtlCreateAcl(acl, size, rev));
1606 BOOL WINAPI ImpersonateNamedPipeClient( HANDLE hNamedPipe )
1608 IO_STATUS_BLOCK io_block;
1610 TRACE("(%p)\n", hNamedPipe);
1612 return set_ntstatus( NtFsControlFile(hNamedPipe, NULL, NULL, NULL,
1613 &io_block, FSCTL_PIPE_IMPERSONATE, NULL, 0, NULL, 0) );
1616 /******************************************************************************
1617 * AddAccessAllowedAce [ADVAPI32.@]
1619 BOOL WINAPI AddAccessAllowedAce(
1620 IN OUT PACL pAcl,
1621 IN DWORD dwAceRevision,
1622 IN DWORD AccessMask,
1623 IN PSID pSid)
1625 return set_ntstatus(RtlAddAccessAllowedAce(pAcl, dwAceRevision, AccessMask, pSid));
1628 /******************************************************************************
1629 * AddAccessAllowedAceEx [ADVAPI32.@]
1631 BOOL WINAPI AddAccessAllowedAceEx(
1632 IN OUT PACL pAcl,
1633 IN DWORD dwAceRevision,
1634 IN DWORD AceFlags,
1635 IN DWORD AccessMask,
1636 IN PSID pSid)
1638 return set_ntstatus(RtlAddAccessAllowedAceEx(pAcl, dwAceRevision, AceFlags, AccessMask, pSid));
1641 /******************************************************************************
1642 * AddAccessDeniedAce [ADVAPI32.@]
1644 BOOL WINAPI AddAccessDeniedAce(
1645 IN OUT PACL pAcl,
1646 IN DWORD dwAceRevision,
1647 IN DWORD AccessMask,
1648 IN PSID pSid)
1650 return set_ntstatus(RtlAddAccessDeniedAce(pAcl, dwAceRevision, AccessMask, pSid));
1653 /******************************************************************************
1654 * AddAccessDeniedAceEx [ADVAPI32.@]
1656 BOOL WINAPI AddAccessDeniedAceEx(
1657 IN OUT PACL pAcl,
1658 IN DWORD dwAceRevision,
1659 IN DWORD AceFlags,
1660 IN DWORD AccessMask,
1661 IN PSID pSid)
1663 return set_ntstatus(RtlAddAccessDeniedAceEx(pAcl, dwAceRevision, AceFlags, AccessMask, pSid));
1666 /******************************************************************************
1667 * AddAce [ADVAPI32.@]
1669 BOOL WINAPI AddAce(
1670 IN OUT PACL pAcl,
1671 IN DWORD dwAceRevision,
1672 IN DWORD dwStartingAceIndex,
1673 LPVOID pAceList,
1674 DWORD nAceListLength)
1676 return set_ntstatus(RtlAddAce(pAcl, dwAceRevision, dwStartingAceIndex, pAceList, nAceListLength));
1679 BOOL WINAPI AddMandatoryAce(ACL *acl, DWORD ace_revision, DWORD ace_flags, DWORD mandatory_policy, PSID label_sid)
1681 FIXME("%p %x %x %x %p - stub\n", acl, ace_revision, ace_flags, mandatory_policy, label_sid);
1682 return FALSE;
1685 /******************************************************************************
1686 * DeleteAce [ADVAPI32.@]
1688 BOOL WINAPI DeleteAce(PACL pAcl, DWORD dwAceIndex)
1690 return set_ntstatus(RtlDeleteAce(pAcl, dwAceIndex));
1693 /******************************************************************************
1694 * FindFirstFreeAce [ADVAPI32.@]
1696 BOOL WINAPI FindFirstFreeAce(IN PACL pAcl, LPVOID * pAce)
1698 return RtlFirstFreeAce(pAcl, (PACE_HEADER *)pAce);
1701 /******************************************************************************
1702 * GetAce [ADVAPI32.@]
1704 BOOL WINAPI GetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1706 return set_ntstatus(RtlGetAce(pAcl, dwAceIndex, pAce));
1709 /******************************************************************************
1710 * GetAclInformation [ADVAPI32.@]
1712 BOOL WINAPI GetAclInformation(
1713 PACL pAcl,
1714 LPVOID pAclInformation,
1715 DWORD nAclInformationLength,
1716 ACL_INFORMATION_CLASS dwAclInformationClass)
1718 return set_ntstatus(RtlQueryInformationAcl(pAcl, pAclInformation,
1719 nAclInformationLength, dwAclInformationClass));
1722 /******************************************************************************
1723 * IsValidAcl [ADVAPI32.@]
1725 BOOL WINAPI IsValidAcl(IN PACL pAcl)
1727 return RtlValidAcl(pAcl);
1730 /* ##############################
1731 ###### MISC FUNCTIONS ######
1732 ##############################
1735 /******************************************************************************
1736 * AllocateLocallyUniqueId [ADVAPI32.@]
1738 * PARAMS
1739 * lpLuid []
1741 BOOL WINAPI AllocateLocallyUniqueId( PLUID lpLuid )
1743 return set_ntstatus(NtAllocateLocallyUniqueId(lpLuid));
1746 static const WCHAR SE_CREATE_TOKEN_NAME_W[] =
1747 { 'S','e','C','r','e','a','t','e','T','o','k','e','n','P','r','i','v','i','l','e','g','e',0 };
1748 static const WCHAR SE_ASSIGNPRIMARYTOKEN_NAME_W[] =
1749 { '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 };
1750 static const WCHAR SE_LOCK_MEMORY_NAME_W[] =
1751 { 'S','e','L','o','c','k','M','e','m','o','r','y','P','r','i','v','i','l','e','g','e',0 };
1752 static const WCHAR SE_INCREASE_QUOTA_NAME_W[] =
1753 { '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 };
1754 static const WCHAR SE_MACHINE_ACCOUNT_NAME_W[] =
1755 { '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 };
1756 static const WCHAR SE_TCB_NAME_W[] =
1757 { 'S','e','T','c','b','P','r','i','v','i','l','e','g','e',0 };
1758 static const WCHAR SE_SECURITY_NAME_W[] =
1759 { 'S','e','S','e','c','u','r','i','t','y','P','r','i','v','i','l','e','g','e',0 };
1760 static const WCHAR SE_TAKE_OWNERSHIP_NAME_W[] =
1761 { '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 };
1762 static const WCHAR SE_LOAD_DRIVER_NAME_W[] =
1763 { 'S','e','L','o','a','d','D','r','i','v','e','r','P','r','i','v','i','l','e','g','e',0 };
1764 static const WCHAR SE_SYSTEM_PROFILE_NAME_W[] =
1765 { '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 };
1766 static const WCHAR SE_SYSTEMTIME_NAME_W[] =
1767 { 'S','e','S','y','s','t','e','m','t','i','m','e','P','r','i','v','i','l','e','g','e',0 };
1768 static const WCHAR SE_PROF_SINGLE_PROCESS_NAME_W[] =
1769 { '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 };
1770 static const WCHAR SE_INC_BASE_PRIORITY_NAME_W[] =
1771 { '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 };
1772 static const WCHAR SE_CREATE_PAGEFILE_NAME_W[] =
1773 { '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 };
1774 static const WCHAR SE_CREATE_PERMANENT_NAME_W[] =
1775 { '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 };
1776 static const WCHAR SE_BACKUP_NAME_W[] =
1777 { 'S','e','B','a','c','k','u','p','P','r','i','v','i','l','e','g','e',0 };
1778 static const WCHAR SE_RESTORE_NAME_W[] =
1779 { 'S','e','R','e','s','t','o','r','e','P','r','i','v','i','l','e','g','e',0 };
1780 static const WCHAR SE_SHUTDOWN_NAME_W[] =
1781 { 'S','e','S','h','u','t','d','o','w','n','P','r','i','v','i','l','e','g','e',0 };
1782 static const WCHAR SE_DEBUG_NAME_W[] =
1783 { 'S','e','D','e','b','u','g','P','r','i','v','i','l','e','g','e',0 };
1784 static const WCHAR SE_AUDIT_NAME_W[] =
1785 { 'S','e','A','u','d','i','t','P','r','i','v','i','l','e','g','e',0 };
1786 static const WCHAR SE_SYSTEM_ENVIRONMENT_NAME_W[] =
1787 { '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 };
1788 static const WCHAR SE_CHANGE_NOTIFY_NAME_W[] =
1789 { 'S','e','C','h','a','n','g','e','N','o','t','i','f','y','P','r','i','v','i','l','e','g','e',0 };
1790 static const WCHAR SE_REMOTE_SHUTDOWN_NAME_W[] =
1791 { '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 };
1792 static const WCHAR SE_UNDOCK_NAME_W[] =
1793 { 'S','e','U','n','d','o','c','k','P','r','i','v','i','l','e','g','e',0 };
1794 static const WCHAR SE_SYNC_AGENT_NAME_W[] =
1795 { 'S','e','S','y','n','c','A','g','e','n','t','P','r','i','v','i','l','e','g','e',0 };
1796 static const WCHAR SE_ENABLE_DELEGATION_NAME_W[] =
1797 { '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 };
1798 static const WCHAR SE_MANAGE_VOLUME_NAME_W[] =
1799 { 'S','e','M','a','n','a','g','e','V','o','l','u','m','e','P','r','i','v','i','l','e','g','e',0 };
1800 static const WCHAR SE_IMPERSONATE_NAME_W[] =
1801 { 'S','e','I','m','p','e','r','s','o','n','a','t','e','P','r','i','v','i','l','e','g','e',0 };
1802 static const WCHAR SE_CREATE_GLOBAL_NAME_W[] =
1803 { 'S','e','C','r','e','a','t','e','G','l','o','b','a','l','P','r','i','v','i','l','e','g','e',0 };
1805 static const WCHAR * const WellKnownPrivNames[SE_MAX_WELL_KNOWN_PRIVILEGE + 1] =
1807 NULL,
1808 NULL,
1809 SE_CREATE_TOKEN_NAME_W,
1810 SE_ASSIGNPRIMARYTOKEN_NAME_W,
1811 SE_LOCK_MEMORY_NAME_W,
1812 SE_INCREASE_QUOTA_NAME_W,
1813 SE_MACHINE_ACCOUNT_NAME_W,
1814 SE_TCB_NAME_W,
1815 SE_SECURITY_NAME_W,
1816 SE_TAKE_OWNERSHIP_NAME_W,
1817 SE_LOAD_DRIVER_NAME_W,
1818 SE_SYSTEM_PROFILE_NAME_W,
1819 SE_SYSTEMTIME_NAME_W,
1820 SE_PROF_SINGLE_PROCESS_NAME_W,
1821 SE_INC_BASE_PRIORITY_NAME_W,
1822 SE_CREATE_PAGEFILE_NAME_W,
1823 SE_CREATE_PERMANENT_NAME_W,
1824 SE_BACKUP_NAME_W,
1825 SE_RESTORE_NAME_W,
1826 SE_SHUTDOWN_NAME_W,
1827 SE_DEBUG_NAME_W,
1828 SE_AUDIT_NAME_W,
1829 SE_SYSTEM_ENVIRONMENT_NAME_W,
1830 SE_CHANGE_NOTIFY_NAME_W,
1831 SE_REMOTE_SHUTDOWN_NAME_W,
1832 SE_UNDOCK_NAME_W,
1833 SE_SYNC_AGENT_NAME_W,
1834 SE_ENABLE_DELEGATION_NAME_W,
1835 SE_MANAGE_VOLUME_NAME_W,
1836 SE_IMPERSONATE_NAME_W,
1837 SE_CREATE_GLOBAL_NAME_W,
1840 /******************************************************************************
1841 * LookupPrivilegeValueW [ADVAPI32.@]
1843 * See LookupPrivilegeValueA.
1845 BOOL WINAPI
1846 LookupPrivilegeValueW( LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid )
1848 UINT i;
1850 TRACE("%s,%s,%p\n",debugstr_w(lpSystemName), debugstr_w(lpName), lpLuid);
1852 if (!ADVAPI_IsLocalComputer(lpSystemName))
1854 SetLastError(RPC_S_SERVER_UNAVAILABLE);
1855 return FALSE;
1857 if (!lpName)
1859 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1860 return FALSE;
1862 for( i=SE_MIN_WELL_KNOWN_PRIVILEGE; i<=SE_MAX_WELL_KNOWN_PRIVILEGE; i++ )
1864 if( !WellKnownPrivNames[i] )
1865 continue;
1866 if( strcmpiW( WellKnownPrivNames[i], lpName) )
1867 continue;
1868 lpLuid->LowPart = i;
1869 lpLuid->HighPart = 0;
1870 TRACE( "%s -> %08x-%08x\n",debugstr_w( lpSystemName ),
1871 lpLuid->HighPart, lpLuid->LowPart );
1872 return TRUE;
1874 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1875 return FALSE;
1878 /******************************************************************************
1879 * LookupPrivilegeValueA [ADVAPI32.@]
1881 * Retrieves LUID used on a system to represent the privilege name.
1883 * PARAMS
1884 * lpSystemName [I] Name of the system
1885 * lpName [I] Name of the privilege
1886 * lpLuid [O] Destination for the resulting LUID
1888 * RETURNS
1889 * Success: TRUE. lpLuid contains the requested LUID.
1890 * Failure: FALSE.
1892 BOOL WINAPI
1893 LookupPrivilegeValueA( LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid )
1895 UNICODE_STRING lpSystemNameW;
1896 UNICODE_STRING lpNameW;
1897 BOOL ret;
1899 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1900 RtlCreateUnicodeStringFromAsciiz(&lpNameW,lpName);
1901 ret = LookupPrivilegeValueW(lpSystemNameW.Buffer, lpNameW.Buffer, lpLuid);
1902 RtlFreeUnicodeString(&lpNameW);
1903 RtlFreeUnicodeString(&lpSystemNameW);
1904 return ret;
1907 BOOL WINAPI LookupPrivilegeDisplayNameA( LPCSTR lpSystemName, LPCSTR lpName, LPSTR lpDisplayName,
1908 LPDWORD cchDisplayName, LPDWORD lpLanguageId )
1910 FIXME("%s %s %s %p %p - stub\n", debugstr_a(lpSystemName), debugstr_a(lpName),
1911 debugstr_a(lpDisplayName), cchDisplayName, lpLanguageId);
1913 return FALSE;
1916 BOOL WINAPI LookupPrivilegeDisplayNameW( LPCWSTR lpSystemName, LPCWSTR lpName, LPWSTR lpDisplayName,
1917 LPDWORD cchDisplayName, LPDWORD lpLanguageId )
1919 FIXME("%s %s %s %p %p - stub\n", debugstr_w(lpSystemName), debugstr_w(lpName),
1920 debugstr_w(lpDisplayName), cchDisplayName, lpLanguageId);
1922 return FALSE;
1925 /******************************************************************************
1926 * LookupPrivilegeNameA [ADVAPI32.@]
1928 * See LookupPrivilegeNameW.
1930 BOOL WINAPI
1931 LookupPrivilegeNameA( LPCSTR lpSystemName, PLUID lpLuid, LPSTR lpName,
1932 LPDWORD cchName)
1934 UNICODE_STRING lpSystemNameW;
1935 BOOL ret;
1936 DWORD wLen = 0;
1938 TRACE("%s %p %p %p\n", debugstr_a(lpSystemName), lpLuid, lpName, cchName);
1940 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1941 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, NULL, &wLen);
1942 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1944 LPWSTR lpNameW = heap_alloc(wLen * sizeof(WCHAR));
1946 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, lpNameW,
1947 &wLen);
1948 if (ret)
1950 /* Windows crashes if cchName is NULL, so will I */
1951 unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName,
1952 *cchName, NULL, NULL);
1954 if (len == 0)
1956 /* WideCharToMultiByte failed */
1957 ret = FALSE;
1959 else if (len > *cchName)
1961 *cchName = len;
1962 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1963 ret = FALSE;
1965 else
1967 /* WideCharToMultiByte succeeded, output length needs to be
1968 * length not including NULL terminator
1970 *cchName = len - 1;
1973 heap_free(lpNameW);
1975 RtlFreeUnicodeString(&lpSystemNameW);
1976 return ret;
1979 /******************************************************************************
1980 * LookupPrivilegeNameW [ADVAPI32.@]
1982 * Retrieves the privilege name referred to by the LUID lpLuid.
1984 * PARAMS
1985 * lpSystemName [I] Name of the system
1986 * lpLuid [I] Privilege value
1987 * lpName [O] Name of the privilege
1988 * cchName [I/O] Number of characters in lpName.
1990 * RETURNS
1991 * Success: TRUE. lpName contains the name of the privilege whose value is
1992 * *lpLuid.
1993 * Failure: FALSE.
1995 * REMARKS
1996 * Only well-known privilege names (those defined in winnt.h) can be retrieved
1997 * using this function.
1998 * If the length of lpName is too small, on return *cchName will contain the
1999 * number of WCHARs needed to contain the privilege, including the NULL
2000 * terminator, and GetLastError will return ERROR_INSUFFICIENT_BUFFER.
2001 * On success, *cchName will contain the number of characters stored in
2002 * lpName, NOT including the NULL terminator.
2004 BOOL WINAPI
2005 LookupPrivilegeNameW( LPCWSTR lpSystemName, PLUID lpLuid, LPWSTR lpName,
2006 LPDWORD cchName)
2008 size_t privNameLen;
2010 TRACE("%s,%p,%p,%p\n",debugstr_w(lpSystemName), lpLuid, lpName, cchName);
2012 if (!ADVAPI_IsLocalComputer(lpSystemName))
2014 SetLastError(RPC_S_SERVER_UNAVAILABLE);
2015 return FALSE;
2017 if (lpLuid->HighPart || (lpLuid->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
2018 lpLuid->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE))
2020 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
2021 return FALSE;
2023 privNameLen = strlenW(WellKnownPrivNames[lpLuid->LowPart]);
2024 /* Windows crashes if cchName is NULL, so will I */
2025 if (*cchName <= privNameLen)
2027 *cchName = privNameLen + 1;
2028 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2029 return FALSE;
2031 else
2033 strcpyW(lpName, WellKnownPrivNames[lpLuid->LowPart]);
2034 *cchName = privNameLen;
2035 return TRUE;
2039 /******************************************************************************
2040 * GetFileSecurityA [ADVAPI32.@]
2042 * Obtains Specified information about the security of a file or directory.
2044 * PARAMS
2045 * lpFileName [I] Name of the file to get info for
2046 * RequestedInformation [I] SE_ flags from "winnt.h"
2047 * pSecurityDescriptor [O] Destination for security information
2048 * nLength [I] Length of pSecurityDescriptor
2049 * lpnLengthNeeded [O] Destination for length of returned security information
2051 * RETURNS
2052 * Success: TRUE. pSecurityDescriptor contains the requested information.
2053 * Failure: FALSE. lpnLengthNeeded contains the required space to return the info.
2055 * NOTES
2056 * The information returned is constrained by the callers access rights and
2057 * privileges.
2059 BOOL WINAPI
2060 GetFileSecurityA( LPCSTR lpFileName,
2061 SECURITY_INFORMATION RequestedInformation,
2062 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2063 DWORD nLength, LPDWORD lpnLengthNeeded )
2065 BOOL r;
2066 LPWSTR name;
2068 name = SERV_dup(lpFileName);
2069 r = GetFileSecurityW( name, RequestedInformation, pSecurityDescriptor,
2070 nLength, lpnLengthNeeded );
2071 heap_free( name );
2073 return r;
2076 /******************************************************************************
2077 * GetFileSecurityW [ADVAPI32.@]
2079 * See GetFileSecurityA.
2081 BOOL WINAPI
2082 GetFileSecurityW( LPCWSTR lpFileName,
2083 SECURITY_INFORMATION RequestedInformation,
2084 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2085 DWORD nLength, LPDWORD lpnLengthNeeded )
2087 HANDLE hfile;
2088 NTSTATUS status;
2089 DWORD access = 0, err;
2091 TRACE("(%s,%d,%p,%d,%p)\n", debugstr_w(lpFileName),
2092 RequestedInformation, pSecurityDescriptor,
2093 nLength, lpnLengthNeeded);
2095 if (RequestedInformation & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|
2096 DACL_SECURITY_INFORMATION))
2097 access |= READ_CONTROL;
2098 if (RequestedInformation & SACL_SECURITY_INFORMATION)
2099 access |= ACCESS_SYSTEM_SECURITY;
2101 err = get_security_file( lpFileName, access, &hfile);
2102 if (err)
2104 SetLastError(err);
2105 return FALSE;
2108 status = NtQuerySecurityObject( hfile, RequestedInformation, pSecurityDescriptor,
2109 nLength, lpnLengthNeeded );
2110 CloseHandle( hfile );
2111 return set_ntstatus( status );
2115 /******************************************************************************
2116 * LookupAccountSidA [ADVAPI32.@]
2118 BOOL WINAPI
2119 LookupAccountSidA(
2120 IN LPCSTR system,
2121 IN PSID sid,
2122 OUT LPSTR account,
2123 IN OUT LPDWORD accountSize,
2124 OUT LPSTR domain,
2125 IN OUT LPDWORD domainSize,
2126 OUT PSID_NAME_USE name_use )
2128 DWORD len;
2129 BOOL r;
2130 LPWSTR systemW;
2131 LPWSTR accountW = NULL;
2132 LPWSTR domainW = NULL;
2133 DWORD accountSizeW = *accountSize;
2134 DWORD domainSizeW = *domainSize;
2136 systemW = SERV_dup(system);
2137 if (account)
2138 accountW = heap_alloc( accountSizeW * sizeof(WCHAR) );
2139 if (domain)
2140 domainW = heap_alloc( domainSizeW * sizeof(WCHAR) );
2142 r = LookupAccountSidW( systemW, sid, accountW, &accountSizeW, domainW, &domainSizeW, name_use );
2144 if (r) {
2145 if (accountW && *accountSize) {
2146 len = WideCharToMultiByte( CP_ACP, 0, accountW, -1, NULL, 0, NULL, NULL );
2147 WideCharToMultiByte( CP_ACP, 0, accountW, -1, account, len, NULL, NULL );
2148 *accountSize = len;
2149 } else
2150 *accountSize = accountSizeW + 1;
2152 if (domainW && *domainSize) {
2153 len = WideCharToMultiByte( CP_ACP, 0, domainW, -1, NULL, 0, NULL, NULL );
2154 WideCharToMultiByte( CP_ACP, 0, domainW, -1, domain, len, NULL, NULL );
2155 *domainSize = len;
2156 } else
2157 *domainSize = domainSizeW + 1;
2159 else
2161 *accountSize = accountSizeW + 1;
2162 *domainSize = domainSizeW + 1;
2165 heap_free( systemW );
2166 heap_free( accountW );
2167 heap_free( domainW );
2169 return r;
2172 /******************************************************************************
2173 * LookupAccountSidW [ADVAPI32.@]
2175 * PARAMS
2176 * system []
2177 * sid []
2178 * account []
2179 * accountSize []
2180 * domain []
2181 * domainSize []
2182 * name_use []
2185 BOOL WINAPI
2186 LookupAccountSidW(
2187 IN LPCWSTR system,
2188 IN PSID sid,
2189 OUT LPWSTR account,
2190 IN OUT LPDWORD accountSize,
2191 OUT LPWSTR domain,
2192 IN OUT LPDWORD domainSize,
2193 OUT PSID_NAME_USE name_use )
2195 unsigned int i, j;
2196 const WCHAR * ac = NULL;
2197 const WCHAR * dm = NULL;
2198 SID_NAME_USE use = 0;
2199 LPWSTR computer_name = NULL;
2200 LPWSTR account_name = NULL;
2202 TRACE("(%s,sid=%s,%p,%p(%u),%p,%p(%u),%p)\n",
2203 debugstr_w(system),debugstr_sid(sid),
2204 account,accountSize,accountSize?*accountSize:0,
2205 domain,domainSize,domainSize?*domainSize:0,
2206 name_use);
2208 if (!ADVAPI_IsLocalComputer(system)) {
2209 FIXME("Only local computer supported!\n");
2210 SetLastError(RPC_S_SERVER_UNAVAILABLE);
2211 return FALSE;
2214 /* check the well known SIDs first */
2215 for (i = 0; i <= WinAccountProtectedUsersSid; i++) {
2216 if (IsWellKnownSid(sid, i)) {
2217 for (j = 0; j < (sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0])); j++) {
2218 if (ACCOUNT_SIDS[j].type == i) {
2219 ac = ACCOUNT_SIDS[j].account;
2220 dm = ACCOUNT_SIDS[j].domain;
2221 use = ACCOUNT_SIDS[j].name_use;
2224 break;
2228 if (dm == NULL) {
2229 MAX_SID local;
2231 /* check for the local computer next */
2232 if (ADVAPI_GetComputerSid(&local)) {
2233 DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
2234 BOOL result;
2236 computer_name = heap_alloc(size * sizeof(WCHAR));
2237 result = GetComputerNameW(computer_name, &size);
2239 if (result) {
2240 if (EqualSid(sid, &local)) {
2241 dm = computer_name;
2242 ac = Blank;
2243 use = 3;
2244 } else {
2245 local.SubAuthorityCount++;
2247 if (EqualPrefixSid(sid, &local)) {
2248 dm = computer_name;
2249 use = 1;
2250 switch (((MAX_SID *)sid)->SubAuthority[4]) {
2251 case DOMAIN_USER_RID_ADMIN:
2252 ac = Administrator;
2253 break;
2254 case DOMAIN_USER_RID_GUEST:
2255 ac = Guest;
2256 break;
2257 case DOMAIN_GROUP_RID_ADMINS:
2258 ac = Domain_Admins;
2259 break;
2260 case DOMAIN_GROUP_RID_USERS:
2261 ac = Domain_Users;
2262 break;
2263 case DOMAIN_GROUP_RID_GUESTS:
2264 ac = Domain_Guests;
2265 break;
2266 case DOMAIN_GROUP_RID_COMPUTERS:
2267 ac = Domain_Computers;
2268 break;
2269 case DOMAIN_GROUP_RID_CONTROLLERS:
2270 ac = Domain_Controllers;
2271 break;
2272 case DOMAIN_GROUP_RID_CERT_ADMINS:
2273 ac = Cert_Publishers;
2274 break;
2275 case DOMAIN_GROUP_RID_SCHEMA_ADMINS:
2276 ac = Schema_Admins;
2277 break;
2278 case DOMAIN_GROUP_RID_ENTERPRISE_ADMINS:
2279 ac = Enterprise_Admins;
2280 break;
2281 case DOMAIN_GROUP_RID_POLICY_ADMINS:
2282 ac = Group_Policy_Creator_Owners;
2283 break;
2284 case DOMAIN_ALIAS_RID_RAS_SERVERS:
2285 ac = RAS_and_IAS_Servers;
2286 break;
2287 case 1000: /* first user account */
2288 size = UNLEN + 1;
2289 account_name = heap_alloc(size * sizeof(WCHAR));
2290 if (GetUserNameW(account_name, &size))
2291 ac = account_name;
2292 else
2293 dm = NULL;
2295 break;
2296 default:
2297 dm = NULL;
2298 break;
2306 if (dm) {
2307 DWORD ac_len = lstrlenW(ac);
2308 DWORD dm_len = lstrlenW(dm);
2309 BOOL status = TRUE;
2311 if (*accountSize > ac_len) {
2312 if (account)
2313 lstrcpyW(account, ac);
2315 if (*domainSize > dm_len) {
2316 if (domain)
2317 lstrcpyW(domain, dm);
2319 if ((*accountSize && *accountSize < ac_len) ||
2320 (!account && !*accountSize && ac_len) ||
2321 (*domainSize && *domainSize < dm_len) ||
2322 (!domain && !*domainSize && dm_len))
2324 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2325 status = FALSE;
2327 if (*domainSize)
2328 *domainSize = dm_len;
2329 else
2330 *domainSize = dm_len + 1;
2331 if (*accountSize)
2332 *accountSize = ac_len;
2333 else
2334 *accountSize = ac_len + 1;
2336 heap_free(account_name);
2337 heap_free(computer_name);
2338 if (status) *name_use = use;
2339 return status;
2342 heap_free(account_name);
2343 heap_free(computer_name);
2344 SetLastError(ERROR_NONE_MAPPED);
2345 return FALSE;
2348 /******************************************************************************
2349 * SetFileSecurityA [ADVAPI32.@]
2351 * See SetFileSecurityW.
2353 BOOL WINAPI SetFileSecurityA( LPCSTR lpFileName,
2354 SECURITY_INFORMATION RequestedInformation,
2355 PSECURITY_DESCRIPTOR pSecurityDescriptor)
2357 BOOL r;
2358 LPWSTR name;
2360 name = SERV_dup(lpFileName);
2361 r = SetFileSecurityW( name, RequestedInformation, pSecurityDescriptor );
2362 heap_free( name );
2364 return r;
2367 /******************************************************************************
2368 * SetFileSecurityW [ADVAPI32.@]
2370 * Sets the security of a file or directory.
2372 * PARAMS
2373 * lpFileName []
2374 * RequestedInformation []
2375 * pSecurityDescriptor []
2377 * RETURNS
2378 * Success: TRUE.
2379 * Failure: FALSE.
2381 BOOL WINAPI
2382 SetFileSecurityW( LPCWSTR lpFileName,
2383 SECURITY_INFORMATION RequestedInformation,
2384 PSECURITY_DESCRIPTOR pSecurityDescriptor )
2386 HANDLE file;
2387 DWORD access = 0, err;
2388 NTSTATUS status;
2390 TRACE("(%s, 0x%x, %p)\n", debugstr_w(lpFileName), RequestedInformation,
2391 pSecurityDescriptor );
2393 if (RequestedInformation & OWNER_SECURITY_INFORMATION ||
2394 RequestedInformation & GROUP_SECURITY_INFORMATION)
2395 access |= WRITE_OWNER;
2396 if (RequestedInformation & SACL_SECURITY_INFORMATION)
2397 access |= ACCESS_SYSTEM_SECURITY;
2398 if (RequestedInformation & DACL_SECURITY_INFORMATION)
2399 access |= WRITE_DAC;
2401 err = get_security_file( lpFileName, access, &file);
2402 if (err)
2404 SetLastError(err);
2405 return FALSE;
2408 status = NtSetSecurityObject( file, RequestedInformation, pSecurityDescriptor );
2409 CloseHandle( file );
2410 return set_ntstatus( status );
2413 /******************************************************************************
2414 * QueryWindows31FilesMigration [ADVAPI32.@]
2416 * PARAMS
2417 * x1 []
2419 BOOL WINAPI
2420 QueryWindows31FilesMigration( DWORD x1 )
2422 FIXME("(%d):stub\n",x1);
2423 return TRUE;
2426 /******************************************************************************
2427 * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@]
2429 * PARAMS
2430 * x1 []
2431 * x2 []
2432 * x3 []
2433 * x4 []
2435 BOOL WINAPI
2436 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3,
2437 DWORD x4 )
2439 FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4);
2440 return TRUE;
2443 /******************************************************************************
2444 * NotifyBootConfigStatus [ADVAPI32.@]
2446 * PARAMS
2447 * x1 []
2449 BOOL WINAPI
2450 NotifyBootConfigStatus( BOOL x1 )
2452 FIXME("(0x%08d):stub\n",x1);
2453 return TRUE;
2456 /******************************************************************************
2457 * RevertToSelf [ADVAPI32.@]
2459 * Ends the impersonation of a user.
2461 * PARAMS
2462 * void []
2464 * RETURNS
2465 * Success: TRUE.
2466 * Failure: FALSE.
2468 BOOL WINAPI
2469 RevertToSelf( void )
2471 HANDLE Token = NULL;
2472 return set_ntstatus( NtSetInformationThread( GetCurrentThread(),
2473 ThreadImpersonationToken, &Token, sizeof(Token) ) );
2476 /******************************************************************************
2477 * ImpersonateSelf [ADVAPI32.@]
2479 * Makes an impersonation token that represents the process user and assigns
2480 * to the current thread.
2482 * PARAMS
2483 * ImpersonationLevel [I] Level at which to impersonate.
2485 * RETURNS
2486 * Success: TRUE.
2487 * Failure: FALSE.
2489 BOOL WINAPI
2490 ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
2492 return set_ntstatus( RtlImpersonateSelf( ImpersonationLevel ) );
2495 /******************************************************************************
2496 * ImpersonateLoggedOnUser [ADVAPI32.@]
2498 BOOL WINAPI ImpersonateLoggedOnUser(HANDLE hToken)
2500 DWORD size;
2501 NTSTATUS Status;
2502 HANDLE ImpersonationToken;
2503 TOKEN_TYPE Type;
2504 static BOOL warn = TRUE;
2506 if (warn)
2508 FIXME( "(%p)\n", hToken );
2509 warn = FALSE;
2511 if (!GetTokenInformation( hToken, TokenType, &Type,
2512 sizeof(TOKEN_TYPE), &size ))
2513 return FALSE;
2515 if (Type == TokenPrimary)
2517 OBJECT_ATTRIBUTES ObjectAttributes;
2519 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
2521 Status = NtDuplicateToken( hToken,
2522 TOKEN_IMPERSONATE | TOKEN_QUERY,
2523 &ObjectAttributes,
2524 SecurityImpersonation,
2525 TokenImpersonation,
2526 &ImpersonationToken );
2527 if (Status != STATUS_SUCCESS)
2529 ERR( "NtDuplicateToken failed with error 0x%08x\n", Status );
2530 SetLastError( RtlNtStatusToDosError( Status ) );
2531 return FALSE;
2534 else
2535 ImpersonationToken = hToken;
2537 Status = NtSetInformationThread( GetCurrentThread(),
2538 ThreadImpersonationToken,
2539 &ImpersonationToken,
2540 sizeof(ImpersonationToken) );
2542 if (Type == TokenPrimary)
2543 NtClose( ImpersonationToken );
2545 if (Status != STATUS_SUCCESS)
2547 ERR( "NtSetInformationThread failed with error 0x%08x\n", Status );
2548 SetLastError( RtlNtStatusToDosError( Status ) );
2549 return FALSE;
2552 return TRUE;
2555 /******************************************************************************
2556 * ImpersonateAnonymousToken [ADVAPI32.@]
2558 BOOL WINAPI ImpersonateAnonymousToken( HANDLE thread )
2560 TRACE("(%p)\n", thread);
2561 return set_ntstatus( NtImpersonateAnonymousToken( thread ) );
2564 /******************************************************************************
2565 * AccessCheck [ADVAPI32.@]
2567 BOOL WINAPI
2568 AccessCheck(
2569 PSECURITY_DESCRIPTOR SecurityDescriptor,
2570 HANDLE ClientToken,
2571 DWORD DesiredAccess,
2572 PGENERIC_MAPPING GenericMapping,
2573 PPRIVILEGE_SET PrivilegeSet,
2574 LPDWORD PrivilegeSetLength,
2575 LPDWORD GrantedAccess,
2576 LPBOOL AccessStatus)
2578 NTSTATUS access_status;
2579 BOOL ret = set_ntstatus( NtAccessCheck(SecurityDescriptor, ClientToken, DesiredAccess,
2580 GenericMapping, PrivilegeSet, PrivilegeSetLength,
2581 GrantedAccess, &access_status) );
2582 if (ret) *AccessStatus = set_ntstatus( access_status );
2583 return ret;
2587 /******************************************************************************
2588 * AccessCheckByType [ADVAPI32.@]
2590 BOOL WINAPI AccessCheckByType(
2591 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2592 PSID PrincipalSelfSid,
2593 HANDLE ClientToken,
2594 DWORD DesiredAccess,
2595 POBJECT_TYPE_LIST ObjectTypeList,
2596 DWORD ObjectTypeListLength,
2597 PGENERIC_MAPPING GenericMapping,
2598 PPRIVILEGE_SET PrivilegeSet,
2599 LPDWORD PrivilegeSetLength,
2600 LPDWORD GrantedAccess,
2601 LPBOOL AccessStatus)
2603 FIXME("stub\n");
2605 *AccessStatus = TRUE;
2607 return !*AccessStatus;
2610 /******************************************************************************
2611 * MapGenericMask [ADVAPI32.@]
2613 * Maps generic access rights into specific access rights according to the
2614 * supplied mapping.
2616 * PARAMS
2617 * AccessMask [I/O] Access rights.
2618 * GenericMapping [I] The mapping between generic and specific rights.
2620 * RETURNS
2621 * Nothing.
2623 VOID WINAPI MapGenericMask( PDWORD AccessMask, PGENERIC_MAPPING GenericMapping )
2625 RtlMapGenericMask( AccessMask, GenericMapping );
2628 /*************************************************************************
2629 * SetKernelObjectSecurity [ADVAPI32.@]
2631 BOOL WINAPI SetKernelObjectSecurity (
2632 IN HANDLE Handle,
2633 IN SECURITY_INFORMATION SecurityInformation,
2634 IN PSECURITY_DESCRIPTOR SecurityDescriptor )
2636 return set_ntstatus (NtSetSecurityObject (Handle, SecurityInformation, SecurityDescriptor));
2640 /******************************************************************************
2641 * AddAuditAccessAce [ADVAPI32.@]
2643 BOOL WINAPI AddAuditAccessAce(
2644 IN OUT PACL pAcl,
2645 IN DWORD dwAceRevision,
2646 IN DWORD dwAccessMask,
2647 IN PSID pSid,
2648 IN BOOL bAuditSuccess,
2649 IN BOOL bAuditFailure)
2651 return set_ntstatus( RtlAddAuditAccessAce(pAcl, dwAceRevision, dwAccessMask, pSid,
2652 bAuditSuccess, bAuditFailure) );
2655 /******************************************************************************
2656 * AddAuditAccessAce [ADVAPI32.@]
2658 BOOL WINAPI AddAuditAccessAceEx(
2659 IN OUT PACL pAcl,
2660 IN DWORD dwAceRevision,
2661 IN DWORD dwAceFlags,
2662 IN DWORD dwAccessMask,
2663 IN PSID pSid,
2664 IN BOOL bAuditSuccess,
2665 IN BOOL bAuditFailure)
2667 return set_ntstatus( RtlAddAuditAccessAceEx(pAcl, dwAceRevision, dwAceFlags, dwAccessMask, pSid,
2668 bAuditSuccess, bAuditFailure) );
2671 /******************************************************************************
2672 * LookupAccountNameA [ADVAPI32.@]
2674 BOOL WINAPI
2675 LookupAccountNameA(
2676 IN LPCSTR system,
2677 IN LPCSTR account,
2678 OUT PSID sid,
2679 OUT LPDWORD cbSid,
2680 LPSTR ReferencedDomainName,
2681 IN OUT LPDWORD cbReferencedDomainName,
2682 OUT PSID_NAME_USE name_use )
2684 BOOL ret;
2685 UNICODE_STRING lpSystemW;
2686 UNICODE_STRING lpAccountW;
2687 LPWSTR lpReferencedDomainNameW = NULL;
2689 RtlCreateUnicodeStringFromAsciiz(&lpSystemW, system);
2690 RtlCreateUnicodeStringFromAsciiz(&lpAccountW, account);
2692 if (ReferencedDomainName)
2693 lpReferencedDomainNameW = heap_alloc(*cbReferencedDomainName * sizeof(WCHAR));
2695 ret = LookupAccountNameW(lpSystemW.Buffer, lpAccountW.Buffer, sid, cbSid, lpReferencedDomainNameW,
2696 cbReferencedDomainName, name_use);
2698 if (ret && lpReferencedDomainNameW)
2700 WideCharToMultiByte(CP_ACP, 0, lpReferencedDomainNameW, -1,
2701 ReferencedDomainName, *cbReferencedDomainName+1, NULL, NULL);
2704 RtlFreeUnicodeString(&lpSystemW);
2705 RtlFreeUnicodeString(&lpAccountW);
2706 heap_free(lpReferencedDomainNameW);
2708 return ret;
2711 /******************************************************************************
2712 * lookup_user_account_name
2714 static BOOL lookup_user_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2715 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2717 char buffer[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
2718 DWORD len = sizeof(buffer);
2719 HANDLE token;
2720 BOOL ret;
2721 PSID pSid;
2722 WCHAR domainName[MAX_COMPUTERNAME_LENGTH + 1];
2723 DWORD nameLen;
2725 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
2727 if (GetLastError() != ERROR_NO_TOKEN) return FALSE;
2728 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) return FALSE;
2731 ret = GetTokenInformation(token, TokenUser, buffer, len, &len);
2732 CloseHandle( token );
2734 if (!ret) return FALSE;
2736 pSid = ((TOKEN_USER *)buffer)->User.Sid;
2738 if (Sid != NULL && (*cbSid >= GetLengthSid(pSid)))
2739 CopySid(*cbSid, Sid, pSid);
2740 if (*cbSid < GetLengthSid(pSid))
2742 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2743 ret = FALSE;
2745 *cbSid = GetLengthSid(pSid);
2747 nameLen = MAX_COMPUTERNAME_LENGTH + 1;
2748 if (!GetComputerNameW(domainName, &nameLen))
2750 domainName[0] = 0;
2751 nameLen = 0;
2753 if (*cchReferencedDomainName <= nameLen || !ret)
2755 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2756 nameLen += 1;
2757 ret = FALSE;
2759 else if (ReferencedDomainName)
2760 strcpyW(ReferencedDomainName, domainName);
2762 *cchReferencedDomainName = nameLen;
2764 if (ret)
2765 *peUse = SidTypeUser;
2767 return ret;
2770 /******************************************************************************
2771 * lookup_computer_account_name
2773 static BOOL lookup_computer_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2774 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2776 MAX_SID local;
2777 BOOL ret;
2778 WCHAR domainName[MAX_COMPUTERNAME_LENGTH + 1];
2779 DWORD nameLen;
2781 if ((ret = ADVAPI_GetComputerSid(&local)))
2783 if (Sid != NULL && (*cbSid >= GetLengthSid(&local)))
2784 CopySid(*cbSid, Sid, &local);
2785 if (*cbSid < GetLengthSid(&local))
2787 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2788 ret = FALSE;
2790 *cbSid = GetLengthSid(&local);
2793 nameLen = MAX_COMPUTERNAME_LENGTH + 1;
2794 if (!GetComputerNameW(domainName, &nameLen))
2796 domainName[0] = 0;
2797 nameLen = 0;
2799 if (*cchReferencedDomainName <= nameLen || !ret)
2801 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2802 nameLen += 1;
2803 ret = FALSE;
2805 else if (ReferencedDomainName)
2806 strcpyW(ReferencedDomainName, domainName);
2808 *cchReferencedDomainName = nameLen;
2810 if (ret)
2811 *peUse = SidTypeDomain;
2813 return ret;
2816 static void split_domain_account( const LSA_UNICODE_STRING *str, LSA_UNICODE_STRING *account,
2817 LSA_UNICODE_STRING *domain )
2819 WCHAR *p = str->Buffer + str->Length / sizeof(WCHAR) - 1;
2821 while (p > str->Buffer && *p != '\\') p--;
2823 if (*p == '\\')
2825 domain->Buffer = str->Buffer;
2826 domain->Length = (p - str->Buffer) * sizeof(WCHAR);
2828 account->Buffer = p + 1;
2829 account->Length = str->Length - ((p - str->Buffer + 1) * sizeof(WCHAR));
2831 else
2833 domain->Buffer = NULL;
2834 domain->Length = 0;
2836 account->Buffer = str->Buffer;
2837 account->Length = str->Length;
2841 static BOOL match_domain( ULONG idx, const LSA_UNICODE_STRING *domain )
2843 ULONG len = strlenW( ACCOUNT_SIDS[idx].domain );
2845 if (len == domain->Length / sizeof(WCHAR) && !strncmpiW( domain->Buffer, ACCOUNT_SIDS[idx].domain, len ))
2846 return TRUE;
2848 return FALSE;
2851 static BOOL match_account( ULONG idx, const LSA_UNICODE_STRING *account )
2853 ULONG len = strlenW( ACCOUNT_SIDS[idx].account );
2855 if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].account, len ))
2856 return TRUE;
2858 if (ACCOUNT_SIDS[idx].alias)
2860 len = strlenW( ACCOUNT_SIDS[idx].alias );
2861 if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].alias, len ))
2862 return TRUE;
2864 return FALSE;
2868 * Helper function for LookupAccountNameW
2870 BOOL lookup_local_wellknown_name( const LSA_UNICODE_STRING *account_and_domain,
2871 PSID Sid, LPDWORD cbSid,
2872 LPWSTR ReferencedDomainName,
2873 LPDWORD cchReferencedDomainName,
2874 PSID_NAME_USE peUse, BOOL *handled )
2876 PSID pSid;
2877 LSA_UNICODE_STRING account, domain;
2878 BOOL ret = TRUE;
2879 ULONG i;
2881 *handled = FALSE;
2882 split_domain_account( account_and_domain, &account, &domain );
2884 for (i = 0; i < sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0]); i++)
2886 /* check domain first */
2887 if (domain.Buffer && !match_domain( i, &domain )) continue;
2889 if (match_account( i, &account ))
2891 DWORD len, sidLen = SECURITY_MAX_SID_SIZE;
2893 if (!(pSid = heap_alloc( sidLen ))) return FALSE;
2895 if ((ret = CreateWellKnownSid( ACCOUNT_SIDS[i].type, NULL, pSid, &sidLen )))
2897 if (*cbSid < sidLen)
2899 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2900 ret = FALSE;
2902 else if (Sid)
2904 CopySid(*cbSid, Sid, pSid);
2906 *cbSid = sidLen;
2909 len = strlenW( ACCOUNT_SIDS[i].domain );
2910 if (*cchReferencedDomainName <= len || !ret)
2912 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2913 len++;
2914 ret = FALSE;
2916 else if (ReferencedDomainName)
2918 strcpyW( ReferencedDomainName, ACCOUNT_SIDS[i].domain );
2921 *cchReferencedDomainName = len;
2922 if (ret)
2923 *peUse = ACCOUNT_SIDS[i].name_use;
2925 heap_free(pSid);
2926 *handled = TRUE;
2927 return ret;
2930 return ret;
2933 BOOL lookup_local_user_name( const LSA_UNICODE_STRING *account_and_domain,
2934 PSID Sid, LPDWORD cbSid,
2935 LPWSTR ReferencedDomainName,
2936 LPDWORD cchReferencedDomainName,
2937 PSID_NAME_USE peUse, BOOL *handled )
2939 DWORD nameLen;
2940 LPWSTR userName = NULL;
2941 LSA_UNICODE_STRING account, domain;
2942 BOOL ret = TRUE;
2944 *handled = FALSE;
2945 split_domain_account( account_and_domain, &account, &domain );
2947 /* Let the current Unix user id masquerade as first Windows user account */
2949 nameLen = UNLEN + 1;
2950 if (!(userName = heap_alloc( nameLen * sizeof(WCHAR) ))) return FALSE;
2952 if (domain.Buffer)
2954 /* check to make sure this account is on this computer */
2955 if (GetComputerNameW( userName, &nameLen ) &&
2956 (domain.Length / sizeof(WCHAR) != nameLen || strncmpW( domain.Buffer, userName, nameLen )))
2958 SetLastError(ERROR_NONE_MAPPED);
2959 ret = FALSE;
2961 nameLen = UNLEN + 1;
2964 if (GetUserNameW( userName, &nameLen ) &&
2965 account.Length / sizeof(WCHAR) == nameLen - 1 && !strncmpW( account.Buffer, userName, nameLen - 1 ))
2967 ret = lookup_user_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2968 *handled = TRUE;
2970 else
2972 nameLen = UNLEN + 1;
2973 if (GetComputerNameW( userName, &nameLen ) &&
2974 account.Length / sizeof(WCHAR) == nameLen && !strncmpW( account.Buffer, userName , nameLen ))
2976 ret = lookup_computer_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2977 *handled = TRUE;
2981 heap_free(userName);
2982 return ret;
2985 /******************************************************************************
2986 * LookupAccountNameW [ADVAPI32.@]
2988 BOOL WINAPI LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid,
2989 LPDWORD cbSid, LPWSTR ReferencedDomainName,
2990 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2992 BOOL ret, handled;
2993 LSA_UNICODE_STRING account;
2995 TRACE("%s %s %p %p %p %p %p\n", debugstr_w(lpSystemName), debugstr_w(lpAccountName),
2996 Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse);
2998 if (!ADVAPI_IsLocalComputer( lpSystemName ))
3000 FIXME("remote computer not supported\n");
3001 SetLastError( RPC_S_SERVER_UNAVAILABLE );
3002 return FALSE;
3005 if (!lpAccountName || !strcmpW( lpAccountName, Blank ))
3007 lpAccountName = BUILTIN;
3010 RtlInitUnicodeString( &account, lpAccountName );
3012 /* Check well known SIDs first */
3013 ret = lookup_local_wellknown_name( &account, Sid, cbSid, ReferencedDomainName,
3014 cchReferencedDomainName, peUse, &handled );
3015 if (handled)
3016 return ret;
3018 /* Check user names */
3019 ret = lookup_local_user_name( &account, Sid, cbSid, ReferencedDomainName,
3020 cchReferencedDomainName, peUse, &handled);
3021 if (handled)
3022 return ret;
3024 SetLastError( ERROR_NONE_MAPPED );
3025 return FALSE;
3028 /******************************************************************************
3029 * PrivilegeCheck [ADVAPI32.@]
3031 BOOL WINAPI PrivilegeCheck( HANDLE ClientToken, PPRIVILEGE_SET RequiredPrivileges, LPBOOL pfResult)
3033 BOOL ret;
3034 BOOLEAN Result;
3036 TRACE("%p %p %p\n", ClientToken, RequiredPrivileges, pfResult);
3038 ret = set_ntstatus (NtPrivilegeCheck (ClientToken, RequiredPrivileges, &Result));
3039 if (ret)
3040 *pfResult = Result;
3041 return ret;
3044 /******************************************************************************
3045 * AccessCheckAndAuditAlarmA [ADVAPI32.@]
3047 BOOL WINAPI AccessCheckAndAuditAlarmA(LPCSTR Subsystem, LPVOID HandleId, LPSTR ObjectTypeName,
3048 LPSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
3049 PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
3050 LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
3052 FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_a(Subsystem),
3053 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName),
3054 SecurityDescriptor, DesiredAccess, GenericMapping,
3055 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
3056 return TRUE;
3059 /******************************************************************************
3060 * AccessCheckAndAuditAlarmW [ADVAPI32.@]
3062 BOOL WINAPI AccessCheckAndAuditAlarmW(LPCWSTR Subsystem, LPVOID HandleId, LPWSTR ObjectTypeName,
3063 LPWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
3064 PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
3065 LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
3067 FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_w(Subsystem),
3068 HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName),
3069 SecurityDescriptor, DesiredAccess, GenericMapping,
3070 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
3071 return TRUE;
3074 BOOL WINAPI ObjectCloseAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3076 FIXME("stub (%s,%p,%x)\n", debugstr_a(SubsystemName), HandleId, GenerateOnClose);
3078 return TRUE;
3081 BOOL WINAPI ObjectCloseAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3083 FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
3085 return TRUE;
3088 BOOL WINAPI ObjectDeleteAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3090 FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
3092 return TRUE;
3095 BOOL WINAPI ObjectOpenAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, LPSTR ObjectTypeName,
3096 LPSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
3097 DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
3098 LPBOOL GenerateOnClose)
3100 FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_a(SubsystemName),
3101 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName), pSecurityDescriptor,
3102 ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
3103 GenerateOnClose);
3105 return TRUE;
3108 BOOL WINAPI ObjectOpenAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, LPWSTR ObjectTypeName,
3109 LPWSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
3110 DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
3111 LPBOOL GenerateOnClose)
3113 FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_w(SubsystemName),
3114 HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName), pSecurityDescriptor,
3115 ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
3116 GenerateOnClose);
3118 return TRUE;
3121 BOOL WINAPI ObjectPrivilegeAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
3122 DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3124 FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_a(SubsystemName), HandleId, ClientToken,
3125 DesiredAccess, Privileges, AccessGranted);
3127 return TRUE;
3130 BOOL WINAPI ObjectPrivilegeAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
3131 DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3133 FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_w(SubsystemName), HandleId, ClientToken,
3134 DesiredAccess, Privileges, AccessGranted);
3136 return TRUE;
3139 BOOL WINAPI PrivilegedServiceAuditAlarmA( LPCSTR SubsystemName, LPCSTR ServiceName, HANDLE ClientToken,
3140 PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3142 FIXME("stub (%s,%s,%p,%p,%x)\n", debugstr_a(SubsystemName), debugstr_a(ServiceName),
3143 ClientToken, Privileges, AccessGranted);
3145 return TRUE;
3148 BOOL WINAPI PrivilegedServiceAuditAlarmW( LPCWSTR SubsystemName, LPCWSTR ServiceName, HANDLE ClientToken,
3149 PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3151 FIXME("stub %s,%s,%p,%p,%x)\n", debugstr_w(SubsystemName), debugstr_w(ServiceName),
3152 ClientToken, Privileges, AccessGranted);
3154 return TRUE;
3157 /******************************************************************************
3158 * GetSecurityInfo [ADVAPI32.@]
3160 * Retrieves a copy of the security descriptor associated with an object.
3162 * PARAMS
3163 * hObject [I] A handle for the object.
3164 * ObjectType [I] The type of object.
3165 * SecurityInfo [I] A bitmask indicating what info to retrieve.
3166 * ppsidOwner [O] If non-null, receives a pointer to the owner SID.
3167 * ppsidGroup [O] If non-null, receives a pointer to the group SID.
3168 * ppDacl [O] If non-null, receives a pointer to the DACL.
3169 * ppSacl [O] If non-null, receives a pointer to the SACL.
3170 * ppSecurityDescriptor [O] Receives a pointer to the security descriptor,
3171 * which must be freed with LocalFree.
3173 * RETURNS
3174 * ERROR_SUCCESS if all's well, and a WIN32 error code otherwise.
3176 DWORD WINAPI GetSecurityInfo(
3177 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3178 SECURITY_INFORMATION SecurityInfo, PSID *ppsidOwner,
3179 PSID *ppsidGroup, PACL *ppDacl, PACL *ppSacl,
3180 PSECURITY_DESCRIPTOR *ppSecurityDescriptor
3183 PSECURITY_DESCRIPTOR sd;
3184 NTSTATUS status;
3185 ULONG n1, n2;
3186 BOOL present, defaulted;
3188 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
3189 if (!(ppsidOwner||ppsidGroup||ppDacl||ppSacl||ppSecurityDescriptor)) return ERROR_INVALID_PARAMETER;
3191 /* If no descriptor, we have to check that there's a pointer for the requested information */
3192 if( !ppSecurityDescriptor && (
3193 ((SecurityInfo & OWNER_SECURITY_INFORMATION) && !ppsidOwner)
3194 || ((SecurityInfo & GROUP_SECURITY_INFORMATION) && !ppsidGroup)
3195 || ((SecurityInfo & DACL_SECURITY_INFORMATION) && !ppDacl)
3196 || ((SecurityInfo & SACL_SECURITY_INFORMATION) && !ppSacl) ))
3197 return ERROR_INVALID_PARAMETER;
3199 switch (ObjectType)
3201 case SE_SERVICE:
3202 status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, NULL, 0, &n1);
3203 break;
3204 default:
3205 status = NtQuerySecurityObject(hObject, SecurityInfo, NULL, 0, &n1);
3206 break;
3208 if (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_SUCCESS)
3209 return RtlNtStatusToDosError(status);
3211 sd = LocalAlloc(0, n1);
3212 if (!sd)
3213 return ERROR_NOT_ENOUGH_MEMORY;
3215 switch (ObjectType)
3217 case SE_SERVICE:
3218 status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, sd, n1, &n2);
3219 break;
3220 default:
3221 status = NtQuerySecurityObject(hObject, SecurityInfo, sd, n1, &n2);
3222 break;
3224 if (status != STATUS_SUCCESS)
3226 LocalFree(sd);
3227 return RtlNtStatusToDosError(status);
3230 if (ppsidOwner)
3232 *ppsidOwner = NULL;
3233 GetSecurityDescriptorOwner(sd, ppsidOwner, &defaulted);
3235 if (ppsidGroup)
3237 *ppsidGroup = NULL;
3238 GetSecurityDescriptorGroup(sd, ppsidGroup, &defaulted);
3240 if (ppDacl)
3242 *ppDacl = NULL;
3243 GetSecurityDescriptorDacl(sd, &present, ppDacl, &defaulted);
3245 if (ppSacl)
3247 *ppSacl = NULL;
3248 GetSecurityDescriptorSacl(sd, &present, ppSacl, &defaulted);
3250 if (ppSecurityDescriptor)
3251 *ppSecurityDescriptor = sd;
3253 /* The security descriptor (sd) cannot be freed if ppSecurityDescriptor is
3254 * NULL, because native happily returns the SIDs and ACLs that are requested
3255 * in this case.
3258 return ERROR_SUCCESS;
3261 /******************************************************************************
3262 * GetSecurityInfoExA [ADVAPI32.@]
3264 DWORD WINAPI GetSecurityInfoExA(
3265 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3266 SECURITY_INFORMATION SecurityInfo, LPCSTR lpProvider,
3267 LPCSTR lpProperty, PACTRL_ACCESSA *ppAccessList,
3268 PACTRL_AUDITA *ppAuditList, LPSTR *lppOwner, LPSTR *lppGroup
3271 FIXME("stub!\n");
3272 return ERROR_BAD_PROVIDER;
3275 /******************************************************************************
3276 * GetSecurityInfoExW [ADVAPI32.@]
3278 DWORD WINAPI GetSecurityInfoExW(
3279 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3280 SECURITY_INFORMATION SecurityInfo, LPCWSTR lpProvider,
3281 LPCWSTR lpProperty, PACTRL_ACCESSW *ppAccessList,
3282 PACTRL_AUDITW *ppAuditList, LPWSTR *lppOwner, LPWSTR *lppGroup
3285 FIXME("stub!\n");
3286 return ERROR_BAD_PROVIDER;
3289 /******************************************************************************
3290 * BuildExplicitAccessWithNameA [ADVAPI32.@]
3292 VOID WINAPI BuildExplicitAccessWithNameA( PEXPLICIT_ACCESSA pExplicitAccess,
3293 LPSTR pTrusteeName, DWORD AccessPermissions,
3294 ACCESS_MODE AccessMode, DWORD Inheritance )
3296 TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_a(pTrusteeName),
3297 AccessPermissions, AccessMode, Inheritance);
3299 pExplicitAccess->grfAccessPermissions = AccessPermissions;
3300 pExplicitAccess->grfAccessMode = AccessMode;
3301 pExplicitAccess->grfInheritance = Inheritance;
3303 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3304 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3305 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3306 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3307 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3310 /******************************************************************************
3311 * BuildExplicitAccessWithNameW [ADVAPI32.@]
3313 VOID WINAPI BuildExplicitAccessWithNameW( PEXPLICIT_ACCESSW pExplicitAccess,
3314 LPWSTR pTrusteeName, DWORD AccessPermissions,
3315 ACCESS_MODE AccessMode, DWORD Inheritance )
3317 TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_w(pTrusteeName),
3318 AccessPermissions, AccessMode, Inheritance);
3320 pExplicitAccess->grfAccessPermissions = AccessPermissions;
3321 pExplicitAccess->grfAccessMode = AccessMode;
3322 pExplicitAccess->grfInheritance = Inheritance;
3324 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3325 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3326 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3327 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3328 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3331 /******************************************************************************
3332 * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
3334 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
3335 SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
3336 LPSTR InheritedObjectTypeName, LPSTR Name )
3338 DWORD ObjectsPresent = 0;
3340 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3341 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
3343 /* Fill the OBJECTS_AND_NAME structure */
3344 pObjName->ObjectType = ObjectType;
3345 if (ObjectTypeName != NULL)
3347 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3350 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3351 if (InheritedObjectTypeName != NULL)
3353 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3356 pObjName->ObjectsPresent = ObjectsPresent;
3357 pObjName->ptstrName = Name;
3359 /* Fill the TRUSTEE structure */
3360 pTrustee->pMultipleTrustee = NULL;
3361 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3362 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3363 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3364 pTrustee->ptstrName = (LPSTR)pObjName;
3367 /******************************************************************************
3368 * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
3370 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
3371 SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
3372 LPWSTR InheritedObjectTypeName, LPWSTR Name )
3374 DWORD ObjectsPresent = 0;
3376 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3377 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
3379 /* Fill the OBJECTS_AND_NAME structure */
3380 pObjName->ObjectType = ObjectType;
3381 if (ObjectTypeName != NULL)
3383 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3386 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3387 if (InheritedObjectTypeName != NULL)
3389 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3392 pObjName->ObjectsPresent = ObjectsPresent;
3393 pObjName->ptstrName = Name;
3395 /* Fill the TRUSTEE structure */
3396 pTrustee->pMultipleTrustee = NULL;
3397 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3398 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3399 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3400 pTrustee->ptstrName = (LPWSTR)pObjName;
3403 /******************************************************************************
3404 * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
3406 VOID WINAPI BuildTrusteeWithObjectsAndSidA( PTRUSTEEA pTrustee, POBJECTS_AND_SID pObjSid,
3407 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3409 DWORD ObjectsPresent = 0;
3411 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3413 /* Fill the OBJECTS_AND_SID structure */
3414 if (pObjectGuid != NULL)
3416 pObjSid->ObjectTypeGuid = *pObjectGuid;
3417 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3419 else
3421 ZeroMemory(&pObjSid->ObjectTypeGuid,
3422 sizeof(GUID));
3425 if (pInheritedObjectGuid != NULL)
3427 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3428 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3430 else
3432 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3433 sizeof(GUID));
3436 pObjSid->ObjectsPresent = ObjectsPresent;
3437 pObjSid->pSid = pSid;
3439 /* Fill the TRUSTEE structure */
3440 pTrustee->pMultipleTrustee = NULL;
3441 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3442 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3443 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3444 pTrustee->ptstrName = (LPSTR) pObjSid;
3447 /******************************************************************************
3448 * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
3450 VOID WINAPI BuildTrusteeWithObjectsAndSidW( PTRUSTEEW pTrustee, POBJECTS_AND_SID pObjSid,
3451 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3453 DWORD ObjectsPresent = 0;
3455 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3457 /* Fill the OBJECTS_AND_SID structure */
3458 if (pObjectGuid != NULL)
3460 pObjSid->ObjectTypeGuid = *pObjectGuid;
3461 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3463 else
3465 ZeroMemory(&pObjSid->ObjectTypeGuid,
3466 sizeof(GUID));
3469 if (pInheritedObjectGuid != NULL)
3471 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3472 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3474 else
3476 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3477 sizeof(GUID));
3480 pObjSid->ObjectsPresent = ObjectsPresent;
3481 pObjSid->pSid = pSid;
3483 /* Fill the TRUSTEE structure */
3484 pTrustee->pMultipleTrustee = NULL;
3485 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3486 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3487 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3488 pTrustee->ptstrName = (LPWSTR) pObjSid;
3491 /******************************************************************************
3492 * BuildTrusteeWithSidA [ADVAPI32.@]
3494 VOID WINAPI BuildTrusteeWithSidA(PTRUSTEEA pTrustee, PSID pSid)
3496 TRACE("%p %p\n", pTrustee, pSid);
3498 pTrustee->pMultipleTrustee = NULL;
3499 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3500 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3501 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3502 pTrustee->ptstrName = pSid;
3505 /******************************************************************************
3506 * BuildTrusteeWithSidW [ADVAPI32.@]
3508 VOID WINAPI BuildTrusteeWithSidW(PTRUSTEEW pTrustee, PSID pSid)
3510 TRACE("%p %p\n", pTrustee, pSid);
3512 pTrustee->pMultipleTrustee = NULL;
3513 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3514 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3515 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3516 pTrustee->ptstrName = pSid;
3519 /******************************************************************************
3520 * BuildTrusteeWithNameA [ADVAPI32.@]
3522 VOID WINAPI BuildTrusteeWithNameA(PTRUSTEEA pTrustee, LPSTR name)
3524 TRACE("%p %s\n", pTrustee, debugstr_a(name) );
3526 pTrustee->pMultipleTrustee = NULL;
3527 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3528 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3529 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3530 pTrustee->ptstrName = name;
3533 /******************************************************************************
3534 * BuildTrusteeWithNameW [ADVAPI32.@]
3536 VOID WINAPI BuildTrusteeWithNameW(PTRUSTEEW pTrustee, LPWSTR name)
3538 TRACE("%p %s\n", pTrustee, debugstr_w(name) );
3540 pTrustee->pMultipleTrustee = NULL;
3541 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3542 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3543 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3544 pTrustee->ptstrName = name;
3547 /******************************************************************************
3548 * GetTrusteeFormA [ADVAPI32.@]
3550 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee)
3552 TRACE("(%p)\n", pTrustee);
3554 if (!pTrustee)
3555 return TRUSTEE_BAD_FORM;
3557 return pTrustee->TrusteeForm;
3560 /******************************************************************************
3561 * GetTrusteeFormW [ADVAPI32.@]
3563 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee)
3565 TRACE("(%p)\n", pTrustee);
3567 if (!pTrustee)
3568 return TRUSTEE_BAD_FORM;
3570 return pTrustee->TrusteeForm;
3573 /******************************************************************************
3574 * GetTrusteeNameA [ADVAPI32.@]
3576 LPSTR WINAPI GetTrusteeNameA(PTRUSTEEA pTrustee)
3578 TRACE("(%p)\n", pTrustee);
3580 if (!pTrustee)
3581 return NULL;
3583 return pTrustee->ptstrName;
3586 /******************************************************************************
3587 * GetTrusteeNameW [ADVAPI32.@]
3589 LPWSTR WINAPI GetTrusteeNameW(PTRUSTEEW pTrustee)
3591 TRACE("(%p)\n", pTrustee);
3593 if (!pTrustee)
3594 return NULL;
3596 return pTrustee->ptstrName;
3599 /******************************************************************************
3600 * GetTrusteeTypeA [ADVAPI32.@]
3602 TRUSTEE_TYPE WINAPI GetTrusteeTypeA(PTRUSTEEA pTrustee)
3604 TRACE("(%p)\n", pTrustee);
3606 if (!pTrustee)
3607 return TRUSTEE_IS_UNKNOWN;
3609 return pTrustee->TrusteeType;
3612 /******************************************************************************
3613 * GetTrusteeTypeW [ADVAPI32.@]
3615 TRUSTEE_TYPE WINAPI GetTrusteeTypeW(PTRUSTEEW pTrustee)
3617 TRACE("(%p)\n", pTrustee);
3619 if (!pTrustee)
3620 return TRUSTEE_IS_UNKNOWN;
3622 return pTrustee->TrusteeType;
3625 BOOL WINAPI SetAclInformation( PACL pAcl, LPVOID pAclInformation,
3626 DWORD nAclInformationLength,
3627 ACL_INFORMATION_CLASS dwAclInformationClass )
3629 FIXME("%p %p 0x%08x 0x%08x - stub\n", pAcl, pAclInformation,
3630 nAclInformationLength, dwAclInformationClass);
3632 return TRUE;
3635 static DWORD trustee_name_A_to_W(TRUSTEE_FORM form, char *trustee_nameA, WCHAR **ptrustee_nameW)
3637 switch (form)
3639 case TRUSTEE_IS_NAME:
3641 *ptrustee_nameW = SERV_dup(trustee_nameA);
3642 return ERROR_SUCCESS;
3644 case TRUSTEE_IS_OBJECTS_AND_NAME:
3646 OBJECTS_AND_NAME_A *objA = (OBJECTS_AND_NAME_A *)trustee_nameA;
3647 OBJECTS_AND_NAME_W *objW = NULL;
3649 if (objA)
3651 if (!(objW = heap_alloc( sizeof(OBJECTS_AND_NAME_W) )))
3652 return ERROR_NOT_ENOUGH_MEMORY;
3654 objW->ObjectsPresent = objA->ObjectsPresent;
3655 objW->ObjectType = objA->ObjectType;
3656 objW->ObjectTypeName = SERV_dup(objA->ObjectTypeName);
3657 objW->InheritedObjectTypeName = SERV_dup(objA->InheritedObjectTypeName);
3658 objW->ptstrName = SERV_dup(objA->ptstrName);
3661 *ptrustee_nameW = (WCHAR *)objW;
3662 return ERROR_SUCCESS;
3664 /* These forms do not require conversion. */
3665 case TRUSTEE_IS_SID:
3666 case TRUSTEE_IS_OBJECTS_AND_SID:
3667 *ptrustee_nameW = (WCHAR *)trustee_nameA;
3668 return ERROR_SUCCESS;
3669 default:
3670 return ERROR_INVALID_PARAMETER;
3674 static void free_trustee_name(TRUSTEE_FORM form, WCHAR *trustee_nameW)
3676 switch (form)
3678 case TRUSTEE_IS_NAME:
3679 heap_free( trustee_nameW );
3680 break;
3681 case TRUSTEE_IS_OBJECTS_AND_NAME:
3683 OBJECTS_AND_NAME_W *objW = (OBJECTS_AND_NAME_W *)trustee_nameW;
3685 if (objW)
3687 heap_free( objW->ptstrName );
3688 heap_free( objW->InheritedObjectTypeName );
3689 heap_free( objW->ObjectTypeName );
3690 heap_free( objW );
3693 break;
3695 /* Other forms did not require allocation, so no freeing is necessary. */
3696 default:
3697 break;
3701 /******************************************************************************
3702 * SetEntriesInAclA [ADVAPI32.@]
3704 DWORD WINAPI SetEntriesInAclA( ULONG count, PEXPLICIT_ACCESSA pEntries,
3705 PACL OldAcl, PACL* NewAcl )
3707 DWORD err = ERROR_SUCCESS;
3708 EXPLICIT_ACCESSW *pEntriesW;
3709 UINT alloc_index, free_index;
3711 TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
3713 if (NewAcl)
3714 *NewAcl = NULL;
3716 if (!count && !OldAcl)
3717 return ERROR_SUCCESS;
3719 pEntriesW = heap_alloc( count * sizeof(EXPLICIT_ACCESSW) );
3720 if (!pEntriesW)
3721 return ERROR_NOT_ENOUGH_MEMORY;
3723 for (alloc_index = 0; alloc_index < count; ++alloc_index)
3725 pEntriesW[alloc_index].grfAccessPermissions = pEntries[alloc_index].grfAccessPermissions;
3726 pEntriesW[alloc_index].grfAccessMode = pEntries[alloc_index].grfAccessMode;
3727 pEntriesW[alloc_index].grfInheritance = pEntries[alloc_index].grfInheritance;
3728 pEntriesW[alloc_index].Trustee.pMultipleTrustee = NULL; /* currently not supported */
3729 pEntriesW[alloc_index].Trustee.MultipleTrusteeOperation = pEntries[alloc_index].Trustee.MultipleTrusteeOperation;
3730 pEntriesW[alloc_index].Trustee.TrusteeForm = pEntries[alloc_index].Trustee.TrusteeForm;
3731 pEntriesW[alloc_index].Trustee.TrusteeType = pEntries[alloc_index].Trustee.TrusteeType;
3733 err = trustee_name_A_to_W( pEntries[alloc_index].Trustee.TrusteeForm,
3734 pEntries[alloc_index].Trustee.ptstrName,
3735 &pEntriesW[alloc_index].Trustee.ptstrName );
3736 if (err != ERROR_SUCCESS)
3738 if (err == ERROR_INVALID_PARAMETER)
3739 WARN("bad trustee form %d for trustee %d\n",
3740 pEntries[alloc_index].Trustee.TrusteeForm, alloc_index);
3742 goto cleanup;
3746 err = SetEntriesInAclW( count, pEntriesW, OldAcl, NewAcl );
3748 cleanup:
3749 /* Free any previously allocated trustee name buffers, taking into account
3750 * a possible out-of-memory condition while building the EXPLICIT_ACCESSW
3751 * list. */
3752 for (free_index = 0; free_index < alloc_index; ++free_index)
3753 free_trustee_name( pEntriesW[free_index].Trustee.TrusteeForm, pEntriesW[free_index].Trustee.ptstrName );
3755 heap_free( pEntriesW );
3756 return err;
3759 /******************************************************************************
3760 * SetEntriesInAclW [ADVAPI32.@]
3762 DWORD WINAPI SetEntriesInAclW( ULONG count, PEXPLICIT_ACCESSW pEntries,
3763 PACL OldAcl, PACL* NewAcl )
3765 ULONG i;
3766 PSID *ppsid;
3767 DWORD ret = ERROR_SUCCESS;
3768 DWORD acl_size = sizeof(ACL);
3769 NTSTATUS status;
3771 TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
3773 if (NewAcl)
3774 *NewAcl = NULL;
3776 if (!count && !OldAcl)
3777 return ERROR_SUCCESS;
3779 /* allocate array of maximum sized sids allowed */
3780 ppsid = heap_alloc(count * (sizeof(SID *) + FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES])));
3781 if (!ppsid)
3782 return ERROR_OUTOFMEMORY;
3784 for (i = 0; i < count; i++)
3786 ppsid[i] = (char *)&ppsid[count] + i * FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3788 TRACE("[%d]:\n\tgrfAccessPermissions = 0x%x\n\tgrfAccessMode = %d\n\tgrfInheritance = 0x%x\n\t"
3789 "Trustee.pMultipleTrustee = %p\n\tMultipleTrusteeOperation = %d\n\tTrusteeForm = %d\n\t"
3790 "Trustee.TrusteeType = %d\n\tptstrName = %p\n", i,
3791 pEntries[i].grfAccessPermissions, pEntries[i].grfAccessMode, pEntries[i].grfInheritance,
3792 pEntries[i].Trustee.pMultipleTrustee, pEntries[i].Trustee.MultipleTrusteeOperation,
3793 pEntries[i].Trustee.TrusteeForm, pEntries[i].Trustee.TrusteeType,
3794 pEntries[i].Trustee.ptstrName);
3796 if (pEntries[i].Trustee.MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE)
3798 WARN("bad multiple trustee operation %d for trustee %d\n", pEntries[i].Trustee.MultipleTrusteeOperation, i);
3799 ret = ERROR_INVALID_PARAMETER;
3800 goto exit;
3803 switch (pEntries[i].Trustee.TrusteeForm)
3805 case TRUSTEE_IS_SID:
3806 if (!CopySid(FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]),
3807 ppsid[i], pEntries[i].Trustee.ptstrName))
3809 WARN("bad sid %p for trustee %d\n", pEntries[i].Trustee.ptstrName, i);
3810 ret = ERROR_INVALID_PARAMETER;
3811 goto exit;
3813 break;
3814 case TRUSTEE_IS_NAME:
3816 DWORD sid_size = FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3817 DWORD domain_size = MAX_COMPUTERNAME_LENGTH + 1;
3818 SID_NAME_USE use;
3819 if (!strcmpW( pEntries[i].Trustee.ptstrName, CURRENT_USER ))
3821 if (!lookup_user_account_name( ppsid[i], &sid_size, NULL, &domain_size, &use ))
3823 ret = GetLastError();
3824 goto exit;
3827 else if (!LookupAccountNameW(NULL, pEntries[i].Trustee.ptstrName, ppsid[i], &sid_size, NULL, &domain_size, &use))
3829 WARN("bad user name %s for trustee %d\n", debugstr_w(pEntries[i].Trustee.ptstrName), i);
3830 ret = ERROR_INVALID_PARAMETER;
3831 goto exit;
3833 break;
3835 case TRUSTEE_IS_OBJECTS_AND_SID:
3836 FIXME("TRUSTEE_IS_OBJECTS_AND_SID unimplemented\n");
3837 break;
3838 case TRUSTEE_IS_OBJECTS_AND_NAME:
3839 FIXME("TRUSTEE_IS_OBJECTS_AND_NAME unimplemented\n");
3840 break;
3841 default:
3842 WARN("bad trustee form %d for trustee %d\n", pEntries[i].Trustee.TrusteeForm, i);
3843 ret = ERROR_INVALID_PARAMETER;
3844 goto exit;
3847 /* Note: we overestimate the ACL size here as a tradeoff between
3848 * instructions (simplicity) and memory */
3849 switch (pEntries[i].grfAccessMode)
3851 case GRANT_ACCESS:
3852 case SET_ACCESS:
3853 acl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3854 break;
3855 case DENY_ACCESS:
3856 acl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3857 break;
3858 case SET_AUDIT_SUCCESS:
3859 case SET_AUDIT_FAILURE:
3860 acl_size += FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart) + GetLengthSid(ppsid[i]);
3861 break;
3862 case REVOKE_ACCESS:
3863 break;
3864 default:
3865 WARN("bad access mode %d for trustee %d\n", pEntries[i].grfAccessMode, i);
3866 ret = ERROR_INVALID_PARAMETER;
3867 goto exit;
3871 if (OldAcl)
3873 ACL_SIZE_INFORMATION size_info;
3875 status = RtlQueryInformationAcl(OldAcl, &size_info, sizeof(size_info), AclSizeInformation);
3876 if (status != STATUS_SUCCESS)
3878 ret = RtlNtStatusToDosError(status);
3879 goto exit;
3881 acl_size += size_info.AclBytesInUse - sizeof(ACL);
3884 *NewAcl = LocalAlloc(0, acl_size);
3885 if (!*NewAcl)
3887 ret = ERROR_OUTOFMEMORY;
3888 goto exit;
3891 status = RtlCreateAcl( *NewAcl, acl_size, ACL_REVISION );
3892 if (status != STATUS_SUCCESS)
3894 ret = RtlNtStatusToDosError(status);
3895 goto exit;
3898 for (i = 0; i < count; i++)
3900 switch (pEntries[i].grfAccessMode)
3902 case GRANT_ACCESS:
3903 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3904 pEntries[i].grfInheritance,
3905 pEntries[i].grfAccessPermissions,
3906 ppsid[i]);
3907 break;
3908 case SET_ACCESS:
3910 ULONG j;
3911 BOOL add = TRUE;
3912 if (OldAcl)
3914 for (j = 0; ; j++)
3916 const ACE_HEADER *existing_ace_header;
3917 status = RtlGetAce(OldAcl, j, (LPVOID *)&existing_ace_header);
3918 if (status != STATUS_SUCCESS)
3919 break;
3920 if (pEntries[i].grfAccessMode == SET_ACCESS &&
3921 existing_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3922 EqualSid(ppsid[i], &((ACCESS_ALLOWED_ACE *)existing_ace_header)->SidStart))
3924 add = FALSE;
3925 break;
3929 if (add)
3930 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3931 pEntries[i].grfInheritance,
3932 pEntries[i].grfAccessPermissions,
3933 ppsid[i]);
3934 break;
3936 case DENY_ACCESS:
3937 status = RtlAddAccessDeniedAceEx(*NewAcl, ACL_REVISION,
3938 pEntries[i].grfInheritance,
3939 pEntries[i].grfAccessPermissions,
3940 ppsid[i]);
3941 break;
3942 case SET_AUDIT_SUCCESS:
3943 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3944 pEntries[i].grfInheritance,
3945 pEntries[i].grfAccessPermissions,
3946 ppsid[i], TRUE, FALSE);
3947 break;
3948 case SET_AUDIT_FAILURE:
3949 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3950 pEntries[i].grfInheritance,
3951 pEntries[i].grfAccessPermissions,
3952 ppsid[i], FALSE, TRUE);
3953 break;
3954 default:
3955 FIXME("unhandled access mode %d\n", pEntries[i].grfAccessMode);
3959 if (OldAcl)
3961 for (i = 0; ; i++)
3963 BOOL add = TRUE;
3964 ULONG j;
3965 const ACE_HEADER *old_ace_header;
3966 status = RtlGetAce(OldAcl, i, (LPVOID *)&old_ace_header);
3967 if (status != STATUS_SUCCESS) break;
3968 for (j = 0; j < count; j++)
3970 if (pEntries[j].grfAccessMode == SET_ACCESS &&
3971 old_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3972 EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3974 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION, pEntries[j].grfInheritance, pEntries[j].grfAccessPermissions, ppsid[j]);
3975 add = FALSE;
3976 break;
3978 else if (pEntries[j].grfAccessMode == REVOKE_ACCESS)
3980 switch (old_ace_header->AceType)
3982 case ACCESS_ALLOWED_ACE_TYPE:
3983 if (EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3984 add = FALSE;
3985 break;
3986 case ACCESS_DENIED_ACE_TYPE:
3987 if (EqualSid(ppsid[j], &((ACCESS_DENIED_ACE *)old_ace_header)->SidStart))
3988 add = FALSE;
3989 break;
3990 case SYSTEM_AUDIT_ACE_TYPE:
3991 if (EqualSid(ppsid[j], &((SYSTEM_AUDIT_ACE *)old_ace_header)->SidStart))
3992 add = FALSE;
3993 break;
3994 case SYSTEM_ALARM_ACE_TYPE:
3995 if (EqualSid(ppsid[j], &((SYSTEM_ALARM_ACE *)old_ace_header)->SidStart))
3996 add = FALSE;
3997 break;
3998 default:
3999 FIXME("unhandled ace type %d\n", old_ace_header->AceType);
4002 if (!add)
4003 break;
4006 if (add)
4007 status = RtlAddAce(*NewAcl, ACL_REVISION, 1, (PACE_HEADER)old_ace_header, old_ace_header->AceSize);
4008 if (status != STATUS_SUCCESS)
4010 WARN("RtlAddAce failed with error 0x%08x\n", status);
4011 ret = RtlNtStatusToDosError(status);
4012 break;
4017 exit:
4018 heap_free(ppsid);
4019 return ret;
4022 /******************************************************************************
4023 * SetNamedSecurityInfoA [ADVAPI32.@]
4025 DWORD WINAPI SetNamedSecurityInfoA(LPSTR pObjectName,
4026 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
4027 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
4029 LPWSTR wstr;
4030 DWORD r;
4032 TRACE("%s %d %d %p %p %p %p\n", debugstr_a(pObjectName), ObjectType,
4033 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
4035 wstr = SERV_dup(pObjectName);
4036 r = SetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, psidOwner,
4037 psidGroup, pDacl, pSacl );
4039 heap_free( wstr );
4041 return r;
4044 BOOL WINAPI SetPrivateObjectSecurity( SECURITY_INFORMATION SecurityInformation,
4045 PSECURITY_DESCRIPTOR ModificationDescriptor,
4046 PSECURITY_DESCRIPTOR* ObjectsSecurityDescriptor,
4047 PGENERIC_MAPPING GenericMapping,
4048 HANDLE Token )
4050 FIXME("0x%08x %p %p %p %p - stub\n", SecurityInformation, ModificationDescriptor,
4051 ObjectsSecurityDescriptor, GenericMapping, Token);
4053 return TRUE;
4056 BOOL WINAPI AreAllAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
4058 return RtlAreAllAccessesGranted( GrantedAccess, DesiredAccess );
4061 /******************************************************************************
4062 * AreAnyAccessesGranted [ADVAPI32.@]
4064 * Determines whether or not any of a set of specified access permissions have
4065 * been granted or not.
4067 * PARAMS
4068 * GrantedAccess [I] The permissions that have been granted.
4069 * DesiredAccess [I] The permissions that you want to have.
4071 * RETURNS
4072 * Nonzero if any of the permissions have been granted, zero if none of the
4073 * permissions have been granted.
4076 BOOL WINAPI AreAnyAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
4078 return RtlAreAnyAccessesGranted( GrantedAccess, DesiredAccess );
4081 /******************************************************************************
4082 * SetNamedSecurityInfoW [ADVAPI32.@]
4084 DWORD WINAPI SetNamedSecurityInfoW(LPWSTR pObjectName,
4085 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
4086 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
4088 DWORD access = 0;
4089 HANDLE handle;
4090 DWORD err;
4092 TRACE( "%s %d %d %p %p %p %p\n", debugstr_w(pObjectName), ObjectType,
4093 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
4095 if (!pObjectName) return ERROR_INVALID_PARAMETER;
4097 if (SecurityInfo & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION))
4098 access |= WRITE_OWNER;
4099 if (SecurityInfo & DACL_SECURITY_INFORMATION)
4100 access |= WRITE_DAC;
4101 if (SecurityInfo & SACL_SECURITY_INFORMATION)
4102 access |= ACCESS_SYSTEM_SECURITY;
4104 switch (ObjectType)
4106 case SE_SERVICE:
4107 if (!(err = get_security_service( pObjectName, access, &handle )))
4109 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4110 CloseServiceHandle( handle );
4112 break;
4113 case SE_REGISTRY_KEY:
4114 if (!(err = get_security_regkey( pObjectName, access, &handle )))
4116 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4117 RegCloseKey( handle );
4119 break;
4120 case SE_FILE_OBJECT:
4121 if (SecurityInfo & DACL_SECURITY_INFORMATION)
4122 access |= READ_CONTROL;
4123 if (!(err = get_security_file( pObjectName, access, &handle )))
4125 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4126 CloseHandle( handle );
4128 break;
4129 default:
4130 FIXME( "Object type %d is not currently supported.\n", ObjectType );
4131 return ERROR_SUCCESS;
4133 return err;
4136 /******************************************************************************
4137 * GetExplicitEntriesFromAclA [ADVAPI32.@]
4139 DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntries,
4140 PEXPLICIT_ACCESSA* pListOfExplicitEntries)
4142 FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
4143 return ERROR_CALL_NOT_IMPLEMENTED;
4146 /******************************************************************************
4147 * GetExplicitEntriesFromAclW [ADVAPI32.@]
4149 DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG pcCountOfExplicitEntries,
4150 PEXPLICIT_ACCESSW* pListOfExplicitEntries)
4152 FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
4153 return ERROR_CALL_NOT_IMPLEMENTED;
4156 /******************************************************************************
4157 * GetAuditedPermissionsFromAclA [ADVAPI32.@]
4159 DWORD WINAPI GetAuditedPermissionsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
4160 PACCESS_MASK pFailedAuditRights)
4162 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
4163 return ERROR_CALL_NOT_IMPLEMENTED;
4167 /******************************************************************************
4168 * GetAuditedPermissionsFromAclW [ADVAPI32.@]
4170 DWORD WINAPI GetAuditedPermissionsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
4171 PACCESS_MASK pFailedAuditRights)
4173 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
4174 return ERROR_CALL_NOT_IMPLEMENTED;
4178 /******************************************************************************
4179 * ParseAclStringFlags
4181 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
4183 DWORD flags = 0;
4184 LPCWSTR szAcl = *StringAcl;
4186 while (*szAcl != '(')
4188 if (*szAcl == 'P')
4190 flags |= SE_DACL_PROTECTED;
4192 else if (*szAcl == 'A')
4194 szAcl++;
4195 if (*szAcl == 'R')
4196 flags |= SE_DACL_AUTO_INHERIT_REQ;
4197 else if (*szAcl == 'I')
4198 flags |= SE_DACL_AUTO_INHERITED;
4200 szAcl++;
4203 *StringAcl = szAcl;
4204 return flags;
4207 /******************************************************************************
4208 * ParseAceStringType
4210 static const ACEFLAG AceType[] =
4212 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
4213 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
4214 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
4215 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
4216 { SDDL_MANDATORY_LABEL,SYSTEM_MANDATORY_LABEL_ACE_TYPE },
4218 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
4219 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
4220 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
4221 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
4223 { NULL, 0 },
4226 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
4228 UINT len = 0;
4229 LPCWSTR szAcl = *StringAcl;
4230 const ACEFLAG *lpaf = AceType;
4232 while (*szAcl == ' ')
4233 szAcl++;
4235 while (lpaf->wstr &&
4236 (len = strlenW(lpaf->wstr)) &&
4237 strncmpW(lpaf->wstr, szAcl, len))
4238 lpaf++;
4240 if (!lpaf->wstr)
4241 return 0;
4243 *StringAcl = szAcl + len;
4244 return lpaf->value;
4248 /******************************************************************************
4249 * ParseAceStringFlags
4251 static const ACEFLAG AceFlags[] =
4253 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
4254 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
4255 { SDDL_INHERITED, INHERITED_ACE },
4256 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
4257 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
4258 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
4259 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
4260 { NULL, 0 },
4263 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
4265 UINT len = 0;
4266 BYTE flags = 0;
4267 LPCWSTR szAcl = *StringAcl;
4269 while (*szAcl == ' ')
4270 szAcl++;
4272 while (*szAcl != ';')
4274 const ACEFLAG *lpaf = AceFlags;
4276 while (lpaf->wstr &&
4277 (len = strlenW(lpaf->wstr)) &&
4278 strncmpW(lpaf->wstr, szAcl, len))
4279 lpaf++;
4281 if (!lpaf->wstr)
4282 return 0;
4284 flags |= lpaf->value;
4285 szAcl += len;
4288 *StringAcl = szAcl;
4289 return flags;
4293 /******************************************************************************
4294 * ParseAceStringRights
4296 static const ACEFLAG AceRights[] =
4298 { SDDL_GENERIC_ALL, GENERIC_ALL },
4299 { SDDL_GENERIC_READ, GENERIC_READ },
4300 { SDDL_GENERIC_WRITE, GENERIC_WRITE },
4301 { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
4303 { SDDL_READ_CONTROL, READ_CONTROL },
4304 { SDDL_STANDARD_DELETE, DELETE },
4305 { SDDL_WRITE_DAC, WRITE_DAC },
4306 { SDDL_WRITE_OWNER, WRITE_OWNER },
4308 { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP},
4309 { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP},
4310 { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD},
4311 { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD},
4312 { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST},
4313 { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF},
4314 { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT},
4315 { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE},
4316 { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS},
4318 { SDDL_FILE_ALL, FILE_ALL_ACCESS },
4319 { SDDL_FILE_READ, FILE_GENERIC_READ },
4320 { SDDL_FILE_WRITE, FILE_GENERIC_WRITE },
4321 { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE },
4323 { SDDL_KEY_ALL, KEY_ALL_ACCESS },
4324 { SDDL_KEY_READ, KEY_READ },
4325 { SDDL_KEY_WRITE, KEY_WRITE },
4326 { SDDL_KEY_EXECUTE, KEY_EXECUTE },
4328 { SDDL_NO_READ_UP, SYSTEM_MANDATORY_LABEL_NO_READ_UP },
4329 { SDDL_NO_WRITE_UP, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP },
4330 { SDDL_NO_EXECUTE_UP, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP },
4331 { NULL, 0 },
4334 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
4336 UINT len = 0;
4337 DWORD rights = 0;
4338 LPCWSTR szAcl = *StringAcl;
4340 while (*szAcl == ' ')
4341 szAcl++;
4343 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
4345 LPCWSTR p = szAcl;
4347 while (*p && *p != ';')
4348 p++;
4350 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
4352 rights = strtoulW(szAcl, NULL, 16);
4353 szAcl = p;
4355 else
4356 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
4358 else
4360 while (*szAcl != ';')
4362 const ACEFLAG *lpaf = AceRights;
4364 while (lpaf->wstr &&
4365 (len = strlenW(lpaf->wstr)) &&
4366 strncmpW(lpaf->wstr, szAcl, len))
4368 lpaf++;
4371 if (!lpaf->wstr)
4372 return 0;
4374 rights |= lpaf->value;
4375 szAcl += len;
4379 *StringAcl = szAcl;
4380 return rights;
4384 /******************************************************************************
4385 * ParseStringAclToAcl
4387 * dacl_flags(string_ace1)(string_ace2)... (string_acen)
4389 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
4390 PACL pAcl, LPDWORD cBytes)
4392 DWORD val;
4393 DWORD sidlen;
4394 DWORD length = sizeof(ACL);
4395 DWORD acesize = 0;
4396 DWORD acecount = 0;
4397 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
4398 DWORD error = ERROR_INVALID_ACL;
4400 TRACE("%s\n", debugstr_w(StringAcl));
4402 if (!StringAcl)
4403 return FALSE;
4405 if (pAcl) /* pAce is only useful if we're setting values */
4406 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
4408 /* Parse ACL flags */
4409 *lpdwFlags = ParseAclStringFlags(&StringAcl);
4411 /* Parse ACE */
4412 while (*StringAcl == '(')
4414 StringAcl++;
4416 /* Parse ACE type */
4417 val = ParseAceStringType(&StringAcl);
4418 if (pAce)
4419 pAce->Header.AceType = (BYTE) val;
4420 if (*StringAcl != ';')
4422 error = RPC_S_INVALID_STRING_UUID;
4423 goto lerr;
4425 StringAcl++;
4427 /* Parse ACE flags */
4428 val = ParseAceStringFlags(&StringAcl);
4429 if (pAce)
4430 pAce->Header.AceFlags = (BYTE) val;
4431 if (*StringAcl != ';')
4432 goto lerr;
4433 StringAcl++;
4435 /* Parse ACE rights */
4436 val = ParseAceStringRights(&StringAcl);
4437 if (pAce)
4438 pAce->Mask = val;
4439 if (*StringAcl != ';')
4440 goto lerr;
4441 StringAcl++;
4443 /* Parse ACE object guid */
4444 while (*StringAcl == ' ')
4445 StringAcl++;
4446 if (*StringAcl != ';')
4448 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4449 goto lerr;
4451 StringAcl++;
4453 /* Parse ACE inherit object guid */
4454 while (*StringAcl == ' ')
4455 StringAcl++;
4456 if (*StringAcl != ';')
4458 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4459 goto lerr;
4461 StringAcl++;
4463 /* Parse ACE account sid */
4464 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
4466 while (*StringAcl && *StringAcl != ')')
4467 StringAcl++;
4470 if (*StringAcl != ')')
4471 goto lerr;
4472 StringAcl++;
4474 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
4475 length += acesize;
4476 if (pAce)
4478 pAce->Header.AceSize = acesize;
4479 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
4481 acecount++;
4484 *cBytes = length;
4486 if (length > 0xffff)
4488 ERR("ACL too large\n");
4489 goto lerr;
4492 if (pAcl)
4494 pAcl->AclRevision = ACL_REVISION;
4495 pAcl->Sbz1 = 0;
4496 pAcl->AclSize = length;
4497 pAcl->AceCount = acecount++;
4498 pAcl->Sbz2 = 0;
4500 return TRUE;
4502 lerr:
4503 SetLastError(error);
4504 WARN("Invalid ACE string format\n");
4505 return FALSE;
4509 /******************************************************************************
4510 * ParseStringSecurityDescriptorToSecurityDescriptor
4512 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
4513 LPCWSTR StringSecurityDescriptor,
4514 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
4515 LPDWORD cBytes)
4517 BOOL bret = FALSE;
4518 WCHAR toktype;
4519 WCHAR *tok;
4520 LPCWSTR lptoken;
4521 LPBYTE lpNext = NULL;
4522 DWORD len;
4524 *cBytes = sizeof(SECURITY_DESCRIPTOR);
4526 tok = heap_alloc( (lstrlenW(StringSecurityDescriptor) + 1) * sizeof(WCHAR));
4528 if (SecurityDescriptor)
4529 lpNext = (LPBYTE)(SecurityDescriptor + 1);
4531 while (*StringSecurityDescriptor == ' ')
4532 StringSecurityDescriptor++;
4534 while (*StringSecurityDescriptor)
4536 toktype = *StringSecurityDescriptor;
4538 /* Expect char identifier followed by ':' */
4539 StringSecurityDescriptor++;
4540 if (*StringSecurityDescriptor != ':')
4542 SetLastError(ERROR_INVALID_PARAMETER);
4543 goto lend;
4545 StringSecurityDescriptor++;
4547 /* Extract token */
4548 lptoken = StringSecurityDescriptor;
4549 while (*lptoken && *lptoken != ':')
4550 lptoken++;
4552 if (*lptoken)
4553 lptoken--;
4555 len = lptoken - StringSecurityDescriptor;
4556 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
4557 tok[len] = 0;
4559 switch (toktype)
4561 case 'O':
4563 DWORD bytes;
4565 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4566 goto lend;
4568 if (SecurityDescriptor)
4570 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
4571 lpNext += bytes; /* Advance to next token */
4574 *cBytes += bytes;
4576 break;
4579 case 'G':
4581 DWORD bytes;
4583 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4584 goto lend;
4586 if (SecurityDescriptor)
4588 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
4589 lpNext += bytes; /* Advance to next token */
4592 *cBytes += bytes;
4594 break;
4597 case 'D':
4599 DWORD flags;
4600 DWORD bytes;
4602 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4603 goto lend;
4605 if (SecurityDescriptor)
4607 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
4608 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
4609 lpNext += bytes; /* Advance to next token */
4612 *cBytes += bytes;
4614 break;
4617 case 'S':
4619 DWORD flags;
4620 DWORD bytes;
4622 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4623 goto lend;
4625 if (SecurityDescriptor)
4627 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
4628 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
4629 lpNext += bytes; /* Advance to next token */
4632 *cBytes += bytes;
4634 break;
4637 default:
4638 FIXME("Unknown token\n");
4639 SetLastError(ERROR_INVALID_PARAMETER);
4640 goto lend;
4643 StringSecurityDescriptor = lptoken;
4646 bret = TRUE;
4648 lend:
4649 heap_free(tok);
4650 return bret;
4653 /******************************************************************************
4654 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
4656 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
4657 LPCSTR StringSecurityDescriptor,
4658 DWORD StringSDRevision,
4659 PSECURITY_DESCRIPTOR* SecurityDescriptor,
4660 PULONG SecurityDescriptorSize)
4662 BOOL ret;
4663 LPWSTR StringSecurityDescriptorW;
4665 if(!StringSecurityDescriptor)
4666 return FALSE;
4668 StringSecurityDescriptorW = SERV_dup(StringSecurityDescriptor);
4669 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
4670 StringSDRevision, SecurityDescriptor,
4671 SecurityDescriptorSize);
4672 heap_free(StringSecurityDescriptorW);
4674 return ret;
4677 /******************************************************************************
4678 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
4680 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
4681 LPCWSTR StringSecurityDescriptor,
4682 DWORD StringSDRevision,
4683 PSECURITY_DESCRIPTOR* SecurityDescriptor,
4684 PULONG SecurityDescriptorSize)
4686 DWORD cBytes;
4687 SECURITY_DESCRIPTOR* psd;
4688 BOOL bret = FALSE;
4690 TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
4692 if (GetVersion() & 0x80000000)
4694 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4695 goto lend;
4697 else if (!StringSecurityDescriptor || !SecurityDescriptor)
4699 SetLastError(ERROR_INVALID_PARAMETER);
4700 goto lend;
4702 else if (StringSDRevision != SID_REVISION)
4704 SetLastError(ERROR_UNKNOWN_REVISION);
4705 goto lend;
4708 /* Compute security descriptor length */
4709 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4710 NULL, &cBytes))
4711 goto lend;
4713 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
4714 if (!psd) goto lend;
4716 psd->Revision = SID_REVISION;
4717 psd->Control |= SE_SELF_RELATIVE;
4719 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4720 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
4722 LocalFree(psd);
4723 goto lend;
4726 if (SecurityDescriptorSize)
4727 *SecurityDescriptorSize = cBytes;
4729 bret = TRUE;
4731 lend:
4732 TRACE(" ret=%d\n", bret);
4733 return bret;
4736 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
4738 if (cch == -1)
4739 cch = strlenW(string);
4741 if (plen)
4742 *plen += cch;
4744 if (pwptr)
4746 memcpy(*pwptr, string, sizeof(WCHAR)*cch);
4747 *pwptr += cch;
4751 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
4753 DWORD i;
4754 WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
4755 WCHAR subauthfmt[] = { '-','%','u',0 };
4756 WCHAR buf[26];
4757 SID *pisid = psid;
4759 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
4761 SetLastError(ERROR_INVALID_SID);
4762 return FALSE;
4765 if (pisid->IdentifierAuthority.Value[0] ||
4766 pisid->IdentifierAuthority.Value[1])
4768 FIXME("not matching MS' bugs\n");
4769 SetLastError(ERROR_INVALID_SID);
4770 return FALSE;
4773 sprintfW( buf, fmt, pisid->Revision,
4774 MAKELONG(
4775 MAKEWORD( pisid->IdentifierAuthority.Value[5],
4776 pisid->IdentifierAuthority.Value[4] ),
4777 MAKEWORD( pisid->IdentifierAuthority.Value[3],
4778 pisid->IdentifierAuthority.Value[2] )
4779 ) );
4780 DumpString(buf, -1, pwptr, plen);
4782 for( i=0; i<pisid->SubAuthorityCount; i++ )
4784 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
4785 DumpString(buf, -1, pwptr, plen);
4787 return TRUE;
4790 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
4792 size_t i;
4793 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
4795 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
4797 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
4798 return TRUE;
4802 return DumpSidNumeric(psid, pwptr, plen);
4805 static const LPCWSTR AceRightBitNames[32] = {
4806 SDDL_CREATE_CHILD, /* 0 */
4807 SDDL_DELETE_CHILD,
4808 SDDL_LIST_CHILDREN,
4809 SDDL_SELF_WRITE,
4810 SDDL_READ_PROPERTY, /* 4 */
4811 SDDL_WRITE_PROPERTY,
4812 SDDL_DELETE_TREE,
4813 SDDL_LIST_OBJECT,
4814 SDDL_CONTROL_ACCESS, /* 8 */
4815 NULL,
4816 NULL,
4817 NULL,
4818 NULL, /* 12 */
4819 NULL,
4820 NULL,
4821 NULL,
4822 SDDL_STANDARD_DELETE, /* 16 */
4823 SDDL_READ_CONTROL,
4824 SDDL_WRITE_DAC,
4825 SDDL_WRITE_OWNER,
4826 NULL, /* 20 */
4827 NULL,
4828 NULL,
4829 NULL,
4830 NULL, /* 24 */
4831 NULL,
4832 NULL,
4833 NULL,
4834 SDDL_GENERIC_ALL, /* 28 */
4835 SDDL_GENERIC_EXECUTE,
4836 SDDL_GENERIC_WRITE,
4837 SDDL_GENERIC_READ
4840 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
4842 static const WCHAR fmtW[] = {'0','x','%','x',0};
4843 WCHAR buf[15];
4844 size_t i;
4846 if (mask == 0)
4847 return;
4849 /* first check if the right have name */
4850 for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
4852 if (AceRights[i].wstr == NULL)
4853 break;
4854 if (mask == AceRights[i].value)
4856 DumpString(AceRights[i].wstr, -1, pwptr, plen);
4857 return;
4861 /* then check if it can be built from bit names */
4862 for (i = 0; i < 32; i++)
4864 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
4866 /* can't be built from bit names */
4867 sprintfW(buf, fmtW, mask);
4868 DumpString(buf, -1, pwptr, plen);
4869 return;
4873 /* build from bit names */
4874 for (i = 0; i < 32; i++)
4875 if (mask & (1 << i))
4876 DumpString(AceRightBitNames[i], -1, pwptr, plen);
4879 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
4881 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
4882 static const WCHAR openbr = '(';
4883 static const WCHAR closebr = ')';
4884 static const WCHAR semicolon = ';';
4886 if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
4888 SetLastError(ERROR_INVALID_ACL);
4889 return FALSE;
4892 piace = pace;
4893 DumpString(&openbr, 1, pwptr, plen);
4894 switch (piace->Header.AceType)
4896 case ACCESS_ALLOWED_ACE_TYPE:
4897 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
4898 break;
4899 case ACCESS_DENIED_ACE_TYPE:
4900 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
4901 break;
4902 case SYSTEM_AUDIT_ACE_TYPE:
4903 DumpString(SDDL_AUDIT, -1, pwptr, plen);
4904 break;
4905 case SYSTEM_ALARM_ACE_TYPE:
4906 DumpString(SDDL_ALARM, -1, pwptr, plen);
4907 break;
4909 DumpString(&semicolon, 1, pwptr, plen);
4911 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
4912 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
4913 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
4914 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
4915 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
4916 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
4917 if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
4918 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
4919 if (piace->Header.AceFlags & INHERITED_ACE)
4920 DumpString(SDDL_INHERITED, -1, pwptr, plen);
4921 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
4922 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
4923 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
4924 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
4925 DumpString(&semicolon, 1, pwptr, plen);
4926 DumpRights(piace->Mask, pwptr, plen);
4927 DumpString(&semicolon, 1, pwptr, plen);
4928 /* objects not supported */
4929 DumpString(&semicolon, 1, pwptr, plen);
4930 /* objects not supported */
4931 DumpString(&semicolon, 1, pwptr, plen);
4932 if (!DumpSid(&piace->SidStart, pwptr, plen))
4933 return FALSE;
4934 DumpString(&closebr, 1, pwptr, plen);
4935 return TRUE;
4938 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
4940 WORD count;
4941 UINT i;
4943 if (protected)
4944 DumpString(SDDL_PROTECTED, -1, pwptr, plen);
4945 if (autoInheritReq)
4946 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
4947 if (autoInherited)
4948 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
4950 if (pacl == NULL)
4951 return TRUE;
4953 if (!IsValidAcl(pacl))
4954 return FALSE;
4956 count = pacl->AceCount;
4957 for (i = 0; i < count; i++)
4959 LPVOID ace;
4960 if (!GetAce(pacl, i, &ace))
4961 return FALSE;
4962 if (!DumpAce(ace, pwptr, plen))
4963 return FALSE;
4966 return TRUE;
4969 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4971 static const WCHAR prefix[] = {'O',':',0};
4972 BOOL bDefaulted;
4973 PSID psid;
4975 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
4976 return FALSE;
4978 if (psid == NULL)
4979 return TRUE;
4981 DumpString(prefix, -1, pwptr, plen);
4982 if (!DumpSid(psid, pwptr, plen))
4983 return FALSE;
4984 return TRUE;
4987 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4989 static const WCHAR prefix[] = {'G',':',0};
4990 BOOL bDefaulted;
4991 PSID psid;
4993 if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
4994 return FALSE;
4996 if (psid == NULL)
4997 return TRUE;
4999 DumpString(prefix, -1, pwptr, plen);
5000 if (!DumpSid(psid, pwptr, plen))
5001 return FALSE;
5002 return TRUE;
5005 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
5007 static const WCHAR dacl[] = {'D',':',0};
5008 SECURITY_DESCRIPTOR_CONTROL control;
5009 BOOL present, defaulted;
5010 DWORD revision;
5011 PACL pacl;
5013 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
5014 return FALSE;
5016 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
5017 return FALSE;
5019 if (!present)
5020 return TRUE;
5022 DumpString(dacl, 2, pwptr, plen);
5023 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
5024 return FALSE;
5025 return TRUE;
5028 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
5030 static const WCHAR sacl[] = {'S',':',0};
5031 SECURITY_DESCRIPTOR_CONTROL control;
5032 BOOL present, defaulted;
5033 DWORD revision;
5034 PACL pacl;
5036 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
5037 return FALSE;
5039 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
5040 return FALSE;
5042 if (!present)
5043 return TRUE;
5045 DumpString(sacl, 2, pwptr, plen);
5046 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
5047 return FALSE;
5048 return TRUE;
5051 /******************************************************************************
5052 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
5054 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen)
5056 ULONG len;
5057 WCHAR *wptr, *wstr;
5059 if (SDRevision != SDDL_REVISION_1)
5061 ERR("Program requested unknown SDDL revision %d\n", SDRevision);
5062 SetLastError(ERROR_UNKNOWN_REVISION);
5063 return FALSE;
5066 len = 0;
5067 if (RequestedInformation & OWNER_SECURITY_INFORMATION)
5068 if (!DumpOwner(SecurityDescriptor, NULL, &len))
5069 return FALSE;
5070 if (RequestedInformation & GROUP_SECURITY_INFORMATION)
5071 if (!DumpGroup(SecurityDescriptor, NULL, &len))
5072 return FALSE;
5073 if (RequestedInformation & DACL_SECURITY_INFORMATION)
5074 if (!DumpDacl(SecurityDescriptor, NULL, &len))
5075 return FALSE;
5076 if (RequestedInformation & SACL_SECURITY_INFORMATION)
5077 if (!DumpSacl(SecurityDescriptor, NULL, &len))
5078 return FALSE;
5080 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
5081 if (RequestedInformation & OWNER_SECURITY_INFORMATION)
5082 if (!DumpOwner(SecurityDescriptor, &wptr, NULL)) {
5083 LocalFree (wstr);
5084 return FALSE;
5086 if (RequestedInformation & GROUP_SECURITY_INFORMATION)
5087 if (!DumpGroup(SecurityDescriptor, &wptr, NULL)) {
5088 LocalFree (wstr);
5089 return FALSE;
5091 if (RequestedInformation & DACL_SECURITY_INFORMATION)
5092 if (!DumpDacl(SecurityDescriptor, &wptr, NULL)) {
5093 LocalFree (wstr);
5094 return FALSE;
5096 if (RequestedInformation & SACL_SECURITY_INFORMATION)
5097 if (!DumpSacl(SecurityDescriptor, &wptr, NULL)) {
5098 LocalFree (wstr);
5099 return FALSE;
5101 *wptr = 0;
5103 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
5104 *OutputString = wstr;
5105 if (OutputLen)
5106 *OutputLen = strlenW(*OutputString)+1;
5107 return TRUE;
5110 /******************************************************************************
5111 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
5113 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen)
5115 LPWSTR wstr;
5116 ULONG len;
5117 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
5119 int lenA;
5121 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
5122 *OutputString = heap_alloc(lenA);
5123 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
5124 LocalFree(wstr);
5126 if (OutputLen != NULL)
5127 *OutputLen = lenA;
5128 return TRUE;
5130 else
5132 *OutputString = NULL;
5133 if (OutputLen)
5134 *OutputLen = 0;
5135 return FALSE;
5139 /******************************************************************************
5140 * ConvertStringSidToSidW [ADVAPI32.@]
5142 BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid)
5144 BOOL bret = FALSE;
5145 DWORD cBytes;
5147 TRACE("%s, %p\n", debugstr_w(StringSid), Sid);
5148 if (GetVersion() & 0x80000000)
5149 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5150 else if (!StringSid || !Sid)
5151 SetLastError(ERROR_INVALID_PARAMETER);
5152 else if (ParseStringSidToSid(StringSid, NULL, &cBytes))
5154 PSID pSid = *Sid = LocalAlloc(0, cBytes);
5156 bret = ParseStringSidToSid(StringSid, pSid, &cBytes);
5157 if (!bret)
5158 LocalFree(*Sid);
5160 return bret;
5163 /******************************************************************************
5164 * ConvertStringSidToSidA [ADVAPI32.@]
5166 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
5168 BOOL bret = FALSE;
5170 TRACE("%s, %p\n", debugstr_a(StringSid), Sid);
5171 if (GetVersion() & 0x80000000)
5172 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5173 else if (!StringSid || !Sid)
5174 SetLastError(ERROR_INVALID_PARAMETER);
5175 else
5177 WCHAR *wStringSid = SERV_dup(StringSid);
5178 bret = ConvertStringSidToSidW(wStringSid, Sid);
5179 heap_free(wStringSid);
5181 return bret;
5184 /******************************************************************************
5185 * ConvertSidToStringSidW [ADVAPI32.@]
5187 * format of SID string is:
5188 * S-<count>-<auth>-<subauth1>-<subauth2>-<subauth3>...
5189 * where
5190 * <rev> is the revision of the SID encoded as decimal
5191 * <auth> is the identifier authority encoded as hex
5192 * <subauthN> is the subauthority id encoded as decimal
5194 BOOL WINAPI ConvertSidToStringSidW( PSID pSid, LPWSTR *pstr )
5196 DWORD len = 0;
5197 LPWSTR wstr, wptr;
5199 TRACE("%p %p\n", pSid, pstr );
5201 len = 0;
5202 if (!DumpSidNumeric(pSid, NULL, &len))
5203 return FALSE;
5204 wstr = wptr = LocalAlloc(0, (len+1) * sizeof(WCHAR));
5205 DumpSidNumeric(pSid, &wptr, NULL);
5206 *wptr = 0;
5208 *pstr = wstr;
5209 return TRUE;
5212 /******************************************************************************
5213 * ConvertSidToStringSidA [ADVAPI32.@]
5215 BOOL WINAPI ConvertSidToStringSidA(PSID pSid, LPSTR *pstr)
5217 LPWSTR wstr = NULL;
5218 LPSTR str;
5219 UINT len;
5221 TRACE("%p %p\n", pSid, pstr );
5223 if( !ConvertSidToStringSidW( pSid, &wstr ) )
5224 return FALSE;
5226 len = WideCharToMultiByte( CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL );
5227 str = LocalAlloc( 0, len );
5228 WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, len, NULL, NULL );
5229 LocalFree( wstr );
5231 *pstr = str;
5233 return TRUE;
5236 BOOL WINAPI ConvertToAutoInheritPrivateObjectSecurity(
5237 PSECURITY_DESCRIPTOR pdesc,
5238 PSECURITY_DESCRIPTOR cdesc,
5239 PSECURITY_DESCRIPTOR* ndesc,
5240 GUID* objtype,
5241 BOOL isdir,
5242 PGENERIC_MAPPING genmap )
5244 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
5246 return FALSE;
5249 BOOL WINAPI CreatePrivateObjectSecurity(
5250 PSECURITY_DESCRIPTOR ParentDescriptor,
5251 PSECURITY_DESCRIPTOR CreatorDescriptor,
5252 PSECURITY_DESCRIPTOR* NewDescriptor,
5253 BOOL IsDirectoryObject,
5254 HANDLE Token,
5255 PGENERIC_MAPPING GenericMapping )
5257 SECURITY_DESCRIPTOR_RELATIVE *relative;
5258 DWORD needed, offset;
5259 BYTE *buffer;
5261 FIXME("%p %p %p %d %p %p - returns fake SECURITY_DESCRIPTOR\n", ParentDescriptor,
5262 CreatorDescriptor, NewDescriptor, IsDirectoryObject, Token, GenericMapping);
5264 needed = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5265 needed += sizeof(sidWorld);
5266 needed += sizeof(sidWorld);
5267 needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5268 needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5270 if (!(buffer = heap_alloc( needed ))) return FALSE;
5271 relative = (SECURITY_DESCRIPTOR_RELATIVE *)buffer;
5272 if (!InitializeSecurityDescriptor( relative, SECURITY_DESCRIPTOR_REVISION ))
5274 heap_free( buffer );
5275 return FALSE;
5277 relative->Control |= SE_SELF_RELATIVE;
5278 offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5280 memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5281 relative->Owner = offset;
5282 offset += sizeof(sidWorld);
5284 memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5285 relative->Group = offset;
5286 offset += sizeof(sidWorld);
5288 GetWorldAccessACL( (ACL *)(buffer + offset) );
5289 relative->Dacl = offset;
5290 offset += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5292 GetWorldAccessACL( (ACL *)(buffer + offset) );
5293 relative->Sacl = offset;
5295 *NewDescriptor = relative;
5296 return TRUE;
5299 BOOL WINAPI DestroyPrivateObjectSecurity( PSECURITY_DESCRIPTOR* ObjectDescriptor )
5301 FIXME("%p - stub\n", ObjectDescriptor);
5303 heap_free( *ObjectDescriptor );
5304 return TRUE;
5307 BOOL WINAPI CreateProcessAsUserA(
5308 HANDLE hToken,
5309 LPCSTR lpApplicationName,
5310 LPSTR lpCommandLine,
5311 LPSECURITY_ATTRIBUTES lpProcessAttributes,
5312 LPSECURITY_ATTRIBUTES lpThreadAttributes,
5313 BOOL bInheritHandles,
5314 DWORD dwCreationFlags,
5315 LPVOID lpEnvironment,
5316 LPCSTR lpCurrentDirectory,
5317 LPSTARTUPINFOA lpStartupInfo,
5318 LPPROCESS_INFORMATION lpProcessInformation )
5320 BOOL ret;
5321 WCHAR *appW, *cmdlnW, *cwdW;
5322 STARTUPINFOW sinfo;
5324 TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken, debugstr_a(lpApplicationName),
5325 debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
5326 dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
5328 appW = SERV_dup(lpApplicationName);
5329 cmdlnW = SERV_dup(lpCommandLine);
5330 cwdW = SERV_dup(lpCurrentDirectory);
5331 sinfo.cb = sizeof(sinfo);
5332 sinfo.lpReserved = SERV_dup(lpStartupInfo->lpReserved);
5333 sinfo.lpDesktop = SERV_dup(lpStartupInfo->lpDesktop);
5334 sinfo.lpTitle = SERV_dup(lpStartupInfo->lpTitle);
5335 sinfo.dwX = lpStartupInfo->dwX;
5336 sinfo.dwY = lpStartupInfo->dwY;
5337 sinfo.dwXSize = lpStartupInfo->dwXSize;
5338 sinfo.dwYSize = lpStartupInfo->dwYSize;
5339 sinfo.dwXCountChars = lpStartupInfo->dwXCountChars;
5340 sinfo.dwYCountChars = lpStartupInfo->dwYCountChars;
5341 sinfo.dwFillAttribute = lpStartupInfo->dwFillAttribute;
5342 sinfo.dwFlags = lpStartupInfo->dwFlags;
5343 sinfo.wShowWindow = lpStartupInfo->wShowWindow;
5344 sinfo.cbReserved2 = lpStartupInfo->cbReserved2;
5345 sinfo.lpReserved2 = lpStartupInfo->lpReserved2;
5346 sinfo.hStdInput = lpStartupInfo->hStdInput;
5347 sinfo.hStdOutput = lpStartupInfo->hStdOutput;
5348 sinfo.hStdError = lpStartupInfo->hStdError;
5349 ret = CreateProcessAsUserW(hToken, appW, cmdlnW, lpProcessAttributes,
5350 lpThreadAttributes, bInheritHandles, dwCreationFlags,
5351 lpEnvironment, cwdW, &sinfo, lpProcessInformation);
5352 heap_free(appW);
5353 heap_free(cmdlnW);
5354 heap_free(cwdW);
5355 heap_free(sinfo.lpReserved);
5356 heap_free(sinfo.lpDesktop);
5357 heap_free(sinfo.lpTitle);
5359 return ret;
5362 BOOL WINAPI CreateProcessAsUserW(
5363 HANDLE hToken,
5364 LPCWSTR lpApplicationName,
5365 LPWSTR lpCommandLine,
5366 LPSECURITY_ATTRIBUTES lpProcessAttributes,
5367 LPSECURITY_ATTRIBUTES lpThreadAttributes,
5368 BOOL bInheritHandles,
5369 DWORD dwCreationFlags,
5370 LPVOID lpEnvironment,
5371 LPCWSTR lpCurrentDirectory,
5372 LPSTARTUPINFOW lpStartupInfo,
5373 LPPROCESS_INFORMATION lpProcessInformation )
5375 FIXME("%p %s %s %p %p %d 0x%08x %p %s %p %p - semi-stub\n", hToken,
5376 debugstr_w(lpApplicationName), debugstr_w(lpCommandLine), lpProcessAttributes,
5377 lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
5378 debugstr_w(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
5380 /* We should create the process with a suspended main thread */
5381 if (!CreateProcessW (lpApplicationName,
5382 lpCommandLine,
5383 lpProcessAttributes,
5384 lpThreadAttributes,
5385 bInheritHandles,
5386 dwCreationFlags, /* CREATE_SUSPENDED */
5387 lpEnvironment,
5388 lpCurrentDirectory,
5389 lpStartupInfo,
5390 lpProcessInformation))
5392 return FALSE;
5395 return TRUE;
5398 /******************************************************************************
5399 * CreateProcessWithLogonW
5401 BOOL WINAPI CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags,
5402 LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment,
5403 LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
5405 FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
5406 debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
5407 debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
5408 lpStartupInfo, lpProcessInformation);
5410 return FALSE;
5413 BOOL WINAPI CreateProcessWithTokenW(HANDLE token, DWORD logon_flags, LPCWSTR application_name, LPWSTR command_line,
5414 DWORD creation_flags, void *environment, LPCWSTR current_directory, STARTUPINFOW *startup_info,
5415 PROCESS_INFORMATION *process_information )
5417 FIXME("%p 0x%08x %s %s 0x%08x %p %s %p %p - semi-stub\n", token,
5418 logon_flags, debugstr_w(application_name), debugstr_w(command_line),
5419 creation_flags, environment, debugstr_w(current_directory),
5420 startup_info, process_information);
5422 /* FIXME: check if handles should be inherited */
5423 return CreateProcessW( application_name, command_line, NULL, NULL, FALSE, creation_flags, environment,
5424 current_directory, startup_info, process_information );
5427 /******************************************************************************
5428 * DuplicateTokenEx [ADVAPI32.@]
5430 BOOL WINAPI DuplicateTokenEx(
5431 HANDLE ExistingTokenHandle, DWORD dwDesiredAccess,
5432 LPSECURITY_ATTRIBUTES lpTokenAttributes,
5433 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
5434 TOKEN_TYPE TokenType,
5435 PHANDLE DuplicateTokenHandle )
5437 OBJECT_ATTRIBUTES ObjectAttributes;
5439 TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
5440 ImpersonationLevel, TokenType, DuplicateTokenHandle);
5442 InitializeObjectAttributes(
5443 &ObjectAttributes,
5444 NULL,
5445 (lpTokenAttributes && lpTokenAttributes->bInheritHandle) ? OBJ_INHERIT : 0,
5446 NULL,
5447 lpTokenAttributes ? lpTokenAttributes->lpSecurityDescriptor : NULL );
5449 return set_ntstatus( NtDuplicateToken( ExistingTokenHandle,
5450 dwDesiredAccess,
5451 &ObjectAttributes,
5452 ImpersonationLevel,
5453 TokenType,
5454 DuplicateTokenHandle ) );
5457 BOOL WINAPI DuplicateToken(
5458 HANDLE ExistingTokenHandle,
5459 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
5460 PHANDLE DuplicateTokenHandle )
5462 return DuplicateTokenEx( ExistingTokenHandle, TOKEN_IMPERSONATE | TOKEN_QUERY,
5463 NULL, ImpersonationLevel, TokenImpersonation,
5464 DuplicateTokenHandle );
5467 /******************************************************************************
5468 * ComputeStringSidSize
5470 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
5472 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
5474 int ctok = 0;
5475 while (*StringSid)
5477 if (*StringSid == '-')
5478 ctok++;
5479 StringSid++;
5482 if (ctok >= 3)
5483 return GetSidLengthRequired(ctok - 2);
5485 else /* String constant format - Only available in winxp and above */
5487 unsigned int i;
5489 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5490 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5491 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
5493 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
5494 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
5496 MAX_SID local;
5497 ADVAPI_GetComputerSid(&local);
5498 return GetSidLengthRequired(*GetSidSubAuthorityCount(&local) + 1);
5503 return GetSidLengthRequired(0);
5506 /******************************************************************************
5507 * ParseStringSidToSid
5509 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
5511 BOOL bret = FALSE;
5512 SID* pisid=pSid;
5514 TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
5515 if (!StringSid)
5517 SetLastError(ERROR_INVALID_PARAMETER);
5518 TRACE("StringSid is NULL, returning FALSE\n");
5519 return FALSE;
5522 while (*StringSid == ' ')
5523 StringSid++;
5525 *cBytes = ComputeStringSidSize(StringSid);
5526 if (!pisid) /* Simply compute the size */
5528 TRACE("only size requested, returning TRUE with %d\n", *cBytes);
5529 return TRUE;
5532 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
5534 DWORD i = 0, identAuth;
5535 DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
5537 StringSid += 2; /* Advance to Revision */
5538 pisid->Revision = atoiW(StringSid);
5540 if (pisid->Revision != SDDL_REVISION)
5542 TRACE("Revision %d is unknown\n", pisid->Revision);
5543 goto lend; /* ERROR_INVALID_SID */
5545 if (csubauth == 0)
5547 TRACE("SubAuthorityCount is 0\n");
5548 goto lend; /* ERROR_INVALID_SID */
5551 pisid->SubAuthorityCount = csubauth;
5553 /* Advance to identifier authority */
5554 while (*StringSid && *StringSid != '-')
5555 StringSid++;
5556 if (*StringSid == '-')
5557 StringSid++;
5559 /* MS' implementation can't handle values greater than 2^32 - 1, so
5560 * we don't either; assume most significant bytes are always 0
5562 pisid->IdentifierAuthority.Value[0] = 0;
5563 pisid->IdentifierAuthority.Value[1] = 0;
5564 identAuth = atoiW(StringSid);
5565 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
5566 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
5567 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
5568 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
5570 /* Advance to first sub authority */
5571 while (*StringSid && *StringSid != '-')
5572 StringSid++;
5573 if (*StringSid == '-')
5574 StringSid++;
5576 while (*StringSid)
5578 pisid->SubAuthority[i++] = atoiW(StringSid);
5580 while (*StringSid && *StringSid != '-')
5581 StringSid++;
5582 if (*StringSid == '-')
5583 StringSid++;
5586 if (i != pisid->SubAuthorityCount)
5587 goto lend; /* ERROR_INVALID_SID */
5589 bret = TRUE;
5591 else /* String constant format - Only available in winxp and above */
5593 unsigned int i;
5594 pisid->Revision = SDDL_REVISION;
5596 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5597 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5599 DWORD j;
5600 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
5601 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
5602 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
5603 pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
5604 bret = TRUE;
5607 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
5608 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
5610 ADVAPI_GetComputerSid(pisid);
5611 pisid->SubAuthority[pisid->SubAuthorityCount] = WellKnownRids[i].Rid;
5612 pisid->SubAuthorityCount++;
5613 bret = TRUE;
5616 if (!bret)
5617 FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
5620 lend:
5621 if (!bret)
5622 SetLastError(ERROR_INVALID_SID);
5624 TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
5625 return bret;
5628 /******************************************************************************
5629 * GetNamedSecurityInfoA [ADVAPI32.@]
5631 DWORD WINAPI GetNamedSecurityInfoA(LPSTR pObjectName,
5632 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5633 PSID* ppsidOwner, PSID* ppsidGroup, PACL* ppDacl, PACL* ppSacl,
5634 PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
5636 LPWSTR wstr;
5637 DWORD r;
5639 TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo,
5640 ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
5642 wstr = SERV_dup(pObjectName);
5643 r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
5644 ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
5646 heap_free( wstr );
5648 return r;
5651 /******************************************************************************
5652 * GetNamedSecurityInfoW [ADVAPI32.@]
5654 DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type,
5655 SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl,
5656 PACL* sacl, PSECURITY_DESCRIPTOR* descriptor )
5658 DWORD access = 0;
5659 HANDLE handle;
5660 DWORD err;
5662 TRACE( "%s %d %d %p %p %p %p %p\n", debugstr_w(name), type, info, owner,
5663 group, dacl, sacl, descriptor );
5665 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
5666 if (!name || !(owner||group||dacl||sacl||descriptor) ) return ERROR_INVALID_PARAMETER;
5668 /* If no descriptor, we have to check that there's a pointer for the requested information */
5669 if( !descriptor && (
5670 ((info & OWNER_SECURITY_INFORMATION) && !owner)
5671 || ((info & GROUP_SECURITY_INFORMATION) && !group)
5672 || ((info & DACL_SECURITY_INFORMATION) && !dacl)
5673 || ((info & SACL_SECURITY_INFORMATION) && !sacl) ))
5674 return ERROR_INVALID_PARAMETER;
5676 if (info & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION))
5677 access |= READ_CONTROL;
5678 if (info & SACL_SECURITY_INFORMATION)
5679 access |= ACCESS_SYSTEM_SECURITY;
5681 switch (type)
5683 case SE_SERVICE:
5684 if (!(err = get_security_service( name, access, &handle )))
5686 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5687 CloseServiceHandle( handle );
5689 break;
5690 case SE_REGISTRY_KEY:
5691 if (!(err = get_security_regkey( name, access, &handle )))
5693 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5694 RegCloseKey( handle );
5696 break;
5697 case SE_FILE_OBJECT:
5698 if (!(err = get_security_file( name, access, &handle )))
5700 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5701 CloseHandle( handle );
5703 break;
5704 default:
5705 FIXME( "Object type %d is not currently supported.\n", type );
5706 if (owner) *owner = NULL;
5707 if (group) *group = NULL;
5708 if (dacl) *dacl = NULL;
5709 if (sacl) *sacl = NULL;
5710 if (descriptor) *descriptor = NULL;
5711 return ERROR_SUCCESS;
5713 return err;
5716 /******************************************************************************
5717 * GetNamedSecurityInfoExW [ADVAPI32.@]
5719 DWORD WINAPI GetNamedSecurityInfoExW( LPCWSTR object, SE_OBJECT_TYPE type,
5720 SECURITY_INFORMATION info, LPCWSTR provider, LPCWSTR property,
5721 PACTRL_ACCESSW* access_list, PACTRL_AUDITW* audit_list, LPWSTR* owner, LPWSTR* group )
5723 FIXME("(%s, %d, %d, %s, %s, %p, %p, %p, %p) stub\n", debugstr_w(object), type, info,
5724 debugstr_w(provider), debugstr_w(property), access_list, audit_list, owner, group);
5725 return ERROR_CALL_NOT_IMPLEMENTED;
5728 /******************************************************************************
5729 * GetNamedSecurityInfoExA [ADVAPI32.@]
5731 DWORD WINAPI GetNamedSecurityInfoExA( LPCSTR object, SE_OBJECT_TYPE type,
5732 SECURITY_INFORMATION info, LPCSTR provider, LPCSTR property,
5733 PACTRL_ACCESSA* access_list, PACTRL_AUDITA* audit_list, LPSTR* owner, LPSTR* group )
5735 FIXME("(%s, %d, %d, %s, %s, %p, %p, %p, %p) stub\n", debugstr_a(object), type, info,
5736 debugstr_a(provider), debugstr_a(property), access_list, audit_list, owner, group);
5737 return ERROR_CALL_NOT_IMPLEMENTED;
5740 /******************************************************************************
5741 * DecryptFileW [ADVAPI32.@]
5743 BOOL WINAPI DecryptFileW(LPCWSTR lpFileName, DWORD dwReserved)
5745 FIXME("(%s, %08x): stub\n", debugstr_w(lpFileName), dwReserved);
5746 return TRUE;
5749 /******************************************************************************
5750 * DecryptFileA [ADVAPI32.@]
5752 BOOL WINAPI DecryptFileA(LPCSTR lpFileName, DWORD dwReserved)
5754 FIXME("(%s, %08x): stub\n", debugstr_a(lpFileName), dwReserved);
5755 return TRUE;
5758 /******************************************************************************
5759 * EncryptFileW [ADVAPI32.@]
5761 BOOL WINAPI EncryptFileW(LPCWSTR lpFileName)
5763 FIXME("(%s): stub\n", debugstr_w(lpFileName));
5764 return TRUE;
5767 /******************************************************************************
5768 * EncryptFileA [ADVAPI32.@]
5770 BOOL WINAPI EncryptFileA(LPCSTR lpFileName)
5772 FIXME("(%s): stub\n", debugstr_a(lpFileName));
5773 return TRUE;
5776 /******************************************************************************
5777 * FileEncryptionStatusW [ADVAPI32.@]
5779 BOOL WINAPI FileEncryptionStatusW(LPCWSTR lpFileName, LPDWORD lpStatus)
5781 FIXME("(%s %p): stub\n", debugstr_w(lpFileName), lpStatus);
5782 if (!lpStatus)
5783 return FALSE;
5784 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5785 return TRUE;
5788 /******************************************************************************
5789 * FileEncryptionStatusA [ADVAPI32.@]
5791 BOOL WINAPI FileEncryptionStatusA(LPCSTR lpFileName, LPDWORD lpStatus)
5793 FIXME("(%s %p): stub\n", debugstr_a(lpFileName), lpStatus);
5794 if (!lpStatus)
5795 return FALSE;
5796 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5797 return TRUE;
5800 /******************************************************************************
5801 * SetSecurityInfo [ADVAPI32.@]
5803 DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType,
5804 SECURITY_INFORMATION SecurityInfo, PSID psidOwner,
5805 PSID psidGroup, PACL pDacl, PACL pSacl)
5807 SECURITY_DESCRIPTOR sd;
5808 PACL dacl = pDacl;
5809 NTSTATUS status;
5811 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
5812 return ERROR_INVALID_SECURITY_DESCR;
5814 if (SecurityInfo & OWNER_SECURITY_INFORMATION)
5815 SetSecurityDescriptorOwner(&sd, psidOwner, FALSE);
5816 if (SecurityInfo & GROUP_SECURITY_INFORMATION)
5817 SetSecurityDescriptorGroup(&sd, psidGroup, FALSE);
5818 if (SecurityInfo & DACL_SECURITY_INFORMATION)
5820 if (ObjectType == SE_FILE_OBJECT && pDacl)
5822 SECURITY_DESCRIPTOR_CONTROL control;
5823 PSECURITY_DESCRIPTOR psd;
5824 OBJECT_NAME_INFORMATION *name_info;
5825 DWORD size, rev;
5827 status = NtQuerySecurityObject(handle, SecurityInfo, NULL, 0, &size);
5828 if (status != STATUS_BUFFER_TOO_SMALL)
5829 return RtlNtStatusToDosError(status);
5831 psd = heap_alloc(size);
5832 if (!psd)
5833 return ERROR_NOT_ENOUGH_MEMORY;
5835 status = NtQuerySecurityObject(handle, SecurityInfo, psd, size, &size);
5836 if (status)
5838 heap_free(psd);
5839 return RtlNtStatusToDosError(status);
5842 status = RtlGetControlSecurityDescriptor(psd, &control, &rev);
5843 heap_free(psd);
5844 if (status)
5845 return RtlNtStatusToDosError(status);
5846 /* TODO: copy some control flags to new sd */
5848 /* inherit parent directory DACL */
5849 if (!(control & SE_DACL_PROTECTED))
5851 status = NtQueryObject(handle, ObjectNameInformation, NULL, 0, &size);
5852 if (status != STATUS_INFO_LENGTH_MISMATCH)
5853 return RtlNtStatusToDosError(status);
5855 name_info = heap_alloc(size);
5856 if (!name_info)
5857 return ERROR_NOT_ENOUGH_MEMORY;
5859 status = NtQueryObject(handle, ObjectNameInformation, name_info, size, NULL);
5860 if (status)
5862 heap_free(name_info);
5863 return RtlNtStatusToDosError(status);
5866 for (name_info->Name.Length-=2; name_info->Name.Length>0; name_info->Name.Length-=2)
5867 if (name_info->Name.Buffer[name_info->Name.Length/2-1]=='\\' ||
5868 name_info->Name.Buffer[name_info->Name.Length/2-1]=='/')
5869 break;
5870 if (name_info->Name.Length)
5872 OBJECT_ATTRIBUTES attr;
5873 IO_STATUS_BLOCK io;
5874 HANDLE parent;
5875 PSECURITY_DESCRIPTOR parent_sd;
5876 ACL *parent_dacl;
5877 DWORD err = ERROR_ACCESS_DENIED;
5879 name_info->Name.Buffer[name_info->Name.Length/2] = 0;
5881 attr.Length = sizeof(attr);
5882 attr.RootDirectory = 0;
5883 attr.Attributes = 0;
5884 attr.ObjectName = &name_info->Name;
5885 attr.SecurityDescriptor = NULL;
5886 status = NtOpenFile(&parent, READ_CONTROL, &attr, &io,
5887 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5888 FILE_OPEN_FOR_BACKUP_INTENT);
5889 heap_free(name_info);
5890 if (!status)
5892 err = GetSecurityInfo(parent, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
5893 NULL, NULL, &parent_dacl, NULL, &parent_sd);
5894 CloseHandle(parent);
5897 if (!err)
5899 int i;
5901 dacl = heap_alloc_zero(pDacl->AclSize+parent_dacl->AclSize);
5902 if (!dacl)
5904 LocalFree(parent_sd);
5905 return ERROR_NOT_ENOUGH_MEMORY;
5907 memcpy(dacl, pDacl, pDacl->AclSize);
5908 dacl->AclSize = pDacl->AclSize+parent_dacl->AclSize;
5910 for (i=0; i<parent_dacl->AceCount; i++)
5912 ACE_HEADER *ace;
5914 if (!GetAce(parent_dacl, i, (void*)&ace))
5915 continue;
5916 if (!(ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)))
5917 continue;
5918 if ((ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)) !=
5919 (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE))
5921 FIXME("unsupported flags: %x\n", ace->AceFlags);
5922 continue;
5925 if (ace->AceFlags & NO_PROPAGATE_INHERIT_ACE)
5926 ace->AceFlags &= ~(OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE|NO_PROPAGATE_INHERIT_ACE);
5927 ace->AceFlags &= ~INHERIT_ONLY_ACE;
5928 ace->AceFlags |= INHERITED_ACE;
5930 if(!AddAce(dacl, ACL_REVISION, MAXDWORD, ace, ace->AceSize))
5931 WARN("error adding inherited ACE\n");
5933 LocalFree(parent_sd);
5936 else
5937 heap_free(name_info);
5941 SetSecurityDescriptorDacl(&sd, TRUE, dacl, FALSE);
5943 if (SecurityInfo & SACL_SECURITY_INFORMATION)
5944 SetSecurityDescriptorSacl(&sd, TRUE, pSacl, FALSE);
5946 switch (ObjectType)
5948 case SE_SERVICE:
5949 FIXME("stub: Service objects are not supported at this time.\n");
5950 status = STATUS_SUCCESS; /* Implement SetServiceObjectSecurity */
5951 break;
5952 default:
5953 status = NtSetSecurityObject(handle, SecurityInfo, &sd);
5954 break;
5956 if (dacl != pDacl)
5957 heap_free(dacl);
5958 return RtlNtStatusToDosError(status);
5961 /******************************************************************************
5962 * SaferCreateLevel [ADVAPI32.@]
5964 BOOL WINAPI SaferCreateLevel(DWORD ScopeId, DWORD LevelId, DWORD OpenFlags,
5965 SAFER_LEVEL_HANDLE* LevelHandle, LPVOID lpReserved)
5967 FIXME("(%u, %x, %u, %p, %p) stub\n", ScopeId, LevelId, OpenFlags, LevelHandle, lpReserved);
5969 *LevelHandle = (SAFER_LEVEL_HANDLE)0xdeadbeef;
5970 return TRUE;
5973 /******************************************************************************
5974 * SaferComputeTokenFromLevel [ADVAPI32.@]
5976 BOOL WINAPI SaferComputeTokenFromLevel(SAFER_LEVEL_HANDLE handle, HANDLE token, PHANDLE access_token,
5977 DWORD flags, LPVOID reserved)
5979 FIXME("(%p, %p, %p, %x, %p) stub\n", handle, token, access_token, flags, reserved);
5981 *access_token = (HANDLE)0xdeadbeef;
5982 return TRUE;
5985 /******************************************************************************
5986 * SaferCloseLevel [ADVAPI32.@]
5988 BOOL WINAPI SaferCloseLevel(SAFER_LEVEL_HANDLE handle)
5990 FIXME("(%p) stub\n", handle);
5991 return TRUE;
5994 DWORD WINAPI TreeResetNamedSecurityInfoW( LPWSTR pObjectName,
5995 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5996 PSID pOwner, PSID pGroup, PACL pDacl, PACL pSacl,
5997 BOOL KeepExplicit, FN_PROGRESS fnProgress,
5998 PROG_INVOKE_SETTING ProgressInvokeSetting, PVOID Args)
6000 FIXME("(%s, %i, %i, %p, %p, %p, %p, %i, %p, %i, %p) stub\n",
6001 debugstr_w(pObjectName), ObjectType, SecurityInfo, pOwner, pGroup,
6002 pDacl, pSacl, KeepExplicit, fnProgress, ProgressInvokeSetting, Args);
6004 return ERROR_SUCCESS;
6007 /******************************************************************************
6008 * SaferGetPolicyInformation [ADVAPI32.@]
6010 BOOL WINAPI SaferGetPolicyInformation(DWORD scope, SAFER_POLICY_INFO_CLASS class, DWORD size,
6011 PVOID buffer, PDWORD required, LPVOID lpReserved)
6013 FIXME("(%u %u %u %p %p %p) stub\n", scope, class, size, buffer, required, lpReserved);
6014 return FALSE;
6017 /******************************************************************************
6018 * SaferSetLevelInformation [ADVAPI32.@]
6020 BOOL WINAPI SaferSetLevelInformation(SAFER_LEVEL_HANDLE handle, SAFER_OBJECT_INFO_CLASS infotype,
6021 LPVOID buffer, DWORD size)
6023 FIXME("(%p %u %p %u) stub\n", handle, infotype, buffer, size);
6024 return FALSE;