News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

wsprintf - Symbol not defined ??

Started by Chip, July 30, 2006, 01:56:38 AM

Previous topic - Next topic

Chip


When I use the following code:

            #include "C:\Program Files\Assembly\Include\windows.inc"
            #include "C:\Program Files\Assembly\Include\all_api.inc"
            #include "C:\Program Files\Assembly\Include\comdef.inc"
            #include "C:\Program Files\Assembly\Include\CommDlg_VTable.inc"
            #include "C:\Program Files\Assembly\Include\ShObj_VTables.inc"
            #include "C:\Program Files\Assembly\Include\DonkeyLib.inc"
            #include "C:\Program Files\Assembly\Include\masm32.inc"
            #include "C:\Program Files\Assembly\Include\kernel32.inc"
            #include "C:\Program Files\Assembly\Include\user32.inc"

            INVOKE wsprintf,  ADDR SYS.ConsoleOut, ADDR SYS.ConsoleFormat, ADDR Todays.Date, ADDR Exact.Time, ADDR Message

I receive the following error message from the Link Program:


           GoLink.Exe Version 0.26.4 - Copyright Jeremy Gordon 2002/6-JG@JGnet.co.uk
      
      C:\Program Files\Assembly\My Programs\Number\Number.obj
          Made on Saturday, July 29, 2006 at 18:46 size: 42,030 bytes
      C:\SYSTEM\system32\Kernel32.dll
          Made on Wednesday, August 04, 2004 at 05:00 size: 983,552 bytes
          Number of required imports found in this file: 12
      
      Error!
      The following symbol was not defined in the object file or files:-
      <wsprintfA>
      Output file not made

Searching the forum, I found various references to "wsprintf" in include files,
but frankly,  I do not understand the nature of that discussion.

Any help would be appreaciated!

Chip

I am on Skype under my email address!

jorgon

Hi Chip

The wsprintf Windows function (Windows API) which the include file has altered to wsprintfA (ANSI version of the API) is contained within the Windows DLL called User32.dll.  You can see that this is so by looking at the Windows documentation for wsprintf which tells you which DLL holds that function.

The GoLink error message tells you that the linker could not find the wsprintf function (actually because of the action of the include file it's looking for wsprintfA).  Judging from this error message it seems likely that you have not told GoLink to look inside User32.dll for the functions your program requires.  Clearly GoLink has been told to look inside Kernel32.dll (this can be seen from the fact that it has reported that it has found 12 functions in that DLL).  You need, therefore, to add User32.dll as well.  You can tell GoLink which DLLs to look into for the functions that the program requires either in the command line or command file given to GoLink.  You need to add User32.dll to this list.  Exactly where this list of DLLs is, depends on how you are starting GoLink - information which you have not given us.



Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

Chip

Jeremy,

You were right about not including additional Dll's in GoLink.  (For some reason,
I deleted the input file to Golink that had included all of your suggested Dll's.)

However, I am still getting the error message!

Below, is the revised GoLink output.  I also copied the entry from User32.Inc.

(Perhaps this is all in vain anyway - I am only trying to concantenate different
fiellds prior to sending to the console out.  Not sure if "wsprintf" is the best way
to do this. Im really only trying to create a general purpose "log" of significant
events that is date and time stamped; Start time, file name in, progress, etc.
I had hoped to create one procedure, and just move messages to it when
needed. In the long run, I may redirect this to a log file, since it is only a system
service routine that is generally not monitored by a user.)

Thank you for your earlier prompt reply.

Chip







GoLink output follows:

Revised Output from GoLink
GoAsm.Exe Version 0.55.03 beta- Copyright Jeremy Gordon 2001/6 - JG@JGnet.co.uk
Output file: Number.obj
Output file: Number.lst



GoLink.Exe Version 0.26.4 - Copyright Jeremy Gordon 2002/6-JG@JGnet.co.uk

C:\Program Files\Assembly\My Programs\Number\Number.obj
    Made on Sunday, July 30, 2006 at 02:58 size: 533,965 bytes
C:\SYSTEM\system32\Kernel32.dll
    Made on Wednesday, August 04, 2004 at 05:00 size: 983,552 bytes
    Number of required imports found in this file: 13
C:\SYSTEM\system32\User32.dll
    Made on Wednesday, March 02, 2005 at 11:09 size: 577,024 bytes
    Number of required imports found in this file: none
C:\SYSTEM\system32\Gdi32.dll
    Made on Wednesday, December 28, 2005 at 19:54 size: 280,064 bytes
    Number of required imports found in this file: none
C:\SYSTEM\system32\COMCTL32.dll
    Made on Wednesday, August 04, 2004 at 05:00 size: 611,328 bytes
    Number of required imports found in this file: none
C:\SYSTEM\system32\comdlg32.dll
    Made on Wednesday, August 04, 2004 at 05:00 size: 276,992 bytes
    Number of required imports found in this file: none
C:\SYSTEM\system32\OLEAUT32.dll
    Made on Wednesday, August 04, 2004 at 05:00 size: 553,472 bytes
    Number of required imports found in this file: none
C:\SYSTEM\system32\Hhctrl.ocx
    Made on Thursday, May 26, 2005 at 19:04 size: 546,304 bytes
    Number of required imports found in this file: none
C:\SYSTEM\system32\winspool.drv
    Made on Wednesday, August 04, 2004 at 05:00 size: 146,432 bytes
    Number of required imports found in this file: none
C:\SYSTEM\system32\shell32.dll
    Made on Thursday, March 16, 2006 at 21:03 size: 8,452,096 bytes
    Number of required imports found in this file: none

Error!
The following symbol was not defined in the object file or files:-
<wsprintfA>
Output file not made



Copied From User32.Inc

     IFNDEF USER32_INC
     USER32_INC equ <1>

     IFNDEF _wininc_
       wsprintfA PROTO C :DWORD,:VARARG
       wsprintf equ <wsprintfA>
     ENDIF

I am on Skype under my email address!

jorgon

Chip

If you change your call to wsprintf to this:-
QuoteINVOKE wsprintfA,  ADDR SYS.ConsoleOut, ADDR SYS.ConsoleFormat, ADDR Todays.Date, ADDR Exact.Time, ADDR Message
in other words if you change wsprintf to wsprintfA, then your program should assemble and link properly.
What you will have done with this change is to specify by hand that you want to call the ANSI version of the function which is called wsprintfA (as opposed to the Unicode version, which is called wsprintfW).

In the expectation that this has worked, here is an explanation as to what is going on:-

1. If you specify wsprintf in your code, then you also need to tell the assembler what wsprintf really means.  This is because there is actually no function called wsprintf.  Instead, there are two related Windows functions (APIs) in User32.dll.  One is wsprintfA and one is wsprintW.  wsprintfA is an ANSI version (it takes ANSI strings) and wsprintW is the "wide character" version (it takes Unicode strings).  Which one you call depends on whether you are working with ANSI or Unicode strings.
2. You would use an "equate" such as this line to tell the assembler what wsprintf means:-
wsprintf=wsprintfA
This tells the assembler that if the assembler finds wsprintf it should in fact regard it as wsprintfA instead.
3. Often programmers will use include files containing a whole load of such equates.
4. In general, personally I don't use such equates nor do I use include files and the above is a good example why not.  When writing this program, I would know that I was only working with ANSI strings and therefore that I was calling the ANSI version of the API.  Therefore I would simply call wsprintfA in the first place.  Then at some later time when I came back to the source code I would see that wsprintA is called, and I would not have to look inside the include file to see what function is actually being called.  So the source code is clearer and more obvious.
5. A possible exception to the above would be if I am using the same source code to make two versions of my program, one for Windows 95/98 which would use ANSI strings, and one for Windows XP using Unicode strings.  Then the correct equate would be switched in using conditional assembly.
6. In your case, for some reason you are using MASM include files.  The PROTO declaration means nothing to GoAsm (it does not need any PROTO lines to declare functions).  So GoAsm believes your program is trying to call <wsprintfA> which of course does not exist.  The answer is either to stop using include files altogether (abolish them - see 4 above), or use GoAsm include files.  GoAsm include files are available from Donkey's stable or alternatively you can make your own include files from the Windows header files using Wayne J Radburn's thINC utility.

Incidentally, wsprintfA and wsprintfW are one of the very few APIs which do not alter the stack pointer to suit the number of parameters you send them, so you need to clear up the stack yourself immediately after calling one of these APIs, by adding 4 bytes to ESP for each parameter sent to the API.

QuoteI am only trying to concantenate different fields prior to sending to the console out.  Not sure if "wsprintf" is the best way to do this
Well its does seem a pretty cumbersome way to concatenate two strings when you can simply use something like:-

MOV ESI,ADDR Message             ;get in ESI the address of the new text to add
MOV EDI,ADDR Console_End         ;get in EDI the current end of text in the buffer
MOV ECX,[textlength]             ;get in ECX the number of bytes to transfer (length of new ANSI text)
JECXZ >L1                        ;if ECX=0 don't do the next instruction
REP MOVSB                        ;move ECX bytes from [ESI] to [EDI]
L1:

Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)