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

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

unix.superglobalmegacorp.com

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