1

I am new to the win32 api and need help trying to understand how the GetLogicalDrives() function works. I am trying to populate a cbs_dropdownlist with all the available drives that are not in use. here is what I have so far. I would appreciate any help.

void FillListBox(HWND hWndDropMenu)
{
 DWORD drives = GetLogicalDrives();
 for (int i=0; i<26; i++)
 {
    SendMessage(hWndDropMenu, CB_ADDSTRING, 0, (LPARAM)drives);
 }
}
arynhard
  • 473
  • 2
  • 8
  • 26

2 Answers2

10

The function GetLogicalDrives returns a bitmask of the logical drives available. Here is how you would do it:

 DWORD drives = GetLogicalDrives();
 for (int i=0; i<26; i++)
 {
    if( !( drives & ( 1 << i ) ) )
    {
       TCHAR driveName[] = { TEXT('A') + i, TEXT(':'), TEXT('\\'), TEXT('\0') };
       SendMessage(hWndDropMenu, CB_ADDSTRING, 0, (LPARAM)driveName);
    }
 }

The code checks whether the i-th bit in the bitmask is not set to 1 or true.

K-ballo
  • 80,396
  • 20
  • 159
  • 169
  • From what I understand, `GetLogicalDrives()` returns a bitmask which contains a zero if a drive is available. I want to populate a dropdownlist with only the letters not in use. Does `GetLogicalDriveStrings()` return all drives even if they are in use? – arynhard Jun 09 '12 at 17:57
  • @arynhard: Sorry, I missed that you wanted the opposite of the logical drives. Updated my answer to reflect that. – K-ballo Jun 09 '12 at 17:58
  • Thank you! You have been very helpful. – arynhard Jun 09 '12 at 18:02
  • Slight problem. I am getting a bunch of Chinese characters in my list. – arynhard Jun 09 '12 at 18:04
  • @arynhard: I would believe you are using _Unicode_ instead of _MultiByte_ characters, change `CHAR` for `WCHAR` and every occurrence of `'?'` for `L'?'`. Damned those _Windows_ macros that fail to catch the simplest of mistakes... – K-ballo Jun 09 '12 at 18:05
  • Could also be my inexperience :) I still have to learn when and how to use either type. Appreciate the help. – arynhard Jun 09 '12 at 18:07
  • @arynhard: No, its actually a _WinAPI_ design issue for using macros, which don't have means to check the correct types are been used. However, while its an awful design choice in _C++_, _C_ provides no other alternatives... – K-ballo Jun 09 '12 at 18:08
  • @Skurmedel: +1 anyway, your answer provides so much detail. – K-ballo Jun 09 '12 at 18:11
  • I agree. :) Thanks for the depth of info – arynhard Jun 09 '12 at 18:26
  • Better yet, if you want to support both Unicode and MBCS, use the macros intended for that purpose. (Also, I'd declare `drives` as a `const`, but that's a stylistic thing. My style in C++ is to use `const` whenever absolutely possible.) – Cody Gray - on strike Aug 04 '12 at 12:15
4

GetLogicalDrives returns a bitmask and to inspect it you need to use bitwise operators. To see if drive A is in use:

GetLogicalDrives() & 1 == 1

If drive A is unavailable, GetLogicalDrives() & 1 would yield 0 and the condition would fail.

To check the next drive you'll need to use the next multiple of 2, GetLogicalDrives() & 2, GetLogicalDrives() & 4 and so on.

You could use GetLogicalDriveStrings but this returns the inverse of what you want, all the used logical drives.

I would build a table instead, and index into that:

const char *drive_names[] = 
{
    "A:",
    "B:",
    ...
    "Z:"
};

Then your loop could be:

DWORD drives_bitmask = GetLogicalDrives();

for (DWORD i < 0; i < 32; i++)
{
    // Shift 1 to a multiple of 2. 1 << 0 = 1 (0000 0001), 1 << 1 = 2 etc.
    DWORD mask_index = 1 << i;
    if (drives_bitmask & i == 0)
    {
        // Drive unavailable, add it to list.
        const char *name = drive_names[i];
        // ... do GUI work.
    }
}
Skurmedel
  • 21,515
  • 5
  • 53
  • 66