// MiniChat - Copyright (C) 2003 Skywing #include #include #include // Visual C++-specific #pragma intrinsic(memcmp, memcpy, memset, strcat, strcmp, strcpy, strlen) #define MAKEIP(b4,b3,b2,b1) ((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4)))) #define RENDIAN_WORD(W) ((HIBYTE(WORD(W)) >> 0) | (LOBYTE(WORD(W)) << 8)) #define DATA_SIZE 4096 int InitWinsock(void) { WSAData Data; return WSAStartup(0x0202, &Data); } int Connect(SOCKET Sock) { SOCKADDR_IN Address; Address.sin_addr.s_addr = MAKEIP(63,240,202,138); //Address.sin_addr.s_addr = MAKEIP(211,233,0,76); Address.sin_port = RENDIAN_WORD(6112); Address.sin_family = AF_INET; memset(Address.sin_zero, 0, sizeof(Address.sin_zero)); return connect(Sock, (PSOCKADDR)&Address, sizeof(Address)); } void* Alloc(DWORD Size) { return HeapAlloc(GetProcessHeap(), HEAP_NO_SERIALIZE, Size); } void* AllocZ(DWORD Size) { return HeapAlloc(GetProcessHeap(), HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, Size); } void Free(void* Memory) { HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, Memory); } VOID WINAPI SendCompletion(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped) { Free(lpOverlapped->hEvent); // Data duplicated Free(lpOverlapped); } void SendData(SOCKET Sock, const char* Data) { size_t Bytes = strlen(Data); void* DuplicateData = Alloc(Bytes); LPOVERLAPPED Overlapped = (LPOVERLAPPED)AllocZ(sizeof(OVERLAPPED)); memcpy(DuplicateData, Data, Bytes); Overlapped->hEvent = DuplicateData; WriteFileEx((HANDLE)Sock, DuplicateData, Bytes, Overlapped, &SendCompletion); } struct ReceiveOverlapped : public OVERLAPPED { SOCKET Sock; bool* Disconnect; HWND OutWindow; }; VOID WINAPI ReceiveCompletion(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, ReceiveOverlapped* lpOverlapped) { if(!dwErrorCode && dwNumberOfBytesTransferred) { LPBYTE Data = (LPBYTE)lpOverlapped->hEvent; CHARRANGE Range = {-1, -1}; Data[dwNumberOfBytesTransferred] = '\0'; SendMessage(lpOverlapped->OutWindow, EM_EXSETSEL, 0, (LPARAM)&Range); SendMessage(lpOverlapped->OutWindow, EM_REPLACESEL, FALSE, (LPARAM)Data); ReadFileEx((HANDLE)lpOverlapped->Sock, Data, DATA_SIZE-1, lpOverlapped, (LPOVERLAPPED_COMPLETION_ROUTINE)&ReceiveCompletion); } else { closesocket(lpOverlapped->Sock); *lpOverlapped->Disconnect = true; } } void RunMainLoop(HWND OutWindow, HWND InWindow) { SOCKET Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(Sock == INVALID_SOCKET) return; bool Disconnect = false; if(!Connect(Sock)) { ShowWindow(OutWindow, SW_SHOW); ShowWindow(InWindow, SW_SHOW); BYTE Data[DATA_SIZE]; ReceiveOverlapped Overlapped; // This MUST NOT go out of scope while ReadFileEx is in progress Overlapped.hEvent = Data; Overlapped.Sock = Sock; Overlapped.Disconnect = &Disconnect; Overlapped.OutWindow = OutWindow; if(ReadFileEx((HANDLE)Sock, Data, DATA_SIZE-1, &Overlapped, (LPOVERLAPPED_COMPLETION_ROUTINE)&ReceiveCompletion) || GetLastError() == ERROR_IO_PENDING) { SendData(Sock, "\x03\x04""Anonymous\r\n"); // Workaround for VC bug while(!Disconnect) { switch(MsgWaitForMultipleObjectsEx(0, 0, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE)) { case WAIT_OBJECT_0: MSG msg; while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { UINT m = msg.message; TranslateMessage(&msg); if(msg.hwnd == InWindow && msg.message == WM_CHAR && msg.wParam == '\r') { int Size = GetWindowTextLength(InWindow)+3; char* Text = (char*)Alloc(Size); if(!GetWindowText(InWindow, Text, Size-2)) Text[0] = '\0'; *(LPWORD)&Text[Size-3] = '\n\r'; Text[Size-1] = 0; SendData(Sock, Text); SetWindowText(InWindow, ""); } else DispatchMessage(&msg); } if(!IsWindow(InWindow) || !IsWindow(OutWindow)) { closesocket(Sock); SleepEx(0, TRUE); Disconnect = true; } break; } } } } else closesocket(Sock); } void Main(void) { HINSTANCE RichEdit = LoadLibrary("RichEd20.dll"); if(!RichEdit) { ExitProcess(ERROR_FILE_NOT_FOUND); __assume(0); // Visual C++-specific } if(!InitWinsock()) { HINSTANCE Mod = GetModuleHandle(0); if(HWND OutWindow = CreateWindowEx(WS_EX_APPWINDOW | WS_EX_OVERLAPPEDWINDOW, "RICHEDIT20A", "", WS_CAPTION | ES_AUTOVSCROLL | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX | WS_SYSMENU | ES_READONLY | ES_MULTILINE, CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, 0, Mod, 0)) { if(HWND InWindow = CreateWindowEx(0, "EDIT", "MiniChat", WS_CAPTION | ES_AUTOHSCROLL | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX | WS_SYSMENU, 50, 50, 200, 45, OutWindow, 0, Mod, 0)) { RunMainLoop(OutWindow, InWindow); DestroyWindow(InWindow); } DestroyWindow(OutWindow); } WSACleanup(); } FreeLibrary(RichEdit); ExitProcess(ERROR_SUCCESS); }