0

(I'm not native English speaker so sorry for potential mistake :p)

I want to write a Windows tool that can accelerate big files copying just like FastCopy. But get stuck at the very first step: Write data to specific offset of a file via OVERLAPPED (with WriteFile).

Here is my code:

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <Windows.h>
#include <fileapi.h>

LPOVERLAPPED SetupOvl(DWORD OffsetHigh, DWORD Offset) {
    printf("Ovl??: Got Offset %d\n", Offset);
    LPOVERLAPPED Ovl = (LPOVERLAPPED)malloc(sizeof(OVERLAPPED));
    Ovl->Internal = 0;
    Ovl->InternalHigh = 0;
    Ovl->OffsetHigh = OffsetHigh;
    Ovl->Offset = Offset;
    Ovl->Pointer = NULL;
    Ovl->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    return Ovl;
}

int main()
{
    HANDLE hf,hf2;
    void* buffer2 = (void*)malloc(2 << 16);
    void* buffer = (void*)malloc(2 << 16);
    int readed_number = 0, writed_number = 0;
    DWORD written_number = 0;
    DWORD wn1 = 0, wn2 = 0;

    // OpenThread
    DeleteFileW(L"C:\\Users\\Lev\\Downloads\\dst.txt");
    hf = CreateFileW(
        L"C:\\Users\\Lev\\Downloads\\src.txt",
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        0);
    hf2 = CreateFileW(
        L"C:\\Users\\Lev\\Downloads\\dst.txt",
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        CREATE_NEW,
        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
        NULL);

    // ReadThread
    BOOL ret = ReadFile(
        hf,
        buffer,
        2 << 15,
        (LPDWORD)&readed_number,
        NULL
    );

    SetFilePointer(hf2, 16, 0, FILE_BEGIN);
    SetEndOfFile(hf2);

    LPOVERLAPPED Ovl1 = SetupOvl(0, 2);
    WriteFile(hf2, buffer, 6, NULL, Ovl1);

    LPOVERLAPPED Ovl2 = SetupOvl(0, 12);
    buffer = (void*)((char*)buffer + (unsigned int)(10));
    WriteFile(hf2, buffer, 4, NULL, Ovl2);

    ret = GetOverlappedResult(hf2, Ovl1, &wn1, TRUE);
    ret = GetOverlappedResult(hf2, Ovl2, &wn2, TRUE);

    printf("Write_A: Write %d Bytes!\n", wn1);
    printf("Write_B: Write %d Bytes!\n", wn2);

    free(Ovl1);
    free(Ovl2);
    CloseHandle(hf);
    CloseHandle(hf2);

    return 0;
}

Output from console:

Ovl??: Got Offset 2
Ovl??: Got Offset 8
Write_A: Write 4 Bytes!
Write_B: Write 5 Bytes!

Content of src.txt: 1234567890abcdefghijklmn

Content of dst.txt: abcd56 (6 charactors and lots of 0x00)

In the code I try to write "123456" at 3rd byte and "abcd" at 13th byte. But it didn't work. I have look up MSDN and some books but found not code examples I need.

By the way, which is the best way to make a multi-thread acceleration? Multi-thread reading or multi-thread writing? Is it possible to use OVERLAPPED I/O to implement multiple threads writing to the same file in parallel? Or does it just write sequentially?

Any helpful suggestion is appreciated!

  • When programming in C++, whenever you need to use C-style casting (like you do with e.g. `(void*)malloc(2 << 16)`) you should take this as a sign that you're doing something wrong. Especially since that specific cast isn't actually needed in your code. But still, you should use `std::vector` for all kinds of "dynamic arrays", don't do your own explicit manual memory handling. – Some programmer dude Apr 17 '22 at 11:31
  • `Ovl->Pointer = NULL;` this is your error - look how `Pointer` is defined ( inside `union`) – RbMm Apr 17 '22 at 11:43
  • you not close `hEvent` inside `OVERLAPPED` and for synchronous I/O (on `hf` ) it not need. why not both files use asynchronous I/O ? for synchronous not need use `GetOverlappedResult`, .. – RbMm Apr 17 '22 at 11:48
  • @RbMm You're right. I should not initialize the Pointer... Now it works well. Sorry for my stupid question :P It was written this way for debugging purposes. Thank you! – play_as_megumin Apr 17 '22 at 12:09
  • @Someprogrammerdude Thanks for your suggestion. I will improve this later. – play_as_megumin Apr 17 '22 at 12:10
  • asynchronous I/O basically implemented in another way. not need call `GetOverlappedResult` and wait in place - instead need have event driven model - get notification when i/o finished and from here start new I/O. *Multi-thread reading or multi-thread writing*- also wrong. need use multiple I/O requests at once instead multiple threads (it even can be single if you use APC completion). you can start multiple reads I/O - when some this request finished - start write and then new read – RbMm Apr 17 '22 at 12:14
  • I finally make it with APC, thank you! :) – play_as_megumin May 15 '22 at 14:52

0 Answers0