News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

error msg?

Started by shankle, June 26, 2012, 12:49:14 AM

Previous topic - Next topic

shankle

#135
Thanks all for the help.
The previous items in WM_CREATE seem to check out fine now.
However the program is still not printing.
I have included a snippet of the code that might be in error.
Of course it could be something else.

.data
PT2       db  '01020207010302040105020602030208',0             
            db  '01010103020501070208010402060106',0             
            db  '01040102010102060207010802010105',0                                         
saveebx   dd       0
holdR       db   "  ",0
             DOCINFOA <sizeof(DOCINFOA),AppName,NULL,NULL,0>
; other code

WndProc:
        FRAME  hWnd,iMsg,wParam,lParam
        USES ebx,edi,esi
        Local hdcPrn
; other code
        invoke StartDoc, [hdcPrn],addr doci
       
         lea ebx,PT2
         mov [saveebx],ebx    ; address PT2 in saveebx
       
; other code
         mov ebx, [saveebx]   ; address in ebx
; not sure if ebx should have " []"  or not in invoke         
         invoke WriteToPrinter, [hdcPrn],393,660,1045,ebx         
               
; other code
WriteToPrinter FRAME hdcPrn,Horz1,Horz2,Vert4,LpBuffer
; Have no idea which of the following two instructions are correct
       mov ecx,addr LpBuffer        ; address in LpBuffer of PT2
       mov ecx,[LpBuffer]             ; address in LpBuffer of PT2       

;This line is causing the problem - address in ecx should move data to ax
;Have a messagebox here and the program boombs after it.       
       mov ax,W[ecx]
       cmp al,030h
        jne >
         mov al,020h
:
       mov W[holdR],ax                         
       invoke TextOutA, [hdcPrn],[Horz1],[Vert4],[holdR],2       
     ret
     ENDF
     

jj2007

Check
holdR       db   "  ",0
The upper byte of that "fake dword" used in TextOut gets supplied by DOCINFOA. Now if the lowest byte of DOCINFOA contains something different from zero, you are in trouble ;-)

Edit: Sorry, I just saw you are using only 2 bytes. Disregard this post, please.

wjr

I believe what you had originally was correct and the problem was elsewhere. If your program doesn't work and you are coming from a working MASM program, then the error(s) are somewhere in your translation to GoAsm syntax, and you should really be stepping through your code in a debugger to quickly track these down. Another alternative is re-comparing to the MASM source code. The "not sure" and "have no idea" are a little worrisome. There is a big difference between [ebx] and ebx, and the syntax in this case is the same between the two assemblers (although in other cases some differences with GoAsm B/W/D/Q prefix vs MASM PTR variations). There is also a big difference between [LpBuffer] and ADDR LpBuffer (for the first one, GoAsm requires the [] where MASM allows LpBuffer... for the second one, if I recall correctly you would see MASM with OFFSET LpBuffer).

dedndave

in masm, OFFSET is used for globals
ADDR can be used for either locals or globals - i prefer to use it only for locals

satpro

In GoAsm both ADDR and OFFSET are accepted.


From the GoAsm manual:

"In order to get the offset in GoAsm you must use
MOV EBX,ADDR wParam
or if you prefer
MOV EBX,OFFSET wParam
which means the same thing"

MichaelW

For MASM ADDR is valid only with INVOKE.
Well Microsoft, here's another nice mess you've gotten us into.

shankle

Been over this before but I still am not able to print anything.
So I decide to start testing in WM_CREATE again.
MASM32 was using "winspool.inc" for the printer.
EnumPrintersA fails with a buffer to small error

.data
dwNeeded    dd  0
dwReturned  dd  0
pinf04           dd  0

.code
; other code

WndProc:
        FRAME hWnd,iMsg,wParam,lParam
        USES ebx,edi,esi
        Local hMemory,hdc,hdcPrn

