The MASM Forum

General => The Campus => Topic started by: Magnum on March 05, 2013, 04:54:02 AM

Title: Check if printer is ready
Post by: Magnum on March 05, 2013, 04:54:02 AM
I want to check if a printer is ready, otherwise I don't want to load a printer program I won't need.

; This should work, but Lexmark pops up a box saying it can't communicate with the printer.
; The MessageBox never even makes an appearance even though eax is less than 32.
;
; If the function fails, the return value is an error value that is less than or equal to 32.
; The following table lists these error values:



.386
include \masm32\include\masm32rt.inc
.code

start:

fn ShellExecute,0,"print","test.txt",NULL,NULL,NULL
invoke ExitProcess,NULL

.if eax <= 32

fn MessageBox,0,str$(eax),"Title",MB_OK


.else

.endif

end start
Title: Re: Check if printer is ready
Post by: dedndave on March 05, 2013, 05:04:14 AM
OpenPrinter
GetPrinter (PRINTER_INFO_6)
ClosePrinter
Title: Re: Check if printer is ready
Post by: Magnum on March 05, 2013, 01:55:07 PM
This is what I have come up with, but not working.

I also had to deal with an unauthorized intruder masquerading as a a system file except with a v appended to the end.

Ich weiß, wer es war, und ich kann eine Kanone zu verwenden. l.o.i.c.


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
    include \masm32\include\winspool.inc
    includelib \masm32\lib\winspool.lib
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data

        hPrinter dd 0
        cbBuffer dd 0

.data?

P_Handle dd ?

    .code

start:

; printer name buffer and size of name buffer

    invoke GetDefaultPrinter, NULL, ADDR cbBuffer
    ;print str$(eax),13,10
    ;print str$(cbBuffer),13,10

    mov ebx, alloc(cbBuffer)

    invoke GetDefaultPrinter, ebx, ADDR cbBuffer
    ;print str$(eax),13,10
    ;print ebx,13,10

invoke OpenPrinter, ebx, ADDR hPrinter, NULL ; name, handle, and pointer to printer defaults structure
mov P_Handle,eax ; store handle

invoke GetPrinter,P_Handle,6,ADDR hPrinter,sizeof hPrinter,NULL

;int 3

.if eax == 0 ; process failed

fn MessageBox,0,str$(eax),"Title",MB_OK

.endif

    invoke ClosePrinter, hPrinter
   
    free ebx

    invoke ExitProcess,0

end start
Title: Re: Check if printer is ready
Post by: dedndave on March 05, 2013, 02:41:49 PM
that's a bit confusing   :P

hPrinter would normally refer to a printer handle
phPrinter would be the address of that handle variable (pointer to a handle)
pPrinter, in the case of (6), is a pointer to a PRINTER_INFO_6 structure, which has a size of 1 dword

when you call GetDefaultPrinter, you should test for a return value of zero
it may be that there is no default printer

