*============================================================================== >* Function: GetVolumeInformation >* Purpose: Returns information about the specified volume >* Author: Doug Hennig, from code taken off MSDN >* Copyright: (c) 2001 Stonefield Systems Group Inc. >* Last revision: 02/20/2001 >* Parameters: tcVolume - the volume to get information for >* taArray - an array to hold information about the volume: >* >* Column Information >* ------ ----------- >* 1 Volume name >* 2 Volume serial number >* 3 File system name (FAT, NTFS, etc.) >* 4 .T. if the file system supports case-sensitive >* filenames >* 5 .T. if the file system preserves case of filenames >* 6 .T. if the file system supports Unicode filenames >* 7 .T. if the file system preserves and enforces ACLs >* (NTFS only) >* 8 .T. if the file system supports file-based >* compression >* 9 .T. if the volume is compressed >* 10 maximum filename length >* >* Returns: .T. >* Environment in: none >* Environment out: none >*============================================================================== > >lparameters tcVolume, ; > taArray >local lcVolume, ; > lcVolumeName, ; > lnVolumeNameLen, ; > lnVolumeSerialNumber, ; > lnMaxFileNameLen, ; > lnFileSystemFlags, ; > lcFileSystemName, ; > lnFileSystemNameLen, ; > lcFileInfo, ; > lcFileName, ; > laFiles[1], ; > lnFiles, ; > lnI, ; > lcFile, ; > lnHandle > >* Declare the API function and constants. > >declare GetVolumeInformation in Win32API ; > string lpRootPathName, string @lpVolumeNameBuffer, ; > integer nVolumeNameSize, integer @lpVolumeSerialNumber, ; > integer @lpMaximumComponentLength, integer @lpFileSystemFlags, ; > string @lpFileSystemNameBuffer, integer nFileSystemNameSize > >* If the path wasn't specified, use the current drive. Otherwise, get the drive >* for the specified path, handling UNC paths specially. > >do case > case vartype(tcVolume) <> 'C' or empty(tcVolume) > lcVolume = addbs(sys(5)) > case left(tcVolume, 2) = '\\' > lcVolume = addbs(tcVolume) > lcVolume = left(lcVolume, at('\', lcVolume, 4)) > case len(tcVolume) = 1 > lcVolume = tcVolume + ':\' > otherwise > lcVolume = addbs(justdrive(tcVolume)) >endcase > >* Create the parameters for the API function, then call it. > >lcVolumeName = space(255) >lnVolumeNameLen = len(lcVolumeName) >lnVolumeSerialNumber = 0 >lnMaxFileNameLen = 0 >lnFileSystemFlags = 0 >lcFileSystemName = space(255) >lnFileSystemNameLen = len(lcFileSystemName) >GetVolumeInformation(lcVolume, @lcVolumeName, lnVolumeNameLen, ; > @lnVolumeSerialNumber, @lnMaxFileNameLen, @lnFileSystemFlags, ; > @lcFileSystemName, lnFileSystemNameLen) > >* Put the information into the array. > >dimension taArray[10] >taArray[ 1] = left(lcVolumeName, at(ccNULL, lcVolumeName) - 1) >taArray[ 2] = lnVolumeSerialNumber >taArray[ 3] = left(lcFileSystemName, at(ccNULL, lcFileSystemName) - 1) >taArray[ 4] = bittest(lnFileSystemFlags, cnFS_CASE_SENSITIVE) >taArray[ 5] = bittest(lnFileSystemFlags, cnFS_CASE_IS_PRESERVED) >taArray[ 6] = bittest(lnFileSystemFlags, cnFS_UNICODE_STORED_ON_DISK) >taArray[ 7] = bittest(lnFileSystemFlags, cnFS_PERSISTENT_ACLS) >taArray[ 8] = bittest(lnFileSystemFlags, cnFS_FILE_COMPRESSION) >taArray[ 9] = bittest(lnFileSystemFlags, cnFS_VOL_IS_COMPRESSED) >taArray[10] = lnMaxFileNameLen > >* If the serial number is 0 (which happens with Win95/98 systems on remote >* drives), open a file on the drive and get the file information for it. > >if lnVolumeSerialNumber = 0 > declare GetFileInformationByHandle in Win32API ; > integer lnHandle, string @lcFileInfo > declare integer CreateFile in Win32API ; > string @lcFileName, integer dwDesiredAccess, ; > integer dwShareMode, integer lpSecurityAttributes, ; > integer dwCreationDisposition, integer dwFlagsAndAttributes, ; > integer hTemplateFile > declare CloseHandle in Win32API ; > integer lnHandle > lcFileInfo = space(255) > >* If a file was specified for the volume name, use it. Otherwise, find some >* file we can open. > > if file(tcVolume) > lcFileName = tcVolume > else > lnFiles = adir(laFiles, lcVolume + '*.*') > lcFileName = '' > for lnI = 1 to lnFiles > lcFile = lcVolume + laFiles[lnI, 1] > lnHandle = fopen(lcFile) > fclose(lnHandle) > if lnHandle >= 0 > lcFileName = lcFile > exit > endif lnHandle >= 0 > next lnI > endif file(tcVolume) > if not empty(lcFileName) > lnHandle = CreateFile(@lcFileName, 0, 0, 0, 3, 0, 0) > if lnHandle >= 0 > GetFileInformationByHandle(lnHandle, @lcFileInfo) > CloseHandle(lnHandle) > lnVolumeSerialNumber = Hex2Decimal(substr(lcFileInfo, 29, 4)) > taArray[2] = lnVolumeSerialNumber > endif lnHandle >= 0 > endif not empty(lcFileName) >endif lnVolumeSerialNumber = 0 >return .T. > >*============================================================================== >* Function: Hex2Decimal >* Purpose: Converts a value in Intel format to a decimal value >* Author: Doug Hennig >* Copyright: (c) 1996 Stonefield Systems Group Inc. >* Last Revision: 09/07/99 >* Parameters: tcValue - the value to convert >* tlSigned - .T. if the value is signed >* Returns: the numeric value >* Environment in: none >* Environment out: none >*============================================================================== > >lparameters tcValue, ; > tlSigned >local lnDecimal, ; > lnLen, ; > lnI, ; > lnMSB, ; > lnMax >lnDecimal = 0 >lnLen = len(tcValue) >for lnI = 1 to lnLen > lnDecimal = lnDecimal + asc(substr(tcValue, lnI, 1)) * 256 ^ (lnI - 1) >next lnI >if tlSigned > lnMSB = (lnLen * 8) - 1 > if bittest(lnDecimal, lnMSB) > lnMax = 2 ^ (lnMSB + 1) > lnDecimal = lnResult - lnMax > endif bittest(lnDecimal, lnMSB) >endif tlSigned >return lnDecimal