Win32 Programming with NASM

0. Introduction
1. Who the package is for
2. What the package provides
3. What the package doesn't provide
4. Pros and Cons
5. Basic concepts
6. Unicode
7. Windows header files
8. Pitfalls and avoiding them
9. Further information
10. Examples
    Core concepts
      Making use of NASM's power
      Hello world from a message box
      Hello world from a window
      Hello world from a console window
      Keyboard reader
      Mouse reader
      Command line displayer
      DLL
      Files
      Icons and cursors
      Character strings
      Menus
      Child windows
      Child window controls
      Window subclassing
      Window superclassing
      Dialog boxes
      Debugging
11. Conclusion

------------------------------------------------------------------------------

Introduction
    Win32 applications have a lot to offer:

        o Huge target base of machines running Windows 9x or NT (now 2000)

        o Transparent support for massive hardware base via a common API that
          masks differences and implementation

        o Large and diverse API that handles many things, including:

          o GUI

          o Networking

          o Mouse / keyboard input

          o Sound (samples and MIDI)

          o Graphics (fonts, icons, bitmaps, DirectX for lots more)

          It should be noted that all of these would have required lots of
          custom code or libraries in the past, and it was difficult to ensure
          that your code worked on all hardware configurations as there was
          little standardisation (well, there was, but everyone went their own
          way in this regard...). Also note that there was no standard user
          interface and the quality of much of the above varied greatly between
          vendors (and even between vendor's products!).

    All those things sure look nice compared to having to practically do
    everything by hand in DOS... However, Win32 applications have traditionally
    been written in some form of HLL, mainly C. With today's tools that is
    changing even more to include C++, Object Pascal and Visual Basic. Let's
    get one thing clear to start with though -

        Writing Win32 applications in x86 assembler is _easy_.

    Yeah, that's right, it's _easy_. Well, providing you already have a basic
    understanding of x86 assembler and can grasp the Win32 programming model,
    that is.

------------------------------------------------------------------------------

Who the package is for
        o You want to write Win32 applications or DLLs fully in assembler

        o You're not frightened by this prospect (indeed, you relish it :)

        o You've got a basic grasp of x86 assembler, and understand (or at
          least can use) a memory model where all code and data is referenced
          without segment registers

        o No previous knowledge of Win32 is assumed or expected

        o You're willing to do some work in your own time to learn more about
          writing Win32 applications and the Win32 architecture - you won't
          get all the answers spoon-fed to you here

    Extra credit
        o You've already done some Win32 programming

        o You've got a good grasp of x86 assembler

        o You know C (even a little)

        o You've got all of the above :)

------------------------------------------------------------------------------

What the package provides
        o An include file with the major Win32 equates, etc.

        o The linker to turn the NASM output into executables

        o A help file detailing much of the core Win32 API (separate download)

        o Docs and examples

------------------------------------------------------------------------------

What the package doesn't provide
        o A tutorial on writing Win32 applications. Whilst I've tried to cover
          all the mechanics of how a Win32 program works and how you can write
          one, I've had to leave out much of the theory and in-depth details as
          this is the sort of thing best left to books. I've got two:

            o Programming Windows, 5th edition by Charles Petzold, published
              by Microsoft Press, 1500 pages, RRP $60 UK57
                + Well written and readable
                + Covers the Win32 core - keyboard, mouse, windows, dialogs,
                  resources, controls, fonts, bitmaps, clipboard, GDI, printing,
                  multimedia, DLLs, multithreading, MDI and more
                + Covers almost all topics extensively
                + Source code is in C
                + Comes with a CD of all the source code and the whole book
                  as a HTMLHelp file
                + Far larger and more detailed than any other book I've
                  come across
                - More expensive than other books
                - Beginners book - doesn't go into any advanced topics
                  beyond the basics, eg DirectX, COM, ADO, etc.
                - Looking dated - nothing on common controls or any of the
                  the recent GUI enhancements. In particular, very little on
                  networking - the paltry internet section has a tacked-on
                  feel to it
                  
            o Windows 98 Programming from the Ground Up by Herbert Schildt,
              published by Osborne, 809 pages, RRP $35 UK28
                + Covers dialogs, controls, resources, graphics, tree views,
                  property sheets, wizards, help files, the registry, screen
                  savers and ActiveX.
                + More up to date
                - Broad scope means less detail and information on each topic
                  than Programming Windows, number of topics addressed in the
                  book's size may leave the reader feeling 'rushed'
                - Source only available to download from http://www.osborne.com
                - A colleague has told me the book is not looked on favourably
                  in the Win32 newsgroups, mostly because it contains errors
                  that the author has refused to correct or make corrected
                  source code available for.

          I don't really recommend the second book, to me it doesn't
          introduce anything that you couldn't figure out from searching the
          web and perusing MSDN, etc.

          The first is a great beginners book, if you can afford it, but
          after mastering the basics you'll quickly outgrow it. Only buy it
          if you want a good beginners book on Windows programming.

          If you decide to go looking for a book (which I recommend you do at
          some stage) you'll no doubt be left slightly bewildered by the huge
          number of them about Win32 programming. Be _very_ careful about which
          one you choose - despite the titles, many of the recent ones are
          aimed primarily at C++ (particularly used with the Microsoft
          Foundation Classes, or MFC for short), Visual Basic and other such
          HLLs. For programming in assembler, these are _no good_. You want
          one which uses C, like Programming Windows. Translating C to x86 is
          fairly straightforward, C++ or VB is definitely not. Besides, Win32
          was designed with C in mind so why make things difficult?

