source: trunk/src/kernel32/disk.cpp@ 8257

Last change on this file since 8257 was 8257, checked in by bird, 23 years ago

GetDriveType - made it just as strict as WinXP.

File size: 19.7 KB
Line 
1/* $Id: disk.cpp,v 1.33 2002-04-13 06:20:36 bird Exp $ */
2
3/*
4 * Win32 Disk API functions for OS/2
5 *
6 * Copyright 1998 Sander van Leeuwen
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13
14#include <odin.h>
15#include <odinwrap.h>
16#include <os2sel.h>
17
18#include <os2win.h>
19#include <stdlib.h>
20#include <string.h>
21#include "unicode.h"
22#include "oslibdos.h"
23#include "exceptutil.h"
24#include "profile.h"
25
26#define DBG_LOCALLOG DBG_disk
27#include "dbglocal.h"
28
29
30ODINDEBUGCHANNEL(KERNEL32-DISK)
31
32//******************************************************************************
33//******************************************************************************
34BOOL WIN32API SetVolumeLabelA( LPCSTR arg1, LPCSTR arg2)
35{
36 dprintf(("KERNEL32: OS2SetVolumeLabelA\n"));
37 return O32_SetVolumeLabel(arg1, arg2);
38}
39//******************************************************************************
40//******************************************************************************
41BOOL WIN32API SetVolumeLabelW(LPCWSTR lpRootPathName, LPCWSTR lpVolumeName)
42{
43 char *asciiroot, *asciivolname;
44 BOOL rc;
45
46 dprintf(("KERNEL32: OS2SetVolumeLabelW\n"));
47 asciiroot = UnicodeToAsciiString((LPWSTR)lpRootPathName);
48 asciivolname = UnicodeToAsciiString((LPWSTR)lpVolumeName);
49 rc = O32_SetVolumeLabel(asciiroot, asciivolname);
50 FreeAsciiString(asciivolname);
51 FreeAsciiString(asciiroot);
52 return(rc);
53}
54
55//******************************************************************************
56//******************************************************************************
57BOOL WIN32API GetDiskFreeSpaceA(LPCSTR lpszRootPathName, PDWORD lpSectorsPerCluster,
58 PDWORD lpBytesPerSector, PDWORD lpFreeClusters,
59 PDWORD lpClusters)
60{
61 BOOL rc;
62 DWORD dwSectorsPerCluster; // address of sectors per cluster ter
63 DWORD dwBytesPerSector; // address of bytes per sector
64 DWORD dwNumberOfFreeClusters; // address of number of free clusters
65 DWORD dwTotalNumberOfClusters; // address of total number of clusters
66
67 rc = OSLibGetDiskFreeSpace((LPSTR)lpszRootPathName, &dwSectorsPerCluster, &dwBytesPerSector,
68 &dwNumberOfFreeClusters, &dwTotalNumberOfClusters);
69 if(rc)
70 {
71 if (lpSectorsPerCluster!=NULL)
72 *lpSectorsPerCluster = dwSectorsPerCluster;
73 if (lpBytesPerSector!=NULL)
74 *lpBytesPerSector = dwBytesPerSector;
75 if (lpFreeClusters!=NULL)
76 *lpFreeClusters = dwNumberOfFreeClusters;
77 if (lpClusters!=NULL)
78 *lpClusters = dwTotalNumberOfClusters;
79
80 /* CW: Windows Media Player setup complains about wrong clustersize when odin is installed on
81 a TVFS drive. This fakes the clustersizes to 32. The following
82 entry must be present in ODIN.INI:
83
84 [DRIVESPACE]
85 TVFSTOHPFS = 1
86 */
87 if(lpSectorsPerCluster!=NULL)
88 {
89 if(*lpSectorsPerCluster==1024 && PROFILE_GetOdinIniBool("DRIVESPACE","CLUSTERTO32",0))
90 {/* TVFS returns 1024 sectors per cluster */
91 dprintf(("KERNEL32: GetDiskFreeSpaceA, TVFS-Drive detected. Faking clustersize to 32.\n"));
92 *lpSectorsPerCluster=32;
93 if (lpFreeClusters!=NULL)
94 *lpFreeClusters = dwNumberOfFreeClusters<<0x5;
95 if (lpClusters!=NULL)
96 *lpClusters = dwTotalNumberOfClusters<<0x5;
97 }
98 }
99 }
100 return rc;
101}
102//******************************************************************************
103//******************************************************************************
104BOOL WIN32API GetDiskFreeSpaceW(LPCWSTR lpszRootPathName,
105 PDWORD lpSectorsPerCluster,
106 PDWORD lpBytesPerSector,
107 PDWORD lpFreeClusters,
108 PDWORD lpClusters)
109{
110 BOOL rc;
111 char *astring;
112
113 astring = UnicodeToAsciiString((LPWSTR)lpszRootPathName);
114 rc = GetDiskFreeSpaceA(astring, lpSectorsPerCluster, lpBytesPerSector, lpFreeClusters, lpClusters);
115 FreeAsciiString(astring);
116 return(rc);
117}
118
119
120/*****************************************************************************
121 * Name : GetDiskFreeSpaceEx
122 * Purpose :
123 * Parameters: lpDirectoryName [in] Pointer to a null-terminated string that
124 * specifies a directory on the disk of interest.
125 * This string can be a UNC name. If this
126 * parameter is a UNC name, you must follow it
127 * with an additional backslash. For example, you
128 * would specify \\MyServer\MyShare as
129 * \\MyServer\MyShare\.
130 * If lpDirectoryName is NULL, the
131 * GetDiskFreeSpaceEx function obtains
132 * information about the object store.
133 * Note that lpDirectoryName does not have to
134 * specify the root directory on a disk. The
135 * function accepts any directory on the disk.
136 *
137 * lpFreeBytesAvailableToCaller
138 * [out] Pointer to a variable to receive the
139 * total number of free bytes on the disk that
140 * are available to the user associated with the
141 * calling thread.
142 * lpTotalNumberOfBytes
143 * [out] Pointer to a variable to receive the
144 * total number of bytes on the disk that are
145 * available to the user associated with the
146 * calling thread.
147 * lpTotalNumberOfFreeBytes
148 * [out] Pointer to a variable to receive the
149 * total number of free bytes on the disk.
150 * This parameter can be NULL.
151 * Variables :
152 * Result : Nonzero indicates success. Zero indicates failure. To get
153 * extended error information, call GetLastError.
154 * Remark : Note that the values obtained by this function are of type
155 * ULARGE_INTEGER. Be careful not to truncate these values to
156 * 32 bits.
157 * Status :
158 *
159 * Author : Patrick Haller [Fri, 2000/01/08 23:44]
160 *****************************************************************************/
161
162BOOL WIN32API GetDiskFreeSpaceExA(LPCSTR lpDirectoryName,
163 PULARGE_INTEGER lpFreeBytesAvailableToCaller,
164 PULARGE_INTEGER lpTotalNumberOfBytes,
165 PULARGE_INTEGER lpTotalNumberOfFreeBytes )
166{
167 BOOL rc;
168 DWORD dwSectorsPerCluster; // address of sectors per cluster ter
169 DWORD dwBytesPerSector; // address of bytes per sector
170 DWORD dwNumberOfFreeClusters; // address of number of free clusters
171 DWORD dwTotalNumberOfClusters; // address of total number of clusters
172
173 rc = GetDiskFreeSpaceA(lpDirectoryName, &dwSectorsPerCluster, &dwBytesPerSector,
174 &dwNumberOfFreeClusters, &dwTotalNumberOfClusters);
175 if(rc)
176 {
177 if(lpFreeBytesAvailableToCaller!=NULL) {
178 Mul32x32to64(lpFreeBytesAvailableToCaller, dwNumberOfFreeClusters, (dwSectorsPerCluster*dwBytesPerSector));
179 dprintf(("lpFreeBytesAvailableToCaller %x%x", lpFreeBytesAvailableToCaller->HighPart, lpFreeBytesAvailableToCaller->LowPart));
180 }
181 if(lpTotalNumberOfBytes!=NULL) {
182 Mul32x32to64(lpTotalNumberOfBytes, dwTotalNumberOfClusters, (dwSectorsPerCluster*dwBytesPerSector));
183 dprintf(("lpTotalNumberOfBytes %x%x", lpTotalNumberOfBytes->HighPart, lpTotalNumberOfBytes->LowPart));
184 }
185 if(lpTotalNumberOfFreeBytes!=NULL) {
186 memcpy(lpTotalNumberOfFreeBytes, lpFreeBytesAvailableToCaller, sizeof(*lpFreeBytesAvailableToCaller));
187 dprintf(("lpTotalNumberOfFreeBytes %x%x", lpTotalNumberOfFreeBytes->HighPart, lpTotalNumberOfFreeBytes->LowPart));
188 }
189 }
190 return rc;
191}
192//******************************************************************************
193//******************************************************************************
194BOOL WIN32API GetDiskFreeSpaceExW(LPCWSTR lpDirectoryName,
195 PULARGE_INTEGER lpFreeBytesAvailableToCaller,
196 PULARGE_INTEGER lpTotalNumberOfBytes,
197 PULARGE_INTEGER lpTotalNumberOfFreeBytes )
198{
199 BOOL rc;
200 char *astring;
201
202 dprintf(("KERNEL32: OS2GetDiskFreeSpaceExW\n"));
203 astring = UnicodeToAsciiString((LPWSTR)lpDirectoryName);
204 rc = GetDiskFreeSpaceExA(astring, lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes, lpTotalNumberOfFreeBytes);
205 FreeAsciiString(astring);
206 return(rc);
207}
208
209
210/**
211 * Determin the type of a specific drive or the current drive.
212 *
213 * @returns DRIVE_UNKNOWN
214 * DRIVE_NO_ROOT_DIR
215 * DRIVE_CANNOTDETERMINE
216 * DRIVE_DOESNOTEXIST
217 * DRIVE_REMOVABLE
218 * DRIVE_FIXED
219 * DRIVE_REMOTE
220 * DRIVE_CDROM
221 * DRIVE_RAMDISK
222 *
223 * @param lpszDrive Root path of the drive in question.
224 * NULL means the current drive.
225 * @sketch
226 * If no drive Then
227 * Get Current Drive Index.
228 * ElseIf valid drive letter Then
229 * Convert to Drive Index.
230 * Else
231 * Return Error: Invalid root dir.
232 * Endif
233 * Call the OSLib worker function with the index.
234 * return it's result.
235 *
236 * @status completely implemented and tested
237 * @author Sander
238 * @remark NT4, SP6 does not change the last error, regardless of the junk it receives!
239 */
240UINT WIN32API GetDriveTypeA(LPCSTR lpszDrive)
241{
242 UINT rc;
243 ULONG ulDrive = ~0;
244
245 /* validate and convert input */
246 if (!lpszDrive)
247 ulDrive = OSLibDosQueryCurrentDisk() - 1;
248 else if (*lpszDrive != '\0' && lpszDrive[1] == ':')
249 {
250 if (*lpszDrive >= 'A' && *lpszDrive <= 'Z')
251 ulDrive = *lpszDrive - 'A';
252 else if (*lpszDrive >= 'a' && *lpszDrive <= 'z')
253 ulDrive = *lpszDrive - 'a';
254
255 /*
256 * Validate the rest of the path.
257 * Note: This validate is kind of weird.
258 * "c:\\\\\\\\\\\\" is ok
259 * "c:\\\\\\\\\\\\." is ok
260 * "c:\\\\\\\\\\\\........" is ok
261 * "c:\\\\\\\\\\\.\" is not ok
262 * "c:..............." is ok
263 * "c:\\ \ \ \ \ \\\\\" is not ok
264 * "c:\\ \ \ \ \ \\\\\" is not ok
265 * "c:\ . . . . . ." is ok
266 * "c:\/\/\/ . . . . ." is ok
267 * "c:\\\.\\\/\." is ok
268 * I hope I got it right.
269 */
270 if (ulDrive != ~0)
271 {
272 LPCSTR lpsz = lpszDrive + 2;
273
274 /* skip slashes and dots */
275 while (*lpsz == '.' || *lpsz == '\\' || *lpsz == '/')
276 lpsz++;
277 /* skip dot's and spaces. */
278 while (*lpsz == ' ' || *lpsz == '.')
279 lpsz++;
280 if (*lpsz)
281 ulDrive = ~0;
282 }
283 }
284
285 /* check if validation failed */
286 if (ulDrive == ~0)
287 {
288 dprintf(("KERNEL32: GetDriveType(""%s"") -> DRIVE_NO_ROOT_DIR (%d)", lpszDrive, DRIVE_NO_ROOT_DIR));
289 return DRIVE_NO_ROOT_DIR; //return value checked in NT4, SP6 (GetDriveType(""), GetDriveType("4");
290 }
291
292 //NOTE: Although GetDriveTypeW handles -1, GetDriveTypeA crashes in NT 4, SP6
293 rc = OSLibGetDriveType(ulDrive);
294 dprintf(("KERNEL32: GetDriveType %s = %d", lpszDrive, rc));
295 return rc;
296}
297
298
299/**
300 * Determin the type of a specific drive or the current drive.
301 *
302 * @returns DRIVE_UNKNOWN
303 * DRIVE_NO_ROOT_DIR
304 * DRIVE_CANNOTDETERMINE
305 * DRIVE_DOESNOTEXIST
306 * DRIVE_REMOVABLE
307 * DRIVE_FIXED
308 * DRIVE_REMOTE
309 * DRIVE_CDROM
310 * DRIVE_RAMDISK
311 *
312 * @param lpszDrive Root path of the drive in question.
313 * NULL means the current drive.
314 * @sketch
315 * If no drive Then
316 * Get Current Drive Index.
317 * ElseIf valid drive letter Then
318 * Convert to Drive Index.
319 * Else
320 * Return Error: Invalid root dir.
321 * Endif
322 * Call the OSLib worker function with the index.
323 * return it's result.
324 *
325 * @status completely implemented and tested
326 * @author Sander
327 * @remark NT4, SP6 does not change the last error, regardless of the junk it receives!
328 */
329UINT WIN32API GetDriveTypeW(LPCWSTR lpszDrive)
330{
331 UINT rc;
332 char *astring;
333
334 if(lpszDrive == (LPCWSTR)-1) {
335 return DRIVE_CANNOTDETERMINE; //NT 4, SP6 returns this (VERIFIED)
336 }
337 astring = UnicodeToAsciiString((LPWSTR)lpszDrive);
338 dprintf(("KERNEL32: GetDriveTypeW %s", astring));
339 rc = GetDriveTypeA(astring);
340 FreeAsciiString(astring);
341 return(rc);
342}
343//******************************************************************************
344//******************************************************************************
345BOOL WIN32API GetVolumeInformationA(LPCSTR lpRootPathName,
346 LPSTR lpVolumeNameBuffer,
347 DWORD nVolumeNameSize,
348 PDWORD lpVolumeSerialNumber,
349 PDWORD lpMaximumComponentLength,
350 PDWORD lpFileSystemFlags,
351 LPSTR lpFileSystemNameBuffer,
352 DWORD nFileSystemNameSize)
353{
354 CHAR tmpstring[256];
355 CHAR szOrgFileSystemName[256] = "";
356 ULONG drive;
357 BOOL rc;
358
359 dprintf(("GetVolumeInformationA %s", lpRootPathName));
360
361 if(lpRootPathName == NULL) {
362 GetCurrentDirectoryA(sizeof(tmpstring), tmpstring);
363 lpRootPathName = tmpstring;
364 }
365
366 if('A' <= *lpRootPathName && *lpRootPathName <= 'Z') {
367 drive = *lpRootPathName - 'A' + 1;
368 }
369 else
370 if('a' <= *lpRootPathName && *lpRootPathName <= 'z') {
371 drive = *lpRootPathName - 'a' + 1;
372 }
373 else {
374 SetLastError(ERROR_INVALID_PARAMETER);
375 return FALSE;
376 }
377
378 if(lpVolumeSerialNumber || lpVolumeNameBuffer) {
379 rc = OSLibDosQueryVolumeSerialAndName(drive, lpVolumeSerialNumber, lpVolumeNameBuffer, nVolumeNameSize);
380 if(lpVolumeSerialNumber) {
381 dprintf2(("Volume serial number: %x", *lpVolumeSerialNumber));
382 }
383 if(lpVolumeNameBuffer) {
384 dprintf2(("Volume name: %s", lpVolumeNameBuffer));
385 }
386 }
387 if(lpFileSystemNameBuffer || lpMaximumComponentLength || lpFileSystemFlags)
388 {
389 if(!lpFileSystemNameBuffer) {
390 lpFileSystemNameBuffer = tmpstring;
391 nFileSystemNameSize = sizeof(tmpstring);
392 }
393 rc = OSLibDosQueryVolumeFS(drive, lpFileSystemNameBuffer, nFileSystemNameSize);
394 //save original file system name
395 if(rc == ERROR_SUCCESS) strcpy(szOrgFileSystemName, lpFileSystemNameBuffer);
396
397 if(lpFileSystemNameBuffer)
398 {
399 dprintf2(("File system name: %s", lpFileSystemNameBuffer));
400 if(!strcmp(lpFileSystemNameBuffer, "JFS"))
401 {
402 strcpy(lpFileSystemNameBuffer, "NTFS");
403 }
404 else
405 if(!strcmp(lpFileSystemNameBuffer, "CDFS") ||
406 !strcmp(lpFileSystemNameBuffer, "UDF"))
407 {
408 //do nothing
409 }
410 else
411 {//pretend everything else is FAT16 (HPFS and FAT have the same file size limit)
412 strcpy(lpFileSystemNameBuffer, "FAT16");
413 }
414 dprintf2(("Final file system name: %s", lpFileSystemNameBuffer));
415 }
416 }
417 if(lpMaximumComponentLength) {
418 if(!strcmp(szOrgFileSystemName, "FAT16") || !strcmp(szOrgFileSystemName, "FAT")) {
419 *lpMaximumComponentLength = 12; //8.3
420 }
421 else *lpMaximumComponentLength = 255; //TODO: Always correct? (CDFS?)
422 }
423 if(lpFileSystemFlags)
424 {
425 if(strcmp(lpFileSystemNameBuffer, "FAT16")) {
426 *lpFileSystemFlags = FS_CASE_IS_PRESERVED;
427 }
428 else
429 if(!strcmp(lpFileSystemNameBuffer, "CDFS")) {
430 *lpFileSystemFlags = FS_CASE_SENSITIVE; //NT4 returns this
431 }
432 else
433 if(!strcmp(lpFileSystemNameBuffer, "UDF")) {//TODO: correct?
434 *lpFileSystemFlags = FS_CASE_SENSITIVE | FS_UNICODE_STORED_ON_DISK;
435 }
436 else *lpFileSystemFlags = 0;
437
438 dprintf2(("File system flags: %x", lpFileSystemFlags));
439 }
440
441 if(rc) {
442 SetLastError(rc);
443 return FALSE;
444 }
445 SetLastError(ERROR_SUCCESS);
446 return TRUE;
447}
448//******************************************************************************
449//******************************************************************************
450BOOL WIN32API GetVolumeInformationW(LPCWSTR lpRootPathName,
451 LPWSTR lpVolumeNameBuffer,
452 DWORD nVolumeNameSize,
453 PDWORD lpVolumeSerialNumber,
454 PDWORD lpMaximumComponentLength,
455 PDWORD lpFileSystemFlags,
456 LPWSTR lpFileSystemNameBuffer,
457 DWORD nFileSystemNameSize)
458{
459 char *asciiroot,
460 *asciivol,
461 *asciifs;
462 BOOL rc;
463
464 // transform into ascii
465 asciivol = (char *)malloc(nVolumeNameSize+1);
466 asciifs = (char *)malloc(nFileSystemNameSize+1);
467
468 // clear ascii buffers
469 memset (asciivol, 0, (nVolumeNameSize + 1));
470 memset (asciifs, 0, (nFileSystemNameSize + 1));
471
472 if (lpRootPathName != NULL) // NULL is valid!
473 asciiroot = UnicodeToAsciiString((LPWSTR)lpRootPathName);
474 else
475 asciiroot = NULL;
476
477 rc = GetVolumeInformationA(asciiroot,
478 asciivol,
479 nVolumeNameSize,
480 lpVolumeSerialNumber,
481 lpMaximumComponentLength,
482 lpFileSystemFlags,
483 asciifs,
484 nFileSystemNameSize);
485
486 if (lpVolumeNameBuffer != NULL) /* @@@PH 98/06/07 */
487 AsciiToUnicodeN(asciivol, lpVolumeNameBuffer, nVolumeNameSize);
488
489 if (lpFileSystemNameBuffer != NULL) /* @@@PH 98/06/07 */
490 AsciiToUnicodeN(asciifs, lpFileSystemNameBuffer, nFileSystemNameSize);
491
492
493 if (asciiroot != NULL)
494 FreeAsciiString(asciiroot);
495
496 free(asciifs);
497 free(asciivol);
498 return(rc);
499}
500//******************************************************************************
501//******************************************************************************
502DWORD WIN32API GetLogicalDrives(void)
503{
504 dprintf(("KERNEL32: GetLogicalDrives\n"));
505 return OSLibGetLogicalDrives();
506}
507//******************************************************************************
508//******************************************************************************
509UINT WIN32API GetLogicalDriveStringsA(UINT cchBuffer, LPSTR lpszBuffer)
510{
511 dprintf(("KERNEL32: GetLogicalDriveStringsA", cchBuffer, lpszBuffer));
512 return O32_GetLogicalDriveStrings(cchBuffer, lpszBuffer);
513}
514//******************************************************************************
515//******************************************************************************
516UINT WIN32API GetLogicalDriveStringsW(UINT nBufferLength, LPWSTR lpBuffer)
517{
518 char *asciibuffer = (char *)malloc(nBufferLength+1);
519 DWORD rc;
520
521 dprintf(("KERNEL32: OS2GetLogicalDriveStringsW\n"));
522
523 rc = O32_GetLogicalDriveStrings(nBufferLength, asciibuffer);
524 if(rc) AsciiToUnicode(asciibuffer, lpBuffer);
525 free(asciibuffer);
526 return(rc);
527}
528//******************************************************************************
529//******************************************************************************
530
Note: See TracBrowser for help on using the repository browser.