Programmieren mit C++

Borland C++

32-Bit-Programmierung

Erweiterte Laufwerkserkennung

Warum liefert die API-Funktion GetDriveType() auf Windows 95 und Windows NT für manche Input-Strings unterschiedliche Ergebnisse und wie läßt sich dies abstellen?

Frage

Die API-Funktion GetDriveType() bringt drei Probleme mit sich:

  • Enthält der Pfadname einen Dateinamen, so resultiert der Fehlercode DRIVE_NO_ROOT_DIR
  • Enthält der Pfad einen Name der Form „\\.\d\“, erkennt die Funktion das lokale Laufwerk nicht
  • Die Funktion arbeitet unterschiedlich auf Windows NT und Windows 95

Die nachfolgend vorgestellte Funktion beseitigt diese Probleme, indem der Name des Pfads verkürzt wird, bis nur noch entweder ein Laufwerksbuchstabe wie beispielsweise „C:“ oder ein Netzwerkpfad mit „\\“-Präfix übrig bleibt. Dateinamensanteile werden abgeschnitten. Zusätzlich berücksichtigt die neue Funktion getDriveType() Pfade, die keine Laufwerksangaben bzw. UNC-Namen haben.

Letztlich wird auch kompensiert, daß _splitpath() unter Windows 95 und Windows NT unterschiedlich parst. Dies ist letztendlich auch dafür verantwortlich, daß die API-Funktion GetDriveType() unterschiedliche Ergebnisse liefert.

So ergibt sich zum Beispiel die folgende Abweichung, wenn der Blackslash vorhanden oder nicht vorhanden ist.

Input

Win 95

Win NT

C:

DRIVE_NO_ROOT_DIR

DRIVE_FIXED

C:\

DRIVE_FIXED

DRIVE_FIXED

Die Funktion getDriveType(), die sich von der API-Funktion nur durch die Schreibweise des ersten Buchstabens unterscheidet, übernimmt als Parameter den vollständigen Pfadnamen und returniert als Funktionsergebnis eine der DRIVE_-Konstanten, die auch GetDriveType() liefert.

Als erstes spaltet die Funktion den gelieferten Pfadnamen in die einzelnen Bestandteile auf.

Lösung

UINT getDriveType(LPCTSTR fullpath)
{
  TCHAR drv[_MAX_PATH];
  TCHAR path[_MAX_PATH];
  TCHAR filename[_MAX_PATH];
  TCHAR ext[_MAX_PATH];
 
  _splitpath(fullpath, drv, path, 
             filename, ext);

Liegt ein Laufwerksbuchstabe vor, wird zunächst ein Backslash angehängt, um Windows 95 davon abzuhalten, den Fehlercode DRIVE_NO_ROOT_DIR zu returnieren.

Funktion getDriveType

  if(lstrlen(drv) != 0)
  { 
     lstrcat(drv, _T("\\"));
     return GetDriveType(drv);
  } 
  else { 

Liegt kein Laufwerksbuchstabe vor und startet der Pfad nicht mit „\“, so handelt es sich um einen relativen Pfad. In diesem Fall wird das aktuelle Verzeichnis verwendet.

Beginnt der Pfad mit einem Backslash, auf den jedoch kein weiterer Backslash folgt, handelt es sich um einen Pfad, der von der Wurzel des aktuellen Laufwerks ausgeht. In beiden Fällen kann die API-Funktion GetDriveType() direkt aufgerufen werden.

Backslash an Laufwerksbuch-staben anhängen

    if (path[0] != _T('\\') ||
        (lstrlen(path) > 2 && 
         path[0] == _T('\\') &&
         path[1] != _T('\\')))
      return GetDriveType(NULL);

Ansonsten verwendet die Funktion einen kleinen Trick, indem zunächst erst einmal GetDriveType() aufgerufen wird, wenn der Pfad mit „\\“ beginnt.

Lautet das Ergebnis DRIVE_NO_ROOT_DIR, wird ein neuer Name erzeugt, bei dem das „\\“ unterdrückt wird. Desweiteren wird dann auch der Spezialfall „\\.\“ behandelt.

Korrekter Pfad liegt vor

    UINT result = GetDriveType(path);
 
    if(result == DRIVE_NO_ROOT_DIR &&
       lstrlen(path) >= 4 && 
       path[0] == _T('\\') && 
       path[1] == _T('\\') && 
       path[2] == _T('.') && 
       path[3] == _T('\\'))
    {
      if (lstrlen(path) == 4)
        lstrcat(path, filename);
 
      LPTSTR p = &path[4];
      LPTSTR b = strchr(p, _T('\\'));
 
      if(b != NULL)
      {
        *b++ = _T(':');
        *b++ = _T('\\');
        *b = _T('\0');
      }
      else lstrcat(p, _T(":\\"));

Dieser neu erzeugte Pfadname wird nun an GetDriveType() übergeben.

Neuen Namen erzeugen

      return GetDriveType(p);
    }

Beginnt der Pfad nicht mit „\\“, wird das zuvor ermittelte Funktionsresultat von GetDriveType() direkt returniert.

    if (lstrlen(path) < 2 || 
        path[0] != _T('\\') || 
        path[1] != _T('\\'))
      return result;

Für alle übrigen Fälle wird das Ergebnis von GetDriveType() für den Ausgangsparameter path returniert.

  return GetDriveType(path);
  }
}

Laufwerkstyp ermitteln

Die so modifizierte Funktion umgeht die Klippen der API-Funktion GetDriveType() und liefert in nahezu allen Fällen ein korrektes Ergebnis zurück. Kommt es dennoch einmal zu Fehlinterpretationen, sollte sich der Entwickler fragen, ob er nicht vielleicht doch den Pfadnamen etwas besser aufbereitet an die Funktion hätte übergeben können.

Resume





Sachgebiet


© 2009-2012 by Alojado Publishing. Alle Rechte vorbehalten. Ausgewiesene Marken gehören ihren jeweiligen Eigentümern.
Mit der Benutzung dieser Seite erkennen Sie die Nutzungsbedingungen und die Datenschutzerklärung an. Der Betreiber übernimmt keine Haftung für den Inhalt verlinkter externer Internetseiten.
Seite erzeugt 2012-05-20 02:01:10 von textarchiv.alojado.de