Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

DRIVE OBJECT wrapper functions

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • DRIVE OBJECT wrapper functions

    ' Wrapper functions and procedures to use the Drive object
    ' included in the Microsoft Scriptin Runtime (scrrun.dll).

    ' The routines access directly the COM functions through the VTable
    ' which is faster than the Invoke method used by COM Automation.

    ' Another advantage is that each routine returns an error code,
    ' instead of the infamous %DISP_E_EXCEPTION (decimal -2147614729,
    ' hexadecimal &H80020009)
    Code:
    ' *********************************************************************************************
    ' DRIVE OBJECT
    ' Provides access to the properties of a particular disk drive or network share.
    ' *********************************************************************************************
    
      #DIM ALL
      #DEBUG ERROR ON
      #INCLUDE "win32api.INC"
    
      GLOBAL Drv_Error_Code AS DWORD
    
      '   MIDL___MIDL_itf_scrrun_0094_0001:
      %MIDL___MIDL_itf_scrrun_0094_0001_UnknownType = 0
      %MIDL___MIDL_itf_scrrun_0094_0001_Removable = 1
      %MIDL___MIDL_itf_scrrun_0094_0001_Fixed = 2
      %MIDL___MIDL_itf_scrrun_0094_0001_Remote = 3
      %MIDL___MIDL_itf_scrrun_0094_0001_CDRom = 4
      %MIDL___MIDL_itf_scrrun_0094_0001_RamDisk = 5
    
      TYPE SAFEARRAYBOUNDTYPE
         cElements AS DWORD
         lLbound   AS LONG
      END TYPE
    
      TYPE SAFEARRAYTYPE
         cDims      AS WORD
         fFeatures  AS WORD
         cbElements AS DWORD
         cLocks     AS DWORD
         pvData     AS DWORD
         rgsabound(0 TO 1) AS SAFEARRAYBOUNDTYPE
      END TYPE
    
    
      DECLARE FUNCTION SafeArrayCreate LIB "OLEAUT32.DLL" ALIAS "SafeArrayCreate" (BYVAL vt AS WORD, BYVAL cDims AS DWORD, BYREF rgsabound AS SAFEARRAYBOUNDTYPE) AS DWORD
      DECLARE FUNCTION SafeArrayDestroy LIB "OLEAUT32.DLL" ALIAS "SafeArrayDestroy" (BYVAL psa AS DWORD) AS DWORD
      DECLARE FUNCTION SafeArrayGetElement LIB "OLEAUT32.DLL" ALIAS "SafeArrayGetElement" (BYVAL psa AS DWORD, BYVAL rgIndices AS LONG, BYVAL pv AS DWORD) AS DWORD
      DECLARE FUNCTION SafeArrayGetLBound LIB "OLEAUT32.DLL" ALIAS "SafeArrayGetLBound" (BYVAL psa AS DWORD, BYVAL nDim AS DWORD, BYREF plLbound AS LONG) AS DWORD
      DECLARE FUNCTION SafeArrayGetUBound LIB "OLEAUT32.DLL" ALIAS "SafeArrayGetUBound" (BYVAL psa AS DWORD, BYVAL nDim AS DWORD, BYREF plUbound AS LONG) AS DWORD
      DECLARE FUNCTION SafeArrayPutElement LIB "OLEAUT32.DLL" ALIAS "SafeArrayPutElement" (BYVAL psa AS DWORD, BYVAL rgIndices AS LONG, BYVAL pv AS DWORD) AS DWORD
    
    ' *********************************************************************************************
    ' HRESULT Drives([out,retval] **IDriveCollection pReturn)
    ' Returns a Drives collection consisting of all Drive objects available on the local machine.
    ' Example: lpDrives = IDrive_GetDrives(lpFso)
    ' *********************************************************************************************
      DECLARE FUNCTION Template_IDrive_GetDrives CDECL(BYVAL pThis AS DWORD, BYREF pReturn AS DWORD) AS DWORD
    ' *********************************************************************************************
      FUNCTION IDrive_GetDrives (BYVAL lpFso AS DWORD) EXPORT AS DWORD
         LOCAL lpDrives AS DWORD
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = lpFso
         pvtbl = @ppthis
         ppmethod = pvtbl + 28
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IDrive_GetDrives(lpFso, lpDrives) TO Drv_Error_Code
         FUNCTION = lpDrives
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT GetDrive([in] BSTR DriveSpec, [out,retval] **IDrive pReturn)
    ' Returns a Drive object corresponding to the drive in a specified path.
    ' Example: lpDrive = IDrive_GetDrive(lpFso, "C:")
    ' *********************************************************************************************
      DECLARE FUNCTION Template_IDrive_GetDrive CDECL(BYVAL pThis AS DWORD, BYVAL DriveSpec AS DWORD, BYREF pReturn AS DWORD) AS DWORD
    ' *********************************************************************************************
      FUNCTION IDrive_GetDrive (BYVAL lpFso AS DWORD, strDriveSpec AS STRING) EXPORT AS DWORD
         LOCAL lpDrive AS DWORD
         LOCAL uDriveSpec AS STRING
         uDriveSpec = UCODE$(strDriveSpec)
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = lpFSO
         pvtbl = @ppthis
         ppmethod = pvtbl + 76
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IDrive_GetDrive(lpFso, STRPTR(uDriveSpec), lpDrive) TO Drv_Error_Code
         FUNCTION = lpDrive
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT Path([out,retval] *BSTR pReturn)
    ' Returns the path for a specified drive.
    ' **********************************************************************************************
      DECLARE FUNCTION Template_IDrive_GetDrivePath CDECL(BYVAL pThis AS DWORD, BYVAL pReturn AS DWORD) AS DWORD
    ' *********************************************************************************************
      FUNCTION IDrive_GetDrivePath (BYVAL lpDrive AS DWORD) EXPORT AS STRING
         LOCAL uPath AS STRING
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = lpDrive
         pvtbl = @ppthis
         ppmethod = pvtbl + 28
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IDrive_GetDrivePath(lpDrive, VARPTR(uPath)) TO Drv_Error_Code
         FUNCTION = ACODE$(uPath)
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT DriveLetter([out,retval] *BSTR pReturn)
    ' Returns the drive letter of a physical local drive or a network share. Read-only.
    ' Example:
    ' lpFile = IDrive_GetFile(lpFso, "H:\Archivos de Programa\Image Browser")
    ' strDriveLetter = IDrive_GetDriveLetter(lpFile)
    ' **********************************************************************************************
      DECLARE FUNCTION Template_IDrive_GetDriveLetter CDECL(BYVAL pThis AS DWORD, BYVAL pReturn AS DWORD) AS DWORD
    ' *********************************************************************************************
      FUNCTION IDrive_GetDriveLetter (BYVAL lpDrive AS DWORD) EXPORT AS STRING
         LOCAL uDriveLetter AS STRING
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = lpDrive
         pvtbl = @ppthis
         ppmethod = pvtbl + 32
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IDrive_GetDriveLetter(lpDrive, VARPTR(uDriveLetter)) TO Drv_Error_Code
         FUNCTION = ACODE$(uDriveLetter)
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT ShareName([out,retval] *BSTR pReturn)
    ' Returns the network share name for a specified drive.
    ' Example:
    ' lpDrive = IDrive_GetDrive(lpFso, "A")
    ' strShareName = IDrive_GetShareName(lpDrive)
    ' **********************************************************************************************
      DECLARE FUNCTION Template_IDrive_GetShareName CDECL(BYVAL pThis AS DWORD, BYVAL pReturn AS DWORD) AS DWORD
    ' *********************************************************************************************
      FUNCTION IDrive_GetShareName (BYVAL lpDrive AS DWORD) EXPORT AS STRING
         LOCAL uShareName AS STRING
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = lpDrive
         pvtbl = @ppthis
         ppmethod = pvtbl + 36
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IDrive_GetShareName(lpDrive, VARPTR(uShareName)) TO Drv_Error_Code
         FUNCTION = ACODE$(uShareName)
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT DriveType([out,retval] *DriveTypeConst pReturn)
    ' Returns a value indicating the type of a specified drive.
    ' Example:
    ' lpDrive = IDrive_GetDrive(lpFso, "A")
    ' lType = IDrive_GetDriveType(lpDrive)
    ' *********************************************************************************************
      DECLARE FUNCTION Template_IDrive_GetDriveType CDECL(BYVAL pThis AS DWORD, BYREF pReturn AS LONG) AS DWORD
    ' *********************************************************************************************
      FUNCTION IDrive_GetDriveType (BYVAL lpDrive AS DWORD) EXPORT AS LONG
         LOCAL lpType AS LONG
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = lpDrive
         pvtbl = @ppthis
         ppmethod = pvtbl + 40
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IDrive_GetDriveType(lpDrive, lpType) TO Drv_Error_Code
         FUNCTION = lpType
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT RootFolder([out,retval] **IFolder pReturn)
    ' Returns a Folder object representing the root folder of a specified drive. Read-only.
    ' Example:
    ' lpDrive = IDrive_GetDrive(lpFso, "A")
    ' lpRootfolder = IDrive_GetRootFolder(lpDrive)
    ' *********************************************************************************************
      DECLARE FUNCTION Template_IDrive_GetRootFolder CDECL(BYVAL pThis AS DWORD, BYREF pReturn AS DWORD) AS DWORD
    ' *********************************************************************************************
      FUNCTION IDrive_GetRootFolder (BYVAL lpDrive AS DWORD) EXPORT AS DWORD
         LOCAL lpRootFolder AS LONG
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = lpDrive
         pvtbl = @ppthis
         ppmethod = pvtbl + 44
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IDrive_GetRootFolder(lpDrive, lpRootFolder) TO Drv_Error_Code
         FUNCTION = lpRootFolder
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT AvailableSpace([out,retval] *VARIANT pReturn)
    ' Returns the amount of space available to a user on the specified drive or network share.
    ' Example:
    ' lpDrive = IDrive_GetDrive(lpFso, "A")
    ' qSize = IDrive_GetAvailableSpace(lpDrive)
    ' **********************************************************************************************
      DECLARE FUNCTION Template_IDrive_GetAvailableSpace CDECL(BYVAL pThis AS DWORD, BYREF pReturn AS VARIANT) AS DWORD
    ' *********************************************************************************************
      FUNCTION IDrive_GetAvailableSpace (BYVAL lpDrive AS DWORD) EXPORT AS QUAD
         LOCAL qSpace AS QUAD
         LOCAL vSpace AS VARIANT
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = lpDrive
         pvtbl = @ppthis
         ppmethod = pvtbl + 48
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IDrive_GetAvailableSpace(lpDrive, vSpace) TO Drv_Error_Code
         FUNCTION = VARIANT#(vSpace)
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT FreeSpace([out,retval] *VARIANT pReturn)
    ' Returns the amount of free space available to a user on the specified drive or network share.
    ' Example:
    ' lpDrive = IDrive_GetDrive(lpFso, "A")
    ' qSize = IDrive_GetFreeSpace(lpDrive)
    ' **********************************************************************************************
      DECLARE FUNCTION Template_IDrive_GetFreeSpace CDECL(BYVAL pThis AS DWORD, BYREF pReturn AS VARIANT) AS DWORD
    ' *********************************************************************************************
      FUNCTION IDrive_GetFreeSpace (BYVAL lpDrive AS DWORD) EXPORT AS QUAD
         LOCAL qSpace AS QUAD
         LOCAL vSpace AS VARIANT
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = lpDrive
         pvtbl = @ppthis
         ppmethod = pvtbl + 52
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IDrive_GetFreeSpace(lpDrive, vSpace) TO Drv_Error_Code
         FUNCTION = VARIANT#(vSpace)
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT TotalSize([out,retval] *VARIANT pReturn)
    ' Returns the total space, in bytes, of a drive or network share.
    ' Example:
    ' lpDrive = IDrive_GetDrive(lpFso, "A")
    ' qSize = IDrive_GetTotalSize(lpDrive)
    ' **********************************************************************************************
      DECLARE FUNCTION Template_IDrive_GetTotalSize CDECL(BYVAL pThis AS DWORD, BYREF pReturn AS VARIANT) AS DWORD
    ' *********************************************************************************************
      FUNCTION IDrive_GetTotalSize (BYVAL lpDrive AS DWORD) EXPORT AS QUAD
         LOCAL qSize AS QUAD
         LOCAL vSize AS VARIANT
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = lpDrive
         pvtbl = @ppthis
         ppmethod = pvtbl + 56
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IDrive_GetTotalSize(lpDrive, vSize) TO Drv_Error_Code
         FUNCTION = VARIANT#(vSize)
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT VolumeName([out,retval] *BSTR pReturn)
    ' Sets or returns the volume name of the specified drive. Read/write.
    ' Example:
    ' lpDrive = IDrive_GetDrive(lpFso, "A")
    ' strVolumeName = IDrive_GetVolumeName(lpDrive)
    ' **********************************************************************************************
      DECLARE FUNCTION Template_IDrive_GetVolumeName CDECL(BYVAL pThis AS DWORD, BYVAL pReturn AS DWORD) AS DWORD
    ' *********************************************************************************************
      FUNCTION IDrive_GetVolumeName (BYVAL lpDrive AS DWORD) EXPORT AS STRING
         LOCAL uVolumeName AS STRING
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = lpDrive
         pvtbl = @ppthis
         ppmethod = pvtbl + 60
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IDrive_GetVolumeName(lpDrive, VARPTR(uVolumeName)) TO Drv_Error_Code
         FUNCTION = ACODE$(uVolumeName)
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT VolumeName([in] BSTR Par0)
    ' Example:
    ' lpDrive = IDrive_GetDrive(lpFso, "A")
    ' IDrive_PutVolumeName lpDrive, "NEW_LABEL"
    ' *********************************************************************************************
      DECLARE FUNCTION Template_IDrive_PutVolumeName CDECL(BYVAL pThis AS DWORD, BYVAL Par0 AS DWORD) AS DWORD
    ' **********************************************************************************************
      SUB IDrive_PutVolumeName (BYVAL lpDrive AS DWORD, strName AS STRING) EXPORT
         LOCAL uName AS STRING
         uName = UCODE$(strName)
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = lpDrive
         pvtbl = @ppthis
         ppmethod = pvtbl + 64
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IDrive_PutVolumeName(lpDrive, STRPTR(uName)) TO Drv_Error_Code
      END SUB
    ' **********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT FileSystem([out,retval] *BSTR pReturn)
    ' Returns the type of file system in use for the specified drive.
    ' Example:
    ' lpDrive = IDrive_GetDrive(lpFso, "A")
    ' strFileSystem = IDrive_GetFileSystem(lpDrive)
    ' **********************************************************************************************
      DECLARE FUNCTION Template_IDrive_GetFileSystem CDECL(BYVAL pThis AS DWORD, BYVAL pReturn AS DWORD) AS DWORD
    ' *********************************************************************************************
      FUNCTION IDrive_GetFileSystem (BYVAL lpDrive AS DWORD) EXPORT AS STRING
         LOCAL uFileSystem AS STRING
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = lpDrive
         pvtbl = @ppthis
         ppmethod = pvtbl + 68
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IDrive_GetFileSystem(lpDrive, VARPTR(uFileSystem)) TO Drv_Error_Code
         FUNCTION = ACODE$(uFileSystem)
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT SerialNumber([out,retval] *I4 pReturn)
    ' Returns the decimal serial number used to uniquely identify a disk volume.
    ' Example:
    ' lpDrive = IDrive_GetDrive(lpFso, "A")
    ' lSerialNumber = IDrive_GetSerialNumber(lpDrive)
    ' *********************************************************************************************
      DECLARE FUNCTION Template_IDrive_GetSerialNumber CDECL(BYVAL pThis AS DWORD, BYREF pReturn AS LONG) AS DWORD
    ' *********************************************************************************************
      FUNCTION IDrive_GetSerialNumber (BYVAL lpDrive AS DWORD) EXPORT AS LONG
         LOCAL lpSerialNumber AS LONG
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = lpDrive
         pvtbl = @ppthis
         ppmethod = pvtbl + 72
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IDrive_GetSerialNumber(lpDrive, lpSerialNumber) TO Drv_Error_Code
         FUNCTION = lpSerialNumber
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT IsReady([out,retval] *BOOL pReturn)
    ' Returns True if the specified drive is ready; False if it is not.
    ' Example:
    ' lpDrive = IDrive_GetDrive(lpFso, "A")
    ' lBool = IDrive_DriveIsReady(lpDrive)
    ' *********************************************************************************************
      DECLARE FUNCTION Template_IDrive_DriveIsReady CDECL(BYVAL pThis AS DWORD, BYREF pReturn AS LONG) AS DWORD
    ' *********************************************************************************************
      FUNCTION IDrive_DriveIsReady (BYVAL lpDrive AS DWORD) EXPORT AS LONG
         LOCAL lpReady AS LONG
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = lpDrive
         pvtbl = @ppthis
         ppmethod = pvtbl + 76
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IDrive_DriveIsReady(lpDrive, lpReady) TO Drv_Error_Code
         FUNCTION = CINT(lpReady)
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' Returns an error message
    ' *********************************************************************************************
      FUNCTION DrvObjError (BYVAL dwError AS DWORD) EXPORT AS STRING
         IF dwError = 0 THEN EXIT FUNCTION
         LOCAL pBuffer   AS ASCIIZ PTR
         LOCAL ncbBuffer AS DWORD
         ncbBuffer = FormatMessage(%FORMAT_MESSAGE_ALLOCATE_BUFFER OR _
            %FORMAT_MESSAGE_FROM_SYSTEM OR %FORMAT_MESSAGE_IGNORE_INSERTS, _
            BYVAL %NULL, dwError, BYVAL MAKELANGID(%LANG_NEUTRAL, %SUBLANG_DEFAULT), _
            BYVAL VARPTR(pBuffer), 0, BYVAL %NULL)
         IF ncbBuffer THEN
            FUNCTION = "Error " & FORMAT$(dwError) & " [&H" & HEX$(dwError, 8) & "] " & @pBuffer
            LocalFree pBuffer
         ELSE
            FUNCTION = "Error " & FORMAT$(dwError) & " [&H" & HEX$(dwError, 8) & "]
         END IF
      END FUNCTION
    ' *********************************************************************************************
    
    
    ' *********************************************************************************************
    ' HRESULT QueryInterface([in] *GUID riid, [out] **VOID ppvObj)
    ' Determines whether the object supports a particular COM interface. If it does, the system
    ' increases the object's reference count, and the application can use that interface
    ' Parameters:
    ' pUnk   [in] : Pointer to the interface to be queried.
    ' riid   [in] : A Guid, passed by reference, that is the interface identifier (IID) of the
    '        requested interface.
    ' ppvObj [out] : Address of pointer variable that receives the interface pointer requested in
    '        riid. Upon successful return, *ppvObject contains the requested interface pointer to
    '        the object. If the object does not support the interface specified in iid, *ppvObject
    '        is set to NULL.
    ' Return Value:
    ' %S_OK if the interface is supported, %E_NOINTERFACE if not.
    ' *********************************************************************************************
      DECLARE FUNCTION Template_IEnumVARIANT_QueryInterface CDECL(BYVAL pUnk AS DWORD, BYREF riid AS GUID, BYVAL ppvObj AS DWORD) AS DWORD
    ' *********************************************************************************************
      FUNCTION IEnumVARIANT_QueryInterface (BYVAL pUnk AS DWORD, BYREF riid AS GUID, BYVAL ppvObj AS DWORD) EXPORT AS DWORD
         LOCAL HRESULT AS DWORD
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = pUnk
         pvtbl = @ppthis
         ppmethod = pvtbl
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IEnumVARIANT_QueryInterface(pUnk, riid, ppvObj) TO HRESULT
         FUNCTION = HRESULT
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' UI4 AddRef()
    ' Increments the reference count on the specified interface.
    ' Returns an integer from 1 to n, the value of the new reference count. This information is
    ' meant to be used for diagnostic/testing purposes only, because, in certain situations, the
    ' value may be unstable.
    ' *********************************************************************************************
      DECLARE FUNCTION Template_IEnumVARIANT_AddRef CDECL(BYVAL pThis AS DWORD) AS DWORD
    ' *********************************************************************************************
      FUNCTION IEnumVARIANT_AddRef (BYVAL pThis AS DWORD) EXPORT AS DWORD
         LOCAL HRESULT AS DWORD
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = pThis
         pvtbl = @ppthis
         ppmethod = pvtbl + 4
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IEnumVARIANT_AddRef(pThis) TO HRESULT
         FUNCTION = HRESULT
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' UI4 Release()
    ' Decrements the reference count on the specified interface.  If the reference count on the
    ' object falls to 0, the object is freed from memory.
    ' Returns the resulting value of the reference count, which is used for diagnostic/testing
    ' purposes only.
    ' *********************************************************************************************
      DECLARE FUNCTION Template_IEnumVARIANT_Release CDECL(BYVAL pThis AS DWORD) AS DWORD
    ' *********************************************************************************************
      FUNCTION IEnumVARIANT_Release (BYVAL pThis AS DWORD) EXPORT AS DWORD
         LOCAL HRESULT AS DWORD
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = pThis
         pvtbl = @ppthis
         ppmethod = pvtbl + 8
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IEnumVARIANT_Release(pThis) TO HRESULT
         FUNCTION = HRESULT
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT Next([in] UI4 celt, [in] *VARIANT rgvar, [out] *UI4 pceltFetched)
    ' The Next method enumerates the next celt elements in the enumerator's list, returning them in
    ' rgelt along with the actual number of enumerated elements in pceltFetched.
    ' Parameters:
    ' celt : [in] Number of items in the array.
    ' rgelt : [out] Address of array containing items.
    ' pceltFetched: [out] Address of variable containing actual number of items.
    ' Return Value:
    ' Returns %S_OK if the method succeeds.
    ' *********************************************************************************************
      DECLARE FUNCTION Template_IEnumVARIANT_Next CDECL(BYVAL pThis AS DWORD, BYVAL celt AS DWORD, BYREF rgelt AS VARIANT, BYREF pceltFetched AS DWORD) AS DWORD
    ' *********************************************************************************************
      FUNCTION IEnumVARIANT_Next (BYVAL pThis AS DWORD, BYVAL celt AS DWORD, BYREF rgelt AS VARIANT, BYREF pceltFetched AS DWORD) EXPORT AS DWORD
         LOCAL HRESULT AS DWORD
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = pThis
         pvtbl = @ppthis
         ppmethod = pvtbl + 12
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IEnumVARIANT_Next(pThis,celt,rgelt,pceltFetched) TO HRESULT
         FUNCTION = HRESULT
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT Skip([in] UI4 celt)
    ' The Skip method Instructs the enumerator to skip the next celt elements in the enumeration so
    ' the next call to IENumVARIANT_Next does not return those elements.
    ' Parameter:
    ' celt : [in] Number of items to skip.
    ' Return Value:
    ' Returns %S_OK if the method succeeds.
    ' *********************************************************************************************
      DECLARE FUNCTION Template_IEnumVARIANT_Skip CDECL(BYVAL pThis AS DWORD, BYVAL celt AS DWORD) AS DWORD
    ' *********************************************************************************************
      FUNCTION IEnumVARIANT_Skip (BYVAL pThis AS DWORD, BYVAL celt AS DWORD) EXPORT AS DWORD
         LOCAL HRESULT AS DWORD
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = pThis
         pvtbl = @ppthis
         ppmethod = pvtbl + 16
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IEnumVARIANT_Skip(pThis,celt) TO HRESULT
         FUNCTION = HRESULT
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT Reset()
    ' The Reset method instructs the enumerator to position itself at the beginning of the list
    ' of elements.
    ' Return Value:
    ' Returns %S_OK if the method succeeds.
    ' *********************************************************************************************
      DECLARE FUNCTION Template_IEnumVARIANT_Reset CDECL(BYVAL pThis AS DWORD) AS DWORD
    ' *********************************************************************************************
      FUNCTION IEnumVARIANT_Reset (BYVAL pThis AS DWORD) EXPORT AS DWORD
         LOCAL HRESULT AS DWORD
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = pThis
         pvtbl = @ppthis
         ppmethod = pvtbl + 20
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IEnumVARIANT_Reset(pThis) TO HRESULT
         FUNCTION = HRESULT
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT Clone([out] **IEnumVARIANT ppenum)
    ' The Clone method creates another items enumerator with the same state as the current
    ' enumerator to iterate over the same list. This method makes it possible to record a point in
    ' the enumeration sequence in order to return to that point at a later time.
    ' Parameters:
    ' pThis : Pointer
    ' ppenum [out] Address of a variable that receives the IEnumVARIANT interface pointer.
    ' Return Value:
    ' Returns %S_OK if the method succeeds.
    ' Remarks
    ' The caller must release the new enumerator separately from the first enumerator.
    ' *********************************************************************************************
      DECLARE FUNCTION Template_IEnumVARIANT_Clone CDECL(BYVAL pThis AS DWORD, BYVAL ppenum AS DWORD) AS DWORD
    ' *********************************************************************************************
      FUNCTION IEnumVARIANT_Clone (BYVAL pThis AS DWORD, BYVAL ppenum AS DWORD) EXPORT AS DWORD
         LOCAL HRESULT AS DWORD
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = pThis
         pvtbl = @ppthis
         ppmethod = pvtbl + 24
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IEnumVARIANT_Clone(pThis,ppenum) TO hresult
         FUNCTION = HRESULT
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' ENUMERATOR - Helper function to enumerate collectios.
    ' Parameter:
    ' pUnk = Pointer to the collection.
    ' Return Value:
    ' Returns a pointer to a safe array containing the contents of the collection or %Null.
    ' It is responsability of the caller to free this safe array.
    ' *********************************************************************************************
      FUNCTION FsoEnumerator (BYVAL pUnk AS DWORD) EXPORT AS DWORD
    
        LOCAL IID_IEnumVariant AS GUID
        IID_IEnumVARIANT = GUID$("{00020404-0000-0000-c000-000000000046}")
    
        LOCAL HRESULT AS DWORD
        LOCAL pIEnumVARIANT AS DWORD
        LOCAL nElements AS DWORD
        LOCAL celtFetched AS DWORD
        LOCAL vRes AS VARIANT
        LOCAL aBound AS SAFEARRAYBOUNDTYPE
        LOCAL hsa AS DWORD
        LOCAL idx AS LONG
    
        IF pUnk = 0 THEN EXIT FUNCTION
    
        ' ------------------------------------------------------------------
        ' Find is the interface is supported
        ' ------------------------------------------------------------------
        HRESULT = IEnumVARIANT_QueryInterface (pUnk, IID_IEnumVARIANT, VARPTR(pIEnumVARIANT))
    
        IF HRESULT <> %S_OK THEN EXIT FUNCTION
    
        ' ------------------------------------------------------------------
        ' Position the enumerator at the beginning of the list of elements
        ' ------------------------------------------------------------------
        HRESULT = IEnumVARIANT_Reset (pIEnumVARIANT)
        IF HRESULT <> %S_OK THEN
           IEnumVARIANT_Release pIEnumVARIANT
           EXIT FUNCTION
        END IF
    
        ' ------------------------------------------------------------------
        ' Count the number of elements in the collection
        ' ------------------------------------------------------------------
        nElements = 0
    
        DO
           HRESULT = IEnumVARIANT_Next (pIEnumVARIANT, 1, vRes, celtFetched)
           IF HRESULT <> %S_OK OR celtFetched < 1 THEN EXIT DO
           nElements = nElements + 1
        LOOP
    
        ' ------------------------------------------------------------------
        ' Exit if the collection is empty
        ' ------------------------------------------------------------------
        IF nElements = 0 THEN
           IEnumVARIANT_Release pIEnumVARIANT
           EXIT FUNCTION
        END IF
    
        ' ------------------------------------------------------------------
        ' Create the safe array
        ' ------------------------------------------------------------------
        aBound.cElements = nElements
        aBound.lLBound = 1
    
        hsa = SafeArrayCreate (%VT_VARIANT, 1, aBound)
        IF hsa = 0 THEN
           IEnumVARIANT_Release pIEnumVARIANT
           EXIT FUNCTION
        END IF
    
        ' ------------------------------------------------------------------
        ' Position the enumerator at the beginning of the list of elements
        ' ------------------------------------------------------------------
        HRESULT = IEnumVARIANT_Reset (pIEnumVARIANT)
        IF HRESULT <> %S_OK THEN
           IEnumVARIANT_Release pIEnumVARIANT
           EXIT FUNCTION
        END IF
    
        ' ------------------------------------------------------------------
        ' Fill the safe array
        ' ------------------------------------------------------------------
        idx = 1
    
        DO
           HRESULT = IEnumVARIANT_Next (pIEnumVARIANT, 1, vRes, celtFetched)
           IF HRESULT <> %S_OK OR celtFetched < 1 THEN EXIT DO
           SafeArrayPutElement hsa, BYVAL VARPTR(idx), BYVAL VARPTR(vRes)
           idx = idx + 1
        LOOP
        ' ------------------------------------------------------------------
        ' Release the collection and return a pointer to the safe array
        ' ------------------------------------------------------------------
    
        HRESULT = IEnumVARIANT_Release(pIEnumVARIANT)
        FUNCTION = hsa
    
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' HRESULT _NewEnum([out,retval] *UNKNOWN pReturn)
    ' Returns a a reference to the IUnknown interface of the Drive collection.
    ' *********************************************************************************************
      DECLARE FUNCTION Template_IDrive_NewEnum CDECL(BYVAL pThis AS DWORD, BYREF pReturn AS DWORD) AS DWORD
    ' *********************************************************************************************
      FUNCTION IDrive_NewEnum (BYVAL lpDrives AS DWORD) EXPORT AS DWORD
         LOCAL lpUnk AS DWORD
         LOCAL ppthis AS DWORD PTR
         LOCAL pvtbl AS DWORD PTR
         LOCAL ppmethod AS DWORD PTR
         LOCAL pmethod AS DWORD
         ppthis = lpDrives
         pvtbl = @ppthis
         ppmethod = pvtbl + 32
         pmethod = @ppmethod
         CALL DWORD pmethod USING Template_IDrive_NewEnum(lpDrives,lpUnk) TO Drv_Error_Code
         FUNCTION = lpUnk
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
    ' Enumerates the Drives collection and returns an array of dwords in a VARIANT.
    ' *********************************************************************************************
    ' Example:
    '
    ' DIM vRes AS VARIANT
    ' DIM aDrives(0) AS DWORD
    ' DIM i AS LONG
    ' IF IDrive_EnumerateDrives(lpFso, vRes) THEN
    '    aDrives() = vRes
    '    FOR i = LBOUND(aDrives) TO UBOUND(aDrives)
    '       STDOUT "Drive: " & IDrive_GetDriveLetter(aDrives(i))
    '    NEXT
    ' END IF
    ' *********************************************************************************************
      FUNCTION IDrive_EnumerateDrives (BYVAL lpDrives AS DWORD, vRes AS VARIANT) EXPORT AS LONG
    
         LOCAL lpUnk AS DWORD
         LOCAL hsa AS DWORD
         LOCAL IEnumLBound AS LONG
         LOCAL iEnumUBound AS LONG
         LOCAL hr AS DWORD
         LOCAL vVar AS VARIANT
         LOCAL i AS LONG
    
         lpUnk = IDrive_NewEnum(lpDrives)
         IF lpUnk THEN
            hsa = FsoEnumerator(lpUnk)
            IF hsa THEN
               SafeArrayGetLBound hsa, 1, IEnumLBound
               SafeArrayGetUBound hsa, 1, IEnumUBound
               REDIM aDrives(IEnumLBound TO iEnumUBound) AS DWORD
               FOR i = IEnumLBound TO IEnumUBound
                  hr = SafearrayGetElement(hsa, BYVAL VARPTR(i), BYVAL VARPTR(vVar))
                  IF hr THEN EXIT FOR
                  aDrives(i) = VARIANT#(vVar)
               NEXT
               SafeArrayDestroy(hsa)   '// Destroy the SafeArray
               vRes = aDrives()        '// Return the array in a VARIANT
               FUNCTION = -1           '// The mark of success
             END IF
         END IF
    
      END FUNCTION
    ' *********************************************************************************************
    
    
    ' *********************************************************************************************
      FUNCTION ShowDriveType (BYVAL lpDrive AS DWORD) AS STRING
    
         DIM S AS STRING
    
         SELECT CASE IDrive_GetDriveType (lpDrive)
         CASE %MIDL___MIDL_itf_scrrun_0094_0001_Removable
            S = "Removable"
         CASE %MIDL___MIDL_itf_scrrun_0094_0001_Fixed
            S = "Fixed"
         CASE %MIDL___MIDL_itf_scrrun_0094_0001_Remote
            S = "Remote"
         CASE %MIDL___MIDL_itf_scrrun_0094_0001_CDRom
            S = "CD-ROM"
         CASE %MIDL___MIDL_itf_scrrun_0094_0001_RamDisk
            S = "RAM Disk"
         CASE ELSE
            S = "Unknown"
         END SELECT
    
         FUNCTION = S
    
      END FUNCTION
    ' *********************************************************************************************
    
    ' *********************************************************************************************
      SUB ShowDriveInformation (BYVAL lpFso AS DWORD)
    
         DIM S AS STRING
         LOCAL lpDrives AS DWORD
         LOCAL i AS LONG
    
         lpDrives = IDrive_GetDrives(lpFso)
    
         DIM vRes AS VARIANT
         DIM aDrives(0) AS DWORD
         IF IDrive_EnumerateDrives(lpDrives, vRes) THEN
            aDrives() = vRes
            FOR i = LBOUND(aDrives) TO UBOUND(aDrives)
               S = S & "Drive letter: " & IDrive_GetDriveLetter(aDrives(i)) & $CRLF
               S = S & "Path: " & IDrive_GetDrivePath(aDrives(i)) & $CRLF
               S = S & "Drive type: " & ShowDriveType(aDrives(i)) & $CRLF
               S = S & "Ready: " & IIF$(IDrive_DriveIsReady(aDrives(i)), "True", "False") & $CRLF
               IF IDrive_DriveIsReady(aDrives(i)) THEN
                  IF IDrive_GetDriveType (aDrives(i)) THEN
                     S = S & "Share name: " & IDrive_GetShareName(aDrives(i)) & $CRLF
                  ELSE
                     S = S & "Volume name: " & IDrive_GetVolumeName(aDrives(i)) & $CRLF
                  END IF
                  S = S & "File system: " & IDrive_GetFileSystem(aDrives(i)) & $CRLF
                  S = S & "Total size: " & STR$(IDrive_GetTotalSize(aDrives(i))) & $CRLF
                  S = S & "Free space: " & STR$(IDrive_GetFreeSpace(aDrives(i))) & $CRLF
                  S = S & "Available space: " & STR$(IDrive_GetAvailableSpace(aDrives(i))) & $CRLF
                  S = S & "Serial number: " & STR$(IDrive_GetSerialNumber(aDrives(i))) & $CRLF
               END IF
               MSGBOX s, %MB_ICONINFORMATION, "Drive information"
               S = ""
            NEXT
         END IF
    
      END SUB
    ' *********************************************************************************************
    
    
    ' *********************************************************************************************
    ' ** Main **
    ' *********************************************************************************************
      FUNCTION PBMAIN
    
        ' -------------------------------------------------------------------------
        ' ** STARTUP **
        ' -------------------------------------------------------------------------
        ' Create an instance of the object.
        ' -------------------------------------------------------------------------
        LOCAL oFso AS DISPATCH
        SET oFso = NEW DISPATCH IN "Scripting.FileSystemObject"
        IF ISFALSE ISOBJECT(oFso) THEN EXIT FUNCTION
        ' -------------------------------------------------------------------------
    
        ' -------------------------------------------------------------------------
        ' Get the object pointer to be used with the wrapper functions
        ' -------------------------------------------------------------------------
        LOCAL lpFso AS DWORD
        lpFso = OBJPTR(oFso)
        ' --------------------------------------------------------------------------
    
        ShowDriveInformation (lpFso)
    
        ' Example of how obtain the total size of a drive
    '    LOCAL lpDrive AS DWORD
    '    lpDrive = IDrive_GetDrive(lpFso, "C")
    '    MSGBOX STR$(IDrive_GetTotalSize(lpDrive))
    
    
        ' -------------------------------------------------------------------------
        ' ** CLEANUP **
        ' -------------------------------------------------------------------------
        ' Release the FileSystem object
        ' -------------------------------------------------------------------------
        SET oFso = NOTHING
    
      END FUNCTION
    ' *********************************************************************************************

    ------------------




    [This message has been edited by JOSE ROCA (edited September 08, 2003).]
Working...
X