source: trunk/src/kernel32/disk.cpp

Last change on this file was 21567, checked in by dmik, 15 years ago

kernel32: Implemented GetVolumePathName() API.

File size: 34.2 KB
RevLine 
[10560]1/* $Id: disk.cpp,v 1.41 2004-03-25 09:19:46 sandervl Exp $ */
[100]2
[4]3/*
4 * Win32 Disk API functions for OS/2
5 *
[8409]6 * Copyright 1998-2002 Sander van Leeuwen
[4]7 *
[46]8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
[4]11 */
[1651]12
13
14#include <odin.h>
15#include <odinwrap.h>
16#include <os2sel.h>
17
[4]18#include <os2win.h>
[8397]19#include <stdio.h>
[4]20#include <stdlib.h>
[1651]21#include <string.h>
[8397]22#include <versionos2.h>
[4]23#include "unicode.h"
[3593]24#include "oslibdos.h"
[8397]25#include "osliblvm.h"
[8401]26#include "asmutil.h"
[4753]27#include "profile.h"
[8397]28#include "hmdisk.h"
[4]29
[3264]30#define DBG_LOCALLOG DBG_disk
[2802]31#include "dbglocal.h"
[1651]32
[2802]33
[1651]34ODINDEBUGCHANNEL(KERNEL32-DISK)
35
[8397]36
[4]37//******************************************************************************
38//******************************************************************************
39BOOL WIN32API SetVolumeLabelA( LPCSTR arg1, LPCSTR arg2)
40{
41 dprintf(("KERNEL32: OS2SetVolumeLabelA\n"));
42 return O32_SetVolumeLabel(arg1, arg2);
43}
44//******************************************************************************
45//******************************************************************************
[682]46BOOL WIN32API SetVolumeLabelW(LPCWSTR lpRootPathName, LPCWSTR lpVolumeName)
[4]47{
[8409]48 char *asciiroot, *asciivolname;
49 BOOL rc;
[4]50
51 dprintf(("KERNEL32: OS2SetVolumeLabelW\n"));
[682]52 asciiroot = UnicodeToAsciiString((LPWSTR)lpRootPathName);
53 asciivolname = UnicodeToAsciiString((LPWSTR)lpVolumeName);
[4]54 rc = O32_SetVolumeLabel(asciiroot, asciivolname);
55 FreeAsciiString(asciivolname);
56 FreeAsciiString(asciiroot);
57 return(rc);
58}
59
60//******************************************************************************
61//******************************************************************************
[7849]62BOOL WIN32API GetDiskFreeSpaceA(LPCSTR lpszRootPathName, PDWORD lpSectorsPerCluster,
63 PDWORD lpBytesPerSector, PDWORD lpFreeClusters,
64 PDWORD lpClusters)
[4]65{
[8409]66 BOOL rc;
67 DWORD dwSectorsPerCluster; // address of sectors per cluster ter
68 DWORD dwBytesPerSector; // address of bytes per sector
69 DWORD dwNumberOfFreeClusters; // address of number of free clusters
70 DWORD dwTotalNumberOfClusters; // address of total number of clusters
[4753]71
[8409]72 rc = OSLibGetDiskFreeSpace((LPSTR)lpszRootPathName, &dwSectorsPerCluster, &dwBytesPerSector,
73 &dwNumberOfFreeClusters, &dwTotalNumberOfClusters);
74 if(rc)
75 {
76 if (lpSectorsPerCluster!=NULL)
77 *lpSectorsPerCluster = dwSectorsPerCluster;
78 if (lpBytesPerSector!=NULL)
79 *lpBytesPerSector = dwBytesPerSector;
80 if (lpFreeClusters!=NULL)
81 *lpFreeClusters = dwNumberOfFreeClusters;
82 if (lpClusters!=NULL)
83 *lpClusters = dwTotalNumberOfClusters;
[4749]84
85 /* CW: Windows Media Player setup complains about wrong clustersize when odin is installed on
86 a TVFS drive. This fakes the clustersizes to 32. The following
87 entry must be present in ODIN.INI:
[4753]88
[4749]89 [DRIVESPACE]
90 TVFSTOHPFS = 1
91 */
[21567]92 if(lpSectorsPerCluster!=NULL)
[8409]93 {
[21567]94 if(*lpSectorsPerCluster==1024 && PROFILE_GetOdinIniBool("DRIVESPACE","CLUSTERTO32",0))
[8409]95 {/* TVFS returns 1024 sectors per cluster */
96 dprintf(("KERNEL32: GetDiskFreeSpaceA, TVFS-Drive detected. Faking clustersize to 32.\n"));
97 *lpSectorsPerCluster=32;
98 if (lpFreeClusters!=NULL)
99 *lpFreeClusters = dwNumberOfFreeClusters<<0x5;
100 if (lpClusters!=NULL)
101 *lpClusters = dwTotalNumberOfClusters<<0x5;
102 }
103 }
[4749]104 }
[8409]105 return rc;
[4]106}
107//******************************************************************************
108//******************************************************************************
[7849]109BOOL WIN32API GetDiskFreeSpaceW(LPCWSTR lpszRootPathName,
110 PDWORD lpSectorsPerCluster,
111 PDWORD lpBytesPerSector,
112 PDWORD lpFreeClusters,
113 PDWORD lpClusters)
[4]114{
[8409]115 BOOL rc;
116 char *astring;
[4]117
[8409]118 astring = UnicodeToAsciiString((LPWSTR)lpszRootPathName);
119 rc = GetDiskFreeSpaceA(astring, lpSectorsPerCluster, lpBytesPerSector, lpFreeClusters, lpClusters);
120 FreeAsciiString(astring);
121 return(rc);
[4]122}
[2361]123
124
125/*****************************************************************************
126 * Name : GetDiskFreeSpaceEx
127 * Purpose :
[3264]128 * Parameters: lpDirectoryName [in] Pointer to a null-terminated string that
[2361]129 * specifies a directory on the disk of interest.
[3264]130 * This string can be a UNC name. If this
131 * parameter is a UNC name, you must follow it
132 * with an additional backslash. For example, you
133 * would specify \\MyServer\MyShare as
[2361]134 * \\MyServer\MyShare\.
[3264]135 * If lpDirectoryName is NULL, the
136 * GetDiskFreeSpaceEx function obtains
[2361]137 * information about the object store.
[3264]138 * Note that lpDirectoryName does not have to
139 * specify the root directory on a disk. The
[2361]140 * function accepts any directory on the disk.
141 *
142 * lpFreeBytesAvailableToCaller
[3264]143 * [out] Pointer to a variable to receive the
144 * total number of free bytes on the disk that
145 * are available to the user associated with the
[2361]146 * calling thread.
147 * lpTotalNumberOfBytes
[3264]148 * [out] Pointer to a variable to receive the
149 * total number of bytes on the disk that are
150 * available to the user associated with the
[2361]151 * calling thread.
152 * lpTotalNumberOfFreeBytes
[3264]153 * [out] Pointer to a variable to receive the
[2361]154 * total number of free bytes on the disk.
155 * This parameter can be NULL.
156 * Variables :
[3264]157 * Result : Nonzero indicates success. Zero indicates failure. To get
[2361]158 * extended error information, call GetLastError.
[3264]159 * Remark : Note that the values obtained by this function are of type
160 * ULARGE_INTEGER. Be careful not to truncate these values to
[2361]161 * 32 bits.
162 * Status :
163 *
164 * Author : Patrick Haller [Fri, 2000/01/08 23:44]
165 *****************************************************************************/
166
[7849]167BOOL WIN32API GetDiskFreeSpaceExA(LPCSTR lpDirectoryName,
168 PULARGE_INTEGER lpFreeBytesAvailableToCaller,
169 PULARGE_INTEGER lpTotalNumberOfBytes,
170 PULARGE_INTEGER lpTotalNumberOfFreeBytes )
[2361]171{
[3577]172 BOOL rc;
[4753]173 DWORD dwSectorsPerCluster; // address of sectors per cluster ter
174 DWORD dwBytesPerSector; // address of bytes per sector
175 DWORD dwNumberOfFreeClusters; // address of number of free clusters
176 DWORD dwTotalNumberOfClusters; // address of total number of clusters
[3264]177
[4189]178 rc = GetDiskFreeSpaceA(lpDirectoryName, &dwSectorsPerCluster, &dwBytesPerSector,
179 &dwNumberOfFreeClusters, &dwTotalNumberOfClusters);
[3577]180 if(rc)
181 {
[4753]182 if(lpFreeBytesAvailableToCaller!=NULL) {
[4763]183 Mul32x32to64(lpFreeBytesAvailableToCaller, dwNumberOfFreeClusters, (dwSectorsPerCluster*dwBytesPerSector));
[6679]184 dprintf(("lpFreeBytesAvailableToCaller %x%x", lpFreeBytesAvailableToCaller->HighPart, lpFreeBytesAvailableToCaller->LowPart));
[4763]185 }
[4753]186 if(lpTotalNumberOfBytes!=NULL) {
[4763]187 Mul32x32to64(lpTotalNumberOfBytes, dwTotalNumberOfClusters, (dwSectorsPerCluster*dwBytesPerSector));
[6679]188 dprintf(("lpTotalNumberOfBytes %x%x", lpTotalNumberOfBytes->HighPart, lpTotalNumberOfBytes->LowPart));
[4763]189 }
[4753]190 if(lpTotalNumberOfFreeBytes!=NULL) {
[4763]191 memcpy(lpTotalNumberOfFreeBytes, lpFreeBytesAvailableToCaller, sizeof(*lpFreeBytesAvailableToCaller));
[6679]192 dprintf(("lpTotalNumberOfFreeBytes %x%x", lpTotalNumberOfFreeBytes->HighPart, lpTotalNumberOfFreeBytes->LowPart));
[4763]193 }
[4753]194 }
[3577]195 return rc;
[2361]196}
[4763]197//******************************************************************************
198//******************************************************************************
[7849]199BOOL WIN32API GetDiskFreeSpaceExW(LPCWSTR lpDirectoryName,
200 PULARGE_INTEGER lpFreeBytesAvailableToCaller,
201 PULARGE_INTEGER lpTotalNumberOfBytes,
202 PULARGE_INTEGER lpTotalNumberOfFreeBytes )
[2361]203{
[8409]204 BOOL rc;
205 char *astring;
[3264]206
[3577]207 dprintf(("KERNEL32: OS2GetDiskFreeSpaceExW\n"));
208 astring = UnicodeToAsciiString((LPWSTR)lpDirectoryName);
209 rc = GetDiskFreeSpaceExA(astring, lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes, lpTotalNumberOfFreeBytes);
210 FreeAsciiString(astring);
211 return(rc);
[2361]212}
[8392]213//******************************************************************************
214//Note: NT4, SP6 does not change the last error, regardless of the junk it receives!
215//******************************************************************************
[4559]216UINT WIN32API GetDriveTypeA(LPCSTR lpszDrive)
[4]217{
[8409]218 UINT rc;
219 ULONG driveIndex;
[4763]220
[8392]221 if(lpszDrive == 0) {
222 driveIndex = OSLibDosQueryCurrentDisk() - 1;
[4763]223 }
[8392]224 else
225 if(*lpszDrive >= 'A' && *lpszDrive <= 'Z')
226 driveIndex = (DWORD)(*lpszDrive - 'A');
227 else
228 if(*lpszDrive >= 'a' && *lpszDrive <= 'z') {
229 driveIndex = (DWORD)(*lpszDrive - 'a');
230 }
231 else {
[8397]232 //Volume functions only available in Windows 2000 and up
[21567]233 if(VERSION_IS_WIN2000_OR_HIGHER() && !strncmp(lpszDrive, VOLUME_NAME_PREFIX, sizeof(VOLUME_NAME_PREFIX)-1))
[8397]234 {
235 char *pszVolume;
236 int length;
237
238 //strip volume name prefix (\\\\?\\Volume\\)
239 length = strlen(lpszDrive);
240 pszVolume = (char *)alloca(length);
241
[21567]242 if(OSLibLVMStripVolumeName(lpszDrive, pszVolume, length))
[8401]243 {
[8397]244 rc = OSLibLVMGetDriveType(pszVolume);
245 dprintf(("KERNEL32: GetDriveType %s = %d (LVM)", lpszDrive, rc));
246 return rc;
247 }
248 }
[4763]249 return DRIVE_NO_ROOT_DIR; //return value checked in NT4, SP6 (GetDriveType(""), GetDriveType("4");
250 }
251
[4559]252 //NOTE: Although GetDriveTypeW handles -1, GetDriveTypeA crashes in NT 4, SP6
[8392]253 rc = OSLibGetDriveType(driveIndex);
[4559]254 dprintf(("KERNEL32: GetDriveType %s = %d", lpszDrive, rc));
[3264]255 return rc;
[4]256}
[8392]257//******************************************************************************
258//******************************************************************************
[4559]259UINT WIN32API GetDriveTypeW(LPCWSTR lpszDrive)
[4]260{
[8409]261 UINT rc;
262 char *astring;
[4]263
[4559]264 if(lpszDrive == (LPCWSTR)-1) {
[4763]265 return DRIVE_CANNOTDETERMINE; //NT 4, SP6 returns this (VERIFIED)
[4559]266 }
267 astring = UnicodeToAsciiString((LPWSTR)lpszDrive);
[7742]268 dprintf(("KERNEL32: GetDriveTypeW %s", astring));
[7738]269 rc = GetDriveTypeA(astring);
[4]270 FreeAsciiString(astring);
271 return(rc);
272}
273//******************************************************************************
[8409]274static int fForce2GBFileSize = FALSE;
[4]275//******************************************************************************
[8409]276void WIN32API CustForce2GBFileSize()
277{
278 fForce2GBFileSize = TRUE;
279}
280//******************************************************************************
281//******************************************************************************
[7849]282BOOL WIN32API GetVolumeInformationA(LPCSTR lpRootPathName,
283 LPSTR lpVolumeNameBuffer,
284 DWORD nVolumeNameSize,
285 PDWORD lpVolumeSerialNumber,
286 PDWORD lpMaximumComponentLength,
287 PDWORD lpFileSystemFlags,
288 LPSTR lpFileSystemNameBuffer,
289 DWORD nFileSystemNameSize)
[4]290{
[3593]291 CHAR tmpstring[256];
[7704]292 CHAR szOrgFileSystemName[256] = "";
[3593]293 ULONG drive;
[8397]294 BOOL rc, fVolumeName = FALSE;
295 char *pszVolume;
[3593]296
[4763]297 dprintf(("GetVolumeInformationA %s", lpRootPathName));
[3593]298
[4763]299 if(lpRootPathName == NULL) {
300 GetCurrentDirectoryA(sizeof(tmpstring), tmpstring);
301 lpRootPathName = tmpstring;
302 }
[3593]303
[4763]304 if('A' <= *lpRootPathName && *lpRootPathName <= 'Z') {
[4753]305 drive = *lpRootPathName - 'A' + 1;
[4763]306 }
307 else
308 if('a' <= *lpRootPathName && *lpRootPathName <= 'z') {
[4753]309 drive = *lpRootPathName - 'a' + 1;
[4763]310 }
311 else {
[8397]312 //Volume functions only available in Windows 2000 and up
[21567]313 if(LOBYTE(GetVersion()) >= 5 && !strncmp(lpRootPathName, VOLUME_NAME_PREFIX, sizeof(VOLUME_NAME_PREFIX)-1))
[8397]314 {
315 int length;
316
317 //strip volume name prefix (\\\\?\\Volume\\)
318 length = strlen(lpRootPathName);
319 pszVolume = (char *)alloca(length);
320
[21567]321 if(OSLibLVMStripVolumeName(lpRootPathName, pszVolume, length))
[8401]322 {
323 pszVolume[length-2] = 0;
[8397]324 fVolumeName = TRUE;
325 goto proceed;
326 }
327 }
[4763]328 SetLastError(ERROR_INVALID_PARAMETER);
329 return FALSE;
330 }
[8397]331proceed:
[3593]332
[4763]333 if(lpVolumeSerialNumber || lpVolumeNameBuffer) {
[8397]334 if(fVolumeName) {
335 rc = OSLibLVMQueryVolumeSerialAndName(pszVolume, lpVolumeSerialNumber, lpVolumeNameBuffer, nVolumeNameSize);
336 }
337 else rc = OSLibDosQueryVolumeSerialAndName(drive, lpVolumeSerialNumber, lpVolumeNameBuffer, nVolumeNameSize);
[4171]338 if(lpVolumeSerialNumber) {
[4763]339 dprintf2(("Volume serial number: %x", *lpVolumeSerialNumber));
340 }
[4171]341 if(lpVolumeNameBuffer) {
[4763]342 dprintf2(("Volume name: %s", lpVolumeNameBuffer));
343 }
[4753]344 }
[21567]345 if(lpFileSystemNameBuffer || lpMaximumComponentLength || lpFileSystemFlags)
[7704]346 {
[10560]347 if(!lpFileSystemNameBuffer || (nFileSystemNameSize == 0)) {
[4763]348 lpFileSystemNameBuffer = tmpstring;
349 nFileSystemNameSize = sizeof(tmpstring);
350 }
[8397]351 if(fVolumeName) {
352 rc = OSLibLVMQueryVolumeFS(pszVolume, lpFileSystemNameBuffer, nFileSystemNameSize);
353 }
354 else rc = OSLibDosQueryVolumeFS(drive, lpFileSystemNameBuffer, nFileSystemNameSize);
355
[7704]356 //save original file system name
357 if(rc == ERROR_SUCCESS) strcpy(szOrgFileSystemName, lpFileSystemNameBuffer);
358
[21567]359 if(lpFileSystemNameBuffer)
[7645]360 {
[4763]361 dprintf2(("File system name: %s", lpFileSystemNameBuffer));
[21567]362 if(!strcmp(lpFileSystemNameBuffer, "JFS"))
[7645]363 {
[10560]364 strncpy(lpFileSystemNameBuffer, "NTFS", nFileSystemNameSize);
[7645]365 }
366 else
367 if(!strcmp(lpFileSystemNameBuffer, "CDFS") ||
[8401]368 !strcmp(lpFileSystemNameBuffer, "UDF") ||
369 !strcmp(lpFileSystemNameBuffer, "NTFS") ||
370 !strcmp(lpFileSystemNameBuffer, "FAT32"))
[7645]371 {
372 //do nothing
373 }
[21567]374 else
[7645]375 {//pretend everything else is FAT16 (HPFS and FAT have the same file size limit)
[10556]376 // @@VP:20040323 - nFileSystemNameSize may be 0!!!
377 strncpy(lpFileSystemNameBuffer, "FAT16", nFileSystemNameSize);
[7645]378 }
[8409]379 if(fForce2GBFileSize) {
380 if(strcmp(lpFileSystemNameBuffer, "CDFS") &&
[21567]381 strcmp(lpFileSystemNameBuffer, "UDF"))
[8409]382 {//everything is FAT -> 2 GB file size limit
[10556]383 strncpy(lpFileSystemNameBuffer, "FAT16", nFileSystemNameSize);
[8409]384 }
385 }
[7645]386 dprintf2(("Final file system name: %s", lpFileSystemNameBuffer));
[4763]387 }
[4753]388 }
[4763]389 if(lpMaximumComponentLength) {
[7704]390 if(!strcmp(szOrgFileSystemName, "FAT16") || !strcmp(szOrgFileSystemName, "FAT")) {
391 *lpMaximumComponentLength = 12; //8.3
[4763]392 }
[7704]393 else *lpMaximumComponentLength = 255; //TODO: Always correct? (CDFS?)
[4753]394 }
[4763]395 if(lpFileSystemFlags)
396 {
[7645]397 if(strcmp(lpFileSystemNameBuffer, "FAT16")) {
[7704]398 *lpFileSystemFlags = FS_CASE_IS_PRESERVED;
[4763]399 }
400 else
401 if(!strcmp(lpFileSystemNameBuffer, "CDFS")) {
[7704]402 *lpFileSystemFlags = FS_CASE_SENSITIVE; //NT4 returns this
[4763]403 }
404 else
405 if(!strcmp(lpFileSystemNameBuffer, "UDF")) {//TODO: correct?
[7704]406 *lpFileSystemFlags = FS_CASE_SENSITIVE | FS_UNICODE_STORED_ON_DISK;
[4763]407 }
[7704]408 else *lpFileSystemFlags = 0;
[4763]409
410 dprintf2(("File system flags: %x", lpFileSystemFlags));
[4753]411 }
[4763]412
413 if(rc) {
414 SetLastError(rc);
415 return FALSE;
[4753]416 }
[4763]417 SetLastError(ERROR_SUCCESS);
418 return TRUE;
[4]419}
420//******************************************************************************
421//******************************************************************************
[7849]422BOOL WIN32API GetVolumeInformationW(LPCWSTR lpRootPathName,
423 LPWSTR lpVolumeNameBuffer,
424 DWORD nVolumeNameSize,
425 PDWORD lpVolumeSerialNumber,
426 PDWORD lpMaximumComponentLength,
427 PDWORD lpFileSystemFlags,
428 LPWSTR lpFileSystemNameBuffer,
429 DWORD nFileSystemNameSize)
[4]430{
[8409]431 char *asciiroot,
432 *asciivol,
433 *asciifs;
434 BOOL rc;
[4]435
[8409]436 // transform into ascii
437 asciivol = (char *)malloc(nVolumeNameSize+1);
438 asciifs = (char *)malloc(nFileSystemNameSize+1);
[4]439
[8409]440 // clear ascii buffers
441 memset (asciivol, 0, (nVolumeNameSize + 1));
442 memset (asciifs, 0, (nFileSystemNameSize + 1));
[4]443
[8409]444 if (lpRootPathName != NULL) // NULL is valid!
445 asciiroot = UnicodeToAsciiString((LPWSTR)lpRootPathName);
446 else
447 asciiroot = NULL;
[4]448
[8409]449 rc = GetVolumeInformationA(asciiroot, asciivol, nVolumeNameSize, lpVolumeSerialNumber,
450 lpMaximumComponentLength, lpFileSystemFlags, asciifs, nFileSystemNameSize);
[1651]451
452 if (lpVolumeNameBuffer != NULL) /* @@@PH 98/06/07 */
[8409]453 AsciiToUnicodeN(asciivol, lpVolumeNameBuffer, nVolumeNameSize);
[1651]454
455 if (lpFileSystemNameBuffer != NULL) /* @@@PH 98/06/07 */
[8409]456 AsciiToUnicodeN(asciifs, lpFileSystemNameBuffer, nFileSystemNameSize);
[1651]457
[8409]458 if (asciiroot != NULL)
459 FreeAsciiString(asciiroot);
[1651]460
[8409]461 free(asciifs);
462 free(asciivol);
463 return(rc);
[4]464}
465//******************************************************************************
466//******************************************************************************
467DWORD WIN32API GetLogicalDrives(void)
468{
469 dprintf(("KERNEL32: GetLogicalDrives\n"));
[4763]470 return OSLibGetLogicalDrives();
[4]471}
472//******************************************************************************
473//******************************************************************************
[7645]474UINT WIN32API GetLogicalDriveStringsA(UINT cchBuffer, LPSTR lpszBuffer)
[4]475{
[7645]476 dprintf(("KERNEL32: GetLogicalDriveStringsA", cchBuffer, lpszBuffer));
477 return O32_GetLogicalDriveStrings(cchBuffer, lpszBuffer);
[4]478}
479//******************************************************************************
480//******************************************************************************
[10556]481UINT WIN32API GetLogicalDriveStringsW(UINT nBufferLength, LPWSTR lpBufferW)
[4]482{
[10556]483 LPSTR lpBufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, sizeof(CHAR) * (nBufferLength + 1) );
484 DWORD dwResult = GetLogicalDriveStringsA( nBufferLength, lpBufferA );
[4]485
[10556]486 dprintf(("KERNEL32: GetLogicalDriveStringsW %d %x", nBufferLength, lpBufferA));
[4]487
[10556]488 if ( dwResult && dwResult <= nBufferLength )
489 MultiByteToWideChar( CP_ACP, 0, lpBufferA, dwResult + 1, lpBufferW, nBufferLength );
490
491 HeapFree( GetProcessHeap(), 0, lpBufferA );
492
493 return dwResult;
[4]494}
[4763]495//******************************************************************************
[8397]496typedef struct {
497 HANDLE hLVMVolumeControlData;
498 DWORD lastvol;
499} VOLINFO;
[4763]500//******************************************************************************
[8392]501HANDLE WIN32API FindFirstVolumeA(LPTSTR lpszVolumeName, DWORD cchBufferLength)
502{
[8397]503 HANDLE hVolume;
504 VOLINFO *pVolInfo;
505 char szdrive[3];
506 char szVolume[256];
507
508 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
509 SetLastError(ERROR_NOT_SUPPORTED);
510 return FALSE;
511 }
512
513 hVolume = GlobalAlloc(0, sizeof(VOLINFO));
514 if(hVolume == 0) {
515 dprintf(("ERROR: FindFirstVolumeA: out of memory!!"));
516 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
517 return 0;
518 }
519 pVolInfo = (VOLINFO *)GlobalLock(hVolume);
520 pVolInfo->hLVMVolumeControlData = OSLibLVMQueryVolumeControlData();
521 pVolInfo->lastvol = 0;
522
[9304]523 if(OSLibLVMQueryVolumeName(pVolInfo->hLVMVolumeControlData, &pVolInfo->lastvol, szVolume, sizeof(szVolume)) == FALSE) {
[8397]524 SetLastError(ERROR_NO_MORE_FILES);
525 goto fail;
526 }
527 if(strlen(szVolume) + 14 + 1 > cchBufferLength) {
528 SetLastError(ERROR_INSUFFICIENT_BUFFER);
529 goto fail;
530 }
531 sprintf(lpszVolumeName, VOLUME_NAME_PREFIX"{%s}\\", szVolume);
532 dprintf(("FindFirstVolumeA returned %s", lpszVolumeName));
533 pVolInfo->lastvol++;
534 GlobalUnlock(hVolume);
535 SetLastError(ERROR_SUCCESS);
536 return hVolume;
537
538fail:
539 GlobalUnlock(hVolume);
540 GlobalFree(hVolume);
[8392]541 return 0;
542}
543//******************************************************************************
544//******************************************************************************
545HANDLE WIN32API FindFirstVolumeW(LPWSTR lpszVolumeName, DWORD cchBufferLength)
546{
[8397]547 LPSTR pszvolname = NULL;
548 HANDLE hVolume;
549
550 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
551 SetLastError(ERROR_NOT_SUPPORTED);
552 return FALSE;
553 }
554
555 if(cchBufferLength) {
556 pszvolname = (char *)alloca(cchBufferLength);
557 }
558 hVolume = FindFirstVolumeA(pszvolname, cchBufferLength);
559 if(hVolume) {
560 int len = MultiByteToWideChar( CP_ACP, 0, pszvolname, -1, NULL, 0);
561 MultiByteToWideChar(CP_ACP, 0, pszvolname, -1, lpszVolumeName, len);
562 }
563 return hVolume;
[8392]564}
565//******************************************************************************
566//******************************************************************************
[21567]567BOOL WIN32API FindNextVolumeA(HANDLE hFindVolume, LPTSTR lpszVolumeName,
[8392]568 DWORD cchBufferLength)
569{
[8397]570 VOLINFO *pVolInfo;
571 char szdrive[3];
572 DWORD DeviceType;
573 char szVolume[256];
574
575 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
576 SetLastError(ERROR_NOT_SUPPORTED);
577 return FALSE;
578 }
579
580 pVolInfo = (VOLINFO *)GlobalLock(hFindVolume);
581 if(pVolInfo == NULL) {
582 SetLastError(ERROR_INVALID_PARAMETER);
583 return FALSE;
584 }
[21567]585 if(OSLibLVMQueryVolumeName(pVolInfo->hLVMVolumeControlData, &pVolInfo->lastvol,
[8397]586 szVolume, sizeof(szVolume)) == FALSE) {
587 SetLastError(ERROR_NO_MORE_FILES);
588 GlobalUnlock(hFindVolume);
589 return FALSE;
590 }
591 if(strlen(szVolume) + 14 + 1 > cchBufferLength) {
592 SetLastError(ERROR_INSUFFICIENT_BUFFER);
593 GlobalUnlock(hFindVolume);
594 return FALSE;
595 }
596 sprintf(lpszVolumeName, VOLUME_NAME_PREFIX"{%s}\\", szVolume);
597 dprintf(("FindNextVolumeA returned %s", lpszVolumeName));
598 pVolInfo->lastvol++;
599 GlobalUnlock(hFindVolume);
600 SetLastError(ERROR_SUCCESS);
601 return TRUE;
[8392]602}
603//******************************************************************************
604//******************************************************************************
[21567]605BOOL WIN32API FindNextVolumeW(HANDLE hFindVolume, LPWSTR lpszVolumeName,
[8392]606 DWORD cchBufferLength)
607{
[8397]608 LPSTR pszvolnameA = NULL;
609 BOOL ret;
610
611 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
612 SetLastError(ERROR_NOT_SUPPORTED);
613 return FALSE;
614 }
615
616 if(cchBufferLength) {
617 pszvolnameA = (char *)alloca(cchBufferLength);
618 }
619 ret = FindNextVolumeA(hFindVolume, pszvolnameA, cchBufferLength);
620 if(ret) {
621 int len = MultiByteToWideChar( CP_ACP, 0, pszvolnameA, -1, NULL, 0);
622 MultiByteToWideChar(CP_ACP, 0, pszvolnameA, -1, lpszVolumeName, len);
623 }
624 return ret;
[8392]625}
626//******************************************************************************
627//******************************************************************************
628BOOL WIN32API FindVolumeClose(HANDLE hFindVolume)
629{
[8397]630 VOLINFO *pVolInfo;
631
632 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
633 SetLastError(ERROR_NOT_SUPPORTED);
634 return FALSE;
635 }
636
637 if(hFindVolume) {
638 pVolInfo = (VOLINFO *)GlobalLock(hFindVolume);
639 OSLibLVMFreeVolumeControlData(pVolInfo->hLVMVolumeControlData);
640 GlobalUnlock(hFindVolume);
641 GlobalFree(hFindVolume);
642 return TRUE;
643 }
644 return FALSE;
[8392]645}
646//******************************************************************************
647//******************************************************************************
[21567]648HANDLE WIN32API FindFirstVolumeMountPointA(LPTSTR lpszRootPathName,
[8392]649 LPTSTR lpszVolumeMountPoint,
650 DWORD cchBufferLength)
651{
[8397]652 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
653 SetLastError(ERROR_NOT_SUPPORTED);
[9298]654 return INVALID_HANDLE_VALUE;
[8397]655 }
[21567]656
[8397]657 SetLastError(ERROR_NO_MORE_FILES);
[9298]658 return INVALID_HANDLE_VALUE;
[8392]659}
660//******************************************************************************
661//******************************************************************************
[21567]662HANDLE WIN32API FindFirstVolumeMountPointW(LPWSTR lpszRootPathName,
[8392]663 LPWSTR lpszVolumeMountPoint,
664 DWORD cchBufferLength)
665{
[8397]666 LPSTR pszmountpointnameA = NULL;
667 LPSTR pszrootA = NULL;
668 HANDLE hVolume;
669
670 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
671 SetLastError(ERROR_NOT_SUPPORTED);
[9298]672 return INVALID_HANDLE_VALUE;
[8397]673 }
674
675 if(cchBufferLength) {
676 pszmountpointnameA = (char *)alloca(cchBufferLength);
677 }
678 if(lpszRootPathName) {
679 pszrootA = (char *)alloca(lstrlenW(lpszRootPathName)+1);
680
681 int len = WideCharToMultiByte( CP_ACP, 0, lpszRootPathName, -1, NULL, 0, 0, NULL);
682 WideCharToMultiByte(CP_ACP, 0, lpszRootPathName, -1, pszrootA, len, 0, NULL);
683 }
684
685 hVolume = FindFirstVolumeMountPointA(pszrootA, pszmountpointnameA, cchBufferLength);
686 if(hVolume) {
687 int len = MultiByteToWideChar( CP_ACP, 0, pszmountpointnameA, -1, NULL, 0);
688 MultiByteToWideChar(CP_ACP, 0, pszmountpointnameA, -1, lpszVolumeMountPoint, len);
689 }
690 return hVolume;
[8392]691}
692//******************************************************************************
693//******************************************************************************
694BOOL WIN32API FindNextVolumeMountPointA(HANDLE hFindVolumeMountPoint,
695 LPTSTR lpszVolumeMountPoint,
696 DWORD cchBufferLength)
697{
[8397]698 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
699 SetLastError(ERROR_NOT_SUPPORTED);
700 return FALSE;
701 }
702 SetLastError(ERROR_NO_MORE_FILES);
[8392]703 return FALSE;
704}
705//******************************************************************************
706//******************************************************************************
707BOOL WIN32API FindNextVolumeMountPointW(HANDLE hFindVolumeMountPoint,
708 LPWSTR lpszVolumeMountPoint,
709 DWORD cchBufferLength)
710{
[8397]711 LPSTR pszmoutpointnameA = NULL;
712 BOOL ret;
713
714 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
715 SetLastError(ERROR_NOT_SUPPORTED);
716 return FALSE;
717 }
718
719 if(cchBufferLength) {
720 pszmoutpointnameA = (char *)alloca(cchBufferLength);
721 }
722 ret = FindFirstVolumeA(pszmoutpointnameA, cchBufferLength);
723 if(ret) {
724 int len = MultiByteToWideChar( CP_ACP, 0, pszmoutpointnameA, -1, NULL, 0);
725 MultiByteToWideChar(CP_ACP, 0, pszmoutpointnameA, -1, lpszVolumeMountPoint, len);
726 }
727 return ret;
[8392]728}
729//******************************************************************************
730//******************************************************************************
731BOOL WIN32API FindVolumeMountPointClose(HANDLE hFindVolumeMountPoint)
732{
[8397]733 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
734 SetLastError(ERROR_NOT_SUPPORTED);
735 return FALSE;
736 }
737
738 if(hFindVolumeMountPoint) {
739 GlobalFree(hFindVolumeMountPoint);
740 return TRUE;
741 }
742 return FALSE;
[8392]743}
744//******************************************************************************
745//******************************************************************************
746BOOL WIN32API GetVolumeNameForVolumeMountPointA(LPCSTR lpszVolumeMountPoint,
747 LPSTR lpszVolumeName,
748 DWORD cchBufferLength)
749{
[8401]750 LPSTR pszvol;
751
752 pszvol = (char *)alloca(cchBufferLength);
753 if(pszvol == NULL) {
754 DebugInt3();
755 return FALSE;
756 }
757
[8397]758 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
759 SetLastError(ERROR_NOT_SUPPORTED);
760 return FALSE;
761 }
762
[21567]763 if(OSLibLVMGetVolumeNameForVolumeMountPoint(lpszVolumeMountPoint, pszvol,
764 cchBufferLength) == TRUE)
[8397]765 {
[8401]766 int length = strlen(pszvol);
767 if(length + sizeof(VOLUME_NAME_PREFIX) - 1 + 3 > cchBufferLength) {
768 SetLastError(ERROR_INSUFFICIENT_BUFFER);
769 return FALSE;
770 }
771 sprintf(lpszVolumeName, VOLUME_NAME_PREFIX"{%s}\\", pszvol);
772
[21567]773 dprintf(("KERNEL32: GetVolumeNameForVolumeMountPointA %s returned %s", lpszVolumeMountPoint, lpszVolumeName));
[8397]774 SetLastError(ERROR_SUCCESS);
775 return TRUE;
776 }
[21567]777 dprintf(("KERNEL32: GetVolumeNameForVolumeMountPointA: %s not found!!", lpszVolumeMountPoint));
[8397]778 SetLastError(ERROR_FILE_NOT_FOUND);
[8392]779 return FALSE;
780}
781//******************************************************************************
782//******************************************************************************
783BOOL WIN32API GetVolumeNameForVolumeMountPointW(LPCWSTR lpszVolumeMountPoint,
784 LPWSTR lpszVolumeName,
785 DWORD cchBufferLength)
786{
[8397]787 LPSTR pszmoutpointnameA = NULL;
788 LPSTR pszvolumenameA = NULL;
789 BOOL ret;
790 int len;
791
792 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
793 SetLastError(ERROR_NOT_SUPPORTED);
794 return FALSE;
795 }
796 len = WideCharToMultiByte( CP_ACP, 0, lpszVolumeMountPoint, -1, NULL, 0, 0, NULL);
797 pszmoutpointnameA = (char *)alloca(len+1);
798 WideCharToMultiByte(CP_ACP, 0, lpszVolumeMountPoint, -1, pszmoutpointnameA, len, 0, NULL);
799
800 if(cchBufferLength && lpszVolumeName) {
801 pszvolumenameA = (char *)alloca(cchBufferLength);
802 }
803 ret = GetVolumeNameForVolumeMountPointA(pszmoutpointnameA, pszvolumenameA, cchBufferLength);
804 if(ret) {
805 int len = MultiByteToWideChar( CP_ACP, 0, pszvolumenameA, -1, NULL, 0);
806 MultiByteToWideChar(CP_ACP, 0, pszvolumenameA, -1, lpszVolumeName, len);
807 }
808 return ret;
[8392]809}
810//******************************************************************************
811//******************************************************************************
[21567]812BOOL WIN32API GetVolumePathNameA(LPCSTR lpszFileName,
813 LPSTR lpszVolumePathName,
814 DWORD cchBufferLength)
815{
816 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
817 SetLastError(ERROR_NOT_SUPPORTED);
818 return FALSE;
819 }
820
821 if(!*lpszFileName) {
822 // According to MSDN:
823 SetLastError(ERROR_SUCCESS);
824 return FALSE;
825 }
826
827 // We only support drive letters as volume names
828 if(cchBufferLength < 3) {
829 SetLastError(ERROR_INSUFFICIENT_BUFFER);
830 return FALSE;
831 }
832
833 CHAR fullName[MAX_PATH];
834 DWORD rc = GetFullPathNameA(lpszFileName, sizeof(fullName), fullName, NULL);
835 if (rc == 0 || rc > sizeof(fullName))
836 return FALSE;
837
838 if(fullName[0] == '\\' && fullName[1] == '\\') {
839 // UNC path, search for the 2nd single slash: we should return "\\foo\bar\"
840 LPSTR slash1 = strchr(&fullName[2], '\\');
841 if(!slash1 || slash1 - fullName == 2) {
842 SetLastError(ERROR_INVALID_NAME);
843 return FALSE;
844 }
845 LPSTR slash2 = strchr(slash1 + 1, '\\');
846 if(!slash2 || slash2 - slash1 == 1) {
847 SetLastError(ERROR_INVALID_NAME);
848 return FALSE;
849 }
850 DWORD len = slash2 - fullName + 1; // with trailing slash
851 if(cchBufferLength < len + 1) {
852 SetLastError(ERROR_INSUFFICIENT_BUFFER);
853 return FALSE;
854 }
855 memcpy(lpszVolumePathName, fullName, len);
856 lpszVolumePathName[len] = '\0';
857 } else {
858 lpszVolumePathName[0] = fullName[0];
859 lpszVolumePathName[1] = ':';
860 if(cchBufferLength == 3) {
861 lpszVolumePathName[2] = '\0';
862 } else {
863 lpszVolumePathName[2] = '\\';
864 lpszVolumePathName[3] = '\0';
865 }
866 }
867
868 dprintf(("KERNEL32: GetVolumePathNameA %s returned %s", lpszFileName, lpszVolumePathName));
869 SetLastError(ERROR_SUCCESS);
870 return TRUE;
871}
872//******************************************************************************
873//******************************************************************************
874BOOL WIN32API GetVolumePathNameW(LPCWSTR lpszFileName,
875 LPWSTR lpszVolumePathName,
876 DWORD cchBufferLength)
877{
878 LPSTR lpszFileNameA = NULL;
879 LPSTR lpszVolumePathNameA = NULL;
880 BOOL ret;
881 int len;
882
883 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
884 SetLastError(ERROR_NOT_SUPPORTED);
885 return FALSE;
886 }
887 len = WideCharToMultiByte( CP_ACP, 0, lpszFileName, -1, NULL, 0, 0, NULL);
888 lpszFileNameA = (char *)alloca(len+1);
889 WideCharToMultiByte(CP_ACP, 0, lpszFileName, -1, lpszFileNameA, len, 0, NULL);
890
891 if(cchBufferLength && lpszVolumePathName) {
892 lpszVolumePathNameA = (char *)alloca(cchBufferLength);
893 }
894 ret = GetVolumePathNameA(lpszFileNameA, lpszVolumePathNameA, cchBufferLength);
895 if(ret) {
896 int len = MultiByteToWideChar( CP_ACP, 0, lpszVolumePathNameA, -1, NULL, 0);
897 MultiByteToWideChar(CP_ACP, 0, lpszVolumePathNameA, -1, lpszVolumePathName, len);
898 }
899 return ret;
900}
901//******************************************************************************
902//******************************************************************************
Note: See TracBrowser for help on using the repository browser.