wspool.c
Upload User: caisha3
Upload Date: 2013-09-21
Package Size: 208739k
Code Size: 16k
Category:

Windows Develop

Development Platform:

Visual C++

  1. /*++
  2.  *
  3.  *  WOW v1.0
  4.  *
  5.  *  Copyright (c) 1991, Microsoft Corporation
  6.  *
  7.  *  WSPOOL.C
  8.  *  WOW32 printer spooler support routines
  9.  *
  10.  *  These routines help a Win 3.0 task to use the print spooler apis. These
  11.  *  apis were exposed by DDK in Win 3.1.
  12.  *
  13.  *  History:
  14.  *  Created 1-July-1993 by Chandan Chauhan (ChandanC)
  15.  *
  16. --*/
  17. #include "precomp.h"
  18. #pragma hdrstop
  19. #include <winspool.h>
  20. extern WORD gUser16hInstance;
  21. VOID WOWSpoolerThread(WOWSPOOL *lpwowSpool);
  22. WORD gprn16 = 0x100;  // Global spooler job # (can be anything > 0)
  23. MODNAME(wspool.c);
  24. LPDEVMODE GetDefaultDevMode32(LPSTR szDriver)
  25. {
  26.     LONG        cbDevMode;
  27.     LPDEVMODE   lpDevMode = NULL;
  28.     if (szDriver != NULL) {
  29.         if (!(*spoolerapis[WOW_EXTDEVICEMODE].lpfn)) {
  30.             if (!LoadLibraryAndGetProcAddresses("WINSPOOL.DRV", spoolerapis, WOW_SPOOLERAPI_COUNT)) {
  31.                 goto LeaveGetDefaultDevMode32;
  32.             }
  33.         }
  34.         if ((cbDevMode = (*spoolerapis[WOW_EXTDEVICEMODE].lpfn)(NULL, NULL, NULL, szDriver, NULL, NULL, NULL, 0)) > 0) {
  35.             if ((lpDevMode = (LPDEVMODE) malloc_w(cbDevMode)) != NULL) {
  36.                 if ((*spoolerapis[WOW_EXTDEVICEMODE].lpfn)(NULL, NULL, lpDevMode, szDriver, NULL, NULL, NULL, DM_COPY) != IDOK) {
  37.                     free_w(lpDevMode);
  38.                     lpDevMode = NULL;
  39.                 }
  40.             }
  41.         }
  42. LeaveGetDefaultDevMode32:
  43.         if (!lpDevMode) {
  44.                 LOGDEBUG(0,("WOW::GetDefaultDevMode32: Unable to get default DevModen"));
  45.         }
  46.     }
  47.     return(lpDevMode);
  48. }
  49. ULONG FASTCALL   WG32OpenJob (PVDMFRAME pFrame)
  50. {
  51.     INT         len;
  52.     PSZ         psz1      = NULL;
  53.     PSZ         psz2      = NULL;
  54.     PSZ         pszDriver = NULL;
  55.     ULONG       ul=0;
  56.     DOC_INFO_1  DocInfo1;
  57.     HANDLE      hnd;
  58.     register    POPENJOB16 parg16;
  59.     PRINTER_DEFAULTS  PrinterDefault;
  60.     PPRINTER_DEFAULTS pPrinterDefault = NULL;
  61.     GETARGPTR(pFrame, sizeof(OPENJOB16), parg16);
  62.     // save off the 16-bit params now since this could callback into a 16-bit
  63.     // fax driver & cause 16-bit memory to move.
  64.     if(parg16->f1) {
  65.         if(psz1 = malloc_w_strcpy_vp16to32(parg16->f1, FALSE, 0)) {
  66.             len = strlen(psz1);
  67.             pszDriver = malloc_w(max(len, 40));
  68.         }
  69.     }
  70.     if(parg16->f2) {
  71.         psz2 = malloc_w_strcpy_vp16to32(parg16->f2, FALSE, 0);
  72.     }
  73.     FREEARGPTR(parg16);
  74.     // all 16-bit pointers are now invalid!!
  75.     // this implies that psz1 may also be bad
  76.     if(!pszDriver) {
  77.         goto exitpath;
  78.     }
  79.     if (!(*spoolerapis[WOW_OpenPrinterA].lpfn)) {
  80.         if (!LoadLibraryAndGetProcAddresses("WINSPOOL.DRV", spoolerapis, WOW_SPOOLERAPI_COUNT)) {
  81.             goto exitpath;
  82.         }
  83.     }
  84.     if (GetDriverName(psz1, pszDriver)) {
  85.         if((PrinterDefault.pDevMode = GetDefaultDevMode32(pszDriver)) != NULL) {
  86.             PrinterDefault.pDatatype = NULL;
  87.             PrinterDefault.DesiredAccess  = 0;
  88.             pPrinterDefault = &PrinterDefault;
  89.             if ((*spoolerapis[WOW_OpenPrinterA].lpfn) (pszDriver, 
  90.                                                        &hnd, 
  91.                                                        pPrinterDefault)) {
  92.                 DocInfo1.pDocName = psz2;
  93.                 DocInfo1.pOutputFile = psz1;
  94.                 DocInfo1.pDatatype = NULL;
  95.                 if (ul = (*spoolerapis[WOW_StartDocPrinterA].lpfn) (hnd, 1, (LPBYTE)&DocInfo1)) {
  96.                     ul = GetPrn16(hnd);
  97.                 }
  98.                 else {
  99.                     ul = GetLastError();
  100.                 }
  101.             }
  102.             else {
  103.                 ul = GetLastError();
  104.             }
  105.         }
  106.     }
  107.     LOGDEBUG(0,("WOW::WG32OpenJob: ul = %xn", ul));
  108.     if (pPrinterDefault) {
  109.         free_w(PrinterDefault.pDevMode);
  110.     }
  111. exitpath:
  112.     if(psz1) {
  113.         free_w(psz1);
  114.     }
  115.     if(psz2) {
  116.         free_w(psz2);
  117.     }
  118.     if(pszDriver) {
  119.         free_w(pszDriver);
  120.     }
  121.     RETURN(ul);
  122. }
  123. ULONG FASTCALL   WG32StartSpoolPage (PVDMFRAME pFrame)
  124. {
  125.     ULONG       ul=0;
  126.     register    PSTARTSPOOLPAGE16 parg16;
  127.     GETARGPTR(pFrame, sizeof(STARTSPOOLPAGE16), parg16);
  128.     if (!(ul = (*spoolerapis[WOW_StartPagePrinter].lpfn) (Prn32(parg16->f1)))) {
  129.         ul = GetLastError();
  130.     }
  131.     LOGDEBUG(0,("WOW::WG32StartSpoolPage: ul = %xn", ul));
  132.     FREEARGPTR(parg16);
  133.     RETURN(ul);
  134. }
  135. ULONG FASTCALL   WG32EndSpoolPage (PVDMFRAME pFrame)
  136. {
  137.     ULONG       ul=0;
  138.     register    PENDSPOOLPAGE16 parg16;
  139.     GETARGPTR(pFrame, sizeof(ENDSPOOLPAGE16), parg16);
  140.     if (!(ul = (*spoolerapis[WOW_EndPagePrinter].lpfn) (Prn32(parg16->f1)))) {
  141.         ul = GetLastError();
  142.     }
  143.     LOGDEBUG(0,("WOW::WG32EndSpoolPage: ul = %xn", ul));
  144.     FREEARGPTR(parg16);
  145.     RETURN(ul);
  146. }
  147. ULONG FASTCALL   WG32CloseJob (PVDMFRAME pFrame)
  148. {
  149.     ULONG       ul=0;
  150.     register    PCLOSEJOB16 parg16;
  151.     GETARGPTR(pFrame, sizeof(CLOSEJOB16), parg16);
  152.     if (!(ul = (*spoolerapis[WOW_EndDocPrinter].lpfn) (Prn32(parg16->f1)))) {
  153.         ul = GetLastError();
  154.     }
  155.     if (!(ul = (*spoolerapis[WOW_ClosePrinter].lpfn) (Prn32(parg16->f1)))) {
  156.         ul = GetLastError();
  157.     }
  158.     if (ul) {
  159.         FreePrn(parg16->f1);
  160.     }
  161.     LOGDEBUG(0,("WOW::WG32CloseJob: ul = %xn", ul));
  162.     FREEARGPTR(parg16);
  163.     RETURN(ul);
  164. }
  165. ULONG FASTCALL   WG32WriteSpool (PVDMFRAME pFrame)
  166. {
  167.     DWORD       dwWritten;
  168.     ULONG       ul=0;
  169.     register    PWRITESPOOL16 parg16;
  170.     LPVOID      pBuf;
  171.     GETARGPTR(pFrame, sizeof(WRITESPOOL16), parg16);
  172.     GETMISCPTR (parg16->f2, pBuf);
  173.     if (ul = (*spoolerapis[WOW_WritePrinter].lpfn) (Prn32(parg16->f1), pBuf,
  174.                              FETCHWORD(parg16->f3), &dwWritten)) {
  175.         ul = FETCHWORD(parg16->f3);
  176.     }
  177.     else {
  178.         ul = GetLastError();
  179.     }
  180.     LOGDEBUG(0,("WOW::WG32WriteSpool: ul = %xn", ul));
  181.     FREEMISCPTR(pBuf);
  182.     FREEARGPTR(parg16);
  183.     RETURN(ul);
  184. }
  185. ULONG FASTCALL   WG32DeleteJob (PVDMFRAME pFrame)
  186. {
  187.     ULONG       ul = 0;
  188.     register    PDELETEJOB16 parg16;
  189.     GETARGPTR(pFrame, sizeof(DELETEJOB16), parg16);
  190.     if (!(ul = (*spoolerapis[WOW_DeletePrinter].lpfn) (Prn32(parg16->f1)))) {
  191.         ul = GetLastError();
  192.     }
  193.     LOGDEBUG(0,("WOW::WG32DeleteJob: ul = %xn", ul));
  194.     FREEARGPTR(parg16);
  195.     RETURN(ul);
  196. }
  197. ULONG FASTCALL WG32SpoolFile (PVDMFRAME pFrame)
  198. {
  199.     INT         len;
  200.     PSZ         psz2      = NULL;
  201.     PSZ         psz3      = NULL;
  202.     PSZ         psz4      = NULL;
  203.     PSZ         pszDriver = NULL;
  204.     LONG        ul        = -1;   // SP_ERROR
  205.     HANDLE      hFile     = NULL;
  206.     HANDLE      hPrinter  = NULL;
  207.     HANDLE      hThread   = NULL;
  208.     WOWSPOOL    *lpwowSpool = NULL;
  209.     DOC_INFO_1  DocInfo1;
  210.     DWORD       dwUnused;
  211.     register    PSPOOLFILE16 parg16;
  212.     GETARGPTR(pFrame, sizeof(SPOOLFILE16), parg16);
  213.     // save off the 16-bit params now since this could callback into a 16-bit
  214.     // fax driver & cause 16-bit memory to move.
  215.     // ignore psz1 (printer name)
  216.     // get the port name and the associated driver name
  217.     if(parg16->f2) {
  218.         if(!(psz2 = malloc_w_strcpy_vp16to32(parg16->f2, FALSE, 0))) {
  219.             goto exitpath;
  220.         }
  221.         len = strlen(psz2);
  222.         if(!(pszDriver = malloc_w(max(len, 40)))) {
  223.             goto exitpath;
  224.         }
  225.         if(!GetDriverName(psz2, pszDriver)) {
  226.             goto exitpath;
  227.         }
  228.     }
  229.     // get the Job Title
  230.     if(parg16->f3) {
  231.         if(!(psz3 = malloc_w_strcpy_vp16to32(parg16->f3, FALSE, 0))) {
  232.             goto exitpath;
  233.         }
  234.     }
  235.     // get the file name
  236.     if(parg16->f4) {
  237.         if(!(psz4 = malloc_w_strcpy_vp16to32(parg16->f4, FALSE, 0))) {
  238.             goto exitpath;
  239.         }
  240.     }
  241.     FREEARGPTR(parg16);
  242.     // all 16-bit pointers are now invalid!!
  243.     // all fields of this struct are initially zero
  244.     if(!(lpwowSpool = (WOWSPOOL *)malloc_w_zero(sizeof(WOWSPOOL)))) {
  245.         goto exitpath;
  246.     }
  247.     if(!(*spoolerapis[WOW_OpenPrinterA].lpfn)) {
  248.         if(!LoadLibraryAndGetProcAddresses("WINSPOOL.DRV", spoolerapis, WOW_SPOOLERAPI_COUNT)) {
  249.             goto exitpath;
  250.         }
  251.     }
  252.     // open the specified file
  253.     if((hFile = CreateFile(psz4, 
  254.                            GENERIC_READ, 
  255.                            0, 
  256.                            NULL, 
  257.                            OPEN_EXISTING,
  258.                            FILE_FLAG_SEQUENTIAL_SCAN,
  259.                            NULL)) == INVALID_HANDLE_VALUE) {
  260.         goto exitpath;
  261.     }
  262.     // create the WOWSpoolerThread to handle the "spooling"
  263.     if(!(hThread = CreateThread(NULL,
  264.                                 16384,
  265.                                 (LPTHREAD_START_ROUTINE)WOWSpoolerThread,
  266.                                 lpwowSpool,
  267.                                 CREATE_SUSPENDED,
  268.                                 (LPDWORD)&dwUnused))) {
  269.         goto exitpath;
  270.     }
  271.     
  272.     // open the printer
  273.     if((*spoolerapis[WOW_OpenPrinterA].lpfn)(pszDriver, &hPrinter, NULL)) {
  274.         DocInfo1.pDocName    = psz3;
  275.         DocInfo1.pOutputFile = NULL;
  276.         DocInfo1.pDatatype   = "RAW";
  277.         // start a doc
  278.         if(!(*spoolerapis[WOW_StartDocPrinterA].lpfn)(hPrinter, 
  279.                                                       1, 
  280.                                                       (LPBYTE)&DocInfo1)) {
  281.             goto ClosePrinter;
  282.         }
  283.         // start a page
  284.         if((*spoolerapis[WOW_StartPagePrinter].lpfn)(hPrinter)) {
  285.             // tell the WOWSpoolerThread that it's OK to do its thing
  286.             lpwowSpool->fOK      = TRUE;
  287.             lpwowSpool->hFile    = hFile;
  288.             lpwowSpool->hPrinter = hPrinter;
  289.             lpwowSpool->prn16    = gprn16;
  290.             // tell the app that everything is hunky dory
  291.             ul = (LONG)gprn16++;
  292.             // make sure this doesn't go negative (-> an error ret to the app)
  293.             if(gprn16 & 0x8000) {
  294.                 gprn16 = 0x100;
  295.             }
  296.         } 
  297.         // error path
  298.         else {
  299.             (*spoolerapis[WOW_EndDocPrinter].lpfn)  (hPrinter);
  300. ClosePrinter:
  301.             // note: hPrinter is freed by WOW_ClosePrinter
  302.             (*spoolerapis[WOW_ClosePrinter].lpfn)   (hPrinter);
  303.         }
  304.     }
  305. exitpath:
  306.     LOGDEBUG(2,("WOW::WG32SpoolFile: ul = %xn", ul));
  307.     if(psz2) {
  308.         free_w(psz2);
  309.     }
  310.     if(psz3) {
  311.         free_w(psz3);
  312.     }
  313.     if(psz4) {
  314.         free_w(psz4);
  315.     }
  316.     if(pszDriver) {
  317.         free_w(pszDriver);
  318.     }
  319.     // give the spooler thread a kick start then close the thread handle
  320.     // (note: the thread will still be active)
  321.     if(hThread) {
  322.         ResumeThread(hThread);
  323.         CloseHandle(hThread);
  324.     }
  325.     // clean up if there was an error -- otherwise the thread will clean up
  326.     if(ul == -1) {
  327.         if(hFile) {
  328.             CloseHandle(hFile);
  329.         }
  330.         if(lpwowSpool) {
  331.             free_w(lpwowSpool);
  332.         }
  333.         // note: hPrinter is freed by WOW_ClosePrinter
  334.     }
  335.     return((ULONG)ul);
  336. }
  337. #define  SPOOL_BUFF_SIZE   4096
  338. VOID WOWSpoolerThread(WOWSPOOL *lpwowSpool)
  339. {
  340.     DWORD  dwBytes; 
  341.     DWORD  dwWritten;
  342.     LPBYTE buf[SPOOL_BUFF_SIZE];
  343.     // this thread will only do something if fOK is TRUE
  344.     if(lpwowSpool->fOK) {
  345.       do {
  346.         // this is a sequential read
  347.         if(ReadFile(lpwowSpool->hFile, buf, SPOOL_BUFF_SIZE, &dwBytes, NULL)) { 
  348.             // if dwBytes==0 --> EOF
  349.             if(dwBytes) {
  350.                 // 
  351.                 if(!(*spoolerapis[WOW_WritePrinter].lpfn)(lpwowSpool->hPrinter, 
  352.                                                           buf, 
  353.                                                           dwBytes, 
  354.                                                           &dwWritten)) {
  355.                     LOGDEBUG(0,("WOW::WOWSpoolerThread:WritePrinter ERROR!n"));
  356.                     break;
  357.                 }
  358.                 else if(dwBytes != dwWritten) {
  359.                     LOGDEBUG(0,("WOW::WOWSpoolerThread:WritePrinter error!n"));
  360.                     break;
  361.                 }
  362.                 
  363.             }
  364.         }
  365.       } while (dwBytes == SPOOL_BUFF_SIZE);
  366.       // shut down the print job
  367.       (*spoolerapis[WOW_EndPagePrinter].lpfn) (lpwowSpool->hPrinter);
  368.       (*spoolerapis[WOW_EndDocPrinter].lpfn)  (lpwowSpool->hPrinter);
  369.       // note: hPrinter is freed by WOW_ClosePrinter
  370.       (*spoolerapis[WOW_ClosePrinter].lpfn)   (lpwowSpool->hPrinter);
  371.       // clean up
  372.       if(lpwowSpool->hFile) {
  373.           CloseHandle(lpwowSpool->hFile);
  374.       }
  375.       if(lpwowSpool) {
  376.           free_w(lpwowSpool);
  377.       }
  378.     } // end if
  379.     ExitThread(0);
  380. }
  381. WORD GetPrn16(HANDLE h32)
  382. {
  383.     HANDLE  hnd;
  384.     VPVOID  vp;
  385.     LPBYTE  lpMem16;
  386.     hnd = LocalAlloc16(LMEM_MOVEABLE, sizeof(HANDLE), (HANDLE) gUser16hInstance);
  387.     vp = LocalLock16(hnd);
  388.     if (vp) {
  389.         GETMISCPTR (vp, lpMem16);
  390.         if (lpMem16) {
  391.             *((PDWORD16)lpMem16) = (DWORD) h32;
  392.             FREEMISCPTR(lpMem16);
  393.             LocalUnlock16(hnd);
  394.         }
  395.     }
  396.     else {
  397.         LOGDEBUG (0, ("WOW::GETPRN16: Can't allocate a 16 bit handlen"));
  398.     }
  399.     return (LOWORD(hnd));
  400. }
  401. HANDLE Prn32(WORD h16)
  402. {
  403.     VPVOID  vp;
  404.     HANDLE  h32 = NULL;
  405.     LPBYTE  lpMem16;
  406.     vp = LocalLock16 ((HANDLE) MAKELONG(h16, gUser16hInstance));
  407.     if (vp) {
  408.         GETMISCPTR (vp, lpMem16);
  409.         if (lpMem16) {
  410.             h32 = (HANDLE) *((PDWORD16)lpMem16);
  411.             FREEMISCPTR(lpMem16);
  412.         }
  413.         LocalUnlock16 ((HANDLE) MAKELONG(h16, gUser16hInstance));
  414.     }
  415.     return (h32);
  416. }
  417. VOID FreePrn (WORD h16)
  418. {
  419.     LocalFree16 ((HANDLE) MAKELONG(h16, gUser16hInstance));
  420. }
  421. BOOL GetDriverName (char *psz, char *pszDriver)
  422. {
  423.     CHAR szAllDevices[1024];
  424.     CHAR *szNextDevice;
  425.     CHAR szPrinter[64];
  426.     CHAR *szOutput;
  427.     UINT len;
  428.     if(!psz || (*psz == '')) {
  429.         return FALSE;
  430.     }
  431.   
  432.     len = strlen(psz);
  433.     GetProfileString ("devices", NULL, "", szAllDevices, sizeof(szAllDevices));
  434.     szNextDevice = szAllDevices;
  435.     LOGDEBUG(6,("WOW::GetDriverName: szAllDevices = %sn", szAllDevices));
  436.     // strings from win.ini will be of the form "PS Printer=PSCRIPT,LPT1:"
  437.     while (*szNextDevice) {
  438.         GetProfileString ("devices", szNextDevice, "", szPrinter, sizeof(szPrinter));
  439.         if (*szPrinter) {
  440.             if (szOutput = WOW32_strchr (szPrinter, ',')) {
  441.                 szOutput++;
  442.                 while (*szOutput == ' ') {
  443.                     szOutput++;
  444.                 }
  445.                 if (!WOW32_stricmp(psz, szOutput)) {
  446.                     break;  // found it!
  447.                 }
  448.                 // some apps pass "LPT1" without the ':' -- account for that
  449.                 // if the app passed "LPT1" and ...
  450.                 if (psz[len-1] != ':') {
  451.                     // ...strlen(szOutput) == 5 && szOutput[4] == ':' ...
  452.                     if((strlen(szOutput) == len+1) && (szOutput[len] == ':')) {
  453.                         // ...clobber the ':' char ...
  454.                         szOutput[len] = '';
  455.                         // ...and see if the strings match now
  456.                         if (!WOW32_stricmp(psz, szOutput)) {
  457.                             break;  // found it!
  458.                         }
  459.                     }
  460.                 }
  461.             }
  462.         }
  463.         if (szNextDevice = WOW32_strchr (szNextDevice, '')) {
  464.             szNextDevice++;
  465.         }
  466.         else {
  467.             szNextDevice = "";
  468.             break;
  469.         }
  470.     }
  471.     if (*szNextDevice) {
  472.         LOGDEBUG(0,("WOW::GetDriverName: szNextDevice = %sn", szNextDevice));
  473.         if (lstrcpy (pszDriver, szNextDevice)) {
  474.             return TRUE;
  475.         }
  476.     }
  477.     // else they may have specified a network printer eg. "\msprint44corpk"
  478.     // in which case we'll assume it's all right (since it will fail once the
  479.     // WOW functions that call into this will fail when they call into the 
  480.     // driver with a bogus driver name)
  481.     if(psz[0] == '\' && psz[1] == '\') {
  482.         strcpy(pszDriver, psz);
  483.         return TRUE;
  484.     }
  485.     return FALSE;
  486. }