+HCU papers
courtesy of fravia's page of reverse engineering
28 June 1999
SLH's seventh paper
The Succession
"The second version
of the masm32 package
is already in circulation and reasonably well received
and I am just
putting the finishing touches to the third version. At
the end of the
assay before the ASM template is a pair of links where
people who are
interested can download the package to try it out."
SLH is back again with another (the seventh) of his small masterpieces: You would be well advised to read
all the preceding parts of what is going to be a DEFINITIVE HCU MANUAL INTRODUCING
WINDOWS DISASSEMBLING: it's a concentrated very good
course about the UTMOST IMPORTANCE of assembling
in everyday windows (or whatever) programming. This will help you, among other
things :-) in order to
better understand
the purposes (and the power) of what we are all doing here...
And here you go... Enjoy!
+HCU papers
THE SUCCESSION
There has to be a good reason for an ancient warrior to return from a place
in space / time to the modern world of computing and it usually has to do
with the need to again practice the black arts from a time when the world
of computers was young and Billy Gates was just becoming the all American
Mr Nice Guy.
The lack of viable tools for writing quality binary code in 32 bit
assembler has been a hallmark of the sickness inflicted on the general
programming community since Windows 95 was introduced on the market, the
problem of where programs that once showed the speed and vigour of youth
have become sick and bloated as the tools became the toys of children, not
the cutting edge tools of warriors.
The cold steel in the ancient warriors eye looks through the marketing hype
at the fundamental lie of the land and it was here that the real damage
was done when the tools of the ancient black arts no longer worked.
Closed system proprietry information left a hole in the capacity of to
write the new format programs so the black art of writing assembler lived
on only in the memories of the ancient warriors who did battle using them
in the ancient times.
Warriors of a different way arose out of the chaos and re-discovered a part
of the ancient black art and put it to a new and clever use, reverse
engineering the trash that was being peddled to the unsuspecting as
computer programs.
Among the true masters of the new warriors, the pursuit of knowledge with
no taint of squalid gain became the hallmark of their movement that
continues to defy the efforts of the greedy to crush it yet it also gave
rise to the knowledge of part of the ancient black art, the low level
structure of binary files.
For the ancient warrior who had returned in the past in search of clever
things, the corridors of the internet were a desolate and desperate place
where the cries of the ignorant were posted like signposts to destruction.
The precision and power of the past had almost been lost in the hype that
surrounded the garbage that was peddled as development tools, "we have
objects, gimmicks, glitzy front ends, OLE, DDE" but to the eye of the
ancient, there was no power, just the delusion of the ignorant.
For the interim period, there were leftovers of the ancients that sufficed
in keeping the persistent seeker of knowledge with some vestige of power,
it was an anarchronism in the C and similar compilers that would still
write inline assembler. Although an imperfect vehicle, it was an entry
into the black arts of old.
Often, thing in far away places have subtle yet very influential effects
on the way the rest of the world works. The Microsoft Corporation had not
only succeeded in crushing almost all of its competition
but had also succeeded in becoming a monopoly as well, but in doing so, it
fell foul of another great power, the US Department of Justice, an opponent
that had already left the battered remains of both Standard Oil and IBM
in its wake.
Knowledge of the ancient black arts meant knowing the real tools of the
trade as many of the newer players did not even know what they were and it
was here that the ancient warrior saw the change that was part of the
fallout from the ongoing battle between the Microsoft Corporation and the
Department of Justice.
As a sign of repentence for its past arrogance, the Microsoft Corporation
have posted as free downloads, two of the necessary components to return
to the ancient black arts, the WIN98DDK and the PLATFORMSDK. From the DDK
came version 6.11 of the assembler for MASM which when upgraded with the
version 6.13 patch to be the latest assembler available, ML.EXE 6.13. The
DDK also contained the coff format linker version 5.12.8078 which was also
the latest version available.
From the PLATFORMSDK came the full set of IMPORT libraries so the
necessary tools had again become available. What was missing was
a matching full set of include files as those from the DDK were both
flawed and incomplete.
The breakthrough came in the form of the data about the
imports in the libraries.
Using one of the incomplete but functional include files that had been
available for some time, the linker referenced the import libraries for
parameter numbers and size. The data occurred in the form _FunctionName@12
where the decimal number at the end referred to the number of bytes that
the parameters used when passed.
It just happens to be that almost every windows API function uses :DWORD
size parameters so the conversion of the internal data from the import
libraries to a prototype was a fussy but more or less routine process.
The last great hurdle was an extensive set of equates and structures and
this was done the old hard way as a joint project with another ancient
warrior, Iczelion.
Iczelion is a warrior from a far and exotic land who cut his teeth on
C/C++ compilers and is fluent in both TASM and MASM. From his hand
has come the best set of tutorials for MASM on the market covering
an important range of topics in 32 bit windows assembler.
There are number of architectures in assembler language programming that
have been used for 32 bit windows. The ground breaking work by Sven B.
Schrieber was very powerful for the available technology but it could not
be described as entry level assembler.
The very influential work of Steve Gibson was an important breakthrough in
that it showed how to make an assembler application that was fundamentally
simple in construction that could be extended without the usual problems
associated with programs that were very hard to read.
The architecture that did have the promise of the age to come was that of
Iczelion. By using MASM's capacity with procedures, a very orthodox
looking "WinMain" and "WndProc" procedures brought assembler
out of the novelty market into the mainstream of 32 bit windows
programming.
One of the many things that pure assembler does well is emulate the
architecture of C. This is an important consideration when writing code
for an operating system that is a fundamentally C style
construction. The main difference between C and ASM is the freedom in ASM to
lay out code design in almost any way that a programmer wishes. The other
of course is that in ASM, the programmer is free of the C runtime libraries
and their overhead.
Ancient warriors are not noted for either their patience or tolerance when
it comes to the tools of the trade and it was here that the need for some
new and small tools arose. Ancient warriors grew up in open architecture
systems and do not trust the closed system approach that the modern IDE
assumes.
When you write code, you write it in an EDITOR, when you assemble it you
use an ASSEMBLER and when you finally link it, you use a
LINKER. For the resources, you use a RESOURCE compiler and in this
way, the programmer is in control of the code that is written, not a prisoner of
the IDE designer and the assumptions that go with it.
This is a formula for a programmable editor that will run external tools
in a convenient way and it is here that ancient warriors
have the experience of the past in that if the tool does not exist, write it.
MASM32 - the new way.
To put enough things together to write assembler in fast and convenient
ways was a problem of logistics. The Microsoft binaries
were available as free downloads which gave the low level tools necessary to
produce the binary files.
The import libraries solved another problem, with the development of the
utility L2INC.EXE, the full set of include files for all of the windows
APIs became a routine production and with the joint project of the equates
and structures in the WINDOWS.INC file being maintained, the rest was just
screwing a new package together.
One of the virtues of ancient warriors writing their own tools and
accessories is that they are not beholding to the financial considerations
of other sources and can use their own tools to build whatever they like.
The birth of the MASM32 package is based on the rights of use being
extended under copyright to any person who wishes to use it
without any form of cost whatsoever.
MASM32 comes as a working programming environment for
writing 32 bit ASM in a fast and convenient way. It needs to be installed
and the libraries need to be added in the correct directory. Once this is
done, the L2INC.EXE utility is run from the include directory which will
build a complete set of include files.
The way of testing if the installation is correct is to start the editor,
QEDITOR.EXE, load the file called TEMPLATE.ASM in the directory called
TEMPLATE and select from the Project menu, the option Build All. If all is
set up correctly, the EXE file is built by compiling the resources,
assembling the code and linking it into a 32 bit portable executable file.
The Code Design.
Almost all of the data for windows APIs comes in C or C++ notation. The
main sources of windows APIs is the WIN32.HLP file. While it is not the only
architecture available, using a C style WinMain and WndProc have a great
advantage in that they are already familiar to a very large body of
programmers who have written API code in windows.
MASM has a very good simulation of certain high level constructions that C
programmers are used to using but without any of the overhead that is
normally associated with the use of a high level language. It can do
runtime comparisons in a very similar way to the traditional C switch
block which can be nested in the normal manner.
MASM will also do a reasonable simulation of function calls using its
"invoke" syntax. The only extra step is that you must get the return value
in eax if you need the function's return value.
Writing a simulation of a function is reasonably straight forward, you
write a proc with the parameters you need, write the code that you want
and place the return value in the eax register with "ret" after it.
Data types.
The similarities stop when it comes to data types, the latest count of
C/C++ data types is now somewhere over 60 yet when you look at the header
files, they reduce down to the three that are determined by the processor
registers, :BYTE :WORD & :DWORD.
Many have approached assembler as an appendage to other languages and in
many respects, have restricted it to the limitations of the other language
but fundamentally, pure assembler is simple if you don't try to cripple
it.
MASM32 treats assembler as a language in its own right and only uses the
generic ASM data types. This factor alone reduces the enormous range of
errors that follow from incorrect data sizes.
MASM has capacities that high level languages do not have. The capacity to
write macros puts the assembler language programmer in a position to
effectively create a new language if that is what is required. Macros in
assembler are one of the very smart ways of improving throughput.
An assembler macro is a form of text expansion where you can pass
parameters to. The following is a very simple macro out of
MASM32.
return MACRO arg
mov eax, arg
ret
ENDM
This allows the programmer to type,
return 0
which in turn will be expanded by the assembler to,
mov eax, 0
ret
There is no mnemonic to copy memory to memory so a simple macro is used in
MASM32 to do this operation.
m2m MACRO M1, M2
push M2
pop M1
ENDM
This allows memory operand copy in a single line of code,
m2m mVar2, mVar1
which is expanded by the assembler to,
push mVar1
pop mVar2
MASM32 has deliberately avoided using complex macros as they are not
immediately easy to understand yet this capacity is very powerful when it
is understood and used.
The following macro is used to automate calling a DLL by the direct
method.
Using the code,
calldll
"dllname.dll","ExportFunctionName",par1,par2 etc...
The following code is expanded at assemble time and performs the direct
call to the DLL.
;--------------------------------------------------------------------------
calldll MACRO
DllName:REQ,FuncName:REQ,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,
p11,p12,p13,p14,p15,p16,p17,p18,p19,p20
LOCAL lbl ;; assembler replaces LOCAL
variables
LOCAL LibName ;; with a unique ID so that
the macro
LOCAL ProcName ;; can be called more than
once.
LOCAL ByPass
LOCAL TheEnd
jmp lbl
LibName db DllName,0
ProcName db FuncName,0
lbl:
;; -------------------------------------------
;; loop through parameters backwards and
;; push non blank ones onto the stack
;; -------------------------------------------
FOR
arg,<p20,p19,p18,p17,p16,p15,p14,p13,p12,p11,\
p10,p9,p8,p7,p6,p5,p4,p3,p2,p1>
IFNB <arg> ;; If not blank
push arg ;; push parameter
ENDIF
ENDM
mov eax, offset LibName ;; parameter for
LoadLibrary
push eax
call LoadLibrary
cmp eax, 0 ;; if function fails
je TheEnd ;; don't process
others
mov edx, offset ProcName ;; use edx so as to
not change eax
push edx
push eax ;; module handle
from LoadLibrary
mov esi, eax ;; store it in esi
call GetProcAddress ;; DLL function
address returned in eax
cmp eax, 0 ;; if function fails
je ByPass ;; don't call DLL
function
call eax ;; call the function
in DLL
ByPass:
push eax ;; function return
or 0 from
GetProcddress
push esi ;; push module
handle onto stack
call FreeLibrary
pop eax ;; pop function
return value
TheEnd:
ENDM
;------------------------------------------------------------------------
It is worth noting that the above macro contains error
checking of the
return values of some of the functions which makes the
code slightly
larger than it should be. The experienced programmer
would simply pass the
correct values to the macro and save the increase in
code size. In the
development stage, there may be some value of having
two different macros
available, one for development and the other for the
release version.
Macros of this complexity and many others like it are
among the capacity
that the assembler programmer has at their disposal
and this is one of the
ways that ASM programmers dramatically improve their
throughput of code,
the difference is that it is still pure assembler, not
some bloated bag of
junk.
A consideration in the design of MASM32 is that it
will be run on
computers
that already have other programming languages
installed on them which have
various environment settings set up for their own
requirements. MASM32
uses
no environment settings and specifies the full paths
and names of any
binary or text file that it uses.
This consideration requires a little more typing but
it ensures that the
correct include files and libraries are used. The
following example is the
normal way of using the matching include files and
libraries in MASM32.
include drv:\masm32\include\windows.inc
include drv:\masm32\include\user32.inc
include drv:\masm32\include\kernel32.inc
includelib drv:\masm32\lib\user32.lib
includelib drv:\masm32\lib\kernel32.lib
The bare mimimum code for a working exe file in MASM32
is smaller than
many
would think. Without the declarations it is as
follows,
;
#########################################################################
.code
start:
jmp @F
szDlgTitle db "Minimum MASM",0
szMsg db " --- MASM Pure and Simple ---
",0
@@:
invoke MessageBox,0,ADDR szMsg,ADDR
szDlgTitle,MB_OK
invoke ExitProcess,0
end start
;
#########################################################################
This amazing piece of bloatware assembles at 1536
bytes as a working
portable executable file. Posted at the end of this
document is a full
working template for a win32asm program that assembles
at 11264 bytes. It
has a toolbar, multi-part status bar, common dialog
support for file Open
and Save and its similarity to code written in proper
C for windows is
intentional.
MASM32 is aimed at programmers who among other things,
have a background
in
writing windows code in C, Basic & Pascal compilers
who are interested in
migrating some of their coding into pure assembler.
The architecture of
writing ASM code in a familiar and convenient way is
not only far more
productive, it assembles without size or performance
penalty to ASM code
that is written like an assembler dump.
The capacity to write assembler in a similar manner to
a high level
language
has economies in code design that actually make the
program either smaller
or faster or both.
IS THERE LIFE AFTER CRACKING ?
This may have a lot to do with what is on television
for the next few
months but boredom is a serious problem for those who
have developed the
skills of healing sick software and have nowhere else
left to go. Its like
building a rocketship but having it locked in your
garage.
There is a solution to post cracking depression,
instead of being trapped
in a maze of garbage looking for that elusive byte or
whatever, take the
next step and craft a program or two that has none of
the irritations of
the junk that you are used to shovelling through.
The brain of the cracker is well equiped to take the
next step into
writing
pure assembler as the attention to detail necessary to
write assembler is
already there, what is needed is the capacity to
impliment an architecture
that can be extended with elegance and efficiency and
this just takes
practice.
THE ANCIENTS
For those many ancient warriors who have put their
hand to the succession
of the black arts to the next generation, a small
treat is in order as a
gesture of honour between ancient warriors across
space / time, select one
of your favourite pure malts, a smooth dry highland
malt if you are in a
hot and dry land, perhaps a good Islay or Orkney malt
if your place in
space / time is cold and windy and "Salute", the
succession has started.
Now for the young guys, one of the secrets of writing
elegant and fast
assembler is the knowledge of what constitutes a good
malt and how to use
it. The correct balance will see the production of
binary of true
excellence, get it wrong and your wits will fade from
you. Ancient
warriors
have spent many years perfecting this balance.
The tools are now in your hands to write software that
has the virility
and
speed of youth, make sure it is worthy of the ancient
warriors that worked
to pass it down to you.
THE SUCCESSION
---===o===---
MASM32 and the import libraries can be downloaded from
either of the two
following sites. The excellent set of tutorials
written by Iczelion can be
downloaded from the first address.
http://win32asm.cjb.net
http://www.pbq.com.au/home/hutch/masm.htm
;
@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@
;
; MODEL.ASM
; ~~~~~~~~~
; This template is designed for a larger architecture
application which
; has a separate include file for its local prototypes
and .data section.
;
; It uses a tool bar technique which is easier to
modify & extend and it
; uses a multi-part status bar for displaying
different values at the same
; time. It also has standard File Open & File Save
common dialog boxes.
;
@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@
.386
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
include model.inc ; local includes for this
file
;
#########################################################################
.code
start:
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke GetCommandLine
mov CommandLine, eax
invoke InitCommonControls
invoke
WinMain,hInstance,NULL,CommandLine,SW_SHOWDEFAULT
invoke ExitProcess,eax
;
#########################################################################
WinMain proc hInst :DWORD,
hPrevInst :DWORD,
CmdLine :DWORD,
CmdShow :DWORD
;====================
; Put LOCALs on stack
;====================
LOCAL wc :WNDCLASSEX
LOCAL msg :MSG
LOCAL Wwd :DWORD
LOCAL Wht :DWORD
LOCAL Wtx :DWORD
LOCAL Wty :DWORD
;==================================================
; Fill WNDCLASSEX structure with required
variables
;==================================================
invoke LoadIcon,hInst,500 ; icon ID
mov hIcon, eax
mov wc.cbSize, sizeof WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
\
or CS_BYTEALIGNWINDOW
mov wc.lpfnWndProc, offset WndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
m2m wc.hInstance, hInst
mov wc.hbrBackground, COLOR_BTNFACE+1
mov wc.lpszMenuName, NULL
mov wc.lpszClassName, offset szClassName
m2m wc.hIcon, hIcon
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor, eax
m2m wc.hIconSm, hIcon
invoke RegisterClassEx, ADDR wc
;================================
; Centre window at following size
;================================
mov Wwd, 500
mov Wht, 350
invoke GetSystemMetrics,SM_CXSCREEN
invoke TopXY,Wwd,eax
mov Wtx, eax
invoke GetSystemMetrics,SM_CYSCREEN
invoke TopXY,Wht,eax
mov Wty, eax
szText szClassName,"Template_Class"
invoke CreateWindowEx,WS_EX_LEFT,
ADDR szClassName,
ADDR szDisplayName,
WS_OVERLAPPEDWINDOW,
Wtx,Wty,Wwd,Wht,
NULL,NULL,
hInst,NULL
mov hWnd,eax
szText stTxt1," Advanced MASM32 template"
invoke SendMessage,hStatus,SB_SETTEXT,3,ADDR
stTxt1
invoke LoadMenu,hInst,600 ; menu ID
invoke SetMenu,hWnd,eax
invoke ShowWindow,hWnd,SW_SHOWNORMAL
invoke UpdateWindow,hWnd
;===================================
; Loop until PostQuitMessage is sent
;===================================
StartLoop:
invoke GetMessage,ADDR msg,NULL,0,0
cmp eax, 0
je ExitLoop
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp StartLoop
ExitLoop:
return msg.wParam
WinMain endp
;
#########################################################################
WndProc proc hWin :DWORD,
uMsg :DWORD,
wParam :DWORD,
lParam :DWORD
LOCAL caW :DWORD
LOCAL caH :DWORD
LOCAL Rct :RECT
LOCAL tbab:TBADDBITMAP
LOCAL tbb :TBBUTTON
LOCAL sbParts[4] :DWORD
.if uMsg == WM_COMMAND
;======== toolbar commands ========
.if wParam == 50
szText tb1,"Button 1"
invoke MessageBox,hWin,ADDR tb1,ADDR
szDisplayName,MB_OK
.elseif wParam == 51
szText tb2,"Button 2"
invoke MessageBox,hWin,ADDR tb2,ADDR
szDisplayName,MB_OK
.elseif wParam == 52
szText tb3,"Button 3"
invoke MessageBox,hWin,ADDR tb3,ADDR
szDisplayName,MB_OK
.elseif wParam == 53
szText tb4,"Button 4"
invoke MessageBox,hWin,ADDR tb4,ADDR
szDisplayName,MB_OK
.elseif wParam == 54
szText tb5,"Button 5"
invoke MessageBox,hWin,ADDR tb5,ADDR
szDisplayName,MB_OK
.elseif wParam == 55
szText tb6,"Button 6"
invoke MessageBox,hWin,ADDR tb6,ADDR
szDisplayName,MB_OK
;======== menu commands ========
.elseif wParam == 1000
jmp @F
szTitleO db "Open A File",0
szFilterO db "All files",0,"*.*",0,
"Text files",0,"*.TEXT",0,0
@@:
invoke FillBuffer,ADDR szFileName,length
szFileName,0
invoke GetFileName,hWin,ADDR szTitleO,ADDR
szFilterO
cmp szFileName[0],0 ;<< zero if cancel
pressed in dlgbox
je @F
; file name returned in szFileName
invoke MessageBox,hWin,ADDR szFileName,
ADDR szDisplayName,MB_OK
@@:
.elseif wParam == 1001
jmp @F
szTitleS db "Save file as",0
szFilterS db "All files",0,"*.*",0,
"Text files",0,"*.TEXT",0,0
@@:
invoke FillBuffer,ADDR szFileName,length
szFileName,0
invoke SaveFileName,hWin,ADDR szTitleS,ADDR
szFilterS
cmp szFileName[0],0 ;<< zero if cancel
pressed in dlgbox
je @F
; file name returned in szFileName
invoke MessageBox,hWin,ADDR szFileName,
ADDR szDisplayName,MB_OK
@@:
.elseif wParam == 1010
invoke
SendMessage,hWin,WM_SYSCOMMAND,SC_CLOSE,NULL
.elseif wParam == 1900
szText AboutMsg,"MASM32 Pure Assembler
Template",13,10,\
"Copyright © MASM32 1999"
invoke ShellAbout,hWin,ADDR
szDisplayName,ADDR AboutMsg,hIcon
.endif
;====== end menu commands ======
.elseif uMsg == WM_SYSCOLORCHANGE
invoke Do_ToolBar,hWin
.elseif uMsg == WM_CREATE
invoke Do_ToolBar,hWin
invoke CreateStatusWindow,WS_CHILD or
WS_VISIBLE or \
SBS_SIZEGRIP,NULL,
hWin, 200
mov hStatus, eax
; -------------------------------------
; sbParts is a DWORD array of 4 members
; -------------------------------------
mov [sbParts + 0], 100 ; 1st member,
pixels from edge
mov [sbParts + 4], 200 ; 2nd member,
pixels from edge
mov [sbParts + 8], 300 ; 3rd member,
pixels from edge
mov [sbParts +12], -1 ; 4th member,
furthest right side
invoke SendMessage,hStatus,SB_SETPARTS,4,ADDR
sbParts
.elseif uMsg == WM_SIZE
invoke SendMessage,hToolBar,TB_AUTOSIZE,0,0
invoke MoveWindow,hStatus,0,0,0,0,TRUE
.elseif uMsg == WM_CLOSE
szText TheText,"Please Confirm Exit"
invoke MessageBox,hWin,ADDR TheText,ADDR
szDisplayName,MB_YESNO
.if eax == IDNO
return 0
.endif
.elseif uMsg == WM_DESTROY
invoke PostQuitMessage,NULL
return 0
.endif
invoke DefWindowProc,hWin,uMsg,wParam,lParam
ret
WndProc endp
;
########################################################################
TopXY proc wDim:DWORD, sDim:DWORD
shr sDim, 1 ; divide screen dimension by 2
shr wDim, 1 ; divide window dimension by 2
mov eax, wDim ; copy window dimension into eax
sub sDim, eax ; sub half win dimension from
half screen dimension
return sDim
TopXY endp
;
########################################################################
GetFileName proc
hParent:DWORD,lpTitle:DWORD,lpFilter:DWORD
mov ofn.lStructSize, sizeof OPENFILENAME
m2m ofn.hWndOwner, hParent
m2m ofn.hInstance, hInstance
m2m ofn.lpstrFilter, lpFilter
m2m ofn.lpstrFile, offset szFileName
mov ofn.nMaxFile, sizeof szFileName
m2m ofn.lpstrTitle, lpTitle
mov ofn.Flags, OFN_EXPLORER or
OFN_FILEMUSTEXIST or \
OFN_LONGNAMES
invoke GetOpenFileName,ADDR ofn
ret
GetFileName endp
;
#########################################################################
SaveFileName proc
hParent:DWORD,lpTitle:DWORD,lpFilter:DWORD
mov ofn.lStructSize, sizeof OPENFILENAME
m2m ofn.hWndOwner, hParent
m2m ofn.hInstance, hInstance
m2m ofn.lpstrFilter, lpFilter
m2m ofn.lpstrFile, offset szFileName
mov ofn.nMaxFile, sizeof szFileName
m2m ofn.lpstrTitle, lpTitle
mov ofn.Flags, OFN_EXPLORER or
OFN_LONGNAMES
invoke GetSaveFileName,ADDR ofn
ret
SaveFileName endp
;
########################################################################
FillBuffer proc
lpBuffer:DWORD,lenBuffer:DWORD,TheChar:BYTE
push edi
mov edi, lpBuffer ; address of buffer
mov ecx, lenBuffer ; buffer length
mov al, TheChar ; load al with character
rep stosb ; write character to buffer
until ecx = 0
pop edi
ret
FillBuffer endp
;
########################################################################
SetBmpColor proc hBitmap:DWORD
LOCAL mDC :DWORD
LOCAL hBrush :DWORD
LOCAL hOldBmp :DWORD
LOCAL hReturn :DWORD
LOCAL hOldBrush :DWORD
invoke CreateCompatibleDC,NULL
mov mDC,eax
invoke SelectObject,mDC,hBitmap
mov hOldBmp,eax
invoke GetSysColor,COLOR_BTNFACE
invoke CreateSolidBrush,eax
mov hBrush,eax
invoke SelectObject,mDC,hBrush
mov hOldBrush,eax
invoke GetPixel,mDC,1,1
invoke ExtFloodFill,mDC,1,1,eax,FLOODFILLSURFACE
invoke SelectObject,mDC,hOldBrush
invoke DeleteObject,hBrush
invoke SelectObject,mDC,hBitmap
mov hReturn,eax
invoke DeleteDC,mDC
mov eax,hReturn
ret
SetBmpColor endp
;
########################################################################
Do_ToolBar proc hWin :DWORD
LOCAL bSize :DWORD
LOCAL tbab :TBADDBITMAP
LOCAL tbb :TBBUTTON
szText tbClass,"ToolbarWindow32"
invoke CreateWindowEx,0,
ADDR tbClass,
ADDR szDisplayName,
WS_CHILD or WS_VISIBLE, ;
or TBSTYLE_FLAT,
0,0,500,40,
hWin,NULL,
hInstance,NULL
mov hToolBar, eax
invoke
SendMessage,hToolBar,TB_BUTTONSTRUCTSIZE,sizeof
TBBUTTON,0
; ---------------------------------------
; Put width & height of bitmap into DWORD
; ---------------------------------------
mov ecx,25 ; loword = bitmap Width
mov eax,25 ; hiword = bitmap Height
shl eax,16
mov ax, cx
mov bSize, eax
invoke
SendMessage,hToolBar,TB_SETBITMAPSIZE,0,bSize
; ------------------
; the toolbar bitmap
; ------------------
invoke LoadBitmap,hInstance,750
mov hTbBmp,eax
invoke SetBmpColor,hTbBmp
mov hTbBmp,eax
mov tbab.hInst, 0
m2m tbab.nID, hTbBmp
invoke SendMessage,hToolBar,TB_ADDBITMAP,12,ADDR
tbab
invoke
SendMessage,hToolBar,TB_SETBUTTONSIZE,0,bSize
mov tbb.fsState, TBSTATE_ENABLED
mov tbb.dwData, 0
mov tbb.iString, 0
mov tbb.iBitmap, 0
mov tbb.idCommand, 0
mov tbb.fsStyle, TBSTYLE_SEP
invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR
tbb
mov tbb.iBitmap, 0
mov tbb.idCommand, 50
mov tbb.fsStyle, TBSTYLE_BUTTON
invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR
tbb
mov tbb.iBitmap, 1
mov tbb.idCommand, 51
mov tbb.fsStyle, TBSTYLE_BUTTON
invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR
tbb
mov tbb.iBitmap, 2
mov tbb.idCommand, 52
mov tbb.fsStyle, TBSTYLE_BUTTON
invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR
tbb
mov tbb.iBitmap, 0
mov tbb.idCommand, 0
mov tbb.fsStyle, TBSTYLE_SEP
invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR
tbb
mov tbb.iBitmap, 3
mov tbb.idCommand, 53
mov tbb.fsStyle, TBSTYLE_BUTTON
invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR
tbb
mov tbb.iBitmap, 4
mov tbb.idCommand, 54
mov tbb.fsStyle, TBSTYLE_BUTTON
invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR
tbb
mov tbb.iBitmap, 5
mov tbb.idCommand, 55
mov tbb.fsStyle, TBSTYLE_BUTTON
invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR
tbb
ret
Do_ToolBar endp
;
########################################################################
end start
+HCU papers
homepage
links
anonymity
+ORC
students' essays
academy database
antismut
tools
bots & agents reversing
cocktails
javascript wars
search_forms
mail_fravia
Is reverse engineering illegal?