Win32 Disk Management IO Control Codes - SET DRIVE LAYOUT
post id: 12
post length: 17569
post datetime: 12/9/2009 6:52:57 PM
post ip: 77.51.3.219
Win32 Disk Management IO Control Codes - SET DRIVE LAYOUT
Дата подачи: 24.01.2009
Win32 Disk Management I/O Control Codes
(from winioctl.h).
• GET DRIVE LAYOUT
• SET DRIVE LAYOUT
[Продолжение прошлогодней темы…]
смотрим все логические диски разделов 1-го физического диска и у кого ФАТ16 - меняем на ФАТ32.
'
' на всякий случай, при необходимости пройтись непосредственно по
' томам (вернее логич. дискам) можно
' применить такую конструкци.
'
For Each str As String In Environment.GetLogicalDrives()
'
Dim Handle As Integer = CreateFile(String.Concat("\\.\", Left(str, Len(str) - 1)) _
, GENERIC_ALL _
, FILE_SHARE_READ Or FILE_SHARE_WRITE _
, 0 _
, OPEN_EXISTING _
, FILE_ATTRIBUTE_NORMAL _
, 0)
'
' обход томов, смонтированных на
' что-либо рассматривалось
' ранее.
'
GetVolumeNameForVolumeMountPoint(str)
'
' ...
' ...
'
Next
Example [Visual Basic]:
Option Strict Off : Option Explicit On
Imports Tested.Emicrox.DiskManagement _
, Tested.Emicrox.Exception _
, Tested.Emicrox.TAPE _
, Tested.Emicrox.IO
Public Module Main
'
<STAThread()> Sub Main()
'
Dim Handle As Integer = CreateFile("\\.\PHYSICALDRIVE0" _
, GENERIC_READ Or GENERIC_WRITE _
, FILE_SHARE_READ Or FILE_SHARE_WRITE _
, 0 _
, OPEN_EXISTING _
, FILE_ATTRIBUTE_NORMAL _
, 0)
'
If Not (Handle = -1) Then
'
Dim DriverLayout = Z_Get_Drive_Layout(Handle)
'
With DriverLayout
'
For i As Integer = 0 To .PartitionCount
'
With .PartitionEnTry(i)
'
If (.PartitionType = PartitionType.FAT16) _
Or (.PartitionType = PartitionType.FAT32) _
Or (.PartitionType = PartitionType.NTFS) Then
'
If (.PartitionType = PartitionType.FAT16) And Not (.BootIndicator = 1) Then
'
' ну, или как-то так...
'
.PartitionType = PartitionType.FAT32
'
Z_Set_Drive_Layout(Handle, DriverLayout)
'
End If
'
End If
'
End With
'
Next
'
End With
'
CloseHandle(Handle)
'
Else
'
Console.WriteLine(String.Concat("error opening device: " _
, GetErrorMessage()) _
)
'
End If
'
Console.ReadLine()
'
End Sub
'
End Module
----------
Namespace Emicrox
'
<SuppressUnmanagedCodeSecurity()> _
Public NotInheritable Class DiskManagement
'
#Region "---------- DISK LAYOUT ----------"
'
Shared Function Z_Get_Drive_Layout(ByVal Handle As Integer)
'
Dim ret = Nothing
'
Dim ptrSize = 1024
'
Dim ptr As IntPtr = Marshal.AllocHGlobal(ptrSize)
'
If Not (DeviceIoControl(Handle _
, IOCTL_DISK_GET_DRIVE_LAYOUT, Nothing, 0, ptr, ptrSize _
, New Integer, 0) = 0) Then
'
ret = Marshal.PtrToStructure(ptr _
, GetType(DRIVE_LAYOUT_INFORMATION))
'
Else
'
Console.WriteLine(String.Concat("error get drive layout: " _
, GetErrorMessage()) _
)
'
End If
'
Marshal.FreeHGlobal(ptr)
'
Return ret
'
End Function
'
Shared Sub Z_Set_Drive_Layout(ByVal Handle As Integer, ByVal drivelayout As DRIVE_LAYOUT_INFORMATION)
'
Dim ptrSize = Marshal.SizeOf(drivelayout)
'
Dim ptr As IntPtr = Marshal.AllocHGlobal(ptrSize)
'
Marshal.StructureToPtr(drivelayout, ptr, True)
'
If Not (DeviceIoControl(Handle _
, IOCTL_DISK_SET_DRIVE_LAYOUT, ptr, ptrSize, Nothing, 0 _
, New Integer, 0) = 0) Then
'
Else
'
Console.WriteLine(String.Concat("error set drive layout: " _
, GetErrorMessage()) _
)
'
End If
'
Marshal.FreeHGlobal(ptr)
'
End Sub
'
Const IOCTL_DISK_GET_DRIVE_LAYOUT_EX As Integer = 458832
Const IOCTL_DISK_SET_DRIVE_LAYOUT_EX As Integer = 507988
Const IOCTL_DISK_GET_DRIVE_LAYOUT As Integer = 475148
Const IOCTL_DISK_SET_DRIVE_LAYOUT As Integer = 507920
'
Public Enum PartitionType As Byte
FAT16 = 6
FAT32 = 11
NTFS = 7
End Enum
'
<StructLayout(LayoutKind.Sequential)> _
Public Structure DRIVE_LAYOUT_INFORMATION
Public PartitionCount As Integer
Public Signature As Integer
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=56)> Public PartitionEnTry() As PARTITION_INFORMATION
End Structure
'
<StructLayout(LayoutKind.Explicit)> _
Public Structure PARTITION_INFORMATION
<FieldOffset(0)> Public StartingOffset As Long
<FieldOffset(8)> Public PartitionLength As Long
<FieldOffset(16)> Public HiddenSectors As Integer
<FieldOffset(20)> Public PartitionNumber As Integer
<FieldOffset(24)> Public PartitionType As Byte
<FieldOffset(25)> Public BootIndicator As Byte
<FieldOffset(26)> Public RecognizedPartition As Byte
<FieldOffset(27)> Public RewritePartition As Byte
End Structure
'
#End Region
'
<DllImport("kernel32")> _
Public Shared Function DeviceIoControl( _
ByVal hDevice As Integer, _
ByVal dwIoControlCode As Integer, _
ByVal lpInBuffer As [IntPtr], _
ByVal nInBufferSize As Integer, _
ByVal lpOutBuffer As [IntPtr], _
ByVal nOutBufferSize As Integer, _
ByRef lpBytesReturned As Integer, _
ByVal lpOverlapped As Integer _
) As Integer
End Function
'
End Class
'
'
End Namespace
----------
Namespace Emicrox
'
<SuppressUnmanagedCodeSecurity()> _
Public Class Exception
'
Shared FORMAT_MESSAGE_ALLOCATE_BUFFER As Integer = &H100
Shared FORMAT_MESSAGE_IGNORE_INSERTS As Integer = &H200
Shared FORMAT_MESSAGE_FROM_SYSTEM As Integer = &H1000
'
Public Shared Function GetErrorMessage() As String
'
Dim errorCode = GetLastError()
'
Dim msgSize As Integer = 255
'
Dim lpMsgBuf As String = Nothing
'
Dim dwFlags As Integer = FORMAT_MESSAGE_ALLOCATE_BUFFER _
Or FORMAT_MESSAGE_FROM_SYSTEM _
Or FORMAT_MESSAGE_IGNORE_INSERTS
'
Dim lpSource As IntPtr = IntPtr.Zero
'
Dim lpArguments As IntPtr = IntPtr.Zero
'
Dim ReturnVal As Integer _
= FormatMessage(dwFlags, lpSource, errorCode, 0, lpMsgBuf, msgSize, lpArguments)
'
If ReturnVal = 0 Then
'
Return errorCode.ToString()
'
Else
'
Return lpMsgBuf
'
End If
'
End Function
'
'
<DllImport("kernel32")> _
Public Shared Function GetLastError( _
) As Integer
End Function
'
<DllImport("kernel32.dll")> _
Public Shared Function FormatMessage( _
ByVal dwFlags As Integer, _
ByRef lpSource As IntPtr, _
ByVal dwMessageId As Integer, _
ByVal dwLanguageId As Integer, _
ByRef lpBuffer As [String], _
ByVal nSize As Integer, _
ByRef Arguments As IntPtr _
) As Integer
End Function
'
End Class
'
End Namespace
Namespace Emicrox
'
<SuppressUnmanagedCodeSecurity()> _
Public Class IO
'
Public Const FILE_SHARE_READ = &H1
Public Const FILE_SHARE_WRITE = &H2
Public Const FILE_SHARE_DELETE = &H4
' ...
'
<DllImport("kernel32", EnTryPoint:="CreateFileA", ExactSpelling:=True, CharSet:=CharSet.[Ansi])> _
Public Shared Function CreateFile( _
<MarshalAs(UnmanagedType.VBByRefStr)> ByRef lpFileName As String, _
ByVal dwDesiredAccess As UInteger, _
ByVal dwShareMode As Integer, _
ByVal lpSecurityAttributes As Integer, _
ByVal dwCreationDisposition As Integer, _
ByVal dwFlagsAndAttributes As Integer, _
ByVal hTemplateFile As Integer _
) As Integer
End Function
' ...
'
End Class
'
End Namespace
|
THE END.
-------------------------------------
коррект от: 24.01.2009
ВРЕМЕННО! Будет удалено..
Для внутреннего пользования! ;))
Win32 Disk Management I/O Control Codes
(from winioctl.h).
• SET DRIVE LAYOUT
Кратко по поводу защиты данных на флешке:
Суть: Модифицируем структуру разделов съёмного диска перед его извлечением. Комбинируя такми значениями таблицы разделов, как [PartitionType], [PartitionLength] и [StartOfset] получаем своеобразное неординарное сочетание параметров, без восстановления которых работа с данными как бы не возможна.
До:
После:
Результат:
-----------------------
Option Strict Off : Option Explicit On
Imports System.Runtime.InteropServices
Public Module Main
<DllImport("kernel32")> _
Public Shared Function DeviceIoControl( _
<[In]()> ByVal hDevice As Integer, _
<[In]()> ByVal dwIoControlCode As Integer, _
<[In]()> ByVal lpInBuffer As [IntPtr], _
<[In]()> ByVal nInBufferSize As Integer, _
<[Out]()> ByVal lpOutBuffer As [IntPtr], _
<[In]()> ByVal nOutBufferSize As Integer, _
<[In]()> ByRef lpBytesReturned As Integer, _
<[In]()> ByVal lpOverlapped As Integer _
) As Integer
End Function
<StructLayout(LayoutKind.Sequential)> _
Public Structure DRIVE_LAYOUT_INFORMATION
Public PartitionCount As Integer
Public Signature As Integer
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> Public PartitionEnTry() As PARTITION_INFORMATION
End Structure
<StructLayout(LayoutKind.Explicit)> _
Public Structure PARTITION_INFORMATION
<FieldOffset(0)> Public StartingOffset As Long
<FieldOffset(8)> Public PartitionLength As Long
<FieldOffset(16)> Public HiddenSectors As Integer
<FieldOffset(20)> Public PartitionNumber As Integer
<FieldOffset(24)> Public PartitionType As Byte
<FieldOffset(25)> Public BootIndicator As Boolean
<FieldOffset(26)> Public RecognizedPartition As Boolean
<FieldOffset(27)> Public RewritePartition As Boolean
End Structure
Shared Function Z_Get_Drive_Layout(ByVal Handle As Integer)
'
Dim ret = Nothing
'
Dim ptrSize = Marshal.SizeOf(New DRIVE_LAYOUT_INFORMATION)
'
Dim ptr As IntPtr = Marshal.AllocHGlobal(ptrSize)
'
If Not (DeviceIoControl(Handle _
, [475148.0F], Nothing, 0, ptr, ptrSize _
, New Integer, 0) = 0) Then
'
ret = Marshal.PtrToStructure(ptr _
, GetType(DRIVE_LAYOUT_INFORMATION))
'
End If
'
Marshal.FreeHGlobal(ptr)
'
Return ret
'
End Function
'
Shared Sub Z_Set_Drive_Layout(ByVal Handle As Integer, ByVal drivelayout As DRIVE_LAYOUT_INFORMATION)
'
Dim ptrSize = Marshal.SizeOf(drivelayout)
'
Dim ptr As IntPtr = Marshal.AllocHGlobal(ptrSize)
'
Marshal.StructureToPtr(drivelayout, ptr, True)
'
If Not (DeviceIoControl(Handle _
, [507920.0F], ptr, ptrSize, Nothing, 0 _
, New Integer, 0) = 0) Then
End If
'
Marshal.FreeHGlobal(ptr)
'
End Sub
Shared Sub Z_Update_Properties(ByVal Handle As Integer)
'
If Not (DeviceIoControl(Handle _
, [459072.0F], Nothing, 0, Nothing, 0 _
, New Integer, 0) = 0) Then
Else
'
Console.WriteLine(String.Concat(GetErrorMessage()))
'
End If
'
End Sub
<STAThread()> Sub Main()
'
Dim Handle As Integer = CreateFile("\\.\K:" _
, &H80000000L _
+ &H40000000L _
+ &H20000000L, &H1 _
+ &H2 _
+ &H4 _
, 0, 3, 128, 0)
'
If Not (Handle = -1) Then
'
Dim DriverLayout = Z_Get_Drive_Layout(Handle)
'
' 1-й [из 4-х]:
With DriverLayout.PartitionEnTry(0)
'
.RewritePartition = True
'
Select Case .PartitionType
Case 7.0F 'NTFS
'
' [1] Encripted...
'
.PartitionLength = 1024
.PartitionType = [2.0F]
'
Case 2.0F 'none
'
' [2] Decripted...
'
.PartitionLength = [original value]
.PartitionType = [7.0F]
'
End Select
'
End With
'
Z_Set_Drive_Layout(Handle, DriverLayout)
'
Z_Update_Properties(Handle)
'
CloseHandle(Handle)
'
End If
'
End Sub
'
End Module
|
То же самое можно реализовать и вообще не прибегая к [DeviceIoControl] , а исключительно используя абсолютные офсеты,
например:
из MSDN:
Partition Table on Basic Disks
The partition table, which is a 64-byte data Structure that is used to identify the type and location of partitions on a hard disk, conforms to a standard layout, independent of the operating system. Each partition table enTry is 16 bytes long, With a maximum of four entries. EachenTry starts at a predetermined offset from the beginning of the sector, As follows:
• Partition 1 0x01BE (446)
0x01BE 1 byte 80 Boot Indicator. Indicates whether the
volume
is the
active partition. Legal values include:
• 00. Do not use For booting.
• 80. Active partition.
0x01BF 1 byte 01 Starting Head.
0x01C0 6 bits 01 *2 Starting Sector. Only bits 0–5 are
used. The
upper two bits, 6 and 7, are used by the Starting Cylinder field.
0x01C1 10 bits 00 * Starting Cylinder. Uses 1 byte in
addition to
the upper 2 bits from the Starting Sector field to make up the
cylinder value. The Starting Cylinder is a 10-bit number that hAs a
maximum value of 1023.
0x01C2 1 byte 07 System ID. Defines the volume type. See
the table
titled “System ID Values” later in this section For sample values.
0x01C3 1 byte FE Ending Head.
0x01C4 6 bits BF * Ending Sector. Only bits 0–5 are used.
The upper
two bits, 6 and 7, are used by the Ending Cylinder field.
0x01C5 10 bits 09 * Ending Cylinder. Uses 1 byte in
addition to the
upper 2 bits from the Ending Sector field to make up the cylinder
value. The Ending Cylinder is a 10-bit number, With a maximum value
of 1023.
0x01C6 4 bytes 3F 00 00 00 Relative Sectors. The offset
from the
beginning of the disk to the beginning of the volume, counting by
sectors.
0x01CA 4 bytes 4B F5 7F 00 Total Sectors. The total number
of sectors in the volume.
• Partition 2 0x01CE (462)
• Partition 3 0x01DE (478)
• Partition 4 0x01EE (494)
и т.д…
[подробнее – в MS:SDK]
THE END. |