/* $Id: disk.cpp,v 1.41 2004-03-25 09:19:46 sandervl Exp $ */ /* * Win32 Disk API functions for OS/2 * * Copyright 1998-2002 Sander van Leeuwen * * * Project Odin Software License can be found in LICENSE.TXT * */ #include #include #include #include #include #include #include #include #include "unicode.h" #include "oslibdos.h" #include "osliblvm.h" #include "asmutil.h" #include "profile.h" #include "hmdisk.h" #define DBG_LOCALLOG DBG_disk #include "dbglocal.h" ODINDEBUGCHANNEL(KERNEL32-DISK) //****************************************************************************** //****************************************************************************** BOOL WIN32API SetVolumeLabelA( LPCSTR arg1, LPCSTR arg2) { dprintf(("KERNEL32: OS2SetVolumeLabelA\n")); return O32_SetVolumeLabel(arg1, arg2); } //****************************************************************************** //****************************************************************************** BOOL WIN32API SetVolumeLabelW(LPCWSTR lpRootPathName, LPCWSTR lpVolumeName) { char *asciiroot, *asciivolname; BOOL rc; dprintf(("KERNEL32: OS2SetVolumeLabelW\n")); asciiroot = UnicodeToAsciiString((LPWSTR)lpRootPathName); asciivolname = UnicodeToAsciiString((LPWSTR)lpVolumeName); rc = O32_SetVolumeLabel(asciiroot, asciivolname); FreeAsciiString(asciivolname); FreeAsciiString(asciiroot); return(rc); } //****************************************************************************** //****************************************************************************** BOOL WIN32API GetDiskFreeSpaceA(LPCSTR lpszRootPathName, PDWORD lpSectorsPerCluster, PDWORD lpBytesPerSector, PDWORD lpFreeClusters, PDWORD lpClusters) { BOOL rc; DWORD dwSectorsPerCluster; // address of sectors per cluster ter DWORD dwBytesPerSector; // address of bytes per sector DWORD dwNumberOfFreeClusters; // address of number of free clusters DWORD dwTotalNumberOfClusters; // address of total number of clusters rc = OSLibGetDiskFreeSpace((LPSTR)lpszRootPathName, &dwSectorsPerCluster, &dwBytesPerSector, &dwNumberOfFreeClusters, &dwTotalNumberOfClusters); if(rc) { if (lpSectorsPerCluster!=NULL) *lpSectorsPerCluster = dwSectorsPerCluster; if (lpBytesPerSector!=NULL) *lpBytesPerSector = dwBytesPerSector; if (lpFreeClusters!=NULL) *lpFreeClusters = dwNumberOfFreeClusters; if (lpClusters!=NULL) *lpClusters = dwTotalNumberOfClusters; /* CW: Windows Media Player setup complains about wrong clustersize when odin is installed on a TVFS drive. This fakes the clustersizes to 32. The following entry must be present in ODIN.INI: [DRIVESPACE] TVFSTOHPFS = 1 */ if(lpSectorsPerCluster!=NULL) { if(*lpSectorsPerCluster==1024 && PROFILE_GetOdinIniBool("DRIVESPACE","CLUSTERTO32",0)) {/* TVFS returns 1024 sectors per cluster */ dprintf(("KERNEL32: GetDiskFreeSpaceA, TVFS-Drive detected. Faking clustersize to 32.\n")); *lpSectorsPerCluster=32; if (lpFreeClusters!=NULL) *lpFreeClusters = dwNumberOfFreeClusters<<0x5; if (lpClusters!=NULL) *lpClusters = dwTotalNumberOfClusters<<0x5; } } } return rc; } //****************************************************************************** //****************************************************************************** BOOL WIN32API GetDiskFreeSpaceW(LPCWSTR lpszRootPathName, PDWORD lpSectorsPerCluster, PDWORD lpBytesPerSector, PDWORD lpFreeClusters, PDWORD lpClusters) { BOOL rc; char *astring; astring = UnicodeToAsciiString((LPWSTR)lpszRootPathName); rc = GetDiskFreeSpaceA(astring, lpSectorsPerCluster, lpBytesPerSector, lpFreeClusters, lpClusters); FreeAsciiString(astring); return(rc); } /***************************************************************************** * Name : GetDiskFreeSpaceEx * Purpose : * Parameters: lpDirectoryName [in] Pointer to a null-terminated string that * specifies a directory on the disk of interest. * This string can be a UNC name. If this * parameter is a UNC name, you must follow it * with an additional backslash. For example, you * would specify \\MyServer\MyShare as * \\MyServer\MyShare\. * If lpDirectoryName is NULL, the * GetDiskFreeSpaceEx function obtains * information about the object store. * Note that lpDirectoryName does not have to * specify the root directory on a disk. The * function accepts any directory on the disk. * * lpFreeBytesAvailableToCaller * [out] Pointer to a variable to receive the * total number of free bytes on the disk that * are available to the user associated with the * calling thread. * lpTotalNumberOfBytes * [out] Pointer to a variable to receive the * total number of bytes on the disk that are * available to the user associated with the * calling thread. * lpTotalNumberOfFreeBytes * [out] Pointer to a variable to receive the * total number of free bytes on the disk. * This parameter can be NULL. * Variables : * Result : Nonzero indicates success. Zero indicates failure. To get * extended error information, call GetLastError. * Remark : Note that the values obtained by this function are of type * ULARGE_INTEGER. Be careful not to truncate these values to * 32 bits. * Status : * * Author : Patrick Haller [Fri, 2000/01/08 23:44] *****************************************************************************/ BOOL WIN32API GetDiskFreeSpaceExA(LPCSTR lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailableToCaller, PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes ) { BOOL rc; DWORD dwSectorsPerCluster; // address of sectors per cluster ter DWORD dwBytesPerSector; // address of bytes per sector DWORD dwNumberOfFreeClusters; // address of number of free clusters DWORD dwTotalNumberOfClusters; // address of total number of clusters rc = GetDiskFreeSpaceA(lpDirectoryName, &dwSectorsPerCluster, &dwBytesPerSector, &dwNumberOfFreeClusters, &dwTotalNumberOfClusters); if(rc) { if(lpFreeBytesAvailableToCaller!=NULL) { Mul32x32to64(lpFreeBytesAvailableToCaller, dwNumberOfFreeClusters, (dwSectorsPerCluster*dwBytesPerSector)); dprintf(("lpFreeBytesAvailableToCaller %x%x", lpFreeBytesAvailableToCaller->HighPart, lpFreeBytesAvailableToCaller->LowPart)); } if(lpTotalNumberOfBytes!=NULL) { Mul32x32to64(lpTotalNumberOfBytes, dwTotalNumberOfClusters, (dwSectorsPerCluster*dwBytesPerSector)); dprintf(("lpTotalNumberOfBytes %x%x", lpTotalNumberOfBytes->HighPart, lpTotalNumberOfBytes->LowPart)); } if(lpTotalNumberOfFreeBytes!=NULL) { memcpy(lpTotalNumberOfFreeBytes, lpFreeBytesAvailableToCaller, sizeof(*lpFreeBytesAvailableToCaller)); dprintf(("lpTotalNumberOfFreeBytes %x%x", lpTotalNumberOfFreeBytes->HighPart, lpTotalNumberOfFreeBytes->LowPart)); } } return rc; } //****************************************************************************** //****************************************************************************** BOOL WIN32API GetDiskFreeSpaceExW(LPCWSTR lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailableToCaller, PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes ) { BOOL rc; char *astring; dprintf(("KERNEL32: OS2GetDiskFreeSpaceExW\n")); astring = UnicodeToAsciiString((LPWSTR)lpDirectoryName); rc = GetDiskFreeSpaceExA(astring, lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes, lpTotalNumberOfFreeBytes); FreeAsciiString(astring); return(rc); } //****************************************************************************** //Note: NT4, SP6 does not change the last error, regardless of the junk it receives! //****************************************************************************** UINT WIN32API GetDriveTypeA(LPCSTR lpszDrive) { UINT rc; ULONG driveIndex; if(lpszDrive == 0) { driveIndex = OSLibDosQueryCurrentDisk() - 1; } else if(*lpszDrive >= 'A' && *lpszDrive <= 'Z') driveIndex = (DWORD)(*lpszDrive - 'A'); else if(*lpszDrive >= 'a' && *lpszDrive <= 'z') { driveIndex = (DWORD)(*lpszDrive - 'a'); } else { //Volume functions only available in Windows 2000 and up if(VERSION_IS_WIN2000_OR_HIGHER() && !strncmp(lpszDrive, VOLUME_NAME_PREFIX, sizeof(VOLUME_NAME_PREFIX)-1)) { char *pszVolume; int length; //strip volume name prefix (\\\\?\\Volume\\) length = strlen(lpszDrive); pszVolume = (char *)alloca(length); if(OSLibLVMStripVolumeName(lpszDrive, pszVolume, length)) { rc = OSLibLVMGetDriveType(pszVolume); dprintf(("KERNEL32: GetDriveType %s = %d (LVM)", lpszDrive, rc)); return rc; } } return DRIVE_NO_ROOT_DIR; //return value checked in NT4, SP6 (GetDriveType(""), GetDriveType("4"); } //NOTE: Although GetDriveTypeW handles -1, GetDriveTypeA crashes in NT 4, SP6 rc = OSLibGetDriveType(driveIndex); dprintf(("KERNEL32: GetDriveType %s = %d", lpszDrive, rc)); return rc; } //****************************************************************************** //****************************************************************************** UINT WIN32API GetDriveTypeW(LPCWSTR lpszDrive) { UINT rc; char *astring; if(lpszDrive == (LPCWSTR)-1) { return DRIVE_CANNOTDETERMINE; //NT 4, SP6 returns this (VERIFIED) } astring = UnicodeToAsciiString((LPWSTR)lpszDrive); dprintf(("KERNEL32: GetDriveTypeW %s", astring)); rc = GetDriveTypeA(astring); FreeAsciiString(astring); return(rc); } //****************************************************************************** static int fForce2GBFileSize = FALSE; //****************************************************************************** void WIN32API CustForce2GBFileSize() { fForce2GBFileSize = TRUE; } //****************************************************************************** //****************************************************************************** BOOL WIN32API GetVolumeInformationA(LPCSTR lpRootPathName, LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize, PDWORD lpVolumeSerialNumber, PDWORD lpMaximumComponentLength, PDWORD lpFileSystemFlags, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize) { CHAR tmpstring[256]; CHAR szOrgFileSystemName[256] = ""; ULONG drive; BOOL rc, fVolumeName = FALSE; char *pszVolume; dprintf(("GetVolumeInformationA %s", lpRootPathName)); if(lpRootPathName == NULL) { GetCurrentDirectoryA(sizeof(tmpstring), tmpstring); lpRootPathName = tmpstring; } if('A' <= *lpRootPathName && *lpRootPathName <= 'Z') { drive = *lpRootPathName - 'A' + 1; } else if('a' <= *lpRootPathName && *lpRootPathName <= 'z') { drive = *lpRootPathName - 'a' + 1; } else { //Volume functions only available in Windows 2000 and up if(LOBYTE(GetVersion()) >= 5 && !strncmp(lpRootPathName, VOLUME_NAME_PREFIX, sizeof(VOLUME_NAME_PREFIX)-1)) { int length; //strip volume name prefix (\\\\?\\Volume\\) length = strlen(lpRootPathName); pszVolume = (char *)alloca(length); if(OSLibLVMStripVolumeName(lpRootPathName, pszVolume, length)) { pszVolume[length-2] = 0; fVolumeName = TRUE; goto proceed; } } SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } proceed: if(lpVolumeSerialNumber || lpVolumeNameBuffer) { if(fVolumeName) { rc = OSLibLVMQueryVolumeSerialAndName(pszVolume, lpVolumeSerialNumber, lpVolumeNameBuffer, nVolumeNameSize); } else rc = OSLibDosQueryVolumeSerialAndName(drive, lpVolumeSerialNumber, lpVolumeNameBuffer, nVolumeNameSize); if(lpVolumeSerialNumber) { dprintf2(("Volume serial number: %x", *lpVolumeSerialNumber)); } if(lpVolumeNameBuffer) { dprintf2(("Volume name: %s", lpVolumeNameBuffer)); } } if(lpFileSystemNameBuffer || lpMaximumComponentLength || lpFileSystemFlags) { if(!lpFileSystemNameBuffer || (nFileSystemNameSize == 0)) { lpFileSystemNameBuffer = tmpstring; nFileSystemNameSize = sizeof(tmpstring); } if(fVolumeName) { rc = OSLibLVMQueryVolumeFS(pszVolume, lpFileSystemNameBuffer, nFileSystemNameSize); } else rc = OSLibDosQueryVolumeFS(drive, lpFileSystemNameBuffer, nFileSystemNameSize); //save original file system name if(rc == ERROR_SUCCESS) strcpy(szOrgFileSystemName, lpFileSystemNameBuffer); if(lpFileSystemNameBuffer) { dprintf2(("File system name: %s", lpFileSystemNameBuffer)); if(!strcmp(lpFileSystemNameBuffer, "JFS")) { strncpy(lpFileSystemNameBuffer, "NTFS", nFileSystemNameSize); } else if(!strcmp(lpFileSystemNameBuffer, "CDFS") || !strcmp(lpFileSystemNameBuffer, "UDF") || !strcmp(lpFileSystemNameBuffer, "NTFS") || !strcmp(lpFileSystemNameBuffer, "FAT32")) { //do nothing } else {//pretend everything else is FAT16 (HPFS and FAT have the same file size limit) // @@VP:20040323 - nFileSystemNameSize may be 0!!! strncpy(lpFileSystemNameBuffer, "FAT16", nFileSystemNameSize); } if(fForce2GBFileSize) { if(strcmp(lpFileSystemNameBuffer, "CDFS") && strcmp(lpFileSystemNameBuffer, "UDF")) {//everything is FAT -> 2 GB file size limit strncpy(lpFileSystemNameBuffer, "FAT16", nFileSystemNameSize); } } dprintf2(("Final file system name: %s", lpFileSystemNameBuffer)); } } if(lpMaximumComponentLength) { if(!strcmp(szOrgFileSystemName, "FAT16") || !strcmp(szOrgFileSystemName, "FAT")) { *lpMaximumComponentLength = 12; //8.3 } else *lpMaximumComponentLength = 255; //TODO: Always correct? (CDFS?) } if(lpFileSystemFlags) { if(strcmp(lpFileSystemNameBuffer, "FAT16")) { *lpFileSystemFlags = FS_CASE_IS_PRESERVED; } else if(!strcmp(lpFileSystemNameBuffer, "CDFS")) { *lpFileSystemFlags = FS_CASE_SENSITIVE; //NT4 returns this } else if(!strcmp(lpFileSystemNameBuffer, "UDF")) {//TODO: correct? *lpFileSystemFlags = FS_CASE_SENSITIVE | FS_UNICODE_STORED_ON_DISK; } else *lpFileSystemFlags = 0; dprintf2(("File system flags: %x", lpFileSystemFlags)); } if(rc) { SetLastError(rc); return FALSE; } SetLastError(ERROR_SUCCESS); return TRUE; } //****************************************************************************** //****************************************************************************** BOOL WIN32API GetVolumeInformationW(LPCWSTR lpRootPathName, LPWSTR lpVolumeNameBuffer, DWORD nVolumeNameSize, PDWORD lpVolumeSerialNumber, PDWORD lpMaximumComponentLength, PDWORD lpFileSystemFlags, LPWSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize) { char *asciiroot, *asciivol, *asciifs; BOOL rc; // transform into ascii asciivol = (char *)malloc(nVolumeNameSize+1); asciifs = (char *)malloc(nFileSystemNameSize+1); // clear ascii buffers memset (asciivol, 0, (nVolumeNameSize + 1)); memset (asciifs, 0, (nFileSystemNameSize + 1)); if (lpRootPathName != NULL) // NULL is valid! asciiroot = UnicodeToAsciiString((LPWSTR)lpRootPathName); else asciiroot = NULL; rc = GetVolumeInformationA(asciiroot, asciivol, nVolumeNameSize, lpVolumeSerialNumber, lpMaximumComponentLength, lpFileSystemFlags, asciifs, nFileSystemNameSize); if (lpVolumeNameBuffer != NULL) /* @@@PH 98/06/07 */ AsciiToUnicodeN(asciivol, lpVolumeNameBuffer, nVolumeNameSize); if (lpFileSystemNameBuffer != NULL) /* @@@PH 98/06/07 */ AsciiToUnicodeN(asciifs, lpFileSystemNameBuffer, nFileSystemNameSize); if (asciiroot != NULL) FreeAsciiString(asciiroot); free(asciifs); free(asciivol); return(rc); } //****************************************************************************** //****************************************************************************** DWORD WIN32API GetLogicalDrives(void) { dprintf(("KERNEL32: GetLogicalDrives\n")); return OSLibGetLogicalDrives(); } //****************************************************************************** //****************************************************************************** UINT WIN32API GetLogicalDriveStringsA(UINT cchBuffer, LPSTR lpszBuffer) { dprintf(("KERNEL32: GetLogicalDriveStringsA", cchBuffer, lpszBuffer)); return O32_GetLogicalDriveStrings(cchBuffer, lpszBuffer); } //****************************************************************************** //****************************************************************************** UINT WIN32API GetLogicalDriveStringsW(UINT nBufferLength, LPWSTR lpBufferW) { LPSTR lpBufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, sizeof(CHAR) * (nBufferLength + 1) ); DWORD dwResult = GetLogicalDriveStringsA( nBufferLength, lpBufferA ); dprintf(("KERNEL32: GetLogicalDriveStringsW %d %x", nBufferLength, lpBufferA)); if ( dwResult && dwResult <= nBufferLength ) MultiByteToWideChar( CP_ACP, 0, lpBufferA, dwResult + 1, lpBufferW, nBufferLength ); HeapFree( GetProcessHeap(), 0, lpBufferA ); return dwResult; } //****************************************************************************** typedef struct { HANDLE hLVMVolumeControlData; DWORD lastvol; } VOLINFO; //****************************************************************************** HANDLE WIN32API FindFirstVolumeA(LPTSTR lpszVolumeName, DWORD cchBufferLength) { HANDLE hVolume; VOLINFO *pVolInfo; char szdrive[3]; char szVolume[256]; if(!VERSION_IS_WIN2000_OR_HIGHER()) { SetLastError(ERROR_NOT_SUPPORTED); return FALSE; } hVolume = GlobalAlloc(0, sizeof(VOLINFO)); if(hVolume == 0) { dprintf(("ERROR: FindFirstVolumeA: out of memory!!")); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0; } pVolInfo = (VOLINFO *)GlobalLock(hVolume); pVolInfo->hLVMVolumeControlData = OSLibLVMQueryVolumeControlData(); pVolInfo->lastvol = 0; if(OSLibLVMQueryVolumeName(pVolInfo->hLVMVolumeControlData, &pVolInfo->lastvol, szVolume, sizeof(szVolume)) == FALSE) { SetLastError(ERROR_NO_MORE_FILES); goto fail; } if(strlen(szVolume) + 14 + 1 > cchBufferLength) { SetLastError(ERROR_INSUFFICIENT_BUFFER); goto fail; } sprintf(lpszVolumeName, VOLUME_NAME_PREFIX"{%s}\\", szVolume); dprintf(("FindFirstVolumeA returned %s", lpszVolumeName)); pVolInfo->lastvol++; GlobalUnlock(hVolume); SetLastError(ERROR_SUCCESS); return hVolume; fail: GlobalUnlock(hVolume); GlobalFree(hVolume); return 0; } //****************************************************************************** //****************************************************************************** HANDLE WIN32API FindFirstVolumeW(LPWSTR lpszVolumeName, DWORD cchBufferLength) { LPSTR pszvolname = NULL; HANDLE hVolume; if(!VERSION_IS_WIN2000_OR_HIGHER()) { SetLastError(ERROR_NOT_SUPPORTED); return FALSE; } if(cchBufferLength) { pszvolname = (char *)alloca(cchBufferLength); } hVolume = FindFirstVolumeA(pszvolname, cchBufferLength); if(hVolume) { int len = MultiByteToWideChar( CP_ACP, 0, pszvolname, -1, NULL, 0); MultiByteToWideChar(CP_ACP, 0, pszvolname, -1, lpszVolumeName, len); } return hVolume; } //****************************************************************************** //****************************************************************************** BOOL WIN32API FindNextVolumeA(HANDLE hFindVolume, LPTSTR lpszVolumeName, DWORD cchBufferLength) { VOLINFO *pVolInfo; char szdrive[3]; DWORD DeviceType; char szVolume[256]; if(!VERSION_IS_WIN2000_OR_HIGHER()) { SetLastError(ERROR_NOT_SUPPORTED); return FALSE; } pVolInfo = (VOLINFO *)GlobalLock(hFindVolume); if(pVolInfo == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } if(OSLibLVMQueryVolumeName(pVolInfo->hLVMVolumeControlData, &pVolInfo->lastvol, szVolume, sizeof(szVolume)) == FALSE) { SetLastError(ERROR_NO_MORE_FILES); GlobalUnlock(hFindVolume); return FALSE; } if(strlen(szVolume) + 14 + 1 > cchBufferLength) { SetLastError(ERROR_INSUFFICIENT_BUFFER); GlobalUnlock(hFindVolume); return FALSE; } sprintf(lpszVolumeName, VOLUME_NAME_PREFIX"{%s}\\", szVolume); dprintf(("FindNextVolumeA returned %s", lpszVolumeName)); pVolInfo->lastvol++; GlobalUnlock(hFindVolume); SetLastError(ERROR_SUCCESS); return TRUE; } //****************************************************************************** //****************************************************************************** BOOL WIN32API FindNextVolumeW(HANDLE hFindVolume, LPWSTR lpszVolumeName, DWORD cchBufferLength) { LPSTR pszvolnameA = NULL; BOOL ret; if(!VERSION_IS_WIN2000_OR_HIGHER()) { SetLastError(ERROR_NOT_SUPPORTED); return FALSE; } if(cchBufferLength) { pszvolnameA = (char *)alloca(cchBufferLength); } ret = FindNextVolumeA(hFindVolume, pszvolnameA, cchBufferLength); if(ret) { int len = MultiByteToWideChar( CP_ACP, 0, pszvolnameA, -1, NULL, 0); MultiByteToWideChar(CP_ACP, 0, pszvolnameA, -1, lpszVolumeName, len); } return ret; } //****************************************************************************** //****************************************************************************** BOOL WIN32API FindVolumeClose(HANDLE hFindVolume) { VOLINFO *pVolInfo; if(!VERSION_IS_WIN2000_OR_HIGHER()) { SetLastError(ERROR_NOT_SUPPORTED); return FALSE; } if(hFindVolume) { pVolInfo = (VOLINFO *)GlobalLock(hFindVolume); OSLibLVMFreeVolumeControlData(pVolInfo->hLVMVolumeControlData); GlobalUnlock(hFindVolume); GlobalFree(hFindVolume); return TRUE; } return FALSE; } //****************************************************************************** //****************************************************************************** HANDLE WIN32API FindFirstVolumeMountPointA(LPTSTR lpszRootPathName, LPTSTR lpszVolumeMountPoint, DWORD cchBufferLength) { if(!VERSION_IS_WIN2000_OR_HIGHER()) { SetLastError(ERROR_NOT_SUPPORTED); return INVALID_HANDLE_VALUE; } SetLastError(ERROR_NO_MORE_FILES); return INVALID_HANDLE_VALUE; } //****************************************************************************** //****************************************************************************** HANDLE WIN32API FindFirstVolumeMountPointW(LPWSTR lpszRootPathName, LPWSTR lpszVolumeMountPoint, DWORD cchBufferLength) { LPSTR pszmountpointnameA = NULL; LPSTR pszrootA = NULL; HANDLE hVolume; if(!VERSION_IS_WIN2000_OR_HIGHER()) { SetLastError(ERROR_NOT_SUPPORTED); return INVALID_HANDLE_VALUE; } if(cchBufferLength) { pszmountpointnameA = (char *)alloca(cchBufferLength); } if(lpszRootPathName) { pszrootA = (char *)alloca(lstrlenW(lpszRootPathName)+1); int len = WideCharToMultiByte( CP_ACP, 0, lpszRootPathName, -1, NULL, 0, 0, NULL); WideCharToMultiByte(CP_ACP, 0, lpszRootPathName, -1, pszrootA, len, 0, NULL); } hVolume = FindFirstVolumeMountPointA(pszrootA, pszmountpointnameA, cchBufferLength); if(hVolume) { int len = MultiByteToWideChar( CP_ACP, 0, pszmountpointnameA, -1, NULL, 0); MultiByteToWideChar(CP_ACP, 0, pszmountpointnameA, -1, lpszVolumeMountPoint, len); } return hVolume; } //****************************************************************************** //****************************************************************************** BOOL WIN32API FindNextVolumeMountPointA(HANDLE hFindVolumeMountPoint, LPTSTR lpszVolumeMountPoint, DWORD cchBufferLength) { if(!VERSION_IS_WIN2000_OR_HIGHER()) { SetLastError(ERROR_NOT_SUPPORTED); return FALSE; } SetLastError(ERROR_NO_MORE_FILES); return FALSE; } //****************************************************************************** //****************************************************************************** BOOL WIN32API FindNextVolumeMountPointW(HANDLE hFindVolumeMountPoint, LPWSTR lpszVolumeMountPoint, DWORD cchBufferLength) { LPSTR pszmoutpointnameA = NULL; BOOL ret; if(!VERSION_IS_WIN2000_OR_HIGHER()) { SetLastError(ERROR_NOT_SUPPORTED); return FALSE; } if(cchBufferLength) { pszmoutpointnameA = (char *)alloca(cchBufferLength); } ret = FindFirstVolumeA(pszmoutpointnameA, cchBufferLength); if(ret) { int len = MultiByteToWideChar( CP_ACP, 0, pszmoutpointnameA, -1, NULL, 0); MultiByteToWideChar(CP_ACP, 0, pszmoutpointnameA, -1, lpszVolumeMountPoint, len); } return ret; } //****************************************************************************** //****************************************************************************** BOOL WIN32API FindVolumeMountPointClose(HANDLE hFindVolumeMountPoint) { if(!VERSION_IS_WIN2000_OR_HIGHER()) { SetLastError(ERROR_NOT_SUPPORTED); return FALSE; } if(hFindVolumeMountPoint) { GlobalFree(hFindVolumeMountPoint); return TRUE; } return FALSE; } //****************************************************************************** //****************************************************************************** BOOL WIN32API GetVolumeNameForVolumeMountPointA(LPCSTR lpszVolumeMountPoint, LPSTR lpszVolumeName, DWORD cchBufferLength) { LPSTR pszvol; pszvol = (char *)alloca(cchBufferLength); if(pszvol == NULL) { DebugInt3(); return FALSE; } if(!VERSION_IS_WIN2000_OR_HIGHER()) { SetLastError(ERROR_NOT_SUPPORTED); return FALSE; } if(OSLibLVMGetVolumeNameForVolumeMountPoint(lpszVolumeMountPoint, pszvol, cchBufferLength) == TRUE) { int length = strlen(pszvol); if(length + sizeof(VOLUME_NAME_PREFIX) - 1 + 3 > cchBufferLength) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } sprintf(lpszVolumeName, VOLUME_NAME_PREFIX"{%s}\\", pszvol); dprintf(("KERNEL32: GetVolumeNameForVolumeMountPointA %s returned %s", lpszVolumeMountPoint, lpszVolumeName)); SetLastError(ERROR_SUCCESS); return TRUE; } dprintf(("KERNEL32: GetVolumeNameForVolumeMountPointA: %s not found!!", lpszVolumeMountPoint)); SetLastError(ERROR_FILE_NOT_FOUND); return FALSE; } //****************************************************************************** //****************************************************************************** BOOL WIN32API GetVolumeNameForVolumeMountPointW(LPCWSTR lpszVolumeMountPoint, LPWSTR lpszVolumeName, DWORD cchBufferLength) { LPSTR pszmoutpointnameA = NULL; LPSTR pszvolumenameA = NULL; BOOL ret; int len; if(!VERSION_IS_WIN2000_OR_HIGHER()) { SetLastError(ERROR_NOT_SUPPORTED); return FALSE; } len = WideCharToMultiByte( CP_ACP, 0, lpszVolumeMountPoint, -1, NULL, 0, 0, NULL); pszmoutpointnameA = (char *)alloca(len+1); WideCharToMultiByte(CP_ACP, 0, lpszVolumeMountPoint, -1, pszmoutpointnameA, len, 0, NULL); if(cchBufferLength && lpszVolumeName) { pszvolumenameA = (char *)alloca(cchBufferLength); } ret = GetVolumeNameForVolumeMountPointA(pszmoutpointnameA, pszvolumenameA, cchBufferLength); if(ret) { int len = MultiByteToWideChar( CP_ACP, 0, pszvolumenameA, -1, NULL, 0); MultiByteToWideChar(CP_ACP, 0, pszvolumenameA, -1, lpszVolumeName, len); } return ret; } //****************************************************************************** //****************************************************************************** BOOL WIN32API GetVolumePathNameA(LPCSTR lpszFileName, LPSTR lpszVolumePathName, DWORD cchBufferLength) { if(!VERSION_IS_WIN2000_OR_HIGHER()) { SetLastError(ERROR_NOT_SUPPORTED); return FALSE; } if(!*lpszFileName) { // According to MSDN: SetLastError(ERROR_SUCCESS); return FALSE; } // We only support drive letters as volume names if(cchBufferLength < 3) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } CHAR fullName[MAX_PATH]; DWORD rc = GetFullPathNameA(lpszFileName, sizeof(fullName), fullName, NULL); if (rc == 0 || rc > sizeof(fullName)) return FALSE; if(fullName[0] == '\\' && fullName[1] == '\\') { // UNC path, search for the 2nd single slash: we should return "\\foo\bar\" LPSTR slash1 = strchr(&fullName[2], '\\'); if(!slash1 || slash1 - fullName == 2) { SetLastError(ERROR_INVALID_NAME); return FALSE; } LPSTR slash2 = strchr(slash1 + 1, '\\'); if(!slash2 || slash2 - slash1 == 1) { SetLastError(ERROR_INVALID_NAME); return FALSE; } DWORD len = slash2 - fullName + 1; // with trailing slash if(cchBufferLength < len + 1) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } memcpy(lpszVolumePathName, fullName, len); lpszVolumePathName[len] = '\0'; } else { lpszVolumePathName[0] = fullName[0]; lpszVolumePathName[1] = ':'; if(cchBufferLength == 3) { lpszVolumePathName[2] = '\0'; } else { lpszVolumePathName[2] = '\\'; lpszVolumePathName[3] = '\0'; } } dprintf(("KERNEL32: GetVolumePathNameA %s returned %s", lpszFileName, lpszVolumePathName)); SetLastError(ERROR_SUCCESS); return TRUE; } //****************************************************************************** //****************************************************************************** BOOL WIN32API GetVolumePathNameW(LPCWSTR lpszFileName, LPWSTR lpszVolumePathName, DWORD cchBufferLength) { LPSTR lpszFileNameA = NULL; LPSTR lpszVolumePathNameA = NULL; BOOL ret; int len; if(!VERSION_IS_WIN2000_OR_HIGHER()) { SetLastError(ERROR_NOT_SUPPORTED); return FALSE; } len = WideCharToMultiByte( CP_ACP, 0, lpszFileName, -1, NULL, 0, 0, NULL); lpszFileNameA = (char *)alloca(len+1); WideCharToMultiByte(CP_ACP, 0, lpszFileName, -1, lpszFileNameA, len, 0, NULL); if(cchBufferLength && lpszVolumePathName) { lpszVolumePathNameA = (char *)alloca(cchBufferLength); } ret = GetVolumePathNameA(lpszFileNameA, lpszVolumePathNameA, cchBufferLength); if(ret) { int len = MultiByteToWideChar( CP_ACP, 0, lpszVolumePathNameA, -1, NULL, 0); MultiByteToWideChar(CP_ACP, 0, lpszVolumePathNameA, -1, lpszVolumePathName, len); } return ret; } //****************************************************************************** //******************************************************************************