2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/kernel32/client/file/disk.c
5 * PURPOSE: Disk and Drive functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7 * Erik Bos, Alexandre Julliard :
8 * GetLogicalDriveStringsA,
9 * GetLogicalDriveStringsW, GetLogicalDrives
13 //WINE copyright notice:
15 * DOS drives handling functions
17 * Copyright 1993 Erik Bos
18 * Copyright 1996 Alexandre Julliard
24 DEBUG_CHANNEL(kernel32file
);
26 #define MAX_DOS_DRIVES 26
27 HANDLE WINAPI
InternalOpenDirW(IN LPCWSTR DirName
, IN BOOLEAN Write
);
32 /* Synced to Wine-2008/12/28 */
35 GetLogicalDriveStringsA(IN DWORD nBufferLength
,
42 dwDriveMap
= GetLogicalDrives();
44 for (drive
= count
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
46 if (dwDriveMap
& (1<<drive
))
51 if ((count
* 4) + 1 > nBufferLength
) return ((count
* 4) + 1);
55 for (drive
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
56 if (dwDriveMap
& (1<<drive
))
58 *p
++ = 'A' + (UCHAR
)drive
;
71 /* Synced to Wine-2008/12/28 */
74 GetLogicalDriveStringsW(IN DWORD nBufferLength
,
81 dwDriveMap
= GetLogicalDrives();
83 for (drive
= count
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
85 if (dwDriveMap
& (1<<drive
))
89 if ((count
* 4) + 1 > nBufferLength
) return ((count
* 4) + 1);
92 for (drive
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
93 if (dwDriveMap
& (1<<drive
))
95 *p
++ = (WCHAR
)('A' + drive
);
108 /* Synced to Wine-? */
111 GetLogicalDrives(VOID
)
114 PROCESS_DEVICEMAP_INFORMATION ProcessDeviceMapInfo
;
116 /* Get the Device Map for this Process */
117 Status
= NtQueryInformationProcess(NtCurrentProcess(),
119 &ProcessDeviceMapInfo
,
120 sizeof(ProcessDeviceMapInfo
),
123 /* Return the Drive Map */
124 if (!NT_SUCCESS(Status
))
126 BaseSetLastNTError(Status
);
130 return ProcessDeviceMapInfo
.Query
.DriveMap
;
138 GetDiskFreeSpaceA(IN LPCSTR lpRootPathName
,
139 OUT LPDWORD lpSectorsPerCluster
,
140 OUT LPDWORD lpBytesPerSector
,
141 OUT LPDWORD lpNumberOfFreeClusters
,
142 OUT LPDWORD lpTotalNumberOfClusters
)
144 PWCHAR RootPathNameW
=NULL
;
148 if (!(RootPathNameW
= FilenameA2W(lpRootPathName
, FALSE
)))
152 return GetDiskFreeSpaceW (RootPathNameW
,
155 lpNumberOfFreeClusters
,
156 lpTotalNumberOfClusters
);
164 GetDiskFreeSpaceW(IN LPCWSTR lpRootPathName
,
165 OUT LPDWORD lpSectorsPerCluster
,
166 OUT LPDWORD lpBytesPerSector
,
167 OUT LPDWORD lpNumberOfFreeClusters
,
168 OUT LPDWORD lpTotalNumberOfClusters
)
170 FILE_FS_SIZE_INFORMATION FileFsSize
;
171 IO_STATUS_BLOCK IoStatusBlock
;
172 WCHAR RootPathName
[MAX_PATH
];
178 wcsncpy (RootPathName
, lpRootPathName
, 3);
182 GetCurrentDirectoryW (MAX_PATH
, RootPathName
);
186 hFile
= InternalOpenDirW(RootPathName
, FALSE
);
187 if (INVALID_HANDLE_VALUE
== hFile
)
189 SetLastError(ERROR_PATH_NOT_FOUND
);
193 errCode
= NtQueryVolumeInformationFile(hFile
,
196 sizeof(FILE_FS_SIZE_INFORMATION
),
197 FileFsSizeInformation
);
198 if (!NT_SUCCESS(errCode
))
201 BaseSetLastNTError (errCode
);
205 if (lpSectorsPerCluster
)
206 *lpSectorsPerCluster
= FileFsSize
.SectorsPerAllocationUnit
;
207 if (lpBytesPerSector
)
208 *lpBytesPerSector
= FileFsSize
.BytesPerSector
;
209 if (lpNumberOfFreeClusters
)
210 *lpNumberOfFreeClusters
= FileFsSize
.AvailableAllocationUnits
.u
.LowPart
;
211 if (lpTotalNumberOfClusters
)
212 *lpTotalNumberOfClusters
= FileFsSize
.TotalAllocationUnits
.u
.LowPart
;
223 GetDiskFreeSpaceExA(IN LPCSTR lpDirectoryName OPTIONAL
,
224 OUT PULARGE_INTEGER lpFreeBytesAvailableToCaller
,
225 OUT PULARGE_INTEGER lpTotalNumberOfBytes
,
226 OUT PULARGE_INTEGER lpTotalNumberOfFreeBytes
)
228 PWCHAR DirectoryNameW
=NULL
;
232 if (!(DirectoryNameW
= FilenameA2W(lpDirectoryName
, FALSE
)))
236 return GetDiskFreeSpaceExW (DirectoryNameW
,
237 lpFreeBytesAvailableToCaller
,
238 lpTotalNumberOfBytes
,
239 lpTotalNumberOfFreeBytes
);
247 GetDiskFreeSpaceExW(IN LPCWSTR lpDirectoryName OPTIONAL
,
248 OUT PULARGE_INTEGER lpFreeBytesAvailableToCaller
,
249 OUT PULARGE_INTEGER lpTotalNumberOfBytes
,
250 OUT PULARGE_INTEGER lpTotalNumberOfFreeBytes
)
254 FILE_FS_SIZE_INFORMATION FsSize
;
255 FILE_FS_FULL_SIZE_INFORMATION FsFullSize
;
257 IO_STATUS_BLOCK IoStatusBlock
;
258 ULARGE_INTEGER BytesPerCluster
;
262 if (lpDirectoryName
== NULL
)
263 lpDirectoryName
= L
"\\";
265 hFile
= InternalOpenDirW(lpDirectoryName
, FALSE
);
266 if (INVALID_HANDLE_VALUE
== hFile
)
271 if (lpFreeBytesAvailableToCaller
!= NULL
|| lpTotalNumberOfBytes
!= NULL
)
273 /* To get the free space available to the user associated with the
274 current thread, try FileFsFullSizeInformation. If this is not
275 supported by the file system, fall back to FileFsSize */
277 Status
= NtQueryVolumeInformationFile(hFile
,
280 sizeof(FsInfo
.FsFullSize
),
281 FileFsFullSizeInformation
);
283 if (NT_SUCCESS(Status
))
285 /* Close the handle before returning data
286 to avoid a handle leak in case of a fault! */
289 BytesPerCluster
.QuadPart
=
290 FsInfo
.FsFullSize
.BytesPerSector
* FsInfo
.FsFullSize
.SectorsPerAllocationUnit
;
292 if (lpFreeBytesAvailableToCaller
!= NULL
)
294 lpFreeBytesAvailableToCaller
->QuadPart
=
295 BytesPerCluster
.QuadPart
* FsInfo
.FsFullSize
.CallerAvailableAllocationUnits
.QuadPart
;
298 if (lpTotalNumberOfBytes
!= NULL
)
300 lpTotalNumberOfBytes
->QuadPart
=
301 BytesPerCluster
.QuadPart
* FsInfo
.FsFullSize
.TotalAllocationUnits
.QuadPart
;
304 if (lpTotalNumberOfFreeBytes
!= NULL
)
306 lpTotalNumberOfFreeBytes
->QuadPart
=
307 BytesPerCluster
.QuadPart
* FsInfo
.FsFullSize
.ActualAvailableAllocationUnits
.QuadPart
;
314 Status
= NtQueryVolumeInformationFile(hFile
,
317 sizeof(FsInfo
.FsSize
),
318 FileFsSizeInformation
);
320 /* Close the handle before returning data
321 to avoid a handle leak in case of a fault! */
324 if (!NT_SUCCESS(Status
))
326 BaseSetLastNTError (Status
);
330 BytesPerCluster
.QuadPart
=
331 FsInfo
.FsSize
.BytesPerSector
* FsInfo
.FsSize
.SectorsPerAllocationUnit
;
333 if (lpFreeBytesAvailableToCaller
)
335 lpFreeBytesAvailableToCaller
->QuadPart
=
336 BytesPerCluster
.QuadPart
* FsInfo
.FsSize
.AvailableAllocationUnits
.QuadPart
;
339 if (lpTotalNumberOfBytes
)
341 lpTotalNumberOfBytes
->QuadPart
=
342 BytesPerCluster
.QuadPart
* FsInfo
.FsSize
.TotalAllocationUnits
.QuadPart
;
345 if (lpTotalNumberOfFreeBytes
)
347 lpTotalNumberOfFreeBytes
->QuadPart
=
348 BytesPerCluster
.QuadPart
* FsInfo
.FsSize
.AvailableAllocationUnits
.QuadPart
;
359 GetDriveTypeA(IN LPCSTR lpRootPathName
)
361 PWCHAR RootPathNameW
;
364 return GetDriveTypeW(NULL
);
366 if (!(RootPathNameW
= FilenameA2W(lpRootPathName
, FALSE
)))
367 return DRIVE_UNKNOWN
;
369 return GetDriveTypeW(RootPathNameW
);
377 GetDriveTypeW(IN LPCWSTR lpRootPathName
)
379 FILE_FS_DEVICE_INFORMATION FileFsDevice
;
380 OBJECT_ATTRIBUTES ObjectAttributes
;
381 IO_STATUS_BLOCK IoStatusBlock
;
382 UNICODE_STRING PathName
;
385 PWSTR CurrentDir
= NULL
;
390 /* If NULL is passed, use current directory path */
391 DWORD BufferSize
= GetCurrentDirectoryW(0, NULL
);
392 CurrentDir
= HeapAlloc(GetProcessHeap(), 0, BufferSize
* sizeof(WCHAR
));
394 return DRIVE_UNKNOWN
;
395 if (!GetCurrentDirectoryW(BufferSize
, CurrentDir
))
397 HeapFree(GetProcessHeap(), 0, CurrentDir
);
398 return DRIVE_UNKNOWN
;
401 if (wcslen(CurrentDir
) > 3)
404 lpRootPath
= (PCWSTR
)CurrentDir
;
408 TRACE("lpRootPathName: %S\n", lpRootPathName
);
409 lpRootPath
= lpRootPathName
;
412 TRACE("lpRootPath: %S\n", lpRootPath
);
414 if (!RtlDosPathNameToNtPathName_U(lpRootPath
, &PathName
, NULL
, NULL
))
416 if (CurrentDir
!= NULL
)
417 HeapFree(GetProcessHeap(), 0, CurrentDir
);
419 return DRIVE_NO_ROOT_DIR
;
422 TRACE("PathName: %S\n", PathName
.Buffer
);
424 if (CurrentDir
!= NULL
)
425 HeapFree(GetProcessHeap(), 0, CurrentDir
);
427 InitializeObjectAttributes(&ObjectAttributes
,
429 OBJ_CASE_INSENSITIVE
,
433 Status
= NtOpenFile(&FileHandle
,
434 FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
437 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
438 FILE_SYNCHRONOUS_IO_NONALERT
);
439 RtlFreeHeap(RtlGetProcessHeap(), 0, PathName
.Buffer
);
440 if (!NT_SUCCESS(Status
))
441 return DRIVE_NO_ROOT_DIR
; /* According to WINE regression tests */
443 Status
= NtQueryVolumeInformationFile(FileHandle
,
446 sizeof(FILE_FS_DEVICE_INFORMATION
),
447 FileFsDeviceInformation
);
449 if (!NT_SUCCESS(Status
))
454 switch (FileFsDevice
.DeviceType
)
456 case FILE_DEVICE_CD_ROM
:
457 case FILE_DEVICE_CD_ROM_FILE_SYSTEM
:
459 case FILE_DEVICE_VIRTUAL_DISK
:
460 return DRIVE_RAMDISK
;
461 case FILE_DEVICE_NETWORK_FILE_SYSTEM
:
463 case FILE_DEVICE_DISK
:
464 case FILE_DEVICE_DISK_FILE_SYSTEM
:
465 if (FileFsDevice
.Characteristics
& FILE_REMOTE_DEVICE
)
467 if (FileFsDevice
.Characteristics
& FILE_REMOVABLE_MEDIA
)
468 return DRIVE_REMOVABLE
;
472 ERR("Returning DRIVE_UNKNOWN for device type %lu\n", FileFsDevice
.DeviceType
);
474 return DRIVE_UNKNOWN
;