More Programming Information

Back to Win95 ASM Page

Program startup

When a Win95 program starts, the segment registers are set up this way:     CS maps to the same linear address as DS, ES, and SS.
    FS maps to a TIB which is embedded in a data block known as the TDB (thread data base). The TIB contains the thread-specific exception handling chain and pointer to the TLS (thread local storage.) The thread local storage is not the same as C local storage.
    ESP is set by Win95 to a high address, not necessarily at the 2G mark.
    DF (descending/direction flag) is cleared, so string ops will cause an increment (ascending mode.)

If you've ever programmed a protected mode switcher, you'll know how CS can have a different "segment" value and still be able to address the same memory area with the same offsets.
    For ASM programmers who aren't familiar with protected mode, the "segment" is no longer a segment (paragraph) value, it's a selector. A selector is a reference to a descriptor, where information about the "segment" (which can be any size) is stored.

Other startup values

Previous instance handle:
    There is no previous instance handle because instance handles cannot be used to access data from another process (application instance). The WinMain parameter is always 0 (NULL.) Other techniques exist for ensuring only one instance (running copy) of an application.

Instance/module handle of EXE:

    push    large 0             ; NULL string pointer
    call    GetModuleHandle     ; EAX = hInstance of EXE
Command line arguments:
    call    GetCommandLine      ; EAX = pointer to full command line
[Environment variables:]

Standard I/O, nCmdShow:

STARTUPINFO struc
startSize   dd ?    ; cb, size of STARTUPINFO
            dd ?    ; lpReserved
startDesktop dd ?   ; lpDesktop, (string) name of desktop
; *** Start of console window info
startTitle  dd ?    ; lpTitle, (string) title/caption
startX      dd ?    ; dwX, upper left corner
startY      dd ?    ; dwY, upper left corner
startXSize  dd ?    ; dwXSize, width
startYSize  dd ?    ; dwYSize, height
startXChars dd ?    ; dwXCountChars, console width
startYChars dd ?    ; dwYCountChars, console height
startFillAttr dd ?  ; dwFillAttribute, console window attributes
; *** End of console window info
startFlags  dd ?    ; dwFlags, option flags, used by CreateProcess
startShowWnd dw ?   ; wShowWindow, used in first call to ShowWindow
            dw ?    ; cbReserved2
            dd ?    ; lpReserved2
startStdin  dd ?    ; hStdInput, standard input handle
startStdout dd ?    ; hStdOutput, standard output handle
startStderr dd ?    ; hStdError, standard error output handle
STARTUPINFO ends

    push    offset <startupinfo>
    call    GetStartupInfo      ; void function

Creating an import library from an arbitrary DLL

With the Borland linker, use IMPDEF to create a .DEF file from the DLL. Then use IMPLIB to create the import library from the .DEF file.

With the Microsoft linker, use DUMPBIN /EXPORTS to get a list of entry points and their "ordinals". Redirect the output into a .DEF file. Change each line with an entry point name to:

        entryname
Eliminate all other lines. Then add to the beginning of the file:
        LIBRARY  dllbasename
        EXPORTS
Then use LIB /DEF to generate the .LIB file from the editted .DEF file. LIB will prepend an underscore, "_", to each entry name. Due to the lack of argument information, LIB will not add any other characters to the link name.

Deadlock theory

Deadlock, or the deadly embrace, is a condition where processes are waiting forever to acquire resources that can't be released. For the purposes of deadlock theory, a Win32 thread can be treated as a process, and a resource is defined as any allocatable item.
    For reasoning about deadlock due to window messaging, it's more fruitful to treat each window as a process, and each thread as a resource that can cause deadlock.
    There are four necessary and sufficient conditions for creating deadlocks.

Necessary means that all conditions must exist for deadlock to occur.
Sufficient means that when all conditions exist, deadlock will occur.

According to Tanenbaum [referring to an article by Coffman, Elphick & Shoshani], they are:

Brinch Hansen's restatement [of Coffman et al.] may be more revealing:

Title (caption) bar and Taskbar button anomalies

The standard Win95 title bar (requested either by default or with WS_CAPTION) isn't nearly as customizable as the old Win3.1 title bar (NT or 16-bit). If you want the title bar to behave better, you'll probably have to draw your own.
    When you disable a title bar button, it doesn't necessarily disappear. The minimize and maximize buttons disappear as a pair. If you disable one and enable the other, both will show and the disabled button is grayed. The close (X) button can be disabled (grayed) with CS_NOCLOSE, but doesn't appear to be removable.
    Enabling the minimize button will create a Taskbar button, but enabling the maximize button won't.
    The close button cannot be enabled unless the system menu is also enabled.
    There is some curious behavior when no system menu and no size buttons are specified. When a shortcut is used to start with maximized windows, you get a Taskbar button. When the shortcut is used to start with minimized windows, you get a "button" that doesn't sit in the Taskbar.

Documented Win32 functions that don't exist

There are a few official API functions that are converted by C macros to equivalent functions with extra arguments. The extra arguments are 0 or NULL.

Obsolete Win16 functions

There are a number of Win16 API functions that either no longer exist in Win32, or exist solely for compatibility with Win16 programming in C.