ReactOS 0.4.16-dev-91-g764881a
dosdev.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/kernel32/client/dosdev.c
5 * PURPOSE: Dos device functions
6 * PROGRAMMER: Ariadne (ariadne@xs4all.nl)
7 * Pierre Schweitzer
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 */
11
12/* INCLUDES ******************************************************************/
13
14#include <k32.h>
15
16#define NDEBUG
17#include <debug.h>
18#include <dbt.h>
20
21/* FUNCTIONS *****************************************************************/
22
23/*
24 * @implemented
25 */
29 PBOOLEAN IsGlobal)
30{
33 UNICODE_STRING GlobalString;
34 OBJECT_NAME_INFORMATION NameInfo, *PNameInfo;
35
36 /* We need both parameters */
37 if (DirectoryHandle == 0 || IsGlobal == NULL)
38 {
40 }
41
42 PNameInfo = NULL;
44 {
45 /* Query handle information */
48 &NameInfo,
49 0,
51 /* Only failure we tolerate is length mismatch */
53 {
54 /* Allocate big enough buffer */
55 PNameInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, ReturnLength);
56 if (PNameInfo == NULL)
57 {
60 }
61
62 /* Query again handle information */
65 PNameInfo,
68
69 /*
70 * If it succeed, check we have Global??
71 * If so, return success
72 */
73 if (NT_SUCCESS(Status))
74 {
75 RtlInitUnicodeString(&GlobalString, L"\\GLOBAL??");
76 *IsGlobal = RtlEqualUnicodeString(&GlobalString, &PNameInfo->Name, FALSE);
78 }
79 }
80 }
82 {
83 if (PNameInfo != NULL)
84 {
85 RtlFreeHeap(RtlGetProcessHeap(), 0, PNameInfo);
86 }
87 }
89
90 return Status;
91}
92
93/*
94 * @implemented
95 */
98 PWSTR NameToFind,
99 PWSTR NamesList,
100 DWORD TotalEntries,
102{
103 WCHAR Current;
105 PWSTR PartialNamesList;
106
107 /* We need all parameters to be set */
108 if (NameToFind == NULL || NamesList == NULL || Found == NULL)
109 {
111 }
112
113 /* Assume failure */
114 *Found = FALSE;
115
116 /* If no entries, job done, nothing found */
117 if (TotalEntries == 0)
118 {
119 return ERROR_SUCCESS;
120 }
121
122 /* Start browsing the names list */
123 Entries = 0;
124 PartialNamesList = NamesList;
125 /* As long as we didn't find the name... */
126 while (wcscmp(NameToFind, PartialNamesList) != 0)
127 {
128 /* We chomped an entry! */
129 ++Entries;
130
131 /* We're out of entries, bail out not to overrun */
132 if (Entries > TotalEntries)
133 {
134 /*
135 * Even though we found nothing,
136 * the function ran fine
137 */
138 return ERROR_SUCCESS;
139 }
140
141 /* Jump to the next string */
142 do
143 {
144 Current = *PartialNamesList;
145 ++PartialNamesList;
146 } while (Current != UNICODE_NULL);
147 }
148
149 /*
150 * We're here because the loop stopped:
151 * it means we found the name in the list
152 */
153 *Found = TRUE;
154 return ERROR_SUCCESS;
155}
156
157/*
158 * @implemented
159 */
160BOOL
161WINAPI
164 LPCSTR lpDeviceName,
165 LPCSTR lpTargetPath
166 )
167{
168 BOOL Result;
171 PWSTR TargetPathBuffer;
172 UNICODE_STRING TargetPathU;
173 PUNICODE_STRING DeviceNameU;
174
175 /* Convert DeviceName using static unicode string */
176 RtlInitAnsiString(&AnsiString, lpDeviceName);
177 DeviceNameU = &NtCurrentTeb()->StaticUnicodeString;
179 if (!NT_SUCCESS(Status))
180 {
181 /*
182 * If the static unicode string is too small,
183 * it's because the name is too long...
184 * so, return appropriate status!
185 */
187 {
189 return FALSE;
190 }
191
193 return FALSE;
194 }
195
196 /* Convert target path if existing */
197 if (lpTargetPath != NULL)
198 {
199 RtlInitAnsiString(&AnsiString, lpTargetPath);
201 if (!NT_SUCCESS(Status))
202 {
204 return FALSE;
205 }
206
207 TargetPathBuffer = TargetPathU.Buffer;
208 }
209 else
210 {
211 TargetPathBuffer = NULL;
212 }
213
214 /* Call W */
215 Result = DefineDosDeviceW(dwFlags, DeviceNameU->Buffer, TargetPathBuffer);
216
217 /* Free target path if allocated */
218 if (TargetPathBuffer != NULL)
219 {
220 RtlFreeUnicodeString(&TargetPathU);
221 }
222
223 return Result;
224}
225
226
227/*
228 * @implemented
229 */
230BOOL
231WINAPI
234 LPCWSTR lpDeviceName,
235 LPCWSTR lpTargetPath
236 )
237{
238 ULONG ArgumentCount;
240 BASE_API_MESSAGE ApiMessage;
241 PBASE_DEFINE_DOS_DEVICE DefineDosDeviceRequest = &ApiMessage.Data.DefineDosDeviceRequest;
242 PCSR_CAPTURE_BUFFER CaptureBuffer;
243 UNICODE_STRING NtTargetPathU;
244 UNICODE_STRING DeviceNameU;
245 HANDLE hUser32;
247 DWORD dwRecipients;
248 typedef long (WINAPI *BSM_type)(DWORD, LPDWORD, UINT, WPARAM, LPARAM);
249 BSM_type BSM_ptr;
250 BOOLEAN LUIDDeviceMapsEnabled;
253
254 /* Get status about local device mapping */
255 LUIDDeviceMapsEnabled = BaseStaticServerData->LUIDDeviceMapsEnabled;
256
257 /* Validate input & flags */
258 if ((dwFlags & 0xFFFFFFE0) ||
261 (lpTargetPath == NULL && !(dwFlags & (DDD_LUID_BROADCAST_DRIVE | DDD_REMOVE_DEFINITION))) ||
263 (lpDeviceName == NULL || lpTargetPath != NULL || dwFlags & (DDD_NO_BROADCAST_SYSTEM | DDD_EXACT_MATCH_ON_REMOVE | DDD_RAW_TARGET_PATH) || !LUIDDeviceMapsEnabled)))
264 {
266 return FALSE;
267 }
268
269 /* Initialize device unicode string to ease its use */
270 RtlInitUnicodeString(&DeviceNameU, lpDeviceName);
271
272 /* The buffer for CSR call will contain it */
273 BufferSize = DeviceNameU.MaximumLength;
274 ArgumentCount = 1;
275
276 /* If we don't have target path, use empty string */
277 if (lpTargetPath == NULL)
278 {
279 RtlInitUnicodeString(&NtTargetPathU, NULL);
280 }
281 else
282 {
283 /* Else, use it raw if asked to */
285 {
286 RtlInitUnicodeString(&NtTargetPathU, lpTargetPath);
287 }
288 else
289 {
290 /* Otherwise, use it converted */
291 if (!RtlDosPathNameToNtPathName_U(lpTargetPath,
292 &NtTargetPathU,
293 NULL,
294 NULL))
295 {
296 WARN("RtlDosPathNameToNtPathName_U() failed\n");
298 return FALSE;
299 }
300 }
301
302 /* This target path will be the second arg */
303 ArgumentCount = 2;
304 BufferSize += NtTargetPathU.MaximumLength;
305 }
306
307 /* Allocate the capture buffer for our strings */
308 CaptureBuffer = CsrAllocateCaptureBuffer(ArgumentCount,
309 BufferSize);
310 if (CaptureBuffer == NULL)
311 {
313 {
314 RtlFreeUnicodeString(&NtTargetPathU);
315 }
316
318 return FALSE;
319 }
320
321 /* Set the flags */
322 DefineDosDeviceRequest->Flags = dwFlags;
323
324 /* Allocate a buffer for the device name */
325 DefineDosDeviceRequest->DeviceName.MaximumLength = CsrAllocateMessagePointer(CaptureBuffer,
326 DeviceNameU.MaximumLength,
327 (PVOID*)&DefineDosDeviceRequest->DeviceName.Buffer);
328 /* And copy it while upcasing it */
329 RtlUpcaseUnicodeString(&DefineDosDeviceRequest->DeviceName, &DeviceNameU, FALSE);
330
331 /* If we have a target path, copy it too, and free it if allocated */
332 if (NtTargetPathU.Length != 0)
333 {
334 DefineDosDeviceRequest->TargetPath.MaximumLength = CsrAllocateMessagePointer(CaptureBuffer,
335 NtTargetPathU.MaximumLength,
336 (PVOID*)&DefineDosDeviceRequest->TargetPath.Buffer);
337 RtlCopyUnicodeString(&DefineDosDeviceRequest->TargetPath, &NtTargetPathU);
338
340 {
341 RtlFreeUnicodeString(&NtTargetPathU);
342 }
343 }
344 /* Otherwise, null initialize the string */
345 else
346 {
347 RtlInitUnicodeString(&DefineDosDeviceRequest->TargetPath, NULL);
348 }
349
350 /* Finally, call the server */
352 CaptureBuffer,
354 sizeof(*DefineDosDeviceRequest));
355 CsrFreeCaptureBuffer(CaptureBuffer);
356
357 /* Return failure if any */
358 if (!NT_SUCCESS(ApiMessage.Status))
359 {
360 WARN("CsrClientCallServer() failed (Status %lx)\n", ApiMessage.Status);
361 BaseSetLastNTError(ApiMessage.Status);
362 return FALSE;
363 }
364
365 /* Here is the success path, we will always return true */
366
367 /* Should broadcast the event? Only do if not denied and if drive letter */
369 DeviceNameU.Length == 2 * sizeof(WCHAR) &&
370 DeviceNameU.Buffer[1] == L':')
371 {
372 /* Make sure letter is valid and there are no local device mappings */
373 Letter = RtlUpcaseUnicodeChar(DeviceNameU.Buffer[0]) - L'A';
374 if (Letter < 26 && !LUIDDeviceMapsEnabled)
375 {
376 /* Rely on user32 for broadcasting */
377 hUser32 = LoadLibraryW(L"user32.dll");
378 if (hUser32 != 0)
379 {
380 /* Get the function pointer */
381 BSM_ptr = (BSM_type)GetProcAddress(hUser32, "BroadcastSystemMessageW");
382 if (BSM_ptr)
383 {
384 /* Set our target */
385 dwRecipients = BSM_APPLICATIONS;
386
387 /* And initialize our structure */
388 dbcv.dbcv_size = sizeof(DEV_BROADCAST_VOLUME);
390 dbcv.dbcv_reserved = 0;
391
392 /* Set the volume which had the event */
393 dbcv.dbcv_unitmask = 1 << Letter;
394 dbcv.dbcv_flags = DBTF_NET;
395
396 /* And properly set the event (removal or arrival?) */
398
399 /* And broadcast! */
400 BSM_ptr(BSF_SENDNOTIFYMESSAGE | BSF_FLUSHDISK,
401 &dwRecipients,
403 wParam,
404 (LPARAM)&dbcv);
405 }
406
407 /* We're done! */
408 FreeLibrary(hUser32);
409 }
410 }
411 }
412
413 return TRUE;
414}
415
416
417/*
418 * @implemented
419 */
420DWORD
421WINAPI
423 LPCSTR lpDeviceName,
424 LPSTR lpTargetPath,
425 DWORD ucchMax
426 )
427{
431 UNICODE_STRING TargetPathU;
432 PUNICODE_STRING DeviceNameU;
433 DWORD RetLength, CurrentLength, Length;
434 PWSTR DeviceNameBuffer, TargetPathBuffer;
435
436 /* If we want a specific device name, convert it */
437 if (lpDeviceName != NULL)
438 {
439 /* Convert DeviceName using static unicode string */
440 RtlInitAnsiString(&AnsiString, lpDeviceName);
441 DeviceNameU = &NtCurrentTeb()->StaticUnicodeString;
443 if (!NT_SUCCESS(Status))
444 {
445 /*
446 * If the static unicode string is too small,
447 * it's because the name is too long...
448 * so, return appropriate status!
449 */
451 {
453 return FALSE;
454 }
455
457 return FALSE;
458 }
459
460 DeviceNameBuffer = DeviceNameU->Buffer;
461 }
462 else
463 {
464 DeviceNameBuffer = NULL;
465 }
466
467 /* Allocate the output buffer for W call */
468 TargetPathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, ucchMax * sizeof(WCHAR));
469 if (TargetPathBuffer == NULL)
470 {
472 return 0;
473 }
474
475 /* Call W */
476 Length = QueryDosDeviceW(DeviceNameBuffer, TargetPathBuffer, ucchMax);
477 /* We'll return that length in case of a success */
478 RetLength = Length;
479
480 /* Handle the case where we would fill output buffer completly */
481 if (Length != 0 && Length == ucchMax)
482 {
483 /* This will be our work length (but not the one we return) */
484 --Length;
485 /* Already 0 the last char */
486 lpTargetPath[Length] = ANSI_NULL;
487 }
488
489 /* If we had an output, start the convert loop */
490 if (Length != 0)
491 {
492 /*
493 * We'll have to loop because TargetPathBuffer may contain
494 * several strings (NULL separated)
495 * We'll start at position 0
496 */
497 CurrentPosition = 0;
498 while (CurrentPosition < Length)
499 {
500 /* Get the maximum length */
501 CurrentLength = min(Length - CurrentPosition, MAXUSHORT / 2);
502
503 /* Initialize our output string */
504 AnsiString.Length = 0;
505 AnsiString.MaximumLength = CurrentLength + sizeof(ANSI_NULL);
506 AnsiString.Buffer = &lpTargetPath[CurrentPosition];
507
508 /* Initialize input string that will be converted */
509 TargetPathU.Length = CurrentLength * sizeof(WCHAR);
510 TargetPathU.MaximumLength = CurrentLength * sizeof(WCHAR) + sizeof(UNICODE_NULL);
511 TargetPathU.Buffer = &TargetPathBuffer[CurrentPosition];
512
513 /* Convert to ANSI */
515 if (!NT_SUCCESS(Status))
516 {
518 /* In case of a failure, forget about everything */
519 RetLength = 0;
520
521 goto Leave;
522 }
523
524 /* Move to the next string */
525 CurrentPosition += CurrentLength;
526 }
527 }
528
529Leave:
530 /* Free our intermediate buffer and leave */
531 RtlFreeHeap(RtlGetProcessHeap(), 0, TargetPathBuffer);
532
533 return RetLength;
534}
535
536
537/*
538 * @implemented
539 */
540DWORD
541WINAPI
543 LPCWSTR lpDeviceName,
544 LPWSTR lpTargetPath,
545 DWORD ucchMax
546 )
547{
548 PWSTR Ptr;
551 USHORT i, TotalEntries;
555 BOOLEAN IsGlobal, GlobalNeeded, Found;
557 OBJECT_DIRECTORY_INFORMATION NullEntry = {{0}};
559
560 /* Open the '\??' directory */
565 NULL,
566 NULL);
570 if (!NT_SUCCESS(Status))
571 {
572 WARN("NtOpenDirectoryObject() failed (Status %lx)\n", Status);
574 return 0;
575 }
576
577 Buffer = NULL;
579 {
580 if (lpDeviceName != NULL)
581 {
582 /* Open the lpDeviceName link object */
583 RtlInitUnicodeString(&UnicodeString, lpDeviceName);
588 NULL);
592 if (!NT_SUCCESS(Status))
593 {
594 WARN("NtOpenSymbolicLinkObject() failed (Status %lx)\n", Status);
596 }
597
598 /*
599 * Make sure we don't overrun the output buffer, so convert our DWORD
600 * size to USHORT size properly
601 */
602 Length = (ucchMax <= MAXULONG / sizeof(WCHAR)) ? (ucchMax * sizeof(WCHAR)) : MAXULONG;
603
604 /* Query link target */
605 UnicodeString.Length = 0;
606 UnicodeString.MaximumLength = Length <= MAXUSHORT ? Length : MAXUSHORT;
607 UnicodeString.Buffer = lpTargetPath;
608
609 ReturnLength = 0;
612 &ReturnLength);
614 if (!NT_SUCCESS(Status))
615 {
616 WARN("NtQuerySymbolicLinkObject() failed (Status %lx)\n", Status);
618 }
619
620 TRACE("ReturnLength: %lu\n", ReturnLength);
621 TRACE("TargetLength: %hu\n", UnicodeString.Length);
622 TRACE("Target: '%wZ'\n", &UnicodeString);
623
624 Length = ReturnLength / sizeof(WCHAR);
625 /* Make sure we null terminate output buffer */
626 if (Length == 0 || lpTargetPath[Length - 1] != UNICODE_NULL)
627 {
628 if (Length >= ucchMax)
629 {
630 TRACE("Buffer is too small\n");
633 }
634
635 /* Append null-character */
636 lpTargetPath[Length] = UNICODE_NULL;
637 Length++;
638 }
639
640 if (Length < ucchMax)
641 {
642 /* Append null-character */
643 lpTargetPath[Length] = UNICODE_NULL;
644 Length++;
645 }
646
648 }
649
650 /*
651 * If LUID device maps are enabled,
652 * ?? may not point to BaseNamedObjects
653 * It may only be local DOS namespace.
654 * And thus, it might be required to browse
655 * Global?? for global devices
656 */
657 GlobalNeeded = FALSE;
659 {
660 /* Assume ?? == Global?? */
661 IsGlobal = TRUE;
662 /* Check if it's the case */
664 if (NT_SUCCESS(Status) && !IsGlobal)
665 {
666 /* It's not, we'll have to browse Global?? too! */
667 GlobalNeeded = TRUE;
668 }
669 }
670
671 /*
672 * Make sure we don't overrun the output buffer, so convert our DWORD
673 * size to USHORT size properly
674 */
675 BufferLength = (ucchMax <= MAXULONG / sizeof(WCHAR)) ? (ucchMax * sizeof(WCHAR)) : MAXULONG;
676 Length = 0;
677 Ptr = lpTargetPath;
678
679 Context = 0;
680 TotalEntries = 0;
681
682 /*
683 * We'll query all entries at once, with a rather big buffer
684 * If it's too small, we'll grow it by 2.
685 * Limit the number of attempts to 3.
686 */
687 for (i = 0; i < 3; ++i)
688 {
689 /* Allocate the query buffer */
690 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
691 if (Buffer == NULL)
692 {
695 }
696
697 /* Perform the query */
699 Buffer,
701 FALSE,
702 TRUE,
703 &Context,
704 &ReturnLength);
705 /* Only failure accepted is: no more entries */
706 if (!NT_SUCCESS(Status))
707 {
709 {
711 }
712
713 /*
714 * Which is a success! But break out,
715 * it means our query returned no results
716 * so, nothing to parse.
717 */
719 break;
720 }
721
722 /* In case we had them all, start browsing for devices */
724 {
725 DirInfo = Buffer;
726
727 /* Loop until we find the nul entry (terminating entry) */
728 while (TRUE)
729 {
730 /* It's an entry full of zeroes */
731 if (RtlCompareMemory(&NullEntry, DirInfo, sizeof(NullEntry)) == sizeof(NullEntry))
732 {
733 break;
734 }
735
736 /* Only handle symlinks */
737 if (!wcscmp(DirInfo->TypeName.Buffer, L"SymbolicLink"))
738 {
739 TRACE("Name: '%wZ'\n", &DirInfo->Name);
740
741 /* Get name length in chars to only comparisons */
742 NameLength = DirInfo->Name.Length / sizeof(WCHAR);
743
744 /* Make sure we don't overrun output buffer */
745 if (Length > ucchMax ||
746 NameLength > ucchMax - Length ||
747 ucchMax - NameLength - Length < sizeof(WCHAR))
748 {
751 }
752
753 /* Copy and NULL terminate string */
754 memcpy(Ptr, DirInfo->Name.Buffer, DirInfo->Name.Length);
755 Ptr[NameLength] = UNICODE_NULL;
756
757 Ptr += (NameLength + 1);
758 Length += (NameLength + 1);
759
760 /*
761 * Keep the entries count, in case we would have to
762 * handle GLOBAL?? too
763 */
764 ++TotalEntries;
765 }
766
767 /* Move to the next entry */
768 ++DirInfo;
769 }
770
771 /*
772 * No need to loop again here, we got all the entries
773 * Note: we don't free the buffer here, because we may
774 * need it for GLOBAL??, so we save a few cycles here.
775 */
776 break;
777 }
778
779 /* Failure path here, we'll need bigger buffer */
780 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
781 Buffer = NULL;
782
783 /* We can't have bigger than that one, so leave */
784 if (BufferLength == MAXULONG)
785 {
786 break;
787 }
788
789 /* Prevent any overflow while computing new size */
791 {
793 }
794 else
795 {
796 BufferLength *= 2;
797 }
798 }
799
800 /*
801 * Out of the hot loop, but with more entries left?
802 * that's an error case, leave here!
803 */
805 {
808 }
809
810 /* Now, if we had to handle GLOBAL??, go for it! */
812 {
814 DirectoryHandle = 0;
815
816 RtlInitUnicodeString(&UnicodeString, L"\\GLOBAL??");
820 NULL,
821 NULL);
825 if (!NT_SUCCESS(Status))
826 {
827 WARN("NtOpenDirectoryObject() failed (Status %lx)\n", Status);
829 }
830
831 /*
832 * We'll query all entries at once, with a rather big buffer
833 * If it's too small, we'll grow it by 2.
834 * Limit the number of attempts to 3.
835 */
836 for (i = 0; i < 3; ++i)
837 {
838 /* If we had no buffer from previous attempt, allocate one */
839 if (Buffer == NULL)
840 {
841 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
842 if (Buffer == NULL)
843 {
846 }
847 }
848
849 /* Perform the query */
851 Buffer,
853 FALSE,
854 TRUE,
855 &Context,
856 &ReturnLength);
857 /* Only failure accepted is: no more entries */
858 if (!NT_SUCCESS(Status))
859 {
861 {
863 }
864
865 /*
866 * Which is a success! But break out,
867 * it means our query returned no results
868 * so, nothing to parse.
869 */
871 break;
872 }
873
874 /* In case we had them all, start browsing for devices */
876 {
877 DirInfo = Buffer;
878
879 /* Loop until we find the nul entry (terminating entry) */
880 while (TRUE)
881 {
882 /* It's an entry full of zeroes */
883 if (RtlCompareMemory(&NullEntry, DirInfo, sizeof(NullEntry)) == sizeof(NullEntry))
884 {
885 break;
886 }
887
888 /* Only handle symlinks */
889 if (!wcscmp(DirInfo->TypeName.Buffer, L"SymbolicLink"))
890 {
891 TRACE("Name: '%wZ'\n", &DirInfo->Name);
892
893 /*
894 * Now, we previously already browsed ??, and we
895 * don't want to devices twice, so we'll check
896 * the output buffer for duplicates.
897 * We'll add our entry only if we don't have already
898 * returned it.
899 */
900 if (FindSymbolicLinkEntry(DirInfo->Name.Buffer,
901 lpTargetPath,
902 TotalEntries,
903 &Found) == ERROR_SUCCESS &&
904 !Found)
905 {
906 /* Get name length in chars to only comparisons */
907 NameLength = DirInfo->Name.Length / sizeof(WCHAR);
908
909 /* Make sure we don't overrun output buffer */
910 if (Length > ucchMax ||
911 NameLength > ucchMax - Length ||
912 ucchMax - NameLength - Length < sizeof(WCHAR))
913 {
914 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
917 return 0;
918 }
919
920 /* Copy and NULL terminate string */
921 memcpy(Ptr, DirInfo->Name.Buffer, DirInfo->Name.Length);
922 Ptr[NameLength] = UNICODE_NULL;
923
924 Ptr += (NameLength + 1);
925 Length += (NameLength + 1);
926 }
927 }
928
929 /* Move to the next entry */
930 ++DirInfo;
931 }
932
933 /* No need to loop again here, we got all the entries */
934 break;
935 }
936
937 /* Failure path here, we'll need bigger buffer */
938 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
939 Buffer = NULL;
940
941 /* We can't have bigger than that one, so leave */
942 if (BufferLength == MAXULONG)
943 {
944 break;
945 }
946
947 /* Prevent any overflow while computing new size */
949 {
951 }
952 else
953 {
954 BufferLength *= 2;
955 }
956 }
957
958 /*
959 * Out of the hot loop, but with more entries left?
960 * that's an error case, leave here!
961 */
963 {
966 }
967 }
968
969 /* If we failed somewhere, just leave */
970 if (!NT_SUCCESS(Status))
971 {
973 }
974
975 /* If we returned no entries, time to write the empty string */
976 if (Length == 0)
977 {
978 /* Unless output buffer is too small! */
979 if (ucchMax <= 0)
980 {
983 }
984
985 /* Emptry string is one char (terminator!) */
986 *Ptr = UNICODE_NULL;
987 ++Ptr;
988 Length = 1;
989 }
990
991 /*
992 * If we have enough room, we need to double terminate the buffer:
993 * that's a MULTI_SZ buffer, its end is marked by double NULL.
994 * One was already added during the "copy string" process.
995 * If we don't have enough room: that's a failure case.
996 */
997 if (Length < ucchMax)
998 {
999 *Ptr = UNICODE_NULL;
1000 ++Ptr;
1001 }
1002 else
1003 {
1005 }
1006 }
1008 {
1009 if (DirectoryHandle != 0)
1010 {
1012 }
1013
1014 if (Buffer != NULL)
1015 {
1016 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1017 }
1018
1019 if (!NT_SUCCESS(Status))
1020 {
1021 Length = 0;
1023 }
1024 }
1025 _SEH2_END;
1026
1027 return Length;
1028}
1029
1030/* EOF */
WCHAR Letter
@ ObjectNameInformation
Definition: DriverTester.h:55
NTSTATUS NtQueryObject(IN HANDLE Handle, IN OBJECT_INFO_CLASS ObjectInformationClass, OUT PVOID ObjectInformation, IN ULONG ObjectInformationLength, OUT PULONG ReturnLength)
static const ENTRY Entries[]
static HANDLE DirectoryHandle
Definition: ObType.c:48
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DEBUG_CHANNEL(args)
Definition: rdesktop.h:159
#define WARN(fmt,...)
Definition: precomp.h:61
@ BasepDefineDosDevice
Definition: basemsg.h:44
#define BASESRV_SERVERDLL_INDEX
Definition: basemsg.h:15
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
return Found
Definition: dirsup.c:1270
Definition: bufpool.h:45
WPARAM wParam
Definition: combotst.c:138
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define CSR_CREATE_API_NUMBER(ServerId, ApiId)
Definition: csrmsg.h:37
#define BSF_FLUSHDISK
Definition: dbt.h:53
#define DBT_DEVTYP_VOLUME
Definition: dbt.h:21
#define DBTF_NET
Definition: dbt.h:44
#define BSM_APPLICATIONS
Definition: dbt.h:48
#define DBT_DEVICEARRIVAL
Definition: dbt.h:12
#define DBT_DEVICEREMOVECOMPLETE
Definition: dbt.h:16
struct _DEV_BROADCAST_VOLUME DEV_BROADCAST_VOLUME
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define BufferSize
Definition: mmc.h:75
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
#define GetProcAddress(x, y)
Definition: compat.h:753
#define FreeLibrary(x)
Definition: compat.h:748
#define LoadLibraryW(x)
Definition: compat.h:747
PBASE_STATIC_SERVER_DATA BaseStaticServerData
Definition: dllmain.c:19
DWORD WINAPI QueryDosDeviceA(LPCSTR lpDeviceName, LPSTR lpTargetPath, DWORD ucchMax)
Definition: dosdev.c:422
BOOL WINAPI DefineDosDeviceA(DWORD dwFlags, LPCSTR lpDeviceName, LPCSTR lpTargetPath)
Definition: dosdev.c:162
BOOL WINAPI DefineDosDeviceW(DWORD dwFlags, LPCWSTR lpDeviceName, LPCWSTR lpTargetPath)
Definition: dosdev.c:232
DWORD FindSymbolicLinkEntry(PWSTR NameToFind, PWSTR NamesList, DWORD TotalEntries, PBOOLEAN Found)
Definition: dosdev.c:97
NTSTATUS IsGlobalDeviceMap(HANDLE DirectoryHandle, PBOOLEAN IsGlobal)
Definition: dosdev.c:27
DWORD WINAPI QueryDosDeviceW(LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWORD ucchMax)
Definition: dosdev.c:542
@ AnsiString
Definition: dnslib.h:19
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:43
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define _SEH2_LEAVE
Definition: filesup.c:20
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_Inout_ PUSB_DEVICE_HANDLE DeviceHandle
Definition: hubbusif.h:121
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define NtCurrentTeb
#define kernel32file
Definition: kernel32.h:6
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
NTSYSAPI BOOLEAN NTAPI RtlDosPathNameToNtPathName_U(_In_opt_z_ PCWSTR DosPathName, _Out_ PUNICODE_STRING NtPathName, _Out_opt_ PCWSTR *NtFileNamePart, _Out_opt_ PRTL_RELATIVE_NAME_U DirectoryInfo)
WCHAR NTAPI RtlUpcaseUnicodeChar(_In_ WCHAR Source)
Definition: nlsboot.c:176
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
#define SYMBOLIC_LINK_QUERY
Definition: nt_native.h:1265
#define DIRECTORY_QUERY
Definition: nt_native.h:1254
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define LPDWORD
Definition: nt_native.h:46
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define DWORD
Definition: nt_native.h:44
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
#define UNICODE_NULL
#define ANSI_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI NtOpenDirectoryObject(OUT PHANDLE DirectoryHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: obdir.c:393
NTSTATUS NTAPI NtQueryDirectoryObject(IN HANDLE DirectoryHandle, OUT PVOID Buffer, IN ULONG BufferLength, IN BOOLEAN ReturnSingleEntry, IN BOOLEAN RestartScan, IN OUT PULONG Context, OUT PULONG ReturnLength OPTIONAL)
Definition: obdir.c:490
ULONG CurrentPosition
Definition: patchapi.h:57
unsigned short USHORT
Definition: pedump.c:61
#define long
Definition: qsort.c:33
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:167
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
PCSR_CAPTURE_BUFFER NTAPI CsrAllocateCaptureBuffer(_In_ ULONG ArgumentCount, _In_ ULONG BufferSize)
Definition: capture.c:87
ULONG NTAPI CsrAllocateMessagePointer(_Inout_ PCSR_CAPTURE_BUFFER CaptureBuffer, _In_ ULONG MessageLength, _Out_ PVOID *CapturedData)
Definition: capture.c:152
VOID NTAPI CsrFreeCaptureBuffer(_In_ _Frees_ptr_ PCSR_CAPTURE_BUFFER CaptureBuffer)
Definition: capture.c:210
NTSTATUS NTAPI CsrClientCallServer(_Inout_ PCSR_API_MESSAGE ApiMessage, _Inout_opt_ PCSR_CAPTURE_BUFFER CaptureBuffer, _In_ CSR_API_NUMBER ApiNumber, _In_ ULONG DataLength)
Definition: connect.c:366
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define TRACE(s)
Definition: solgame.cpp:4
NTSTATUS Status
Definition: basemsg.h:279
BASE_DEFINE_DOS_DEVICE DefineDosDeviceRequest
Definition: basemsg.h:300
union _BASE_API_MESSAGE::@3534 Data
UNICODE_STRING TargetPath
Definition: basemsg.h:257
UNICODE_STRING DeviceName
Definition: basemsg.h:256
BOOLEAN LUIDDeviceMapsEnabled
Definition: base.h:141
DWORD dbcv_reserved
Definition: dbt.h:103
DWORD dbcv_unitmask
Definition: dbt.h:104
DWORD dbcv_devicetype
Definition: dbt.h:102
UNICODE_STRING TypeName
Definition: obtypes.h:279
UNICODE_STRING Name
Definition: nt_native.h:1270
USHORT MaximumLength
Definition: env_spec_w32.h:370
uint16_t * PWSTR
Definition: typedefs.h:56
#define MAXULONG
Definition: typedefs.h:251
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define MAXUSHORT
Definition: typedefs.h:83
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_MORE_ENTRIES
Definition: udferr_usr.h:124
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
#define DDD_NO_BROADCAST_SYSTEM
Definition: winbase.h:526
#define DDD_EXACT_MATCH_ON_REMOVE
Definition: winbase.h:525
#define DDD_RAW_TARGET_PATH
Definition: winbase.h:523
#define DDD_LUID_BROADCAST_DRIVE
Definition: winbase.h:527
#define DDD_REMOVE_DEFINITION
Definition: winbase.h:524
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
LONG_PTR LPARAM
Definition: windef.h:208
UINT_PTR WPARAM
Definition: windef.h:207
#define WINAPI
Definition: msvc.h:6
#define ERROR_FILENAME_EXCED_RANGE
Definition: winerror.h:263
#define WM_DEVICECHANGE
Definition: winuser.h:1814
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185