NO

Author Topic: WinMain is not necessary  (Read 2769 times)

Jokaste

  • Guest
WinMain is not necessary
« on: October 07, 2017, 07:31:48 PM »
You think I am a fool! But no.

In a C windows program this function is necessary because you can have the following :

Code: [Select]
Func1(Arg1,Arg2) ;
Func2() ;
Func3(Arg1) ;
WinMain(...) ;

At the first look the compiler does not know where is the entry point.
So it forces you to have a function named "WinMain".

In assembly the programs always beguins at the label following the "END" pseudo-instruction.

Pelles help says :

Quote
The END directive ends the current source file. Any remaining part of the file will be ignored. Unlike some other assemblers, this directive is optional.
If the file has been included by a parent file, the assembler returns to the parent file (and continues assembling that file).
The optional entry point specifies the name of the symbol where execution should begin (for the main module). This information is passed to the linker; see the linker /ENTRY option.

The assembler program looks like this :

Code: [Select]
                     .Model flat,fastcall
                     OPTION   CSTRINGS:ON

                     .Const

                     INCLUDE "AsmView.inc"

;   ----------------------------------------------------------------------------------
;   ----------------------------------------------------------------------------------
;   ----------------------------------------------------------------------------------

                     .Code

;   __________________________________________________________________________________
;   _______________________ WndProc __________________________________________________
;   __________________________________________________________________________________

                     ALIGN   16

WndProc                  PROC   __hWnd:HWND,__uMsg:QWORD,__wParam:WPARAM,__lParam:LPARAM PARMAREA=12*QWORD
WndProc                  ENDP

;   __________________________________________________________________________________
;   _______________________ W i n M a i n ____________________________________________
;   __________________________________________________________________________________

WinMain :
                     ALIGN   16

Start                  PROC   PARMAREA=12*QWORD
                     END      Start



The "Start" function calls the "WinMain" function. So I decided that one of the two functions was not neccessary.

Code: [Select]
WinMain    PROC
                END WinMain

Why proceeding like this?
In assembly there is no reason to make any thing in the "Start" function. All the job is done by "WinMain".
I propose this code:
Code: [Select]
;   __________________________________________________________________________________
;   _______________________ S t a r t ________________________________________________
;   __________________________________________________________________________________

                     ALIGN   16

Start                  PROC   PARMAREA=4*QWORD
                     LOCAL   _hInstance:HINSTANCE
                     LOCAL   _lpszCommandLine:LPSTR
                     LOCAL   _Icc:INITCOMMONCONTROLSEX
                     LOCAL   _szTmp[MAX_PATH + 4]:BYTE
                     LOCAL   _Wc:WNDCLASSEX
                     LOCAL   _Msg:MSG

                     mov      rax,OFFSET hInstance
                     mov      rax,[rax]
                     test   rax,rax
                     jz      @FirstIntance

                     mov      rcx,5678
                     call   ExitProcess

                     ret

@FirstIntance :

                     call   gflLibraryInit

                     xor      ecx,ecx
                     call   GetModuleHandleA
                     mov      _hInstance,rax

                     call   GetCommandLineA
                     mov      _lpszCommandLine,rax

                     mov      rcx,SEM_FAILCRITICALERRORS OR SEM_NOOPENFILEERRORBOX
                     xor      rdx,rdx
                     call   SetThreadErrorMode

                     mov      r10,OFFSET szUserDirectory
                     xor      rcx,rcx
                     mov      rdx,CSIDL_PERSONAL
                     xor      r8,r8
                     xor      r9,r9
                     mov      [rsp + 32],r10
                     call   SHGetFolderPathA

                     mov      r10,OFFSET szMesImages
                     xor      rcx,rcx
                     mov      rdx,CSIDL_MYPICTURES
                     xor      r8,r8
                     xor      r9,r9
                     mov      [rsp + 32],r10
                     call   SHGetFolderPathA

                     mov      r8d,MAX_PATH
                     mov      rax,OFFSET hInstance
                     mov      rdx,OFFSET szProgramPathAndName
                     mov      rcx,[rax]
                     call   GetModuleFileNameA

                     lea      rcx,_szTmp
                     mov      rdx,OFFSET szProgramPathAndName
                     call   lstrcpy

                     mov      rcx,rax
                     call   PathFindFileNameA
                     mov      rdx,rax
                     mov      rcx,OFFSET szProgramName
                     call   lstrcpy

                     lea      rcx,_szTmp
                     call   PathFindFileNameA
                     mov      BYTE PTR [rax],0

                     lea      rdx,_szTmp
                     mov      rcx,OFFSET szProgramFolder
                     call   lstrcpy

                     mov      rcx,OFFSET szProgramFolder
                     call   PathRemoveBackslashA

                     INVOKE   wsprintf,ADDR szTrashFolder,ADDR szFmtTempFolder,ADDR szProgramFolder

                     xor      rdx,rdx
                     mov      rcx,OFFSET szTrashFolder
                     call   CreateDirectoryA

                     INVOKE   wsprintf,ADDR szDataBaseFolder,ADDR szFmtDataBaseFolder,ADDR szProgramFolder

                     xor      rdx,rdx
                     mov      rcx,OFFSET szDataBaseFolder
                     call   CreateDirectoryA

                     INVOKE   wsprintf,ADDR szDataBaseFile,ADDR szFmtDataBaseFile,ADDR szDataBaseFolder

                     call   sqlite3_initialize

                     test   rax,rax
                     jz      @Sqlite_Init_Ok

                     mov      rcx,OFFSET szError_0000
                     jmp      @Errors

;   ==================================================================================
;   ==================================================================================

                     ALIGN   16

@Errors :

                     mov      rax,OFFSET @EndOfJob
                     push   rax
                     jmp      Error

;   ==================================================================================
;   ==================================================================================

                     ALIGN   16

@Sqlite_Init_Ok :

                     mov      rax,OFFSET hSQLite
                     mov      QWORD PTR [rax],0

                     mov      rcx,OFFSET szDataBaseFile
                     mov      rdx,OFFSET hSQLite
                     mov      r8,SQLITE_OPEN_READWRITE or SQLITE_OPEN_CREATE or SQLITE_OPEN_PRIVATECACHE
                     xor      r9,r9
                     call   sqlite3_open_v2

                     test   rax,rax
                     jz      @Sqlite_Open_Ok

                     mov      rcx,OFFSET szError_0001
                     jmp      @Errors

;   ==================================================================================
;   ==================================================================================

                     ALIGN   16

@Sqlite_Open_Ok :

                     lea      rcx,_Icc
                     mov      [rcx].INITCOMMONCONTROLSEX.dwSize,SIZEOF INITCOMMONCONTROLSEX
                     mov      [rcx].INITCOMMONCONTROLSEX.dwICC,ICC_TREEVIEW_CLASSES OR ICC_STANDARD_CLASSES OR ICC_PROGRESS_CLASS OR ICC_BAR_CLASSES OR ICC_TAB_CLASSES ;

                     mov      rdx,OFFSET @InitControlsEnd
                     mov      rax,OFFSET InitCommonControls
                     push   rdx
                     push   rax
                     jmp      InitCommonControlsEx

@InitControlsEnd :

                     lea      rdx,_Wc
                     mov      rax,OFFSET WndProc

                     mov      [rdx].WNDCLASSEX.hInstance,rcx
                     mov      [rdx].WNDCLASSEX.lpfnWndProc,rax
                     mov      [rdx].WNDCLASSEX.cbSize,SIZEOF WNDCLASSEX
                     mov      [rdx].WNDCLASSEX.style,CS_HREDRAW OR CS_VREDRAW OR CS_DROPSHADOW OR CS_DBLCLKS or CS_BYTEALIGNCLIENT or CS_BYTEALIGNWINDOW or CS_OWNDC

                     xor      rax,rax

                     mov      [rdx].WNDCLASSEX.cbClsExtra,eax
                     mov      [rdx].WNDCLASSEX.cbWndExtra,eax
                     mov      [rdx].WNDCLASSEX.lpszMenuName,rax

                     mov      rax,OFFSET szClassName
                     mov      [rdx].WNDCLASSEX.lpszClassName,rax

                     mov      rdx,IDI_MAIN
                     call   LoadIconA

                     lea      rdx,_Wc
                     mov      [rdx].WNDCLASSEX.hIcon,rax
                     mov      [rdx].WNDCLASSEX.hIconSm,rax

                     mov      rdx,IDC_ARROW
                     xor      rcx,rcx
                     call   LoadCursorA

                     lea      rdx,_Wc
                     mov      [rdx].WNDCLASSEX.hCursor,rax

                     mov      rcx,BLACK_BRUSH
                     call   GetStockObject

                     lea      rcx,_Wc
                     mov      [rcx].WNDCLASSEX.hbrBackground,rax

                     call   RegisterClassExA

                     mov      rcx,OFFSET hInstance
                     xor      rax,rax
                     mov      rcx,[rcx]
                     mov      r8,580
                     mov      rdx,330
                     mov      r10,CW_USEDEFAULT

                     mov      [rsp + 58h],rax
                     mov      [rsp + 50h],rcx
                     mov      [rsp + 48h],rax
                     mov      [rsp + 40h],rax
                     mov      [rsp + 38h],r10      ; H
                     mov      [rsp + 30h],r10      ; W
                     mov      [rsp + 28h],r10      ; Y
                     mov      [rsp + 20h],r10      ; X
                     mov      r9,WS_BORDER or WS_CAPTION or WS_MAXIMIZE or WS_MAXIMIZEBOX or WS_MINIMIZEBOX or WS_SYSMENU or WS_VISIBLE
                     mov      r8,OFFSET szAppName
                     mov      rdx,OFFSET szClassName
                     xor      rcx,rcx
                     call   CreateWindowExA

                     mov      rcx,rax
                     mov      rdx,SW_SHOWMAXIMIZED
                     call   ShowWindow

                     mov      rax,OFFSET hWndMain
                     mov      rcx,[rax]
                     call   UpdateWindow

                     mov      rax,OFFSET hInstance
                     mov      edx,ID_ACCELERATOR
                     mov      rcx,[rax]
                     call   LoadAcceleratorsA

                     mov      rcx,OFFSET hAccel
                     mov      [rcx],rax

                     jmp      @MsgLoop

;   ==================================================================================
;   ==================================================================================

                     ALIGN   16

@MsgLoop :

                        lea      rcx,_Msg
                        xor      rdx,rdx
                        xor      r8,r8
                        xor      r9,r9
                        call   GetMessageA

                        test   rax,rax
                        jz      @MsgLoopEnd

                           mov      rax,OFFSET hDlgFiles
                           lea      rdx,_Msg
                           mov      rcx,[rax]
                           call   IsDialogMessage

                           test   rax,rax
                           jnz      @MsgLoop

                              mov      rax,OFFSET hWndMain
                              mov      rdx,OFFSET hAccel
                              mov      rcx,[rax]
                              mov      rdx,[rdx]
                              lea      r8,_Msg
                              call   TranslateAccelerator

                              test   rax,rax
                              jnz      @MsgLoop

                                 lea      rcx,_Msg
                                 call   TranslateMessage

                                 mov      rax,OFFSET @MsgLoop
                                 lea      rcx,_Msg
                                 push   rax
                                 jmp      DispatchMessageA

;   ==================================================================================
;   ==================================================================================

                     ALIGN   16

@MsgLoopEnd :

;   ==================================================================================
;   ==================================================================================

                     ALIGN   16

@EndOfJob :

                     mov      rcx,OFFSET hSQLite
                     mov      rdx,OFFSET gflLibraryExit
                     mov      rax,OFFSET sqlite3_shutdown
                     push   rdx
                     push   rax
                     jmp      sqlite3_close

                     mov      rcx,_Msg.wParam
                     mov      rax,OFFSET __imp_ExitProcess
                     mov      rax,[rax]
                     call   rax

                     Start   ENDP

;   __________________________________________________________________________________
;   _______________________ F I N I S H E D __________________________________________
;   __________________________________________________________________________________

                     END      Start

When someone wants to crack your program he generally looks for the classic "WinMain". He will be lost...
« Last Edit: October 07, 2017, 07:55:34 PM by Jokaste »

Offline Vortex

  • Member
  • *
  • Posts: 797
    • http://www.vortex.masmcode.com
Re: WinMain is not necessary
« Reply #1 on: May 12, 2021, 11:42:08 AM »
Hello,

It's better to use the main function. Of course, you can survive without main but you will have to solve some problems like the cooperation loss of the CRT library with your code :

Code: [Select]
#include <stdio.h>

int start(int argc,char *argv[])
{
int i;

for(i=0 ; i<argc ; ++i)
                         {
                          printf("Command line parameter %d = %s\n",i+1,argv[i]);
                         }
return 0;
}

Nomally, the command line parameters are expected by the main function. You will have to use some trick to build the code above.
Code it... That's all...

Grincheux

  • Guest
Re: WinMain is not necessary
« Reply #2 on: May 12, 2021, 01:44:07 PM »
In assembly just add:
Code: [Select]


xor ecx,ecx
call GetModuleHandleA
mov _hInstance,rax

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2096
Re: WinMain is not necessary
« Reply #3 on: May 12, 2021, 06:12:16 PM »
Also memory manager and many other functions are initialized from CRT, bypassing it expect many problems, unless you don't plan to use only WINAPI32 functions (and even in this case you should expect some surprise...) as demonstrated in the original example.
The rule of thums is: if you need libc functions you need the CRT!
« Last Edit: May 12, 2021, 06:14:13 PM by frankie »
It is better to be hated for what you are than to be loved for what you are not. - Andre Gide