Fixed LARGE_INTEGER handling
[reactos.git] / reactos / lib / kernel32 / file / volume.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/file/volume.c
5 * PURPOSE: File volume functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7 * Erik Bos, Alexandre Julliard :
8 * DRIVE_IsValid, GetLogicalDriveStringsA,
9 * GetLogicalDriveStringsW, GetLogicalDrives
10 * UPDATE HISTORY:
11 * Created 01/11/98
12 */
13 //WINE copyright notice:
14 /*
15 * DOS drives handling functions
16 *
17 * Copyright 1993 Erik Bos
18 * Copyright 1996 Alexandre Julliard
19 */
20
21 #include <windows.h>
22 #include <ddk/ntddk.h>
23 #include <wchar.h>
24 #include <string.h>
25
26 #define NDEBUG
27 #include <kernel32/kernel32.h>
28
29
30 #define MAX_DOS_DRIVES 26
31
32
33 int DRIVE_IsValid( int drive )
34 {
35 char Drives[4];
36 Drives[0] = 'A';
37 Drives[1] = ':';
38 Drives[2] = '\\';
39 Drives[3] = 0;
40
41 Drives[0] = 'A' + drive -1;
42 if ((drive < 0) || (drive >= MAX_DOS_DRIVES)) return 0;
43 if ( CreateFileA(Drives,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS|FILE_ATTRIBUTE_DIRECTORY,NULL) == -1 ) {
44 return 0;
45 }
46 return drive;
47
48 }
49
50
51
52
53
54 DWORD
55 STDCALL
56 GetLogicalDriveStringsA(
57 DWORD nBufferLength,
58 LPSTR lpBuffer
59 )
60 {
61 int drive, count;
62
63 for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
64 if (DRIVE_IsValid(drive)) count++;
65 if (count * 4 * sizeof(char) <= nBufferLength)
66 {
67 LPSTR p = lpBuffer;
68 for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
69 if (DRIVE_IsValid(drive))
70 {
71 *p++ = 'A' + drive;
72 *p++ = ':';
73 *p++ = '\\';
74 *p++ = '\0';
75 }
76 *p = '\0';
77 }
78 return count * 4 * sizeof(char);
79 }
80
81
82 DWORD
83 STDCALL
84 GetLogicalDriveStringsW(
85 DWORD nBufferLength,
86 LPWSTR lpBuffer
87 )
88 {
89 int drive, count;
90
91 for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
92 if (DRIVE_IsValid(drive)) count++;
93 if (count * 4 * sizeof(WCHAR) <= nBufferLength)
94 {
95 LPWSTR p = lpBuffer;
96 for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
97 if (DRIVE_IsValid(drive))
98 {
99 *p++ = (WCHAR)('A' + drive);
100 *p++ = (WCHAR)':';
101 *p++ = (WCHAR)'\\';
102 *p++ = (WCHAR)'\0';
103 }
104 *p = (WCHAR)'\0';
105 }
106 return count * 4 * sizeof(WCHAR);
107 }
108
109
110 DWORD
111 STDCALL
112 GetLogicalDrives(VOID)
113 {
114 DWORD ret = 0;
115 int drive;
116
117 for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
118 if (DRIVE_IsValid(drive)) ret |= (1 << drive);
119 return ret;
120 }
121
122
123
124 WINBOOL
125 STDCALL
126 GetDiskFreeSpaceA(
127 LPCSTR lpRootPathName,
128 LPDWORD lpSectorsPerCluster,
129 LPDWORD lpBytesPerSector,
130 LPDWORD lpNumberOfFreeClusters,
131 LPDWORD lpTotalNumberOfClusters
132 )
133 {
134 ULONG i;
135 WCHAR RootPathNameW[MAX_PATH];
136 i = 0;
137 while ((*lpRootPathName)!=0 && i < MAX_PATH)
138 {
139 RootPathNameW[i] = *lpRootPathName;
140 lpRootPathName++;
141 i++;
142 }
143 RootPathNameW[i] = 0;
144 return GetDiskFreeSpaceW(RootPathNameW,lpSectorsPerCluster, lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters );
145 }
146
147 WINBOOL
148 STDCALL
149 GetDiskFreeSpaceW(
150 LPCWSTR lpRootPathName,
151 LPDWORD lpSectorsPerCluster,
152 LPDWORD lpBytesPerSector,
153 LPDWORD lpNumberOfFreeClusters,
154 LPDWORD lpTotalNumberOfClusters
155 )
156 {
157 FILE_FS_SIZE_INFORMATION FileFsSize;
158 IO_STATUS_BLOCK IoStatusBlock;
159 HANDLE hFile;
160 NTSTATUS errCode;
161
162 hFile = CreateFileW(
163 lpRootPathName,
164 GENERIC_READ,
165 FILE_SHARE_READ,
166 NULL,
167 OPEN_EXISTING,
168 FILE_ATTRIBUTE_NORMAL,
169 NULL
170 );
171
172 errCode = NtQueryVolumeInformationFile(hFile,&IoStatusBlock,&FileFsSize, sizeof(FILE_FS_SIZE_INFORMATION),FileFsSizeInformation);
173 if ( !NT_SUCCESS(errCode) ) {
174 CloseHandle(hFile);
175 SetLastError(RtlNtStatusToDosError(errCode));
176 return FALSE;
177 }
178
179 *lpBytesPerSector = FileFsSize.BytesPerSector;
180 *lpSectorsPerCluster = FileFsSize.SectorsPerAllocationUnit;
181 *lpNumberOfFreeClusters = FileFsSize.AvailableAllocationUnits.LowPart;
182 *lpTotalNumberOfClusters = FileFsSize.TotalAllocationUnits.LowPart;
183 CloseHandle(hFile);
184 return TRUE;
185 }
186
187 UINT
188 STDCALL
189 GetDriveTypeA(
190 LPCSTR lpRootPathName
191 )
192 {
193 ULONG i;
194 WCHAR RootPathNameW[MAX_PATH];
195 i = 0;
196 while ((*lpRootPathName)!=0 && i < MAX_PATH)
197 {
198 RootPathNameW[i] = *lpRootPathName;
199 lpRootPathName++;
200 i++;
201 }
202 RootPathNameW[i] = 0;
203 return GetDriveTypeW(RootPathNameW);
204 }
205
206 UINT
207 STDCALL
208 GetDriveTypeW(
209 LPCWSTR lpRootPathName
210 )
211 {
212 FILE_FS_DEVICE_INFORMATION FileFsDevice;
213 IO_STATUS_BLOCK IoStatusBlock;
214
215 HANDLE hFile;
216 NTSTATUS errCode;
217
218 hFile = CreateFileW(
219 lpRootPathName,
220 GENERIC_ALL,
221 FILE_SHARE_READ|FILE_SHARE_WRITE,
222 NULL,
223 OPEN_EXISTING,
224 FILE_ATTRIBUTE_NORMAL,
225 NULL
226 );
227
228 errCode = NtQueryVolumeInformationFile(hFile,&IoStatusBlock,&FileFsDevice, sizeof(FILE_FS_DEVICE_INFORMATION),FileFsDeviceInformation);
229 if ( !NT_SUCCESS(errCode) ) {
230 CloseHandle(hFile);
231 SetLastError(RtlNtStatusToDosError(errCode));
232 return 0;
233 }
234 CloseHandle(hFile);
235 return (UINT)FileFsDevice.DeviceType;
236
237
238
239 }
240
241 WINBOOL
242 STDCALL
243 GetVolumeInformationA(
244 LPCSTR lpRootPathName,
245 LPSTR lpVolumeNameBuffer,
246 DWORD nVolumeNameSize,
247 LPDWORD lpVolumeSerialNumber,
248 LPDWORD lpMaximumComponentLength,
249 LPDWORD lpFileSystemFlags,
250 LPSTR lpFileSystemNameBuffer,
251 DWORD nFileSystemNameSize
252 )
253 {
254 ULONG i;
255 WCHAR RootPathNameW[MAX_PATH];
256 WCHAR VolumeNameBufferW[MAX_PATH];
257 WCHAR FileSystemNameBufferW[MAX_PATH];
258
259
260 i = 0;
261 while ((*lpRootPathName)!=0 && i < MAX_PATH)
262 {
263 RootPathNameW[i] = *lpRootPathName;
264 lpRootPathName++;
265 i++;
266 }
267 RootPathNameW[i] = 0;
268
269 if ( GetVolumeInformationW(RootPathNameW,
270 VolumeNameBufferW,
271 nVolumeNameSize,
272 lpVolumeSerialNumber,
273 lpMaximumComponentLength,
274 lpFileSystemFlags,
275 FileSystemNameBufferW,
276 nFileSystemNameSize ) ) {
277 for(i=0;i<nVolumeNameSize;i++)
278 lpVolumeNameBuffer[i] = (CHAR)VolumeNameBufferW[i];
279
280 for(i=0;i<nFileSystemNameSize;i++)
281 lpFileSystemNameBuffer[i] = (CHAR)FileSystemNameBufferW[i];
282
283 return TRUE;
284 }
285 return FALSE;
286
287 }
288
289
290
291
292 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
293
294 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
295
296
297 WINBOOL
298 STDCALL
299 GetVolumeInformationW(
300 LPCWSTR lpRootPathName,
301 LPWSTR lpVolumeNameBuffer,
302 DWORD nVolumeNameSize,
303 LPDWORD lpVolumeSerialNumber,
304 LPDWORD lpMaximumComponentLength,
305 LPDWORD lpFileSystemFlags,
306 LPWSTR lpFileSystemNameBuffer,
307 DWORD nFileSystemNameSize
308 )
309 {
310 PFILE_FS_VOLUME_INFORMATION FileFsVolume;
311 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute;
312 IO_STATUS_BLOCK IoStatusBlock;
313 USHORT Buffer[FS_VOLUME_BUFFER_SIZE];
314 USHORT Buffer2[FS_ATTRIBUTE_BUFFER_SIZE];
315
316 HANDLE hFile;
317 NTSTATUS errCode;
318
319 FileFsVolume = (PFILE_FS_VOLUME_INFORMATION)Buffer;
320 FileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer2;
321
322 DPRINT("FileFsVolume %p\n", FileFsVolume);
323 DPRINT("FileFsAttribute %p\n", FileFsAttribute);
324
325 hFile = CreateFileW(lpRootPathName,
326 FILE_READ_ATTRIBUTES,
327 FILE_SHARE_READ|FILE_SHARE_WRITE,
328 NULL,
329 OPEN_EXISTING,
330 FILE_ATTRIBUTE_NORMAL,
331 NULL);
332
333 DPRINT("hFile: %x\n", hFile);
334 errCode = NtQueryVolumeInformationFile(hFile,
335 &IoStatusBlock,
336 FileFsVolume,
337 FS_VOLUME_BUFFER_SIZE,
338 FileFsVolumeInformation);
339 if ( !NT_SUCCESS(errCode) ) {
340 DPRINT("Status: %x\n", errCode);
341 CloseHandle(hFile);
342 SetLastError(RtlNtStatusToDosError(errCode));
343 return FALSE;
344 }
345
346 if (lpVolumeSerialNumber)
347 *lpVolumeSerialNumber = FileFsVolume->VolumeSerialNumber;
348
349 if (lpVolumeNameBuffer)
350 wcsncpy(lpVolumeNameBuffer, FileFsVolume->VolumeLabel,min(nVolumeNameSize,MAX_PATH));
351
352 errCode = NtQueryVolumeInformationFile(hFile,&IoStatusBlock,FileFsAttribute, FS_ATTRIBUTE_BUFFER_SIZE,FileFsAttributeInformation);
353 if ( !NT_SUCCESS(errCode) ) {
354 DPRINT("Status: %x\n", errCode);
355 CloseHandle(hFile);
356 SetLastError(RtlNtStatusToDosError(errCode));
357 return FALSE;
358 }
359
360 if (lpFileSystemFlags)
361 *lpFileSystemFlags = FileFsAttribute->FileSystemAttributes;
362 if (lpMaximumComponentLength)
363 *lpMaximumComponentLength = FileFsAttribute->MaximumComponentNameLength;
364 if (lpFileSystemNameBuffer)
365 wcsncpy(lpFileSystemNameBuffer, FileFsAttribute->FileSystemName,min(nFileSystemNameSize,MAX_PATH));
366
367 CloseHandle(hFile);
368 return TRUE;
369 }
370
371 WINBOOL
372 STDCALL
373 SetVolumeLabelA(
374 LPCSTR lpRootPathName,
375 LPCSTR lpVolumeName
376 )
377 {
378 WCHAR RootPathNameW[MAX_PATH];
379 WCHAR VolumeNameW[MAX_PATH];
380 UINT i;
381
382 i = 0;
383 while ((*lpRootPathName)!=0 && i < MAX_PATH)
384 {
385 RootPathNameW[i] = *lpRootPathName;
386 lpRootPathName++;
387 i++;
388 }
389 RootPathNameW[i] = 0;
390
391 i = 0;
392 while ((*lpVolumeName)!=0 && i < MAX_PATH)
393 {
394 VolumeNameW[i] = *lpVolumeName;
395 lpVolumeName++;
396 i++;
397 }
398 VolumeNameW[i] = 0;
399 return SetVolumeLabelW(RootPathNameW,VolumeNameW);
400 }
401
402 WINBOOL
403 STDCALL
404 SetVolumeLabelW(
405 LPCWSTR lpRootPathName,
406 LPCWSTR lpVolumeName
407 )
408 {
409 return FALSE;
410 }