;.WM_CREATE
        cmp D[iMsg],WM_CREATE 
        jne >>.WM_CHAR                 
                   
        invoke  EnumPrintersA, PRINTER_ENUM_LOCAL,NULL,4,NULL,0,\
                addr dwNeeded,addr dwReturned               
       invoke  GlobalAlloc, GHND,addr dwNeeded
       mov       [hMemory], eax
       invoke  GlobalLock, eax      
       mov       [pinf04],eax   
       mov       ebx,eax   
        invoke  EnumPrintersA, PRINTER_ENUM_LOCAL,NULL,4,[pinf04],\
                          addr dwNeeded,addr dwNeeded,addr dwReturned
        lea eax, [ebx+PRINTER_INFO_4.pPrinterName]                                          
        invoke  CreateDC, NULL,eax,NULL,NULL                              
       mov       [hdcPrn],eax
       mov       [hdc],eax
       invoke  GlobalUnlock, [hMemory]   
       invoke  GlobalFree, [hMemory]      
        jmp >>.default
; other code       
       endf

Yuri


invoke  GlobalAlloc, GHND,addr dwNeeded

The second argument should be [dwNeeded].

wjr

In the second call to EnumPrinters, the third last argument cbBuf should also be [dwNeeded].

shankle

I'll try one more time and then I'll have to abandon Goasm.
I know I have been a pest - sorry.

MASM32 was using "winspool.inc" for the printer.
Enumprinter 2 never gets the name of the printer in parmeter 4 (PrintCString).
It shows executing clean.
Therefor CreatDC does not work.
I have been playing with this for days.
PrintDlgEX  won't work
I can get the Buffer length in dwNeeded which is 72.

.data
dwNeeded    dd  0
dwReturned  dd  0
PrintCString   db   90 DUP 0    ; buffer to receive the printer name

.code
; other code

WndProc:
        FRAME hWnd,iMsg,wParam,lParam
        USES ebx,edi,esi
        Local hMemory,hdc,hdcPrn

;.WM_CREATE
        cmp D[iMsg],WM_CREATE 
        jne >>.WM_CHAR                 
        invoke  EnumPrinters, PRINTER_ENUM_LOCAL,NULL,4,NULL,\
                0,addr dwNeeded,addr dwReturned
   invoke  GlobalAlloc, GHND,[dwNeeded]
   mov       [hMemory], eax
   invoke  GlobalLock, eax   
;       mov       ebx,eax
       invoke  EnumPrinters, PRINTER_ENUM_LOCAL,NULL,4,addr PrintCString,\
                                [dwNeeded],addr dwNeeded,addr dwReturned
;        lea edx, [ebx+PRINTER_INFO_4.pPrinterName]
        invoke  CreateDC, NULL,addr PrintCString,NULL,NULL
       mov       [hdcPrn],eax
       invoke  GlobalUnlock, [hMemory]   
       invoke  GlobalFree, [hMemory]   
       jmp >>.default
       endf

wjr

Although there is a bit of a learning curve with GoAsm or any other assembler, there have been occasions here where the problem seems related more to the lower level understanding of pointers and their use in API functions.

Another correction in your earlier code, use mov instead of lea:
mov eax, [ebx+PRINTER_INFO_4.pPrinterName]

Your EnumPrinters returns an array of PRINTER_INFO_4 structures. CreateDC requires a pointer to a string for the name of the device (the first member of PRINTER_INFO_4), but with your recent "addr PrintCString" you are incorrectly passing the pointer to a PRINTER_INFO_4 structure. Note that there can be more than one of these structures, so perhaps you have more code that advances ebx to select which printer. There is also the GetDefaultPrinter API function.

I am in the process of getting printing operational for a program. I wasn't quite there yet, but unfortunately even with these corrections, the call to CreateDC fails. I have seen some sample code with the first argument as "WINSPOOL", but the documentation does recommend NULL for a printer. That sample code does pass a pointer to a DEVMODE structure though, perhaps that is the missing piece of the puzzle (although NULL does seem like it should work for a default initialization).

jj2007

TinyIDE has a printing routine. Look for PrintRTF inside the (Masm, not GoAsm) source, maybe you can get some inspiration. The *.asc file is the source of the source and opens in TinyIDE.exe.

satpro


"I'll try one more time and then I'll have to abandon Goasm"
Well, is that fair?

In the first call to EnumPrinters the 4th param is NULL.  Doesn't that need to be a ptr to a buffer that receives an array of PRINTER_INFO_4 structures?  WinHlp doesn't mention anything about specifying a NULL ptr.  Then the 5th param should be a buffer size number, right?  Then, if more detailed info is needed, a 2nd call with a level 2 info structure can be called later.

Where are the comments (e.g. 1 per line of code?) that help you with what's going on?  Also, error-checking all OS calls would be a GREAT idea.  EnumPrinters returns TRUE if the function succeeds.  Same with GlobalAlloc (a ptr).  Where are the checks for success or failure?  You would know the call is not succeeding (and why) right then and there.  And then, why not use GMEM_FIXED | GMEM_ZEROINIT in GlobalAlloc and skip the Lock/Unlock calls, along with their lock counts?  The returned handle in this case is a ptr to your memory and you're freeing it almost immediately anyway, not that it matters.  It's your memory to use.

Wayne's advice about lea is right on the money.  You can refer to the values in a structure using the [register + structure.member] approach.  The assembler will handle the lea for you.

Maybe, and this is just a thought, how about try this in a console first, where you don't have the worries of the window proc heaped on top of a complicated series of calls to EnumPrinters?  It's really not that much code.  Move it back to the window when you iron everything out. 

It doesn't seem right that the assembler should have to take the fall here...

shankle

Hi Satpro,
I've done all the error checking it's just not posted here. I also have comments and
their not posted here. Trying to keep it simple and straight forward.
It fails at CreateDC, Handle is not created. My understanding of the 1st EnumPrinter 
is that it is supposed to fail and only return the length of the buffer.

satpro

Okay.  The call should be set up to succeed.  Make sure the buffer is large enough and that you use valid pointers.  The INFO_4 structure is 12 bytes per device.  Two ptrs and an attributes dword.  You said you needed 72 bytes, right?  90 should be fine, except it's not a multiple of 12.  Of course, the call still reports what you would need.  Or, use the larger buffer when you don't know the answer.  It's only a few bytes in DATA, right?

Also, "WINSPOOL",0 is used with computers after Win95/98.  And I just thought of something else.





Try this:

DATA SECTION
winspoolstring db "WINSPOOL", 0

CODE SECTION
mov ebx, ADDR PrintCString  (your buffer)
invoke CreateDC, addr winspoolstring, [ebx+PRINTER_INFO_4.pPrinterName], NULL, NULL


You can do this instead and GoAsm places the 0-term string 'WINSPOOL' in the CONST section for you (or DATA if no CONST or CODE if no DATA section):


CONST SECTION

CODE SECTION    (this might be easier for you)

mov ebx, ADDR PrintCString  (your buffer)
invoke CreateDC, 'WINSPOOL', [ebx+PRINTER_INFO_4.pPrinterName], NULL, NULL



Here's why:
The INFO_4 structure contains ptrs as it's first two members, and you want the first ptr.  Therefore, you would want the data at that address, which is the address of the string you need, contained within the structure, and not the address of the structure itself.  This means brackets and not ADDR.  Data, not address.

I have to admit that in using GoAsm you are working without a net most of the time because hardly anyone here uses it.  From my own experience I have found it to be a very efficient assembler that does ANYTHING I need it to do.  Not that Masm doesn't.  Once you get the hang of its (actually very simple) syntax there is nothing you cannot accomplish with it, and with no extra overhead.  But I don't use 'C' calls at all and macros almost never.  So for me GoAsm is ideal.  I'm not kidding--I had to read the manual a lot more than once and still refer to my printed copy frequently, although less and less.  But my source seems much easier to read with GoAsm; I like that very much.

In Masm you don't use ADDR much, maybe just with invoke.  The Masm guys already stated that.  If you feel more comfortable using OFFSET--use that instead.  Just remember that when accessing a variable's contents (its data) you use [somevariable] and in Masm you don't have to but can if you want --> somevariable or [somevariable].

Keep plugging away...
Bert