window下的磁盘相关操作qt版本,相关磁盘操作接口亦可用于MFC

China☆狼群 提交于 2020-10-14 00:38:19

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <windows.h>
#include <dbt.h>
#include <QThread>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class Thread;

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void my_log(QString str);
    void my_log1(QString str);
    void WriteToFile(const char* fileName, const char* str);
    wchar_t MydwordTowchar_t(DWORD i);
    void AddusbToChoice(wchar_t letter);
    void DelusbToChoice(wchar_t letter);
    int WriteSector(int startsector, int numberofsector, char *buffer);
    char * ReadSector(int startsector, int numberofsectors);
    DWORD GetTotalSector(QString szPath);
    int GetPhysicalDriveNumber(char cDriveName );
    int ChangeStringDriveNameToDriveNumber();


private:
    //UsbConfig usbConfig;
    char FirstDriveFromMask(ULONG unitmask);
    DWORD GetDesignatedDiskFreeSpace(const QString &szPath);
    DWORD GetSystemDiskPhysicalNumber();
    int GetPhysicalDriveFromPartitionLetter(wchar_t letter);
    DWORD FormatVolume(wchar_t letter);
    DWORD GetDriveGeometry(const wchar_t*disk, DISK_GEOMETRY *pdg);
    int DestroyDisk(DWORD disk);
    int CreateDisk(DWORD disk, WORD partNum);
public slots:
    void DealThreadMsgInt(int value);
    void DealThreadMsgQString(QString value);

protected:
    bool nativeEvent(const QByteArray &eventType, void *message, long *result);


private slots:
    void on_pushButton_format_clicked();

    void on_pushButton_sdcard_clicked();

    void on_pushButton_fub_clicked();

    void on_pushButton_start_clicked();

    void on_radioButton_s32v_clicked();

    void on_radioButton_imx6_clicked();

    void on_textBrowser_log_textChanged();

    void on_textBrowser_log1_textChanged();


    void on_comboBox_emmc1_currentIndexChanged(const QString &arg1);

    void on_comboBox_emmc_currentIndexChanged(const QString &arg1);

public:
    Ui::MainWindow *ui;

    //write tool
    QString m_log;
    QString m_pathDriver;
    QString m_strDriveSize;
    QString sdcard_strFilePath;
    QString fub_strFilePath;
    QString fub_strFileName;
    int progress_bar;
    DWORD Sdcard_StartWriteSector{8}; //2个扇区为1k
    DWORD m_dwStartWriteSector;
    int m_nPhysicalNumber{0};
    int m_dwDriveNumber{0x100};
    BOOL m_isWritting{false};
    BOOL m_isFormating{false};
    Thread * m_workThread{nullptr};

    //format tool
    int m_sysdiskNumber{0};
    int m_seldiskNumber{1};
    QString m_strDriveSize1;
    QString m_log1;
    QString m_pathDriver1;
};




class Thread : public QThread
{
    Q_OBJECT
public:
    Thread(MainWindow *p):pm(p){};
    ~Thread(){};
signals:
    void msgPrgress(int value);
    void msgPrgress(QString value);
private:
    void run();
private:
    MainWindow* pm;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QtSerialPort/QSerialPortInfo>
#include <stdio.h>
#include <string>
#include <stdlib.h>
#include <fstream>
#include <sstream>
#include <QMessageBox>
#include <QFileDialog>
#include <QFile>



#define VOLUMEDISKSIZE (sizeof(VOLUME_DISK_EXTENTS))


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->comboBox_emmc->setCurrentText("");
    ui->comboBox_emmc1->setCurrentText("");
    ui->tabWidget->setCurrentIndex(0);
    ui->radioButton_s32v->setChecked(true);
    m_sysdiskNumber = GetSystemDiskPhysicalNumber();

    for(wchar_t i =L'A';i<L'Z';i++)
    {
        AddusbToChoice(i);
    }
}

MainWindow::~MainWindow()
{

    delete ui;
    m_workThread->deleteLater();
}

void MainWindow::my_log(QString str)
{
    m_log +=str;
    m_log += "\r";
    ui->textBrowser_log->setText(m_log);
}

void MainWindow::my_log1(QString str1)
{
    m_log1 +=str1;
    m_log1 += "\r";
    ui->textBrowser_log1->setText(m_log1);
}

char MainWindow::FirstDriveFromMask(ULONG unitmask)
{
    char i;
    for (i = 0; i < 26; ++i)
    {
        if (unitmask & 0x1)
            break;
        unitmask = unitmask >> 1;
    }
    return (i + 'A');

}

DWORD MainWindow::GetDesignatedDiskFreeSpace(const QString &szPath)
{
    DWORD dwTotalDiskSpace, dwFreeDiskSpace, dwUsedDiskSpace;

    ULARGE_INTEGER uiFreeBytesAvailableToCaller;
    ULARGE_INTEGER uiTotalNumberOfBytes;
    ULARGE_INTEGER uiTotalNumberOfFreeBytes;


    const wchar_t * encodedName = reinterpret_cast<const wchar_t *>(szPath.utf16());

    if (GetDiskFreeSpaceEx(encodedName, &uiFreeBytesAvailableToCaller,
                           &uiTotalNumberOfBytes,
                           &uiTotalNumberOfFreeBytes))
    {
        dwTotalDiskSpace = (DWORD)(uiTotalNumberOfBytes.QuadPart / 1024 / 1024);
        dwFreeDiskSpace = (DWORD)(uiFreeBytesAvailableToCaller.QuadPart >> 20);
        dwUsedDiskSpace = dwTotalDiskSpace - dwFreeDiskSpace;
        QString str=QString("磁盘%1总空间%2MB, 已用%3MB, 可用%4MB").arg(szPath).arg(dwTotalDiskSpace).arg(dwUsedDiskSpace).arg(dwFreeDiskSpace);
        my_log(str);
        my_log1(str);
        return dwTotalDiskSpace;
    }
    return -1;
}

DWORD MainWindow::GetSystemDiskPhysicalNumber()
{
    wchar_t diskLetter[50];
    DWORD diskNumber;

    DWORD ret = GetSystemDirectory(diskLetter, sizeof(diskLetter));
    if (ret <= 0)
    {
        MessageBoxA(NULL,"获取系统盘目录失败!!", "错误", NULL);
        return (DWORD)-1;
    }

    diskNumber = GetPhysicalDriveFromPartitionLetter(diskLetter[0]);
    return diskNumber;
}

int MainWindow::GetPhysicalDriveFromPartitionLetter(wchar_t letter)
{
    HANDLE hDevice;               // handle to the drive to be examined
    BOOL result;                 // results flag
    DWORD readed;                   // discard results
    STORAGE_DEVICE_NUMBER number;   //use this to get disk numbers

    wchar_t _devicename[] = TEXT("\\\\.\\A:");
    _devicename[4] = letter;

    hDevice = CreateFile(_devicename, // drive to open
                         GENERIC_READ | GENERIC_WRITE,    // access to the drive
                         FILE_SHARE_READ | FILE_SHARE_WRITE,    //share mode
                         NULL,             // default security attributes
                         OPEN_EXISTING,    // disposition
                         0,                // file attributes
                         NULL);            // do not copy file attribute
    if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    {
        return -1;
    }

    result = DeviceIoControl(
                hDevice,                // handle to device
                IOCTL_STORAGE_GET_DEVICE_NUMBER, // dwIoControlCode
                NULL,                            // lpInBuffer
                0,                               // nInBufferSize
                &number,           // output buffer
                sizeof(number),         // size of output buffer
                &readed,       // number of bytes returned
                NULL      // OVERLAPPED structure
                );
    if (!result) // fail
    {
        (void)CloseHandle(hDevice);
        return -1;
    }
    //printf("%d %d %d\n\n", number.DeviceType, number.DeviceNumber, number.PartitionNumber);

    (void)CloseHandle(hDevice);
    return number.DeviceNumber;
}

DWORD MainWindow::FormatVolume(wchar_t letter)
{
    DWORD ret = -1;
    wchar_t commod[] = L"format Z: /fs:fat32 /Q /Y";
    commod[7] = letter;

    size_t convertedChars = 0;
    size_t dByteNum = sizeof(commod) / sizeof(wchar_t) + 1;

    char* dest = new char[dByteNum];

    if (wcstombs_s(&convertedChars, dest, dByteNum, commod, _TRUNCATE) == 0)
    {
        WriteToFile("DiskPartition.bat", dest);
        Sleep(1000);
        ShellExecute(NULL, NULL, L"DiskPartition.bat", NULL, NULL, SW_HIDE);
        Sleep(1000);
        ret = 1;
    }
    return ret;
}

DWORD MainWindow::GetDriveGeometry(const wchar_t *disk, DISK_GEOMETRY *pdg)
{
    HANDLE hDevice;               // handle to the drive to be examined
    BOOL bResult;                  // results flag
    DWORD junk;                   // discard results

    hDevice = CreateFile(disk, // drive
                         0,                // no access to the drive
                         FILE_SHARE_READ | // share mode
                         FILE_SHARE_WRITE,
                         NULL,             // default security attributes
                         OPEN_EXISTING,   // disposition
                         0,                // file attributes
                         NULL);            // do not copy file attributes

    if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    {
        return DWORD(-1);
    }

    bResult = DeviceIoControl(hDevice, // device to be queried
                              IOCTL_DISK_GET_DRIVE_GEOMETRY, // operation to perform
                              NULL, 0, // no input buffer
                              pdg, sizeof(*pdg),     // output buffer
                              &junk,                 // # bytes returned
                              (LPOVERLAPPED)NULL); // synchronous I/O

    CloseHandle(hDevice);

    return 0;
}

int MainWindow::DestroyDisk(DWORD disk)
{
    HANDLE hDevice;               // handle to the drive to be examined
    BOOL result;                  // results flag
    DWORD readed;                 // discard results
    wchar_t diskPath[] = L"\\\\.\\PhysicalDrive1";

    diskPath[17] = MydwordTowchar_t(disk);

    hDevice = CreateFile(
                diskPath, // drive to open
                GENERIC_READ | GENERIC_WRITE,     // access to the drive
                FILE_SHARE_READ | FILE_SHARE_WRITE, //share mode
                NULL,             // default security attributes
                OPEN_EXISTING,    // disposition
                0,                // file attributes
                NULL            // do not copy file attribute
                );
    if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    {
        return -1;
    }

    result = DeviceIoControl(
                hDevice,               // handle to device
                IOCTL_DISK_DELETE_DRIVE_LAYOUT, // dwIoControlCode
                NULL,                           // lpInBuffer
                0,                              // nInBufferSize
                NULL,                           // lpOutBuffer
                0,                              // nOutBufferSize
                &readed,      // number of bytes returned
                NULL        // OVERLAPPED structure
                );
    if (!result)
    {
        //fprintf(stderr, "IOCTL_DISK_DELETE_DRIVE_LAYOUT Error: %ld\n", GetLastError());
        (void)CloseHandle(hDevice);
        return -1;
    }

    //fresh the partition table
    result = DeviceIoControl(hDevice,IOCTL_DISK_UPDATE_PROPERTIES,NULL,0,
                             NULL,0,&readed,NULL);
    if (!result)
    {
        (void)CloseHandle(hDevice);
        return -1;
    }
    (void)CloseHandle(hDevice);
    return true;
}

