-1

Language: C

Platform: Windows 10

Compiler: MinGW

I am obtaining a return value from the GetFileAttributesW() function (part of the Win32 API) equal to 17, which does not match any of the file attribute macros listed here, nor is it equal to the macro INVALID_FILE_ATTRIBUTES (-1).

Upon calling GetLastError() after the function call, ERROR_SUCCESS is returned (0) - indicating no error. So I am perplexed as to what is going on.

The file in question (passed as a command-line argument) is my Downloads directory, which is why I find it odd that the value returned by GetFileAttributesW() (17) is only one number off of FILE_ATTRIBUTE_DIRECTORY (16).

Minimum reproducible example:

#include <stdio.h>

#ifdef _WIN32
#include <windows.h>
#else
#include <sys/stat.h>
#include <time.h>
#include <dirent.h>
#endif

int main(int argc, char **argv) {

    if (argc != 2) {
        fprintf(stderr, "Invalid number of arguments provided.\n");
        return -1;
    }

#ifdef _WIN32
    int Argc;
    LPWSTR *dir = CommandLineToArgvW(GetCommandLineW(), &Argc);

    if (dir == NULL) {
        fprintf(stderr, "Error getting command line arguments.\n");
        return -1;
    }
    DWORD fileAttribute = GetFileAttributesW(*(dir + 1));
    wprintf(L"fileAttribute: %d\n", fileAttribute);
#endif
    
    return 0;
}

There might be something simple that I'm missing, or perhaps there is no clear solution. Any help would be appreciated, thanks.

  • 4
    It looks like `FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY`. – MikeCAT Jul 22 '22 at 22:25
  • @MikeCAT Oh crickey, I hadn't even realised that the return value could be a bitwise or combination of flags. Cheers, will go check that out right now. Would you then suggest doing a check for various different bitwise or'ed combinations? – Gregor Hartl Watters Jul 22 '22 at 22:26
  • 1
    Each bits corresponds to each flags. You can use bitwise AND with each flags to check if each flags are ON. – MikeCAT Jul 22 '22 at 22:28
  • @MikeCAT that's brilliant, cheers. Hadn't even crossed my mind. Will work on that now. – Gregor Hartl Watters Jul 22 '22 at 22:30
  • 1
    @GregorWattersHärtl on a side note, you don't need `malloc()`, `wcscpy()` or `free()` in this example (you do need to `LocalFree()` the pointer returned by `CommandLineToArgvW()`, though). You can pass `dir[1]` as-is to `GetFileAttributesW()` instead (I would rename `dir` to `Argv`), eg: `int Argc; LPWSTR *Argv = CommandLineToArgvW(GetCommandLineW(), &Argc); ... DWORD fileAttribute = GetFileAttributesW(Argv[1]); ... LocalFree(Argv);` – Remy Lebeau Jul 22 '22 at 22:38
  • @RemyLebeau cheers, thanks, it was only there because of how I use it in the rest of the program, but I'll remove it to make this example clearer! Thank you too though for the comment on LocalFree(), I hadn't heard about this function before – Gregor Hartl Watters Jul 22 '22 at 22:41
  • @GregorWattersHärtl "*I hadn't heard about [the LocalFree() function] before*" - then I take it that you did not read [`CommandLineToArgvW()`'s documentation](https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-commandlinetoargvw), did you? "*CommandLineToArgvW allocates a block of contiguous memory for pointers to the argument strings, and for the argument strings themselves; the calling application must free the memory used by the argument list when it is no longer needed. **To free the memory, use a single call to the LocalFree function**.*" – Remy Lebeau Jul 23 '22 at 00:35
  • @RemyLebeau nope, I had not, so thanks for pointing this out to me – Gregor Hartl Watters Jul 23 '22 at 09:25

1 Answers1

2

The return value is a bitmask, multiple flags can be combined using the bitwise OR operator.

The value 17 is FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY.

You can use the bitwise AND operator to check if the value contains each flag.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
MikeCAT
  • 73,922
  • 11
  • 45
  • 70