Fehler bei der Ausgabe eines Binär-IMG auf USB-PhysicalDrive



  • Nun klappt bei mir das Lesen von USB-PhysicalDrives und von Disketten, auch die Ausgabe auf die Dskette als PhysicalDrive "\.\A:" funktioniert. Wenn ich jedoch auf einen USB-Stick oder eine SD-Card im USB-Cardreader ausgeben will, dann gibt es beim Sektor 8 einen Fehler

    Folgende Disketten-/USB-Laufwerke gefunden => 
    B:  FAT       Partition 1    CF16MB-CARD   "\\.\PhysicalDrive6"
    Aktuelles Laufwerk = B:\ = "\\.\PhysicalDrive6"
    Sektor 0 wurde ausgegeben.
    Sektor 1 wurde ausgegeben.
    Sektor 2 wurde ausgegeben.
    Sektor 3 wurde ausgegeben.
    Sektor 4 wurde ausgegeben.
    Sektor 5 wurde ausgegeben.
    Sektor 6 wurde ausgegeben.
    Sektor 7 wurde ausgegeben.
    
    Fehler <write> beim Sektor 8
    ~~~~~~~~~~~~~~~~<Exception-Anfang>~~~~~~~~~~~~~~~~~~~~~~
    System.UnauthorizedAccessException: Der Zugriff auf den Pfad wurde verweigert.
       bei System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       bei System.IO.FileStream.WriteCore(Byte[] buffer, Int32 offset, Int32 count)
       bei System.IO.FileStream.Write(Byte[] array, Int32 offset, Int32 count)
       bei HkDiskette.Form1.WriteUsb() in V:\#PgmHK\VC20xx\HKcs\HkDiskette\Form1.cs:Zeile 2122.
    ~~~~~~~~~~~~~~~~~<Exception-Ende>~~~~~~~~~~~~~~~~~~~~~~~
    

    Ich habe ein kleines Test-Programm dafür gemacht. Ein Disketten-IMG soll ausgegeben werden. (Rufus macht das ohne Probleme).

            [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
            public static extern IntPtr CreateFile(
                string fileName,
                [MarshalAs(UnmanagedType.U4)] FileAccess fileAccess,
                [MarshalAs(UnmanagedType.U4)] FileShare fileShare,
                IntPtr securityAttributes,
                [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
                [MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
                IntPtr template);
    
            [DllImport("Kernel32.dll", SetLastError = true)]
            private static extern bool DeviceIoControl(
                SafeFileHandle hDevice,
                uint dwIoControlCode,
                [In] byte[] InBuffer,
                int nInBufferSize,
                [Out] byte[] OutBuffer,
                int nOutBufferSize,
                out int pBytesReturned,
                IntPtr overlapped);
    
    
            private void WriteUsb() 
            {
                //SafeFileHandle h;
                int Rc = 0;
                string TestPhysName = @"\\.\PhysicalDrive6";
                byte[] DiskIMG = File.ReadAllBytes(@"G:\Test\VHD\Disk144VS.img");
                SafeFileHandle h = new SafeFileHandle(CreateFile(TestPhysName,
                                       FileAccess.ReadWrite, FileShare.None,
                                       new IntPtr(0), FileMode.Open, 0, new IntPtr(0) ),
                                       true);
    
                if (h.IsInvalid)
                {
                    PutLst("Fehler <IsInvalid == true> bei <CreateFile> des USB-Laufwerkes \"" + TestPhysName + "\"");
                    h.Close();
                    return;
                }
    
                if (!DeviceIoControl(h, FSCTL_DISMOUNT_VOLUME,
                                     null, 0, null, 0, out Rc, IntPtr.Zero))
                {
                    PutLst("Fehler DeviceIoControl FSCTL_DISMOUNT_VOLUME");
                    return;
                }
    
                if (!DeviceIoControl(h, FSCTL_LOCK_VOLUME,
                                     null, 0, null, 0, out Rc, IntPtr.Zero))
                {
                    PutLst("Fehler DeviceIoControl FSCTL_LOCK_VOLUME");
                    return;
                }
    
                Stream outPutFile = new FileStream(h, FileAccess.Write);
    
                int AnzSek = DiskIMG.Length / 512;
                int LfdPos = 0;
                for (int i = 0; i < AnzSek; i++)
                {
                    byte[] SecPu = new byte[512];
                    for (int j=0; j < 512; j++) 
                    { SecPu[j] = DiskIMG[LfdPos++]; }
                    try
                    {
                        outPutFile.Write(SecPu, 0, 512);
                        PutLst("Sektor " + i.ToString("###,###,##0") + " wurde ausgegeben.");
                    }
                    catch (Exception ex)
                    {
                        PutLst("");
                        PutLst("Fehler <write> beim Sektor " + i.ToString("###,###,##0"));
                        PutLst("~~~~~~~~~~~~~~~~<Exception-Anfang>~~~~~~~~~~~~~~~~~~~~~~");
                        PutLst(ex.ToString());
                        PutLst("~~~~~~~~~~~~~~~~~<Exception-Ende>~~~~~~~~~~~~~~~~~~~~~~~");
                        return;
                    }
                } // for (int i = 0; i < AnzSek; i++)
    
                if (!DeviceIoControl(h, FSCTL_UNLOCK_VOLUME,
                                     null, 0, null, 0, out Rc, IntPtr.Zero))
                {
                    PutLst("Fehler DeviceIoControl FSCTL_UNLOCK_VOLUME");
                    return;
                }
    
            } // private void WriteUsb() 
    
    
    Jetzt habe ich das Programm auf dem gleichen PC unter Windows 11 laufen lassen (vorher Windows 10),
    da kommt auch dieser Fehler, aber erst einige Sektoren später..
    
    ```cpp
    Folgende Disketten-/USB-Laufwerke gefunden => 
    E:  FAT       Partition 1    CF16MB-CARD   "\\.\PhysicalDrive6"
    Aktuelles Laufwerk = E:\ = "\\.\PhysicalDrive6"
    Sektor 0 wurde ausgegeben.
    Sektor 1 wurde ausgegeben.
    Sektor 2 wurde ausgegeben.
    Sektor 3 wurde ausgegeben.
    Sektor 4 wurde ausgegeben.
    Sektor 5 wurde ausgegeben.
    Sektor 6 wurde ausgegeben.
    Sektor 7 wurde ausgegeben.
    Sektor 8 wurde ausgegeben.
    Sektor 9 wurde ausgegeben.
    Sektor 10 wurde ausgegeben.
    Sektor 11 wurde ausgegeben.
    Sektor 12 wurde ausgegeben.
    Sektor 13 wurde ausgegeben.
    Sektor 14 wurde ausgegeben.
    Sektor 15 wurde ausgegeben.
    Sektor 16 wurde ausgegeben.
    Sektor 17 wurde ausgegeben.
    Sektor 18 wurde ausgegeben.
    Sektor 19 wurde ausgegeben.
    Sektor 20 wurde ausgegeben.
    Sektor 21 wurde ausgegeben.
    Sektor 22 wurde ausgegeben.
    Sektor 23 wurde ausgegeben.
    Sektor 24 wurde ausgegeben.
    Sektor 25 wurde ausgegeben.
    Sektor 26 wurde ausgegeben.
    Sektor 27 wurde ausgegeben.
    Sektor 28 wurde ausgegeben.
    Sektor 29 wurde ausgegeben.
    Sektor 30 wurde ausgegeben.
    Sektor 31 wurde ausgegeben.
    Sektor 32 wurde ausgegeben.
    Sektor 33 wurde ausgegeben.
    Sektor 34 wurde ausgegeben.
    Sektor 35 wurde ausgegeben.
    Sektor 36 wurde ausgegeben.
    Sektor 37 wurde ausgegeben.
    Sektor 38 wurde ausgegeben.
    Sektor 39 wurde ausgegeben.
    
    Fehler <write> beim Sektor 40
    ~~~~~~~~~~~~~~~~<Exception-Anfang>~~~~~~~~~~~~~~~~~~~~~~
    System.UnauthorizedAccessException: Der Zugriff auf den Pfad wurde verweigert.
       bei System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       bei System.IO.FileStream.WriteCore(Byte[] buffer, Int32 offset, Int32 count)
       bei System.IO.FileStream.Write(Byte[] array, Int32 offset, Int32 count)
       bei HkDiskette.Form1.WriteUsb() in V:\#PgmHK\VC20xx\HKcs\HkDiskette\Form1.cs:Zeile 2122.
    ~~~~~~~~~~~~~~~~~<Exception-Ende>~~~~~~~~~~~~~~~~~~~~~~~
    
    ```


  • Ich habe noch etwas probiert und die Schreib-Routine folgendermassen gestaltet

            //#####################################
            // USB ausgeben TEST (2)
            //#####################################
            private void WriteUsb2()
            {
                string deviceId = @"\\.\PhysicalDrive6";
                byte[] DiskIMG = File.ReadAllBytes(@"G:\Test\USB\CF16SD.img"); // 16.056.320 Bytes = ca. 16 MB
                int intOut = 0;
    
                SafeFileHandle h = CreateFile(deviceId, GENERIC_READ | GENERIC_WRITE, 0,
                                              IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
    
                if (h.IsInvalid)
                {
                    PutLst("Fehler <IsInvalid == true> bei <CreateFile> des USB-Laufwerkes \"" + deviceId + "\"");
                    return;
                }
                PutLst("<CreateFile> des USB-Laufwerkes \""+ deviceId + "\" = OK");
    
                if (!DeviceIoControl(h, FSCTL_LOCK_VOLUME, null, 0, null, 0, out intOut, IntPtr.Zero))
                {
                    PutLst("Fehler DeviceIoControl FSCTL_LOCK_VOLUME");
                    CloseHandle(h);
                    return;
                }
                PutLst("<DeviceIoControl FSCTL_LOCK_VOLUME> OK");
    
                if (!DeviceIoControl(h, FSCTL_DISMOUNT_VOLUME, null, 0, null, 0, out intOut, IntPtr.Zero))
                {
                    PutLst("Fehler DeviceIoControl FSCTL_DISMOUNT_VOLUME");
                    CloseHandle(h);
                    return;
                }
                PutLst("<DeviceIoControl FSCTL_DISMOUNT_VOLUME> OK");
    
                Stream outPutFile = new FileStream(h, FileAccess.Write);
                PutLst("<FileStream(h, FileAccess.Write> OK");
    
                PutLst("<outPutFile.Write(DiskIMG, 0, " + DiskIMG.Length.ToString() + ")> wird gestartet ...");
    
                try 
                { 
                    outPutFile.Write(DiskIMG, 0, DiskIMG.Length);
                    PutLst("<outPutFile.Write(DiskIMG, 0, " + DiskIMG.Length.ToString() + ")> = OK");
                }
                catch (Exception ex)
                {
                    PutLst("");
                    PutLst("Fehler bei <write>");
                    PutLst("~~~~~~~~~~~~~~~~<Exception-Anfang>~~~~~~~~~~~~~~~~~~~~~~");
                    PutLst(ex.ToString());
                    PutLst("~~~~~~~~~~~~~~~~~<Exception-Ende>~~~~~~~~~~~~~~~~~~~~~~~");
                    return;
                }
    
                if (!DeviceIoControl(h, FSCTL_UNLOCK_VOLUME, null, 0, null, 0, out intOut, IntPtr.Zero))
                { PutLst("Fehler DeviceIoControl FSCTL_UNLOCK_VOLUME"); return; }
                PutLst("DeviceIoControl FSCTL_UNLOCK_VOLUME = OK");
    
                if (!CloseHandle(h))
                {
                    PutLst("\"" + deviceId + "\" 0x" + Marshal.GetHRForLastWin32Error().ToString("X8") + ": close handle error: " +
                           Marshal.GetHRForLastWin32Error().ToString("X8"));
                    return;
                }
                PutLst("\"" + deviceId + "\" 0x" + Marshal.GetHRForLastWin32Error().ToString("X8") + ": handle closed."); 
                PutLst("Ausgabe fertig");
    
            } //   private void WriteUsb2()
    

    VS2022 wird mit "Als Administrator ausführen" gestartet. Rechts oben wird im VS2022-Fenster ADMINISTRATOR angezeigt.

    Mit DiskPart CLEAN lösche ich den USB-Stick vor dem Programmstart.
    Auch dort kommt meistens eine Fehlermeldung und CLEAN klappt dann bei der Wiederholung.

    Microsoft DiskPart-Version 10.0.19041.964
    
    Copyright (C) Microsoft Corporation.
    Auf Computer: R980
    
    DISKPART> list disk
    
      Datenträger ###  Status         Größe    Frei     Dyn  GPT
      ---------------  -------------  -------  -------  ---  ---
      Datenträger 0    Online         2794 GB  1024 KB        *
      Datenträger 1    Online         1863 GB  1024 KB        *
      Datenträger 2    Online         5589 GB      0 B        *
      Datenträger 3    Online          931 GB  1024 KB        *
      Datenträger 4    Online          931 GB  1024 KB        *
      Datenträger 5    Online          931 GB  1024 KB        *
      Datenträger 6    Online          960 MB   944 MB
    
    DISKPART> select disk 6
    
    Datenträger 6 ist jetzt der gewählte Datenträger.
    
    DISKPART> clean
    
    Fehler in DiskPart: Zugriff verweigert
    Weitere Informationen finden Sie im Systemereignisprotokoll.
    
    DISKPART> clean
    
    Der Datenträger wurde bereinigt.
    
    DISKPART>
    

    Unter Windows 10 kommt allerdings weiterhin eine Fehlermeldung

    <CreateFile> des USB-Laufwerkes "\\.\PhysicalDrive6" = OK
    <DeviceIoControl FSCTL_LOCK_VOLUME> OK
    <DeviceIoControl FSCTL_DISMOUNT_VOLUME> OK
    <FileStream(h, FileAccess.Write> OK
    <outPutFile.Write(DiskIMG, 0, 16056320)> wird gestartet ...
    
    Fehler bei <write>
    ~~~~~~~~~~~~~~~~<Exception-Anfang>~~~~~~~~~~~~~~~~~~~~~~
    System.UnauthorizedAccessException: Der Zugriff auf den Pfad wurde verweigert.
       bei System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       bei System.IO.FileStream.WriteCore(Byte[] buffer, Int32 offset, Int32 count)
       bei System.IO.FileStream.Write(Byte[] array, Int32 offset, Int32 count)
       bei HkDiskette.Form1.WriteUsb2() in V:\#PgmHK\VC20xx\HKcs\HkDiskette\Form1.cs:Zeile 2158.
    ~~~~~~~~~~~~~~~~~<Exception-Ende>~~~~~~~~~~~~~~~~~~~~~~~
    

    Wenn ich das Programm unter Windows 11 laufen lasse (der gleiche PC), dann funktioniert es

    <CreateFile> des USB-Laufwerkes "\\.\PhysicalDrive6" = OK
    <DeviceIoControl FSCTL_LOCK_VOLUME> OK
    <DeviceIoControl FSCTL_DISMOUNT_VOLUME> OK
    <FileStream(h, FileAccess.Write> OK
    <outPutFile.Write(DiskIMG, 0, 16056320)> wird gestartet ...
    <outPutFile.Write(DiskIMG, 0, 16056320)> = OK
    DeviceIoControl FSCTL_UNLOCK_VOLUME = OK
    "\\.\PhysicalDrive6" 0x80070000: handle closed.
    Ausgabe fertig
    

    Ich habe Windows 10 im abgesicherten Modus gestartet, da klappt es genau so, wie bei Windows 11.

    Ich vermute, dass der Windows 10 - Defender die Ursache ist.
    Programme, wie Rufus und Acronis können doch auch auf Phys.Laufwerke schreiben, ohne dass man zuvor DiskPart-CLEAN ausführen muss. Wie kann man die Zugriffs-Verweigerung umgehen/ vermeiden ?



  • Nun noch eine Erkenntnis...
    Unter Windows 10 (im Normal-Modus - im abgesicherten Modus funktioniert es) kommt bei der Ausgabe auf ein USB-Laufwerk konstant ein Fehler

    
    ~~~~~~~~~~~~~~~~~~< USB-Laufwerk ausgeben >~~~~~~~~~~~~~~~~~~
     
    USB-Laufwerk "\\.\PhysicalDrive7" wird erstellt.
    Fehler <catch> beim Schreiben <Write> des USB-Laufwerkes "\\.\PhysicalDrive7"
    ~~~~~~~~~~~~~~~~<Exception-Anfang>~~~~~~~~~~~~~~~~~~~~~~
    System.UnauthorizedAccessException: Der Zugriff auf den Pfad wurde verweigert.
       bei System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       bei System.IO.FileStream.WriteCore(Byte[] buffer, Int32 offset, Int32 count)
       bei System.IO.FileStream.Write(Byte[] array, Int32 offset, Int32 count)
       bei HkDiskette.Form1.UsbAusgeben()
    ~~~~~~~~~~~~~~~~~<Exception-Ende>~~~~~~~~~~~~~~~~~~~~~~~
    

    Unter Windows 11 fuktioniert alles ohne Fehler.

    Wenn ich nun unter Windows 10 VMWare Workstation 17 Player starte und dort Windows 7 Ultimate X64 und unter diesem Windows 7 mein Programm, dann klappt ebenfalls alles ohne Fehler.
    Die USB-Laufwerke werden vom VMWare Player exclusiv der VM zugeordnet, so dass das übergeordnete Windows 10 sich offenbar nicht mehr darum kümmert. Bei Windows 7 läuft Microsoft Security Essentials als Virenschutz.

    Es ist eben immer gut, wenn man mehrere Möglichkeiten hat.

    Andererseits kann Rufus problemlos auch unter Windows 10 einen USB-Stick aus einer VHD- oder IMG-Datei erstellen.
    Wie macht das Programm das ? Bei RUFUS steht, dass er das mit C++ programmiert hat.
    Da gibt es evtl. weiter Möglichkeiten, sich die Berechtigung für das Schreiben zu holen.
    Bei RUFUS läuft ja der gleiche Win10-Virenschutz-Defender.



  • @hkdd
    ich glaube, nun habe ich die Ursache für das Nicht-Funktionieren unter Windows 10 gefunden.
    So habe ich CreateFile benutzt - das klappt auch bei Win7 und 8 und 11, aber nicht bei Win10.

            [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
            public static extern IntPtr CreateFile(
                string fileName,
                [MarshalAs(UnmanagedType.U4)] FileAccess fileAccess,
                [MarshalAs(UnmanagedType.U4)] FileShare fileShare,
                IntPtr securityAttributes,
                [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
                [MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
                IntPtr template);
    
     SafeFileHandle h = new SafeFileHandle(CreateFile(DiskName,
                                                      FileAccess.ReadWrite,
                                                      FileShare.ReadWrite,
                                                      IntPtr.Zero,
                                                      FileMode.Open,
                                                      0,
                                                      IntPtr.Zero  ),
                                             true);
    

    Man soll IntPtr bei CreateFile nich mehr benutzen, stattdessen SafeFileHandle
    Ich habe es folgendermaßen abgeändert:

                [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
                public static extern SafeFileHandle CreateFile(
                    string fileName,
                    uint fileAccess,
                    uint fileShare,
                    IntPtr securityAttributes,
                    uint creationDisposition,
                    uint flags,
                    IntPtr template);
    
                SafeFileHandle h = CreateFile(DiskName,
                                   FileAccess.ReadWrite,
                                   FileShare.ReadWrite, 
                                   IntPtr.Zero,
                                   FileMode.Open,
                                   0,
                                   IntPtr.Zero );
    

    Und nun funktioniert es auch mit Windows 10, es lag also nicht am Defender.

    Den entscheidenten Hinweis habe ich hier gefunden:
    https://www.nullify.net/Comments/189

    Hier steht immer noch IntPtr...
    http://pinvoke.net/search.aspx?search=CreateFile&namespace=[All]



  • @hkdd So beim groben Überfliegen scheinen das doch schon sehr spezielle Probleme zu sein, mit denen du da kämpfst. Ohne dein Setup zu reproduzieren (schon etwas mehr als nur einmal den Compiler anzuwerfen und daher aufwändiger) wird es wohl nur bei sehr offensichtlichen Dingen jemanden geben, der dir nur vom Quellcode-Lesen her helfen kann.

    Dennoch gut, dass du deine Erkenntnisse hier dokumentierst. Vielleicht hilft das ja irgendwann mal jemandem weiter 👍


Anmelden zum Antworten