------------------------------------------------------------------------------

Pros and Cons
    Writing Win32 applications in x86 assembler has several advantages and
    disadvantages, which are described below:

        + You can obtain the best performance with the power of assembler, and
          without the hinderance of OO (or HLL messiness like the MFC) or the
          HLL itself (Visual Basic springs to mind at this point...)

        + If you like, you can write the majority of your code in the HLL of
          your choice and the critical parts in assembler as a DLL (if you
          don't like inline assembler or your HLL doesn't suport it, or
          doesn't support it to a great degree)

        + Win32 was designed for C programming, and C is easily mapped to x86

        + You _have_ to understand the API, which is important in writing
          efficient Win32 programs and in understanding how Windows works. To
          get the most out of Windows you really have to get to grips with the
          API at some point, even if you use a HLL that hides this for the
          most part (eg Delphi)

        - Unportable code. At one time, people would boast of how Win32
          applications could be compiled for x86, MIPS, Alpha, PowerPC, 680x0,
          Mac and the forthcoming IA64 architecture by changing a define in
          their code, assuming their code was written in a portable way of
          course. Then, seeing the tiny markets, Microsoft began dropping
          support for all but x86, IA64 and DEC Alpha, and has now finally
          given up Alpha as well. Since Itanium (formerly Merced), Intel's
          IA64 chip, will still run existing code I don't see this as an issue.

        - Lack of standard HLL libraries, though Win32 does have a lot of
          support for common functions and memory handling

        - You need to be careful with how you write your code, as a HLL would
          automagically steer clear of potential pitfalls

------------------------------------------------------------------------------

Basic concepts
    Writing a Win32 program consists of several steps:

        o Write the source code in your favourite text editor or IDE

        o Assemble with NASM to an object file

        o Link the object file with the Win32 DLLs and any user-defined DLLs
          or resources

    For the moment, we don't need to consider steps two and three - we'll cover
    these when we get to the examples - so we can concentrate on how we write
    our source code.

    You're probably used to using sections in your assembler programs, and Win32
    is no exception. There are three we use:

        o [section .text]
          This is where all your actual code goes

        o [section .bss]
          You can place all your uninitialised data here (ie resb stuff)

        o [section .data]
          All your data goes here

    Win32 programs run in a flat memory model so you need never worry about
    sections and don't need to refer to any of the segment registers. They're
    32-bit so all addresses are dwords, almost every variable type is also a
    dword and 32-bit registers should be used.

    You will often want to call an API function, and this can be done by
    knowing the parameters the particular function takes. Here's where some
    knowledge of C comes in useful, as does a good API reference. Don't
    panic if you've not got any, but don't skip this bit!

    A commonly used API call is MessageBox, which displays a small dialog box
    on screen with an icon and one or more buttons (usually Ok, Ok or Cancel
    or some combination like this). It's defined in the API as:
    
        int MessageBox(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)

    We need to be able to map this into a form usable for us. We know that
    almost every data type in Win32 is a dword, so it seems logical to assume
    that all the parameters are dword in size. In fact, this is true, but we
    have to be careful - lpText and lpCaption are dwords but refer to the
    strings to be used in the message box. We might call this by (in C):

        MessageBox(NULL, "A simple message box, click Ok", "Demo", MB_OK)

    Hold it, what's NULL and MB_OK? NULL is actually 0 and MB_OK is a constant
    defined for Win32. You don't need to worry about this yet. Notice how in a
    HLL we can just put the text we want into the function call, but how do we
    do this in assembler? It's obvious we can't just fit it into a dword.

    The answer lies in how Windows treats parameters that aren't dword (or
    word or byte for that matter) in size - instead of the parameter itself
    these are passed by the _address_ of the parameter. So, knowing this, we
    can say how we'll refer to the four parameters in assembler:

        hWnd        NULL              dword constant
        lpText      _textvar          address of _textvar in memory
        lpCaption   _captionvar       address of _captionvar in memory
        uType       MB_OK             dword constant

    Where the two strings are defined in the data section something like:

        _textvar    db "A simple message box, click Ok",0
        _captionvar db "Demo",0

    Note how they've been null-terminated, almost all strings in Win32 are
    defined in this way. But how about calling the function itself? We have to
    be able to pass these parameters to it as well. All (bar one) functions
    are called in a standard method:

        o Push the parameters onto the stack, _in the reverse order of their
          API definition_

        o Call the function via the call instruction

        o You don't need to tidy the stack as the function takes care of
          this for you

    So, to call the MessageBox function we'd do:

        push    dword MB_OK           ; constant
        push    _textvar              ; address of _textvar
        push    _captionvar           ; address of _captionvar
        push    dword NULL            ; constant
        call    MessageBox            ; call the function

    Unfortunately, this won't work. Function names are like this in C, but
    not in assembler. Because of the way things work, we need to prefix an
    underscore to the function name, and also need to add an @ sign and the
    total size of the parameters passed. Continuing the MessageBox example,
    it takes four dword parameters = 16 bytes total, so we end up with
    _MessageBox@16 for the function call.

    But this still isn't the end of the story. Win32 often has two versions
    of the function, denoted by a single letter before the @ sign - A or W.
    The two versions of MessageBox are _MessageBoxA@16 and _MessageBoxW@16.
    I'll discuss the reasons for this in the Unicode section, so for now
    just accept there are two versions of most functions.

    All that typing sure is a lot of work, you really tire of it after
    doing a few API calls and quickly coding them up is a pain. We can use
    NASM's powerful macro abilities to make this easier though by defining
    a general macro which actually calls the API and specific equs for
    each API call. Why do a two-stage process like this? We can ensure that
    the correct number of parameters are passed, which is _much_ better
    than crashes due to the wrong number of pushes. After this, we can make
    API calls with the following code:

        sc MessageBox, NULL, _textvar, _captionvar, MB_OK

    Notice how much easier this is than all those pushes. Also, you don't
    need to remember the messy call details and when you have lots of API
    calls your code stays manageable. The sc, in case you're wondering,
    stands for stdcall. For those of you that like more meaningful macro
    names, you can also use api, invoke and stdcall. So, the following are
    all exactly the same:

        invoke  MessageBox, NULL, _textvar, _captionvar, MB_OK
        sc      MessageBox, NULL, _textvar, _captionvar, MB_OK
        stdcall MessageBox, NULL, _textvar, _captionvar, MB_OK

    Having said that, we need equs for all the API calls with two versions,
    and also every API call used in a program needs to be declared so that
    NASM knows where the address of the function is. For the moment, don't
    worry about this, all will be explained a bit further on.

------------------------------------------------------------------------------

Unicode
    A while ago, the ASCII character set was more than enough. It had all the
    characters you'd ever need and each character was only a single byte. It
    had also been thought up by programmers and was easy to use. Nowadays,
    support is expected for languages and character sets throughout the world,
    and one byte just isn't enough. Hence, a new standard was thought up -
    Unicode.

    In Unicode, each character is two bytes and this can hold all the character
    sets you'll ever need. Unfortunately, this clearly presents problems for
    us - what do we do with function calls that take strings (as now they'll
    be two bytes / character) and what do we do with existing software?

    Win32 brought the answer to this - for functions which require it, there
    are two versions, an ASCII one and a Unicode one. To differentiate the two,
    we place a marker within the function name - an A (for ASCII) or a W (for
    Wide characters). Hence, now you can see why MessageBox actually has two
    functions defined for it (_MessageBoxA@16 and _MessageBoxW@16).

    The question you should be asking though is why HLL people have never seen
    this. In actual fact, their include files contain macros that put in the
    correct function call depending on whether they're using Unicode or not.
    Hence, you only ever call MessageBox regardless of whether you want to
    use Unicode or not.

    Where does this leave us? This is covered in more detail below, but suffice
    to say that you'll only ever call the macro and you'll tell NASM whether
    to use the ASCII or Unicode version.

------------------------------------------------------------------------------

Windows header files
    If you're writing a Win32 application in C you need to have all the API
    calls declared before you can use them. Also, you like to be able to use the
    nice names for constants (eg MB_OK) rather than unfriendly numbers.

    To do this, you include a header file, typically called windows.h. In actual
    fact, this then includes a lot of other files but that isn't really
    important. What is, is that all the API functions and the named constants
    are defined in the header files so we'll use a similar idea. I'll
    illustrate this with a quick excerpt from a header file:

        #define MB_OK                       0x00000000L
        #define MB_OKCANCEL                 0x00000001L
        #define MB_ABORTRETRYIGNORE         0x00000002L
        #define MB_YESNOCANCEL              0x00000003L
        #define MB_YESNO                    0x00000004L
        #define MB_RETRYCANCEL              0x00000005L

        WINUSERAPI
        int
        WINAPI
        MessageBoxA(
            HWND hWnd ,
            LPCSTR lpText,
            LPCSTR lpCaption,
            UINT uType);
        WINUSERAPI
        int
        WINAPI
        MessageBoxW(
            HWND hWnd ,
            LPCWSTR lpText,
            LPCWSTR lpCaption,
            UINT uType);
        #ifdef UNICODE
        #define MessageBox  MessageBoxW
        #else
        #define MessageBox  MessageBoxA
        #endif // !UNICODE

    Basically, this defines the actual numbers used for the constants so we don't
    have to remember them (and can use the nice names instead) and the function
    itself. In assmbler, we'd have something like:

        MB_OK                 equ 0
        MB_OKCANCEL           equ 1
        MB_ABORTRETRYIGNORE   equ 2
        MB_YESNOCANCEL        equ 3
        MB_YESNO              equ 4
        MB_RETRYCANCEL        equ 5

        EXTERN _MessageBoxA@16 ; actual API name, we will always refer to it by
                               ; the more friendly MessageBox though
        MessageBox@16 equ _MessageBoxA@16

    Note that I've only done the ASCII version and that we have to use the EXTERN
    keyword to say the the _MessageBoxA@16 label refers to an address that isn't
    defined in this file (it will actually be defined when we link it later).

    A quick glance at the API reference shows that there are a _lot_ of API calls
    and an even greater number of constant definitions. Fortunately, I've done
    most of the hard work for you already and have currently done the main windows
    header files. That means all the constants and macros for all the API calls.

    All of these are defined in Windows.inc, found in the Include directory. To
    make assembly as fast as possible, you need to tell NASM which bits of the
    include file you want to use, by defining any of the following, hopefully
    which bits they represent should be self-explanatory:

        _WINNT_
        _WINERROR_
        _WINMESSAGES_
        _WINACCESSIBILITY_
        _WINCOLOR_
        _WINCONSOLE_
        _WINCLIPBOARD_
        _WINDDE_
        _WINDEBUG_
        _WINDEVCAPS_
        _WINESCAPES_
        _WINEVENTS_
        _WINFONTS_
        _WINHELP_
        _WINHOOK_
        _WINIMAGES_
        _WINIME_
        _WINIO_
        _WINMDI_
        _WINMETAFILES_
        _WINNETWORK_
        _WINNLS_
        _WINOEMRESOURCE_
        _WINOPENGL_
        _WINPERFMON_
        _WINPRINTER_
        _WINPROCESS_
        _WINREGISTRY_
        _WINSECURITY_
        _WINSERVICES_
        _WINSHELL_
        _WINSYSTEM_
        _WINVER_
        _WINVKEYS_

    So if you wanted support for messages (which almost every Win32 program
    needs) and virtual keys you'd do:

        %define _WINMESSAGES_
        %define _WINVKEYS_
        %include "Gaz\Win32\Include\Windows.inc"

    The bottom line? When you call an API function, check in the docs which
    header file it's defined in. You can find in the Include\C\C Headers\done
    directory all of the header files that I've done. Every constant and API call
    from these has been converted and is freely useable without any extra work.
    Should you need something from outside these you'll have to start converting
    the API calls and constant definitions by hand I'm afraid. Until you start
    venturing outside the API core though, you shouldn't hit this barrier. In time,
    I hope to increase the API support a lot more.

------------------------------------------------------------------------------

Pitfalls and avoiding them
    There are a number of pitfalls that only occur in assembler, as in a HLL
    these would be taken care of for you automagically:

        o Register usage - eax,ecx and edx are considered scratch registers and
          should be considered undefined upon return from an API call.
          Conversely, ebx, esi, edi and ebp are always preserved across API
          calls and Windows also expects _you_ to preserve them in _any_ code
          that may be called by Windows (ie the Window procedure or callbacks)

        o If you use the MMX registers, be sure to do an EMMS before exiting
          a procedure that may be called by Windows

        o Segment registers should never be altered, though they can be used in
          a read-only manner (indeed they can provide useful information)

        o Windows expects the direction flag to be clear whenever you call an
          API function, and also expects the direction flag to be clear upon
          return from any of your code that Windows calls.

        o All data should be dword aligned

    If you don't follow these rules, don't be surprised if your program
    doesn't work properly or crashes out.

------------------------------------------------------------------------------

Further information
    As described earlier, there are a wide range of books available for Win32
    programming, with many covering specific topics like ADO or DirectX. Whilst
    there is a lot of information available freely (ie on the web) you may
    want to consider investing in one (or more!) of these to gain further
    in-depth knowledge in particular areas. If you do decide to do this, check
    out the book(s) beforehand to ensure that you can translate the source to
    assembler. C is obviously ideal but many recent books use C++ or some other
    HLL (Visual Basic). Be careful to check that a book that uses C++ actually
    uses the enhanced features of C++ (ie object orientation) and isn't just
    using it to keep up with the current trend.

    On the web, there are a large number of resources. Don't forget that any
    sites detailing information about a topic can be a great source of
    information - a lot of the time, the main difficulty is understanding the
    correct API call sequences or how they interact, and once you understand
    this you can implement it in your chosen language. The most important site
    is probably Microsoft's which contains a huge amount of information over
    many areas:

        o MSDN online - msdn.microsoft.com
            Contains the MSDN library online, _the_ reference site for Microsoft
            products, technologies, etc. containing everything - API
            documentation, calling conventions, product manuals, literally
            everything about anything to do with Microsoft in any way. A
            superb resource, perhaps not quite as convenient as a help file
            but it _is_ up to date and usually is more complete. If you're
            after information about a subject this is definitely worth a
            look. Also of note are the various weekly/monthly columns as well
            as the archives of previous columns and other assorted information.
            Also, there is the Platform SDK - this is downloadable C header
            files, etc. for Win32 development and has some useful tools in it
            like the resource compiler. (Note that you can choose which bits of
            the SDK you download but it can easily become super-massive)

        o DirectX - www.microsoft.com/directx
            The DirectX SDK is available to order from here, though you can
            download it as part of the Platform SDK (there's a link to it from
            this site). Be warned that it's around 80Mb so be prepared to have
            a fast line or a lot of patience :) Recently revamped to Microsoft's
            new style, this now contains a lot more pointers (or downloads) to
            other DirectX documentation, examples, etc. unlike the previous
            attempt at a few links and a user-orientated FAQ.

        o ADO - www.microsoft.com/ado
            This might have moved, but contains information about Microsoft's
            open database connectivity. Worth checking out if you're interested
            in the database side of things.

        o Hardware development - www.microsoft.com/hwdev
            Contains lots of information about hardware development - device
            drivers, etc - and has the Device Driver development kit available
            for download. This kit has several useful utilities contained in
            it like the Microsoft linker, etc.

    Other sites can be found by search engines. Remember that you're not really
    looking for assembler specific information, just the principles and
    techniques involved. As far as newsgroups go, comp.lang.asm.x86 is obviously
    one choice, but for more information you might try the Win32 specific
    newsgroups, particularly the microsoft run ones. If you do venture into
    these please bear in mind the following points:

        o Not assembler oriented
            Few of the denizens will have assembler experience, and those that
            do will almost certainly not be interested in your Win32 problems
            _in assembler_. If they were inclined down this route, they'd be
            posting to clax would they not? References to assembly language are
            likely to get replies directing you to the assembler newsgroups.

        o Be prepared to have answers in a HLL
            Many people will reply with code snippets in the group's favourite
            language, so be prepared for this.

        o Post questions in an abstract way (ie non language specific)
          _unless_ the group is for a specific language
            For example, a question like "I'm trying to query a registry key,
            but every time I call RegQueryValueEx the call fails. I'm calling
            RegOpenKeyEx with the following parameters: <parameters> and
            RegQueryValueEx with: <parameters>" would be an example.

        o Post in the group's favourite HLL
            If you're confident in the group's favoured HLL, by all means post
            questions with code snippets in it, but _make sure_ you are up to
            par else you run the risk of getting nothing but replies on
            corrections to your code with no solutions.

        o Don't troll or start flame-wars over your use of assembler
            Posting about your use of assembler in non-assembler groups is likely
            to be interpreted as trolling and if you're not careful you can easily
            become embroiled in a pointless HLL vs LLL flame-war which does no-one
            any good (long-time clax members will recall the infamous Scott Nudds
            in this respect, likewise several C group denizens too)

        o Use standard netiquette
            Ie: _lurk_ for a while to get a feel for the group, _do not_ just wade
            in and start posting. Check the group's FAQ and adhere to any rules
            the group has.

