/*------------------------------------------------------------------------------ -- FUNCTION: PortIOThreadProc -- -- DATE: Oct 13, 2010 -- -- REVISIONS: Nov 05, 2010 -- Modified the function to also listen for a "disconnect" event, -- and to break in that case. ProcessRead() is now called once a -- complete packet is confirmed (as opposed to sending the -- contents of the buffer to ProcessRead() as soon as they arrive). -- -- Nov 29, 2010 -- Renamed function from ReadThreadProc(). The event handling is -- from the original function, but the response to each event has -- changed. -- -- DESIGNER: Dean Morin -- -- PROGRAMMER: Dean Morin, Daniel Wright -- -- INTERFACE: DWORD WINAPI PortIOThreadProc(HWND hWnd) -- hWnd - the handle to the window -- -- RETURNS: 0 because threads are required to return a DWORD. -- -- NOTES: -- While connected, this thread will loop and wait for characters -- to arrive at the port, or for a timeout to occur, then call the -- appropriate function. This function uses overlapped I/O. ------------------------------------------------------------------------------*/ DWORD WINAPI PortIOThreadProc(HWND hWnd) { OVERLAPPED ol = {0}; DWORD dwEvent = 0; DWORD dwError = 0; COMSTAT cs = {0}; HANDLE* hEvents = NULL; PSTATEINFO psi = NULL; PWNDDATA pwd = (PWNDDATA) GetWindowLongPtr(hWnd, 0); if ((ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) { DISPLAY_ERROR("Error creating event in read thread"); } hEvents = (HANDLE*) malloc(sizeof(HANDLE) * PORT_IO_EVENTS); hEvents[0] = CreateEvent(NULL, FALSE, FALSE, TEXT("disconnected")); hEvents[1] = ol.hEvent; psi = (PSTATEINFO) malloc(sizeof(STATEINFO)); InitStateInfo(psi); DL_STATE = psi->iState; while (pwd->bConnected) { SetCommMask(pwd->hPort, EV_RXCHAR); if (!WaitCommEvent(pwd->hPort, &dwEvent, &ol)) { ProcessCommError(pwd->hPort); } dwEvent = WaitForMultipleObjects(PORT_IO_EVENTS, hEvents, FALSE, psi->dwTimeout); ClearCommError(pwd->hPort, &dwError, &cs); if (dwEvent == WAIT_OBJECT_0) { // the connection was severed break; } else if (dwEvent == WAIT_OBJECT_0 + 1 && cs.cbInQue) { // data arrived at the port ReadFromPort(hWnd, psi, ol, cs.cbInQue); } else if (dwEvent == WAIT_TIMEOUT) { // a timeout occured ProcessTimeout(hWnd, psi); } else if (dwEvent == WAIT_FAILED) { DISPLAY_ERROR("Invalid event occured in the Port I/O thread"); } ResetEvent(ol.hEvent); } if (!PurgeComm(pwd->hPort, PURGE_RXCLEAR)) { DISPLAY_ERROR("Error purging read buffer"); } CloseHandle(ol.hEvent); CloseHandle(hEvents[0]); free(hEvents); return 0; }
/*------------------------------------------------------------------------------ -- FUNCTION: CreateFrame -- -- DATE: Nov 24, 2010 -- -- REVISIONS: -- -- DESIGNER: Ian Lee -- -- PROGRAMMER: Ian Lee -- -- INTERFACE: CreateFrame(HWND hWnd, PBYTE psBuf, DWORD dwLength) -- hWnd - a handle to the window -- PBYTE psBuf - data from file -- DWORD dwLength - length of data from file -- -- RETURNS: FRAME - the created frame -- -- NOTES: Creates a frame to be put into the FTP buffer -- ------------------------------------------------------------------------------*/ FRAME CreateFrame(HWND hWnd, PBYTE psBuf, DWORD dwLength){ DWORD i; FRAME myFrame; PWNDDATA pwd = NULL; pwd = (PWNDDATA) GetWindowLongPtr(hWnd, 0); myFrame.soh = 0x1; myFrame.sequence = pwd->TxSequenceNumber; pwd->TxSequenceNumber= (pwd->TxSequenceNumber==0)?1:0; myFrame.length = (SHORT)dwLength; for (i = 0; i<dwLength;i++) { myFrame.payload[i] = *(psBuf++); } while(i<MAX_PAYLOAD_SIZE){ myFrame.payload[i++] =0; } myFrame.crc =0; myFrame.crc = crcFast((PBYTE)&myFrame,FRAME_SIZE - sizeof(crc)); if(crcFast((PBYTE)&myFrame,FRAME_SIZE)!=0){ DISPLAY_ERROR("Failure Creating Frame"); } return myFrame; }
/*------------------------------------------------------------------------------ -- FUNCTION: WriteToFile -- -- DATE: Dec 2, 2010 -- -- REVISIONS: -- -- DESIGNER: Daniel Wright -- -- PROGRAMMER: Daniel Wright -- -- INTERFACE: WriteToFile(HWND hWnd) -- hWnd - a handle to the window -- -- RETURNS: VOID. -- -- NOTES: Removes frames from the Port to File Queue and writes them -- to the receive file until the queue is empty. ------------------------------------------------------------------------------*/ VOID WriteToFile(HWND hWnd){ PWNDDATA pwd = {0}; DWORD dwBytesWritten = 0; PFRAME tempFrame = {0}; HANDLE hMutex = {0}; pwd = (PWNDDATA)GetWindowLongPtr(hWnd, 0); while(pwd->PTFQueueSize != 0){ hMutex = CreateMutex(NULL, FALSE, TEXT("PTFMutex")); WaitForSingleObject(hMutex,INFINITE); tempFrame = RemoveFromFrameQueue(&pwd->PTFBuffHead, 1); ReleaseMutex(hMutex); if(tempFrame->length != 0){ DisplayFrameInfo(hWnd, *tempFrame); pwd->NumOfFrames++; SetWindowLongPtr(hWnd, 0, (LONG_PTR) pwd); } if(!WriteFile(pwd->hFileReceive, tempFrame->payload, tempFrame->length, &dwBytesWritten, NULL)){ DISPLAY_ERROR("Failed to write to file"); } else { pwd->PTFQueueSize--; } if(tempFrame->length != MAX_PAYLOAD_SIZE ){ CloseFileReceive(hWnd); MessageBox(hWnd, TEXT("Finished receiving file"), TEXT("Transfer Complete"), MB_OK); } } }
/*------------------------------------------------------------------------------ -- FUNCTION: CloseFileReceive -- -- DATE: Dec 2, 2010 -- -- REVISIONS: -- -- DESIGNER: Daniel Wright -- -- PROGRAMMER: Daniel Wright -- -- INTERFACE: CloseFileReceive(HWND hWnd) -- hWnd - a handle to the window -- -- RETURNS: VOID. -- -- NOTES: Closes the handle to the receive file and sets it to null. ------------------------------------------------------------------------------*/ VOID CloseFileReceive(HWND hWnd){ PWNDDATA pwd = {0}; pwd = (PWNDDATA)GetWindowLongPtr(hWnd, 0); if(pwd->hFileReceive){ if(!CloseHandle(pwd->hFileReceive)){ DISPLAY_ERROR("Failed to close Receive File"); } pwd->hFileReceive = NULL; } }
/*------------------------------------------------------------------------------ -- FUNCTION: CloseFileTransmit -- -- DATE: Dec 2, 2010 -- -- REVISIONS: -- -- DESIGNER: Daniel Wright -- -- PROGRAMMER: Daniel Wright -- -- INTERFACE: CloseFileTransmit(HWND hWnd) -- hWnd - a handle to the window -- -- RETURNS: VOID. -- -- NOTES: Closes the file handle to the file to be transmitted -- and sets it to null. Sends message to fill File to Port -- Buffer. ------------------------------------------------------------------------------*/ VOID CloseFileTransmit(HWND hWnd){ PWNDDATA pwd = {0}; pwd = (PWNDDATA)GetWindowLongPtr(hWnd, 0); if(pwd->hFileTransmit != NULL){ if(!CloseHandle(pwd->hFileTransmit)){ DISPLAY_ERROR("Failed to close Transmit File"); } pwd->hFileTransmit = NULL; pwd->NumOfReads = 0; } }
/*------------------------------------------------------------------------------ -- FUNCTION: ReadFromFile -- -- DATE: Dec 2, 2010 -- -- REVISIONS: -- -- DESIGNER: Daniel Wright -- -- PROGRAMMER: Daniel Wright -- -- INTERFACE: ReadFromFile(HWND hWnd) -- hWnd - a handle to the window -- -- RETURNS: VOID. -- -- NOTES: While the File to Port queue is not full, reads in increments -- of 1019 bytes from the file to be transmitted, calls CreateFrame -- to frame them and adds them to the File to Port queue. ------------------------------------------------------------------------------*/ VOID ReadFromFile(HWND hWnd){ PWNDDATA pwd = {0}; DWORD dwBytesRead = 0; DWORD dwBytesWritten = 0; DWORD dwSizeOfFile = 0; BOOL eof = FALSE; FRAME frame; HANDLE hMutex = {0}; int i; PBYTE ReadBuffer = (PBYTE) malloc(sizeof(BYTE) *1019); pwd = (PWNDDATA)GetWindowLongPtr(hWnd, 0); if (!(dwSizeOfFile = GetFileSize(pwd->hFileTransmit, NULL))) { return; } while(pwd->FTPQueueSize < FULL_BUFFER && pwd->hFileTransmit != NULL){ if((i =dwSizeOfFile - ((pwd->NumOfReads) * 1019)) > 0){ if(!ReadFile(pwd->hFileTransmit, ReadBuffer, 1019, &dwBytesRead, NULL)){ DISPLAY_ERROR("Failed to read from file"); } ++pwd->NumOfReads; frame = CreateFrame(hWnd, ReadBuffer, dwBytesRead); } else if((dwSizeOfFile - ((pwd->NumOfReads) * 1019)) == 0){ CloseFileTransmit(hWnd); ++pwd->NumOfReads; frame = CreateNullFrame(hWnd); MessageBox(hWnd, TEXT("Transmit File Buffering Complete"), TEXT("File Read Complete"), MB_OK); } else { CloseFileTransmit(hWnd); MessageBox(hWnd, TEXT("Transmit File Buffering Complete"), TEXT("File Read Complete"), MB_OK); return; } hMutex = CreateMutex(NULL, FALSE, TEXT("FTPMutex")); WaitForSingleObject(hMutex,INFINITE); AddToFrameQueue(&pwd->FTPBuffHead, &pwd->FTPBuffTail, frame); pwd->FTPQueueSize+=1; ReleaseMutex(hMutex); } }
/* Initiate or continue SSL handshaking with the peer. This routine does not block. Return -1 on errors, 0 incomplete and awaiting I/O, 1 if successful */ static int nanoHandshake(Webs *wp) { Nano *np; ubyte4 flags; int rc; np = (Nano*) wp->ssl; wp->flags |= SOCKET_HANDSHAKING; SSL_getSessionFlags(np->handle, &flags); if (ME_GOAHEAD_VERIFY_PEER) { flags |= SSL_FLAG_REQUIRE_MUTUAL_AUTH; } else { flags |= SSL_FLAG_NO_MUTUAL_AUTH_REQUEST; } SSL_setSessionFlags(np->handle, flags); rc = 0; while (!np->connected) { if ((rc = SSL_negotiateConnection(np->handle)) < 0) { break; } np->connected = 1; break; } wp->flags &= ~SOCKET_HANDSHAKING; /* Analyze the handshake result */ if (rc < 0) { if (rc == ERR_SSL_UNKNOWN_CERTIFICATE_AUTHORITY) { logmsg(3, "Unknown certificate authority"); /* Common name mismatch, cert revoked */ } else if (rc == ERR_SSL_PROTOCOL_PROCESS_CERTIFICATE) { logmsg(3, "Bad certificate"); } else if (rc == ERR_SSL_NO_SELF_SIGNED_CERTIFICATES) { logmsg(3, "Self-signed certificate"); } else if (rc == ERR_SSL_CERT_VALIDATION_FAILED) { logmsg(3, "Certificate does not validate"); } DISPLAY_ERROR(0, rc); logmsg(4, "NanoSSL: Cannot handshake: error %d", rc); errno = EPROTO; return -1; } return 1; }
/*------------------------------------------------------------------------------ -- FUNCTION: InitRfid -- -- DATE: Nov 6, 2010 -- -- REVISIONS: (Date and Description) -- -- DESIGNER: Daniel Wright -- -- PROGRAMMER: Daniel Wright -- -- INTERFACE: VOID InitRfid(HWND hWnd) -- hWnd - the handle to the window -- -- -- RETURNS: VOID. -- -- NOTES: -- Initializes settings for the RFID scanner. Called everytime -- a connection is made. ------------------------------------------------------------------------------*/ VOID InitRfid(HWND hWnd){ PWNDDATA pwd; CHAR psWriteBuf[26] = {0x30, 0x31, 0x30, 0x41, 0x30, 0x30, 0x30, 0x33, 0x30, 0x31, 0x34, 0x33, 0x30, 0x36, 0x30, 0x30, 0x01, 0x0A, 0x00, 0x03, 0x01, 0x43, 0x06, 0x00, 0x4C, 0xB3}; OVERLAPPED overlap = {0}; DWORD dwBytesRead = 0; UINT bufLength = 26; pwd = (PWNDDATA)GetWindowLongPtr(hWnd, 0); if (!WriteFile(pwd->hPort, psWriteBuf, bufLength, &dwBytesRead, &overlap)) { if (GetLastError() != ERROR_IO_PENDING) { DISPLAY_ERROR("Failed to initialize RFID reader"); } } }
/*------------------------------------------------------------------------------ -- FUNCTION: Disconnect -- -- DATE: Oct 16, 2010 -- -- REVISIONS: Nov 16, 2010 -- This function now creates and signals the event "disconnected". -- -- DESIGNER: Dean Morin -- -- PROGRAMMER: Dean Morin -- -- INTERFACE: Disconnect(HWND hWnd) -- hWnd - the handle to the window -- -- RETURNS: VOID. -- -- NOTES: -- Closes the active serial port and read thread, then -- enables/disables the appropriate menu choices. ------------------------------------------------------------------------------*/ VOID Disconnect(HWND hWnd) { PWNDDATA pwd = (PWNDDATA) GetWindowLongPtr(hWnd, 0); COMMTIMEOUTS timeOut = {0}; HANDLE hEvent = 0; DWORD dwThreadid = 0; DWORD i = 0; if (pwd->hPort == NULL) { return; } // this will end the outer while loop in the read thread pwd->bConnected = FALSE; hEvent = CreateEvent(NULL, TRUE, FALSE, TEXT("disconnected")); SetEvent(hEvent); if (!SetCommTimeouts(pwd->hPort, &pwd->defaultTimeOuts)) { DISPLAY_ERROR("Could not reset comm timeouts to defaults"); } // let the read thread finish up do { GetExitCodeThread(pwd->hThread, &dwThreadid); } while (dwThreadid == STILL_ACTIVE); ResetEvent(hEvent); CloseHandle(pwd->hThread); CloseHandle(pwd->hPort); pwd->hPort = NULL; // enable/disable appropriate menu choices EnableMenuItem(GetMenu(hWnd), IDM_DISCONNECT, MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_CONNECT, MF_ENABLED); EnableMenuItem(GetMenu(hWnd), IDM_COMMSET, MF_ENABLED); for (i = 0; i < NO_OF_PORTS; i++) { EnableMenuItem(GetMenu(hWnd), IDM_COM1 + i, MF_ENABLED); } }
/*------------------------------------------------------------------------------ -- FUNCTION: ProcessCommError -- -- DATE: Oct 13, 2010 -- -- REVISIONS: (Date and Description) -- -- DESIGNER: Dean Morin -- -- PROGRAMMER: Dean Morin -- -- INTERFACE: VOID ProcessCommError(HANDLE hPort) -- hPort - the handle to the open port -- -- RETURNS: VOID. -- -- NOTES: -- Displays messages for various communication errors. Most of the -- time, this function will process ERROR_IO_PENDING and return -- early since this is expected in overlapped I/O. ------------------------------------------------------------------------------*/ VOID ProcessCommError(HANDLE hPort) { DWORD dwError; if (GetLastError() == ERROR_IO_PENDING) { return; } ClearCommError(hPort, &dwError, NULL); switch (dwError) { case CE_BREAK: DISPLAY_ERROR("The hardware detected a break condition"); case CE_FRAME: DISPLAY_ERROR("The hardware detected a framing error"); case CE_OVERRUN: DISPLAY_ERROR("A character-buffer overrun has occurred. The next character is lost."); case CE_RXOVER: DISPLAY_ERROR("An input buffer overflow has occurred. There is either no room in the input buffer, or a character was received after the end-of-file (EOF) character"); case CE_RXPARITY: DISPLAY_ERROR("The hardware detected a parity error"); default: DISPLAY_ERROR("A communication error occured"); } }
/*------------------------------------------------------------------------------ -- FUNCTION: Connect -- -- DATE: Oct 16, 2010 -- -- REVISIONS: Nov 6, 2010 - Added initialization of rfid scanner and printing -- headers for token display. -- -- DESIGNER: Dean Morin -- -- PROGRAMMER: Dean Morin -- -- INTERFACE: Connect(HWND hWnd) -- hWnd - the handle to the window -- -- RETURNS: True if the serial connection was succefully made. -- -- NOTES: -- Opens a serial port connection, displaying appropriate dialogue -- messages for failed connections. If successful, it sets comm -- settings and creates a read thread. It then enables/disables -- the appropriate menu choices. ------------------------------------------------------------------------------*/ BOOL Connect(HWND hWnd) { PWNDDATA pwd = {0}; COMMTIMEOUTS timeOut = {0}; DWORD dwThreadid = 0; DWORD i = 0; COMMCONFIG cc = {0}; pwd = (PWNDDATA) GetWindowLongPtr(hWnd, 0); // open serial port pwd->hPort = CreateFile(pwd->lpszCommName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (pwd->hPort == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_FILE_NOT_FOUND) { DISPLAY_ERROR("Serial port does not exist"); } else { DISPLAY_ERROR("Error opening port"); } return FALSE; } pwd->bConnected = TRUE; cc.dwSize = sizeof(COMMCONFIG); cc.wVersion = 1; GetCommConfig(pwd->hPort, &cc, &cc.dwSize); if (!CommConfigDialog(pwd->lpszCommName, hWnd, &cc)) { DISPLAY_ERROR("The comm settings dialogue failed.\nThis port may not exist"); } // set timeouts for the port if (!GetCommTimeouts(pwd->hPort, &timeOut)) { DISPLAY_ERROR("Error retrieving comm timeouts"); return FALSE; } timeOut.ReadIntervalTimeout = MAXDWORD; timeOut.ReadTotalTimeoutConstant = 0; timeOut.ReadTotalTimeoutMultiplier = 0; timeOut.WriteTotalTimeoutMultiplier = 0; timeOut.WriteTotalTimeoutConstant = 0; if (!SetCommTimeouts(pwd->hPort, &timeOut)) { DISPLAY_ERROR("Could not set comm timeouts"); return FALSE; } if (!SetCommState(pwd->hPort, &cc.dcb)) { DISPLAY_ERROR("Could not set comm state"); return FALSE; } // create thread for reading pwd->hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) PortIOThreadProc, hWnd, 0, &dwThreadid); if (pwd->hThread == INVALID_HANDLE_VALUE) { DISPLAY_ERROR("Error creating read thread"); return FALSE; } if (!EscapeCommFunction(pwd->hPort, SETRTS)) { DISPLAY_ERROR("Error sending RTS signal"); } if (!EscapeCommFunction(pwd->hPort, SETDTR)) { DISPLAY_ERROR("Error sending DTR signal"); } CUR_FG_COLOR = 7; CUR_BG_COLOR = 0; CUR_STYLE = 0; BRIGHTNESS = 0; // enable/disable appropriate menu choices EnableMenuItem(GetMenu(hWnd), IDM_DISCONNECT, MF_ENABLED); EnableMenuItem(GetMenu(hWnd), IDM_CONNECT, MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_COMMSET, MF_GRAYED); for (i = 0; i < NO_OF_PORTS; i++) { EnableMenuItem(GetMenu(hWnd), IDM_COM1 + i, MF_GRAYED); } return TRUE; }
/*------------------------------------------------------------------------------ -- FUNCTION: Connect -- -- DATE: Oct 16, 2010 -- -- REVISIONS: Nov 6, 2010 - Added initialization of rfid scanner and printing -- headers for token display. -- -- DESIGNER: Dean Morin -- -- PROGRAMMER: Dean Morin -- -- INTERFACE: Connect(HWND hWnd) -- hWnd - the handle to the window -- -- RETURNS: True if the serial connection was succefully made. -- -- NOTES: -- Opens a serial port connection, displaying appropriate dialogue -- messages for failed connections. If successful, it sets comm -- settings and creates a read thread. It then enables/disables -- the appropriate menu choices. ------------------------------------------------------------------------------*/ BOOL Connect(HWND hWnd) { PWNDDATA pwd = {0}; COMMTIMEOUTS timeOut = {0}; DWORD dwThreadid = 0; DWORD i = 0; pwd = (PWNDDATA) GetWindowLongPtr(hWnd, 0); // open serial port pwd->hPort = CreateFile(pwd->lpszCommName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (pwd->hPort == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_FILE_NOT_FOUND) { DISPLAY_ERROR("Serial port does not exist"); } else { DISPLAY_ERROR("Error opening port"); } return FALSE; } pwd->bConnected = TRUE; if (!EscapeCommFunction(pwd->hPort, SETRTS)) { DISPLAY_ERROR("Error sending RTS signal"); } if (!EscapeCommFunction(pwd->hPort, SETDTR)) { DISPLAY_ERROR("Error sending DTR signal"); } // set timeouts for the port if (!GetCommTimeouts(pwd->hPort, &pwd->defaultTimeOuts)) { DISPLAY_ERROR("Error retrieving comm timeouts"); return FALSE; } timeOut.ReadIntervalTimeout = 10; timeOut.WriteTotalTimeoutConstant = 5000; if (!SetCommTimeouts(pwd->hPort, &timeOut)) { DISPLAY_ERROR("Could not set comm timeouts"); return FALSE; } //Initialize Rfid scanner InitRfid(hWnd); // create thread for reading pwd->hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ReadThreadProc, hWnd, 0, &dwThreadid); if (pwd->hThread == INVALID_HANDLE_VALUE) { DISPLAY_ERROR("Error creating read thread"); return FALSE; } CUR_FG_COLOR = 7; CUR_BG_COLOR = 0; CUR_STYLE = 0; BRIGHTNESS = 0; pwd->cursorMode = TRUE; // enable/disable appropriate menu choices EnableMenuItem(GetMenu(hWnd), IDM_DISCONNECT, MF_ENABLED); EnableMenuItem(GetMenu(hWnd), IDM_CONNECT, MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_COMMSET, MF_GRAYED); for (i = 0; i < NO_OF_PORTS; i++) { EnableMenuItem(GetMenu(hWnd), IDM_COM1 + i, MF_GRAYED); } return TRUE; }
/*------------------------------------------------------------------------------ -- FUNCTION: InitTerminal -- -- DATE: Oct 19, 2010 -- -- REVISIONS: Dec 02, 2010 - Added a crc initialization -- -- DESIGNER: Dean Morin -- -- PROGRAMMER: Dean Morin -- -- INTERFACE: VOID InitTerminal(HWND hWnd) -- hWnd- the handle to the window -- -- RETURNS: VOID. -- -- NOTES: -- Initializes the terminal to its default state. ------------------------------------------------------------------------------*/ VOID InitTerminal(HWND hWnd) { PWNDDATA pwd = {0}; HDC hdc = {0}; COMMCONFIG cc = {0}; TEXTMETRIC tm = {0}; PAINTSTRUCT ps = {0}; RECT windowRect = {0}; RECT clientRect = {0}; UINT i = 0; UINT j = 0; LONG lxDiff = 0; LONG lyDiff = 0; // create PWNDATA struct and stor it as the window extra if ((pwd = (PWNDDATA) calloc(1, sizeof(WNDDATA))) == 0) { DISPLAY_ERROR("Error allocating memory for WNDDATA structure"); } pwd->lpszCommName = TEXT("COM3"); SetWindowLongPtr(hWnd, 0, (LONG_PTR) pwd); // get text attributes and store values into the window extra struct hdc = GetDC(hWnd); pwd->displayBuf.hFont = (HFONT) GetStockObject(OEM_FIXED_FONT); SelectObject(hdc, pwd->displayBuf.hFont); GetTextMetrics(hdc, &tm); ReleaseDC(hWnd, hdc); // initialize variables in PWDDATA struct to defaults DL_STATE = -1; pwd->bConnected = FALSE; CHAR_WIDTH = tm.tmAveCharWidth; CHAR_HEIGHT = tm.tmHeight; CUR_FG_COLOR = 7; WINDOW_BOTTOM = LINES_PER_SCRN -1; pwd->wordWrap = FALSE; pwd->PTFBuffHead = NULL; pwd->PTFBuffTail = NULL; pwd->FTPBuffHead = NULL; pwd->FTPBuffTail = NULL; pwd->FTPQueueSize = 0; pwd->PTFQueueSize = 0; pwd->NumOfFrames = 0; pwd->NumOfReads = 0; pwd->pReadBufHead = NULL; pwd->pReadBufTail = NULL; pwd->bDebug = FALSE; // initialize a "blank" display buffer for (i = 0; i < LINES_PER_SCRN; i++) { pwd->displayBuf.rows[i] = (PLINE) calloc(1, sizeof(LINE)); for (j = 0; j < CHARS_PER_LINE; j++) { CHARACTER(j, i).character = ' '; CHARACTER(j, i).fgColor = 7; } } // set the window size based off of the font size GetWindowRect(hWnd, &windowRect); GetClientRect(hWnd, &clientRect); lxDiff = (windowRect.right - windowRect.left) - (clientRect.right - clientRect.left); lyDiff = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top); MoveWindow(hWnd, windowRect.left, windowRect.top, CHAR_WIDTH * CHARS_PER_LINE + PADDING * 2 + lxDiff, CHAR_HEIGHT * LINES_PER_SCRN + PADDING * 2 + lyDiff, TRUE); //create tables for crc crcInit(); //print out headers for terminal MakeColumns(hWnd); }
/*------------------------------------------------------------------------------ -- FUNCTION: PerformMenuAction -- -- DATE: Oct 19, 2010 -- -- REVISIONS: Dec 02, 2010 - added a case for opening a transmit file -- -- DESIGNER: Dean Morin -- -- PROGRAMMER: Dean Morin -- -- INTERFACE: VOID PerformMenuAction(HWND hWnd, WPARAM wParam) -- hWnd - the handle to the window -- wParam - contains the menu item that was selected -- -- RETURNS: VOID. -- -- NOTES: -- Responds to a user's selection of a menu item. ------------------------------------------------------------------------------*/ VOID PerformMenuAction(HWND hWnd, WPARAM wParam) { PWNDDATA pwd = NULL; DWORD dwSize = 0; COMMCONFIG cc = {0}; pwd = (PWNDDATA) GetWindowLongPtr(hWnd, 0); switch (LOWORD(wParam)) { case IDM_CONNECT: if(OpenFileReceive(hWnd)) { Connect(hWnd); ShowWindow(pwd->hDlgStats, SW_NORMAL); ShowWindow(pwd->hDlgDebug, SW_NORMAL); } return; case IDM_DISCONNECT: Disconnect(hWnd); CloseFileReceive(hWnd); CloseFileTransmit(hWnd); return; case IDM_EXIT: PostMessage(hWnd, WM_DESTROY, 0, 0); return; case IDM_COM1: case IDM_COM2: case IDM_COM3: case IDM_COM4: case IDM_COM5: case IDM_COM6: case IDM_COM7: case IDM_COM8: case IDM_COM9: SelectPort(hWnd, LOWORD(wParam)); return; case IDM_COMMSET: cc.dwSize = sizeof(COMMCONFIG); cc.wVersion = 1; GetCommConfig(pwd->hPort, &cc, &cc.dwSize); if (!CommConfigDialog(pwd->lpszCommName, hWnd, &cc)) { DISPLAY_ERROR("The comm settings dialogue failed.\nThis port may not exist"); } return; case IDM_STATISTICS: ShowWindow(pwd->hDlgStats, SW_NORMAL); return; case IDM_DEBUGGER: ShowWindow(pwd->hDlgDebug, SW_NORMAL); return; case ID_OPEN_TRANSMITFILE: OpenFileTransmit(hWnd); return; default: return; } }
/*------------------------------------------------------------------------------ -- FUNCTION: ReadFromPort -- -- DATE: Nov 29, 2010 -- -- REVISIONS: (Date and Description) -- -- DESIGNER: Dean Morin -- -- PROGRAMMER: Dean Morin -- -- INTERFACE: VOID ReadFromPort(HWND hWnd, PSTATEINFO psi, OVERLAPPED ol, -- DWORD cbInQue) -- hWnd - a handle to the window -- psi - contains info about the current state of the -- communication -- ol - the overlapped structure used to wait for -- characters at the serial port -- cbinQue - the number of characters that are at the port -- -- RETURNS: VOID. -- -- NOTES: -- Reads from the serial port and calls ProcessRead(). If -- ProcessRead() returns a zero, it means that only a partial -- frame was passed. In that case, it waits for more characters -- to arrive at the port, then appends these new characters to the -- the partial frame, and calls ProcessRead() again. ------------------------------------------------------------------------------*/ VOID ReadFromPort(HWND hWnd, PSTATEINFO psi, OVERLAPPED ol, DWORD cbInQue) { static DWORD dwQueueSize = 0; PWNDDATA pwd = NULL; BYTE pReadBuf[READ_BUFSIZE] = {0}; PBYTE pQueue = NULL; DWORD dwBytesRead = 0; DWORD i = 0; pwd = (PWNDDATA) GetWindowLongPtr(hWnd, 0); if (!ReadFile(pwd->hPort, pReadBuf, READ_BUFSIZE, &dwBytesRead, &ol)) { // read is incomplete or had an error ProcessCommError(pwd->hPort); GetOverlappedResult(pwd->hThread, &ol, &dwBytesRead, TRUE); } if (dwQueueSize == 0) { // the last port read sent an entire frame to ProcessRead() if (dwBytesRead >= CTRL_FRAME_SIZE && ProcessRead(hWnd, psi, pReadBuf, dwBytesRead)) { // read completed successfully return; } else { // a full frame is not yet at the port for (i = 0; i < dwBytesRead; i++) { AddToByteQueue(&pwd->pReadBufHead, &pwd->pReadBufTail, pReadBuf[i]); dwQueueSize++; } if (dwQueueSize != dwBytesRead) { DISPLAY_ERROR("Port read is out of sync"); } } } else { // the previous port read was not finished for (i = 0; i < dwBytesRead; i++) { AddToByteQueue(&pwd->pReadBufHead, &pwd->pReadBufTail, pReadBuf[i]); dwQueueSize++; } // checks for 1 byte read, in case the tx side is out of sync if (dwQueueSize >= FRAME_SIZE || dwBytesRead == CTRL_FRAME_SIZE) { pQueue = RemoveFromByteQueue(&pwd->pReadBufHead, dwQueueSize); ProcessRead(hWnd, psi, pQueue, dwQueueSize); // read completed successfully dwQueueSize = 0; DeleteByteQueue(pwd->pReadBufHead); pwd->pReadBufHead = NULL; pwd->pReadBufTail = NULL; for (i = 0; i < dwQueueSize; i++) { free(pQueue); } } } }