|
|
1.1 ! root 1: /*************************************************************************\ ! 2: * PROGRAM: client32.c ! 3: * ! 4: * PURPOSE: ! 5: * ! 6: * To demonstrate the use of named pipes and the overlapped structure. ! 7: * This code serves as the client side of the named pipe instances. ! 8: * For more details on an overview of this codes designs or use, see ! 9: * the README file. For details on the implementation, see the comments ! 10: * in this code. ! 11: * ! 12: * ! 13: \*************************************************************************/ ! 14: ! 15: #include <windows.h> ! 16: #include "client32.h" ! 17: ! 18: #include <string.h> ! 19: #include <stdio.h> ! 20: #include <stdlib.h> ! 21: ! 22: HANDLE hInst; ! 23: HWND hWndClient; ! 24: ! 25: CHAR ShrName[LINE_LEN]; // Global: net share name. ! 26: CHAR ClntName[NAME_SIZE]; // Global: user or pipe client name. ! 27: ! 28: /*************************************************************************\ ! 29: * ! 30: * FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int) ! 31: * ! 32: * PURPOSE: Launches the Client's dialog box. ! 33: * ! 34: * COMMENTS: ! 35: * ! 36: \*************************************************************************/ ! 37: ! 38: int APIENTRY WinMain (HINSTANCE hInstance, ! 39: HINSTANCE hPrevInstance, ! 40: LPSTR lpCmdLine, ! 41: int nCmdShow) ! 42: ! 43: ! 44: { ! 45: DWORD retCode; ! 46: ! 47: UNREFERENCED_PARAMETER( nCmdShow ); ! 48: UNREFERENCED_PARAMETER( lpCmdLine ); ! 49: UNREFERENCED_PARAMETER( hPrevInstance ); ! 50: ! 51: hInst = hInstance; ! 52: retCode = DialogBox ((HANDLE)hInst, (LPCSTR)"ClientDialog", ! 53: NULL, (DLGPROC)ClientDlgProc); ! 54: return (retCode); ! 55: ! 56: } ! 57: ! 58: ! 59: /*************************************************************************\ ! 60: * ! 61: * PROCEDURE: InitDlgProc (HWND hDlg, WORD wMsg, LONG wParam, LONG lParam) ! 62: * ! 63: * PURPOSE: This dialog box prompts the user for a net share name and ! 64: * a client or user name. These values are placed into global ! 65: * strings ShrName and ClntName. ! 66: * ! 67: * CALLED BY: ! 68: * ! 69: * ClientDlgProc(); ! 70: * ! 71: \*************************************************************************/ ! 72: ! 73: LONG CALLBACK InitDlgProc (HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam) ! 74: { ! 75: ! 76: UNREFERENCED_PARAMETER(lParam); ! 77: ! 78: switch (wMsg) ! 79: { ! 80: case WM_INITDIALOG: ! 81: PostMessage (GetDlgItem (hDlg, IDD_SVREDIT), ! 82: EM_LIMITTEXT, LINE_LEN, 0); ! 83: ! 84: PostMessage (GetDlgItem (hDlg, IDD_CLNTEDIT), ! 85: EM_LIMITTEXT, NAME_SIZE, 0); ! 86: case WM_COMMAND: ! 87: switch (LOWORD(wParam)) ! 88: { // When the user clicks okay, get the ! 89: case IDB_INITOK: // share name and user name from the ! 90: // edit fields. ! 91: GetWindowText (GetDlgItem (hDlg, IDD_SVREDIT), ShrName, LINE_LEN); ! 92: GetWindowText (GetDlgItem (hDlg, IDD_CLNTEDIT), ClntName, NAME_SIZE); ! 93: EndDialog(hDlg, 0); ! 94: return (0); ! 95: ! 96: default: ! 97: return (0); ! 98: } ! 99: default: ! 100: return (0); ! 101: } ! 102: return (0); ! 103: } ! 104: ! 105: ! 106: /*************************************************************************\ ! 107: * ! 108: * PROCEDURE: ClientDlgProc (HWND hDlg, WORD wMsg, LONG wParam, LONG lParam) ! 109: * ! 110: * PURPOSE: This procedure services the dialog box that serves as an interface ! 111: * to the named pipe server instance. The larger edit field is used ! 112: * to read messages from the server instance. The smaller edit field ! 113: * is used to type messages to the server instance. This procedure ! 114: * is responsible for connecting to the named pipe, creating a ! 115: * seperate thread to read the pipe, and sending to the pipe. ! 116: * ! 117: * CALLED BY: ! 118: * ! 119: * WinMain(); ! 120: * ! 121: * CALLS TO: ! 122: * ! 123: * InitDlgProc(); ! 124: * ReadPipe(); ! 125: * ! 126: \**************************************************************************/ ! 127: ! 128: LONG CALLBACK ClientDlgProc (HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam) ! 129: { ! 130: DWORD retCode; // Return code. ! 131: CHAR errorBuf[LINE_LEN] = ""; // Error message buffer. ! 132: CHAR outBuf[OUT_BUF_SIZE] = ""; // Buffer trapping message to send. ! 133: CHAR sendBuf[OUT_BUF_SIZE] = ""; // Buffer used to modify message. ! 134: DWORD bytesWritten; // Used for WriteFile(). ! 135: DWORD threadID; // Used for CreateThread(). ! 136: CHAR fileName[LINE_LEN+NAME_SIZE+2]; // Used to modify pipe/file name. ! 137: DWORD lastError; // Used to get returns from GetLastError. ! 138: DWORD bytesTrans; // Used with overlapped structure. ! 139: ! 140: static HANDLE hPipe; // File or Pipe handle. ! 141: static OVERLAPPED OverLapWrt; // Overlapped structure ! 142: static HANDLE hEventWrt; // Event handle for overlapped writes. ! 143: ! 144: UNREFERENCED_PARAMETER( lParam ); ! 145: ! 146: hWndClient = hDlg; ! 147: ! 148: switch (wMsg) ! 149: { ! 150: ! 151: case WM_COMMAND: ! 152: switch (LOWORD(wParam)) ! 153: { ! 154: ! 155: // When the user presses Send: capture the string from the edit ! 156: // field, prepend it with the user name, and overlap write it to ! 157: // the server instance of the named pipe. ! 158: ! 159: case IDB_SEND: // Get the text from the edit field. ! 160: GetWindowText (GetDlgItem(hDlg,IDD_EDITWRITE), ! 161: outBuf, PLEASE_WRITE); ! 162: ! 163: // Prepend it with the user name, and ! 164: // terminate it with a new line ! 165: // character. ! 166: ! 167: wsprintf (sendBuf, "%s%s %s\n", ClntName, ":", outBuf); ! 168: ! 169: // Do the overlapped write. ! 170: retCode = WriteFile (hPipe, sendBuf, PLEASE_WRITE, ! 171: &bytesWritten, &OverLapWrt); ! 172: if (!retCode) ! 173: { ! 174: lastError = GetLastError(); ! 175: // If Error = IO_PENDING, wait til ! 176: // the event signals success. ! 177: if (lastError == ERROR_IO_PENDING) ! 178: WaitForSingleObject (hEventWrt, (DWORD)-1); ! 179: } ! 180: // Update the file pointer manually. ! 181: GetOverlappedResult (hPipe, &OverLapWrt, &bytesTrans, FALSE); ! 182: OverLapWrt.Offset += bytesTrans; ! 183: ! 184: return (0); ! 185: ! 186: default: ! 187: return (0); ! 188: ! 189: } ! 190: ! 191: ! 192: case WM_INITCLIENT: ! 193: ! 194: // On initialization, use the Init dialog box prompt the user for a ! 195: // net share name and a client or user name. A share name of "." ! 196: // means that the named pipe is local to this machine. Named pipe ! 197: // names should have the form '\\.\PIPE\<pipename>', for a local machine ! 198: // or '\\<machinename>\PIPE\<pipename>' for remote machines. ! 199: // Once the share name is captured from the Init dialog box, ! 200: // convert the name into the proper form; then do a CreateFile() ! 201: // to connect to the pipe. Handle any error from the CreateFile(). ! 202: // Then write the user name to the server instance of the named ! 203: // pipe. Finally, create a thread to read the named pipe. ! 204: ! 205: // Launch Init dialog box to capture ! 206: // share name and user name. ! 207: DialogBox ((HANDLE)GetModuleHandle(NULL), ! 208: (LPCSTR)"InitDialog", ! 209: (HWND)hDlg, ! 210: (DLGPROC)InitDlgProc); ! 211: ! 212: // Put captured user name in window ! 213: // caption. ! 214: SetWindowText (hDlg, ClntName); ! 215: ! 216: // Construct file/pipe name. ! 217: wsprintf (fileName, "%s%s%s", "\\\\", ShrName, "\\PIPE\\test"); ! 218: ! 219: // Do CreateFile() to connect to the ! 220: // named pipe. ! 221: hPipe = CreateFile (fileName, // Pipe name. ! 222: GENERIC_WRITE // Generic access, read/write. ! 223: | GENERIC_READ, ! 224: FILE_SHARE_READ // Share both read and write. ! 225: | FILE_SHARE_WRITE , ! 226: NULL, // No security. ! 227: OPEN_EXISTING, // Fail if not existing. ! 228: FILE_FLAG_OVERLAPPED, // Use overlap. ! 229: NULL); // No template. ! 230: ! 231: // Do some error checking. ! 232: if ((DWORD)hPipe == 0xFFFFFFFF) ! 233: { ! 234: retCode = GetLastError(); ! 235: ! 236: // This error means pipe wasn't found. ! 237: if ((retCode == ERROR_SEEK_ON_DEVICE) || ! 238: (retCode == ERROR_FILE_NOT_FOUND)) ! 239: MessageBox (hDlg, ! 240: "CANNOT FIND PIPE: Assure Server32 is started, check share name.", ! 241: "", ! 242: MB_OK); ! 243: else ! 244: { // Flagging unknown errors. ! 245: wsprintf (errorBuf, ! 246: "CreateFile() on pipe failed, see winerror.h error #%d.", ! 247: retCode); ! 248: MessageBox (hDlg, errorBuf, "Debug Window", ! 249: MB_ICONINFORMATION | MB_OK | MB_APPLMODAL); ! 250: } ! 251: ! 252: EndDialog (hDlg, 0); // Kill app if pipe didn't connect. ! 253: }; ! 254: ! 255: // Create and init overlapped structure ! 256: // for writes. ! 257: hEventWrt = CreateEvent (NULL, TRUE, FALSE, NULL); ! 258: OverLapWrt.hEvent = hEventWrt; ! 259: ! 260: // Write the client name to server. ! 261: retCode = WriteFile (hPipe, ClntName, PLEASE_WRITE, ! 262: &bytesWritten, &OverLapWrt); ! 263: ! 264: if (!retCode) // Wait on overlapped if need be. ! 265: { ! 266: lastError = GetLastError(); ! 267: if (lastError == ERROR_IO_PENDING) ! 268: WaitForSingleObject (hEventWrt, (DWORD)-1); ! 269: } ! 270: // Manually update file pointer. ! 271: GetOverlappedResult (hPipe, &OverLapWrt, &bytesTrans, FALSE); ! 272: OverLapWrt.Offset += bytesTrans; ! 273: ! 274: // Create a thread to read the pipe. ! 275: CreateThread (NULL, ! 276: 0, ! 277: (LPTHREAD_START_ROUTINE)ReadPipe, ! 278: (LPVOID)&hPipe, ! 279: NULL, ! 280: &threadID); ! 281: return (0); ! 282: ! 283: ! 284: ! 285: case WM_INITDIALOG: ! 286: // PostMessage() give time for the ! 287: // dialog box to be created. ! 288: PostMessage (hDlg, WM_INITCLIENT, 0, 0); ! 289: return (0); ! 290: ! 291: ! 292: ! 293: case WM_GO_AWAY: ! 294: CloseHandle (hPipe); ! 295: CloseHandle (hEventWrt); ! 296: EndDialog (hDlg, TRUE); ! 297: return TRUE; ! 298: ! 299: ! 300: ! 301: case WM_SYSCOMMAND: ! 302: if (wParam == SC_CLOSE) ! 303: { ! 304: CloseHandle (hPipe); ! 305: CloseHandle (hEventWrt); ! 306: EndDialog(hDlg, TRUE); ! 307: return TRUE; ! 308: } ! 309: break; ! 310: } ! 311: return (FALSE); ! 312: ! 313: } ! 314: ! 315: /*************************************************************************\ ! 316: * ! 317: * PROCEDURE: ReadPipe (HANDLE *hRead) ! 318: * ! 319: * PURPOSE: This is a thread function which loops and reads the named pipe. ! 320: * ! 321: * CALLED BY: ! 322: * ! 323: * ClientDlgProc. ! 324: * ! 325: * ! 326: \*************************************************************************/ ! 327: ! 328: VOID ReadPipe (HANDLE *hPipe) ! 329: { ! 330: CHAR inBuf[IN_BUF_SIZE] = "";// Input buffer. ! 331: DWORD bytesRead; // Used for ReadFile() ! 332: DWORD retCode; // Used to trap return codes. ! 333: CHAR Buf[80]; // Message box buffer. ! 334: DWORD lastError; // Used to trap returns from GetLastError. ! 335: ! 336: HANDLE hEventRd; // Event handle for overlapped reads. ! 337: OVERLAPPED OverLapRd; // Overlapped structure. ! 338: DWORD bytesTrans; // Bytes transferred in read. ! 339: ! 340: // Create and init overlap structure. ! 341: hEventRd = CreateEvent (NULL, TRUE, FALSE, NULL); ! 342: memset (&OverLapRd, 0, sizeof(OVERLAPPED)); ! 343: OverLapRd.hEvent = hEventRd; ! 344: ! 345: // Loop, reading the named pipe until it is broken. The ReadFile() uses ! 346: // an overlapped structure. When the event handle signals a completed ! 347: // read, this loop writes the message to the larger edit field. ! 348: ! 349: do{ ! 350: // Read the pipe handle. ! 351: retCode = ReadFile (*hPipe, inBuf, IN_BUF_SIZE, &bytesRead, &OverLapRd); ! 352: ! 353: if (!retCode) // Do some error checking. ! 354: { ! 355: lastError = GetLastError(); ! 356: // Check for 3 kinds of errors: ! 357: // IO_PENDING, BROKEN_PIPE, or ! 358: // other. ! 359: // If Error = IO_PENDING, wait for ! 360: // event handle to signal success. ! 361: if (lastError == ERROR_IO_PENDING) ! 362: { ! 363: WaitForSingleObject (hEventRd, (DWORD)-1); ! 364: ! 365: } ! 366: else // If pipe is broken, tell user and ! 367: { // break. ! 368: if (lastError == (DWORD)ERROR_BROKEN_PIPE) ! 369: MessageBox (hWndClient, ! 370: "The connection to this client has been broken.", ! 371: "", MB_OK); ! 372: else // Or flag unknown errors, and break. ! 373: { ! 374: wsprintf (Buf, "ReadFile() on pipe failed, see winerror.h error #%d", GetLastError()); ! 375: MessageBox (hWndClient, Buf, "Client: Debug", MB_OK); ! 376: } ! 377: break; ! 378: } ! 379: } // Manually update file pointer. ! 380: GetOverlappedResult (*hPipe, &OverLapRd, &bytesTrans, FALSE); ! 381: OverLapRd.Offset += bytesTrans; ! 382: ! 383: // NULL terminate string. ! 384: inBuf[bytesTrans] = '\0'; ! 385: ! 386: // Write message to larger edit field. ! 387: SendMessage (GetDlgItem (hWndClient, IDD_EDITREAD), ! 388: EM_REPLACESEL, ! 389: NULL, (LONG)inBuf); ! 390: // Add a new line. ! 391: SendMessage (GetDlgItem (hWndClient, IDD_EDITREAD), ! 392: EM_REPLACESEL, ! 393: NULL, (LONG)"\r\n"); ! 394: }while(1); ! 395: ! 396: // When pipe is broken, send quit ! 397: // messages to Client dialog box. ! 398: PostMessage (hWndClient, WM_GO_AWAY, 0,0); ! 399: ExitThread(0); ! 400: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.