2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/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 IO_STATUS_BLOCK IoStatusBlock
;
386 /* If NULL is passed, use current directory path */
387 DWORD BufferSize
= GetCurrentDirectoryW(0, NULL
);
388 LPWSTR CurrentDir
= HeapAlloc(GetProcessHeap(), 0, BufferSize
* sizeof(WCHAR
));
390 return DRIVE_UNKNOWN
;
391 if (!GetCurrentDirectoryW(BufferSize
, CurrentDir
))
393 HeapFree(GetProcessHeap(), 0, CurrentDir
);
394 return DRIVE_UNKNOWN
;
396 hFile
= InternalOpenDirW(CurrentDir
, FALSE
);
397 HeapFree(GetProcessHeap(), 0, CurrentDir
);
401 hFile
= InternalOpenDirW(lpRootPathName
, FALSE
);
404 if (hFile
== INVALID_HANDLE_VALUE
)
406 return DRIVE_NO_ROOT_DIR
; /* According to WINE regression tests */
409 errCode
= NtQueryVolumeInformationFile (hFile
,
412 sizeof(FILE_FS_DEVICE_INFORMATION
),
413 FileFsDeviceInformation
);
414 if (!NT_SUCCESS(errCode
))
417 BaseSetLastNTError (errCode
);
422 switch (FileFsDevice
.DeviceType
)
424 case FILE_DEVICE_CD_ROM
:
425 case FILE_DEVICE_CD_ROM_FILE_SYSTEM
:
427 case FILE_DEVICE_VIRTUAL_DISK
:
428 return DRIVE_RAMDISK
;
429 case FILE_DEVICE_NETWORK_FILE_SYSTEM
:
431 case FILE_DEVICE_DISK
:
432 case FILE_DEVICE_DISK_FILE_SYSTEM
:
433 if (FileFsDevice
.Characteristics
& FILE_REMOTE_DEVICE
)
435 if (FileFsDevice
.Characteristics
& FILE_REMOVABLE_MEDIA
)
436 return DRIVE_REMOVABLE
;
440 ERR("Returning DRIVE_UNKNOWN for device type %lu\n", FileFsDevice
.DeviceType
);
442 return DRIVE_UNKNOWN
;