alertio.c
来自「一本已经绝版的好书」· C语言 代码 · 共 388 行
C
388 行
/************************************************************
Module name: AlertIO.C
Notices: Copyright (c) 1997 Jeffrey Richter
************************************************************/
#include "..\CmnHdr.H" /* See Appendix C. */
#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include "Resource.H"
/////////////////////////////////////////////////////////////
static BOOL PrepareDstFile(LPCTSTR pszFileSrc, LPCTSTR pszFileDst,
PHANDLE phFileSrc, PHANDLE phFileDst,
PULARGE_INTEGER pulFileSize, DWORD dwPageSize) {
ULARGE_INTEGER ulFileSizeDst;
DWORD dwError;
BOOL fOk = FALSE;
__try {
// Open the existing source file for input.
*phFileSrc = CreateFile(pszFileSrc, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL);
if (*phFileSrc == INVALID_HANDLE_VALUE)
__leave;
// Create the new destination file for output.
*phFileDst = CreateFile(pszFileDst, GENERIC_WRITE,
0, NULL, CREATE_ALWAYS,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, *phFileSrc);
if (*phFileDst == INVALID_HANDLE_VALUE)
__leave;
// Get the size of the original file.
pulFileSize->LowPart = GetFileSize(*phFileSrc,
&pulFileSize->HighPart);
// Round up the source file size
// to an even multiple of pages
ulFileSizeDst.QuadPart = (pulFileSize->QuadPart +
dwPageSize - 1) & ~(dwPageSize - 1);
// Force the destination file to the size needed.
dwError = SetFilePointer(*phFileDst, ulFileSizeDst.LowPart,
(PLONG) ulFileSizeDst.HighPart, FILE_BEGIN);
if ((dwError == 0xffffffff) && (GetLastError() != NO_ERROR))
__leave;
if (!SetEndOfFile(*phFileDst))
__leave;
fOk = TRUE; // We did everything successfully
}
__finally {
// If anything failed, clean up entirely
if (!fOk) {
if (*phFileSrc != INVALID_HANDLE_VALUE) {
CloseHandle(*phFileSrc);
*phFileSrc = INVALID_HANDLE_VALUE;
}
if (*phFileSrc != INVALID_HANDLE_VALUE) {
CloseHandle(*phFileDst);
*phFileDst = INVALID_HANDLE_VALUE;
}
}
}
return(fOk);
}
/////////////////////////////////////////////////////////////
static void CopyCleanup(LPCTSTR pszFileDst, HANDLE hFileSrc,
HANDLE hFileDst, PULARGE_INTEGER pulFileSize) {
// Close the source and destination files
CloseHandle(hFileDst);
CloseHandle(hFileSrc);
// We need another handle to the destination file that is
// opened without FILE_FLAG_NO_BUFFERING. This allows us
// to set the end-of-file marker to a position that is not
// sector-aligned.
hFileDst = CreateFile(pszFileDst, GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
if (hFileDst != INVALID_HANDLE_VALUE) {
// Set the destination file's size to the size of the
// source file, in case the size of the source file was
// not a multiple of the page size.
SetFilePointer(hFileDst, pulFileSize->LowPart,
(PLONG) pulFileSize->HighPart, FILE_BEGIN);
SetEndOfFile(hFileDst);
CloseHandle(hFileDst);
}
}
/////////////////////////////////////////////////////////////
typedef struct {
// The page size used on the host machine
DWORD dwPageSize;
// Handles of the source and destination files
HANDLE hFileSrc, hFileDst;
// Size of source file
ULARGE_INTEGER ulFileSize;
// Offset in source file where next read begins
ULARGE_INTEGER ulNextReadOffset;
// The number of pending read & write I/O requests
int nReadsInProgress;
int nWritesInProgress;
} COPYSTATE, *PCOPYSTATE;
COPYSTATE g_cs;
// Each IO requires an OVERLAPPED structure and a buffer.
typedef struct {
OVERLAPPED Overlapped;
PBYTE pbData;
} IOREQ, *PIOREQ;
#define MAX_PENDING_IO_REQS 4
#define BUFFSIZE (64 * 1024)
/////////////////////////////////////////////////////////////
VOID WINAPI WriteCompletionRoutine(DWORD dwErrorCode,
DWORD dwNumberOfBytesTransferred,
LPOVERLAPPED pOverlapped);
/////////////////////////////////////////////////////////////
VOID WINAPI ReadCompletionRoutine(DWORD dwErrorCode,
DWORD dwNumberOfBytesTransferred,
LPOVERLAPPED pOverlapped) {
PIOREQ pIOReq = (PIOREQ) pOverlapped;
chASSERT(dwErrorCode == NO_ERROR);
g_cs.nReadsInProgress--;
// Round up the number of bytes to write
// to a sector boundary.
dwNumberOfBytesTransferred =
(dwNumberOfBytesTransferred + g_cs.dwPageSize - 1) &
~(g_cs.dwPageSize - 1);
chVERIFY(WriteFileEx(g_cs.hFileDst, pIOReq->pbData,
dwNumberOfBytesTransferred, pOverlapped,
WriteCompletionRoutine));
g_cs.nWritesInProgress++;
}
/////////////////////////////////////////////////////////////
VOID WINAPI WriteCompletionRoutine(DWORD dwErrorCode,
DWORD dwNumberOfBytesTransferred,
LPOVERLAPPED pOverlapped) {
PIOREQ pIOReq = (PIOREQ) pOverlapped;
chASSERT(dwErrorCode == NO_ERROR);
g_cs.nWritesInProgress--;
if (g_cs.ulNextReadOffset.QuadPart < g_cs.ulFileSize.QuadPart) {
// We haven't read past the end of the file yet.
// Read the next chunk of data.
pOverlapped->Offset = g_cs.ulNextReadOffset.LowPart;
pOverlapped->OffsetHigh = g_cs.ulNextReadOffset.HighPart;
chVERIFY(ReadFileEx(g_cs.hFileSrc, pIOReq->pbData,
BUFFSIZE, pOverlapped, ReadCompletionRoutine));
g_cs.nReadsInProgress++;
// Offset in source file where next read begins.
g_cs.ulNextReadOffset.QuadPart += BUFFSIZE;
}
}
/////////////////////////////////////////////////////////////
BOOL FileCopy (LPCTSTR pszFileSrc, LPCTSTR pszFileDst) {
// Maintain info about each IO request.
IOREQ IOReq[MAX_PENDING_IO_REQS] = { 0 };
SYSTEM_INFO si;
int nIOReq;
BOOL fOk;
// Initialize the global COPYSTATE variable.
GetSystemInfo(&si);
g_cs.dwPageSize = si.dwPageSize;
g_cs.ulNextReadOffset.QuadPart = 0;
g_cs.nReadsInProgress = 0;
g_cs.nWritesInProgress = 0;
// Open the existing source file for input.
fOk = PrepareDstFile(pszFileSrc, pszFileDst,
&g_cs.hFileSrc, &g_cs.hFileDst,
&g_cs.ulFileSize, g_cs.dwPageSize);
if (!fOk)
return(fOk);
// Start the copy engine by posting a number of read
// IO requests against the source file.
for (nIOReq = 0; nIOReq < MAX_PENDING_IO_REQS; nIOReq++) {
IOReq[nIOReq].Overlapped.Internal = 0;
IOReq[nIOReq].Overlapped.InternalHigh = 0;
IOReq[nIOReq].Overlapped.Offset =
g_cs.ulNextReadOffset.LowPart;
IOReq[nIOReq].Overlapped.OffsetHigh =
g_cs.ulNextReadOffset.HighPart;
IOReq[nIOReq].Overlapped.hEvent = NULL;
IOReq[nIOReq].pbData = VirtualAlloc(NULL,
BUFFSIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (g_cs.ulNextReadOffset.QuadPart <
g_cs.ulFileSize.QuadPart) {
chVERIFY(ReadFileEx(g_cs.hFileSrc,
IOReq[nIOReq].pbData, BUFFSIZE,
&IOReq[nIOReq].Overlapped,
ReadCompletionRoutine));
g_cs.nReadsInProgress++;
g_cs.ulNextReadOffset.QuadPart += BUFFSIZE;
}
}
// Loop until an error has occurred or until the
// destination file has been written.
while ((g_cs.nReadsInProgress > 0) ||
(g_cs.nWritesInProgress > 0)) {
SleepEx(INFINITE, TRUE);
}
// Free the memory buffers used for the copy.
for (nIOReq = 0; nIOReq < MAX_PENDING_IO_REQS; nIOReq++) {
VirtualFree(IOReq[nIOReq].pbData, 0, MEM_RELEASE);
}
// Close the source and destination files; force the
// destination file to be the same size as the source.
CopyCleanup(pszFileDst, g_cs.hFileSrc,
g_cs.hFileDst, &g_cs.ulFileSize);
return(TRUE);
}
/////////////////////////////////////////////////////////////
BOOL Dlg_OnInitDialog (HWND hwnd, HWND hwndFocus,
LPARAM lParam) {
// Associate an icon with the dialog box.
chSETDLGICONS(hwnd, IDI_ALERTIO, IDI_ALERTIO);
// Disable the "Copy" button because no file
// has been selected yet.
EnableWindow(GetDlgItem(hwnd, IDOK), FALSE);
return(TRUE);
}
/////////////////////////////////////////////////////////////
void Dlg_OnCommand (HWND hwnd, int id,
HWND hwndCtl, UINT codeNotify) {
TCHAR szPathname[_MAX_DIR];
BOOL fOk;
OPENFILENAME ofn;
switch (id) {
case IDOK:
// Copy the source file to the destination file.
Static_GetText(GetDlgItem(hwnd, IDC_SRCFILE),
szPathname, sizeof(szPathname));
SetCursor(LoadCursor(NULL, IDC_WAIT));
FileCopy(szPathname, __TEXT("AlertIO.CPY"));
break;
case IDC_BROWSE:
chINITSTRUCT(ofn, TRUE);
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = __TEXT("*.*\0");
_tcscpy(szPathname, __TEXT("*.*"));
ofn.lpstrFile = szPathname;
ofn.nMaxFile = sizeof(szPathname);
ofn.Flags = OFN_FILEMUSTEXIST;
fOk = GetOpenFileName(&ofn);
if (fOk) {
HANDLE hFile;
Static_SetText(GetDlgItem(hwnd, IDC_SRCFILE),
szPathname);
hFile = CreateFile(szPathname, GENERIC_READ,
0, NULL, OPEN_EXISTING, 0, NULL);
SetDlgItemInt(hwnd, IDC_SRCFILESIZE,
GetFileSize(hFile, NULL), FALSE);
CloseHandle(hFile);
}
// Enable the "Copy" button if the user selected
// a valid pathname.
GetWindowText(GetDlgItem(hwnd, IDC_SRCFILE),
szPathname, sizeof(szPathname));
EnableWindow(GetDlgItem(hwnd, IDOK),
szPathname[0] != __TEXT('('));
if (fOk) {
// If the user pressed the OK button in the file
// dialog box, change focus to the "Copy" button.
FORWARD_WM_NEXTDLGCTL(hwnd,
GetDlgItem(hwnd, IDOK), TRUE, SendMessage);
}
break;
case IDCANCEL:
EndDialog(hwnd, id);
break;
}
}
/////////////////////////////////////////////////////////////
BOOL CALLBACK Dlg_Proc (HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
}
return(FALSE);
}
/////////////////////////////////////////////////////////////
int WINAPI _tWinMain (HINSTANCE hinstExe,
HINSTANCE hinstPrev, LPTSTR pszCmdLine, int nCmdShow) {
chWARNIFUNICODEUNDERWIN95();
DialogBox(hinstExe, MAKEINTRESOURCE(IDD_ALERTIO),
NULL, Dlg_Proc);
return(0);
}
//////////////////////// End Of File ////////////////////////
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?