主题:使用ReadFileEx和WriteFileEx实现复制文件的功能。
1.GetThreadIOPendingFlag:这个函数的功能是检查线程还有没有未完成的IO在底层等待处理,这个等待处理和APC队列中是否还有未处理的项是没有关系的。
下面是我的理解:当这个函数返回值说明没有IO处于pending状态时,表明所有文件的读取操作驱动程序都完成且都投递了对应的APC项到所在线程。
2.只要APC开始执行,可定会将队列清空才回让等待函数返回。
// test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <assert.h>
struct XOVERLAPPED:OVERLAPPED
{
BYTE* pBuf;
HANDLE hFile;
XOVERLAPPED()
{
pBuf = new BYTE[bufsize];
assert(pBuf);
this->OffsetHigh = 0;
count++;
}
~XOVERLAPPED()
{
delete []pBuf;
count--;
}
static const int bufsize = 1024*1024*4;
static int count;
static int max_count;
};
int XOVERLAPPED::count = 0;
int XOVERLAPPED::max_count = 50;
VOID __stdcall WriteCompl(
__in DWORD dwErrorCode,
__in DWORD dwNumberOfBytesTransfered,
__inout LPOVERLAPPED lpOverlapped
)
{
if(dwErrorCode != ERROR_SUCCESS){
printf("Write Error APC\n");
}
delete static_cast<XOVERLAPPED*>(lpOverlapped);
}
VOID __stdcall ReadCompl(
__in DWORD dwErrorCode,
__in DWORD dwNumberOfBytesTransfered,
__inout LPOVERLAPPED lpOverlapped
)
{
if(dwErrorCode != ERROR_SUCCESS){
printf("error\n");
return;
}
XOVERLAPPED* plapped = static_cast<XOVERLAPPED*>(lpOverlapped);
BOOL ret = WriteFileEx(plapped->hFile, plapped->pBuf, dwNumberOfBytesTransfered, lpOverlapped, WriteCompl);
if(ret != 0)
return;
else{
printf("WriteFileEx Error\n");
return;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hr = ::CreateFile(L"xx.ISO", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
HANDLE hw = ::CreateFile(L"b.dll", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
LARGE_INTEGER file_size = {0};
BOOL ret;
ret = SetFilePointerEx(hr, file_size, &file_size, FILE_END);
ret = SetFilePointerEx(hw, file_size, NULL, FILE_BEGIN);
XOVERLAPPED* plapped;
DWORD i;
SYSTEMTIME time_start, time_end;
GetSystemTime(&time_start);
for(i = 0; i < file_size.LowPart; i+=plapped->bufsize){
plapped = new XOVERLAPPED;
plapped->hFile = hw;
plapped->Offset = i;
ret = ReadFileEx(hr, plapped->pBuf, plapped->bufsize, plapped, ReadCompl);
if(ret == 0)
printf("error read\n");
if(plapped->count == plapped->max_count){
SleepEx(0, TRUE);//for execute APC
}
}
//下面这个循环式为了判断IO是否全都完成,睡眠0秒的作用是为了去调用apc的
while(true){
BOOL ret1 = GetThreadIOPendingFlag(GetCurrentThread(), &ret);
if(ret1 != 0){
if(ret == TRUE)
SleepEx(0, TRUE);
else{
SleepEx(0, TRUE);
break;
}
}
}
CloseHandle(hr);
CloseHandle(hw);
GetSystemTime(&time_end);
int minute, second;
minute = time_end.wMinute - time_start.wMinute;
if(time_end.wSecond >= time_start.wSecond)
second = time_end.wSecond - time_start.wSecond;
else{
second = time_end.wSecond - time_start.wSecond + 60;
minute--;
}
printf("%d:%d",minute, second);
}