Annotation of mstools/samples/namepipe/npclient/client32.c, revision 1.1.1.1

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:   }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.