2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: subsys/csrss/win32csr/file.c
5 * PURPOSE: File handling
6 * PROGRAMMERS: Pierre Schweitzer (pierre.schweitzer@reactos.org)
7 * NOTE: Belongs to basesrv.dll
10 /* INCLUDES ******************************************************************/
17 /* GLOBALS *******************************************************************/
19 UINT CsrGetTempFileUnique
;
20 LIST_ENTRY DosDeviceHistory
;
21 RTL_CRITICAL_SECTION Win32CsrDefineDosDeviceCritSec
;
23 /* FUNCTIONS *****************************************************************/
25 CSR_API(CsrGetTempFile
)
27 DPRINT("CsrGetTempFile entered\n");
29 /* Return 16-bits ID */
30 Request
->Data
.GetTempFile
.UniqueID
= (++CsrGetTempFileUnique
& 0xFFFF);
32 DPRINT("Returning: %u\n", Request
->Data
.GetTempFile
.UniqueID
);
34 return STATUS_SUCCESS
;
37 CSR_API(CsrDefineDosDevice
)
39 OBJECT_ATTRIBUTES ObjectAttributes
;
40 HANDLE LinkHandle
= NULL
;
42 UNICODE_STRING DeviceName
= {0};
43 UNICODE_STRING RequestDeviceName
= {0};
44 UNICODE_STRING LinkTarget
= {0};
45 PUNICODE_STRING RequestLinkTarget
;
47 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
48 SID_IDENTIFIER_AUTHORITY SystemAuthority
= {SECURITY_NT_AUTHORITY
};
49 PSECURITY_DESCRIPTOR SecurityDescriptor
;
55 PCSRSS_DOS_DEVICE_HISTORY_ENTRY HistoryEntry
;
58 BOOLEAN Matched
, AddHistory
;
62 DPRINT("CsrDefineDosDevice entered, Flags:%d, DeviceName:%wZ, TargetName:%wZ\n",
63 Request
->Data
.DefineDosDeviceRequest
.dwFlags
,
64 &Request
->Data
.DefineDosDeviceRequest
.DeviceName
,
65 &Request
->Data
.DefineDosDeviceRequest
.TargetName
);
67 Matched
= AddHistory
= FALSE
;
69 AdminSid
= SystemSid
= WorldSid
= NULL
;
70 SecurityDescriptor
= NULL
;
71 ListHead
= &DosDeviceHistory
;
72 dwFlags
= Request
->Data
.DefineDosDeviceRequest
.dwFlags
;
74 /* Validate the flags */
75 if ( (dwFlags
& 0xFFFFFFF0) ||
76 ((dwFlags
& DDD_EXACT_MATCH_ON_REMOVE
) &&
77 ! (dwFlags
& DDD_REMOVE_DEFINITION
)) )
79 return STATUS_INVALID_PARAMETER
;
82 Status
= RtlEnterCriticalSection(&Win32CsrDefineDosDeviceCritSec
);
83 if (! NT_SUCCESS(Status
))
85 DPRINT1("RtlEnterCriticalSection() failed (Status %lx)\n",
93 RtlUpcaseUnicodeString(&RequestDeviceName
,
94 &Request
->Data
.DefineDosDeviceRequest
.DeviceName
,
96 if (! NT_SUCCESS(Status
))
100 &Request
->Data
.DefineDosDeviceRequest
.TargetName
;
102 * Strip off any trailing '\', if we leave a trailing slash the drive remains non-accessible.
103 * So working around it for now.
104 * FIXME: Need to fix this in the object manager ObpLookupObjectName()??, and remove this when the its fixed.
106 while (RequestLinkTarget
->Length
>= sizeof(WCHAR
) &&
107 RequestLinkTarget
->Buffer
[(RequestLinkTarget
->Length
/sizeof(WCHAR
)) - 1] == L
'\\')
109 RequestLinkTarget
->Length
-= sizeof(WCHAR
);
112 lpBuffer
= (PWSTR
) RtlAllocateHeap(Win32CsrApiHeap
,
114 RequestDeviceName
.MaximumLength
+ 5 * sizeof(WCHAR
));
117 DPRINT1("Failed to allocate memory\n");
118 Status
= STATUS_NO_MEMORY
;
125 RtlInitUnicodeString(&DeviceName
,
127 InitializeObjectAttributes(&ObjectAttributes
,
129 OBJ_CASE_INSENSITIVE
,
132 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
135 if (NT_SUCCESS(Status
))
137 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
140 if (! NT_SUCCESS(Status
) &&
141 Status
== STATUS_BUFFER_TOO_SMALL
)
143 LinkTarget
.Length
= 0;
144 LinkTarget
.MaximumLength
= Length
;
145 LinkTarget
.Buffer
= (PWSTR
)
146 RtlAllocateHeap(Win32CsrApiHeap
,
149 if (! LinkTarget
.Buffer
)
151 DPRINT1("Failed to allocate memory\n");
152 Status
= STATUS_NO_MEMORY
;
156 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
161 if (! NT_SUCCESS(Status
))
163 DPRINT1("NtQuerySymbolicLinkObject(%wZ) failed (Status %lx)\n",
164 &DeviceName
, Status
);
168 if ((dwFlags
& DDD_REMOVE_DEFINITION
))
170 /* If no target name specified we remove the current symlink target */
171 if (RequestLinkTarget
->Length
== 0)
175 if (dwFlags
& DDD_EXACT_MATCH_ON_REMOVE
)
176 Matched
= ! RtlCompareUnicodeString(RequestLinkTarget
,
180 Matched
= RtlPrefixUnicodeString(RequestLinkTarget
,
185 if (Matched
&& IsListEmpty(ListHead
))
187 /* Current symlink target macthed and there is nothing to revert to */
188 RequestLinkTarget
= NULL
;
190 else if (Matched
&& ! IsListEmpty(ListHead
))
192 /* Fetch the first history entry we come across for the device name */
193 /* This will become the current symlink target for the device name */
195 Entry
= ListHead
->Flink
;
196 while (Entry
!= ListHead
)
198 HistoryEntry
= (PCSRSS_DOS_DEVICE_HISTORY_ENTRY
)
199 CONTAINING_RECORD(Entry
,
200 CSRSS_DOS_DEVICE_HISTORY_ENTRY
,
203 ! RtlCompareUnicodeString(&RequestDeviceName
,
204 &HistoryEntry
->Device
,
208 RemoveEntryList(&HistoryEntry
->Entry
);
209 RequestLinkTarget
= &HistoryEntry
->Target
;
212 Entry
= Entry
->Flink
;
216 /* Nothing to revert to so delete the symlink */
218 RequestLinkTarget
= NULL
;
222 /* Locate a previous symlink target as we did not get a hit earlier */
223 /* If we find one we need to remove it */
224 Entry
= ListHead
->Flink
;
225 while (Entry
!= ListHead
)
227 HistoryEntry
= (PCSRSS_DOS_DEVICE_HISTORY_ENTRY
)
228 CONTAINING_RECORD(Entry
,
229 CSRSS_DOS_DEVICE_HISTORY_ENTRY
,
232 ! RtlCompareUnicodeString(&RequestDeviceName
,
233 &HistoryEntry
->Device
,
238 Entry
= Entry
->Flink
;
243 if (dwFlags
& DDD_EXACT_MATCH_ON_REMOVE
)
245 if (! RtlCompareUnicodeString(RequestLinkTarget
,
246 &HistoryEntry
->Target
,
252 else if (RtlPrefixUnicodeString(RequestLinkTarget
,
253 &HistoryEntry
->Target
,
261 RemoveEntryList(&HistoryEntry
->Entry
);
264 Entry
= Entry
->Flink
;
268 /* Leave existing symlink as is */
270 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
272 Status
= STATUS_SUCCESS
;
281 Status
= NtMakeTemporaryObject(LinkHandle
);
282 if (! NT_SUCCESS(Status
))
284 DPRINT1("NtMakeTemporaryObject(%wZ) failed (Status %lx)\n",
285 &DeviceName
, Status
);
289 Status
= NtClose(LinkHandle
);
291 if (! NT_SUCCESS(Status
))
293 DPRINT1("NtClose(%wZ) failed (Status %lx)\n",
294 &DeviceName
, Status
);
299 /* Don't create symlink if we don't have a target */
300 if (! RequestLinkTarget
|| RequestLinkTarget
->Length
== 0)
305 HistoryEntry
= (PCSRSS_DOS_DEVICE_HISTORY_ENTRY
)
306 RtlAllocateHeap(Win32CsrApiHeap
,
308 sizeof(CSRSS_DOS_DEVICE_HISTORY_ENTRY
));
311 DPRINT1("Failed to allocate memory\n");
312 Status
= STATUS_NO_MEMORY
;
316 HistoryEntry
->Target
.Buffer
=
317 RtlAllocateHeap(Win32CsrApiHeap
,
320 if (! HistoryEntry
->Target
.Buffer
)
322 DPRINT1("Failed to allocate memory\n");
323 Status
= STATUS_NO_MEMORY
;
326 HistoryEntry
->Target
.Length
=
327 HistoryEntry
->Target
.MaximumLength
=
329 RtlCopyUnicodeString(&HistoryEntry
->Target
,
332 HistoryEntry
->Device
.Buffer
=
333 RtlAllocateHeap(Win32CsrApiHeap
,
335 RequestDeviceName
.Length
);
336 if (! HistoryEntry
->Device
.Buffer
)
338 DPRINT1("Failed to allocate memory\n");
339 Status
= STATUS_NO_MEMORY
;
342 HistoryEntry
->Device
.Length
=
343 HistoryEntry
->Device
.MaximumLength
=
344 RequestDeviceName
.Length
;
345 RtlCopyUnicodeString(&HistoryEntry
->Device
,
348 /* Remember previous symlink target for this device */
349 InsertHeadList(ListHead
,
350 &HistoryEntry
->Entry
);
354 RtlAllocateAndInitializeSid(&WorldAuthority
,
366 RtlAllocateAndInitializeSid(&SystemAuthority
,
368 SECURITY_LOCAL_SYSTEM_RID
,
378 RtlAllocateAndInitializeSid(&SystemAuthority
,
380 SECURITY_BUILTIN_DOMAIN_RID
,
381 DOMAIN_ALIAS_RID_ADMINS
,
390 SidLength
= RtlLengthSid(SystemSid
) +
391 RtlLengthSid(AdminSid
) +
392 RtlLengthSid(WorldSid
);
393 Length
= sizeof(ACL
) + SidLength
+ 3 * sizeof(ACCESS_ALLOWED_ACE
);
395 SecurityDescriptor
= RtlAllocateHeap(Win32CsrApiHeap
,
397 SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
398 if (! SecurityDescriptor
)
400 DPRINT1("Failed to allocate memory\n");
401 Status
= STATUS_NO_MEMORY
;
405 Dacl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
406 Status
= RtlCreateSecurityDescriptor(SecurityDescriptor
,
407 SECURITY_DESCRIPTOR_REVISION
);
408 if (! NT_SUCCESS(Status
))
410 DPRINT1("RtlCreateSecurityDescriptor() failed (Status %lx)\n",
415 Status
= RtlCreateAcl(Dacl
,
418 if (! NT_SUCCESS(Status
))
420 DPRINT1("RtlCreateAcl() failed (Status %lx)\n",
425 (void) RtlAddAccessAllowedAce(Dacl
,
429 (void) RtlAddAccessAllowedAce(Dacl
,
433 (void) RtlAddAccessAllowedAce(Dacl
,
435 STANDARD_RIGHTS_READ
,
438 Status
= RtlSetDaclSecurityDescriptor(SecurityDescriptor
,
442 if (! NT_SUCCESS(Status
))
444 DPRINT1("RtlSetDaclSecurityDescriptor() failed (Status %lx)\n",
449 InitializeObjectAttributes(&ObjectAttributes
,
451 OBJ_CASE_INSENSITIVE
,
454 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
455 SYMBOLIC_LINK_ALL_ACCESS
,
458 if (NT_SUCCESS(Status
))
460 Status
= NtMakePermanentObject(LinkHandle
);
461 if (! NT_SUCCESS(Status
))
463 DPRINT1("NtMakePermanentObject(%wZ) failed (Status %lx)\n",
464 &DeviceName
, Status
);
469 DPRINT1("NtCreateSymbolicLinkObject(%wZ) failed (Status %lx)\n",
470 &DeviceName
, Status
);
475 (void) RtlLeaveCriticalSection(&Win32CsrDefineDosDeviceCritSec
);
476 if (DeviceName
.Buffer
)
477 (void) RtlFreeHeap(Win32CsrApiHeap
,
480 if (LinkTarget
.Buffer
)
481 (void) RtlFreeHeap(Win32CsrApiHeap
,
484 if (SecurityDescriptor
)
485 (void) RtlFreeHeap(Win32CsrApiHeap
,
489 (void) NtClose(LinkHandle
);
491 (void) RtlFreeSid(SystemSid
);
493 (void) RtlFreeSid(AdminSid
);
495 (void) RtlFreeSid(WorldSid
);
496 RtlFreeUnicodeString(&RequestDeviceName
);
499 if (HistoryEntry
->Target
.Buffer
)
500 (void) RtlFreeHeap(Win32CsrApiHeap
,
502 HistoryEntry
->Target
.Buffer
);
503 if (HistoryEntry
->Device
.Buffer
)
504 (void) RtlFreeHeap(Win32CsrApiHeap
,
506 HistoryEntry
->Device
.Buffer
);
507 (void) RtlFreeHeap(Win32CsrApiHeap
,
514 DPRINT("CsrDefineDosDevice Exit, Statux: 0x%x\n", Status
);
518 void CsrCleanupDefineDosDevice(void)
520 PLIST_ENTRY Entry
, ListHead
;
521 PCSRSS_DOS_DEVICE_HISTORY_ENTRY HistoryEntry
;
523 (void) RtlDeleteCriticalSection(&Win32CsrDefineDosDeviceCritSec
);
525 ListHead
= &DosDeviceHistory
;
526 Entry
= ListHead
->Flink
;
527 while (Entry
!= ListHead
)
529 HistoryEntry
= (PCSRSS_DOS_DEVICE_HISTORY_ENTRY
)
530 CONTAINING_RECORD(Entry
,
531 CSRSS_DOS_DEVICE_HISTORY_ENTRY
,
533 Entry
= Entry
->Flink
;
537 if (HistoryEntry
->Target
.Buffer
)
538 (void) RtlFreeHeap(Win32CsrApiHeap
,
540 HistoryEntry
->Target
.Buffer
);
541 if (HistoryEntry
->Device
.Buffer
)
542 (void) RtlFreeHeap(Win32CsrApiHeap
,
544 HistoryEntry
->Device
.Buffer
);
545 (void) RtlFreeHeap(Win32CsrApiHeap
,