------------------------------------------------------------------------------

Examples
    You can find all the examples described here in the Examples directory. For
    each example, I've listed the files, the concepts introduced and a brief
    description of those concepts. The descriptions are intended to be just
    outlines of the concepts so you can see what's being introduced, whilst the
    source code has lots of comments to show how they're actually achieved. It
    is expected that you will seek out more information in the API reference
    (which has a surprising amount) and other sources (eg books, MSDN on
    Microsoft's site, etc).

    Each example builds on the previous ones, utilising previously introduced
    concepts and becoming more advanced. In the example the concept is
    introduced in, there will be extensive comments in the source code. If it
    is used again in another example, unless additional information is
    necessary to understand its use it will likely be uncommented. This should
    enable you to quickly jump to the new stuff in the source file. I
    recommend you work your way through each example in order to understand
    Win32 programming in assembler. Once again, this isn't a tutorial, more
    of a jump start to get you going on your own.

    Each description is broken into three sections:

        o Files, listing the files the example uses, as a relative path from
          the Win32 Examples directory in the installed package

        o Docs, listing any documentation files. This will usually contain
          information about assembling and linking files.

        o Concepts, a brief description of each concept introduced in the
          example.

    If there are no relevant docs to the current example (eg if you link
    and assemble it in the same way as the previous one) the section may
    be omitted. A pre-built executable is also included for each
    example so you can quickly see the end result, and make files have
    also been provided. To use the make files, please ensure that the
    Bin directory holding Link, nasmg, etc. is in your path and also
    that an environment variable called LIBPATH holds the path where
    the .lib files are located.

-------------------------------------------------------------------------------

Core concepts
    Like the title suggests, this section of the examples demonstrate the
    core Win32 concepts, the building blocks of all Win32 applications.
    Without a proper understanding of these fundamentals you will find great
    difficulty in writing Win32 programs of any substance.

Making use of NASM's power
Files:
    o 00 Making use of NASM's power\Macros.asm
Concepts:
    o HLL constructs
        Makes coding easier. Very important that you understand these as
        they're used extensively throughout the examples

Hello world from a message box
Files:
    o 01 Hello World\HW_msgbox.asm
Docs:
    o Docs\Making.txt
Concepts:
    o WinMain
        Defines the program start point, must be GLOBAL and is needed by the
        linker (so declared with procglobal). Can be called anything, but
        is WinMain by tradition.
    o WinMainPrologue
        Special macro that stores information passed to the program on startup
        and also sets up the registers.
    o API calling convention
        Use any of the api, invoke, sc or stdcall macros to call the API,
        passing your parameters in the same order the function defines them.
    o WinMainEpilogue
        Special macro that restores the registers and exits the program.
    o String variables
        Defined with macros, thus hiding Unicode differences.

Hello world from a window
Files:
    o 01 Hello World\HW_window.asm
Concepts:
    o Structures
        Like the constants and API definitions, all the structures from the
        windows header files have also been converted. They are called exactly
        the same as they are in the header files and a structure at label
        _mystruc can have parts of the structure at that point referred to by
        _mystruc + <STRUCTURE NAME>.<MEMBER NAME>. For example, the WNDCLASSEX
        structure can have the style member referred to by WNDCLASSEX.style.
        In cases where a structure contains other structures, they can be
        referred to by <STRUCTURE NAME>.<MEMBER NAME>.<MEMBER NAME>, eg the
        members of the rcMonitor member (a RECT structure) of the MONITORINFO
        structure could be referred to by MONITORINFO.rcMonitor.left
    o API return values
        Any return value from an API call is stored in eax, or in st0 if it's
        a floating point value. Eax should be considered undefined if an API
        call doesn't return a value.
    o Creating and registering a window class
        A window class is a template that is used when you actually create a
        window on the screen. It contains the starting parameters and can be
        reused again and again with different windows. A window class requires
        a window class structure (which has been populated with your chosen
        data) like WNDCLASSEX and is then registered with Windows so that you
        can actually use it.
    o Message loop
        The loop retrieves messages sent to your program by Windows and checks
        that a quit message hasn't been sent. If not, then Windows is told to
        process it using the window procedure you've defined.
    o Window procedure
        This processes any messages sent to your program. It retrieves the
        parameters sent to the window procedure and then checks what message
        we're currently processing and acts accordingly.
    o CallbackPrologue
        Special macro that performs the startup code required for a windows
        callback function.
    o CallbackEpilogue
        Special macro that ends a windows callback function.
    o Drawing text
        To draw text in the window, we need to get a handle to the window's
        client area (where you can actually draw on) and we use this whenever
        we call any of the Win32 drawing functions (collectively known as the
        GDI - Graphics Device Interface). This is done by calls to BeginPaint
        and GetClientRect. EndPaint is used to finish the drawing.

Hello world from a console window
Files:
    o 01 Hello world\HW_console.asm
Docs:
    o Docs\Making.txt
Concepts:
    o Overview
        Console applications are Win32 apps without the GUI, and have access
        to the Win32 API as per normal. They are useful for things which you
        would have used DOS for in the past (eg command-line utilities) but
        don't warrant the extra hassle of a GUI (both coding and useabilitiy
        wise)
    o main
        Defines the program start point, must be GLOBAL and is needed by the
        linker (so declared with procglobal). Can be called anything, but
        is main by tradition.
    o SetConsoleTitle
        Consoles are quite customisable and you can set the title of the console,
        and other calls can change the cursor location (allowing you to write
        anywhere on the console), the colors, etc.
    o GetStdHandle
        To read or write with a console we need handles to the input and output
        devices, which we can obtain from GetStdHandle
    o WriteConsole
        Is used to output a string at the current console cursor location
    o ReadConsole
        Is used to read from the console

Keyboard reader (displays keys pressed)
Files:
    o 02 Keyboard\Keyboard.asm
Concepts:
    o Receiving keyboard messages
        Any time a key is pressed, a WM_KEYDOWN message is sent, and then
        re-sent whilst the key is held down (at the current typematic rate).
        WM_KEYDOWN is useful for non-ASCII keys, but WM_CHAR (sent on every
        keypress) is better for ASCII type keys.
    o Virtual key-codes
        Used in WM_KEYDOWN messages and provide hardware independent keycodes
    o InvalidateRect
        Can be used to tell Windows to update part of your window (by sending
        a WM_PAINT message)

Mouse reader (displays mouse buttons pressed and co-ordinates)
Files:
    o 03 Mouse\Mouse1.asm
      03 Mouse\Mouse2.asm (study Mouse1.asm first)
Concepts:
    o Overview
        The mouse sends messages to the window that is currently active
        whenever a mouse event occurs (a mouse event in Win32 is the mouse
        moving, a button being clicked, released, etc).
    o Receiving mouse messages
        A mouse message is sent when the mouse moves or a mouse button is
        pressed. The state of the buttons and the shift and control keys are
        sent with each message, alongwith the current mouse coordinates.
    o Double-click messages
        These are only received if the window's class style has been set
        to allow double-click messages.
    o wvsprintf
        This can be used to generate formatted strings like C's printf
        function, and takes three parameters - buffer address, address of
        string to process and address of the array holding the parameters
        to go in the processed string
    o SetCapture
        It's possible to detect mouse messages outside your window by
        calling SetCapture.
    o Reader exercise
        Write the code to process WM_MOUSEMOVE messages and display the
        coordinates as the mouse moves. Details in Mouse1.asm (line 99)

Command line reader
Files:
    o 04 Command line\Cmdline.asm
Concepts:
    o Overview
        The command line is available to a Win32 application and the API has
        functions to automatically parse it. However, these only work in a Unicode
        environment so we must parse it ourselves.
    o Getting the command line
        GetCommandLine returns a pointer to the command line string
    o Parsing
        CommandLineToArgv parses the command line but is Unicode only. We use a
        (poor) custom parser for this example.
    o Obvious DLL function
        The parser is a clear winner for a DLL function, see the example source
        for more details on what a DLL version would be like, and see the DLL
        source for details on writing a DLL.
    o No difference for GUI or Console applications
        Though I've used a console application for the example, the process is
        exactly the same for any Win32 program.

DLL
Files:
    o 05 DLL\Dll.asm
      05 DLL\Dll.def
      05 DLL\Dll_test.asm
Docs:
    o Docs\Making.txt
Concepts:
    o Overview
        DLLs are a way of having libraries of functions but not having to include
        all the code with every application that uses the library - instead you
        can create a DLL which Windows will load on demand. If several applications
        use the same DLL you cut down on the disk space used for each application
        (as only one copy of the DLL need be installed) and also only one copy of
        the DLL resides in memory, no matter how many applications actually use
        it. Windows does the hard work of managing the memory and data to make it
        appear to each application that it has its own copy of the DLL in memory.
        As you can imagine, this has many advantages over just linking in your
        code at link-time:

            o You need only supply one DLL for all applications that use it (a
              prime candidate for this sort of thing would be a library of
              commonly used routines)

            o You can easily update the library by simply installing a new
              version of the DLL. All applications using the DLL will then use
              the new version of the DLL. Be careful to maintain backward
              compatibility though! (Unlike MicroSoft who really don't seem
              to care in this regard, and cause _huge_ admin hassles...)

            o Resource usage is kept to a minimum

    o DllMain
        DllMain is the equivalent of WinMain for a DLL and is called when an
        application starts or ends and when a thread is created or destroyed.
        DllMain should return a non-zero value to indicate successful
        initialisation.
    o LibMainPrologue
        Special macro that stores information passed to DllMain and also
        sets up the registers.
    o LibMainEpilogue
        Special macro that restores the registers and returns from DllMain.
    o DLL functions
        Are just like normal functions, but need to be defined as GLOBAL so the
        linker can see them (ie with procglobal).
    o Calling DLL functions
        You need to tell NASM that the functions are defined elsewhere via the
        EXTERN directive.
    o stdcall macro
        The stdcall macro (defined in the modified version of NASM) is used to
        call functions that use the Win32 calling convention (ie defined by
        proc or procglobal).

Files
Files:
    o 06 Files\Cp.asm
      06 Files\Mapped.asm
Concepts:
    o Overview
        File handling is similar to most HLLs and DOS - you first open a file
        (obtaining a handle to the file) specifying the access mode you want to
        open the file in (read only, read/write, etc) and then you can read or
        write as desired before finally closing the file.
    o Opening a file
        The CreateFile function can be used to open or create a file and has
        many options which make it quite versatile. On success, a handle to
        the file is returned which is used for all subsequent operations on
        the file in question. Note that you can open networked files, named
        pipes, etc. with this call.
    o Reading from a file
        Using a file handle, call ReadFile with appropriate parameters.
    o Writing to a file
        As reading, but calling WriteFile instead.
    o Closing files
        Since any open file is referenced by a file handle, we use the
        CloseHandle function.
    o File mapping
        A very convenient way of using a file - the file is treated as though
        it is completely in memory, allowing us to reference it by the usual
        memory operations rather than ReadFile, etc. It isn't really in
        memory, but the OS takes care of the nasty details and it appears to
        us that it is. This is extremely convenient. To map a file, you first
        open it, then map it via CreateFileMapping and then create a view of
        the file using MapViewOfFile. The view is simply the amount of the
        mapped file you want to look at, you could choose to look at only
        a part of it or the whole file.

Icons and cursors
Files:
    o 07 Resources - Icons and cursors\Icon.asm
      07 Resources - Icons and cursors\Icon.rc
      07 Resources - Icons and cursors\Icon.h
      07 Resources - Icons and cursors\Icon.ash
      07 Resources - Icons and cursors\Chemical.ico
      07 Resources - Icons and cursors\Chip.ico
      07 Resources - Icons and cursors\Negative.cur
Docs:
    o Docs\Making.txt
Concepts:
    o Overview
        Resource files group collections of resources together, and can be
        held within executables.
    o Using
        Resources need to be loaded into memory first, after which we use a
        handle to refer to them. Icons are loaded via LoadIcon, whilst
        cursors use LoadCursor. We use the instance of the application to
        refer to the resource file as it is within the executable.

Character strings
Files:
    o 08 Resources - Character strings\String.asm
      08 Resources - Character strings\String.rc
      08 Resources - Character strings\String.h
      08 Resources - Character strings\String.ash
Concepts:
    o Overview
        Rather than storing character strings in your source code, you can
        instead place them in a resource file. If you ever decide to change
        any of the strings, you only need change the resource file and relink
        with your object file(s). This makes changing the language of your
        program very easy as you just relink with the new file.
    o All strings in one place
        If you place all the strings your application uses into the resource
        file, all the strings used are in one place (with menus, etc) which
        makes management easier
    o ANSI or Unicode
        All the strings are stored in Unicode. If you are running in an ANSI
        environment, they're converted to ANSI format when you use them. This
        makes making a Unicode version much easier than having to re-do all
        your source code to make the strings Unicode ones.
    o CHARSIZE
        This is an equate that holds the number of bytes a character takes up.
        In an ANSI app, it will be 1, in a Unicode app it's 2.
    o Reader exercise
        To verify the ease with which you can change the text, change some of
        the text in String.rc and then run Relink.bat which recompiles String.rc
        and then relinks it to String.obj.

Menus
Files:
    o 09 Resources - Menus\Menu.asm
      09 Resources - Menus\Menu.rc
      09 Resources - Menus\Menu.h
      09 Resources - Menus\Menu.ash
