1*c2c66affSColin Finck /* 2*c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory 3*c2c66affSColin Finck * PROJECT: ReactOS system libraries 4*c2c66affSColin Finck * FILE: dll/win32/kernel32/client/dosdev.c 5*c2c66affSColin Finck * PURPOSE: Dos device functions 6*c2c66affSColin Finck * PROGRAMMER: Ariadne (ariadne@xs4all.nl) 7*c2c66affSColin Finck * UPDATE HISTORY: 8*c2c66affSColin Finck * Created 01/11/98 9*c2c66affSColin Finck */ 10*c2c66affSColin Finck 11*c2c66affSColin Finck /* INCLUDES ******************************************************************/ 12*c2c66affSColin Finck 13*c2c66affSColin Finck #include <k32.h> 14*c2c66affSColin Finck 15*c2c66affSColin Finck #define NDEBUG 16*c2c66affSColin Finck #include <debug.h> 17*c2c66affSColin Finck #include <dbt.h> 18*c2c66affSColin Finck DEBUG_CHANNEL(kernel32file); 19*c2c66affSColin Finck 20*c2c66affSColin Finck /* FUNCTIONS *****************************************************************/ 21*c2c66affSColin Finck 22*c2c66affSColin Finck /* 23*c2c66affSColin Finck * @implemented 24*c2c66affSColin Finck */ 25*c2c66affSColin Finck BOOL 26*c2c66affSColin Finck WINAPI 27*c2c66affSColin Finck DefineDosDeviceA( 28*c2c66affSColin Finck DWORD dwFlags, 29*c2c66affSColin Finck LPCSTR lpDeviceName, 30*c2c66affSColin Finck LPCSTR lpTargetPath 31*c2c66affSColin Finck ) 32*c2c66affSColin Finck { 33*c2c66affSColin Finck UNICODE_STRING DeviceNameU = {0}; 34*c2c66affSColin Finck UNICODE_STRING TargetPathU = {0}; 35*c2c66affSColin Finck BOOL Result; 36*c2c66affSColin Finck 37*c2c66affSColin Finck if (lpDeviceName && 38*c2c66affSColin Finck !RtlCreateUnicodeStringFromAsciiz(&DeviceNameU, lpDeviceName)) 39*c2c66affSColin Finck { 40*c2c66affSColin Finck SetLastError(ERROR_NOT_ENOUGH_MEMORY); 41*c2c66affSColin Finck return 0; 42*c2c66affSColin Finck } 43*c2c66affSColin Finck 44*c2c66affSColin Finck if (lpTargetPath && 45*c2c66affSColin Finck !RtlCreateUnicodeStringFromAsciiz(&TargetPathU, lpTargetPath)) 46*c2c66affSColin Finck { 47*c2c66affSColin Finck if (DeviceNameU.Buffer) 48*c2c66affSColin Finck { 49*c2c66affSColin Finck RtlFreeUnicodeString(&DeviceNameU); 50*c2c66affSColin Finck } 51*c2c66affSColin Finck SetLastError(ERROR_NOT_ENOUGH_MEMORY); 52*c2c66affSColin Finck return 0; 53*c2c66affSColin Finck } 54*c2c66affSColin Finck 55*c2c66affSColin Finck Result = DefineDosDeviceW(dwFlags, 56*c2c66affSColin Finck DeviceNameU.Buffer, 57*c2c66affSColin Finck TargetPathU.Buffer); 58*c2c66affSColin Finck 59*c2c66affSColin Finck if (TargetPathU.Buffer) 60*c2c66affSColin Finck { 61*c2c66affSColin Finck RtlFreeUnicodeString(&TargetPathU); 62*c2c66affSColin Finck } 63*c2c66affSColin Finck 64*c2c66affSColin Finck if (DeviceNameU.Buffer) 65*c2c66affSColin Finck { 66*c2c66affSColin Finck RtlFreeUnicodeString(&DeviceNameU); 67*c2c66affSColin Finck } 68*c2c66affSColin Finck return Result; 69*c2c66affSColin Finck } 70*c2c66affSColin Finck 71*c2c66affSColin Finck 72*c2c66affSColin Finck /* 73*c2c66affSColin Finck * @implemented 74*c2c66affSColin Finck */ 75*c2c66affSColin Finck BOOL 76*c2c66affSColin Finck WINAPI 77*c2c66affSColin Finck DefineDosDeviceW( 78*c2c66affSColin Finck DWORD dwFlags, 79*c2c66affSColin Finck LPCWSTR lpDeviceName, 80*c2c66affSColin Finck LPCWSTR lpTargetPath 81*c2c66affSColin Finck ) 82*c2c66affSColin Finck { 83*c2c66affSColin Finck ULONG ArgumentCount; 84*c2c66affSColin Finck ULONG BufferSize; 85*c2c66affSColin Finck BASE_API_MESSAGE ApiMessage; 86*c2c66affSColin Finck PBASE_DEFINE_DOS_DEVICE DefineDosDeviceRequest = &ApiMessage.Data.DefineDosDeviceRequest; 87*c2c66affSColin Finck PCSR_CAPTURE_BUFFER CaptureBuffer; 88*c2c66affSColin Finck UNICODE_STRING NtTargetPathU; 89*c2c66affSColin Finck UNICODE_STRING DeviceNameU; 90*c2c66affSColin Finck UNICODE_STRING DeviceUpcaseNameU; 91*c2c66affSColin Finck HANDLE hUser32; 92*c2c66affSColin Finck DEV_BROADCAST_VOLUME dbcv; 93*c2c66affSColin Finck BOOL Result = TRUE; 94*c2c66affSColin Finck DWORD dwRecipients; 95*c2c66affSColin Finck typedef long (WINAPI *BSM_type)(DWORD, LPDWORD, UINT, WPARAM, LPARAM); 96*c2c66affSColin Finck BSM_type BSM_ptr; 97*c2c66affSColin Finck 98*c2c66affSColin Finck if ( (dwFlags & 0xFFFFFFF0) || 99*c2c66affSColin Finck ((dwFlags & DDD_EXACT_MATCH_ON_REMOVE) && 100*c2c66affSColin Finck ! (dwFlags & DDD_REMOVE_DEFINITION)) ) 101*c2c66affSColin Finck { 102*c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER); 103*c2c66affSColin Finck return FALSE; 104*c2c66affSColin Finck } 105*c2c66affSColin Finck 106*c2c66affSColin Finck ArgumentCount = 1; 107*c2c66affSColin Finck BufferSize = 0; 108*c2c66affSColin Finck if (!lpTargetPath) 109*c2c66affSColin Finck { 110*c2c66affSColin Finck RtlInitUnicodeString(&NtTargetPathU, 111*c2c66affSColin Finck NULL); 112*c2c66affSColin Finck } 113*c2c66affSColin Finck else 114*c2c66affSColin Finck { 115*c2c66affSColin Finck if (dwFlags & DDD_RAW_TARGET_PATH) 116*c2c66affSColin Finck { 117*c2c66affSColin Finck RtlInitUnicodeString(&NtTargetPathU, 118*c2c66affSColin Finck lpTargetPath); 119*c2c66affSColin Finck } 120*c2c66affSColin Finck else 121*c2c66affSColin Finck { 122*c2c66affSColin Finck if (!RtlDosPathNameToNtPathName_U(lpTargetPath, 123*c2c66affSColin Finck &NtTargetPathU, 124*c2c66affSColin Finck NULL, 125*c2c66affSColin Finck NULL)) 126*c2c66affSColin Finck { 127*c2c66affSColin Finck WARN("RtlDosPathNameToNtPathName_U() failed\n"); 128*c2c66affSColin Finck BaseSetLastNTError(STATUS_OBJECT_NAME_INVALID); 129*c2c66affSColin Finck return FALSE; 130*c2c66affSColin Finck } 131*c2c66affSColin Finck } 132*c2c66affSColin Finck ArgumentCount = 2; 133*c2c66affSColin Finck BufferSize += NtTargetPathU.Length; 134*c2c66affSColin Finck } 135*c2c66affSColin Finck 136*c2c66affSColin Finck RtlInitUnicodeString(&DeviceNameU, 137*c2c66affSColin Finck lpDeviceName); 138*c2c66affSColin Finck RtlUpcaseUnicodeString(&DeviceUpcaseNameU, 139*c2c66affSColin Finck &DeviceNameU, 140*c2c66affSColin Finck TRUE); 141*c2c66affSColin Finck BufferSize += DeviceUpcaseNameU.Length; 142*c2c66affSColin Finck 143*c2c66affSColin Finck CaptureBuffer = CsrAllocateCaptureBuffer(ArgumentCount, 144*c2c66affSColin Finck BufferSize); 145*c2c66affSColin Finck if (!CaptureBuffer) 146*c2c66affSColin Finck { 147*c2c66affSColin Finck SetLastError(ERROR_NOT_ENOUGH_MEMORY); 148*c2c66affSColin Finck Result = FALSE; 149*c2c66affSColin Finck } 150*c2c66affSColin Finck else 151*c2c66affSColin Finck { 152*c2c66affSColin Finck DefineDosDeviceRequest->Flags = dwFlags; 153*c2c66affSColin Finck 154*c2c66affSColin Finck CsrCaptureMessageBuffer(CaptureBuffer, 155*c2c66affSColin Finck DeviceUpcaseNameU.Buffer, 156*c2c66affSColin Finck DeviceUpcaseNameU.Length, 157*c2c66affSColin Finck (PVOID*)&DefineDosDeviceRequest->DeviceName.Buffer); 158*c2c66affSColin Finck 159*c2c66affSColin Finck DefineDosDeviceRequest->DeviceName.Length = 160*c2c66affSColin Finck DeviceUpcaseNameU.Length; 161*c2c66affSColin Finck DefineDosDeviceRequest->DeviceName.MaximumLength = 162*c2c66affSColin Finck DeviceUpcaseNameU.Length; 163*c2c66affSColin Finck 164*c2c66affSColin Finck if (NtTargetPathU.Buffer) 165*c2c66affSColin Finck { 166*c2c66affSColin Finck CsrCaptureMessageBuffer(CaptureBuffer, 167*c2c66affSColin Finck NtTargetPathU.Buffer, 168*c2c66affSColin Finck NtTargetPathU.Length, 169*c2c66affSColin Finck (PVOID*)&DefineDosDeviceRequest->TargetPath.Buffer); 170*c2c66affSColin Finck } 171*c2c66affSColin Finck DefineDosDeviceRequest->TargetPath.Length = 172*c2c66affSColin Finck NtTargetPathU.Length; 173*c2c66affSColin Finck DefineDosDeviceRequest->TargetPath.MaximumLength = 174*c2c66affSColin Finck NtTargetPathU.Length; 175*c2c66affSColin Finck 176*c2c66affSColin Finck CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, 177*c2c66affSColin Finck CaptureBuffer, 178*c2c66affSColin Finck CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepDefineDosDevice), 179*c2c66affSColin Finck sizeof(*DefineDosDeviceRequest)); 180*c2c66affSColin Finck CsrFreeCaptureBuffer(CaptureBuffer); 181*c2c66affSColin Finck 182*c2c66affSColin Finck if (!NT_SUCCESS(ApiMessage.Status)) 183*c2c66affSColin Finck { 184*c2c66affSColin Finck WARN("CsrClientCallServer() failed (Status %lx)\n", ApiMessage.Status); 185*c2c66affSColin Finck BaseSetLastNTError(ApiMessage.Status); 186*c2c66affSColin Finck Result = FALSE; 187*c2c66affSColin Finck } 188*c2c66affSColin Finck else 189*c2c66affSColin Finck { 190*c2c66affSColin Finck if (! (dwFlags & DDD_NO_BROADCAST_SYSTEM) && 191*c2c66affSColin Finck DeviceUpcaseNameU.Length == 2 * sizeof(WCHAR) && 192*c2c66affSColin Finck DeviceUpcaseNameU.Buffer[1] == L':' && 193*c2c66affSColin Finck ( (DeviceUpcaseNameU.Buffer[0] - L'A') < 26 )) 194*c2c66affSColin Finck { 195*c2c66affSColin Finck hUser32 = LoadLibraryA("user32.dll"); 196*c2c66affSColin Finck if (hUser32) 197*c2c66affSColin Finck { 198*c2c66affSColin Finck BSM_ptr = (BSM_type) 199*c2c66affSColin Finck GetProcAddress(hUser32, "BroadcastSystemMessageW"); 200*c2c66affSColin Finck if (BSM_ptr) 201*c2c66affSColin Finck { 202*c2c66affSColin Finck dwRecipients = BSM_APPLICATIONS; 203*c2c66affSColin Finck dbcv.dbcv_size = sizeof(DEV_BROADCAST_VOLUME); 204*c2c66affSColin Finck dbcv.dbcv_devicetype = DBT_DEVTYP_VOLUME; 205*c2c66affSColin Finck dbcv.dbcv_reserved = 0; 206*c2c66affSColin Finck dbcv.dbcv_unitmask |= 207*c2c66affSColin Finck (1 << (DeviceUpcaseNameU.Buffer[0] - L'A')); 208*c2c66affSColin Finck dbcv.dbcv_flags = DBTF_NET; 209*c2c66affSColin Finck (void) BSM_ptr(BSF_SENDNOTIFYMESSAGE | BSF_FLUSHDISK, 210*c2c66affSColin Finck &dwRecipients, 211*c2c66affSColin Finck WM_DEVICECHANGE, 212*c2c66affSColin Finck (WPARAM)DBT_DEVICEARRIVAL, 213*c2c66affSColin Finck (LPARAM)&dbcv); 214*c2c66affSColin Finck } 215*c2c66affSColin Finck FreeLibrary(hUser32); 216*c2c66affSColin Finck } 217*c2c66affSColin Finck } 218*c2c66affSColin Finck } 219*c2c66affSColin Finck } 220*c2c66affSColin Finck 221*c2c66affSColin Finck if (NtTargetPathU.Buffer && 222*c2c66affSColin Finck NtTargetPathU.Buffer != lpTargetPath) 223*c2c66affSColin Finck { 224*c2c66affSColin Finck RtlFreeHeap(RtlGetProcessHeap(), 225*c2c66affSColin Finck 0, 226*c2c66affSColin Finck NtTargetPathU.Buffer); 227*c2c66affSColin Finck } 228*c2c66affSColin Finck RtlFreeUnicodeString(&DeviceUpcaseNameU); 229*c2c66affSColin Finck return Result; 230*c2c66affSColin Finck } 231*c2c66affSColin Finck 232*c2c66affSColin Finck 233*c2c66affSColin Finck /* 234*c2c66affSColin Finck * @implemented 235*c2c66affSColin Finck */ 236*c2c66affSColin Finck DWORD 237*c2c66affSColin Finck WINAPI 238*c2c66affSColin Finck QueryDosDeviceA( 239*c2c66affSColin Finck LPCSTR lpDeviceName, 240*c2c66affSColin Finck LPSTR lpTargetPath, 241*c2c66affSColin Finck DWORD ucchMax 242*c2c66affSColin Finck ) 243*c2c66affSColin Finck { 244*c2c66affSColin Finck UNICODE_STRING DeviceNameU; 245*c2c66affSColin Finck UNICODE_STRING TargetPathU; 246*c2c66affSColin Finck ANSI_STRING TargetPathA; 247*c2c66affSColin Finck DWORD Length; 248*c2c66affSColin Finck DWORD CurrentLength; 249*c2c66affSColin Finck PWCHAR Buffer; 250*c2c66affSColin Finck 251*c2c66affSColin Finck if (lpDeviceName) 252*c2c66affSColin Finck { 253*c2c66affSColin Finck if (!RtlCreateUnicodeStringFromAsciiz(&DeviceNameU, 254*c2c66affSColin Finck (LPSTR)lpDeviceName)) 255*c2c66affSColin Finck { 256*c2c66affSColin Finck SetLastError(ERROR_NOT_ENOUGH_MEMORY); 257*c2c66affSColin Finck return 0; 258*c2c66affSColin Finck } 259*c2c66affSColin Finck } 260*c2c66affSColin Finck Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, ucchMax * sizeof(WCHAR)); 261*c2c66affSColin Finck if (Buffer == NULL) 262*c2c66affSColin Finck { 263*c2c66affSColin Finck if (lpDeviceName) 264*c2c66affSColin Finck { 265*c2c66affSColin Finck RtlFreeHeap(RtlGetProcessHeap(), 0, DeviceNameU.Buffer); 266*c2c66affSColin Finck } 267*c2c66affSColin Finck SetLastError(ERROR_NOT_ENOUGH_MEMORY); 268*c2c66affSColin Finck return 0; 269*c2c66affSColin Finck } 270*c2c66affSColin Finck 271*c2c66affSColin Finck Length = QueryDosDeviceW(lpDeviceName ? DeviceNameU.Buffer : NULL, 272*c2c66affSColin Finck Buffer, ucchMax); 273*c2c66affSColin Finck if (Length != 0) 274*c2c66affSColin Finck { 275*c2c66affSColin Finck TargetPathA.Buffer = lpTargetPath; 276*c2c66affSColin Finck TargetPathU.Buffer = Buffer; 277*c2c66affSColin Finck ucchMax = Length; 278*c2c66affSColin Finck 279*c2c66affSColin Finck while (ucchMax) 280*c2c66affSColin Finck { 281*c2c66affSColin Finck CurrentLength = min(ucchMax, MAXUSHORT / 2); 282*c2c66affSColin Finck TargetPathU.MaximumLength = TargetPathU.Length = (USHORT)CurrentLength * sizeof(WCHAR); 283*c2c66affSColin Finck 284*c2c66affSColin Finck TargetPathA.Length = 0; 285*c2c66affSColin Finck TargetPathA.MaximumLength = (USHORT)CurrentLength; 286*c2c66affSColin Finck 287*c2c66affSColin Finck RtlUnicodeStringToAnsiString(&TargetPathA, &TargetPathU, FALSE); 288*c2c66affSColin Finck ucchMax -= CurrentLength; 289*c2c66affSColin Finck TargetPathA.Buffer += TargetPathA.Length; 290*c2c66affSColin Finck TargetPathU.Buffer += TargetPathU.Length / sizeof(WCHAR); 291*c2c66affSColin Finck } 292*c2c66affSColin Finck } 293*c2c66affSColin Finck 294*c2c66affSColin Finck RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); 295*c2c66affSColin Finck if (lpDeviceName) 296*c2c66affSColin Finck { 297*c2c66affSColin Finck RtlFreeHeap(RtlGetProcessHeap(), 0, DeviceNameU.Buffer); 298*c2c66affSColin Finck } 299*c2c66affSColin Finck return Length; 300*c2c66affSColin Finck } 301*c2c66affSColin Finck 302*c2c66affSColin Finck 303*c2c66affSColin Finck /* 304*c2c66affSColin Finck * @implemented 305*c2c66affSColin Finck */ 306*c2c66affSColin Finck DWORD 307*c2c66affSColin Finck WINAPI 308*c2c66affSColin Finck QueryDosDeviceW( 309*c2c66affSColin Finck LPCWSTR lpDeviceName, 310*c2c66affSColin Finck LPWSTR lpTargetPath, 311*c2c66affSColin Finck DWORD ucchMax 312*c2c66affSColin Finck ) 313*c2c66affSColin Finck { 314*c2c66affSColin Finck POBJECT_DIRECTORY_INFORMATION DirInfo; 315*c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes; 316*c2c66affSColin Finck UNICODE_STRING UnicodeString; 317*c2c66affSColin Finck HANDLE DirectoryHandle; 318*c2c66affSColin Finck HANDLE DeviceHandle; 319*c2c66affSColin Finck ULONG ReturnLength; 320*c2c66affSColin Finck ULONG NameLength; 321*c2c66affSColin Finck ULONG Length; 322*c2c66affSColin Finck ULONG Context; 323*c2c66affSColin Finck BOOLEAN RestartScan; 324*c2c66affSColin Finck NTSTATUS Status; 325*c2c66affSColin Finck UCHAR Buffer[512]; 326*c2c66affSColin Finck PWSTR Ptr; 327*c2c66affSColin Finck 328*c2c66affSColin Finck /* Open the '\??' directory */ 329*c2c66affSColin Finck RtlInitUnicodeString(&UnicodeString, L"\\??"); 330*c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 331*c2c66affSColin Finck &UnicodeString, 332*c2c66affSColin Finck OBJ_CASE_INSENSITIVE, 333*c2c66affSColin Finck NULL, 334*c2c66affSColin Finck NULL); 335*c2c66affSColin Finck Status = NtOpenDirectoryObject(&DirectoryHandle, 336*c2c66affSColin Finck DIRECTORY_QUERY, 337*c2c66affSColin Finck &ObjectAttributes); 338*c2c66affSColin Finck if (!NT_SUCCESS(Status)) 339*c2c66affSColin Finck { 340*c2c66affSColin Finck WARN("NtOpenDirectoryObject() failed (Status %lx)\n", Status); 341*c2c66affSColin Finck BaseSetLastNTError(Status); 342*c2c66affSColin Finck return 0; 343*c2c66affSColin Finck } 344*c2c66affSColin Finck 345*c2c66affSColin Finck Length = 0; 346*c2c66affSColin Finck 347*c2c66affSColin Finck if (lpDeviceName != NULL) 348*c2c66affSColin Finck { 349*c2c66affSColin Finck /* Open the lpDeviceName link object */ 350*c2c66affSColin Finck RtlInitUnicodeString(&UnicodeString, (PWSTR)lpDeviceName); 351*c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 352*c2c66affSColin Finck &UnicodeString, 353*c2c66affSColin Finck OBJ_CASE_INSENSITIVE, 354*c2c66affSColin Finck DirectoryHandle, 355*c2c66affSColin Finck NULL); 356*c2c66affSColin Finck Status = NtOpenSymbolicLinkObject(&DeviceHandle, 357*c2c66affSColin Finck SYMBOLIC_LINK_QUERY, 358*c2c66affSColin Finck &ObjectAttributes); 359*c2c66affSColin Finck if (!NT_SUCCESS(Status)) 360*c2c66affSColin Finck { 361*c2c66affSColin Finck WARN("NtOpenSymbolicLinkObject() failed (Status %lx)\n", Status); 362*c2c66affSColin Finck NtClose(DirectoryHandle); 363*c2c66affSColin Finck BaseSetLastNTError(Status); 364*c2c66affSColin Finck return 0; 365*c2c66affSColin Finck } 366*c2c66affSColin Finck 367*c2c66affSColin Finck /* Query link target */ 368*c2c66affSColin Finck UnicodeString.Length = 0; 369*c2c66affSColin Finck UnicodeString.MaximumLength = (USHORT)ucchMax * sizeof(WCHAR); 370*c2c66affSColin Finck UnicodeString.Buffer = lpTargetPath; 371*c2c66affSColin Finck 372*c2c66affSColin Finck ReturnLength = 0; 373*c2c66affSColin Finck Status = NtQuerySymbolicLinkObject(DeviceHandle, 374*c2c66affSColin Finck &UnicodeString, 375*c2c66affSColin Finck &ReturnLength); 376*c2c66affSColin Finck NtClose(DeviceHandle); 377*c2c66affSColin Finck NtClose(DirectoryHandle); 378*c2c66affSColin Finck if (!NT_SUCCESS(Status)) 379*c2c66affSColin Finck { 380*c2c66affSColin Finck WARN("NtQuerySymbolicLinkObject() failed (Status %lx)\n", Status); 381*c2c66affSColin Finck BaseSetLastNTError(Status); 382*c2c66affSColin Finck return 0; 383*c2c66affSColin Finck } 384*c2c66affSColin Finck 385*c2c66affSColin Finck TRACE("ReturnLength: %lu\n", ReturnLength); 386*c2c66affSColin Finck TRACE("TargetLength: %hu\n", UnicodeString.Length); 387*c2c66affSColin Finck TRACE("Target: '%wZ'\n", &UnicodeString); 388*c2c66affSColin Finck 389*c2c66affSColin Finck Length = UnicodeString.Length / sizeof(WCHAR); 390*c2c66affSColin Finck if (Length < ucchMax) 391*c2c66affSColin Finck { 392*c2c66affSColin Finck /* Append null-character */ 393*c2c66affSColin Finck lpTargetPath[Length] = UNICODE_NULL; 394*c2c66affSColin Finck Length++; 395*c2c66affSColin Finck } 396*c2c66affSColin Finck else 397*c2c66affSColin Finck { 398*c2c66affSColin Finck TRACE("Buffer is too small\n"); 399*c2c66affSColin Finck BaseSetLastNTError(STATUS_BUFFER_TOO_SMALL); 400*c2c66affSColin Finck return 0; 401*c2c66affSColin Finck } 402*c2c66affSColin Finck } 403*c2c66affSColin Finck else 404*c2c66affSColin Finck { 405*c2c66affSColin Finck RestartScan = TRUE; 406*c2c66affSColin Finck Context = 0; 407*c2c66affSColin Finck Ptr = lpTargetPath; 408*c2c66affSColin Finck DirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer; 409*c2c66affSColin Finck 410*c2c66affSColin Finck while (TRUE) 411*c2c66affSColin Finck { 412*c2c66affSColin Finck Status = NtQueryDirectoryObject(DirectoryHandle, 413*c2c66affSColin Finck Buffer, 414*c2c66affSColin Finck sizeof(Buffer), 415*c2c66affSColin Finck TRUE, 416*c2c66affSColin Finck RestartScan, 417*c2c66affSColin Finck &Context, 418*c2c66affSColin Finck &ReturnLength); 419*c2c66affSColin Finck if (!NT_SUCCESS(Status)) 420*c2c66affSColin Finck { 421*c2c66affSColin Finck if (Status == STATUS_NO_MORE_ENTRIES) 422*c2c66affSColin Finck { 423*c2c66affSColin Finck /* Terminate the buffer */ 424*c2c66affSColin Finck *Ptr = UNICODE_NULL; 425*c2c66affSColin Finck Length++; 426*c2c66affSColin Finck 427*c2c66affSColin Finck Status = STATUS_SUCCESS; 428*c2c66affSColin Finck } 429*c2c66affSColin Finck else 430*c2c66affSColin Finck { 431*c2c66affSColin Finck Length = 0; 432*c2c66affSColin Finck } 433*c2c66affSColin Finck BaseSetLastNTError(Status); 434*c2c66affSColin Finck break; 435*c2c66affSColin Finck } 436*c2c66affSColin Finck 437*c2c66affSColin Finck if (!wcscmp(DirInfo->TypeName.Buffer, L"SymbolicLink")) 438*c2c66affSColin Finck { 439*c2c66affSColin Finck TRACE("Name: '%wZ'\n", &DirInfo->Name); 440*c2c66affSColin Finck 441*c2c66affSColin Finck NameLength = DirInfo->Name.Length / sizeof(WCHAR); 442*c2c66affSColin Finck if (Length + NameLength + 1 >= ucchMax) 443*c2c66affSColin Finck { 444*c2c66affSColin Finck Length = 0; 445*c2c66affSColin Finck BaseSetLastNTError(STATUS_BUFFER_TOO_SMALL); 446*c2c66affSColin Finck break; 447*c2c66affSColin Finck } 448*c2c66affSColin Finck 449*c2c66affSColin Finck memcpy(Ptr, DirInfo->Name.Buffer, DirInfo->Name.Length); 450*c2c66affSColin Finck Ptr += NameLength; 451*c2c66affSColin Finck Length += NameLength; 452*c2c66affSColin Finck *Ptr = UNICODE_NULL; 453*c2c66affSColin Finck Ptr++; 454*c2c66affSColin Finck Length++; 455*c2c66affSColin Finck } 456*c2c66affSColin Finck 457*c2c66affSColin Finck RestartScan = FALSE; 458*c2c66affSColin Finck } 459*c2c66affSColin Finck 460*c2c66affSColin Finck NtClose(DirectoryHandle); 461*c2c66affSColin Finck } 462*c2c66affSColin Finck 463*c2c66affSColin Finck return Length; 464*c2c66affSColin Finck } 465*c2c66affSColin Finck 466*c2c66affSColin Finck /* EOF */ 467