0

Dear Stack Overflow community.

I am a first time poster here. I've found this forum very helpful in the past and hope to contribute in many ways in the future. Right now I have a problem that I can't make out head or tail of.

I am trying to acquire the filenames in a specific directory using the FindFirstFileA, FindNextFileA and CloseFind functions. I'm writing C++ code in Microsoft Visual Studio 2017 and using UNICODE.

I opted for the "A"-suffix version rather than the "regular" one because I found working with LPCWSTR cumbersome.

My code for the relevant function looks like this at present:

void MainLoop::FindFiles(std::string Directory)
{
    Directory = Directory + "*";
    LPCSTR Path = Directory.c_str();
    LPWIN32_FIND_DATAA FileData;
    HANDLE hFind;
    hFind = FindFirstFileA(Path, FileData);
    while (FindNextFileA(hFind, FileData) != 0)
    {
        Files.push_back(FileData->cFileName);
    }
    FindClose(hFind);
}

There is one "weird" thing about this code, and one error which doesn't let me compile.

The "weird" thing:

In all of the documentation and examples I can find on all FindFirstFile functions it says that the second parameter should be a pointer and thus my code should actually look like this: hFind = FindFirstFileA(Path, &FileData); But when I try that, the compiler tells me that LPWIN32_FIND_DATAA* is not compatible with LPWIN32_FIND_DATAA. I don't know what's going on there, so some light on it would be appreciated.

The actual error does not concern this, however:

When I try to run the program, I'm given an error message stating that "FileData" is uninitialized and then refuses to run. In all examples I've seen, the data structure is declared just as I have. No forum posts I can find address my particular problems. Now, I know that I've only posted a specific function and if you need to know more of my setup I'll be glad to fill you in. Any insight into my problem or constructive comments on either my post or my code are welcome.

Respectfully

Niklas Björkeroth

  • _I opted for the "A"-suffix version rather than the "regular" one because I found working with LPCWSTR cumbersome._ Translation: I opted for the non-Unicode version rather than the Unicode version, because I found working with Unicode cumbersome. (Doesn't much matter if your "A"-suffix code page works for your environment.) – Eljay Apr 20 '20 at 19:56
  • If you're just going to use the `ANSI` version of the `Win32 API` functions `undefine` the `UNICODE` and `_UNICODE` macros. Then you can use the macro version of the functions (without either the `A` or `W`). That being said, you should be using the `W` version of the functions and learning how to deal with unicode in `Windows`. – WBuck Apr 20 '20 at 19:57
  • As you perceive, there are many things I am not sapient of with regards to coding. I don't even understand what you mean by "Doesn't much matter if your "A"-suffix code page works for your environment", Eljay. I can't remember why I defined UNICODE, but it made something easier at the time when I did it. Thank you for pointing this out, I'm learning =) – Arte Birklaus Apr 20 '20 at 20:03
  • @ArteBirklaus The unicode macros `UNICODE` and `_UNICODE` are automatically defined when you create a new project in `Visual Studio` – WBuck Apr 20 '20 at 20:06
  • @WBuck Thank you very much for the suggestions. If you have the time; Why is it better to use the "-W" versions of functions (I assume it was a general suggestion)? Are the other versions going obsolete? Are they less safe? – Arte Birklaus Apr 20 '20 at 20:13

2 Answers2

1

LPWIN32_FIND_DATAA already is a pointer - the LP prefix stands for "long pointer" (a relic of the 16-bit era).

You want to declare the variable as WIN32_FIND_DATAA and pass a pointer to that.

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
  • Thank you so much for answering my question, it helped, both in making the code run and in my understanding of it. Have a good time of day! – Arte Birklaus Apr 20 '20 at 20:05
1

This is an uninitialized pointer:

LPWIN32_FIND_DATAA FileData;

LPWIN32_FIND_DATAA is a typedef for WIN32_FIND_DATAA*.

What you need is an actual instance of the structure, like

WIN32_FIND_DATAA FileData;

Notice that LP is gone from the beginning of the type.

Then when you pass its address to the function, the pointer type will match.

hFind = FindFirstFileA(Path, &FileData);
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Thank you very much for answering my question, I've marked your reply as the best answer because it was the most informative. I wish you a good time of day, whatever it may be =) – Arte Birklaus Apr 20 '20 at 20:06