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

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

unix.superglobalmegacorp.com

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