int MainWindow::CreateDisk(DWORD disk, WORD partNum)
{
    HANDLE hDevice;               // handle to the drive to be examined
    BOOL result;                  // results flag
    DWORD readed;                 // discard results
    DWORD ret;
    WORD i;
    DISK_GEOMETRY pdg;
    DWORD sectorSize;
    DWORD signature;
    LARGE_INTEGER diskSize;
    LARGE_INTEGER partSize;
    BYTE actualPartNum;

    DWORD layoutStructSize;
    DRIVE_LAYOUT_INFORMATION_EX *dl;
    CREATE_DISK newDisk;

    wchar_t diskPath[] = L"\\\\.\\PhysicalDrive1";

    diskPath[17] = MydwordTowchar_t(disk);

    actualPartNum = (BYTE)partNum;

    hDevice = CreateFile(diskPath,GENERIC_READ | GENERIC_WRITE,
                         FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,  //default security attributes
                         OPEN_EXISTING, // disposition
                         0,              // file attributes
                         NULL);
    if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    {
        return -1;
    }

    // Create primary partition MBR
    newDisk.PartitionStyle = PARTITION_STYLE_MBR;
    signature = (DWORD)time(NULL);     //get signature from current time
    newDisk.Mbr.Signature = signature;

    result = DeviceIoControl(hDevice,IOCTL_DISK_CREATE_DISK,&newDisk,
                             sizeof(CREATE_DISK),NULL,0,&readed,NULL);
    if (!result)
    {
        (void)CloseHandle(hDevice);
        return -1;
    }

    //fresh the partition table
    result = DeviceIoControl(hDevice,IOCTL_DISK_UPDATE_PROPERTIES,
                             NULL,0,NULL,0,&readed,NULL);
    if (!result)
    {
        (void)CloseHandle(hDevice);
        return -1;
    }

    //Now create the partitions
    ret = GetDriveGeometry(diskPath, &pdg);

    if ((DWORD)-1 == ret)
    {
        return ret;
    }
    sectorSize = pdg.BytesPerSector;
    diskSize.QuadPart = pdg.Cylinders.QuadPart * pdg.TracksPerCylinder *
            pdg.SectorsPerTrack * pdg.BytesPerSector;       //calculate the disk size;
    partSize.QuadPart = diskSize.QuadPart / actualPartNum;

    layoutStructSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + (actualPartNum - 1) * sizeof(PARTITION_INFORMATION_EX);
    dl = (DRIVE_LAYOUT_INFORMATION_EX*)malloc(layoutStructSize);
    if (NULL == dl)
    {
        (void)CloseHandle(hDevice);
        return -1;
    }

    dl->PartitionStyle = (DWORD)PARTITION_STYLE_MBR;
    dl->PartitionCount = actualPartNum;
    dl->Mbr.Signature = signature;

    //clear the unused partitions
    for (i = 0; i < actualPartNum; i++){
        dl->PartitionEntry[i].RewritePartition = 1;
        dl->PartitionEntry[i].Mbr.PartitionType = PARTITION_ENTRY_UNUSED;
    }
    //set the profile of the partitions
    for (i = 0; i < actualPartNum; i++){
        dl->PartitionEntry[i].PartitionStyle = PARTITION_STYLE_MBR;
        dl->PartitionEntry[i].StartingOffset.QuadPart = 60*1024*1024 +  //开头空出60M空间
                (partSize.QuadPart * i) + ((LONGLONG)(pdg.SectorsPerTrack) * (LONGLONG)(pdg.BytesPerSector));   //32256
        dl->PartitionEntry[i].PartitionLength.QuadPart = partSize.QuadPart - 60 * 1024 * 1024 -
                ((LONGLONG)(pdg.SectorsPerTrack) * (LONGLONG)(pdg.BytesPerSector));
        dl->PartitionEntry[i].PartitionNumber = i + 1;
        dl->PartitionEntry[i].RewritePartition = TRUE;
        dl->PartitionEntry[i].Mbr.PartitionType = PARTITION_FAT32;
        dl->PartitionEntry[i].Mbr.BootIndicator = FALSE;
        dl->PartitionEntry[i].Mbr.RecognizedPartition = TRUE;
        dl->PartitionEntry[i].Mbr.HiddenSectors =
                pdg.SectorsPerTrack + (DWORD)((partSize.QuadPart / sectorSize) * i);
    }
    //execute the layout
    result = DeviceIoControl(hDevice,IOCTL_DISK_SET_DRIVE_LAYOUT_EX,dl,
                             layoutStructSize,NULL,0,&readed,NULL);
    if (!result)
    {
        free(dl);
        (void)CloseHandle(hDevice);
        return -1;
    }

    //fresh the partition table
    result = DeviceIoControl(hDevice,IOCTL_DISK_UPDATE_PROPERTIES,
                             NULL,0,NULL,0,&readed,NULL);
    if (!result)
    {
        free(dl);
        (void)CloseHandle(hDevice);
        return -1;
    }

    free(dl);
    (void)CloseHandle(hDevice);
    Sleep(3000);            //wait the operations take effect
    return true;
}

void MainWindow::DealThreadMsgInt(int value)
{
    ui->progressBar->setValue(value);
}

void MainWindow::DealThreadMsgQString(QString value)
{
    m_log +=value;
    m_log += "\r";
    ui->textBrowser_log->setText(m_log);
}

