📄 writer.c
字号:
/*-----------------------------------------------------------------------------
This is a part of the Microsoft Source Code Samples.
Copyright (C) 1995 Microsoft Corporation.
All rights reserved.
This source code is only intended as a supplement to
Microsoft Development Tools and/or WinHelp documentation.
See these sources for detailed information regarding the
Microsoft samples programs.
MODULE: Writer.c
PURPOSE: Handles all port writing and write request linked list
FUNCTIONS:
WriterProc - Thread procedure handles all writing
HandleWriteRequests - calls writing procedures based on write request type
WriterTerminate - sets the transfer complete event
WriterFile - Writes a file transfer packet out the port
WriterFileStart - initializes a file transfer
WriterChar - Writes a char out the port
WriterGeneric - Actual writing funciton handles all i/o operations
WriterAddNewNode - Adds new write request packet to linked list
WriterAddNewNodeTimeout - Adds new node, but can timeout.
WriterAddExistingNode - Modifies an existing packet and
links it to the linked list
AddToLinkedList - Adds the node to the list
RemoveFromLinkedList - Removes a node
-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
Write request packets are put into the writer request linked list
and processed by the functions in this module.
The members of the WRITEREQUEST structure are described as follows:
DWORD dwWriteType; // dictates the type of request
DWORD dwSize; // size of data to write
char ch; // character to send
char * lpBuf; // address of data buffer
HANDLE hHeap; // heap containing data buffer
HWND hWndProgress; // hwnd for progress indicator
dwWriteType can be one of the following values:
WRITE_CHAR 0x01 // indicates the request is for sending a single character
WriteRequest.ch contains the character to send
WRITE_FILE 0x02 // indicates the request is for a file transfer
WriteRequest.dwSize : contains the size of the buffer
WriteReqeust.lpBuf : points to the buffer containing the data to send
WriteRequest.hHeap : contains the handle of the heap containing the data buffer
WriteReqeust.hWndProgress : contains the hwnd of the file transfer progress indicator
WRITE_FILESTART 0x03 // indicates the a file transfer is starting
WriteRequest.dwSize : indicates the total size of the file
WRITE_FILEEND 0x04 // indicates the last block in a file transfer
WRITE_ABORT 0x05 // indicates the file transfer is aborted
WRITE_BLOCK 0x06 // indicates the request is for sending
// a block of data
WriteRequest.dwSize : containst the size of the buffer
WriteRequest.lpBuf : points to the buffer containing the data to send
-----------------------------------------------------------------------------*/
#include <windows.h>
#include <commctrl.h>
#include "MTTTY.h"
//
// Prototypes for function called only within this file
//
PWRITEREQUEST RemoveFromLinkedList( PWRITEREQUEST );
BOOL WriterAddExistingNode( PWRITEREQUEST, DWORD, DWORD, char, char *, HANDLE, HWND );
BOOL WriterAddNewNode( DWORD, DWORD, char, char *, HANDLE, HWND );
void HandleWriteRequests( void );
void WriterFileStart( DWORD );
void WriterComplete( void );
void WriterAbort( PWRITEREQUEST );
void AddToLinkedList( PWRITEREQUEST );
void AddToFrontOfLinkedList( PWRITEREQUEST );
void WriterGeneric( char *, DWORD );
void WriterFile( PWRITEREQUEST );
void WriterChar( PWRITEREQUEST );
void WriterBlock( PWRITEREQUEST );
/*-----------------------------------------------------------------------------
FUNCTION: WriterProc(LPVOID)
PURPOSE: Thread function controls console input and comm port writing
HISTORY: Date: Author: Comment:
10/27/95 AllenD Wrote it
-----------------------------------------------------------------------------*/
DWORD WINAPI WriterProc(LPVOID lpV)
{
SYSTEM_INFO sysInfo;
HANDLE hArray[2];
DWORD dwRes;
DWORD dwSize;
BOOL fDone = FALSE;
//
// create a heap for WRITE_REQUEST packets
//
GetSystemInfo(&sysInfo);
ghWriterHeap = HeapCreate(0, sysInfo.dwPageSize*2, sysInfo.dwPageSize*4);
if (ghWriterHeap == NULL)
ErrorInComm("HeapCreate (write request heap)");
//
// create synchronization events for write requests and file transfers
//
ghWriterEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (ghWriterEvent == NULL)
ErrorInComm("CreateEvent(writ request event)");
ghTransferCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (ghTransferCompleteEvent == NULL)
ErrorInComm("CreateEvent(transfer complete event)");
//
// initialize write request linked list
//
dwSize = sizeof(WRITEREQUEST);
gpWriterHead = HeapAlloc(ghWriterHeap, HEAP_ZERO_MEMORY, dwSize);
gpWriterTail = HeapAlloc(ghWriterHeap, HEAP_ZERO_MEMORY, dwSize);
gpWriterHead->pNext = gpWriterTail;
gpWriterTail->pPrev = gpWriterHead;
hArray[0] = ghWriterEvent;
hArray[1] = ghThreadExitEvent;
while ( !fDone ) {
dwRes = WaitForMultipleObjects(2, hArray, FALSE, WRITE_CHECK_TIMEOUT);
switch(dwRes)
{
case WAIT_TIMEOUT:
break;
case WAIT_FAILED:
ErrorReporter("WaitForMultipleObjects( writer proc )");
break;
//
// write request event
//
case WAIT_OBJECT_0:
HandleWriteRequests();
break;
//
// thread exit event
//
case WAIT_OBJECT_0 + 1:
fDone = TRUE;
break;
}
}
CloseHandle(ghTransferCompleteEvent);
CloseHandle(ghWriterEvent);
//
// Destroy WRITE_REQUEST heap
//
HeapDestroy(ghWriterHeap);
return 1;
}
/*-----------------------------------------------------------------------------
FUNCTION: HandleWriteRequests
PURPOSE: Retrieves write request and calls the proper function
depending on the write request type.
HISTORY: Date: Author: Comment:
10/27/95 AllenD Wrote it
5/25/96 AllenD Modified to include
-----------------------------------------------------------------------------*/
void HandleWriteRequests()
{
PWRITEREQUEST pWrite;
BOOL fRes;
pWrite = gpWriterHead->pNext;
while(pWrite != gpWriterTail) {
switch(pWrite->dwWriteType)
{
case WRITE_CHAR: WriterChar(pWrite); break;
case WRITE_FILESTART: WriterFileStart(pWrite->dwSize); break;
case WRITE_FILE: WriterFile(pWrite);
//
// free data block
//
EnterCriticalSection(&gcsDataHeap);
fRes = HeapFree(pWrite->hHeap, 0, pWrite->lpBuf);
LeaveCriticalSection(&gcsDataHeap);
if (!fRes)
ErrorReporter("HeapFree(file transfer buffer)");
break;
case WRITE_FILEEND: WriterComplete(); break;
case WRITE_ABORT: WriterAbort(pWrite); break;
case WRITE_BLOCK: WriterBlock(pWrite); break;
default: ErrorReporter("Bad write request");
break;
}
//
// remove current node and get next node
//
pWrite = RemoveFromLinkedList(pWrite);
pWrite = gpWriterHead->pNext;
}
return;
}
/*-----------------------------------------------------------------------------
FUNCTION: WriterComplete
PURPOSE: Handle an transfer completion
HISTORY: Date: Author: Comment:
1/26/96 AllenD Wrote it
-----------------------------------------------------------------------------*/
void WriterComplete()
{
if (!SetEvent(ghTransferCompleteEvent))
ErrorReporter("SetEvent (transfer complete event)");
return;
}
/*-----------------------------------------------------------------------------
FUNCTION: WriterAbort
PURPOSE: Handle an transfer abort. Delete all writer packets.
Data packets get deleted with the entire data heap in the transfer
thread.
HISTORY: Date: Author: Comment:
1/26/96 AllenD Wrote it
-----------------------------------------------------------------------------*/
void WriterAbort(PWRITEREQUEST pAbortNode)
{
PWRITEREQUEST pCurrent;
PWRITEREQUEST pNextNode;
BOOL fRes;
int i = 0;
char szMessage[30];
EnterCriticalSection(&gcsWriterHeap);
// remove all nodes after me
pCurrent = pAbortNode->pNext;
while (pCurrent != gpWriterTail) {
pNextNode = pCurrent->pNext;
fRes = HeapFree(ghWriterHeap, 0, pCurrent);
if (!fRes)
break;
i++;
pCurrent = pNextNode;
}
pAbortNode->pNext = gpWriterTail;
gpWriterTail->pPrev = pAbortNode;
LeaveCriticalSection(&gcsWriterHeap);
wsprintf(szMessage, "%d packets ignored.\n", i);
OutputDebugString(szMessage);
if (!fRes)
ErrorReporter("HeapFree (Writer heap)");
if (!SetEvent(ghTransferCompleteEvent))
ErrorReporter("SetEvent (transfer complete event)");
return;
}
/*-----------------------------------------------------------------------------
FUNCTION: WriterFile(PWRITEREQUEST)
PURPOSE: Handles a file transfer request
PARAMETERS:
pWrite - pointer to write request packet
COMMENTS: WRITEREQUEST packet contains the following:
lpBuf : Address of data buffer
dwSize : size of data buffer
hWndProgress: hwnd of progress indicator
hHeap : handle to heap which contains the data buffer
HISTORY: Date: Author: Comment:
10/27/95 AllenD Wrote it
-----------------------------------------------------------------------------*/
void WriterFile(PWRITEREQUEST pWrite)
{
WriterGeneric(pWrite->lpBuf, pWrite->dwSize);
//
// update progress indicator (even if aborting)
//
if (!PostMessage(pWrite->hWndProgress, PBM_STEPIT, 0, 0))
ErrorReporter("PostMessage (file transfer status)");
return;
}
/*-----------------------------------------------------------------------------
FUNCTION: WriterBlock(PWRITEREQUEST)
PURPOSE: Sends a block of characters
PARAMETERS:
pWrite - pointer to write request packet
COMMENTS: WRITEREQUEST packet contains the following:
lpBuf : Address of data buffer
dwSize : size of data buffer
HISTORY: Date: Author: Comment:
1/29/96 AllenD Wrote it
-----------------------------------------------------------------------------*/
void WriterBlock(PWRITEREQUEST pWrite)
{
WriterGeneric(pWrite->lpBuf, pWrite->dwSize);
return;
}
/*-----------------------------------------------------------------------------
FUNCTION: WriterFileStart(DWORD)
PURPOSE: Initializes a file transfer (send)
PARAMETER:
dwFileSize - not used
COMMENTS: Provided to do any special initializations for transfer
HISTORY: Date: Author: Comment:
10/27/95 AllenD Wrote it
11/20/95 AllenD Took out all test code
-----------------------------------------------------------------------------*/
void WriterFileStart(DWORD dwFileSize)
{
return;
}
/*-----------------------------------------------------------------------------
FUNCTION: WriterChar(PWRITEREQUEST)
PURPOSE: Handles sending characters
PARAMETER:
pWrite - pointer to write request packet
COMMENTS: WRITEREQUEST packet contains the following:
ch : character to send
HISTORY: Date: Author: Comment:
10/27/95 AllenD Wrote it
-----------------------------------------------------------------------------*/
void WriterChar(PWRITEREQUEST pWrite)
{
WriterGeneric(&(pWrite->ch), 1);
return;
}
/*-----------------------------------------------------------------------------
FUNCTION: WriterGeneric(char *, DWORD)
PURPOSE: Handles sending all types of data
PARAMETER:
lpBuf - pointer to data buffer
dwToWrite - size of buffer
HISTORY: Date: Author: Comment:
10/27/95 AllenD Wrote it
-----------------------------------------------------------------------------*/
void WriterGeneric(char * lpBuf, DWORD dwToWrite)
{
OVERLAPPED osWrite = {0};
HANDLE hArray[2];
DWORD dwWritten;
DWORD dwRes;
//
// If no writing is allowed, then just return
//
if (NOWRITING(TTYInfo))
return ;
//
// create this writes overlapped structure hEvent
//
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -