Это же не все. Это только декларации, а где вызовы?sosed213 писал(а):Сделал вот так:
Это же не все. Это только декларации, а где вызовы?sosed213 писал(а):Сделал вот так:
Dim sDriveRoot As String
Dim sFS As String
sDriveRoot = StrConv(CStr(DriveRoot), vbUnicode)
sFS = StrConv("NTFS" & Chr(0), vbUnicode)
Call FormatEx2(ByVal StrPtr(sDriveRoot), _
FMIFS_HARDDISK, _
ByVal StrPtr(sFS), _
ByVal VarPtr(vFormat), _
AddressOf Callback.FormatExCallBack)
typedef void (STDAPICALLTYPE *PFORMATEX2)
(IN PWSTR pDrive, IN FMIFS_MEDIA_TYPE dwMediaType, IN PWSTR
pFileSystem,
IN PFORMATEX2PARAM pFormatEx2Param, IN PFMIFSCALLBACK Callback);
with
typedef struct _FORMATEX2PARAM
{
int nMajorVersion;
long nFlags;
PWSTR pVolumeLabel;
DWORD dwClusterSize;
int nVersion;
Public Type FormatEx2Param
nMajorVersion As Long
nFlags As Long
pVolumeLabel As Long
dwClusterSize As Long
nVersion As Long
End Type
Public Declare Sub FormatEx2 Lib "FMIFS.DLL" _
(ByVal pDrive As Long, _
ByVal dwMediaType As Long, _
ByVal pFileSystem As Long, _
ByVal pFormatEx2Param As Long, _
ByVal Callback As Long)
Если есть нормально работающая, то чем она не устраивает?sosed213 писал(а):P.S. Есть похожая функция FormatEx, она работает нормально.
Нифига такая ф-ция не вызывается, если открыть консоль для форматирования ее там даже в импортах нет. А откуда такая информация, что именно эта ф-ция вызывается для стандартного форматирования? И еще, отладку с форматированием проводить может быть весьма фатальным для данных занятием. Одна ошибка, даже случайная и геммора на месяц хватит.sosed213 писал(а):какие значения параметров передаются в функцию FormatEx2 (FMIFS.DLL), при помощи стандартного окна форматирования (в Windows)
RecognizedPartition
Indicates, when TRUE, that the system recognized the type of the partition. When FALSE, the system did not recognize the type of the partition.
Public Type DRIVE_LAYOUT_INFORMATION_MBR
Signature As Long
End Type
Public Type PARTITION_INFORMATION_MBR
PartitionType As Byte 'FAT32=0x0B
BootIndicator As Byte
Recognized As Integer
HiddenSectors As Long 'LARGE_LONG
End Type
Public Type PARTITION_INFORMATION_GPT
PartitionType As GUID
PartitionId As GUID
Attributes As LARGE_INTEGER 'DWord64
mName(35) As Integer
End Type
Public Type PARTITION_INFORMATION_EX
PartitionStyle As Long 'PARTITION_STYLE
OffSet As LARGE_INTEGER
Size As LARGE_INTEGER
PartitionNumber As Long
RewritePartition As Byte
Union_Part_Mbr_Gpt As PARTITION_INFORMATION_GPT
End Type
Public Type DRIVE_LAYOUT_INFORMATION_GPT
DiskId As GUID
StartingUsableOffset As LARGE_INTEGER
UsableLength As LARGE_INTEGER
MaxPartitionCount As Long
End Type
Public Type DRIVE_LAYOUT_INFORMATION_EX
PartitionStyle As Long 'PARTITION_STYLE
PartitionCount As Long
Union_Driver_Mbr_Gpt As DRIVE_LAYOUT_INFORMATION_GPT
Partitions(127) As PARTITION_INFORMATION_EX
End Type
Dim dwOutBytes As Long
Dim DL As DRIVE_LAYOUT_INFORMATION_EX
Dim retIOCTL As Long
retIOCTL = DeviceIoControl(hDrive, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, ByVal 0&, 0, DL, LenB(DL), dwOutBytes, ByVal 0&)
/*
Control codes used while bringing disk online
*/
#define IOCTL_DISK_GET_DISK_ATTRIBUTES CTL_CODE(IOCTL_DISK_BASE, 0x003c, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DISK_SET_DISK_ATTRIBUTES CTL_CODE(IOCTL_DISK_BASE, 0x003d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define DISK_ATTRIBUTE_OFFLINE 0x1
#define DISK_ATTRIBUTE_READ_ONLY 0x2
/*
Structure used while bringing disk Online
*/
typedef struct _SET_DISK_ATTRIBUTES
{
ULONG Version; //Structure size
BOOLEAN Persist; //Remain after reboot
BOOLEAN RelinquishOwnership; //Release previously received ownership
BOOLEAN Reserved1[2]; //Padding
ULONGLONG Attributes; //Attributes(DISK_ATTRIBUTE_OFFLINE,DISK_ATTRIBUTE_READ_ONLY)
ULONGLONG AttributesMask; //Attributes mask
GUID Owner; //Owner GUID
} SET_DISK_ATTRIBUTES, *PSET_DISK_ATTRIBUTES;
typedef enum
{
PROGRESS,
DONEWITHSTRUCTURE,
UNKNOWN2,
UNKNOWN3,
UNKNOWN4,
UNKNOWN5,
INSUFFICIENTRIGHTS,
UNKNOWN7,
UNKNOWN8,
UNKNOWN9,
UNKNOWNA,
DONE,
UNKNOWNC,
UNKNOWND,
OUTPUT,
STRUCTUREPROGRESS
} CALLBACKCOMMAND;
typedef BOOLEAN (__stdcall *PFMIFSCALLBACK)( CALLBACKCOMMAND Command, DWORD SubAction, PVOID ActionInfo );
// Format command in FMIFS
//
// media flags
#define FMIFS_HARDDISK 0xC
#define FMIFS_FLOPPY 0x8
typedef VOID (__stdcall *PFORMATEX)( PWCHAR DriveRoot,
DWORD MediaFlag,
PWCHAR Format,
PWCHAR Label,
BOOL QuickFormat,
DWORD ClusterSize,
PFMIFSCALLBACK Callback );
bool bFormatSuccess = false;
/*
Retrieves just all volume GUIDs
*/
void GetVolumeGUIDS( std::vector<std::wstring>& pVec )
{
DWORD dwResult = ERROR_SUCCESS;
HANDLE FindHandle = INVALID_HANDLE_VALUE;
BOOL Success = FALSE;
WCHAR VolumeName[MAX_PATH] = L"";
// Enumerate all volumes in the system.
FindHandle = FindFirstVolumeW(VolumeName, ARRAYSIZE(VolumeName));
if (FindHandle == INVALID_HANDLE_VALUE)
return;
for (;;)
{
pVec.push_back(std::wstring(VolumeName));
// Move on to the next volume.
Success = FindNextVolumeW(FindHandle, VolumeName, ARRAYSIZE(VolumeName));
if ( !Success )
{
dwResult = GetLastError();
if (dwResult != ERROR_NO_MORE_FILES)
{
dwResult = GetLastError();
break;
}
// Finished iterating through all the volumes.
dwResult = ERROR_SUCCESS;
break;
}
}
FindVolumeClose(FindHandle);
}
/*
Removes previously available volumes from container
*/
void FilterGuids( std::vector<std::wstring> vecCurrent, std::vector<std::wstring>& vecDiff )
{
std::vector<std::wstring> vecNewGUIDs;
std::vector<std::wstring> vecTmp;
bool bPresent = false;
GetVolumeGUIDS(vecNewGUIDs);
for(DWORD i=0;i<vecNewGUIDs.size();i++)
{
bPresent = false;
for(DWORD j=0;j<vecCurrent.size();j++)
if(vecCurrent[j].compare(vecNewGUIDs[i])==0)
{
bPresent = true;
break;
}
if(!bPresent)
vecTmp.push_back(vecNewGUIDs[i]);
}
vecDiff = vecTmp;
}
/*
Assigns letter to a volume by its GUID
IN:
wszGUID - volume GUID
pwsLetter - pointer to variable that will receive letter
maxlen - max size of pwsLetter
OUT:
pwsLetter - assigned letter
Return:
Error code
*/
DWORD AssignLetter( const wchar_t* wszGUID, wchar_t* pwsLetter, int maxlen )
{
BOOL bResult = FALSE;
DWORD dwByteCount = 0; //Returned bytes count
DWORD dwCounter =0;
//Obtain volume letter from GUID
bResult = GetVolumePathNamesForVolumeNameW(wszGUID, pwsLetter, maxlen, &dwByteCount);
//Assign letter to volume
if(wcslen(pwsLetter)==0)
{
//Retrieve bitmap of used letters
DWORD dwUsedLetters = GetLogicalDrives();
//starting from C:\ (3rd drive)
DWORD dwCurrLetterBit = 1<<2;
//Get first unused letter
while(dwUsedLetters & dwCurrLetterBit)
{
//Move to next drive bit
dwCurrLetterBit <<= 1;
dwCounter++;
}
//Print letter
StringCbPrintfW(pwsLetter, maxlen, L"%c:\\", dwCounter+67);
//Assign letter to volume
bResult = SetVolumeMountPointW(pwsLetter, wszGUID);
if(!bResult)
return GetLastError();
}
return ERROR_SUCCESS;
}
/*
Callback for FormatEx function
IN:
Command - callback command
Modifier - unknown
Argument - pointer to callback data
Return:
Error code
*/
BOOLEAN __stdcall FormatExCallback( CALLBACKCOMMAND Command, DWORD Modifier, PVOID Argument )
{
PBOOLEAN status = NULL;
// We get other types of commands, but we don't have to pay attention to them
if(Command == DONE)
{
status = (PBOOLEAN) Argument;
if( *status == FALSE )
{
DWORD dwErr = GetLastError();
//Sometimes function finishes with FALSE status, but formats partition
//If partition was formatted, last error is not 0
if(dwErr != ERROR_SUCCESS)
{
bFormatSuccess = false;
return FALSE;
}
}
else
{
bFormatSuccess = true;
return TRUE;
}
}
return TRUE;
}
/*
Performs partition format
IN:
pwszName - partition letter
OUT:
void
Return:
Error code
*/
DWORD FormatVolume(wchar_t* pwszName )
{
DWORD dwResult = ERROR_SUCCESS;
DWORD dwRetries = 3;
//Load dll containing format function
HMODULE hDll = LoadLibrary("fmifs.dll");
if(!hDll)
return GetLastError();
PFORMATEX FormatEx = (PFORMATEX)GetProcAddress(hDll, "FormatEx");
if(!FormatEx)
{
FreeLibrary(hDll);
return GetLastError();
}
bFormatSuccess = false;
SetLastError(ERROR_SUCCESS);
//Perform quick format to NTFS with default cluster size
FormatEx(pwszName, FMIFS_HARDDISK, L"NTFS", L"Label", TRUE, 0,FormatExCallback);
//Retry format in case of fail. Sometimes partition is formatted only on second run
while (!bFormatSuccess && dwRetries > 0)
{
Sleep(100);
dwRetries--;
bFormatSuccess = false;
SetLastError(ERROR_SUCCESS);
FormatEx(pwszName, FMIFS_HARDDISK, L"NTFS", L"Label", TRUE, 0,FormatExCallback);
}
FreeLibrary(hDll);
return dwResult;
}
/*
Partitions attached disk and creates NTFS volume
IN:
dDrive - zero-based PhysicalDrive number
OUT:
void
Return:
Error code
*/
DWORD CreateVolume( HANDLE hDrive )
{
DWORD dwResult = ERROR_SUCCESS;
GET_LENGTH_INFORMATION DiskLength = {0}; //Disk size
HANDLE hDevice = hDrive; //Disk device handle
BOOL bResult = 0; //Function call result
DWORD junk = 0; //bytes received
DRIVE_LAYOUT_INFORMATION_EX *pLayoutInfo; //Partitioning structure
DWORD dwStructSize = 0; //size of pLie
CREATE_DISK disk; //MBR sector info
SET_DISK_ATTRIBUTES sda = {0}; //Used to bring disk online
std::vector<std::wstring> vecGUIDs; //List of volumes in system
//Enumerate present volumes before creating new
GetVolumeGUIDS(vecGUIDs);
//Required size for 4 partitions
dwStructSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX)+3*sizeof(PARTITION_INFORMATION_EX);
pLayoutInfo = (DRIVE_LAYOUT_INFORMATION_EX*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, dwStructSize);
if(hDevice==INVALID_HANDLE_VALUE)
return GetLastError();
ZeroMemory(&disk,sizeof(CREATE_DISK));
disk.PartitionStyle = PARTITION_STYLE_MBR;
disk.Mbr.Signature = GetTickCount(); //signature
//Some values got from experimenting, and they work
sda.Version = sizeof(sda);
sda.Persist = 1;
sda.RelinquishOwnership = FALSE;
sda.Attributes = 0;
sda.AttributesMask = 3;
//Bring disk online and clear read-only flag
bResult = DeviceIoControl(hDevice,IOCTL_DISK_SET_DISK_ATTRIBUTES,&sda,sizeof(sda), NULL, 0,&junk,NULL);
if(!bResult)
{
if(pLayoutInfo)
HeapFree(GetProcessHeap(),0,pLayoutInfo);
return GetLastError();
}
//Get disk size
bResult = DeviceIoControl(hDevice,IOCTL_DISK_GET_LENGTH_INFO,NULL,0, &DiskLength, sizeof(GET_LENGTH_INFORMATION),&junk,NULL);
if(!bResult)
{
if(pLayoutInfo)
HeapFree(GetProcessHeap(),0,pLayoutInfo);
return GetLastError();
}
//Create MBR
bResult = DeviceIoControl(hDevice,IOCTL_DISK_CREATE_DISK,&disk,sizeof(CREATE_DISK),NULL, 0,&junk,NULL);
if(!bResult)
{
if(pLayoutInfo)
HeapFree(GetProcessHeap(),0,pLayoutInfo);
return GetLastError();
}
//Get new device properties
bResult = DeviceIoControl(hDevice,IOCTL_DISK_UPDATE_PROPERTIES,NULL,0,NULL, 0,&junk,NULL);
if(!bResult)
{
if(pLayoutInfo)
HeapFree(GetProcessHeap(),0,pLayoutInfo);
return GetLastError();
}
//Fill partition table
if (hDevice!=INVALID_HANDLE_VALUE)
{
//First partition - occupies all available space
pLayoutInfo->PartitionEntry[0].PartitionStyle = PARTITION_STYLE_MBR;
pLayoutInfo->PartitionEntry[0].StartingOffset.QuadPart = 1048576; //1 MB offset
pLayoutInfo->PartitionEntry[0].PartitionLength.QuadPart = DiskLength.Length.QuadPart - 1048576 - 2048*512;
pLayoutInfo->PartitionEntry[0].PartitionNumber = 1;
pLayoutInfo->PartitionEntry[0].RewritePartition = TRUE;
pLayoutInfo->PartitionEntry[0].Mbr.PartitionType = PARTITION_IFS; //valid NTFS partition
pLayoutInfo->PartitionEntry[0].Mbr.BootIndicator = FALSE;
pLayoutInfo->PartitionEntry[0].Mbr.RecognizedPartition = 1;
pLayoutInfo->PartitionEntry[0].Mbr.HiddenSectors = /*32256/512*/2048; //Vista style partitioning
//Fill unused partitions info
for(int i=1;i<4;i++)
{
pLayoutInfo->PartitionEntry[i].PartitionStyle = PARTITION_STYLE_MBR;
pLayoutInfo->PartitionEntry[i].PartitionNumber = i+1;
pLayoutInfo->PartitionEntry[i].Mbr.PartitionType = PARTITION_ENTRY_UNUSED;
}
pLayoutInfo->PartitionStyle = PARTITION_STYLE_MBR;
pLayoutInfo->PartitionCount = 4; //must be exactly 4
pLayoutInfo->Mbr.Signature = GetTickCount();
//Set partition layout
bResult = DeviceIoControl(hDevice,IOCTL_DISK_SET_DRIVE_LAYOUT_EX,pLayoutInfo,dwStructSize,NULL,0,&junk,NULL);
if(bResult)
{
wchar_t wszLetter[4];
DWORD dwTimeout = 20 * 1000; //20 sec.
std::vector<std::wstring> vecDiff; //New volume GUID
DeviceIoControl(hDevice,IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0,NULL,0,&junk,NULL);
if(pLayoutInfo)
HeapFree(GetProcessHeap(),0,pLayoutInfo);
//Wait for system to find new volume
FilterGuids(vecGUIDs, vecDiff);
while (vecDiff.size() == 0 && dwTimeout > 0)
{
dwTimeout -= 100;
Sleep(100);
FilterGuids(vecGUIDs, vecDiff);
}
//if found new partition
if(vecDiff.size() > 0)
{
dwResult = AssignLetter(vecDiff[0].data(), wszLetter, sizeof(wszLetter));
//Format partition to NTFS
if(dwResult==ERROR_SUCCESS)
dwResult = FormatVolume(wszLetter);
}
else
dwResult = ERROR_NO_DATA;
}
else
{
if(pLayoutInfo)
HeapFree(GetProcessHeap(),0,pLayoutInfo);
dwResult = GetLastError();
}
}
return dwResult;
}
Интересно Mbr.Signature, принципиально за что нибудь отвечает, или это просто идентификатор диска, так нигде описания и не нашел.
А тайминги ты приблизительные ставил или где то написано что так и надо?
Сейчас этот форум просматривают: SemrushBot и гости: 17