int MainWindow::WriteSector(int startsector, int numberofsectors, char *buffer)
{
    wchar_t temp2[20];
    LARGE_INTEGER startbytes;
    QString StringTemp;

    // All msdos data structures must be packed on a 1 byte boundary
#pragma pack (1)
    struct
    {
        DWORD StartingSector ;
        WORD NumberOfSectors ;
        DWORD pBuffer;
    }ControlBlock;
#pragma pack ()

#pragma pack (1)
    typedef struct _DIOC_REGISTERS
    {
        DWORD reg_EBX;
        DWORD reg_EDX;
        DWORD reg_ECX;
        DWORD reg_EAX;
        DWORD reg_EDI;
        DWORD reg_ESI;
        DWORD reg_Flags;
    } DIOC_REGISTERS ;
#pragma pack ()

    HANDLE hDevice ;
    DIOC_REGISTERS reg ;
    BOOL  fResult ;
    DWORD cb ;

    // Creating handle to vwin32.vxd (win 9x)
    hDevice = CreateFile ( TEXT("\\\\.\\vwin32"),
                           0,
                           0,
                           NULL,
                           0,
                           FILE_FLAG_DELETE_ON_CLOSE,
                           NULL );

    if ( hDevice == INVALID_HANDLE_VALUE )
    {
        // win NT/2K/XP code
        HANDLE hDevice;
        DWORD byteswrite;

        wchar_t _devicename[30];

        if (m_nPhysicalNumber == 0 )
            return FALSE;

        swprintf(_devicename,30,TEXT("\\\\.\\PhysicalDrive%d"), m_nPhysicalNumber);

        // Creating a handle to disk drive using CreateFile () function ..
        hDevice = CreateFile(_devicename,
                             GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
                             NULL, OPEN_EXISTING, 0 , NULL);

        if (hDevice == INVALID_HANDLE_VALUE)
            return FALSE;

        startbytes.LowPart = ((startsector&0x7fffff) << 9);
        if (startsector&0xff800000)
            startbytes.HighPart = ((startsector&0xff800000)>>23);
        else
            startbytes.HighPart = 0;

        // Setting the pointer to point to the start of the sector we want to read ..
        SetFilePointerEx (hDevice, startbytes, NULL, FILE_BEGIN);
        //SetFilePointer (hDevice, ((startsector&0x7fffff) << 9), NULL, FILE_BEGIN);

        if (!WriteFile (hDevice, buffer, 512*numberofsectors, &byteswrite, NULL) )
            return FALSE;

        if (byteswrite != (512*(DWORD)numberofsectors))
        {
            swprintf(temp2,20,L"%d sectors",byteswrite);
            StringTemp =QString::fromWCharArray(temp2);
            MessageBoxA(NULL,"Only copy a part ","ERROR",NULL);

            return FALSE;
        }
    }
    else
    {
        return FALSE;
    }
    CloseHandle(hDevice);
    return TRUE;
}

char * MainWindow::ReadSector(int startsector, int numberofsectors)
{
    // All msdos data structures must be packed on a 1 byte boundary
#pragma pack (1)
    struct
    {
        DWORD StartingSector ;
        WORD NumberOfSectors ;
        DWORD pBuffer;
    }ControlBlock;
#pragma pack ()

#pragma pack (1)
    typedef struct _DIOC_REGISTERS
    {
        DWORD reg_EBX;
        DWORD reg_EDX;
        DWORD reg_ECX;
        DWORD reg_EAX;
        DWORD reg_EDI;
        DWORD reg_ESI;
        DWORD reg_Flags;
    } DIOC_REGISTERS ;
#pragma pack ()

    char* buffer = (char*)malloc (512*numberofsectors);
    HANDLE hDevice ;
    DIOC_REGISTERS reg ;
    BOOL  fResult ;
    DWORD cb ;

    // Creating handle to vwin32.vxd (win 9x)
    hDevice = CreateFile ( TEXT("\\\\.\\vwin32"),
                           0,
                           0,
                           NULL,
                           0,
                           FILE_FLAG_DELETE_ON_CLOSE,
                           NULL );

    if ( hDevice == INVALID_HANDLE_VALUE )
    {
        // win NT/2K/XP code
        HANDLE hDevice;
        DWORD bytesread;

        wchar_t _devicename[] = TEXT("\\\\.\\A:");
        _devicename[4] += m_dwDriveNumber;

        // Creating a handle to disk drive using CreateFile () function ..
        hDevice = CreateFile(_devicename,
                             GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
                             NULL, OPEN_EXISTING, 0, NULL);

        if (hDevice == INVALID_HANDLE_VALUE)
        {
            free(buffer);
            buffer = NULL;
            goto finish;
        }

        // Setting the pointer to point to the start of the sector we want to read ..
        SetFilePointer (hDevice, (startsector*512), NULL, FILE_BEGIN);

        if (!ReadFile (hDevice, buffer, 512*numberofsectors, &bytesread, NULL) )
        {
            free(buffer);
            buffer = NULL;
            goto finish;
        }

    }
    else
    {
        free(buffer);
        buffer = NULL;
        goto finish;
    }
finish:
    CloseHandle(hDevice);
    return buffer;
}



