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 typedef BOOL (WINAPI
*PUSER_SOUND_SENTRY
)(VOID
);
22 FirstSoundSentry(VOID
);
24 UINT CsrGetTempFileUnique
;
25 LIST_ENTRY DosDeviceHistory
;
26 RTL_CRITICAL_SECTION Win32CsrDefineDosDeviceCritSec
;
27 PUSER_SOUND_SENTRY _UserSoundSentry
= FirstSoundSentry
;
29 /* FUNCTIONS *****************************************************************/
35 /* In case the function can't be found/is unimplemented */
41 FirstSoundSentry(VOID
)
43 UNICODE_STRING DllString
= RTL_CONSTANT_STRING(L
"winsrv");
44 STRING FuncString
= RTL_CONSTANT_STRING("_UserSoundSentry");
47 PUSER_SOUND_SENTRY NewSoundSentry
= FailSoundSentry
;
49 /* Load winsrv manually */
50 Status
= LdrGetDllHandle(NULL
, NULL
, &DllString
, &DllHandle
);
51 if (NT_SUCCESS(Status
))
53 /* If it was found, get SoundSentry export */
54 Status
= LdrGetProcedureAddress(DllHandle
,
57 (PVOID
*)&NewSoundSentry
);
60 /* Set it as the callback for the future, and call it */
61 _UserSoundSentry
= NewSoundSentry
;
62 return _UserSoundSentry();
65 CSR_API(CsrSoundSentry
)
67 /* Call the API and see if it suceeds */
68 return _UserSoundSentry() ? STATUS_SUCCESS
: STATUS_ACCESS_DENIED
;
71 CSR_API(CsrGetTempFile
)
73 DPRINT("CsrGetTempFile entered\n");
75 /* Return 16-bits ID */
76 Request
->Data
.GetTempFile
.UniqueID
= (++CsrGetTempFileUnique
& 0xFFFF);
78 DPRINT("Returning: %u\n", Request
->Data
.GetTempFile
.UniqueID
);
80 return STATUS_SUCCESS
;
83 CSR_API(CsrDefineDosDevice
)
85 OBJECT_ATTRIBUTES ObjectAttributes
;
86 HANDLE LinkHandle
= NULL
;
88 UNICODE_STRING DeviceName
= {0};
89 UNICODE_STRING RequestDeviceName
= {0};
90 UNICODE_STRING LinkTarget
= {0};
91 PUNICODE_STRING RequestLinkTarget
;
93 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
94 SID_IDENTIFIER_AUTHORITY SystemAuthority
= {SECURITY_NT_AUTHORITY
};
95 PSECURITY_DESCRIPTOR SecurityDescriptor
;
101 PCSRSS_DOS_DEVICE_HISTORY_ENTRY HistoryEntry
;
103 PLIST_ENTRY ListHead
;
104 BOOLEAN Matched
, AddHistory
;
108 DPRINT("CsrDefineDosDevice entered, Flags:%d, DeviceName:%wZ, TargetName:%wZ\n",
109 Request
->Data
.DefineDosDeviceRequest
.dwFlags
,
110 &Request
->Data
.DefineDosDeviceRequest
.DeviceName
,
111 &Request
->Data
.DefineDosDeviceRequest
.TargetName
);
113 Matched
= AddHistory
= FALSE
;
115 AdminSid
= SystemSid
= WorldSid
= NULL
;
116 SecurityDescriptor
= NULL
;
117 ListHead
= &DosDeviceHistory
;
118 dwFlags
= Request
->Data
.DefineDosDeviceRequest
.dwFlags
;
120 /* Validate the flags */
121 if ( (dwFlags
& 0xFFFFFFF0) ||
122 ((dwFlags
& DDD_EXACT_MATCH_ON_REMOVE
) &&
123 ! (dwFlags
& DDD_REMOVE_DEFINITION
)) )
125 return STATUS_INVALID_PARAMETER
;
128 Status
= RtlEnterCriticalSection(&Win32CsrDefineDosDeviceCritSec
);
129 if (! NT_SUCCESS(Status
))
131 DPRINT1("RtlEnterCriticalSection() failed (Status %lx)\n",
139 RtlUpcaseUnicodeString(&RequestDeviceName
,
140 &Request
->Data
.DefineDosDeviceRequest
.DeviceName
,
142 if (! NT_SUCCESS(Status
))
146 &Request
->Data
.DefineDosDeviceRequest
.TargetName
;
147 lpBuffer
= (PWSTR
) RtlAllocateHeap(Win32CsrApiHeap
,
149 RequestDeviceName
.MaximumLength
+ 5 * sizeof(WCHAR
));
152 DPRINT1("Failed to allocate memory\n");
153 Status
= STATUS_NO_MEMORY
;
160 RtlInitUnicodeString(&DeviceName
,
162 InitializeObjectAttributes(&ObjectAttributes
,
164 OBJ_CASE_INSENSITIVE
,
167 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
170 if (NT_SUCCESS(Status
))
172 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
175 if (! NT_SUCCESS(Status
) &&
176 Status
== STATUS_BUFFER_TOO_SMALL
)
178 LinkTarget
.Length
= 0;
179 LinkTarget
.MaximumLength
= Length
;
180 LinkTarget
.Buffer
= (PWSTR
)
181 RtlAllocateHeap(Win32CsrApiHeap
,
184 if (! LinkTarget
.Buffer
)
186 DPRINT1("Failed to allocate memory\n");
187 Status
= STATUS_NO_MEMORY
;
191 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
196 if (! NT_SUCCESS(Status
))
198 DPRINT1("NtQuerySymbolicLinkObject(%wZ) failed (Status %lx)\n",
199 &DeviceName
, Status
);
203 if ((dwFlags
& DDD_REMOVE_DEFINITION
))
205 /* If no target name specified we remove the current symlink target */
206 if (RequestLinkTarget
->Length
== 0)
210 if (dwFlags
& DDD_EXACT_MATCH_ON_REMOVE
)
211 Matched
= ! RtlCompareUnicodeString(RequestLinkTarget
,
215 Matched
= RtlPrefixUnicodeString(RequestLinkTarget
,
220 if (Matched
&& IsListEmpty(ListHead
))
222 /* Current symlink target macthed and there is nothing to revert to */
223 RequestLinkTarget
= NULL
;
225 else if (Matched
&& ! IsListEmpty(ListHead
))
227 /* Fetch the first history entry we come across for the device name */
228 /* This will become the current symlink target for the device name */
230 Entry
= ListHead
->Flink
;
231 while (Entry
!= ListHead
)
233 HistoryEntry
= (PCSRSS_DOS_DEVICE_HISTORY_ENTRY
)
234 CONTAINING_RECORD(Entry
,
235 CSRSS_DOS_DEVICE_HISTORY_ENTRY
,
238 ! RtlCompareUnicodeString(&RequestDeviceName
,
239 &HistoryEntry
->Device
,
243 RemoveEntryList(&HistoryEntry
->Entry
);
244 RequestLinkTarget
= &HistoryEntry
->Target
;
247 Entry
= Entry
->Flink
;
251 /* Nothing to revert to so delete the symlink */
253 RequestLinkTarget
= NULL
;
257 /* Locate a previous symlink target as we did not get a hit earlier */
258 /* If we find one we need to remove it */
259 Entry
= ListHead
->Flink
;
260 while (Entry
!= ListHead
)
262 HistoryEntry
= (PCSRSS_DOS_DEVICE_HISTORY_ENTRY
)
263 CONTAINING_RECORD(Entry
,
264 CSRSS_DOS_DEVICE_HISTORY_ENTRY
,
267 ! RtlCompareUnicodeString(&RequestDeviceName
,
268 &HistoryEntry
->Device
,
273 Entry
= Entry
->Flink
;
278 if (dwFlags
& DDD_EXACT_MATCH_ON_REMOVE
)
280 if (! RtlCompareUnicodeString(RequestLinkTarget
,
281 &HistoryEntry
->Target
,
287 else if (RtlPrefixUnicodeString(RequestLinkTarget
,
288 &HistoryEntry
->Target
,
296 RemoveEntryList(&HistoryEntry
->Entry
);
299 Entry
= Entry
->Flink
;
303 /* Leave existing symlink as is */
305 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
307 Status
= STATUS_SUCCESS
;
316 Status
= NtMakeTemporaryObject(LinkHandle
);
317 if (! NT_SUCCESS(Status
))
319 DPRINT1("NtMakeTemporaryObject(%wZ) failed (Status %lx)\n",
320 &DeviceName
, Status
);
324 Status
= NtClose(LinkHandle
);
326 if (! NT_SUCCESS(Status
))
328 DPRINT1("NtClose(%wZ) failed (Status %lx)\n",
329 &DeviceName
, Status
);
334 /* Don't create symlink if we don't have a target */
335 if (! RequestLinkTarget
|| RequestLinkTarget
->Length
== 0)
340 HistoryEntry
= (PCSRSS_DOS_DEVICE_HISTORY_ENTRY
)
341 RtlAllocateHeap(Win32CsrApiHeap
,
343 sizeof(CSRSS_DOS_DEVICE_HISTORY_ENTRY
));
346 DPRINT1("Failed to allocate memory\n");
347 Status
= STATUS_NO_MEMORY
;
351 HistoryEntry
->Target
.Buffer
=
352 RtlAllocateHeap(Win32CsrApiHeap
,
355 if (! HistoryEntry
->Target
.Buffer
)
357 DPRINT1("Failed to allocate memory\n");
358 Status
= STATUS_NO_MEMORY
;
361 HistoryEntry
->Target
.Length
=
362 HistoryEntry
->Target
.MaximumLength
=
364 RtlCopyUnicodeString(&HistoryEntry
->Target
,
367 HistoryEntry
->Device
.Buffer
=
368 RtlAllocateHeap(Win32CsrApiHeap
,
370 RequestDeviceName
.Length
);
371 if (! HistoryEntry
->Device
.Buffer
)
373 DPRINT1("Failed to allocate memory\n");
374 Status
= STATUS_NO_MEMORY
;
377 HistoryEntry
->Device
.Length
=
378 HistoryEntry
->Device
.MaximumLength
=
379 RequestDeviceName
.Length
;
380 RtlCopyUnicodeString(&HistoryEntry
->Device
,
383 /* Remember previous symlink target for this device */
384 InsertHeadList(ListHead
,
385 &HistoryEntry
->Entry
);
389 RtlAllocateAndInitializeSid(&WorldAuthority
,
401 RtlAllocateAndInitializeSid(&SystemAuthority
,
403 SECURITY_LOCAL_SYSTEM_RID
,
413 RtlAllocateAndInitializeSid(&SystemAuthority
,
415 SECURITY_BUILTIN_DOMAIN_RID
,
416 DOMAIN_ALIAS_RID_ADMINS
,
425 SidLength
= RtlLengthSid(SystemSid
) +
426 RtlLengthSid(AdminSid
) +
427 RtlLengthSid(WorldSid
);
428 Length
= sizeof(ACL
) + SidLength
+ 3 * sizeof(ACCESS_ALLOWED_ACE
);
430 SecurityDescriptor
= RtlAllocateHeap(Win32CsrApiHeap
,
432 SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
433 if (! SecurityDescriptor
)
435 DPRINT1("Failed to allocate memory\n");
436 Status
= STATUS_NO_MEMORY
;
440 Dacl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
441 Status
= RtlCreateSecurityDescriptor(SecurityDescriptor
,
442 SECURITY_DESCRIPTOR_REVISION
);
443 if (! NT_SUCCESS(Status
))
445 DPRINT1("RtlCreateSecurityDescriptor() failed (Status %lx)\n",
450 Status
= RtlCreateAcl(Dacl
,
453 if (! NT_SUCCESS(Status
))
455 DPRINT1("RtlCreateAcl() failed (Status %lx)\n",
460 (void) RtlAddAccessAllowedAce(Dacl
,
464 (void) RtlAddAccessAllowedAce(Dacl
,
468 (void) RtlAddAccessAllowedAce(Dacl
,
470 STANDARD_RIGHTS_READ
,
473 Status
= RtlSetDaclSecurityDescriptor(SecurityDescriptor
,
477 if (! NT_SUCCESS(Status
))
479 DPRINT1("RtlSetDaclSecurityDescriptor() failed (Status %lx)\n",
484 InitializeObjectAttributes(&ObjectAttributes
,
486 OBJ_CASE_INSENSITIVE
,
489 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
490 SYMBOLIC_LINK_ALL_ACCESS
,
493 if (NT_SUCCESS(Status
))
495 Status
= NtMakePermanentObject(LinkHandle
);
496 if (! NT_SUCCESS(Status
))
498 DPRINT1("NtMakePermanentObject(%wZ) failed (Status %lx)\n",
499 &DeviceName
, Status
);
504 DPRINT1("NtCreateSymbolicLinkObject(%wZ) failed (Status %lx)\n",
505 &DeviceName
, Status
);
510 (void) RtlLeaveCriticalSection(&Win32CsrDefineDosDeviceCritSec
);
511 if (DeviceName
.Buffer
)
512 (void) RtlFreeHeap(Win32CsrApiHeap
,
515 if (LinkTarget
.Buffer
)
516 (void) RtlFreeHeap(Win32CsrApiHeap
,
519 if (SecurityDescriptor
)
520 (void) RtlFreeHeap(Win32CsrApiHeap
,
524 (void) NtClose(LinkHandle
);
526 (void) RtlFreeSid(SystemSid
);
528 (void) RtlFreeSid(AdminSid
);
530 (void) RtlFreeSid(WorldSid
);
531 RtlFreeUnicodeString(&RequestDeviceName
);
534 if (HistoryEntry
->Target
.Buffer
)
535 (void) RtlFreeHeap(Win32CsrApiHeap
,
537 HistoryEntry
->Target
.Buffer
);
538 if (HistoryEntry
->Device
.Buffer
)
539 (void) RtlFreeHeap(Win32CsrApiHeap
,
541 HistoryEntry
->Device
.Buffer
);
542 (void) RtlFreeHeap(Win32CsrApiHeap
,
549 DPRINT("CsrDefineDosDevice Exit, Statux: 0x%x\n", Status
);
553 void CsrCleanupDefineDosDevice(void)
555 PLIST_ENTRY Entry
, ListHead
;
556 PCSRSS_DOS_DEVICE_HISTORY_ENTRY HistoryEntry
;
558 (void) RtlDeleteCriticalSection(&Win32CsrDefineDosDeviceCritSec
);
560 ListHead
= &DosDeviceHistory
;
561 Entry
= ListHead
->Flink
;
562 while (Entry
!= ListHead
)
564 HistoryEntry
= (PCSRSS_DOS_DEVICE_HISTORY_ENTRY
)
565 CONTAINING_RECORD(Entry
,
566 CSRSS_DOS_DEVICE_HISTORY_ENTRY
,
568 Entry
= Entry
->Flink
;
572 if (HistoryEntry
->Target
.Buffer
)
573 (void) RtlFreeHeap(Win32CsrApiHeap
,
575 HistoryEntry
->Target
.Buffer
);
576 if (HistoryEntry
->Device
.Buffer
)
577 (void) RtlFreeHeap(Win32CsrApiHeap
,
579 HistoryEntry
->Device
.Buffer
);
580 (void) RtlFreeHeap(Win32CsrApiHeap
,