
/******************************************************************************\
*       This is a part of the Microsoft Source Code Samples. 
*       Copyright (C) 1993 Microsoft Corporation.
*       All rights reserved. 
*       This source code is only intended as a supplement to 
*       Microsoft Development Tools and/or WinHelp documentation.
*       See these sources for detailed information regarding the 
*       Microsoft samples programs.
\******************************************************************************/

/******************************************************************************\
*
*  PROGRAM:     ENUMPRT.C
*
*  PURPOSE:     Handles display of information returned by calls to
*               EnumPrinters, EnumPrinterDrivers. Info formatted and
*               displayed in a dialog box.
*
*
*  FUNTIONS:    EnumPrintersDlgProc      - handles messages for dialog
*               DisplayEnumPrintersInfo  - retrieves printer info
*               SetEnumPrintersDlgFields - formats & displays printer info
*               ComplexEnumPrintersLine  - formats bitfield printer info
*               EnumPrinterDriversDlgProc- handles messages for dialog
*               DisplayPrinterDriversInfo- retrieves, formats, & displays
*                                            printer info
*
\******************************************************************************/

#include <windows.h>
#include <string.h>
#include <drivinit.h>
#include <stdio.h>
#include <winspool.h>
#include "common.h"
#include "enumprt.h"



/******************************************************************************\
*
*  FUNCTION:    EnumPrintersDlgProc (standard dialog procedure INPUTS/RETURNS)
*
*  COMMENTS:    Processes messages for EnumPrinters dialog box
*
\******************************************************************************/

LRESULT CALLBACK EnumPrintersDlgProc (HWND   hwnd, UINT msg, WPARAM wParam,
                                      LPARAM lParam)
{
  switch (msg)
  {
    case WM_INITDIALOG:
    {
      BOOL bReturn;

      //
      // prompt user for EnumPrinters flags...
      //

      if (DialogBox (GetModuleHandle (NULL), (LPCTSTR) "EnumPrtOpt",
                     NULL, (DLGPROC) EnumPrintersOptionsDlgProc))
      {
        //
        // shove all the enum printer info in the list box
        //

        SetCursor (LoadCursor (NULL, IDC_WAIT));
        bReturn = DisplayEnumPrintersInfo (hwnd);
        SetCursor (LoadCursor (NULL, IDC_ARROW));

        if (!bReturn)

          EndDialog (hwnd, TRUE);

        else

          SetWindowText (hwnd, (LPCTSTR)"EnumPrinters");
      }
      else

          EndDialog (hwnd, TRUE);

      break;
    }

    case WM_COMMAND:

      switch (LOWORD (wParam))
      {
        case DID_OK:

          EndDialog (hwnd, TRUE);
          break;
      }
      break;
  }
  return 0;
}



/******************************************************************************\
*
*  FUNCTION:    EnumPrintersOptionsDlgProc (standard dlg proc INPUTS/RETURNS)
*
*  COMMENTS:    Processes messages for EnumPrtOpt dialog box
*
\******************************************************************************/

LRESULT CALLBACK EnumPrintersOptionsDlgProc (HWND   hwnd,   UINT msg,
                                             WPARAM wParam, LPARAM lParam)
{
  switch (msg)
  {
    case WM_INITDIALOG:

      gdwEnumFlags = 0;
      gszEnumName[0] = 0;
      break;

    case WM_COMMAND:

      switch (LOWORD (wParam))
      {
        case DID_OK:

          if (gdwEnumFlags)
          {
            if (gdwEnumFlags & PRINTER_ENUM_NAME)
            {
              GetDlgItemText (hwnd, DID_EDITTEXT, (LPTSTR)gszEnumName,
                              BUFSIZE);

              if (!strlen (gszEnumName))
              {
                MessageBox (hwnd,
                            (LPCTSTR) "Please enter a valid domain/server name",
                            (LPCTSTR) "", MB_OK);
                SetFocus (GetDlgItem (hwnd, DID_EDITTEXT));
                break;
              }
            }

            EndDialog (hwnd, TRUE);
          }

          else

            EndDialog (hwnd, FALSE);

          break;

        case DID_CANCEL:

          EndDialog (hwnd, FALSE);
          break;

        default:

          if (HIWORD(wParam) == BN_CLICKED)
          {
            DWORD dwControlId = (DWORD) LOWORD (wParam);

            if (gdwEnumFlags & dwControlId)
            {
              //
              // remove that flag, if PRINTER_ENUM_NAME disable edittext
              //

              gdwEnumFlags &= ~dwControlId;

              if (dwControlId & PRINTER_ENUM_NAME)
              {
                SetDlgItemText (hwnd, DID_EDITTEXT, (LPCTSTR)"");
                EnableWindow   (GetDlgItem (hwnd, DID_EDITTEXT), FALSE);
              }
            }

            else
            {
              //
              // add that flag, if PRINTER_ENUM_NAME enable edittext
              //

              gdwEnumFlags |= dwControlId;

              if (dwControlId & PRINTER_ENUM_NAME)

                EnableWindow (GetDlgItem (hwnd, DID_EDITTEXT), TRUE);
            }
          }
          break;
      }
  }
  return 0;
}



