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