-----------------------------
                        Win32 Programming in Assembly
                        -----------------------------
                                by: device

                               ------------
                               Introduction
                               ------------

        Welcome to windows 32 bit assembly programming.  If you want to take
part in the new trend of win16/32 viruses currently being made, but don't have
a clue about how to program windows at the assembly level, than this is the
article for you.  This article will assume that you know pretty much nothing
about windows at this level.  If you've ever programmed a windows program
in C(not C++), than this will be a lot easier for you, as the structural as-
pects of windows programs are already familiar to you.  If you've programmed
with C++(MFC), than you're better off just forgetting everything you've done
with that, because it will just hurt you in the end, as it shields you from
the way windows applications really work.  As a conclusion, although there
are no prerequisites for this article, it would greatly help if you've made
windows programs in languages like C, and it is pretty much mandatory that
you be familiar with assembly language itself, because it won't be covered at
all, unless there is something done that is not usually seen in common
programming.

        Although the structures of win16 and win32 programs are similar, this
article will focus on win32.  As an assembler, I use TASM 5.0.  That's what
the source code to this article will assemble with.  I don't know if it'll
assemble with anything else, so you may need to make some modifications
before trying to assemble it with another assembler(like MASM).

        Of course you don't need to know how to build a full win32 program in
assembly to make a virus, but, it does help to know how to do it.  To
demonstrate the basic structure of a win32 program, I've made a small program
called win32app.  It just displays a window, and when you click the mouse on
the window, it gives you a message.  It's nothing amazing, but it's simple
enough to demonstrate windows 32 bit programming in assembly.

        The bad thing that's happening is that the high level application
development systems(like VC++,MFC,VB) are giving windows a bad name, because
of the big, bloated, slow, and dll hungry programs that they create.  But,
once you make your first windows program completely in assembly(with notepad!)
your view about windows programming in general may change.  You'll see that
windows programming is not as hard as you may have thought it was.  And,
there are benefits too. You have access to all of the memory on the computer
(plus more!), and everything is 32 bit in a flat memory model, so you'll
never have to worry about segments!  You'll also see that windows programs
can be just as fast as dos programs(graphics are another story, though), when
written in assembly.

        This article only goes over the basics, so if you decide that you
like win32 programming in assembly, you can move on to the next article in
this series which shows you how to write and explains the source code to a
win32 file encrypter program written in assembly.  This tutorial will
demonstrate some of the more advanced features of windows programming, such
as file input/output, using dialog boxes, using common controls, and how to
structure your program to allow background tasks to run.  If, when finished
reading this, you become interested in making regular windows applications in
assembly(or any language, for that matter), you should get a copy of the win32
SDK help files(a one of those 2000 page books), because there are hundreds and
hundreds of API calls available.  But for now, lets start with the basics.

                        ------------------------
                        Windows message handling
                        ------------------------

        OK, this is the part of windows programs that most separates them
from dos programs.  First, let's review some of the basic differences between
how dos and windows programs are run.  When a dos program is run(in true real
mode), the operating system passes control to the program, and program runs
from top to bottom.  The dos program can do whatever it wants, and can keep
control of the computer for as long as it wants.  It has complete control
over the processor and the resources of the computer.  This is good for some
programs(like games), but when it comes to running more than one program at a
time, giving this kind of freedom to a program wouldn't work out too well.
The general idea behind a multitasking OS is that the programs should not be
able to interfere with any other running programs in any way(unless the
programs are specifically made to share data).  They should also not have the
freedom to communicate directly with hardware, as it needs to be shared with
the other applications.  The Intel processors provide hardware to implement
some of these things, and windows 9x/2K/NT take advantage of it.

        The way that windows multitasks is by preemptive time slicing.  Every
few milliseconds, control is taken away from one task and given to another.
There are many things that can effect this and throw the timer off slightly,
but generally it is done every few milliseconds.  Windows also provides an
API for programs to use.  This API is used to do pretty much anything that a
windows program could ever want to do, including displaying windows, drawing
on the screen, communicating with hardware, and file input/output.  In fact,
windows applications are forced to use this API for the most part.  This
ensures that most low level operations are performed by trusted software, so
a crashed program is handled easily as it doesn't usually leave the hardware
in an unrecoverable state.  Technically, programs do not have to use the
API(there are ways around it), but most do.

        Another major difference between windows programs and dos programs is
