Page 1 of 2 12 LastLast
Results 1 to 10 of 17

Thread: Interfacing Windows SDK HelloWin

  1. #1

    Interfacing Windows SDK HelloWin

    This is the hardcore stuff

    Not the ultimate version by any means - it is quite bulky since it contains all the necesaries for Windows SDK in a single file. And the type declarations are not really required for the code to work in this example.

    I've used some slightly exotic code to place the procedures table pointer immediately before wndproc so it can be picked up by this procedure. (This code has no absolute addresses at assembly time or EXE fixups - everything has to start off relative )

    Getting Windows to spin from scratch in ASM is quite a challenge so I hope this will be useful as a starting point, with some useful pieces for SDK programming.

    [code=thinbasic]
    ' Windows Hello World
    ' #2
    ' with winmain message loop and wndproc
    ' 3 July 2008
    ' Charles Pegge


    Uses "Oxygen"
    Uses "File"

    dim src as string
    src="
    type WNDCLASS
    (
    ;40 bytes
    4 STYLE
    4 lpfnwndproc
    4 cbClsextra
    4 cbWndExtra
    4 hInstance
    4 hIcon
    4 hCursor
    4 hbrBackground
    4 lpszMenuName
    4 lpszClassName
    )

    type MSG
    (
    ; 28 bytes
    4 hwnd;
    4 message
    4 wParam
    4 lParam
    4 time
    8 pt
    )


    indexers `esi` offset 0 ascending
    esi=getmemory 1024
    call WndProcLocate
    mov [eax-4],esi ; store sys proc table pointer here

    var 4 kernel32,user32,GDI32

    kernel32=LoadLibrary `kernel32.dll`
    user32=LoadLibrary `user32.dll`
    GDI32=LoadLibrary `GDI32.dll`

    bind kernel32
    (
    GetCommandLine GetCommandLineA ; @0
    GetModuleHandle GetModuleHandleA ; @4
    ExitProcess ExitProcess ; @4
    )

    bind user32
    (
    LoadIcon LoadIconA ; @8
    LoadCursor LoadCursorA ; @8
    RegisterClass RegisterClassA ; @4
    MessageBox MessageBoxA ; @4
    CreateWindowEx CreateWindowExA ; @48
    ShowWindow ShowWindow ; @8
    UpdateWindow UpdateWindow ; @4
    GetMessage GetMessageA ; @16
    TranslateMessage TranslateMessage ; @4
    DispatchMessage DispatchMessageA ; @4
    PostQuitMessage PostQuitMessage ; @4
    BeginPaint BeginPaint ; @8
    EndPaint EndPaint ; @8
    GetClientRect GetClientRect ; @8
    DrawText DrawTextA ; @20
    PostMessage PostMessageA ; @16
    DefWindowProc DefWindowProcA ; @16
    )


    bind GDI32
    (
    GetStockObject GetStockObject ; @4
    )


    '

    def SW_NORMAL 1
    def SW_SHOWDEFAULT 10


    var 4 cmdline,inst

    cmdline=GetCommandLine
    inst=GetModuleHandle 0
    proc WinMain inst,0,cmdline,SW_NORMAL
    freememory esi
    ret


    o2 !10 ; align 16 bytes


    ;-------
    WinMain:
    ;-------
    '

    def CS_VREDRAW 1
    def CS_HREDRAW 2
    def IDI_APPLICATION 32512
    def IDC_ARROW 32512
    def WHITE_BRUSH 0
    def MB_ICONERROR 16

    def CW_USEDEFAULT 0x80000000
    def WS_OVERLAPPEDWINDOW 0x00cf0000

    push ebp
    mov ebp,esp
    ;allocate stack space
    sub esp,100
    ; setup class data
    mov edi,esp
    '
    def wclass edi
    def style [edi]
    def pWndproc [edi+4]
    def cbClsExtra [edi+08]
    def cbWndExtra [edi+12]
    def hInstance [edi+16]
    def icon [edi+20]
    def cursor [edi+24]
    def background [edi+28]
    def MenuName [edi+32]
    def ClassName [edi+36]

    ; window handle
    def hWnd [edi+40]

    mov eax,CS_HREDRAW '
    or eax,CS_VREDRAW '
    mov style,eax
    pWndProc=proc WndProcLocate
    mov cbClsExtra,0
    mov cbWndExtra,0
    mov eax,[ebp+8]
    mov hInstance,eax
    icon=LoadIcon 0, IDI_APPLICATION
    cursor=LoadCursor 0,IDC_ARROW
    background=GetStockObject WHITE_BRUSH '
    mov MenuName,0
    `HelloWin`
    mov ClassName,eax
    RegisterClass wclass

    cmp eax,0
    ( '
    jnz exit '
    MessageBox 0,`Registration failed`,`Problem`,MB_ICONERROR '
    xor eax,eax ' zero eax
    jmp long end_app ' jmp xitwm
    ) '


    hWnd=CreateWindowEx 0, ClassName,`Hello Window`,
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT,CW_USEDEFAULT,640,480,
    0,0,hInstance,0

    (
    cmp eax,0 '
    jnz exit '
    MessageBox 0,`Unable to create window`,`problem`,MB_ICONERROR
    xor eax,eax ' zero eax
    jmp long end_app ' jmp xitwm
    ) '
    ShowWindow hWnd,[ebp+20] ' show
    UpdateWindow hWnd


    ' MESSAGE LOOP '

    add edi,40 ; place for wmsg struc
    (
    GetMessage edi,0,0,0 '
    cmp eax,0
    jz exit
    TranslateMessage edi
    DispatchMessage edi
    repeat
    ) '
    mov eax,[edi+8] ' Msg.wParam 3rd param

    end_app:
    ; deallocate stack space
    mov esp,ebp
    pop ebp '
    ret 16 '
    ; end of WinMain


    type RECT
    (
    ; 16 bytes
    4 left
    4 top
    4 right
    4 bottom
    )

    type PAINTSTRUCT
    (
    ; 64 bytes
    4 hDC
    4 fErase
    rect rcPaint
    4 fRestore
    4 fIncUpdate
    32 rgbReserved
    )

    ;-------------
    WndProcLocate:
    ;-------------

    ; return absolute location of WndProc
    o2 !10 ; align 16
    o2 e8 00 00 00 00 ; call next location
    o2 58 83 c0 0b c3 ; pop this into eax and add 11 then ret
    o2 00 00 00 00 00 00 ; round to 15 bytes

    ;-------
    WndProc:
    ;-------
    def hWnd [ebp+08]
    def wMsg [ebp+12] '
    def wParam [ebp+16] '
    def lParam [ebp+20] '

    def WM_CREATE 1
    def WM_DESTROY 2
    def WM_PAINT 15
    def WM_CLOSE 16
    def WM_KEYDOWN 256

    push ebp '
    mov ebp,esp
    push esi
    ;
    ; restore sys procs table pointer
    call WndProcLocate
    mov esi, [eax-4]
    ;
    ; not using stack locals so no subractions for esp

    '
    mov eax,wMsg
    (
    (
    cmp eax, WM_CREATE '
    jnz exit
    xor eax,eax
    jmp long endselect
    ) ; end create

    (
    cmp eax, WM_DESTROY
    jnz exit
    PostQuitMessage 0
    xor eax,eax
    jmp long endselect
    ) ; end destroy

    (
    cmp eax,WM_PAINT
    jnz exit
    sub esp,100 ; extra workspace
    def cRect [ebp-60]
    def hDC [ebp-20]
    def Paintst [ebp-100]
    hDC=BeginPaint hWnd,&Paintst
    GetClientRect hWnd,&cRect
    ; style
    ; 0x20 DT_SINGLELINE
    ; 0x04 DT_VCENTER
    ; 0x01 DT_CENTER
    ; 0x25
    DrawText hDC,`Hello World!`,-1,&cRect,0x25
    EndPaint hWnd,&Paintst
    xor eax,eax
    jmp long endselect
    ) ; end paint

    (
    cmp eax,WM_KEYDOWN
    jnz exit
    (
    mov eax,wParam
    cmp al,27 ' esc key
    jnz exit
    PostMessage hWnd,WM_CLOSE,0,0
    )
    xor eax,eax ' zero
    jmp long endselect
    ) ; end keydown
    ; case else
    DefWindowProc hWnd,wMsg,wParam,lParam
    ) ; end select
    endselect:
    ;
    pop esi
    mov esp,ebp
    pop ebp
    ret 16


    "
    'File_Save("z.txt",o2_view_file(src))
    if len(o2_error) then msgbox 0,o2_error
    o2_asmo src
    o2_exec


    [/code]

  2. #2
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    57
    Posts
    8,777
    Rep Power
    10

    Re: Interfacing Windows SDK HelloWin

    Charles,

    it is impressive the level you have reached in Oxygen. It is a complete language per se.
    What a massive work reading your FreeBasic sources.

    My hat down!

    PS:
    maybe the only problem is that every Oxygen script is dependant from "o2asm.data" data file that must be present in the same directory of the script otherwise there is a possible GPF.
    www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
    Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000

  3. #3

    Re: Interfacing Windows SDK HelloWin


    Thank you Eros. It's all open ended as to how the language facility will be used. It is more discovery than invention so I am gradually learning how to use it

    For o2asm.data I suggest it goes into a folder called oxygen, located in thinbasic\lib. This location could also be used to hold any other future intrinsic parts.

    Is this the best fit for the thinBasic file system?

  4. #4
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    57
    Posts
    8,777
    Rep Power
    10

    Re: Interfacing Windows SDK HelloWin

    Well, the problem can also exists when creating thinBasic bundled executable.
    How to know executable is dependant from "o2asm.data" so it has to be included in bundled exe?

    I think an option could be the following:
    • include current "o2asm.data" data directly inside Oxygen module so it is part of the module. I suppose the current file already has the most used cpu operands so it is already very exaustive
    • when Oxygen module is loaded, it can check for an optional file (named as you prefer for example "o2asmUser.data" or whatever) present in the same path of Oxygen module. If that file exists, loads new operands. Consider that you can get the directory where Oxygen module has being loaded using the parameter passed to "LoadLocalSymbols(sPath)" function. Because that directory can change, thinCore pass to every "LoadLocalSymbols" function to every loaded module the directory where it is loading it.


    In this way Oxygen is not dependant from any external file but at the same time it is still open to new operands.

    Maybe another option can be to create a new Oxygen keywords that loads external commands as string or file name: "O2_LoadAdditionalOps(StringBuffer)". This function to be executed in the script before any other Oxygen functions.

    In either cases it is user responsability to manage stuff but at the same time no GPF due to missing data.
    What do you think?

    Ciao
    Eros
    www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
    Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000

  5. #5

    Re: Interfacing Windows SDK HelloWin

    Thanks Eros,

    I am not familiar with bundling yet - not sure where to find loadLocalSymbols.

    Does thinBasic_GetRunTimeInfo("APP_PATH") work within bundles? Do you retain the same directory structure for required modules ie .\Lib\thinBasic_*.dll?

    My test system looks for o2asm.data in the current directory - then it tries APP_PATH\lib\oxygen\o2asm.data

  6. #6
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    57
    Posts
    8,777
    Rep Power
    10

    Re: Interfacing Windows SDK HelloWin

    thinBasic engine (thinCore.dll) loads modules using the path finding described in http://www.thinbasic.com/public/prod.../html/uses.htm under "Remarks" section. So you cannot know where the modules is loaded from at compile time. All is dynamic and follows the following order:
    1. Source script path
    2. Source script path + Lib
    3. Source script path + Bin
    4. Source script path + Mod
    5. Source script path + Lib + "thinBasic_" + ModuleName
    6. Source script path + Bin + "thinBasic_" + ModuleName
    7. Source script path + Mod + "thinBasic_" + ModuleName
    ...reserved...
    11. thinBasic path
    12. thinBasic path + Lib
    13. thinBasic path + Bin
    14. thinBasic path + Mod
    15. thinBasic path + Lib + "thinBasic_" + ModuleName
    16. thinBasic path + Bin + "thinBasic_" + ModuleName
    17. thinBasic path + Mod + "thinBasic_" + ModuleName

    For this reason, when the module is loaded, thinCore pass to it the directory infor where it was loaded from.
    How doe this happening?
    When thinCore.dll loads thinBasic_Oxygen, it calls Oxygen exported function "LoadLocalSymbols" (you will find it in your FreeBasic source file named "thinBasic_Oxygen.bas"). "LoadLocalSymbols" has the following declare:
    [code=freebasic]FUNCTION LoadLocalSymbols Cdecl ALIAS "LoadLocalSymbols" (BYVAL sPath AS STRING) AS Long EXPORT [/code]
    sPath parameters is filled with the directory where thinBasic engine (thinCore.dll) found Oxygen module. As I sayd before this directory can change. For example when you execute a source thinBasic script, usually it is "\thinBasic\Lib\". But when you execute a bundled exe thinBasic script, that directory is usually equal to the directory where the bundled EXE is located.

    Hope this can help.
    Eros
    www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
    Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000

  7. #7

    Re: Interfacing Windows SDK HelloWin

    Yes thank you Eros. I've got the picture now. I'll try some bundling later on today. But first an appointment with Morpheus. Good night.

  8. #8
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    57
    Posts
    8,777
    Rep Power
    10

    Re: Interfacing Windows SDK HelloWin

    Quote Originally Posted by Charles Pegge
    ... But first an appointment with Morpheus. Good night.

    Me too. Good night.
    www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
    Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000

  9. #9
    thinBasic MVPs kryton9's Avatar
    Join Date
    Nov 2006
    Location
    Naples, Florida & Duluth, Georgia
    Age
    67
    Posts
    3,869
    Rep Power
    404

    Re: Interfacing Windows SDK HelloWin

    Thanks Charles, I got it to run. Now to see if I can figure out what is going on. Thanks again for the example!
    Acer Notebook: Win 10 Home 64 Bit, Core i7-4702MQ @ 2.2Ghz, 12 GB RAM, nVidia GTX 760M and Intel HD 4600
    Raspberry Pi 3: Raspbian OS use for Home Samba Server and Test HTTP Server

  10. #10

    Re: Interfacing Windows SDK HelloWin

    Glad it works Kent. If you can figure out what is going on please let me know Windows SDK is so demanding as you can see from all the procs required to get it up and running.

    Eros,
    I have been experimenting with bundles this morning using spath in LoadLocalSymbols. I am using a folder called oxygenlib which normally sits alongside thinbasic_Oxygen.dll, wherever that might be.

    The bundles work well - no problem in locating files including asm scripts. But if the compiled bundle is run from my development directory, it deletes or renders hidden all the original modules, asm files and folders used to create the bundle. This seems to be a consequence of the bundle's cleanup operation. I did not specify a target directory for the bundle though - would it be possible to make the default behaviour safer?


Page 1 of 2 12 LastLast

Members who have read this thread: 0

There are no members to list at the moment.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •