C++ 中的 Win32 API 的无缓冲读写

问题描述 投票:0回答:1

我正在尝试在 UNBEFFERED 模式下写入 150 字节(用于测试),但我错过了一些东西......如果有人可以帮忙? 计算的对齐模拟是正确的,但文件上仍然有错误的数据写入数据... 要求是: 所需尺寸:1024 分配的指针地址位于:DB6154D0 分配的指针地址对齐于:DB615600

#include <Windows.h>
#include <iostream>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#include <string>

void DisplayError(LPTSTR lpszFunction);

// Macro Given by Microsoft for computing the closest even interval from the progam need.
#define ROUND_UP_SIZE(Value,Pow2) ((SIZE_T) ((((ULONG)(Value)) + (Pow2) - 1) & (~(((LONG)(Pow2)) - 1))))
#define ROUND_UP_PTR(Ptr,Pow2)  ((void *) ((((ULONG_PTR)(Ptr)) + (Pow2) - 1) & (~(((LONG_PTR)(Pow2)) - 1))))

// Config structure for Unbeffered IO.
struct HandleConfig {
    DWORD SectorsPerCluster;
    DWORD BytesPerSector;
    DWORD NumberOfFreeClusters;
    DWORD TotalNumberOfClusters;
};

void MesureDisk(HandleConfig* config, BOOL debug) {
    DWORD lpSectorsPerCluster;
    DWORD lpBytesPerSector;
    DWORD lpNumberOfFreeClusters;
    DWORD lpTotalNumberOfClusters;

    if (GetDiskFreeSpaceA(
        NULL,
        &lpSectorsPerCluster,
        &lpBytesPerSector,
        &lpNumberOfFreeClusters,
        &lpTotalNumberOfClusters)) {
        if (!debug) {
            std::cout << "Disk measure Ok.\r\n";
        }
        else {
            std::cout << "Disk measure Ok.\r\n";
            std::cout << "Disk Structure: " << "\r\n" <<
                "SectorsPerCluster: " << lpSectorsPerCluster << "\r\n" <<
                "lpBytesPerSector: " << lpBytesPerSector << "\r\n" <<
                "lpNumberOfFreeClusters: " << lpNumberOfFreeClusters << "\r\n" <<
                "lpTotalNumberOfClusters: " << lpTotalNumberOfClusters << "\r\n";
        }
    }
    config->SectorsPerCluster = lpSectorsPerCluster;
    config->BytesPerSector = lpBytesPerSector;
    config->NumberOfFreeClusters = lpNumberOfFreeClusters;
    config->TotalNumberOfClusters = lpTotalNumberOfClusters;
}

void Windows_write_UNBEFFERED() {
    // Config the handle. 
    HANDLE hFile;
    char DataBuffer[] = "Some data for test !\r\n";
    DWORD dwBytesToWrite = 150;//(DWORD)strlen(DataBuffer);
    DWORD dwBytesWritten = 0;
    LPCSTR filePath = "File.txt";  // File PATH.

    hFile = CreateFileA(
        filePath,
        GENERIC_WRITE,
        FILE_SHARE_READ,
        NULL,
        OPEN_ALWAYS,
        FILE_FLAG_NO_BUFFERING, //Set Flag
        NULL
    );

    // Measure the disc.
    HandleConfig fileConf;
    MesureDisk(&fileConf, TRUE);//Display the struct on Terminal.

    // Ensure you have one more sector than WRITE_SIZE would require.
    size_t sizeNeeded = fileConf.BytesPerSector + ROUND_UP_SIZE(dwBytesToWrite, fileConf.BytesPerSector);
    char* Buffer = new char[sizeNeeded];            //heap Allocation
    void* BufferAligned = ROUND_UP_PTR(Buffer, fileConf.BytesPerSector); //Offset the allocated Pointer from the disk Nomenclature.
    
    printf("sizeneeded: %d \r\n", sizeNeeded);
    printf("Allocated pointer address at: %X \r\n",Buffer );
    printf("Allocated pointer address Aligned at: %X \r\n", BufferAligned);
    
    // void* BU = VirtualAlloc(NULL, dwBytesToWrite, MEM_COMMIT,PAGE_READWRITE);
    if (!WriteFile(
        hFile,
        BufferAligned,
        sizeNeeded,                                 
        &dwBytesWritten,
        NULL)) {
        DWORD message = GetLastError();
        DisplayError((LPTSTR)&message);
        delete[] Buffer;
        CloseHandle(hFile);
        return;
    }
    CloseHandle(hFile);
    // VirtualFree(BU, 0, MEM_RELEASE);
    delete[] Buffer;
}

int main() {
    Windows_write_UNBEFFERED();
    return EXIT_SUCCESS;
}

void DisplayError(LPTSTR lpszFunction)
// Routine Description:
// Retrieve and output the system error message for the last-error code
{
    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError();

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR)&lpMsgBuf,
        0,
        NULL);

    lpDisplayBuf =
        (LPVOID)LocalAlloc(LMEM_ZEROINIT,
            (lstrlen((LPCTSTR)lpMsgBuf)
                + lstrlen((LPCTSTR)lpszFunction)
                + 40) // account for format string
            * sizeof(TCHAR));

    if (FAILED(StringCchPrintf((LPTSTR)lpDisplayBuf,
        LocalSize(lpDisplayBuf) / sizeof(TCHAR),
        TEXT("%s failed with error code %d as follows:\n%s"),
        lpszFunction,
        dw,
        lpMsgBuf)))
    {
        printf("FATAL ERROR: Unable to output error code.\n");
    }

    _tprintf(TEXT("ERROR: %s\n"), (LPCTSTR)lpDisplayBuf);

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
}

我正在尝试使用 WriteFile() 在 Windows 上以 UNBEFFERED 模式将 150 个字节写入一个简单文件,但此代码编译时缺少某些内容,但生成的文件内容错误。

c++ windows writefile
1个回答
0
投票
#include <Windows.h>
#include <iostream>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#include <string>
#include <chrono>

using namespace std::chrono;
void DisplayError(LPTSTR lpszFunction);

// Macro Given by Microsoft for computing the closest even interval from the progam need.
#define ROUND_UP_SIZE(Value,Pow2) ((SIZE_T) ((((ULONG)(Value)) + (Pow2) - 1) & (~(((LONG)(Pow2)) - 1))))
#define ROUND_UP_PTR(Ptr,Pow2)  ((void *) ((((ULONG_PTR)(Ptr)) + (Pow2) - 1) & (~(((LONG_PTR)(Pow2)) - 1))))

// Config structure for Unbeffered IO.
struct HandleConfig {
    DWORD SectorsPerCluster;
    DWORD BytesPerSector;
    DWORD NumberOfFreeClusters;
    DWORD TotalNumberOfClusters;
};

void MesureDisk(HandleConfig* config, BOOL debug) {
    DWORD lpSectorsPerCluster;
    DWORD lpBytesPerSector;
    DWORD lpNumberOfFreeClusters;
    DWORD lpTotalNumberOfClusters;

    if (GetDiskFreeSpaceA(
        NULL,
        &lpSectorsPerCluster,
        &lpBytesPerSector,
        &lpNumberOfFreeClusters,
        &lpTotalNumberOfClusters)) {
        if (!debug) {
            std::cout << "Disk measure Ok.\r\n";
        }
        else {
            std::cout << "Disk measure Ok.\r\n";
            std::cout << "Disk Structure: " << "\r\n" <<
                "SectorsPerCluster: " << lpSectorsPerCluster << "\r\n" <<
                "lpBytesPerSector: " << lpBytesPerSector << "\r\n" <<
                "lpNumberOfFreeClusters: " << lpNumberOfFreeClusters << "\r\n" <<
                "lpTotalNumberOfClusters: " << lpTotalNumberOfClusters << "\r\n";
        }
    }
    config->SectorsPerCluster = lpSectorsPerCluster;
    config->BytesPerSector = lpBytesPerSector;
    config->NumberOfFreeClusters = lpNumberOfFreeClusters;
    config->TotalNumberOfClusters = lpTotalNumberOfClusters;
}