that windows forces its programs to use what's called a message loop.  A
message loop is a software loop coded in each windows program that
continuously polls windows for new messages.  A message in windows is
something that the operating system sends to a program to notify it of an
event that occurred that may have an affect on the program.  Examples of windows
messages are mouse clicks, window changing position, timer ticks, etc.  This
works out well, because due to the nature of windows programs(graphical), it
is more natural to have the operating system tell the program what the user
does, instead of forcing the program to check manually for such events as
button presses, or force the program to continually poll the mouse.

        Here's what actually happens with the message loop: When windows
receives messages, it puts them in a message queue.  A queue is a form of a
linked list in which new links are added to the end, and old links are popped
off the top.  The program then checks(via the API) that queue to see if any
new messages have been put in.  When a message is retrieved, it is removed off
of the queue, some intermediate operations may be performed on it, and it is
sent back to windows.  Windows will then take that message and call one of
the program's message handling functions with the message and any extra data
as parameters to that function. If all that sounds confusing, don't worry
about it.  You don't have to understand the way windows processes messages
internally.  The important thing to know about retrieving messages, however,
is that in your program you must have a special function called a CALL BACK
FUNCTION.  A call back function is a function that you do not call directly in
your program, but instead gets called by windows.  When your program receives
a message, windows will eventually call your call back function with a description
of the message so that the program can handle it.  For example, you might want
to have the computer make a beep sound every time the mouse button is pressed.
The way you would do that is by putting the code that beeps in the call back
function.  That way, when the mouse is clicked, windows will notify your
program via the call back function.  The call back function will then check
to see what kind of message it is, and act accordingly(in this case, sound a
beep if it's the mouse click message).

        Most programs have no need for most of the messages that windows can
give.  As you'll see, the win32app program in this article looks only for 2
messages:  one to indicate a mouse click in the window(which will then signal
the displaying of a window), and a message that indicates that the user wishes
to quit the application.  With all that said, let's discuss how these message
loops work at a more technical level and see where and how they fit into a
program.  Keep in mind that large programs may have many message loops
(usually one per window), but, the example program uses only one.

        First off, when the program is first run, it does some initialization,
which we'll get to later.  For now just know that the initialization may include
initializing data, reading disk files, and almost always displaying one or more
windows.  Once the initialization is complete, the program has usually displayed
a window, and ends up in a message loop waiting for messages.  This is where
the program will stay(in the message loop) until it terminates.  This is what
most message loops look like(in pseudocode):

01: Get_Message(msg)
02: If (Message == QUIT)
03:    goto 07
04: Translate_Message(msg)
05: Dispatch_Message(msg)
06: goto 1
07: quit

        Let's go over these steps in detail:

        1. Line 1 is a call to the function that retrieves the messages off
           of the message queue.  When the program calls this function, it
           will not return until there is a message(it doesn't have to be
           this way, but many times it is).  When there is a message, the
           function returns with the message in the MSG variable.
        4. After the message is received, we check to see if the message is
           a quit message(meaning that the user wishes to exit the program).
           If it is a quit message, we exit the loop.
        2. If the message is not a quit message, we move to line 4, where
           the message gets sent to the Translate_Message function.  This
           function performs some intermediate operations on the message,
           but this isn't very important right now for out purposes, so don't
           worry about this.
        3. The message then comes to line 5, where the Dispatch_Message
           function is called.  By calling this function, the program is
           sending the new message back to windows.  Windows will then take
           this message and send it back to the program again!  But this time,
           when windows sends the message back, it will pass it as a parameter
           to the windows' call back function, which is used to handle the
           messages.  Some examples of messages are mouse clicks, button presses,
           and close window.
        4. We then repeat the process over again

        Before we move on, let's step through a typical message.  Let's say
it's a mouse click message, meaning that the user has clicked the mouse
button on the program's window.  First, the user clicks the mouse.  Windows
realizes this and put a message onto the program's message queue a long with
some other data such as the mouse position at the time of the click.  The
program then calls Get_Message(if it didn't already), and retrieves the
message that the user has clicked the mouse button on the window.  The message
then gets passed through the Translate_Message function, then gets send back
to windows via Dispatch_Message.  Windows then takes that message, and sends
it(as a parameter) to the program's message handling function where it is
processed.  By processed, I mean that the program can do whatever it needs to
do.  The program in this article will display a message box when it receives
this particular message, but it's not required that you do anything.  As a
matter of fact, if the program doesn't want or need to handle a certain
message, it can send it back to windows and windows will handle it.

        If all this sending of messages back and forth is confusing, don't
worry.  It takes some time to get used to.  Plus, it's not very critical that
you know this procedure inside and out to make a basic windows program.

                     -------------------------------
                     Creating and displaying windows
                     -------------------------------

        Since interacting with the user is the main purpose of windows programs,
and windows are pretty much the only way to interact with the user, you'll want
to know how to display windows.  Here's what we have to do to display a window:

        1.  Register our Window class
        2.  Create the window from the window class
        3.  Show the window
        4.  Enter in the message loop, and stay here until the user wants to
            exit the program.
        5.  exit

        The first step is called registering your window class.  What this is,
is that your telling windows to create a new CLASS of window(or new type).
Along with that you give windows a description of the properties of that window,
as well as a name for it.  That way, when ever you want to use that type of
window in the future, you need only refer to it by name and windows will
automatically recall all of it's properties(such as its icon, background color,
and message handler), and create it.

        The second step is to create the window.  This step is the easiest,
because all you do is tell windows to create a window of the type that you
just described when you registered the class in the previous step.  And the way
you do that is just by giving windows the name of the class.  Along with this
also comes properties that you would like the window to have, such as whether
you want it to have a system menu, title bar, how big it should be, etc.

        The third step is optional, but is usually done.  It is to show the
window.  This is even easier, because you just tell windows to make the window
appear, and it'll take care of the rest for you.

        The fourth step is the message loop.  Here, the program will stay
until the user wishes to exit.  As you read above, a message loop is just a
software loop that continually polls windows for new messages, or events that
happen that the program may be interested in handling.

        If we get to the fifth step, that means that the user wishes to quit
the program, and the message loop has received a quit message.  So, we quit.
The next few sections will go into these steps in more detail and show you how
to implement them.

                             ---------------
                             Technical Stuff
                             ---------------

        Before we dive into writing assembly code implementations of what we've
been talking about, let's get acquainted with some of the details of assembling
a windows program using tasm 5.0.  The first things that you should put at the
top of your assembly file are these lines:

.386
locals
.model flat,stdcall

        The .386 tells tasm that we'll be using 32 bit code.  We need this
because all win32 programs are 32 bit.  The LOCALS directive tells tasm that
we want to enable local symbols.  Local symbols in tasm are variables or labels
that are inside procedures that begin with '@@'.  That way, by making them
local, you can use the save label/variable names in more than one function,
which is useful.  The ".model flat,stdcall" tells turbo assembler to do two
things: first, the program will be assembled using a flat memory model, which
all win32 programs run in.  The second tells turbo assembler to use the
standard calling convention when calling functions.  Normally this wouldn't
be needed in assembly programs, because all parameters to functions are usually
pushed manually.  But, tasm has some high level features that allow you to
call functions much like you would call them in a language like C, which makes
code about 50 times easier to read.  The STDCALL directive tells tasm that
parameters to functions should be pushed from right to left, and that the
functions themselves will be cleaning up the stack afterwards.  Also at the
top of the program, you'll need to declarations to all the API functions that
you'll be using.  You must declare them with the EXTRN keyword.  See the
example program to see this.

        Now, we'll make sample function to show you tasm's high level features:

#1  Foo proc stdcall, @@param1:dword, @@param2:dword
#2  ...
#3  Foo endp

        In line one, we first have the function name(Foo), followed by PROC,
which tells tasm that it's a function.  Then we have STDCALL, which means that
this function will be called using the standard calling convention.  After
that, comes the parameters to the function.  Each parameter is in two parts:

@@name:size

        The NAME is the name of that variable, and the SIZE is the size of
that variable.  This could be BYTE, WORD, DWORD, etc., but the most common
in win32 assembly is DWORD.  Also notice the @@ in front of the names.  This
tells tasm to make these symbols local to only this function, so that if we
wanted to we could make another function with the same parameters names.  Now,
let's say that we wanted to call the function Foo from our code.  Using the
tasm high level features, it's as easy as this:

call    Foo, eax, ebx

        It's divided into 3 parts:  the first part is the instruction(call).
The second part is the function name followed by a comma, and the 3rd section
contains the parameters, each separated by a comma.  Note that the parameters
can be registers, immediate values, or even memory references.  This saves
a lot of time!

        One other thing that you need at the top of ever win32 program is some
kind of header files that contains all of the constants used by windows.  There
are thousands, so the bigger the header file, the better.  The header file
that I'll be using for this tutorial is WIN32.INC, which is an include file
that comes with tasm.  It doesn't have all of the constants, but it has
enough.  To include a header file, do this:

include win32.inc

        Another small detail, is that before you can make your final executable,
you have to link it with a windows linker.  A windows linker requires something
called a DEFINITION file(*.def), which gives it some information about the
program to be linked.  You DEF files will look pretty much the same for all
of your windows programs.  Here is the one that I use for this tutorial:

NAME		W32SHELL
DESCRIPTION    'Win32 Shell'
EXETYPE         WINDOWS
STUB           'WINSTUB.EXE'
CODE		PRELOAD MOVEABLE
DATA		PRELOAD MOVEABLE MULTIPLE
HEAPSIZE	65536
STACKSIZE	65536
EXPORTS         WindowProc

        There are only a few things that you may want to look at here.  First,
the NAME field is the name of the module.  This can be whatever you want.
Second, the DESCRIPTION field is a one sentence description of your program.
Something else that's interesting is the STUB field, which defines the MS-DOS
program that will be linked in to the top of your windows program, which will
be executed if the user tries to run your windows program in DOS.  The stub
is the program that displays the message "This program must be run in Microsoft
Windows".  But, you can replace this(ordinary dos program) with anything that
you want.  The EXPORTS field is another field that you'll have to worry about.
This is the field that will define all of the functions that windows will call.
Among these are you call back functions(or message handling functions).  As
you can see, I have only one call back function here, because I have only to
handle messages from the 1 single window in the program.  But, if you had
more than one window, and therefore more than one callback function, you would
have too add it to the EXPORTS field of the definition file.

        There are other files that are commonly linked into windows programs.
These are called RESOURCE SCRIPTS.  A resource script is a text file(made by
you or by a resource generator program), that describes all of the programs
resources.  The resources of a program include: dialog boxes, buttons, menus,
images, icons, cursors, and other common controls(like edit boxes).  The
resource file pretty much describes everything that will be interacting with
the user.  But, in this tutorial we won't be making a resource file, because
we don't have any dialog boxes or common controls to deal with.

        Another one of tasm's high level features is the way it handles
structures.  Let's say you've defined a structure like this:

test    struc
        field1  dd ?
        field2  dd ?
        field3  dd ?
test    ends

        If you have this structure, you can create a instance of that structure
like this:

        my_struc  test <>

        That will create a variable(my_struc) that will be a structure of type
TEST.  You can access members of the structure like this:

        mov     [my_struc.field1],eax
        
        The last thing that we have to worry about is how to assemble/link
the program after all of the code is finished.  Here is how you do that,
assuming that the assembly file is called TEST32.ASM:

tasm32 /ml /m test32
tlink32 /c /Tpe /aa test32,,,import32,test32

        The first line assembles the test32.asm file into an object file.
the /ml switch tells tasm to turn on case sensitivity for all symbols.  The
/m switch tells tasm to allow multiple passes to resolve forward references.
The next line will link the object file, the import library, and the definition
file into an executable.  The /c tells tlink to use case sensitivity, and
the /Tpe and /aa switches tell tlink what type of application will be generated.
The first test32 is the object file.  The import32 is an import library that
must be linked to win32 programs to allow access to the API functions.  I use
the one that comes with tasm 5.0, but you may use which ever you would like.
The last test32 is the definition file.  Out of all this will come the final
executable.  Now that we understand those details, let's start coding the
windows app.

                         ------------------------
                         Getting the model handle
                         ------------------------

        The first step that must be performed in a win32 application is the
retrieval(via an API function) of the model handle.  This handle is used in
various other functions(such as creating windows).  Luckily, it's very easy.
All we do is this:

        call    GetModuleHandleA, NULL  ; return the model handle in EAX
        mov     [mod_handle],eax        ; store it in a variable

        The first line calls the GetModuleHandle API function to retrieve the
model handle, which will be returned in EAX(like always).  Then, it is simply
stored in a global variable for later use.

                         ----------------------
                         Registering the Window
                         ----------------------

        Before we show or even create our window, we have to register its
window class.  This simply describes the window to windows, giving it some of
its properties(including icon, background color, and NAME).  Then, to refer to
or to create that window in the future, all we need to do is refer to the name
of the class, and windows will automatically call up all of it's properties.
So how do we register a windows class?  First we have to create a window class
structure to fill out.  We will fill out this window class structure with the
information about our window, then pass it to windows.  (NOTE: the following
symbols may be different, depending on which header file you chose):  Anyway,
the window class structure looks like this:

WNDCLASS struc
        clsStyle          dd ?   ; class style
        clsLpfnWndProc    dd ?   ; pointer to message handling function
        clsCbClsExtra     dd ?   ; set to zero
        clsCbWndExtra     dd ?   ; set to zero
        clsHInstance      dd ?   ; instance handle of application
        clsHIcon          dd ?   ; class icon handle(icon to be used for window)
        clsHCursor        dd ?   ; class cursor handle(cursor to be used for window)
        clsHbrBackground  dd ?   ; class background brush(background color)
        clsLpszMenuName   dd ?   ; menu name(if any)
        clsLpszClassName  dd ?   ; pointer to class name
WNDCLASS ends

        The clsStyle field holds various properties and styles about the
window.  The clsLpfnWndProc field is a pointer to a message handler function
for this window, which we'll create later.  The clsHInstance is the module
handle that we retrieved earlier.  The clsHbrBackground field is a BRUSH that
tells windows the background color of the window.  Brushes are very powerful
in windows.  They allow you to specify colors or patterns to fill a surface
with, but we're not going to be covering them here, just to keep it simple.
The clsLpszMenuname is the name of the menu that will be shown at the top
of the window.  Our window will not have a menu, though.  The clsLpszClassName
is the name of the class that we would like this window to have, and with
which we will refer to this window in the future.

        Next, we create a instance of the WNDCLASS structure.  This would
normally be a global variable put in the data segment.  The following will
create a variable named 'wclss' of type WNDCLASS:

wclss   WNDCLASS <>

        Now we have to fill out that structure with the details of our window.
That is done like this:

#1       mov     wclss.clsStyle,CS_HREDRAW or CS_VREDRAW
#2       mov     wclss.clsLpfnWndProc,offset WindowProc
#3       mov     wclss.clsCbClsExtra,0
#4       mov     wclss.clsCbWndExtra,0
#5       mov     eax,[inst]
#6       mov     wclss.clsHInstance,eax
#7       call    LoadIconA,NULL,IDI_APPLICATION
#8       mov     wclss.clsHIcon,eax
#9       call    LoadCursorA,NULL,IDC_ARROW
#10      mov     wclss.clsHCursor,eax
#11      mov     wclss.clsHbrBackground,COLOR_BACKGROUND
#12      mov     wclss.clsLpszMenuName,NULL
#13      mov     wclss.clsLpszClassName,offset classname
#14      call    RegisterClassA,offset wclss

        Once again, for a complete and detailed listing of all of these
functions, get the SDK.  I'll discuss some here, but you may want more
information if you plan to make more advanced windows programs.  Line 1
sets the style of the window class.  CS_HREDRAW and CS_VREDRAW tell windows
to redraw the window when it is resized horizontally or vertically.  You don't
have to worry about that, just put it there.  Line 2 is important.  It gives
windows the address of our message handler.  Again, the message handler is
nothing more than a function that windows will call to notify your program
of any messages that might affect it.  Lines 5 and 6 take the module handle
of the program and store it in the WNDCLASS structure.  This is just something
that windows needs.  Line 7 loads the standard application icon to use with
this window, then on line 8 it is stored in the structure.  Line 9 loads the
standard mouse cursor for use with this window and line 10 stores it in the
structure.  As I said above, line 11 uses a brush to set the background color,
but we're not going to cover brushes here.  In line 13 we give windows the
window class name that we would like the window to have.  And finally, in
line 14, we register the class, passing the address of out WNDCLASS structure
to the RegisterClass function.

                          -------------------
                          Creating the Window
                          -------------------

        After we've registered the window class, we must create the window.
Luckily, this is very easy.  We use the CreateWindowEx function, as follows:

call    CreateWindowExA, 0,                     ; extended window style(none)
                         offset classname,      ; class name of window to create
                         offset windowtitle,    ; title of window
                         WS_BORDER or WS_SYSMENU; style
                         200,                   ; x position of window on screen
                         200,                   ; y position of window on screen
                         640,                   ; width in pixels of window
                         480,                   ; height in pixels of window
                         0,                     ; handle to parent window(none)
                         0,                     ; menu handle(none)
                         instance,              ; handle of application(module handle)
                         0                      ; pointer to window creation data(none)

        mov     hmainwnd,eax                    ; store returned window handle

        The parameters of this function are pretty much self explanatory.
The class name is the name of the class that we have just registered.  The
window title is just an ASCIIZ string that will be the title of the window.
The style field describes the way that a window will look.  Again, I highly
recommend getting the win32 SDK or help files, because there are many
styles that window can have, and I can't list everything here.  After we've
registered the class, the window handle is returned in EAX, which is stored
in a global variable for later reference.

                          ------------------
                          Showing the Window
                          ------------------

        After we've created the window, we have to display it so that the user
can see it.  This is very easy:

	call	ShowWindow,hmainwnd,SW_SHOWNORMAL

        The function is ShowWindow, which can actually either show or hide
a window.  In this case, we're showing it.  The first parameter is the handle
to the window that was returned by CreateWindowEx.  The 2nd parameter is a
constant that tells windows how to show it(i.e. minimized, maximized, normal).
When this function returns, however, the window will not yet be displayed.
There is one more step before out window is displayed: The Message Loop.

                            ----------------
                            The Message Loop
                            ----------------

        Before we enter into the message loop, we have to create the message
structure.  This message structure will hold a single message that is received
from windows.  To do that, we do this:

        message MSGSTRUCT <>

        This creates a variable called 'message' that is of type MSGSTRUCT.
This structure will hold a single message received from windows.  This would
usually be stored as a global variable.  Once we've created the message
structure, we're ready to enter into the loop.  If you're familiar with the
psuedocode of the message loop presented earlier, the code will look pretty
straight forward.  Here it is:

#1      msg_loop:
#2              call    GetMessageA,offset message,0,0,0
#3              cmp     ax,0
#4              je      end_loop
#5              call    TranslateMessage,offset message
#6              call    DispatchMessageA,offset message
#7              jmp     msg_loop
#8      end_loop:
#9              call    ExitProcess,message.msWPARAM

        In line two, we call the GetMessage function will wait for a message
to be sent from windows.  When a message comes, it will return with the message
in the MESSAGE structure.  In lines 3 and 4 we check to see if the value
returned from the GetMessage function is 0.  If it is, that means that the
user wants to quit, so we should exit the loop.  We exit the loop at line 8,
and on line 9 we call the ExitProcess API function that will terminate our
program.  Lines 5 calls the TranslateMessage function to perform some
intermediate operations on the message, and then line 6 sends it back to
windows so that windows can call our message handling function.  But how do
you create the message handling function that we've been talking about for
all this time?

                           -------------------
                           The Message Handler
                           -------------------

        The message handler for a window is nothing more than a normal function
that is called by windows.  It takes special parameters that are given to it
by windows to describe the message.  Here is the skeleton for the function:

WindowProc proc stdcall, @@hwnd:dword,@@wmsg:dword,@@wparam:dword,@@lparam:dword
        ...
WindowProc endp

        The first parameter to this function is the handle to the window that
generated this message.  This is used for various purposes, like drawing to
the window.  The next parameter is the actual message itself, so that we can
figure out what the message is, so that we can act accordingly.  Note that
the message parameter is not a message structure, but instead just a dword.
The next two parameters carry extra data that helps to describe the message.
For instance, on a mouse click message, they hold the position and button
status of the mouse.

        Now what are we going to put in the message handling function?  Well,
the message handling function has to do a few things:  first, it has to figure
out which message was sent.  Then, it will decide whether that message is
important.  If it isn't, it tell windows to handle it and then exit, but if
it is important, it will just to the code that will handle that event.  Here's
some psuedocode to illustrate this:

if (message == MOUSE_LEFT_BUTTON_DOWN)  ; is the message a mouse click message?
    DisplayMessageBox(...)              ; if so, display a message box
if (message == DESTROY_WINDOW)          ; is it a message where the user is trying
    PostQuitMessage()                   ; to close the window?  If so, they want
                                        ; to quit, so add a quit message onto the
                                        ; message queue to quit the program.
else
    Tell_Window_To_Handle_It()          ; we don't need this message, so let
                                        ; windows handle it.

        The first line tests to see if it's a mouse event, and if it is, it
will display a little message.  That's pretty straight forward.  The 3rd line
tests to see if the user is trying to close the window.  The reason why we
do this is to allow the user to exit the program.  You see the user does not
have the ability to actually exit the application themselves with the mouse.
All the user can do is close the window(i.e. clicking the X in the top right
hand corner).  So, we assume that when the user is closing the window, they
want to exit the program.  That's why we test to see if the user is trying
to DESTROY the window(close it).  Actually, when the user closes the main
window, the application doesn't have to exit.  An application can exist just
fine with no windows at all.  But, when people close the main window of the
program, that usually means that they want to exit the entire program.  So
therefore, to tell when the user wants to quit, we just test to see if the
user is trying to close the main window.  When the program has determined that
the user wants to quit, it will call a function that will manually add a message
to the message queue(the linked list where pending messages are kept).  That
way, the message loop that coded earlier will receive that message and exit.
The last two lines will handle the message if we don't want it.  Most of the
messages that we'll receive we don't even need or want.  But, all messages
have to be handled, to any messages that we don't need, we give to windows
to handle for us and that's it.  Once again, I suggest you get the help
files from the win32 SDK, because there are hundreds of messages that you
might want to handle.

        The following is the assembly implementation of what was just discussed.
There is nothing tricky with this code.  If you understand the psuedocode
presented above, you won't have a problem with this.  Once again, this is
what would go inside the message handling function(for our program):

;-----------------------------------------------------------------------------
        mov     eax,@@wmsg                      ; put message in eax
        cmp     eax,WM_LBUTTONDOWN              ; is it mouse press?
        je      button_down                     ; if so, handle it.
        cmp     eax,WM_DESTROY                  ; user trying to exit?
        je      destroy_window                  ; if so, post quit message
        call    DefWindowProcA, @@hwnd,@@wmsg,@@wparam,@@lparam ; let windows
                                                ; handle the messages we don't
                                                ; want.
        ret                                     ; return.
button_down:                                    ; here we'll handle the mouse
                                                ; event--display a message.
        call    MessageBoxA,@@hwnd,             ; handle of parent window.
                            offset string1,     ; the string to display.
                            offset title1,      ; title of message box
                            MB_OK               ; type of message box
        xor     eax,eax                         ; return 0
        ret                                     ; return

destroy_window:                                 ; here we handle the user quitting
        call    PostQuitMessage,0               ; manually add quit message to queue
        xor     eax,eax                         ; return 0
        ret                                     ; return

WindowProc endp
;-----------------------------------------------------------------------------

        This is pretty straight forward.  Some parts to notice are: WM_LBUTTONDOWN
and WM_DESTROY are constants defined in the header files.  The DefWindowProc
function is used to tell windows to handle messages that we don't want.
The MessageBox function is used to display a message on screen.  The first
parameter is the parent window(which is our main window).  The parent window
is a window that "owns" the window.  The next two parameters are ASCIIZ strings
that are the string to display and the title of the message box.  The last
parameter is the type of message box to display.  MB_OK will display a box
with no icon, and just an OK button.  The PostQuitMessage function is used
to manually put a quit message on the message queue, so that the message loop
will eventually receive it and exit the application.

                        ---------------------------
                        The final Program--Win32App
                        ---------------------------

        OK, here it is.  The full win32App source code.  Its code is made up
of all of the bits and pieces of code that were presented in this text exactly
as you saw them.  So basically it's just everything you've learned put together
into one final program.  It will display a window, and display a message box
every time you click the mouse on the window.  You may be surprised at how
short it is(or maybe not).  NOTE:  this program is not commented, because there
is really nothing new in it.  It's just a collection of all the pieces of code
(which are explained in detail) in this text.

;=============================================================================
;= WIN32APP.ASM
;=============================================================================

        .386
        locals
        .model          flat,stdcall

        include         win32.inc

	NULL		equ 0

        extrn           GetModuleHandleA : proc
        extrn           LoadIconA        : proc
        extrn           LoadCursorA      : proc
        extrn           RegisterClassA   : proc
        extrn           CreateWindowExA  : proc
        extrn           GetMessageA      : proc
        extrn           TranslateMessage : proc
        extrn           DispatchMessageA : proc
        extrn           ExitProcess      : proc
        extrn           DefWindowProcA   : proc
        extrn           PostQuitMessage  : proc
        extrn           MessageBoxA      : proc
        extrn           ShowWindow       : proc

.data
        inst            dd 0
	hmainwnd	dd 0
        wclss           WNDCLASS <>
        message         MSGSTRUCT <>
	windowtitle	db 'Win32 Shell',0
	classname	db 'win32win',0

        string          db 'Left Mouse button pressed',0
        title           db 'Note:',0

	public		WindowProc

.code

start:
        call    GetModuleHandleA,NULL
        mov     [inst],eax

        mov     wclss.clsStyle,CS_HREDRAW or CS_VREDRAW
        mov     wclss.clsLpfnWndProc,offset WindowProc
        mov     wclss.clsCbClsExtra,0
        mov     wclss.clsCbWndExtra,0
        mov     eax,[inst]
        mov     wclss.clsHInstance,eax
	call	LoadIconA,NULL,IDI_APPLICATION
        mov     wclss.clsHIcon,eax
	call	LoadCursorA,NULL,IDC_ARROW
        mov     wclss.clsHCursor,eax
        mov     wclss.clsHbrBackground,COLOR_BACKGROUND
        mov     wclss.clsLpszMenuName,NULL
        mov     wclss.clsLpszClassName,offset classname
        call    RegisterClassA,offset wclss

        call    CreateWindowExA,0,offset classname,offset windowtitle,
                                WS_BORDER or WS_SYSMENU or WS_MINIMIZEBOX,
                                200,200,640,480,0,0,inst,0
        mov     [hmainwnd],eax
	call	ShowWindow,hmainwnd,SW_SHOWNORMAL

msg_loop:
	call	GetMessageA,offset message,0,0,0
	cmp	ax,0
	je	end_loop
	call	TranslateMessage,offset message
	call	DispatchMessageA,offset message
	jmp	msg_loop
end_loop:
        call    ExitProcess,message.msWPARAM

WindowProc proc stdcall, @@hwnd:dword,@@wmsg:dword,@@wparam:dword,@@lparam:dword

        mov     eax,@@wmsg
	cmp	eax,WM_LBUTTONDOWN
	je	button_down
        cmp     eax,WM_DESTROY
	je	destroy_window
        call    DefWindowProcA, @@hwnd,@@wmsg,@@wparam,@@lparam
	ret
button_down:
        call    MessageBoxA,@@hwnd,offset string,offset title,MB_OK
	xor	eax,eax
	ret

destroy_window:
	call	PostQuitMessage,0
	xor	eax,eax
	ret

WindowProc endp

	end	start
	end

;=============================================================================
;= WIN32APP.ASM
;=============================================================================

-device