/******************************************************************************\
*
*  FUNCTION:    DisplayEnumPrintersInfo
*
*  INPUTS:      hwnd - handle of the EnumPrinters dialog box
*
*  RETURNS:     TRUE if successful,
*               FALSE otherwise
*
\******************************************************************************/

BOOL DisplayEnumPrintersInfo (HWND hwnd)
{
  DWORD  dwBytesNeeded;
  DWORD  dwPrtRet1, dwPrtRet2;
  DWORD  dwMaxPrt;
  LPTSTR lpName = gdwEnumFlags & PRINTER_ENUM_NAME ? gszEnumName : NULL;

  LPPRINTER_INFO_1 pPrtInfo1;
  LPPRINTER_INFO_2 pPrtInfo2;

  BOOL   bReturn = TRUE;

  //
  // get byte count needed for buffer, alloc buffer, the enum the printers
  //

  EnumPrinters (gdwEnumFlags, lpName, 1, NULL, 0, &dwBytesNeeded,
                     &dwPrtRet1);

  //
  // (simple error checking, if these work assume rest will too)
  //

  if (!(pPrtInfo1 = (LPPRINTER_INFO_1) LocalAlloc (LPTR, dwBytesNeeded)))
  {
    ErrMsgBox ("EnumPrinters/LocalAlloc failed", ERR_MOD_NAME);
    bReturn = FALSE;
    goto display_prts_info_done1;
  }

  if (!EnumPrinters (gdwEnumFlags, lpName, 1, (LPBYTE) pPrtInfo1,
                dwBytesNeeded, &dwBytesNeeded, &dwPrtRet1))
  {
    ErrMsgBox ("EnumPrinters failed", ERR_MOD_NAME);
    bReturn = FALSE;
    goto display_prts_info_done2;
  }

  //
  // get byte count needed for buffer, alloc buffer, the enum the printers
  //

  EnumPrinters (gdwEnumFlags, lpName, 2, NULL, 0, &dwBytesNeeded,
                &dwPrtRet2);

  pPrtInfo2 = (LPPRINTER_INFO_2) LocalAlloc (LPTR, dwBytesNeeded);

  EnumPrinters (gdwEnumFlags, lpName, 2, (LPBYTE) pPrtInfo2,
                dwBytesNeeded, &dwBytesNeeded, &dwPrtRet2);

  if (!dwPrtRet1 || !dwPrtRet2)
  {
    ErrMsgBox ("EnumPrinters returned 0 printers", "");
    bReturn = FALSE;
    goto display_prts_info_done3;
  }

  dwMaxPrt = dwPrtRet1 > dwPrtRet2 ? dwPrtRet2 : dwPrtRet1;

  SetEnumPrintersDlgFields (hwnd, dwMaxPrt, pPrtInfo1,
                            pPrtInfo2);

display_prts_info_done3:

  LocalFree (LocalHandle (pPrtInfo2));

display_prts_info_done2:

  LocalFree (LocalHandle (pPrtInfo1));

display_prts_info_done1:

  return bReturn;
}


/******************************************************************************\
*
*  FUNCTION:    SetEnumPrintersDlgFields
*
*  INPUTS:      hwnd      - handle of the EnumPrinters dialog box
*               dwMaxPrt  - number of elements in the following two arrays
*               pdisplay_prts_info1 - ptr to an array of PRINTER_INFO_1 structs
*               pdisplay_prts_info2 - ptr to an array of PRINTER_INFO_2 structs
*
*  COMMENTS:    This function formats the info returned by EnumPrinters()
*               into readable strings and inserts them in the listbox.
*
\******************************************************************************/

