Win32 Disk Management IO Control Codes - SET DRIVE LAYOUT

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.