once you have the default printer string (let's say the address is in EBX)
    INVOKE  OpenPrinter,ebx,addr hPrinter,NULL
that looks like what you have
the value returned in EAX by OpenPrinter will be zero or non-zero, indicating failure or success
it will not be the handle
the handle will be stored in the hPrinter dword variable

now, the PRINTER_INFO_6 structure is not defined in our current windows.inc
that's ok - it's a dword - let's call it dwPrnStatus
we also need a dword variable for the function to return the number of bytes stored
dwPrnStatus dd ?
dwPrnBytes  dd ?

    INVOKE  GetPrinter,hPrinter,6,addr dwPrnStatus,sizeof dwPrnStatus,addr dwPrnBytes

when you are done, close the handle
    INVOKE  ClosePrinter,hPrinter

of course, you could put the function in a PROC,
and declare the hPrinter, dwPrnStatus, and dwPrnBytes variables as LOCAL
the function could return -1 or something if failure,
or the status if success, in EAX
Title: Re: Check if printer is ready
Post by: Magnum on March 05, 2013, 03:15:44 PM
You are a good person, but I am thinking of jumping on a sword.

:t
Title: Re: Check if printer is ready
Post by: dedndave on March 05, 2013, 03:29:06 PM
Quote...but I am thinking of jumping on a sword.
as in signed word ?   :P
Title: Re: Check if printer is ready
Post by: Magnum on March 10, 2013, 01:29:46 AM
Thanks Dave.

GetPrinter is returning 0 in EAX whether printer is hooked up or not ?

Do I need to send it a print job and look for failure ?

Andy


; dedndave
;
;
    include \masm32\include\masm32rt.inc
    include \masm32\include\winspool.inc
    includelib \masm32\lib\winspool.lib

.data

hPrinter dd 0

cbBuffer dd 0

.data?

dwPrnStatus dd ?
dwPrnBytes  dd ?

.code

start:

invoke GetDefaultPrinter, NULL, ADDR cbBuffer

; you should test for a return value of zero it may be that there is no default printer


mov ebx, alloc(cbBuffer)

invoke OpenPrinter, ebx, ADDR hPrinter, NULL

; the value returned in EAX by OpenPrinter will be zero or non-zero, indicating failure or success
; it will not be the handle
; the handle will be stored in the hPrinter dword variable

INVOKE  GetPrinter,hPrinter,6,addr dwPrnStatus,sizeof dwPrnStatus,addr dwPrnBytes

;If the function fails, the return value is zero.
invoke ClosePrinter, hPrinter
   
free ebx

invoke ExitProcess,0

end start
Title: Re: Check if printer is ready
Post by: dedndave on March 10, 2013, 01:37:38 AM
in the previous code, you used a different method to get the default printer string
you made the first call to GetDefaultPrinter, with a buffer length of 0
that call returns a value that tells you how big of a buffer you need
then, you allocated the buffer and made the second call with the buffer size

in the newer version, you did not do that
so, when you call GetDefaultPrinter, there is no buffer and cbBuffer = 0

give me a little time - let me see what i come up with.....
Title: Re: Check if printer is ready
Post by: dedndave on March 10, 2013, 03:09:10 AM
see if this works.....
Title: Re: Check if printer is ready
Post by: Magnum on March 10, 2013, 08:00:39 AM
Ebx and eax are non-zero whether printer is on or off.

Title: Re: Check if printer is ready
Post by: dedndave on March 10, 2013, 08:23:34 AM
EBX isn't meant to have anything
EAX returned by GetPrnStatus is the one of interest

the bits are defined as 0 "if no flags"
so - 0 means you are not out of paper, not jammed, etc
unfortunately, i do not see a "ready" bit, similar to what we had in DOS days
but, there must be a way to determine if the printer is ready
Title: Re: Check if printer is ready
Post by: Magnum on March 10, 2013, 08:45:58 AM
I am going to look at maybe CreateFile and send the printer a print job.

Andy
Title: Re: Check if printer is ready
Post by: Magnum on March 10, 2013, 08:51:24 AM
Will this work ?

PRINTER_STATUS_OFFLINE The printer is offline. 
Title: Re: Check if printer is ready
Post by: dedndave on March 10, 2013, 09:42:07 AM
that is one of the status bits returned by GetPrinter
it doesn't seem to do what we think - lol
that's probably because we are checking status through the print spooler

there has to be some simple way, without sending a job to the printer
perhaps we need to communicate with the device driver - not the spooler
Title: Re: Check if printer is ready
Post by: sinsi on March 10, 2013, 01:51:45 PM
Hey dave, I think this line is a problem
        INVOKE  GetPrinter,_hPrn,6,addr _dwPrnStatus,sizeof _dwPrnStatus,addr _cbPrnBytes
In my testing it fails and cbPrnBytes=8. Replacing sizeof _dwPrnStatus with 8 doesn't fail but I get a status of 02000000h.
All of the info I can find says the status values end at 01000000h. Maybe it's a new one for win8.
Title: Re: Check if printer is ready
Post by: sinsi on March 10, 2013, 04:42:17 PM
OK, when my other computer is off, I get that status, because it's a shared network printer. Makes sense, PRINTER_STATUS_SERVER_OFFLINE
Quote from: Win8 SDK winspool.h
#define PRINTER_STATUS_SERVER_UNKNOWN    0x00800000
#define PRINTER_STATUS_POWER_SAVE        0x01000000
#define PRINTER_STATUS_SERVER_OFFLINE    0x02000000
#define PRINTER_STATUS_DRIVER_UPDATE_NEEDED    0x04000000
Still not sure about PRINTER_INFO_6, it's still defined as a dword but needs 8 bytes.
Title: Re: Check if printer is ready
Post by: dedndave on March 10, 2013, 10:03:00 PM
hmmmm
a 64-bit OS, no doubt
i can't find anything on it with google

i figured the "ready" status is returned because the spooler is always ready   :P
Title: Re: Check if printer is ready
Post by: dedndave on March 11, 2013, 04:58:28 AM
i wanted to make it UNICODE aware
made a few other changes, also

1) little better error handling in GetDefPrn routine
2) made room for 8 bytes in printer status, per Sinsi (GetPrnStatus routine)
that way, it should work in 32 or 64-bit environment
3) UNICODE aware
Title: Re: Check if printer is ready
Post by: Magnum on March 11, 2013, 07:38:45 AM
Didn't work.

I thought this worked the first thru Olly, but not later ?

I think it's one of those M.S. undocumented "Let's mess with the developer" APIs. a.k.a LMWTD


start:

; If the function succeeds, the return value is greater than zero.

invoke  StartPage, _hpdc

.if EAX == ERROR_INVALID_HANDLE

;fn MessageBox,0,LastError$(),"Last Error Text",MB_OK

.else

.endif

final: