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