Concepts:
    o Overview
        Menus allow easy access to functions within an application.
    o Adding a menu to a window
        Can be added to the window class, in which case all windows based on
        that class automatically have that menu, or set when the window is
        created. You can use the latter to override a window's default
        menu (ie the one set in the window's class)
    o Menu messages
        A WM_COMMAND message indicates a menu item has been selected. A
        parameter in the message structure holds the value of the menu item,
        which is defined in the resource file.

Child windows
Files:
    o 10 Child windows\Child.asm
Concepts:
    o Overview
        Child windows are a way of invisibly dividing up a window into several
        smaller regions. Each region is referred to as a child window and is a
        window in its own right, _except_ it has no menu.
    o Creating a window
        Call CreateWindowEx just like when we create the main window, ensuring
        that a window class has been registered for the window. This allows us
        to change the window's attributes (like the window procedure).
    o Accessing passed parameters
        Parameters may be accessed by defines rather than storing them in
        variables. This keeps code tidy and eases maintenance when there is
        more than one window procedure.
    o Moving / resizing a window
        The MoveWindow function can be used to move or resize a window.
    o Child windows can communicate with their parent
        By sending messages with SendMessage, which are then processed by the
        parent window's window procedure. Likewise, the parent can send
        messages to the child window.
    o Child windows as input devices
        Since child windows can send and receive messages to and from their
        parent window, they can be used as input devices where the child window
        handles any mouse or keyboard input and then informs the parent window
        of what's going on.

Child window controls
Files:
    o 11 Child window controls\Control.asm (examine first)
      11 Child window controls\Buttons.asm
      11 Child window controls\Listboxes.asm
      11 Child window controls\Edit.asm
Concepts:
    o Overview
        Child window controls are an extension of child windows and turn
        the whole child window into a control of some sort, like a button
        or multiline edit box.
    o Creating a child control
        Call CreateWindowEx just like creating a child window, except the
        window class is already registered within Windows so doesn't need
        to be created.
    o No need to register a window class
        Child window controls already have a class predefined by Windows.
    o Child window controls communicate with their parent
        WM_COMMAND messages are sent by child window controls to their
        parent, with lParam holding the handle of the control and the
        high word of wParam holds the notification code.
    o Notification codes
        Are sent by child window controls and act like mini-messages,
        notifying the parent that something has occurred.
    o The parent can communicate with its children
        By sending messages to a child window control, a parent can
        query it for information or tell it to do things.

Window subclassing
Files:
    o 12 Window subclassing\Subclass.asm
Concepts:
    o Overview
        Window subclassing allows us to use a child window control, but
        override parts of its behaviour. Normally, a child window
        control's window procedure is hidden away in Windows (as the
        window class, where it's defined, is predefined by Windows),
        but we can replace it with our own version instead (saving
        the address of the old one in the process).
    o New window procedure
        The new window procedure only needs to process those messages
        we are interested in processing, the rest can be sent to the
        original window procedure and handled normally.
    o Setting a new window procedure
        This is done by SetWindowLong, which will return the old value
        of what we've just replaced.
    o Calling the original window procedure
        Handled by CallWindowProc.
    o Any window can be subclassed
        Window subclassing is not just limited to child window controls.

Window superclassing
Files:
    o 13 Window superclassing\Superclass.asm
Concepts:
    o Overview
        Superclassing allows us to take a window class (known as the _base_
        class) and create a new class that inherits all the attributes of
        the base class but also has attributes that we've added. For
        example, we could create a edit control that only accepted certain
        characters and then use that _as many times as we wanted with
        no additional work_.
    o More efficient than subclassing
        If we wanted to use several edit controls that only accepted certain
        characters we could subclass each control, but this is extremely
        irritating and makes maintenance problematic, or we could superclass
        the edit class and make controls based on this new superclass.
    o Superclassing
        Use GetClassInfoEx to populate a WNDCLASSEX structure with the details
        of the base class, fill in the fields it doesn't return and then
        register the new class.

Dialog boxes
Files:
    o 14 Dialog boxes\Dialog1.asm
Concepts:
    o Overview
        Dialog boxes are a way of prompting the user for more information,
        or informing the user of things that are happening. They can be
        thought of as just like a standard window except that Windows takes
        care of much of the background processing for us.
    o Created via DialogBoxParam
        Simply tell it the dialog box you want to create (the name from the
        resource file) and the address of the dialog box procedure (a
        procedure like the window procedure that processes messages sent
        to the dialog box).
    o Dialog Box procedure
        Just like a normal window procedure except you return non-zero if
        you handled the message and zero if you want Windows to handle it.
        You don't need to call DefWindowProc.

Common dialogs

Debugging
Files:
    o 15 Debugging\Debugging.asm
Concepts:
    o Overview
        You can send formatted strings (like the ones for printf) to a
        debugger to display, thus helping debugging. You can use another
        program to capture these messages if you don't have a debugger.
    o debug macro
        The debug macro allows you to quickly add debugging information to
        an application, and easily format strings to hold register or
        memory information.

------------------------------------------------------------------------------

Conclusion
    Hopefully you've enjoyed the examples and learnt from them. Feel free
    to mail me about comments, corrections or suggestions for the next
    release. I've tried to introduce important concepts to help you write
    robust Win32 applications in assembler, and I hope seeing how easy it
    really is makes you go out and write your own!
