Laden...

Festplatte über WinAPI einbinden und Partitionsinformationen anzeigen

Erstellt von Glowhollow vor 5 Jahren Letzter Beitrag vor 5 Jahren 1.567 Views
G
Glowhollow Themenstarter:in
74 Beiträge seit 2018
vor 5 Jahren
Festplatte über WinAPI einbinden und Partitionsinformationen anzeigen

Hallo und guten Tag,

im Moment wühle ich mich durch die WinAPI und versuche erst mal kleine Schritte um zum Ziel zu kommen. Vorerst möchte ich erstmal ein Laufwerk einbinden, dieses weitergeben und mir die Partitionsinformationen anzeigen lassen.

im moment verwende ich die Enumeratoren von pinvoke.net (z.bsp. https://www.pinvoke.net/default.aspx/kernel32/DeviceIoControl.html) als auch (http://pinvoke.net/default.aspx/kernel32/CreateFile.html)

die eingebundenen DLLS habe ich wiefolgt:


        [DllImport("Kernel32.dll", SetLastError = false, CharSet = CharSet.Auto)]
        public static extern bool DeviceIoControl(
        SafeFileHandle hDevice,
        EIOControlCode IoControlCode,
        [MarshalAs(UnmanagedType.AsAny)]
        [In] object InBuffer,
        uint nInBufferSize,
        [MarshalAs(UnmanagedType.AsAny)]
        [Out] object OutBuffer,
        uint nOutBufferSize,
        ref uint pBytesReturned,
        [In] IntPtr Overlapped
        );
      
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        internal static extern SafeFileHandle CreateFile(
        string fullName,
        [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
        [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
        IntPtr lpSecurityAttributes,
        [MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
        [MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
         IntPtr hTemplateFile);

folgender Strukt-Aufbau:


[StructLayout(LayoutKind.Sequential)]
        struct FILE_ZERO_DATA_INFORMATION
        {
            public FILE_ZERO_DATA_INFORMATION(long offset, long count)
            {
                FileOffset = offset;
                BeyondFinalZero = offset + count;
            }

            public long FileOffset;
            public long BeyondFinalZero;
        }

meine Code sieht wiefolgt aus:


int size = 600;
uint usize = 600;
uint bRet = 0;
IntPtr p = Marshal.AllocHGlobal(size);
long length = 2;
FILE_ZERO_DATA_INFORMATION data = new FILE_ZERO_DATA_INFORMATION(0, length);
uint structSize = (uint)Marshal.SizeOf(data);
IntPtr pBuffer = Marshal.AllocHGlobal((int)structSize);

var safeFileHandle = CreateFile("\\\\.\\C:",FileAccess.Read,FileShare.Write,IntPtr.Zero,FileMode.Open,0,IntPtr.Zero);
bool ok = DeviceIoControl(safeFileHandle, EIOControlCode.DiskGetPartitionInfo,null,0,IntPtr.Zero,4096,ref bRet, IntPtr.Zero);
if (!ok) throw new Win32Exception();
if (bRet != usize) throw new InvalidOperationException("Bad structure declaration");

Im Moment bekomme ich die Fehlermeldung, "Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess verwendet wird".

Ich bin mir auch nicht sicher, ob ich den Call der Funktion richtig habe. Wiegesagt, mein erster Versuch.

Kann sich das jemand mal angucken und mir evtl. die Richtung zeigen ?

Liebe Grüße

Glow

16.806 Beiträge seit 2008
vor 5 Jahren

C: ist keine gültige Angabe, wenn dann C:\
Nen CreateFile auf ein Disk-Root dürfte aber IIRC nicht funktionieren.
Was ist der Sinn, bzw. soll er sein?

G
Glowhollow Themenstarter:in
74 Beiträge seit 2018
vor 5 Jahren

Hi,

Die Sache ist die, das ich den SafeFileHandler für das anbinden an die GetDiskPartitionInfo Funktion brauche. Ich habe ja eigentlich nicht vor drauf zu schreiben, habe im Internet recherchiert, das man mit der CreateFile das Flag auf Write stellen muß, da das anders anscheined nicht funktioniert, wenn man den Verweis auf eine Platte legen will.

Wiegesagt, ich bin hier etwas überfragt. War auch sehr dürftig, die Dokumentation, warum das so sein soll.

[EDIT] //./C: ist schon richtig, ich will ja nicht aufs rootverzeichnis zugreifen, sondern die physische Partition erreichen.

[EDIT2] Geplant ist das ganze ja, um die Grundfunktionen herzustellen und mit der API warm zu werden, im späteren Verlauf, sollen virtuelle disk vergrößert werden können, aber da bin ich noch nicht.

Wichtig für mich ist erst mal eine grundlegende Funktionalität.

J
641 Beiträge seit 2007
vor 5 Jahren

cSharp Projekte : https://github.com/jogibear9988

G
Glowhollow Themenstarter:in
74 Beiträge seit 2018
vor 5 Jahren

[editiert]

Ok, ich habe die Funktion getestet und erste Werte zurückerhalten. Da ich zwar noch nicht alles dekodieren kann, die Struct aber ein guten Hinweis liefert forsche ich mal hier weiter.

DISK_GetPartitionInfo funktioniert. Wende mich jetzt den virtualDisk Funktionen zu, wie z.bsp. erweitern.

G
Glowhollow Themenstarter:in
74 Beiträge seit 2018
vor 5 Jahren

fürs Archiv:

DLL-Import wiefolgt:


[DllImport("Kernel32.dll", SetLastError = true)]
public static extern bool DeviceIoControl(
SafeFileHandle hDevice,
EIOControlCode IoControlCode,
ref STORAGE_PROPERTY_QUERY InBuffer,
int nInBufferSize,
out STORAGE_DEVICE_DESCRIPTOR OutBuffer,
int nOutBufferSize,
out int pBytesReturned,
IntPtr Overlapped
);

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern SafeFileHandle CreateFile(
string fullName,
[MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
[MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
IntPtr lpSecurityAttributes,
[MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
[MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
IntPtr hTemplateFile);

Enums, bitte auf pinvoke ziehen

Strukts zusätzlich wiefolgt:


[StructLayout(LayoutKind.Sequential)]
public struct STORAGE_PROPERTY_QUERY
{
public STORAGE_PROPERTY_ID PropertyId;
public STORAGE_QUERY_TYPE QueryType;
public byte[] AdditionalParameters;
}

[StructLayout(LayoutKind.Sequential)]
public struct STORAGE_DEVICE_DESCRIPTOR
{
public uint Version;
public uint Size;
public byte DeviceType;
public byte DeviceTypeModifier;
[MarshalAs(UnmanagedType.U1)]
public bool RemovableMedia;
[MarshalAs(UnmanagedType.U1)]
public bool CommandQueueing;
public uint VendorIdOffset;
public uint ProductIdOffset;
public uint ProductRevisionOffset;
public uint SerialNumberOffset;
public STORAGE_BUS_TYPE BusType;
public uint RawPropertiesLength;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x16)]
public byte[] RawDeviceProperties;
}

den vorherigen Code ersetze ich durch...


var query = new STORAGE_PROPERTY_QUERY { PropertyId = 0, QueryType = 0 };
var qsize = Marshal.SizeOf(query);
var result = new STORAGE_DEVICE_DESCRIPTOR { DeviceType = 24 } ;
var rsize = Marshal.SizeOf(result);
int written;

var safeFileHandle = CreateFile("\\\\.\\F:",FileAccess.Read,FileShare.Write,IntPtr.Zero,FileMode.Open,0,IntPtr.Zero);
bool ok = DeviceIoControl(safeFileHandle, EIOControlCode.DiskGetPartitionInfo, ref query, qsize, out result, rsize, out written, IntPtr.Zero);

Console.WriteLine("DeviceType:"+result.DeviceType.ToString()) // liefert dann ein ergebnis...
...
...
...
if (!ok) throw new Win32Exception();

mir ist zwar noch nicht ganz klar, was das Sequentiell bzw. Explizit bei den StructLayouts bedeutet, wenn mich hier jemand erleuchten möchten - gerne !

DeviceType 24 = ist eine Virtuelle Platte , F: ist eine virtuelle Platte, da jedoch virtual Disks um sie zu verarbeiten, anders geöffnet werden müssen, beende ich hiermit meine Exkursion und öffne einen neuen Thread, in dem es um Virtuelle Festplatten und die möglichkeit die über die WINApi zu erweitern.

Vielen Dank für die Hilfe.

P.S. Ach so, was macht MarshalAs ? Verstehe das konzept dahinter noch nicht.