DWORD MainWindow::GetTotalSector(QString szPath)
{
    struct _DISK_GEOMETRY_EX
    {	DISK_GEOMETRY  Geometry;
        LARGE_INTEGER  DiskSize;
        UCHAR  Data[1];
    } DiskEX;

    HANDLE hDevice;
    DWORD bytesReturned;
    DWORD totalSector = 0;
    DWORD bRet;

    wchar_t _devicename[] = TEXT("\\\\.\\A:");
    _devicename[4]=szPath.utf16()[0];

    // Creating a handle to disk drive using CreateFile () function ..
    hDevice = CreateFile(_devicename,
                         GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
                         NULL, OPEN_EXISTING, 0, NULL);

    if (hDevice == INVALID_HANDLE_VALUE)
        return FALSE;

    bRet = DeviceIoControl(
                hDevice,              // handle to device
                IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,    // dwIoControlCode
                NULL,                          // lpInBuffer
                0,                             // nInBufferSize
                (LPVOID) &DiskEX,          // output buffer
                sizeof(DiskEX),        // size of output buffer
                (LPDWORD) &bytesReturned ,     // number of bytes returned
                NULL    // OVERLAPPED structure
                );

    if (bRet == 0)
    {
        return FALSE;
    }

    if ( DiskEX.DiskSize.HighPart != 0 )
    {
        totalSector = ((DiskEX.DiskSize.HighPart) << 23);
    }
    totalSector |= (DiskEX.DiskSize.LowPart >> 9);

    return  totalSector;
}


int MainWindow::GetPhysicalDriveNumber(char cDriveName )
{
    HANDLE hDevice;
    DWORD dwOut;
    BOOL bRet;
    wchar_t vcDriveName[ 40 ];
    VOLUME_DISK_EXTENTS* pstVolumeData;
    int iDiskNumber;

    // alloc memory
    pstVolumeData = ( VOLUME_DISK_EXTENTS * ) malloc( VOLUMEDISKSIZE );
    if( pstVolumeData == NULL )
    {
        return -1;
    }
    //
    swprintf( vcDriveName,7,TEXT("\\\\?\\%c:"), cDriveName );
    // Open Device
    hDevice = CreateFile( vcDriveName, GENERIC_READ, FILE_SHARE_READ |
                          FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
    if( hDevice == INVALID_HANDLE_VALUE )
    {
        return -1;
    }
    // Call Device Io Control
    bRet = DeviceIoControl( hDevice, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
                            NULL, 0, pstVolumeData, VOLUMEDISKSIZE, &dwOut, NULL );
    if( bRet == FALSE )
    {
        free( pstVolumeData );
        return -1;
    }
    CloseHandle( hDevice );
    // Disk number is lower than 1 is failed.
    if( pstVolumeData->NumberOfDiskExtents < 1 )
    {
        free( pstVolumeData );
        return -1;
    }
    iDiskNumber = pstVolumeData->Extents[0].DiskNumber;
    free( pstVolumeData );
    return iDiskNumber;
}

int MainWindow::ChangeStringDriveNameToDriveNumber()
{
    DWORD dwReturnValue = TRUE;

    if ( m_pathDriver == "D:\\")
        m_dwDriveNumber = 3; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "E:\\")
        m_dwDriveNumber = 4; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "F:\\")
        m_dwDriveNumber = 5; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "G:\\")
        m_dwDriveNumber = 6; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "H:\\")
        m_dwDriveNumber = 7; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "I:\\")
        m_dwDriveNumber = 8; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "J:\\")
        m_dwDriveNumber = 9; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "K:\\")
        m_dwDriveNumber = 10; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "L:\\")
        m_dwDriveNumber = 11; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "M:\\")
        m_dwDriveNumber = 12; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "N:\\")
        m_dwDriveNumber = 13; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "O:\\")
        m_dwDriveNumber = 14; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "P:\\")
        m_dwDriveNumber = 15; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "Q:\\")
        m_dwDriveNumber = 16; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "R:\\")
        m_dwDriveNumber = 17; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "S:\\")
        m_dwDriveNumber = 18; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "T:\\")
        m_dwDriveNumber = 19; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "U:\\")
        m_dwDriveNumber = 20; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "V:\\")
        m_dwDriveNumber = 21; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "W:\\")
        m_dwDriveNumber = 22; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "X:\\")
        m_dwDriveNumber = 23; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "Y:\\")
        m_dwDriveNumber = 24; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else if ( m_pathDriver == "Z:\\")
        m_dwDriveNumber = 25; // driver number [0=A, 1=B, 2=C, 3=D ....]
    else
        dwReturnValue = FALSE;

    return dwReturnValue;
}

wchar_t MainWindow::MydwordTowchar_t(DWORD i)
{
    wchar_t ch = L'0';
    if(i<10)
    {
        ch = QString("%1").arg(i).utf16()[0];
    }
    return ch;
}

void MainWindow::AddusbToChoice(wchar_t letter)
{
    char ch = letter;
    //int n = GetPhysicalDriveFromPartitionLetter(letter);
    int n = GetPhysicalDriveNumber(ch);
    if(n > 0 && n != m_sysdiskNumber)
    {
        QString temp = QString("%1").arg(QChar(letter))+":\\";
        ui->comboBox_emmc->addItem(temp);
        ui->comboBox_emmc1->addItem(temp);
    }
}

void MainWindow::DelusbToChoice(wchar_t letter)
{
    int index = ui->comboBox_emmc->findText(QString("%1:\\").arg(QChar(letter)));
    ui->comboBox_emmc->removeItem(index);
    ui->comboBox_emmc1->removeItem(index);
    ui->comboBox_emmc->setCurrentIndex(-1);
    ui->comboBox_emmc1->setCurrentIndex(-1);
}


void MainWindow::WriteToFile(const char* fileName, const char* str)
{
    std::filebuf fb;
    if (fb.open(fileName, std::ios::out) == NULL)
    {
        my_log("选择磁盘失败,请重新扫描,并选择相应磁盘.");
        return;
    }
    std::ostream os(&fb);
    os << str;
    fb.close();
}



bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
    Q_UNUSED(eventType);
    *result = 0;
    MSG* msg = reinterpret_cast<MSG*>(message);
    int msgType = msg->message;

    if (msgType == WM_DEVICECHANGE) {

        PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)msg->lParam;

        switch (msg->wParam)
        {
        case DBT_DEVICETYPESPECIFIC:
        {
            qDebug() << "DBT_DEVICETYPESPECIFIC ";
            break;
        }
        case DBT_DEVICEARRIVAL:
            if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME)
            {
                PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
                if (lpdbv->dbcv_flags == 0)
                {
                    // 插入U盘,此处可以做你想做的事
                    // lpdbv->dbcv_unitmask
                    //即盘符标志位,1bit,0为A,1为B,10为C,11为D…以此类推
                    qDebug() << "USB_insert";

                    QString USBDisk = QString(FirstDriveFromMask(lpdbv->dbcv_unitmask));
                    m_seldiskNumber = GetPhysicalDriveFromPartitionLetter(USBDisk.utf16()[0]);
                    AddusbToChoice(USBDisk.utf16()[0]);
                    ui->comboBox_emmc->setCurrentText(USBDisk+":\\");
                    ui->comboBox_emmc1->setCurrentText(USBDisk+":\\");
                    my_log("移动设备:"+USBDisk+"盘插入");
                    my_log1("移动设备:"+USBDisk+"盘插入");
                    //qDebug() << "USB_Arrived and The USBDisk is: "<<USBDisk;

                    m_pathDriver = USBDisk + ":\\";
                    m_pathDriver1 = m_pathDriver;

                    DWORD driveSize = GetTotalSector(m_pathDriver);
                    driveSize = driveSize/2/1024;
                    if (driveSize <= 0 || driveSize > 240800)
                    {
                        MessageBox(NULL,TEXT("获取磁盘大小失败!!"), TEXT("错误"), NULL);
                    }
                    else
                    {
                        QString uint = driveSize > 1024 ? "GB" : "MB";
                        float size = driveSize >= 1024 ? float(driveSize)/1024.0f : driveSize;
                        m_strDriveSize = QString::number(size,'f',2) + uint;
                        ui->lineEdit_size->setText(m_strDriveSize);
                        ui->lineEdit_size1->setText(m_strDriveSize);
                    }
                }
            }
            //qDebug() << "DBT_DEVICEARRIVAL";
            break;
        case DBT_DEVICEREMOVECOMPLETE:
            if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
            {
                PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
                if (lpdbv -> dbcv_flags == 0)
                {
                    qDebug() << "USB_delete";
                    QString USBDisk = QString(FirstDriveFromMask(lpdbv->dbcv_unitmask));
                    DelusbToChoice(USBDisk.utf16()[0]);
                    m_pathDriver = "";
                    m_pathDriver1 = m_pathDriver;
                    my_log("移动设备:"+USBDisk+"盘已拔出");
                    my_log1("移动设备:"+USBDisk+"盘已拔出");
                    ui->comboBox_emmc->setCurrentText(USBDisk+":\\盘已拔出");
                    ui->comboBox_emmc1->setCurrentText(USBDisk+":\\盘已拔出");
                    ui->lineEdit_size->setText("");
                    ui->lineEdit_size1->setText("");
                }
            }
            break;
        }
    }
    return false;
}

void MainWindow::on_pushButton_start_clicked()
{   
    if(m_isWritting||m_isFormating )
    {
        MessageBox(NULL,TEXT("正在进行烧录或格式化\n中,请稍后再行操作!!"), TEXT("提示"), NULL);
        return;
    }

    char *pMBRBuffer = NULL;
    wchar_t temp[6];

    QString strMBR;

    if (!ChangeStringDriveNameToDriveNumber())
    {
        MessageBox(NULL,TEXT("请选择TF卡!!"),TEXT("错误"),NULL);
        return ;
    }
    ui->progressBar->setRange(0,100);
    progress_bar = 0;
    ui->progressBar->setValue(progress_bar);


    if( (m_nPhysicalNumber = GetPhysicalDriveNumber( char((char)(m_dwDriveNumber)+97) )) == -1)
    {
        MessageBox(NULL,TEXT("非TF卡或TF卡不可读!!"),TEXT("错误"),NULL);
        return ;
    }
    pMBRBuffer = ReadSector(0,1); // read MBR sector.
    if (pMBRBuffer == NULL )
    {
        MessageBox(NULL,TEXT("读取扇区失败,请先尝试\n用分区工具进行分区!! "),TEXT("错误"),NULL);
        return ;
    }
    else
    {
        temp[0] = pMBRBuffer[0x52];
        temp[1] = pMBRBuffer[0x53];
        temp[2] = pMBRBuffer[0x54];
        temp[3] = pMBRBuffer[0x55];
        temp[4] = pMBRBuffer[0x56];
        temp[5] = '\0';

        strMBR = QString::fromWCharArray(temp);

        if ( strMBR != "FAT32")
        {
            MessageBox(NULL,TEXT("磁盘不是FAT32格式!!"),TEXT("错误"),NULL);
            return ;
        }
    }

    if (sdcard_strFilePath.isEmpty())
    {
        MessageBox(NULL,TEXT("未选择sdcard系统\n包,请重新选择!!"), TEXT("错误"), NULL);
        return;
    }

    progress_bar+=10;
    ui->progressBar->setValue(progress_bar);

    if(!m_workThread)
    {
        m_workThread = new Thread(this);

        connect(m_workThread,&Thread::started,[this]{
            m_isWritting = true;
        });
        connect(m_workThread,&Thread::finished,[this]{

            disconnect(m_workThread,SIGNAL(msgPrgress(int)),this,SLOT(DealThreadMsgInt(int)));
            disconnect(m_workThread,SIGNAL(msgPrgress(QString)),this,SLOT(DealThreadMsgQString(QString)));
            m_isWritting = false;
            m_workThread->deleteLater();
            m_workThread = nullptr;
        });

        connect(m_workThread,SIGNAL(msgPrgress(int)),this,SLOT(DealThreadMsgInt(int)));
        connect(m_workThread,SIGNAL(msgPrgress(QString)),this,SLOT(DealThreadMsgQString(QString)));

        m_workThread->start();
    }
}