void SetEnumPrintersDlgFields (HWND hwnd, DWORD dwMaxPrt,
                               LPPRINTER_INFO_1 pPrtInfo1,
                               LPPRINTER_INFO_2 pPrtInfo2)
{
  char  buf[256];
  WORD  i;
  DWORD j;

  SendDlgItemMessage (hwnd, DID_LISTBOX, LB_RESETCONTENT, 0, 0);

  for (j = 0; j < dwMaxPrt; j++)
  {
    //
    // Stick PRINTER_INFO_1  data in listbox
    //

    SendDlgItemMessage (hwnd, DID_LISTBOX, LB_INSERTSTRING, (UINT)-1,
                        (LONG) gaEnumPrt[0]);

    outstr (gaEnumPrt[1], (pPrtInfo1 + j)->pDescription);
    outstr (gaEnumPrt[2], (pPrtInfo1 + j)->pName);
    outstr (gaEnumPrt[3], (pPrtInfo1 + j)->pComment);

    //
    // Stick PRINTER_INFO_2  data in listbox
    //

    SendDlgItemMessage (hwnd, DID_LISTBOX, LB_INSERTSTRING, (UINT)-1,
                        (LONG) gaEnumPrt[4]);

    outstr (gaEnumPrt[5],  (pPrtInfo2 + j)->pServerName);
    outstr (gaEnumPrt[6],  (pPrtInfo2 + j)->pPrinterName);
    outstr (gaEnumPrt[7],  (pPrtInfo2 + j)->pShareName);
    outstr (gaEnumPrt[8],  (pPrtInfo2 + j)->pPortName);
    outstr (gaEnumPrt[9],  (pPrtInfo2 + j)->pDriverName);
    outstr (gaEnumPrt[10], (pPrtInfo2 + j)->pComment);
    outstr (gaEnumPrt[11], (pPrtInfo2 + j)->pLocation);

    if ((pPrtInfo2 + j)->pDevMode)
    {
      DWORD dwFields;

      outstr (gaEnumPrt[12], "");
      outstr (gaEnumPrt[13], (pPrtInfo2 + j)->pDevMode->dmDeviceName);
      outnum (gaEnumPrt[14], (pPrtInfo2 + j)->pDevMode->dmSpecVersion);
      outnum (gaEnumPrt[15], (pPrtInfo2 + j)->pDevMode->dmDriverVersion);
      outnum (gaEnumPrt[16], (pPrtInfo2 + j)->pDevMode->dmSize);
      outnum (gaEnumPrt[17], (pPrtInfo2 + j)->pDevMode->dmDriverExtra);

      dwFields = (pPrtInfo2 + j)->pDevMode->dmFields;
      ComplexEnumPrintersLine (hwnd, gaEnumPrt[18], gaFields, MAX_FIELDS,
                               dwFields);

      if (dwFields & DM_ORIENTATION)

        ComplexEnumPrintersLine (hwnd, gaEnumPrt[19], gaOrientation,
                                 MAX_ORIENTATION,
                                 (DWORD)
                                 (pPrtInfo2+j)->pDevMode->dmOrientation);

      if (dwFields & DM_PAPERSIZE)

        ComplexEnumPrintersLine (hwnd, gaEnumPrt[20], gaPaperSize,
                                 MAX_PAPERSIZE,
                                 (DWORD)(pPrtInfo2 + j)->pDevMode->dmPaperSize);

      if (dwFields & DM_PAPERLENGTH)

        outnum (gaEnumPrt[21], (pPrtInfo2 + j)->pDevMode->dmPaperLength);


      if (dwFields & DM_PAPERWIDTH)

        outnum (gaEnumPrt[22], (pPrtInfo2 + j)->pDevMode->dmPaperWidth);

      if (dwFields & DM_SCALE)

        outnum (gaEnumPrt[23], (pPrtInfo2 + j)->pDevMode->dmScale);

      if (dwFields & DM_COPIES)

        outnum (gaEnumPrt[24], (pPrtInfo2 + j)->pDevMode->dmCopies);

      if (dwFields & DM_DEFAULTSOURCE)

        ComplexEnumPrintersLine (hwnd, gaEnumPrt[25], gaDefaultSource,
                                 MAX_DEFAULTSOURCE,
                               (DWORD)(pPrtInfo2+j)->pDevMode->dmDefaultSource);

      if (dwFields & DM_PRINTQUALITY)

        ComplexEnumPrintersLine (hwnd, gaEnumPrt[26], gaPrintQuality,
                                 MAX_PRINTQUALITY,
                                (DWORD)(pPrtInfo2+j)->pDevMode->dmPrintQuality);

      if (dwFields & DM_COLOR)

        ComplexEnumPrintersLine (hwnd, gaEnumPrt[27], gaColor,
                                 MAX_COLOR,
                                 (DWORD)(pPrtInfo2 + j)->pDevMode->dmColor);

      if (dwFields & DM_DUPLEX)

        ComplexEnumPrintersLine (hwnd, gaEnumPrt[28], gaDuplex,
                                 MAX_DUPLEX,
                                 (DWORD)(pPrtInfo2 + j)->pDevMode->dmDuplex);

      if (dwFields & DM_YRESOLUTION)

        outnum (gaEnumPrt[29], NULL);

      if (dwFields & DM_TTOPTION)

        outnum (gaEnumPrt[29], NULL);

      if (dwFields & DM_COLLATE)

        outnum (gaEnumPrt[30], NULL);

      if (dwFields & DM_FORMNAME)

        outnum (gaEnumPrt[31], NULL);
    }
    else
    {
      outstr (gaEnumPrt[12], NULL);
    }

    outstr (gaEnumPrt[33], (pPrtInfo2 + j)->pSepFile);
    outstr (gaEnumPrt[34], (pPrtInfo2 + j)->pPrintProcessor);
    outstr (gaEnumPrt[35], (pPrtInfo2 + j)->pDatatype);
    outstr (gaEnumPrt[36], (pPrtInfo2 + j)->pParameters);

    ComplexEnumPrintersLine (hwnd, gaEnumPrt[37], gaAttributes,
                             MAX_ATTRIBUTES,
                             (pPrtInfo2 + j)->Attributes);

    for (i = 0; i < MAX_PRIORITIES; i++)

      if ((pPrtInfo2 + j)->Priority & gaPriorities[i].dwValue)
      {
        outstr (gaEnumPrt[38], gaPriorities[i].szValue);
        break;
      }

    if (i == MAX_PRIORITIES)

      outnum (gaEnumPrt[39], (pPrtInfo2 + j)->Priority);

    outnum (gaEnumPrt[40], (pPrtInfo2 + j)->DefaultPriority);
    outnum (gaEnumPrt[41], (pPrtInfo2 + j)->StartTime);
    outnum (gaEnumPrt[42], (pPrtInfo2 + j)->UntilTime);

    ComplexEnumPrintersLine (hwnd, gaEnumPrt[43], gaStatus, MAX_STATUS,
                             (pPrtInfo2 + j)->Status);

    outnum (gaEnumPrt[44], (pPrtInfo2 + j)->cJobs);
    outnum (gaEnumPrt[45], (pPrtInfo2 + j)->AveragePPM);
  }
}



