Results 1 to 5 of 5

Thread: Retrieve Volume(s) GUID(s) in windows

  1. #1
    Member DirectuX's Avatar
    Join Date
    Oct 2018
    Location
    France
    Posts
    417
    Rep Power
    55

    Question Retrieve Volume(s) GUID(s) in windows

    Hi,
    until now I've thought about two methods to get the GUIDs :


    method 1: Capturing mountvol.exe output
    Adapting this : https://www.thinbasic.com/community/...Execute-Output

    '---Load Console Module
    Uses "Console"
    
    USES "File"
    uses "Console"
    uses "OS"
    
    Dim sTempFile as string 'complete path to the temporary file that will contain the output of the command
    dim sCommande as string 'command to send to shell
    dim sBuffer as string 'this will contain the output of the command read from the temporary file
    
    sTempFile = OS_GetTempDir & "test1.txt"
    sCommande = OS_ENVIRON("COMSPEC") & " /C " & " mountvol.exe > " & sTempFile
    msgboxw 0,sCommande 'check what will be send to shell
    
    'RunOnce: set console font for thinBasic and cdm.exe
    '
    'uses "registry"
    'Registry_SetValue("HKEYCU", "Console\O:_thinBasic_thinBasic.exe", "FaceName", "Lucida Console")
    'Registry_SetValue("HKEYCU", "Console\C:_Windows_System32_cmd.exe", "FaceName", "Lucida Console")
    '/!\01 Doesn't behave as whished, had to manually change font setting in console's property panel. Rebooting doesn't help.
    
    
    Console_SetOutputCP(65001)'Set output codepage to UTF-8
    Console_Writeline("Test Console App: éùçàëØ€")'Test console output
    'Display is ok after manual console-font change, this is not convenient for final user
    
    
    OS_Shell(sCommande, %OS_WNDSTYLE_HIDE, %OS_SHELL_SYNC)
    sBuffer += file_load(sTempFile)
    ' /!\02 File contains many commas where accentuated characters have to be
    
    msgboxw 0, sBuffer
    ' /!\03 Text displayed contains many `?` where accentuated characters have to be
    
    PrintL "Press a key to end program"
    '---Wait for a key press
    WaitKey
    


    method 2: Calling kernel32.dll functions (Prefered as no file is written, no change to system's console configuration)
    https://docs.microsoft.com/fr-fr/win...ment-functions

    Adapting this : https://www.thinbasic.com/community/...on-from-handle

    
    Uses "OS"
    Uses "console"
    
    '---
    
    '---Standard API functions to get a function address. Those functions are used to simulate Petr SomeDirtyAPIToTellMeHandle function
    
    '---
    
    Declare Function LoadLibrary    Lib "KERNEL32.DLL" Alias "LoadLibraryA"   (lpLibFileName As ASCIIZ) As Long
    Declare Function GetProcAddress Lib "KERNEL32.DLL" Alias "GetProcAddress" (ByVal hModule As DWORD, lpProcName As ASCIIZ) As Long
    
    
    '---
    
    '---Standard API functions to Data Access and Storage. https://docs.microsoft.com/fr-fr/windows/desktop/api/fileapi/
    '   (Memo, this may help too: https://www.codeproject.com/Articles/27355/Inside-Mountvol-exe)
    '---
    
    Declare Function FindFirstVolume (byref lpszVolumeName As Long, cchBufferLength as dword) As Long
    Declare Function FindNextVolume (byref hFindVolume as long,byref lpszVolumeName as long,byref cchBufferLength as Dword) as boolean
    Declare Function FindVolumeClose (byref hFindVolume AS long) as boolean
    '/!\  01 Can't find in thinBasic's documentation any correspondance table with https://docs.microsoft.com/en-us/windows/desktop/winprog/windows-data-types , best guess:
    'BOOL -> Boolean
    'Handle -> Long
    'LPWSTR -> Long
    'DWORD -> Dword
    'TCHAR -> ? (8 or 16-bit Unicode character)
     
    
    '---OK, here we start simulating the assigment of the procedure address
    
    Dim hLib As Long
    Dim hProc As Long
    Dim hProc2 As Long
    dim hProc3 as Long
     
    
    '---First we need to load the library from where we want the address of the function
    
    hLib = LoadLibrary("KERNEL32.DLL")
    
    '---If return value is NOT zero all is ok
    
    If hLib <> 0 Then
    
    '---Now we try to get the address of the prodecure inside the library
    
    hProc = GetProcAddress(hLib, "FindFirstVolumeW")
    hProc2 = GetProcAddress(hLib, "FindNextVolumeW")
    hProc3 = GetProcAddress(hLib, "FindVolumeClose")
    
      '---If return value is NOT zero all is ok
    
      If hProc <> 0 and hproc2 <> 0 and hproc3 <> 0 Then
    
    
        '---
    
        '---Here the new thinBasic functionality. It assign a process address to a generic previously declared function allowing subsequent calling
    
    
        Declare Set ADDRESS FindFirstVolume, hProc
        Declare Set ADDRESS FindNextVolume, hProc2
        Declare Set ADDRESS FindVolumeClose, hProc3
         
    
        '---Now we try to use the functionality 
    
        
        dim VolumeName As String ' will contain the current VolumeName found
        Dim Display as String ' will contain the concatened string to display
        dim lpszVolumeName as long ' pointer to VolumeName
        lpszVolumeName = STRPTR (VolumeName) ' 
    
        Dim cchBufferLength as dword 
        cchBufferLength = 200
    '/!\02 how long ? is it arbitrary ?
        
        dim hFindVolume as long
        dim isClosedVolume as boolean
        isClosedVolume = false
    
        hFindVolume = FindFirstVolume(lpszVolumeName, cchBufferLength)
    '/!\03 This has not populated `VolumeName`
        Display += VolumeName & $CRLF
        do while not isClosedVolume
          DoEvents
          if FindNextVolume(hFindVolume,lpszVolumeName,cchBufferLength) then
    '/!\04 This has returned `0` (false)
            Display += VolumeName & $CRLF
          else
            isClosedVolume = FindVolumeClose(hFindVolume)
          endif    
        loop
        
        MSGBOXw 0, Display
        
      
      Else
    
        MSGBOX 0, "It was not possible to get the procedure address"
    
      End If
    
    Else
    
      MSGBOX 0, "It was not possible to load library"
    
    End If 
    
    
    WaitKey
    
    Method 1 may work but is inconvenient (notice the /!\ in code comments). I can't get method 2 (prefered) to work and examples/discussions found in the forum didn't bring me further than what is above. What didn't I understand about declarations or usage ?

    'ThinAir 1.10.5.0 on Win 8.1 x64

  2. #2
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    57
    Posts
    8,817
    Rep Power
    10
    Ciao DirectuX

    welcome to thinBasic.
    Honestly this is an area I do not know from a programming point of view so I need to study it a bit.
    But I searched WMI world and found something that can be useful.

    I've create below script using iDispatch variable instantiating a WMI engine, asking for info about mounted volumes.

    Check if it does what you need.
    In the meantime I will study API SKD functions.

    Ciao
    Eros

    #Region "Script info"
    // This script uses WMI to collect and print information regarding logical volumes
    #EndRegion
    
    #Region "Web References to resources used in this script"
    // WMI..................: https://msdn.microsoft.com/en-us/library/aa384642(v=vs.85).aspx
    // WMI cimv2............: https://msdn.microsoft.com/en-us/library/aa384463(v=vs.85).aspx
    // Win32_Volume class...: hhttps://msdn.microsoft.com/en-us/library/windows/desktop/aa394515(v=vs.85).aspx
    // Example from.........: http://www.almguide.com/2008/08/getting-drive-and-mount-point-information-using-wmi/
    #EndRegion
    
    #Region "Modules"
      uses "Console"
    #EndRegion
    
    printl "This script uses WMI to collect and print information regarding logical volumes"
    printl "---Press a key to start---"
    WaitKey
    
    string strComputer      = "." 
    iDispatch objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") 
    
    if IsComObject(objWMIService) Then
    
      '---Also check ... NOT NULL
      iDispatch colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Volume WHERE DriveLetter IS NULL")
      'iDispatch colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Volume WHERE DriveLetter IS NOT NULL") 
       
      if IsComObject(colItems) Then
        printl "Items present in colItems collection:", colItems.Count
    
        iDispatch objItem
        For nItem as long = 1 to colItems.Count
            objItem = colItems.ItemIndex(nItem - 1) '---First item in collectins starts at 0
            printl "Volume:", nItem
            printl $tab, "Name..............: ", objItem.Name 
            printl $tab, "Label.............: ", objItem.Label 
            printl $tab, "Caption...........: ", objItem.Caption 
            printl $tab, "DriveLetter.......: ", objItem.DriveLetter 
            printl $tab, "DriveType.........: ", objItem.DriveType
            printl $tab, "FileSystem........: ", objItem.FileSystem
            printl $tab, "SystemName........: ", objItem.SystemName
            printl $tab, "SerialNumber......: ", objItem.SerialNumber
            
            printl 
    
            objItem = Nothing
        Next
    
        colItems = Nothing
      Else
        printl "It was not possible to instantiate colItems"
      end If
    
      objWMIService = Nothing
    Else
      printl "It was not possible to instantiate objWMIService"
    end If
    
    printl "---All done. Press a key to end---"
    WaitKey
    
    Last edited by ErosOlmi; 23-10-2018 at 06:32.
    www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
    Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000

  3. #3
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    57
    Posts
    8,817
    Rep Power
    10
    Here your second method working without the need to get process address, just declare needed functions
    Here I declared ASCII version of the functions

    Uses "console"
    
    
    'LPSTR data type is just a pointer to a string buffer that MUST have enough bytes to receive ... something
    
    
    Declare Function FindFirstVolume  Lib "KERNEL32.DLL" alias "FindFirstVolumeA" (byval lpszVolumeName As dword, byval cchBufferLength as dword) As Long
    Declare Function FindNextVolume   Lib "KERNEL32.DLL" alias "FindNextVolumeA"  (ByVal hFindVolume as long, byval lpszVolumeName as dword, byval cchBufferLength as Dword) as boolean
    Declare Function FindVolumeClose  Lib "KERNEL32.DLL" alias "FindVolumeClose"  (byval hFindVolume AS long) as boolean
    
    
    dim VolumeName      As string = $nul(255) '---Allocate the buffer with some bytes, here we init with nuls
    dim hFindVolume     as long
    dim isClosedVolume  as boolean
    
    
    '---Pass string pointer of the allocated string plus the size. Function must know how much bytes are available
    '---In order NOT to buffer overflow and generate a GPF 
    hFindVolume = FindFirstVolume(strptr(VolumeName), len(VolumeName))
    printl VolumeName
    do 
      if FindNextVolume(hFindVolume, strptr(VolumeName), len(VolumeName)) then
        printl VolumeName
      else
        isClosedVolume = FindVolumeClose(hFindVolume)
      endif   
    loop while not isClosedVolume
    
    
    printl "---Press a key to end---" 
    WaitKey
    
    Last edited by ErosOlmi; 23-10-2018 at 06:48.
    www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
    Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000

  4. #4
    Member DirectuX's Avatar
    Join Date
    Oct 2018
    Location
    France
    Posts
    417
    Rep Power
    55

    Thumbs up

    Quote Originally Posted by ErosOlmi View Post
    welcome to thinBasic.
    Thanks.


    But I searched WMI world and found something that can be useful.

    I've create below script using iDispatch variable instantiating a WMI engine, asking for info about mounted volumes.

    Check if it does what you need.

    I checked it. I found it to be a more difficult method to me. First, although you provided resource links, it's not easy, to me again, to find the right keywords at msdn with this way of programming. Secondly, WMI doesn't return GUID for mounted volumes but their letter instead.


    Here your second method working
    That's inspiring, I'll go with this. Thanks again ErosOlmi.

  5. #5
    Member DirectuX's Avatar
    Join Date
    Oct 2018
    Location
    France
    Posts
    417
    Rep Power
    55

    Lightbulb

    Fourth method:

    (inspired by https://www.thinbasic.com/public/pro...mi_getdata.htm)


    Eros, do you have a preference recommendation (regarding thinBasic development, help page states "WMI module is still highly experimental.") between this method (WMI_GetData) and idispatch method ?




    Uses "WMI", "OS"
    
    Uses "CONSOLE"
    
     
    
    Dim vData()       As String
    
    Dim nItems        As Long
    
    Dim Counter       As Long
    
    Dim ComputerName  As String = OS_GetComputerName
    
    Dim sBuffer       As String
    
     
    
    '--- Ask data to WMI system
    
    
    sBuffer = WMI_GetData(ComputerName, "", "", "", "Win32_Volume")
    
    
    ' -- Parse returned data into single lines
    
    nItems = Parse( sBuffer, vData(), $CRLF) 
    
     
    
    '---Print lines                           
    
    For Counter = 1 To nItems                 
    
      Printl vData(Counter)        
    
    Next                                     
    
     
    
    '---Finished                              
    
    Printl "-----------------------------------------------------"
    
    Printl "Number of lines: " & nItems                           
    
    Printl "---------------------------Press a key to finish-----"   
    
     
    
    WaitKey
    
    ThinBasic 1.11.6.0 ALPHA - Windows 8.1 x64

Similar Threads

  1. How to retrieve thumb position of canvas?
    By EmbeddedMan in forum UI (User Interface)
    Replies: 5
    Last Post: 13-02-2018, 22:24
  2. GUID (not a real type)
    By Vandalf in forum Fixed or cleared errors in help material
    Replies: 1
    Last Post: 06-03-2017, 07:55
  3. Script to retrieve each process CPU usage
    By Petr Schreiber in forum Real world situations and solutions using thinBasic
    Replies: 5
    Last Post: 16-04-2011, 11:52
  4. How to retrieve a return value from thinBasic_FunctionSimpleCall?
    By Michael Hartlef in forum Module SDK (Freebasic version)
    Replies: 6
    Last Post: 10-09-2010, 22:44
  5. Replies: 7
    Last Post: 25-07-2008, 11:46

Members who have read this thread: 0

There are no members to list at the moment.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •