#include "zdsimp.h" int APIENTRY WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow ) { DialogBox(hInstance, MAKEINTRESOURCE(ID_ZDSIM_DLG),NULL, ZdDlgProc); return(0); } BOOL CALLBACK ZdDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { BOOL ReturnValue; ReturnValue = TRUE; HwndDlg = hDlg; switch (uMsg) { HANDLE_MSG(hDlg, WM_INITDIALOG, ZdDlgInit); HANDLE_MSG(hDlg, WM_COMMAND, ZdDlgCommand); HANDLE_MSG(hDlg, WM_HSCROLL, ZdDlgParamChange); default: ReturnValue = FALSE; break; } return ReturnValue; } BOOL ZdDlgInit( HWND hwnd, HWND hwndFocus, LPARAM lParam ) { HWND hwndSB; // // Get output window handle // hwndOutput = GetDlgItem(hwnd, ID_OUTPUT_WINDOW); SelNumberOfClients = DEF_CLIENTS; fSimulationStarted = FALSE; // // Setup simulation parameters // hwndSB = GetDlgItem(hwnd, ID_NUM_CLIENTS); SetScrollRange(hwndSB, SB_CTL, MIN_CLIENTS, MAX_CLIENTS, TRUE); SendMessage(hwnd,WM_HSCROLL,MAKEWPARAM(SB_THUMBTRACK,DEF_CLIENTS),(LPARAM)hwndSB); CheckRadioButton(hwnd,ID_RAD_TCP,ID_RAD_SPX,ID_RAD_TCP); fTcp = TRUE; fSpx = FALSE; CheckRadioButton(hwnd,ID_RAD_THREAD_PER_CLIENT,ID_RAD_DYNAMIC_THREADS,ID_RAD_DYNAMIC_THREADS); fDynamicThreadMode = TRUE; fOneThreadPerClient = FALSE; SelThreadsPerQueue = 2; InitializeCriticalSection(&DynamicCritSect); EnableWindow(GetDlgItem(hwnd, ID_END_SIM),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_1),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_2),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_3),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_4),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_5),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_6),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_7),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_8),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_9),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_10),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_11),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_12),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_13),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_14),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_15),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_16),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_17),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_18),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_19),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_20),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_21),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_22),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_23),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_24),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_25),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_26),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_27),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_28),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_29),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_30),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_31),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_32),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_33),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_34),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_35),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_36),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_37),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_38),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_39),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_40),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_41),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_42),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_43),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_44),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_45),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_46),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_47),FALSE); EnableWindow(GetDlgItem(hwnd, THREAD_48),FALSE); return(TRUE); } void ZdDlgParamChange( HWND hwnd, HWND hwndCtl, UINT code, int pos ) { CHAR szBuf[10]; int nPosCrnt, nPosMin, nPosMax; DWORD ControlId; HWND hwndText; ControlId = GetWindowLong(hwndCtl,GWL_ID); // // Get the current position and the legal range for the // scrollbar that the user is changing. // nPosCrnt = GetScrollPos(hwndCtl,SB_CTL); GetScrollRange(hwndCtl, SB_CTL, &nPosMin, &nPosMax); switch (code) { case SB_LINELEFT: nPosCrnt--; break; case SB_LINERIGHT: nPosCrnt++; break; case SB_PAGELEFT: nPosCrnt += (nPosMax - nPosMin + 1) / 10; break; case SB_PAGERIGHT: nPosCrnt -= (nPosMax - nPosMin + 1) / 10; break; case SB_THUMBTRACK: nPosCrnt = pos; break; case SB_LEFT: nPosCrnt = nPosMin; break; case SB_RIGHT: nPosCrnt = nPosMax; break; } // // Make sure that the new scroll position // is within the legal range. // if (nPosCrnt < nPosMin) { nPosCrnt = nPosMin; } if (nPosCrnt > nPosMax) { nPosCrnt = nPosMax; } switch (ControlId) { case ID_NUM_CLIENTS: hwndText = GetDlgItem(hwnd,ID_NNOC); SelNumberOfClients = nPosCrnt; _stprintf(szBuf, "%d", nPosCrnt); break; default: return; } // // Set the new scroll position. // SetScrollPos(hwndCtl, SB_CTL, nPosCrnt, TRUE); // // Change the value displayed in the text box to // reflect the value in the scrollbar. // SetWindowText(hwndText, szBuf); } void ZdDlgCommand ( HWND hwnd, int id, HWND hwndCtl, UINT codeNotify ) { switch (id) { case ID_START_SIM: case IDOK: EnableWindow(hwndCtl,FALSE); EnableWindow(GetDlgItem(hwnd, ID_END_SIM),TRUE); EnableWindow(GetDlgItem(hwnd, ID_NUM_CLIENTS),FALSE); EnableWindow(GetDlgItem(hwnd, ID_RAD_DYNAMIC_THREADS),FALSE); EnableWindow(GetDlgItem(hwnd, ID_RAD_THREAD_PER_CLIENT),FALSE); EnableWindow(GetDlgItem(hwnd, ID_RAD_TCP),FALSE); EnableWindow(GetDlgItem(hwnd, ID_RAD_SPX),FALSE); SelNumberOfClients = GetScrollPos(GetDlgItem(hwnd, ID_NUM_CLIENTS),SB_CTL); if ( fOneThreadPerClient ) { SelThreadsPerQueue = SelNumberOfClients; } SendMessage(hwndOutput, LB_RESETCONTENT, 0L, 0L); // // Disable the StartSimulation button // if (NULL == GetFocus()) { SetFocus(GetDlgItem(hwnd, ID_END_SIM)); } fSimulationStarted = TRUE; CreateNetConnections(); CreateWorkers(); break; case ID_RAD_DYNAMIC_THREADS: SelThreadsPerQueue = 2; fDynamicThreadMode = TRUE; fOneThreadPerClient = FALSE; break; case ID_RAD_THREAD_PER_CLIENT: SelThreadsPerQueue = GetScrollPos(GetDlgItem(hwnd, ID_NUM_CLIENTS),SB_CTL);; fDynamicThreadMode = FALSE; fOneThreadPerClient = TRUE; break; case ID_RAD_TCP: fTcp = TRUE; fSpx = FALSE; break; case ID_RAD_SPX: fTcp = FALSE; fSpx = TRUE; break; case ID_END_SIM: EnableWindow(GetDlgItem(hwnd, ID_END_SIM),FALSE); fSimulationStarted = FALSE; break; case IDCANCEL: EndDialog(hwnd, id); break; } } // // This function constructs a string using the format string // passed and the variable number of arguments and adds the // string to the output window list box identified by the // global hwndOutput variable. // void OutputString( LPCSTR szFmt, ... ) { CHAR szBuf[150]; int nIndex; va_list va_params; // // Make va_params point to the first argument after szFmt. // va_start(va_params, szFmt); // // Build the string to be displayed. // _vstprintf(szBuf, szFmt, va_params); do { // // Add the string to the end of the list box. // nIndex = SendMessage(hwndOutput,LB_ADDSTRING, 0L, (LPARAM)szBuf); // // If the list box is full, delete the first item in it. // if (nIndex == LB_ERR) { SendMessage(hwndOutput, LB_DELETESTRING, (WPARAM)0, 0); } } while (nIndex == LB_ERR); // // Select the newly added item. // SendMessage(hwndOutput, LB_SETCURSEL, (WPARAM)nIndex, 0); // // Indicate that we are done referencing // the variable arguments. // va_end(va_params); } DWORD WINAPI NetWorkThread( LPVOID WorkContext ) { PZD_WORK_QUEUE MyQueue; PZD_THREAD Me; DWORD WorkIndex; INT err; DWORD ResponseLength; BOOL b; LPOVERLAPPED lpo; DWORD nbytes; Me = (PZD_THREAD)WorkContext; MyQueue = Me->WorkQueue; for(;;){ b = GetQueuedCompletionStatus( CompletionPort, &nbytes, &WorkIndex, &lpo, INFINITE ); if ( b || lpo ) { WorkerStartWork(Me); // // Don't send a response if we received 0 bytes (end of // transmission). // if ( b && nbytes == 4 ) { // // Determine how long a response was desired by the client. // The first four bytes of the received packet contain the // number of bytes desired by the client. // ResponseLength = *(PDWORD)(ZdWorkQueue.IoBuffer[WorkIndex]); // // Send a response and post another asynchronous read on the // socket. // err = send( MyQueue->Sockets[WorkIndex], MyQueue->IoBuffer[WorkIndex], ResponseLength, 0 ); if ( err == SOCKET_ERROR ) { MessageBox(HwndDlg,"Send Failed. Simulation Should Stop","Send Failed",MB_ICONSTOP|MB_OK); } ZdWorkQueue.Overlapped[WorkIndex].hEvent = NULL; err = ReadFile( (HANDLE)ZdWorkQueue.Sockets[WorkIndex], ZdWorkQueue.IoBuffer[WorkIndex], 4, &ZdWorkQueue.Overlapped[WorkIndex].InternalHigh, &ZdWorkQueue.Overlapped[WorkIndex] ); if ( !err && GetLastError( ) != ERROR_IO_PENDING ) { MessageBox(HwndDlg,"ReadFile Failed. Simulation Should Stop","ReadFile Failed",MB_ICONSTOP|MB_OK); } } WorkerEndWork(Me); } else { MessageBox(HwndDlg,"netWorkThread Wait Failed. Simulation Should Stop","Wait Failed",MB_ICONSTOP|MB_OK); } } } DWORD WINAPI NetWorkThread2( LPVOID WorkContext ) { PZD_WORK_QUEUE MyQueue; PZD_THREAD Me; DWORD WorkIndex; INT err; DWORD ResponseLength; Me = (PZD_THREAD)WorkContext; MyQueue = Me->WorkQueue; WorkIndex = Me->ThreadIndex; for(;;){ err = recv( MyQueue->Sockets[WorkIndex], MyQueue->IoBuffer[WorkIndex], 4, 0 ); if ( err == SOCKET_ERROR ) { MessageBox(HwndDlg,"Recv Failed. Simulation Should Stop","Recv Failed",MB_ICONSTOP|MB_OK); break; } if ( err < 4 ) { return; } WorkerStartWork(Me); // // Determine how long a response was desired by the client. The // first four bytes of the received packet contain the number of // bytes desired by the client. // ResponseLength = *(PDWORD)(ZdWorkQueue.IoBuffer[WorkIndex]); // // Send a response and post another asynchronous read on the // socket. // err = send( MyQueue->Sockets[WorkIndex], MyQueue->IoBuffer[WorkIndex], ResponseLength, 0 ); if ( err == SOCKET_ERROR ) { MessageBox(HwndDlg,"Send Failed. Simulation Should Stop","Send Failed",MB_ICONSTOP|MB_OK); break; } WorkerEndWork(Me); } } VOID CreateNetConnections( void ) { DWORD i; SOCKET listener; INT err; WSADATA WsaData; err = WSAStartup( 0x0101, &WsaData ); if ( err == SOCKET_ERROR ) { MessageBox(HwndDlg,"WSAStartup Failed. Simulation Should Stop","WSAStartup Failed",MB_ICONSTOP|MB_OK); return; } // // Open a socket to listen for incoming connections. // if ( fTcp ) { SOCKADDR_IN localAddr; listener = socket( AF_INET, SOCK_STREAM, 0 ); if ( listener == INVALID_SOCKET ) { MessageBox(HwndDlg,"Socket Create Failed. Simulation Should Stop","Socket Create Failed",MB_ICONSTOP|MB_OK); return; } RtlZeroMemory( &localAddr, sizeof(localAddr) ); localAddr.sin_port = htons( 7 ); localAddr.sin_family = AF_INET; err = bind( listener, (PSOCKADDR)&localAddr, sizeof(localAddr) ); if ( err ==SOCKET_ERROR ) { MessageBox(HwndDlg,"Socket Bind Failed. Simulation Should Stop","Socket Bind Failed",MB_ICONSTOP|MB_OK); return; } } else { SOCKADDR_IPX localAddr; listener = socket( AF_IPX, SOCK_STREAM, NSPROTO_SPX ); if ( listener == INVALID_SOCKET ) { MessageBox(HwndDlg,"Socket Create Failed. Simulation Should Stop","Socket Create Failed",MB_ICONSTOP|MB_OK); return; } RtlZeroMemory( &localAddr, sizeof(localAddr) ); localAddr.sa_socket = htons( 7 ); localAddr.sa_family = AF_IPX; err = bind( listener, (PSOCKADDR)&localAddr, sizeof(localAddr) ); if ( err ==SOCKET_ERROR ) { MessageBox(HwndDlg,"Socket Bind Failed. Simulation Should Stop","Socket Bind Failed",MB_ICONSTOP|MB_OK); return; } } err = listen( listener, 5 ); if ( err == SOCKET_ERROR ) { MessageBox(HwndDlg,"Socket Listen Failed. Simulation Should Stop","Socket Listen Failed",MB_ICONSTOP|MB_OK); return; } // // Only Handle a single Queue // for(i=0;iYourControl, BM_SETCHECK, 1, 0); SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_HIGHEST); if ( WorkThread->DynamicMode ) { EnterCriticalSection(&DynamicCritSect); ActiveThreadCount++; if ( ActiveThreadCount == SelThreadsPerQueue ) { ThreadsLoaded++; if ( ThreadsLoaded > ZdThreadAddThreshold ) { ThreadsLoaded = 0; if ( SelThreadsPerQueue < MAX_THREADS_PER_QUEUE ) { SelThreadsPerQueue++; OutputString("Threads Oveloaded. New Thread Added"); if ((SelThreadsPerQueue & 1) == 0) { ZdThreadAddThreshold++; OutputString("New threshold %d", ZdThreadAddThreshold); } CreateWorkers(); } } } else { ThreadsLoaded = 0; } LeaveCriticalSection(&DynamicCritSect); } } VOID WorkerEndWork( PZD_THREAD WorkThread ) { SendMessage(WorkThread->YourControl, BM_SETCHECK, 0, 0); SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_NORMAL); if ( WorkThread->DynamicMode ) { EnterCriticalSection(&DynamicCritSect); ActiveThreadCount--; LeaveCriticalSection(&DynamicCritSect); } }