/******************************************************************************\
*
*  FUNCTION:    ComplexEnumPrintersLine
*
*  INPUTS:      hwnd        - handle of the EnumPrinters dialog box
*               pbuf        - pointer to buffer containing a cap-type
*                              string
*               pLkUp       - pointer to a CAPSLOOKUP table
*               iMaxEntries - # of enries in table pointed at by pLkUp
*               iValue      - an integer containing 1+ bit-value flags.
*
*  COMMENTS:    This function is used to expand an int containing
*               multiple bit-values into a set of strings which are
*               inserted into the DevCapsDlg listbox. The iValue
*               parameter is checked against each iIndex entry in the
*               CAPSLOOKUP table pointed at by pLkUp, and when matches
*               are found the corresponding (lpszValue) string is
*               inserted.
*
*               The buffer pointed to by pbuf will be destroyed.
*
\******************************************************************************/

void ComplexEnumPrintersLine (HWND hwnd, char  *pstr, ENUMPRTLOOKUP *pLkUp,
                              int iMaxEntries, DWORD  dwValue)
{
  char buf [BUFSIZE];
  int  i;
  BOOL bNewLine = FALSE;

  strcpy (buf, pstr);

  for (i = 0; i < iMaxEntries; i++)

    if (dwValue & (pLkUp + i)->dwValue)
    {
      if (bNewLine)
      {
        //
        // Keep the first symbolic constant on the same line as the
        //   cap type, eg:  "TECHNOLOGY:     DT_RASDISPLAY".
        //

        strcpy (buf, BLANKS);
        strcat (buf, (pLkUp + i)->szValue);
      }
      else
      {
        //
        // Put symbolic constant on new line, eg:
        //                  "                DT_RASPRINTER".
        //

        strcat (buf, (pLkUp + i)->szValue);
        bNewLine = TRUE;
      }
      SendDlgItemMessage (hwnd, DID_LISTBOX, LB_INSERTSTRING,
                          (UINT)-1, (LONG) buf);
   }
}



/******************************************************************************\
*
*  FUNCTION:    EnumPrinterDriversDlgProc (standard dlg proc INPUTS/RETURNS)
*
*  COMMENTS:    Processes messages for EnumPrinterDrivers dialog box
*
\******************************************************************************/

