📄 transfer.c
字号:
}
/*-----------------------------------------------------------------------------
FUNCTION: OpenTheFile(LPCTSTR)
PURPOSE: Open a file and return the file handle
PARAMETERS:
lpFName - name of file to open
HISTORY: Date: Author: Comment:
10/27/95 AllenD Wrote it
-----------------------------------------------------------------------------*/
HANDLE OpenTheFile(LPCTSTR lpFName)
{
HANDLE hTemp;
hTemp = CreateFile(lpFName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0,NULL);
if (hTemp == INVALID_HANDLE_VALUE)
ErrorReporter("CreateFile");
return hTemp;
}
/*-----------------------------------------------------------------------------
FUNCTION: CreateTheFile(LPCTSTR)
PURPOSE: Creates a file and returns the file handle
PARAMETERS:
lpFName - name of file to create
HISTORY: Date: Author: Comment:
10/27/95 AllenD Wrote it
-----------------------------------------------------------------------------*/
HANDLE CreateTheFile(LPCTSTR lpFName)
{
HANDLE hTemp;
hTemp = CreateFile(lpFName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0,NULL);
if (hTemp == INVALID_HANDLE_VALUE)
ErrorReporter("CreateFile");
return hTemp;
}
/*-----------------------------------------------------------------------------
FUNCTION: GetTransferSizes(HANDLE, DWORD *, DWORD *, DWORD *)
PURPOSE: Examines file and determines packet size, number of packets,
and file size.
PARAMETERS:
hFile - handle of file to get size information from
pdwDataPacketSize - size of an individual data packet
pdwNumPackets - total number of packets
pdwFileSize - size of file
RETURN:
TRUE - all metrics could be determined
FALSE - something wrong with the file metrics, can't transfer
COMMENTS:
This module can't handle files that are extremely large, so
it may return FALSE if a large file is specified.
HISTORY: Date: Author: Comment:
10/27/95 AllenD Wrote it
-----------------------------------------------------------------------------*/
BOOL GetTransferSizes(HANDLE hFile, DWORD * pdwDataPacketSize, DWORD * pdwNumPackets, DWORD * pdwFileSize)
{
BY_HANDLE_FILE_INFORMATION fi;
if (!GetFileInformationByHandle(hFile, &fi)) {
ErrorReporter("GetFileInformationByHandle");
return FALSE;
}
else {
if (fi.nFileSizeHigh) {
MessageBox(ghwndMain, "File is too large to transfer.", "File Transfer Error", MB_OK);
return FALSE;
}
//
// setup packet size, file size and compute the number of packets
//
*pdwDataPacketSize = MAX_WRITE_BUFFER;
*pdwFileSize = fi.nFileSizeLow;
*pdwNumPackets = *pdwFileSize / *pdwDataPacketSize;
if (*pdwNumPackets > 65534) {
MessageBox(ghwndMain, "File is too large for buffer size.", "File Transfer Error", MB_OK);
return FALSE;
}
}
return TRUE;
}
/*-----------------------------------------------------------------------------
FUNCTION: ShowTransferStatistics(DWORD, DWORD, DWORD)
PURPOSE: Displays bytes transferred and bytes per second
PARAMETERS:
dwEnd - ending time in milliseconds
dwStart - starting time
dwBytesTransferred - bytes sent
HISTORY: Date: Author: Comment:
10/27/95 AllenD Wrote it
-----------------------------------------------------------------------------*/
void ShowTransferStatistics(DWORD dwEnd, DWORD dwStart, DWORD dwBytesTransferred)
{
char szTemp[100];
DWORD dwSecs;
dwSecs = (dwEnd - dwStart) / 1000;
//
// display only if dwSecs != 0; if dwSecs == 0, then divide by zero occurs.
//
if (dwSecs != 0) {
wsprintf(szTemp, "Bytes transferred: %d\r\nBytes/Second: %d\r\n", dwBytesTransferred, dwBytesTransferred / dwSecs);
UpdateStatus(szTemp);
}
return;
}
/*-----------------------------------------------------------------------------
FUNCTION: CheckForMessages
PURPOSE: Check for a message and dispatch it.
RETURN:
If the WM_CLOSE message or the WM_SYSCOMMAND (SC_CLOSE) is
retrieved, WM_CLOSE is posted, and WM_CLOSEQUIT is
returned by the function. This allows the caller
to detect this as an abort condition and exit properly. When
the caller exits, the main message loop in the WinMain function
should be entered again and the WM_CLOSE message will be
handled properly.
If there is a message other than those above, it is dispatched
and TRUE is returned indicating that a message was dispatched.
If no message is found, FALSE is returned.
HISTORY: Date: Author: Comment:
10/27/95 AllenD Wrote it
-----------------------------------------------------------------------------*/
UINT CheckForMessages()
{
MSG msg;
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_CLOSE) {
PostMessage(ghwndMain, WM_CLOSE, 0, 0);
return WM_CLOSE;
}
if (msg.message == WM_SYSCOMMAND && msg.wParam == SC_CLOSE) {
PostMessage(ghwndMain, WM_CLOSE, 0, 0);
return WM_CLOSE;
}
if (!TranslateAccelerator( ghwndMain, ghAccel, &msg )) {
TranslateMessage( &msg ) ;
DispatchMessage( &msg ) ;
}
return TRUE ;
}
return FALSE ;
}
/*-----------------------------------------------------------------------------
FUNCTION: CaptureFile(HANDLE, HWND)
PURPOSE: Receives a file
PARAMETERS:
hFile - handle of file to receive the data being captured (not used)
hWndProgress - window handle of progress bar (not used)
COMMENTS: Sets the receive state and waits for capture to end
HISTORY: Date: Author: Comment:
10/27/95 AllenD Wrote it
-----------------------------------------------------------------------------*/
void CaptureFile(HANDLE hFile, HWND hWndProgress)
{
UINT uMsgResult;
gdwReceiveState = RECEIVE_CAPTURED;
while ( !gfAbortTransfer ) {
uMsgResult = CheckForMessages();
//
// If WM_CLOSE is retrieved, then exit.
// If no message is retrieved, then sleep a little.
// If any other message is retrieved, check for another one.
//
switch(uMsgResult)
{
case WM_CLOSE: gfAbortTransfer = TRUE; break;
case FALSE: Sleep(200); break;
case TRUE: break;
}
}
gdwReceiveState = RECEIVE_TTY;
return;
}
/*-----------------------------------------------------------------------------
FUNCTION: TransferThreadProc(LPVOID)
PURPOSE: Worker thread does all the file transfer work
PARAMETERS:
lpV - actually a HANDLE for the file
COMMENTS: Function allows the hTransferAbortEvent to
signal an abort condition.
If the thread finishes OK, then the thread
calls the TransferFileTextEnd function itself.
HISTORY: Date: Author: Comment:
1/26/96 AllenD Wrote it
-----------------------------------------------------------------------------*/
DWORD WINAPI TransferThreadProc(LPVOID lpV)
{
DWORD dwPacketSize, dwMaxPackets, dwFileSize;
DWORD dwStartTime;
HWND hWndProgress;
HANDLE hFileHandle;
HANDLE hDataHeap;
BOOL fStarted = TRUE;
BOOL fAborting = FALSE;
hFileHandle = (HANDLE) lpV;
hWndProgress = GetDlgItem(ghWndStatusDlg, IDC_TRANSFERPROGRESS);
// set up transfer metrics
if (!GetTransferSizes(hFileHandle, &dwPacketSize, &dwMaxPackets, &dwFileSize))
fAborting = TRUE;
else {
SendMessage(hWndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, dwMaxPackets+1));
SendMessage(hWndProgress, PBM_SETSTEP, (WPARAM) 1, 0);
SendMessage(hWndProgress, PBM_SETPOS, 0, 0);
}
// set up transfer heaps
if (!fAborting) {
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
hDataHeap = HeapCreate(0, sysInfo.dwPageSize * 2, sysInfo.dwPageSize * 10);
if (hDataHeap == NULL) {
ErrorReporter("HeapCreate (Data Heap)");
fAborting = TRUE;
}
}
// inform writer thread that a file is about to be transferred
if (!fAborting) {
if (!WriterAddNewNode(WRITE_FILESTART, dwFileSize, 0, NULL, NULL, NULL))
fAborting = TRUE;
}
OutputDebugString("Xfer: About to start sending data\n");
// Get Transfer Start Time
dwStartTime = GetTickCount();
if (WaitForSingleObject(hTransferAbortEvent, 0) == WAIT_OBJECT_0)
fAborting = TRUE;
while (!fAborting) {
char * lpDataBuf;
PWRITEREQUEST pWrite;
// transfer file, loop until all blocks of file have been read
lpDataBuf = HeapAlloc(hDataHeap, 0, dwPacketSize);
pWrite = HeapAlloc(ghWriterHeap, 0, sizeof(WRITEREQUEST));
if ((lpDataBuf != NULL) && (pWrite != NULL)) {
DWORD dwRead;
// read from file into new buffer
if (ReadFile(hFileHandle, lpDataBuf, dwPacketSize, &dwRead, NULL)) {
WriterAddExistingNode(pWrite, WRITE_FILE, dwRead, 0, lpDataBuf, hDataHeap, hWndProgress);
if (dwRead != dwPacketSize) // eof
break;
}
}
else {
BOOL fRes;
/*
Either the data heap is full, or the writer heap is full.
Free any allocated block, wait a little and try again.
Waiting lets the writer thread send some blocks and free
the data blocks from the data heap and the control
blocks from the writer heap.
*/
if (lpDataBuf) {
EnterCriticalSection(&gcsDataHeap);
fRes = HeapFree(hDataHeap, 0, lpDataBuf);
LeaveCriticalSection(&gcsDataHeap);
if (!fRes)
ErrorReporter("HeapFree (Data block)");
}
if (pWrite) {
EnterCriticalSection(&gcsWriterHeap);
fRes = HeapFree(ghWriterHeap, 0, pWrite);
LeaveCriticalSection(&gcsWriterHeap);
if (!fRes)
ErrorReporter("HeapFree (Writer block)");
}
OutputDebugString("Xfer: A heap is full. Waiting...\n");
// wait a little
// check for abort during the wait
if (WaitForSingleObject(hTransferAbortEvent, 200) == WAIT_OBJECT_0)
fAborting = TRUE;
}
// has the user aborted?
if (WaitForSingleObject(hTransferAbortEvent, 0) == WAIT_OBJECT_0)
fAborting = TRUE;
}
OutputDebugString("Xfer: Done sending packets.\n");
if (fAborting) {
// inform writer that transfer is aborting
OutputDebugString("Xfer: Sending Abort Packet to writer\n");
WriterAddFirstNodeTimeout(WRITE_ABORT, dwFileSize, 0, NULL, NULL, NULL, 500);
}
else
WriterAddNewNodeTimeout(WRITE_FILEEND, dwFileSize, 0, NULL, NULL, NULL, 500);
{
// wait til writer thread finishes with all blocks
HANDLE hEvents[2];
DWORD dwRes;
BOOL fTransferComplete;
hEvents[0] = ghTransferCompleteEvent;
hEvents[1] = hTransferAbortEvent;
OutputDebugString("Xfer: Waiting for transfer complete signal from writer\n");
do {
ResetEvent(hTransferAbortEvent);
dwRes = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
switch(dwRes) {
case WAIT_OBJECT_0:
fTransferComplete = TRUE;
OutputDebugString("Transfer complete signal rec'd\n");
break;
case WAIT_OBJECT_0 + 1:
fAborting = TRUE;
OutputDebugString("Transfer abort signal rec'd\n");
OutputDebugString("Xfer: Sending Abort Packet to writer\n");
if (!WriterAddFirstNodeTimeout(WRITE_ABORT, dwFileSize, 0, NULL, NULL, NULL, 500))
ErrorReporter("Can't add abort packet\n");
break;
case WAIT_TIMEOUT: break;
default:
ErrorReporter("WaitForMultipleObjects(Transfer Complete Event and Transfer Abort Event)");
fTransferComplete = TRUE;
break;
}
} while (!fTransferComplete);
}
OutputDebugString("Xfer: transfer complete\n");
// report statistics
if (!fAborting)
ShowTransferStatistics(GetTickCount(), dwStartTime, dwFileSize);
// break down metrics
PostMessage(hWndProgress, PBM_SETPOS, 0, 0);
// break down heaps
if (hDataHeap != NULL) {
if (!HeapDestroy(hDataHeap))
ErrorReporter("HeapDestroy (data heap)");
}
// If I am done without user intervention, then post the
// "abort" message myself. This will cause the main thread to
// clean up after the file transfer.
if (!fAborting)
PostMessage(ghwndMain, WM_COMMAND, ID_TRANSFER_ABORTSENDING, 0);
// exit thread
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -