FindNextFile always fails - FindFirstFile OK

This is a discussion on FindNextFile always fails - FindFirstFile OK within the Windows Programming forums, part of the Platform Specific Boards category; I've managed to get rename file/directory to work and some other API stuff I've used (console program so far), but ...

  1. #1
    Registered User
    Join Date
    Feb 2012
    Posts
    44

    FindNextFile always fails - FindFirstFile OK

    I've managed to get rename file/directory to work and some other API stuff I've used (console program so far), but FindNextFile is mystifying. I've read every example of code I can find and it's simple. Note: I do not wish to copy other peoples programs or sections verbatim but program it as I would do. I have a suspicion it might have something to do with TCHAR as most datatypes mystify me still (assemble programmer at heart).

    ***********************************
    Code:
    #include <stdio.h>
    #include <windows.h>
    #include <string.h>
    #include <tchar.h>
    
    int main(int argc, char *argv[])
    {
    
    WIN32_FIND_DATA myfind;
    HANDLE hfd;
    int x;
    DWORD dx = 200;
    TCHAR currdir[300];
    char szer = {0};
    char nl = {10};
    char bslsh[2] = {92, 0};
    
    x = GetCurrentDirectory(dx, currdir);
    printf("currdir at run time %s %c", currdir, nl);
    
    currdir[0] = szer;
    currdir[1] = szer;
    lstrcat (currdir, "C:");
    lstrcat (currdir, bslsh);
    lstrcat (currdir, "Documents And Settings");
    lstrcat (currdir, bslsh);
    lstrcat (currdir, "jlewandowsk2");
    lstrcat (currdir, bslsh);
    lstrcat (currdir, "*");
    printf("DIR built %s %c", currdir, nl);
    x = SetCurrentDirectory(currdir);
    
    x = GetCurrentDirectory(dx, currdir);
    printf("SET DIR %s %c", currdir, nl);
    printf("%c", nl);
    
    myfind.cFileName[0] = szer;
    hfd = FindFirstFile(currdir, &myfind);
    printf("handle %d ", hfd);
    printf("FIRST file-dir %s %c", myfind.cFileName, nl);
    
    while ( FindNextFile (hfd, &myfind) ) {
      printf("while loop %c", nl);
      printf("NEXT file-dir %s %c", myfind.cFileName, nl);
    }
    FindClose(hfd);
    
    getchar();
    return 0;
    }
    Last edited by jlewand; 02-02-2012 at 01:32 PM.

  2. #2
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Your troubles have nothing to do with TCHAR. (I'm assuming you're not compiling this in unicode mode.)

    You're not checking your return values. From SetCurrentDirectory documentation:
    The final character before the null character must be a backslash.
    So you should add the "*" after the SetCurrentDirectory call.

    Also, get rid of the GetCurrentDirectory call (or read it into a different buffer) since it just screws up the string you've created, removing the backslash.

    This stuff below is worse than useless. Get rid of it.
    Code:
        char szer = {0};
        char nl = {10};
        char bslsh[2] = {92, 0};
    So try something like this:
    Code:
    void die(char* msg) {
        fprintf(stderr, "Error: %s\n", msg);
        exit(1);
    }
    
    int main(int argc, char* argv[])
    {
        WIN32_FIND_DATA myfind;
        HANDLE hfd;
        int x;
        DWORD dx = 200;
        char currdir[300];
    
        x = GetCurrentDirectory(dx, currdir);
        if (x == 0) die("GetCurrentDirectory");
        printf("currdir at run time %s\n", currdir);
    
        currdir[0] = 0;
        lstrcat (currdir, "C:");
        lstrcat (currdir, "\\");
        lstrcat (currdir, "Documents And Settings");
        lstrcat (currdir, "\\");
        lstrcat (currdir, "jlewandowsk2");
        lstrcat (currdir, "\\");
        printf("DIR built %s\n", currdir);
        x = SetCurrentDirectory(currdir);
        if (x == 0) die("SetCurrentDirectory");
    
        lstrcat (currdir, "*");
    
        myfind.cFileName[0] = 0;
        hfd = FindFirstFile(currdir, &myfind);
        if (hfd == INVALID_HANDLE_VALUE) die("FindFirstFile");
    
        printf("FIRST file-dir %s\n", myfind.cFileName);
    
        while ( FindNextFile (hfd, &myfind) ) {
          printf("NEXT file-dir %s\n", myfind.cFileName);
        }
        FindClose(hfd);
    
        return 0;
    }
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  3. #3
    Registered User
    Join Date
    Feb 2012
    Posts
    44
    I have to do that nl and szer stuff as at work (in my free time), I'm using a web-based C compiler and it removes escape characters from the source for every compile. Otherwise, I have to re-doublebackslash every occurrence of nl and szer every time I compile.

    I know what I'm doing regarding slowly building up to understand the inner workings of C and part of this is things like that. I was going to add "ONLY critique the FindNextFile code" as the rest is serving a purpose.

    I know I'm not checking return codes. But the FindFirstFile works. The FindNextFile always fails (RC=0).

    Can you explain fundamentally why the FindNextFile always fails? Everywhere I looked, people were using TCHAR (same with MSDN).

    I'm trying to modify some of my code to match yours. VS C++ compiler say the currdir parameter is inconsistent with LPWSTR for GetCurrentDirectory.
    Last edited by jlewand; 02-02-2012 at 06:06 PM.

  4. #4
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    I have to do that nl and szer stuff as at work (in my free time), I'm using a web-based C compiler and it removes escape characters from the source for every compile. Otherwise, I have to re-doublebackslash every occurrence of nl and szer every time I compile.
    Okay.

    I know what I'm doing regarding slowly building up to understand the inner workings of C and part of this is things like that.
    Did I say anything was wrong with that?

    I was going to add "ONLY critique the FindNextFile code" as the rest is serving a purpose.
    In that case your code is just fine. As long as you're not screwing something up before that point (which you are) everything's hunky-dory

    I know I'm not checking return codes.
    That's like saying "I know I'm an idiot."

    Did you even read what I wrote?

    IT'S YOUR SetCurrentDirectory CALL THAT'S FAILING!!!
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  5. #5
    Registered User
    Join Date
    Feb 2012
    Posts
    44
    Then why does FindFirstFile work? Must you SetCurrentDirectory before doing a FindFirstFile? It IS returning a handle (a printf %X shows a storage address - word boundary).

    Can you also address my last point that it MUST be a TCHAR field or it won't compile. I can't printf or wprintf currdir (TCHAR). But when I print it byte by byte via %x the GetCurrentDirectory has worked and returned the current DOS directory from which I'm testing. Something is wrong with this whole casting thing that I'm doing or not doing correctly.

    I know it's a handicap having programmed for 35 years as it becomes bewildering to see anything called a "data type". They are non-existent in all but one hardware platform I've worked on (the exception is the mainframe which does have one data type).

    I do appeciate your help, but everywhere I look, the code is SO simple as to be like creating a .bat script.

    Edit: As expected, printing &tcurrdir[subscript] increments by TWO implying it's not a regular string. Is that what a TCHAR is? WCHAR? Further edit, I can wprintf tcurrdir[] if it's a TCHAR. GetCurrentDirectory works.
    Last edited by jlewand; 02-02-2012 at 06:46 PM.

  6. #6
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    It IS returning a handle
    Why would it not return a handle? Obviously SOME directory is the current directory, and it's reading that directory, not the one you want (presumably).

    TCHAR is char for non-unicode mode and wchar_t for unicode mode. Look up TCHAR on MSDN

    MSVC++ defaults to UNICODE mode, I believe. To turn it off you have to go into the project options somewhere. I can't recall offhand exactly where.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  7. #7
    Registered User
    Join Date
    Feb 2012
    Posts
    44
    I'm not worried about which directory, I'm concerned with why FindNextFile never works even though FindFirstFile does.

    All the previous testing I've done in MSVC++ has used vanilla printf and char and no problems whatsoever. Does that imply that I'm not compiling in unicode mode? Also, the MSDN doc for these APIs says TCHAR.

    Update: GetCurrentDirectory and SetCurrentDirectory seem to be working. However, FindFirstFile returns the last directory node of the current directory. The msdn doc doesn't say you need to have a \* on the end for a FindFirstFile to work.

    Further: Yes, a \* needs to be on the end. Working myh way to FindNextFile.
    Last edited by jlewand; 02-02-2012 at 06:59 PM.

  8. #8
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    You're going around in circles. The code I posted works just fine for me. Debug your own code. I'm done.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  9. #9
    Registered User
    Join Date
    Feb 2012
    Posts
    44
    A miracle. For some reason, it works.

    Aha, the PROPERTIES for my project show:

    Character set: Use Unicode. If I switch to non-uni, will I have to change all wprintf back to printf? The mystery deepens.

    Maybe the char I code locally is char. But the function call is using TCHAR which translates to wchar_t?? Mismatch?

    Edit: Turning off unicode now causes compile errors. Hmmm... Had to change all wprintf to printf. Now onto this whole unicode thing for GetDriveStrings. The nightmare continues.....

    Code:
    WIN32_FIND_DATA myfind;
    HANDLE hfd;
    DWORD dx = 200;
    TCHAR tcurrdir[300];
    char currdir[300];
    char szer = {0};
    char nl = {10};
    char bslsh[2] = {92, 0};
    x = GetCurrentDirectory(dx, tcurrdir);
    printf("tcurrdir ");
    for ( x = 0; x < 50; x++) {
    wprintf(L" %X %c %X", tcurrdir[x], tcurrdir[x], &tcurrdir[x]);
    }
    wprintf(L"currdir at run time %s %c", tcurrdir, nl);
    // currdir[0] = szer;
    // currdir[1] = szer;
    tcurrdir[0] = szer;
    tcurrdir[1] = szer;
    lstrcat (tcurrdir, L"D:\\");
    // lstrcat (currdir, bslsh);
    lstrcat (tcurrdir, L"oedbx\\");
    // lstrcat (currdir, bslsh);
    // lstrcat (currdir, "jlewandowsk2");
    // lstrcat (currdir, bslsh);
    // lstrcat (currdir, "*");
    wprintf(L"DIR built %s %c", tcurrdir, nl);
    x = SetCurrentDirectory(tcurrdir);
     
    x = GetCurrentDirectory(dx, tcurrdir);
    wprintf(L"SET DIR %s %c", tcurrdir, nl);
    printf("%c", nl);
    
    lstrcat (tcurrdir, L"\\*");
    myfind.cFileName[0] = szer;
    hfd = FindFirstFile(tcurrdir, &myfind);
    printf("handle %d ", hfd);
    wprintf(L"FIRST file-dir %s %c", myfind.cFileName, nl);
    
    while ( FindNextFile (hfd, &myfind) ) {
      wprintf(L"while loop %c", nl);
      wprintf(L"NEXT file-dir %s %c", myfind.cFileName, nl);
    }
    FindClose(hfd);
    getchar();
    return 0;
    
    Last edited by jlewand; 02-02-2012 at 07:25 PM.

  10. #10
    Registered User
    Join Date
    Feb 2012
    Posts
    44
    Quote Originally Posted by oogabooga View Post
    You're going around in circles. The code I posted works just fine for me. Debug your own code. I'm done.

    I understand your frustration but I'm following the most logical path for me to learn C well. I've only been at it for a week.

    And, you've certainly set the tone for my new presence on this forum.
    Last edited by jlewand; 02-02-2012 at 07:11 PM.

  11. #11
    Registered User ledow's Avatar
    Join Date
    Dec 2011
    Posts
    435
    Learn how you like - but someone pointed out the problem to you in their first few posts, followed by your denial and ignorance of it.

    FindFirstFile might fail miserably. FindNextFile will depend on it not failing miserably, and also on there BEING another file (like strtok, and a million other functions that use similar semantics - the first call only sets up the search, the next call could easily fail if that had returned an error or there are no more files/tokens/whatever). If you don't know where it's listing files from, or whether it encountered an error immediately and couldn't list the first file without an error, how the hell do you expect to tell the program that it's somehow wrong or broken?

    Check your return values. It's rule #1 of playing with any external API (of which the Windows API is a pretty damn important one). It's the *ONLY* way that an OS can tell a running program that there's something wrong and your program was deaf to it and plundered on regardless. It's like saying "Why won't my car move? I've turned the ignition on! I mean, I know I didn't check for an engine sound or any lights, but the key's in the start position so why won't it move?!". Trying to diagnose a car problem like that over the phone to the garage is EXACTLY the same as you trying to diagnose this program without listening to what oogabooga was trying to tell you. Do you think your local garage would be more polite, even if you were PAYING them for an answer?

    There's wanting to learn, and there's ignoring those people who try to help you learn. You posted in a public forum. Expect to listen to the people who reply and for them to switch off if you just ignore them.

    - Compiler warnings are like "Bridge Out Ahead" warnings. DON'T just ignore them.
    - A compiler error is something SO stupid that the compiler genuinely can't carry on with its job. A compiler warning is the compiler saying "Well, that's bloody stupid but if you WANT to ignore me..." and carrying on.
    - The best debugging tool in the world is a bunch of printf()'s for everything important around the bits you think might be wrong.

  12. #12
    Registered User
    Join Date
    Feb 2012
    Posts
    44
    No problem. However, if the FindFirstFile DOES return the first file/directory, and there are MORE files in that directory (which there were), that was the crux of my original question. As mentioned, it's pointing to SOME directory when the FindFirstFile is successful. If I had to do it over, I would have posted only the FFF and FNF parts of the code. My mistake.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. FindNextFile
    By Ducky in forum Windows Programming
    Replies: 17
    Last Post: 08-30-2009, 03:53 AM
  2. FindFirstFile and FindNextFile
    By scwizzo in forum Windows Programming
    Replies: 15
    Last Post: 03-12-2008, 05:50 PM
  3. Msdn example code (FindFirstFile, FindNextFile
    By Probose in forum Windows Programming
    Replies: 2
    Last Post: 09-22-2006, 05:16 PM
  4. FindFirstFile/FindNextFile
    By aff501 in forum C Programming
    Replies: 2
    Last Post: 07-13-2006, 05:16 PM
  5. FindNextFile()
    By siavoshkc in forum C++ Programming
    Replies: 9
    Last Post: 03-03-2006, 09:47 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21