void MainWindow::on_pushButton_format_clicked()
{
    if(m_isWritting||m_isFormating )
    {
        MessageBox(NULL,TEXT("正在进行烧录或格式化\n中,请稍后再行操作!!"), TEXT("提示"), NULL);
        goto END;
    }

    if(ui->comboBox_emmc1->currentText().isEmpty() || ui->lineEdit_size1->text().isEmpty())
    {
        MessageBox(NULL,TEXT("请选择一个磁盘开始格式化!!"), TEXT("错误"), NULL);
        goto END;
    }

    if (m_seldiskNumber > 9 && m_seldiskNumber <= 0)
    {
        MessageBox(NULL,TEXT("磁盘数过多(不可多于9个)或\n选择了系统所在盘!!"), TEXT("错误"), NULL);
        goto END;
    }

    m_isFormating = true;
    if (DestroyDisk(m_seldiskNumber) < 0)
    {
        MessageBox(NULL,TEXT("删除磁盘分区失败,请以管理员\n权限重新运行程序!!"), TEXT("错误"), NULL);
        goto END;
    }

    if (!CreateDisk(m_seldiskNumber, 1))
    {
        MessageBox(NULL,TEXT("创建分区失败,请以管理员\n权限重新运行程序!!"), TEXT("错误"), NULL);
        goto END;
    }

    if(FormatVolume(m_pathDriver1.utf16()[0])< 0)
    {
        MessageBox(NULL,TEXT("格式化分区失败,请以管理员\n权限重新运行程序!!"), TEXT("错误"), NULL);
        goto END;
    }

    my_log1("已分区格式化完成!!");

    MessageBox(NULL,TEXT("一键格式化完成!!"), TEXT("提示"), NULL);
END:
    m_isFormating = FALSE;
    return;
}

void MainWindow::on_pushButton_sdcard_clicked()
{
    sdcard_strFilePath = QFileDialog::QFileDialog::getOpenFileName(this, tr("Open File"),
                                                                   "./",
                                                                   tr("sdcard(*.sdcard);;All(*.*)"));
    ui->lineEdit_sdcard->setText(sdcard_strFilePath);
}

void MainWindow::on_pushButton_fub_clicked()
{
    fub_strFilePath = QFileDialog::getOpenFileName(this, tr("Open File"),
                                                   "./",
                                                   tr("fub(*.fub);;All(*.*)"));
    int index =fub_strFilePath.lastIndexOf('/');
    fub_strFileName = fub_strFilePath.right(fub_strFilePath.length()-index-1);
    ui->lineEdit_fub->setText(fub_strFilePath);
}


void MainWindow::on_radioButton_s32v_clicked()
{
    Sdcard_StartWriteSector = 8;
    my_log("你已选择平台 S32V.");
}

void MainWindow::on_radioButton_imx6_clicked()
{
    Sdcard_StartWriteSector = 2;
    my_log("你已选择平台 IMX6.");

}

void MainWindow::on_textBrowser_log_textChanged()
{
    ui->textBrowser_log->moveCursor(QTextCursor::End);
}

void MainWindow::on_textBrowser_log1_textChanged()
{
    ui->textBrowser_log1->moveCursor(QTextCursor::End);
}

void MainWindow::on_comboBox_emmc_currentIndexChanged(const QString &arg1)
{
    m_pathDriver = arg1;

    if(m_pathDriver.isEmpty()) return;
    ChangeStringDriveNameToDriveNumber();

    if( (m_nPhysicalNumber = GetPhysicalDriveNumber( char((char)(m_dwDriveNumber)+97) )) == -1)
    {
        MessageBox(NULL,TEXT("非TF卡或TF卡不可读!!"),TEXT("错误"),NULL);
        ui->comboBox_emmc->setCurrentText("");
        return;
    }
    DWORD driveSize = GetTotalSector(m_pathDriver);
    driveSize = driveSize/2/1024;
    if (driveSize <= 0 || driveSize > 240800)
    {
        MessageBox(NULL,TEXT("获取磁盘大小失败!!"), TEXT("错误"), NULL);
        ui->comboBox_emmc->setCurrentText("");
        return;
    }
    else
    {
        QString uint = driveSize > 1024 ? " GB" : " MB";
        float size = driveSize >= 1024 ? float(driveSize)/1024.0f : driveSize;
        m_strDriveSize = QString::number(size,'f',2) + uint;
        ui->lineEdit_size->setText(m_strDriveSize);
        my_log("你已选择"+m_pathDriver+"总大小 "+ m_strDriveSize);
    }
}

