ENUMPRT.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:20k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /******************************************************************************
  2. *       This is a part of the Microsoft Source Code Samples. 
  3. *       Copyright (C) 1993-1997 Microsoft Corporation.
  4. *       All rights reserved. 
  5. *       This source code is only intended as a supplement to 
  6. *       Microsoft Development Tools and/or WinHelp documentation.
  7. *       See these sources for detailed information regarding the 
  8. *       Microsoft samples programs.
  9. ******************************************************************************/
  10. /******************************************************************************
  11. *
  12. *  PROGRAM:     ENUMPRT.C
  13. *
  14. *  PURPOSE:     Handles display of information returned by calls to
  15. *               EnumPrinters, EnumPrinterDrivers. Info formatted and
  16. *               displayed in a dialog box.
  17. *
  18. *
  19. *  FUNTIONS:    EnumPrintersDlgProc      - handles messages for dialog
  20. *               DisplayEnumPrintersInfo  - retrieves printer info
  21. *               SetEnumPrintersDlgFields - formats & displays printer info
  22. *               ComplexEnumPrintersLine  - formats bitfield printer info
  23. *               EnumPrinterDriversDlgProc- handles messages for dialog
  24. *               DisplayPrinterDriversInfo- retrieves, formats, & displays
  25. *                                            printer info
  26. *
  27. ******************************************************************************/
  28. #include <windows.h>
  29. #include <string.h>
  30. #include <drivinit.h>
  31. #include <stdio.h>
  32. #include <winspool.h>
  33. #include "common.h"
  34. #include "enumprt.h"
  35. /******************************************************************************
  36. *
  37. *  FUNCTION:    EnumPrintersDlgProc (standard dialog procedure INPUTS/RETURNS)
  38. *
  39. *  COMMENTS:    Processes messages for EnumPrinters dialog box
  40. *
  41. ******************************************************************************/
  42. LRESULT CALLBACK EnumPrintersDlgProc (HWND   hwnd, UINT msg, WPARAM wParam,
  43.                                       LPARAM lParam)
  44. {
  45.   switch (msg)
  46.   {
  47.     case WM_INITDIALOG:
  48.     {
  49.       BOOL bReturn;
  50.       //
  51.       // prompt user for EnumPrinters flags...
  52.       //
  53.       if (DialogBox (GetModuleHandle (NULL), (LPCTSTR) "EnumPrtOpt",
  54.                      NULL, (DLGPROC) EnumPrintersOptionsDlgProc))
  55.       {
  56.         //
  57.         // shove all the enum printer info in the list box
  58.         //
  59.         SetCursor (LoadCursor (NULL, IDC_WAIT));
  60.         bReturn = DisplayEnumPrintersInfo (hwnd);
  61.         SetCursor (LoadCursor (NULL, IDC_ARROW));
  62.         if (!bReturn)
  63.           EndDialog (hwnd, TRUE);
  64.         else
  65.           SetWindowText (hwnd, (LPCTSTR)"EnumPrinters");
  66.       }
  67.       else
  68.           EndDialog (hwnd, TRUE);
  69.       break;
  70.     }
  71.     case WM_COMMAND:
  72.       switch (LOWORD (wParam))
  73.       {
  74.         case DID_OK:
  75.           EndDialog (hwnd, TRUE);
  76.           break;
  77.       }
  78.       break;
  79.   }
  80.   return 0;
  81. }
  82. /******************************************************************************
  83. *
  84. *  FUNCTION:    EnumPrintersOptionsDlgProc (standard dlg proc INPUTS/RETURNS)
  85. *
  86. *  COMMENTS:    Processes messages for EnumPrtOpt dialog box
  87. *
  88. ******************************************************************************/
  89. LRESULT CALLBACK EnumPrintersOptionsDlgProc (HWND   hwnd,   UINT msg,
  90.                                              WPARAM wParam, LPARAM lParam)
  91. {
  92.   switch (msg)
  93.   {
  94.     case WM_INITDIALOG:
  95.       gdwEnumFlags = 0;
  96.       gszEnumName[0] = 0;
  97.       break;
  98.     case WM_COMMAND:
  99.       switch (LOWORD (wParam))
  100.       {
  101.         case DID_OK:
  102.           if (gdwEnumFlags)
  103.           {
  104.             if (gdwEnumFlags & PRINTER_ENUM_NAME)
  105.             {
  106.               GetDlgItemText (hwnd, DID_EDITTEXT, (LPTSTR)gszEnumName,
  107.                               BUFSIZE);
  108. #ifdef FORCE_VALID_NAME
  109.               if (!strlen (gszEnumName))
  110.               {
  111.                 MessageBox (hwnd,
  112.                             (LPCTSTR) GetStringRes(IDS_ASKDOMSRVNM),
  113.                             (LPCTSTR) "", MB_OK);
  114.                 SetFocus (GetDlgItem (hwnd, DID_EDITTEXT));
  115.                 break;
  116.               }
  117. #endif
  118.             }
  119.             EndDialog (hwnd, TRUE);
  120.           }
  121.           else
  122.             EndDialog (hwnd, FALSE);
  123.           break;
  124.         case DID_CANCEL:
  125.           EndDialog (hwnd, FALSE);
  126.           break;
  127.         default:
  128.           if (HIWORD(wParam) == BN_CLICKED)
  129.           {
  130.             DWORD dwControlId = (DWORD) LOWORD (wParam);
  131.             if (gdwEnumFlags & dwControlId)
  132.             {
  133.               //
  134.               // remove that flag, if PRINTER_ENUM_NAME disable edittext
  135.               //
  136.               gdwEnumFlags &= ~dwControlId;
  137.               if (dwControlId & PRINTER_ENUM_NAME)
  138.               {
  139.                 SetDlgItemText (hwnd, DID_EDITTEXT, (LPCTSTR)"");
  140.                 EnableWindow   (GetDlgItem (hwnd, DID_EDITTEXT), FALSE);
  141.               }
  142.             }
  143.             else
  144.             {
  145.               //
  146.               // add that flag, if PRINTER_ENUM_NAME enable edittext
  147.               //
  148.               gdwEnumFlags |= dwControlId;
  149.               if (dwControlId & PRINTER_ENUM_NAME)
  150.                 EnableWindow (GetDlgItem (hwnd, DID_EDITTEXT), TRUE);
  151.             }
  152.           }
  153.           break;
  154.       }
  155.   }
  156.   return 0;
  157. }
  158. /******************************************************************************
  159. *
  160. *  FUNCTION:    DisplayEnumPrintersInfo
  161. *
  162. *  INPUTS:      hwnd - handle of the EnumPrinters dialog box
  163. *
  164. *  RETURNS:     TRUE if successful,
  165. *               FALSE otherwise
  166. *
  167. ******************************************************************************/
  168. BOOL DisplayEnumPrintersInfo (HWND hwnd)
  169. {
  170.   DWORD  dwBytesNeeded;
  171.   DWORD  dwPrtRet1, dwPrtRet2;
  172.   DWORD  dwMaxPrt;
  173.   LPTSTR lpName = gdwEnumFlags & PRINTER_ENUM_NAME ? gszEnumName : NULL;
  174.   LPPRINTER_INFO_1 pPrtInfo1;
  175.   LPPRINTER_INFO_2 pPrtInfo2;
  176.   BOOL   bReturn = TRUE;
  177.   //
  178.   // get byte count needed for buffer, alloc buffer, the enum the printers
  179.   //
  180.   EnumPrinters (gdwEnumFlags, lpName, 1, NULL, 0, &dwBytesNeeded,
  181.                      &dwPrtRet1);
  182.   //
  183.   // (simple error checking, if these work assume rest will too)
  184.   //
  185.   if (!(pPrtInfo1 = (LPPRINTER_INFO_1) LocalAlloc (LPTR, dwBytesNeeded)))
  186.   {
  187.     ErrMsgBox (GetStringRes(IDS_ENUMPRTLALLOCFAIL), GetStringRes2(ERR_MOD_NAME));
  188.     bReturn = FALSE;
  189.     goto display_prts_info_done1;
  190.   }
  191.   if (!EnumPrinters (gdwEnumFlags, lpName, 1, (LPBYTE) pPrtInfo1,
  192.                 dwBytesNeeded, &dwBytesNeeded, &dwPrtRet1))
  193.   {
  194.     TCHAR  tcBuffer[256];
  195.     wsprintf (tcBuffer, "%s, 1, GetLastError: %d", GetStringRes2(ERR_MOD_NAME), GetLastError());
  196.     ErrMsgBox (GetStringRes(IDS_ENUMPRT1FAIL), tcBuffer);
  197.     bReturn = FALSE;
  198.     goto display_prts_info_done2;
  199.   }
  200.   //
  201.   // If we don't get any printers from the Level == 1 call, there is
  202.   //  no point in continuing... report it, free memory, and return.
  203.   //
  204.   if (dwPrtRet1 == 0)
  205.   {
  206.     MessageBox (ghwndMain,
  207.                (LPCTSTR) "EnumPrinters (Level == 1) returned 0 printers",
  208.                GetStringRes2(ERR_MOD_NAME),
  209.                MB_OK);
  210.     bReturn = FALSE;
  211.     goto display_prts_info_done2;
  212.   }
  213.   //
  214.   // Call EnumPrinters again with Level == 2.
  215.   //
  216.   // get byte count needed for buffer, alloc buffer, the enum the printers
  217.   //
  218.   EnumPrinters (gdwEnumFlags, lpName, 2, NULL, 0, &dwBytesNeeded,
  219.                 &dwPrtRet2);
  220.   pPrtInfo2 = (LPPRINTER_INFO_2) LocalAlloc (LPTR, dwBytesNeeded);
  221.   EnumPrinters (gdwEnumFlags, lpName, 2, (LPBYTE) pPrtInfo2,
  222.                 dwBytesNeeded, &dwBytesNeeded, &dwPrtRet2);
  223.   //
  224.   // Calling EnumPrinters with Level == 2 frequently returns 0 printers.
  225.   //  If so display only the PRINTER_INFO_1 structures we got before.
  226.   //
  227.   if (dwPrtRet2 == 0)
  228.   {
  229.     dwMaxPrt = dwPrtRet1;
  230.     pPrtInfo2 = NULL;
  231.   } else {
  232.   dwMaxPrt = dwPrtRet1 > dwPrtRet2 ? dwPrtRet2 : dwPrtRet1;
  233.   }
  234.   SetEnumPrintersDlgFields (hwnd, dwMaxPrt, pPrtInfo1, pPrtInfo2);
  235.   LocalFree (LocalHandle (pPrtInfo2));
  236. display_prts_info_done2:
  237.   LocalFree (LocalHandle (pPrtInfo1));
  238. display_prts_info_done1:
  239.   return bReturn;
  240. }
  241. /******************************************************************************
  242. *
  243. *  FUNCTION:    SetEnumPrintersDlgFields
  244. *
  245. *  INPUTS:      hwnd      - handle of the EnumPrinters dialog box
  246. *               dwMaxPrt  - number of elements in the following two arrays
  247. *               pdisplay_prts_info1 - ptr to an array of PRINTER_INFO_1 structs
  248. *               pdisplay_prts_info2 - ptr to an array of PRINTER_INFO_2 structs
  249. *
  250. *  COMMENTS:    This function formats the info returned by EnumPrinters()
  251. *               into readable strings and inserts them in the listbox.
  252. *
  253. ******************************************************************************/
  254. void SetEnumPrintersDlgFields (HWND hwnd, DWORD dwMaxPrt,
  255.                                LPPRINTER_INFO_1 pPrtInfo1,
  256.                                LPPRINTER_INFO_2 pPrtInfo2)
  257. {
  258.   char  buf[256];
  259.   WORD  i;
  260.   DWORD j;
  261.   SendDlgItemMessage (hwnd, DID_LISTBOX, LB_RESETCONTENT, 0, 0);
  262.   for (j = 0; j < dwMaxPrt; j++) {
  263.     //
  264.     // Stick PRINTER_INFO_1  data in listbox
  265.     //
  266.     SendDlgItemMessage (hwnd, DID_LISTBOX, LB_INSERTSTRING, (UINT)-1,
  267.                         (LONG) gaEnumPrt[0]);
  268.     outstr (gaEnumPrt[1], (pPrtInfo1 + j)->pDescription);
  269.     outstr (gaEnumPrt[2], (pPrtInfo1 + j)->pName);
  270.     outstr (gaEnumPrt[3], (pPrtInfo1 + j)->pComment);
  271.     //
  272.     // Stick PRINTER_INFO_2  data in listbox
  273.     //
  274.     if (pPrtInfo2 != NULL) {
  275.     SendDlgItemMessage (hwnd, DID_LISTBOX, LB_INSERTSTRING, (UINT)-1,
  276.                         (LONG) gaEnumPrt[4]);
  277.     outstr (gaEnumPrt[5],  (pPrtInfo2 + j)->pServerName);
  278.     outstr (gaEnumPrt[6],  (pPrtInfo2 + j)->pPrinterName);
  279.     outstr (gaEnumPrt[7],  (pPrtInfo2 + j)->pShareName);
  280.     outstr (gaEnumPrt[8],  (pPrtInfo2 + j)->pPortName);
  281.     outstr (gaEnumPrt[9],  (pPrtInfo2 + j)->pDriverName);
  282.     outstr (gaEnumPrt[10], (pPrtInfo2 + j)->pComment);
  283.     outstr (gaEnumPrt[11], (pPrtInfo2 + j)->pLocation);
  284.     if ((pPrtInfo2 + j)->pDevMode)
  285.     {
  286.       DWORD dwFields;
  287.       outstr (gaEnumPrt[12], "");
  288.       outstr (gaEnumPrt[13], (pPrtInfo2 + j)->pDevMode->dmDeviceName);
  289.       outnum (gaEnumPrt[14], (pPrtInfo2 + j)->pDevMode->dmSpecVersion);
  290.       outnum (gaEnumPrt[15], (pPrtInfo2 + j)->pDevMode->dmDriverVersion);
  291.       outnum (gaEnumPrt[16], (pPrtInfo2 + j)->pDevMode->dmSize);
  292.       outnum (gaEnumPrt[17], (pPrtInfo2 + j)->pDevMode->dmDriverExtra);
  293.       dwFields = (pPrtInfo2 + j)->pDevMode->dmFields;
  294.       ComplexEnumPrintersLine (hwnd, gaEnumPrt[18], gaFields, MAX_FIELDS,
  295.                                dwFields);
  296.       if (dwFields & DM_ORIENTATION)
  297.         ComplexEnumPrintersLine (hwnd, gaEnumPrt[19], gaOrientation,
  298.                                  MAX_ORIENTATION,
  299.                                  (DWORD)
  300.                                  (pPrtInfo2+j)->pDevMode->dmOrientation);
  301.       if (dwFields & DM_PAPERSIZE)
  302.         ComplexEnumPrintersLine (hwnd, gaEnumPrt[20], gaPaperSize,
  303.                                  MAX_PAPERSIZE,
  304.                                  (DWORD)(pPrtInfo2 + j)->pDevMode->dmPaperSize);
  305.       if (dwFields & DM_PAPERLENGTH)
  306.         outnum (gaEnumPrt[21], (pPrtInfo2 + j)->pDevMode->dmPaperLength);
  307.       if (dwFields & DM_PAPERWIDTH)
  308.         outnum (gaEnumPrt[22], (pPrtInfo2 + j)->pDevMode->dmPaperWidth);
  309.       if (dwFields & DM_SCALE)
  310.         outnum (gaEnumPrt[23], (pPrtInfo2 + j)->pDevMode->dmScale);
  311.       if (dwFields & DM_COPIES)
  312.         outnum (gaEnumPrt[24], (pPrtInfo2 + j)->pDevMode->dmCopies);
  313.       if (dwFields & DM_DEFAULTSOURCE)
  314.         ComplexEnumPrintersLine (hwnd, gaEnumPrt[25], gaDefaultSource,
  315.                                  MAX_DEFAULTSOURCE,
  316.                                (DWORD)(pPrtInfo2+j)->pDevMode->dmDefaultSource);
  317.       if (dwFields & DM_PRINTQUALITY)
  318.         ComplexEnumPrintersLine (hwnd, gaEnumPrt[26], gaPrintQuality,
  319.                                  MAX_PRINTQUALITY,
  320.                                 (DWORD)(pPrtInfo2+j)->pDevMode->dmPrintQuality);
  321.       if (dwFields & DM_COLOR)
  322.         ComplexEnumPrintersLine (hwnd, gaEnumPrt[27], gaColor,
  323.                                  MAX_COLOR,
  324.                                  (DWORD)(pPrtInfo2 + j)->pDevMode->dmColor);
  325.       if (dwFields & DM_DUPLEX)
  326.         ComplexEnumPrintersLine (hwnd, gaEnumPrt[28], gaDuplex,
  327.                                  MAX_DUPLEX,
  328.                                  (DWORD)(pPrtInfo2 + j)->pDevMode->dmDuplex);
  329.       if (dwFields & DM_YRESOLUTION)
  330.         outnum (gaEnumPrt[29], NULL);
  331.       if (dwFields & DM_TTOPTION)
  332.         outnum (gaEnumPrt[29], NULL);
  333.       if (dwFields & DM_COLLATE)
  334.         outnum (gaEnumPrt[30], NULL);
  335.       if (dwFields & DM_FORMNAME)
  336.         outnum (gaEnumPrt[31], NULL);
  337.     }
  338.     else
  339.     {
  340.       outstr (gaEnumPrt[12], NULL);
  341.     }
  342.     outstr (gaEnumPrt[33], (pPrtInfo2 + j)->pSepFile);
  343.     outstr (gaEnumPrt[34], (pPrtInfo2 + j)->pPrintProcessor);
  344.     outstr (gaEnumPrt[35], (pPrtInfo2 + j)->pDatatype);
  345.     outstr (gaEnumPrt[36], (pPrtInfo2 + j)->pParameters);
  346.     ComplexEnumPrintersLine (hwnd, gaEnumPrt[37], gaAttributes,
  347.                              MAX_ATTRIBUTES,
  348.                              (pPrtInfo2 + j)->Attributes);
  349.     for (i = 0; i < MAX_PRIORITIES; i++)
  350.       if ((pPrtInfo2 + j)->Priority & gaPriorities[i].dwValue)
  351.       {
  352.         outstr (gaEnumPrt[38], gaPriorities[i].szValue);
  353.         break;
  354.       }
  355.     if (i == MAX_PRIORITIES)
  356.       outnum (gaEnumPrt[39], (pPrtInfo2 + j)->Priority);
  357.     outnum (gaEnumPrt[40], (pPrtInfo2 + j)->DefaultPriority);
  358.     outnum (gaEnumPrt[41], (pPrtInfo2 + j)->StartTime);
  359.     outnum (gaEnumPrt[42], (pPrtInfo2 + j)->UntilTime);
  360.     ComplexEnumPrintersLine (hwnd, gaEnumPrt[43], gaStatus, MAX_STATUS,
  361.                              (pPrtInfo2 + j)->Status);
  362.     outnum (gaEnumPrt[44], (pPrtInfo2 + j)->cJobs);
  363.     outnum (gaEnumPrt[45], (pPrtInfo2 + j)->AveragePPM);
  364.   }
  365. }
  366. }
  367. /******************************************************************************
  368. *
  369. *  FUNCTION:    ComplexEnumPrintersLine
  370. *
  371. *  INPUTS:      hwnd        - handle of the EnumPrinters dialog box
  372. *               pbuf        - pointer to buffer containing a cap-type
  373. *                              string
  374. *               pLkUp       - pointer to a CAPSLOOKUP table
  375. *               iMaxEntries - # of enries in table pointed at by pLkUp
  376. *               iValue      - an integer containing 1+ bit-value flags.
  377. *
  378. *  COMMENTS:    This function is used to expand an int containing
  379. *               multiple bit-values into a set of strings which are
  380. *               inserted into the DevCapsDlg listbox. The iValue
  381. *               parameter is checked against each iIndex entry in the
  382. *               CAPSLOOKUP table pointed at by pLkUp, and when matches
  383. *               are found the corresponding (lpszValue) string is
  384. *               inserted.
  385. *
  386. *               The buffer pointed to by pbuf will be destroyed.
  387. *
  388. ******************************************************************************/
  389. void ComplexEnumPrintersLine (HWND hwnd, char  *pstr, ENUMPRTLOOKUP *pLkUp,
  390.                               int iMaxEntries, DWORD  dwValue)
  391. {
  392.   char buf [BUFSIZE];
  393.   int  i;
  394.   BOOL bNewLine = FALSE;
  395.   strcpy (buf, pstr);
  396.   for (i = 0; i < iMaxEntries; i++)
  397.     if (dwValue & (pLkUp + i)->dwValue)
  398.     {
  399.       if (bNewLine)
  400.       {
  401.         //
  402.         // Keep the first symbolic constant on the same line as the
  403.         //   cap type, eg:  "TECHNOLOGY:     DT_RASDISPLAY".
  404.         //
  405.         strcpy (buf, BLANKS);
  406.         strcat (buf, (pLkUp + i)->szValue);
  407.       }
  408.       else
  409.       {
  410.         //
  411.         // Put symbolic constant on new line, eg:
  412.         //                  "                DT_RASPRINTER".
  413.         //
  414.         strcat (buf, (pLkUp + i)->szValue);
  415.         bNewLine = TRUE;
  416.       }
  417.       SendDlgItemMessage (hwnd, DID_LISTBOX, LB_INSERTSTRING,
  418.                           (UINT)-1, (LONG) buf);
  419.    }
  420. }
  421. /******************************************************************************
  422. *
  423. *  FUNCTION:    EnumPrinterDriversDlgProc (standard dlg proc INPUTS/RETURNS)
  424. *
  425. *  COMMENTS:    Processes messages for EnumPrinterDrivers dialog box
  426. *
  427. ******************************************************************************/
  428. LRESULT CALLBACK EnumPrinterDriversDlgProc (HWND   hwnd,   UINT   msg,
  429.                                             WPARAM wParam, LPARAM lParam)
  430. {
  431.   switch (msg)
  432.   {
  433.     case WM_INITDIALOG:
  434.     {
  435.       BOOL bReturn;
  436.       SetCursor (LoadCursor (NULL, IDC_WAIT));
  437.       bReturn = DisplayPrinterDriversInfo (hwnd);
  438.       SetCursor (LoadCursor (NULL, IDC_ARROW));
  439.       if (!bReturn)
  440.         EndDialog (hwnd, TRUE);
  441.       else
  442.         SetWindowText (hwnd, (LPCTSTR) "EnumPrinterDrivers");
  443.       break;
  444.     }
  445.     case WM_COMMAND:
  446.       switch (LOWORD (wParam))
  447.       {
  448.         case DID_OK:
  449.           EndDialog (hwnd, TRUE);
  450.           return 1;
  451.       }
  452.       break;
  453.   }
  454.   return 0;
  455. }
  456. /******************************************************************************
  457. *
  458. *  FUNCTION:    DisplayPrinterDriversInfo
  459. *
  460. *  INPUTS:      hwnd - handle of the EnumPrinterDrivers dialog box
  461. *
  462. *  RETURNS:     TRUE if successful,
  463. *               FALSE otherwise
  464. *
  465. *  COMMENTS:    Retrieves EnumPrinterDrivers info, formats, & inserts
  466. *               in listbox.
  467. *
  468. ******************************************************************************/
  469. BOOL DisplayPrinterDriversInfo (HWND hwnd)
  470. {
  471.   DWORD         dwBytesNeeded, dwDrvRet, i;
  472.   DRIVER_INFO_1 *pDriverInfo1;
  473.   DRIVER_INFO_2 *pDriverInfo2;
  474.   char          buf[BUFSIZE];
  475.   BOOL          bReturn = TRUE;
  476.   //
  477.   // get byte count needed for buffer, alloc buffer, the enum the drivers
  478.   //
  479.   EnumPrinterDrivers ((LPTSTR) NULL, (LPTSTR) NULL, 1, NULL,
  480.                       0, &dwBytesNeeded, &dwDrvRet);
  481.   //
  482.   // simple error checking, if these work assume rest will too
  483.   //
  484.   if (!(pDriverInfo1 = (DRIVER_INFO_1 *) LocalAlloc (LPTR, dwBytesNeeded)))
  485.   {
  486.     ErrMsgBox (GetStringRes(IDS_LALLOCFAIL), GetStringRes2(ERR_MOD_NAME));
  487.     bReturn = FALSE;
  488.     goto display_prt_drvs_info_done1;
  489.   }
  490.   if (!EnumPrinterDrivers ((LPTSTR) NULL, (LPTSTR) NULL, 1,
  491.                            (LPBYTE) pDriverInfo1, dwBytesNeeded, &dwBytesNeeded,
  492.                            &dwDrvRet))
  493.   {
  494.     ErrMsgBox (GetStringRes(IDS_ENUMPRTDRVRET0), GetStringRes2(ERR_MOD_NAME));
  495.     bReturn = FALSE;
  496.     goto display_prt_drvs_info_done2;
  497.   }
  498.   EnumPrinterDrivers ((LPTSTR) NULL,(LPTSTR) NULL, 2, NULL,
  499.                       0, &dwBytesNeeded, &dwDrvRet);
  500.   pDriverInfo2 = (DRIVER_INFO_2 *) LocalAlloc (LPTR, dwBytesNeeded);
  501.   EnumPrinterDrivers ((LPTSTR) NULL, (LPTSTR) NULL, 2,
  502.                       (LPBYTE) pDriverInfo2, dwBytesNeeded, &dwBytesNeeded,
  503.                       &dwDrvRet);
  504.   if (!dwDrvRet)
  505.   {
  506.     ErrMsgBox (GetStringRes(IDS_ENUMPRTDRVRET0), "");
  507.     bReturn = FALSE;
  508.     goto display_prt_drvs_info_done3;
  509.   }
  510.   //
  511.   // insert formatted info into listbox
  512.   //
  513.   for (i = 0; i < dwDrvRet; i++)
  514.   {
  515.     sprintf (buf, gaDriverInfo[0]);
  516.     outstr3();
  517.     sprintf (buf, gaDriverInfo[1], (pDriverInfo1 + i)->pName);
  518.     outstr3();
  519.     sprintf (buf, gaDriverInfo[2]);
  520.     outstr3();
  521.     sprintf (buf, gaDriverInfo[3], (pDriverInfo2 + i)->cVersion);
  522.     outstr3();
  523.     sprintf (buf, gaDriverInfo[4], (pDriverInfo2 + i)->pName);
  524.     outstr3();
  525.     sprintf (buf, gaDriverInfo[5], (pDriverInfo2 + i)->pEnvironment);
  526.     outstr3();
  527.     sprintf (buf, gaDriverInfo[6], (pDriverInfo2 + i)->pDriverPath);
  528.     outstr3();
  529.     sprintf (buf, gaDriverInfo[7], (pDriverInfo2 + i)->pDataFile);
  530.     outstr3();
  531.     sprintf (buf, gaDriverInfo[8], (pDriverInfo2 + i)->pConfigFile);
  532.     outstr3();
  533.   }
  534. display_prt_drvs_info_done3:
  535.   LocalFree (LocalHandle (pDriverInfo2));
  536. display_prt_drvs_info_done2:
  537.   LocalFree (LocalHandle (pDriverInfo1));
  538. display_prt_drvs_info_done1:
  539.   return bReturn;
  540. }