void Windows_write_UNBEFFERED() {
    
    //Set the Data.
    std::string date = std::format("Date: {:%a %b %e %H:%M:%S %Z %Y}", zoned_time{ "Europe/Paris",floor<std::chrono::seconds>(system_clock::now()) });
    char DataBuffer[1024] = { "\0" };
    //Quick mem copy.
    size_t ct = 0;
    while (date[ct] != '\0') {
        DataBuffer[ct] = date.data()[ct];
        ct++;
    }

    // Config the handle. 
    HANDLE hFile;
    DWORD dwBytesToWrite = (DWORD)strlen(DataBuffer);
    DWORD dwBytesWritten = 0;
    LPCWSTR filePath = L"File.txt";  // File PATH.
    //Create File
    hFile = CreateFileW(
        filePath,
        GENERIC_WRITE,
        FILE_SHARE_READ,
        NULL,
        CREATE_ALWAYS,
        FILE_FLAG_NO_BUFFERING, //Set Flag
        NULL
    );

    if (hFile == INVALID_HANDLE_VALUE) {
        DWORD message = GetLastError();
        DisplayError((LPTSTR)&message);
        CloseHandle(hFile);
        return;
    }

    // Measure the disc.
    HandleConfig fileConf;
    MesureDisk(&fileConf, TRUE);//Display the struct on Terminal.

    // Ensure you have one more sector than WRITE_SIZE would require.
    const size_t sizeNeeded = fileConf.BytesPerSector + ROUND_UP_SIZE(dwBytesToWrite, fileConf.BytesPerSector);


    //Print Current Buffer Adress and offset Constraints for UNBEFFERED IO.
    printf("size needed: %d \r\n", sizeNeeded);

    // Move the current file pointer in Constreined offset (test for control ...neutral modification... or write in the midle of the block).
    printf("Current pointer position A: 0x%X \r\n", SetFilePointer(hFile, 0, 0, FILE_CURRENT));
    if (SetFilePointer(hFile, 0x200, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {//Move 512 bytes forward.
        DWORD message = GetLastError();
        DisplayError((LPTSTR)&message);
        printf("ERROR on Set file pointer...\r\n");
        CloseHandle(hFile);
        return;
    }
    printf("Current pointer position B: 0x%X \r\n", SetFilePointer(hFile, 0, 0, FILE_CURRENT));
//  printf("Current pointer position C (reset at the begening of file): 0x%X \r\n", SetFilePointer(hFile, 0, 0, FILE_BEGIN));

    // Write the file.
    if (!WriteFile(
        hFile,
        DataBuffer,
        sizeNeeded,
        &dwBytesWritten,
        NULL)) {
        DWORD message = GetLastError();
        DisplayError((LPTSTR)&message);
        CloseHandle(hFile);
        return;
    }
    CloseHandle(hFile);
}

int main() {
    Windows_write_UNBEFFERED();
    return EXIT_SUCCESS;
}

void DisplayError(LPTSTR lpszFunction)
// Routine Description:
// Retrieve and output the system error message for the last-error code
{
    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError();

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR)&lpMsgBuf,
        0,
        NULL);

    lpDisplayBuf =
        (LPVOID)LocalAlloc(LMEM_ZEROINIT,
            (lstrlen((LPCTSTR)lpMsgBuf)
                + lstrlen((LPCTSTR)lpszFunction)
                + 40) // account for format string
            * sizeof(TCHAR));

    if (FAILED(StringCchPrintf((LPTSTR)lpDisplayBuf,
        LocalSize(lpDisplayBuf) / sizeof(TCHAR),
        TEXT("%s failed with error code %d as follows:\n%s"),
        lpszFunction,
        dw,
        lpMsgBuf)))
    {
        printf("FATAL ERROR: Unable to output error code.\n");
    }

    _tprintf(TEXT("ERROR: %s\n"), (LPCTSTR)lpDisplayBuf);

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
}
© www.soinside.com 2019 - 2024. All rights reserved.