void MainWindow::on_comboBox_emmc1_currentIndexChanged(const QString &arg1)
{
    m_pathDriver1 = arg1;
    if(m_pathDriver1.isEmpty()) return;
    m_seldiskNumber = GetPhysicalDriveFromPartitionLetter(m_pathDriver1.utf16()[0]);
    if (m_seldiskNumber == -1)
    {
        MessageBox(NULL,TEXT("获取磁盘失败,请确认此盘是\n否存在或以管理员权限重新\n运行程序!!"), TEXT("错误"), NULL);
        ui->comboBox_emmc1->setCurrentText("");
        return;
    }
    else if (m_seldiskNumber == m_sysdiskNumber)
    {
        MessageBox(NULL,TEXT("系统所在的本地盘不能作\n为格式化对象,请重新选择!!"), TEXT("错误"), NULL);
        ui->comboBox_emmc1->setCurrentText("");
        return;
    }


    DWORD driveSize = GetTotalSector(m_pathDriver1);
    driveSize = driveSize/2/1024;
    if (driveSize <= 0 || driveSize > 240800)
    {
        MessageBox(NULL,TEXT("获取磁盘大小失败!!"), TEXT("错误"), NULL);
        return;
    }
    else
    {
        QString uint = driveSize > 1024 ? " GB" : " MB";
        float size = driveSize >= 1024 ? float(driveSize)/1024.0f : driveSize;
        m_strDriveSize1 = QString::number(size,'f',2) + uint;
        ui->lineEdit_size1->setText(m_strDriveSize1);
        my_log1("你已选择"+m_pathDriver1+"总大小 "+ m_strDriveSize1);
    }
}


void Thread::run()
{
    int count_succeed = 0;
    int count_expect = 0;
    wchar_t sectors[9];
    count_expect++;
    QFile s_sdcardFile(pm->sdcard_strFilePath);
    if(!s_sdcardFile.open(QIODevice::ReadOnly))
    {
        MessageBox(NULL,TEXT("无法打开sdcard文件,请以管理员\n权限重新运行程序!!"), L"错误", NULL);
        _exit(-1);
    }
    pm->progress_bar += 20;  //30
    emit msgPrgress(pm->progress_bar);
    Sleep(1000);

    pm->m_dwStartWriteSector = pm->Sdcard_StartWriteSector;
    QByteArray s_pbWriteBuffer = s_sdcardFile.readAll();

    if (s_pbWriteBuffer.size()<=1)
    {
        MessageBox(NULL,TEXT("读取文件失败,请以管理员\n权限重新运行程序!!"), TEXT("错误"), NULL);
        _exit(-1);
    }
    pm->progress_bar += 10; //40
    emit msgPrgress(pm->progress_bar);
    Sleep(1000);

    QString m_strFromSector,m_strToSector;

    swprintf(sectors, 9, L"%d", pm->m_dwStartWriteSector);
    m_strFromSector = QString::fromWCharArray(sectors);
    swprintf(sectors, 9, L"%d", pm->m_dwStartWriteSector + (s_pbWriteBuffer.size() / 512) + 1);
    m_strToSector = QString::fromWCharArray(sectors);

    emit msgPrgress("烧写 sdcard :" + m_strFromSector + "  到  " + m_strToSector);

    if (!pm->WriteSector(pm->m_dwStartWriteSector, s_pbWriteBuffer.size() / 512, s_pbWriteBuffer.data()))
    {
        MessageBox(NULL,TEXT("sdcard烧写失败,请以管理员\n权限重新运行程序!!"), TEXT("错误"), NULL);
        _exit(-1);
    }

    s_sdcardFile.close();
    emit msgPrgress("sdcard烧写完成 !");

    count_succeed++;

    pm->progress_bar += 20;  //60
    emit msgPrgress(pm->progress_bar);
    Sleep(1000);

    if (!pm->fub_strFilePath.isEmpty())
    {
        count_expect++;
        QFile f_fubFile(pm->fub_strFilePath);
        if (!f_fubFile.open(QIODevice::ReadOnly))
        {
            MessageBox(NULL,TEXT("无法打开Fub文件,请以管理员\n权限重新运行程序!!"), TEXT("错误"), NULL);
            _exit(-1);
        }
        pm->progress_bar += 10;  //70
        emit msgPrgress(pm->progress_bar);
        Sleep(500);

        s_pbWriteBuffer.clear();

        s_pbWriteBuffer = f_fubFile.readAll();
        if (s_pbWriteBuffer.size()<=1)
        {
            MessageBox(NULL,TEXT("读取文件失败,请以管理员\n权限重新运行程序!!"), TEXT("错误"), NULL);
            _exit(-1);
        }
        pm->progress_bar += 10;  //80
        emit msgPrgress(pm->progress_bar);
        Sleep(500);

        //wirte fub to autofuture
        QDir autofuturedir;
        QString csPath;
        csPath = pm->m_pathDriver + "autofuture";
        if (!autofuturedir.exists(csPath))
        {
            autofuturedir.mkpath(csPath);//不存在则创建
        }

        csPath += "\\"; csPath += pm->fub_strFileName;

        emit msgPrgress( "烧写fub文件到autofuture目录下 !");

        QFile MyWriteFile(csPath);

        if (!MyWriteFile.open(QIODevice::WriteOnly|QIODevice::Truncate))
        {
            MessageBox(NULL,TEXT("无法生成Fub文件,请以管理员\n权限重新运行程序!!"), TEXT("错误"), NULL);
            _exit(-1);
        }
        MyWriteFile.write(s_pbWriteBuffer.data(), s_pbWriteBuffer.size());
        MyWriteFile.close();

        f_fubFile.close();
        emit msgPrgress( "fub文件烧写完成 !");
        count_succeed++;

        pm->progress_bar += 20; //100
        emit msgPrgress(pm->progress_bar);
    }
    else
    {
        pm->progress_bar += 40;  //100
        emit msgPrgress(pm->progress_bar);
    }


    if (count_expect == count_succeed){
        MessageBox(NULL,TEXT("恭喜,烧写成功!!"), TEXT("提示"), NULL);
    }
    else{
        MessageBox(NULL,TEXT("烧写失败,请以管理员\n权限重新运行程序!!"), TEXT("错误"), NULL);
        _exit(-1);
    }
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!