LRESULT CALLBACK EnumPrinterDriversDlgProc (HWND   hwnd,   UINT   msg,
                                            WPARAM wParam, LPARAM lParam)
{
  switch (msg)
  {
    case WM_INITDIALOG:
    {
      BOOL bReturn;

      SetCursor (LoadCursor (NULL, IDC_WAIT));
      bReturn = DisplayPrinterDriversInfo (hwnd);
      SetCursor (LoadCursor (NULL, IDC_ARROW));

      if (!bReturn)

        EndDialog (hwnd, TRUE);

      else

        SetWindowText (hwnd, (LPCTSTR) "EnumPrinterDrivers");

      break;
    }

    case WM_COMMAND:

      switch (LOWORD (wParam))
      {
        case DID_OK:

          EndDialog (hwnd, TRUE);

          return 1;
      }
      break;
  }
  return 0;
}



/******************************************************************************\
*
*  FUNCTION:    DisplayPrinterDriversInfo
*
*  INPUTS:      hwnd - handle of the EnumPrinterDrivers dialog box
*
*  RETURNS:     TRUE if successful,
*               FALSE otherwise
*
*  COMMENTS:    Retrieves EnumPrinterDrivers info, formats, & inserts
*               in listbox.
*
\******************************************************************************/

BOOL DisplayPrinterDriversInfo (HWND hwnd)
{
  DWORD         dwBytesNeeded, dwDrvRet, i;
  DRIVER_INFO_1 *pDriverInfo1;
  DRIVER_INFO_2 *pDriverInfo2;
  char          buf[BUFSIZE];
  BOOL          bReturn = TRUE;

  //
  // get byte count needed for buffer, alloc buffer, the enum the drivers
  //

  EnumPrinterDrivers ((LPTSTR) NULL, (LPTSTR) NULL, 1, NULL,
                      0, &dwBytesNeeded, &dwDrvRet);

  //
  // simple error checking, if these work assume rest will too
  //

  if (!(pDriverInfo1 = (DRIVER_INFO_1 *) LocalAlloc (LPTR, dwBytesNeeded)))
  {
    ErrMsgBox ("LocalAlloc failed", ERR_MOD_NAME);
    bReturn = FALSE;
    goto display_prt_drvs_info_done1;
  }

  if (!EnumPrinterDrivers ((LPTSTR) NULL, (LPTSTR) NULL, 1,
                           (LPBYTE) pDriverInfo1, dwBytesNeeded, &dwBytesNeeded,
                           &dwDrvRet))
  {
    ErrMsgBox ("EnumPrinterDrivers returned 0 drivers", ERR_MOD_NAME);
    bReturn = FALSE;
    goto display_prt_drvs_info_done2;
  }

  EnumPrinterDrivers ((LPTSTR) NULL,(LPTSTR) NULL, 2, NULL,
                      0, &dwBytesNeeded, &dwDrvRet);

  pDriverInfo2 = (DRIVER_INFO_2 *) LocalAlloc (LPTR, dwBytesNeeded);

  EnumPrinterDrivers ((LPTSTR) NULL, (LPTSTR) NULL, 2,
                      (LPBYTE) pDriverInfo2, dwBytesNeeded, &dwBytesNeeded,
                      &dwDrvRet);

  if (!dwDrvRet)
  {
    ErrMsgBox ("EnumPrinterDrivers returned 0 drivers", "");
    bReturn = FALSE;
    goto display_prt_drvs_info_done3;
  }

  //
  // insert formatted info into listbox
  //

  for (i = 0; i < dwDrvRet; i++)
  {
    sprintf (buf, gaDriverInfo[0]);
    outstr3();

    sprintf (buf, gaDriverInfo[1], (pDriverInfo1 + i)->pName);
    outstr3();

    sprintf (buf, gaDriverInfo[2]);
    outstr3();

    sprintf (buf, gaDriverInfo[3], (pDriverInfo2 + i)->cVersion);
    outstr3();

    sprintf (buf, gaDriverInfo[4], (pDriverInfo2 + i)->pName);
    outstr3();

    sprintf (buf, gaDriverInfo[5], (pDriverInfo2 + i)->pEnvironment);
    outstr3();

    sprintf (buf, gaDriverInfo[6], (pDriverInfo2 + i)->pDriverPath);
    outstr3();

    sprintf (buf, gaDriverInfo[7], (pDriverInfo2 + i)->pDataFile);
    outstr3();

    sprintf (buf, gaDriverInfo[8], (pDriverInfo2 + i)->pConfigFile);
    outstr3();

  }

display_prt_drvs_info_done3:

  LocalFree (LocalHandle (pDriverInfo2));

display_prt_drvs_info_done2:

  LocalFree (LocalHandle (pDriverInfo1));

display_prt_drvs_info_done1:

  return bReturn;
}
