FindFirstFile() und ERROR_NO_MORE_FILES



  • Hallo,

    ich habe ein Problem mit FindFirstFile(), an dem ich mich schon seit Tagen aufhalte. Mit nachfolgendem Code schaue ich, ob die Datei ( TargetFile ) nicht existiert oder älter als die Referenzdatei ( RetrievedFile ) ist.

    ...
    
    dwError = 0;
    HANDLE hFindTargetFile = FindFirstFile(szFullTargetFilePath.c_str(), &fdTargetFileData);
    dwError = GetLastError();
    if ((dwError & ERROR_NO_MORE_FILES) != 0)
    	MessageBox(hDlgMain, "No more files...", "bullshit!", NULL);
    
    //if the target file doesnt exist or is older
    if ( ((dwError & ERROR_FILE_NOT_FOUND) == 0 &&	/*file exists*/
    	(dwError & ERROR_PATH_NOT_FOUND) == 0 &&	/*path exists*/
    	(fdTargetFileData.dwFileAttributes & fdRetrievedFileData.dwFileAttributes) != 0 && 
    	CompareFileTime(&fdRetrievedFileData.ftLastWriteTime, &fdTargetFileData.ftLastWriteTime) == 1) || 
    	(dwError & ERROR_FILE_NOT_FOUND) != 0 || (dwError & ERROR_PATH_NOT_FOUND) != 0)
    {
    
    	int res = CompareFileTime(&fdRetrievedFileData.ftLastWriteTime, &fdTargetFileData.ftLastWriteTime);
    
    	//For tracking erroneous errors
    	MessageBox(hDlgMain, NumberToStr(res).c_str(), fdRetrievedFileData.cFileName, NULL);
    	MessageBox(hDlgMain, szFullTargetFilePath.c_str(), "error:", NULL);
    	MessageBox(hDlgMain, NumberToStr(dwError).c_str(), "error:", NULL);
    
    	//...
    
    }
    ...
    

    Im Moment ist es so, dass sowohl in einem Verzeichnis als auch dem Anderen alle Dateien identisch sind. Der Error Code (dwError) und das Vergleichsergebnis (CompareFileTime) sind bei den meisten Dateien richtig, aber bei manchen spuckt mir GetLastError() 18 (ERROR_NO_MORE_FILES) aus, was so viel wie "der Ordner ist leer" bedeutet! Das Witzigste daran ist aber, dass solche existieren(!) und nicht älter sind(!) Dateien auch noch durch die if-Überprüfung durchkommen. CompareFileTime gibt immer 0 (bei Dateien sind gleich alt) zurück, was völlig richtig ist. Selbst wenn der Error Code 18 wirklich stimmt (was keinen Sinn macht), will ich doch, dass mir zurückgegeben wird, ob die Kackdatei existiert oder nicht! Ich schaue doch, ob eine bestimmte Datei existiert und nicht ob der Kackordner leer ist.
    Für Win2000 gibt es ein Hotfix für die FindFirstFile-Funktion, aber nicht für Vista. Heißt das wirklich es ist kein Bug, sondern ein Denkfehler von mir? Wenn ja, dann wo... Bitte helfen. 😕

    Grüße,
    Rewind.



  • GetLastError nur Auswerten wenn die Funktion fehlgeschlagen ist. Sonst kommt da murks raus.



  • Dann versteh ich das nicht. Wenn eine Funktion nicht fehlschlägt, muss doch GetLastError ERROR_SUCCESS zurückgeben. Wenn ich aber das so schreibe,

    if (!hFindTargetFile)
    	dwError = GetLastError();
    

    dann werden einige nicht existierende Dateien von FindFirstFile nicht erfasst... Ich geh gleich kaputt

    Noch eine Frage: wird die WIN32_FIND_DATA-Struktur nach dem Schließen des mit FindFirstFile o.ä. geöffneten Handle gelöscht?



  • Wenn die Funktion erfolgreich ist, setzt sie den globalen Fehler nicht unbedingt zurück - und du bekommst dort möglicherweise einen Fehler, der bereits vor dem Aufruf bestand oder den eine von ihr aufgerufene Hilfsfunktion gesetzt hat.

    PS: Und afaik werden die zurückgegebenen Daten zur gefundenen Datei nur gelöscht, wenn du das selber machst.



  • CStoll schrieb:

    und du bekommst dort möglicherweise einen Fehler, der bereits vor dem Aufruf bestand oder den eine von ihr aufgerufene Hilfsfunktion gesetzt hat.

    Das ist ausgeschlossen, da die auszuwertende Error-Variable wird unmittelbar von der Funktion zurückgesetzt und gleich danach initialisiert. Allerdings scheint tatsächlich GetLastError einen fehlerhaften Wert zurückzugeben, wenn die Funktion erfolgreich ausgeführt wird. Und es funktioniert wenn ich die Überprüfung so implementiere (bin mir aber nicht sicher, ob ein binärer Vergleichsoperator nicht besser wäre):

    if (hFindTargetFile == INVALID_HANDLE_VALUE)
        dwError = GetLastError();
    

    Danke an euch beide.



  • [Rewind] schrieb:

    CStoll schrieb:

    und du bekommst dort möglicherweise einen Fehler, der bereits vor dem Aufruf bestand oder den eine von ihr aufgerufene Hilfsfunktion gesetzt hat.

    Das ist ausgeschlossen, da die auszuwertende Error-Variable wird unmittelbar von der Funktion zurückgesetzt und gleich danach initialisiert.

    Das schließt vielleicht ältere Funktionsaufrufe aus, aber keine Hilfsfunktionen, die FindFirstFile() unterwegs aufgerufen hat 😉

    PS: Übrigens macht es nicht sonderlich viel Sinn, die Fehlercodes mit Bit-Operationen zu verrechnen - dahinter steckt kein Bitfeld, sondern eine Auflistung von möglichen Werten.


Log in to reply