Unlike before, I went through the help files this time :) Unfortunately, unlike with the floating point, I don't quite know what I'm looking for. Basically, I want a program that'll use EnumWindows (with two callbacks) that will... hide and show windows. Their functionalities are as follows:
Hide windows will, for each window, see if that window is visible. If it is, then it will add the window's handle to an array (preferrably a dynamic one of sorts...?), hide it, and move onto the next window. After all windows are hidden, the program's window will set a global hotkey that will bring the assembly window back to visible.
Show windows will, for each window in the aforementioned array, go back and un-hide them all.
The purpose is almost a form of protection. I want to hide all my windows, and be able to summon them back by using my program (most likely with a password for added security). The beauty of it is, if they try to use task manager or somesuch to kill it, it'll still leave all the windows hidden. One other thing I might implement is a timer so that every second, it will re-hide all visible windows (and append them to the array) while in the "hidden" mode.
My main problem is, I don't know how to implement a dynamically sized array. I've looked around and seen an example of linked lists, some HLA thing, a lot of stuff... but I don't fully understand it, or it's seemingly far too complicated for this. Is there an easier way? Thanks in advance.
Quote from: Krozgen on December 08, 2005, 05:05:55 AMMy main problem is, I don't know how to implement a dynamically sized array. I've looked around and seen an example of linked lists, some HLA thing, a lot of stuff... but I don't fully understand it, or it's seemingly far too complicated for this. Is there an easier way? Thanks in advance.
Your question is: "how should i keep track of my windows?". This one really is way simpler than you thought. Instead of trying to search sites and/or posts looking for the one correct answer to this question, just sit down and think about it logically for 10 minutes - you will slap your forehead when you realise that you were making it more difficult than what it actually is. And linked lists are easy too, just take the time to read a couple of different tutorials on them, and you will agree with me :8)
For this issue, a linked list is technically your best option because you have a variable number of windows. OTOH, a linked list could be overkill because you wouldn't have that many windows.
Your *array* doesn't have to be variable in size - it is just the number of used array elements that will vary. So why don't you allocate an array of maybe 100 elements in size, knowing that you will probably only ever use 20 to 30 of those elements at any one time?
The thing you haven't thought of is: "when i make a window visible because it is in my list, should it really be visible? What if the application had made it invisible and i am over-riding that?".
I suggest you take a different approach that requires
absolutely no coding at all!!!! Just use a secure OS (ie not Win9x), and use a screen saver, or lock the machine :lol
I'm going to start with the end of your post first, if you don't mind, Sluggy :)
QuoteI suggest you take a different approach that requires absolutely no coding at all!!!! Just use a secure OS (ie not Win9x), and use a screen saver, or lock the machine
It's not so much the purpose of the program that I'm interested in as the concepts learned in making it. By testing out enumwindows and learning about arrays / linked lists in assembly in this manner, I'll learn fifty times faster (just my preference).
As to a fixed size array - I've already figured that out :) I was going to use one, but for one, I'm not wholly sure that it'll be less than the size I allocate (and I really like saving space!!!), and two, a dynamic array is the way to go (or a linked list), imho. That's the whole point of them.
You said a linked list is technically my best option, this I knew beforehand, and if it's as easy as you say to implement one, then it shouldn't be overkill... no? :8)
And the final thing you mentioned (to make this response complete, before I go try to find some more linked list material)...
QuoteThe thing you haven't thought of is: "when i make a window visible because it is in my list, should it really be visible? What if the application had made it invisible and i am over-riding that?".
That's exactly why I'm making the linked list :) I'm going to check to make sure it's
already visible, and if it is, then add it to my spiffy new list. When I un-hide the windows, I'll restore only those windows to a visible position. If you think that won't work, then please provide a feasible alternative ^_^
So... I guess what I'm trying to say here is, I'm just using this as a method of learning. If you have a suggestion for a program to make next to learn some other cool aspect of assembly, let me know! In the meantime, I'm off to look up some more linked list stuff :U
Don't forget to look up memory allocation stuff too.
Linked lists in other languages might be fun, but they can get ugly very easily in assembly language :bg
Eh, I went with a fixed size array... did the job perfectly. I hope no one will mind my posting the full source here... eh, it's relevant :)
hideshow.asm
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.386 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD ; define procedure
.data
dlgname db "HideShowWindowsDialog",0
passwordprompt db "Password? :|",0
invalidpass db "Invalid password :(",0
validpass db "Valid password :)",0
HandleArray dword 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
NumWinsHidden dword 0
LoopCounter byte 0
WindowsHidden bool 0
TempPassword dword ?
.data?
hInstance dd ? ; instance for dialogbox
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.code
start:
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke DialogBoxParam, hInstance, ADDR dlgname, NULL, ADDR WndProc, NULL
invoke ExitProcess, eax
; -------------------------------------------------------------------------
WndProc proc hWin :DWORD,
uMsg :DWORD,
wParam :DWORD,
lParam :DWORD
.if uMsg == WM_COMMAND ; a button has been pressed
.if wParam == 100 ; "Find Open & Hide"
.if WindowsHidden == 0
mov eax,offset HandleArray
mov LoopCounter,0
loop_to_initialize:
mov ebx, 0
mov [eax],ebx
add eax,4
inc LoopCounter
cmp LoopCounter,30
jl loop_to_initialize
mov NumWinsHidden,0
push 0
push offset CountNumberVisibleWindowsProcCallback
call EnumWindows
push SW_HIDE
call HideOrRecallWindows
mov WindowsHidden, 1
invoke ShowWindow,hWin,SW_SHOW
;invoke SetDlgItemInt, hWin, 150, NumWinsHidden, TRUE
invoke SetDlgItemText, hWin, 150, addr passwordprompt
.endif
.elseif wParam == 101 ; "Recall Open & Show"
.if WindowsHidden == 1
invoke GetDlgItemInt, hWin, 150, TempPassword, 10
.if eax == 1337
push SW_SHOW
call HideOrRecallWindows
invoke SetDlgItemText, hWin, 150, addr validpass
mov WindowsHidden, 0
.elseif
invoke SetDlgItemText, hWin, 150, addr invalidpass
.endif
.endif
.elseif wParam == 200 ; exit button
.if WindowsHidden==0
invoke EndDialog,hWin,NULL
.endif
.endif
.elseif uMsg == WM_CLOSE ; X button
.if WindowsHidden==0
invoke EndDialog,hWin,NULL
.endif
.endif
xor eax,eax ; THIS LINE IS KEY! Without it, no dialog "window" appears,
; and the program goes into an infinite loop.
ret
WndProc endp
; -------------------------------------------------------------------------
CountNumberVisibleWindowsProcCallback proc hWin :DWORD, lParam :DWORD
push ebx
invoke IsWindowVisible,hWin
.if eax == TRUE
mov ebx,NumWinsHidden
shl ebx,2
add ebx,offset HandleArray
mov eax, hWin
mov [ebx],eax
inc NumWinsHidden
.endif
mov eax, 1
pop ebx
ret
CountNumberVisibleWindowsProcCallback endp
; -------------------------------------------------------------------------
HideOrRecallWindows proc HideOrShow :WORD
push ebx
mov ebx,offset HandleArray
mov LoopCounter,0
loop_to_hide:
mov eax,[ebx]
invoke ShowWindow,eax,HideOrShow
add ebx,4
inc LoopCounter
cmp LoopCounter,30
jl loop_to_hide
pop ebx
ret
HideOrRecallWindows endp
; -------------------------------------------------------------------------
end start
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
rsrc.rc
#include "\masm32\include\resource.h"
HideShowWindowsDialog DIALOGEX 0, 0, 159, 200
STYLE DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Hide / Show Windows App"
FONT 8, "Tahoma"
{
CONTROL "Find Open and &Hide", 100, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 7, 22, 146, 14
CONTROL "Recall Open and &Show", 101, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 7, 40, 146, 14
CONTROL "&Quit", 200, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 6, 180, 50, 14
CONTROL "Password?", 150, EDIT, ES_CENTER | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 6, 5, 147, 13
}
It's pretty clear what it does... very basic, but helped me learn "arrays". Yea... so basically, it's limited to 30 windows. That amount could be easily modified, but it will always be fixed. At present, the exe is just over 3 KB, and when rar'ed, just below 1 KB. Not bad for a first go, in my opinion :)
HandleArray dword 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
This line could be simplified by using the DUP operator:
HandleArray DWORD 30 DUP (0)
Then you can replace the 30 with an equate and never look at it again.
Also, if you declare it in the uninitialised data section (.data?), it won't make your executable larger:
.data?
HandleArray DWORD 30 DUP (?)
Note though that MASM doesn't like very large amounts of DUPs (ie. 10000+, depending on your computer) and tends to take a long time - search the forum for more on this
Cheers,
Zooba
Thank you so much! One sample of code I originally found as an example of arrays used the DUP, but I didn't underestand it. I also appreciate the info on the data? section; never understood that either! AWSOME! *Dances* How does it not affect the .exe size, if you don't mind me asking?
- EDIT -
Uh... I tried the modification, and it seems to work perfectly, but the executable size didn't go down at all :( Any explanation...?
Quote from: Krozgen on December 13, 2005, 04:15:19 AMHow does it not affect the .exe size, if you don't mind me asking?
Using the '.data?' section tells the assembler it doesn't have to remember what goes into the data. So it just remembers how much data there is and when your executable loads it will allocate that amount. Notice that you cannot initialise anything in the .data? section:
.data?
dwNumber DWORD 123 ; illegal
dwNumber DWORD ? ; legal
The '.data' section remembers how much data and actually
keeps a copy of all the data in the executable (where else can it keep it?). So if you disassemble an executable containing:
.data
HandleArray DWORD 30 DUP (0)
You will find 30 DWORDs (120 bytes) all filled with zeros. However:
.data?
HandleArray DWORD 30 DUP (?)
will not produce 120 bytes worth of zeros. On the downside, there is no way of guaranteeing the values of the variables (and the assembler won't check how you access it like a HLL will), so you have to make sure you initialise it manually. In your case, you are keeping track of the number of handles separately, so you can do this.
In response to your edit, what is your current executable size? There is a minimum size which you can only go below using special linkers. Try using 300 instead of 30 (in both .data and .data?) and see if there is a difference.
Ah, very cool explanation :) The .exe is 3,072 bytes... changing the 30 to 300 didn't change anything, so maybe the minimum size is 3 KB? Eh... UPX couldn't compress it anymore, interestingly enough.
Hi Krozgen,
Try Pelle's PoLink to link your object file, it will reduce the size of your executables. PoLink cames with Hutch's masm32 package.
Good, got the .exe down to 2,048 bytes (2 KB). The makefile's been changed to:
@echo off
if not exist rsrc.rc goto over1
\masm32\bin\rc /v rsrc.rc
\masm32\bin\cvtres /machine:ix86 rsrc.res
:over1
if exist "hideshow.obj" del "hideshow.obj"
if exist "hideshow.exe" del "hideshow.exe"
\masm32\bin\ml /c /coff "hideshow.asm"
if errorlevel 1 goto errasm
if not exist rsrc.obj goto nores
REM \masm32\bin\Link /SUBSYSTEM:WINDOWS "hideshow.obj" rsrc.res
\masm32\bin\polink /SUBSYSTEM:WINDOWS "hideshow.obj" rsrc.res
if errorlevel 1 goto errlink
dir "hideshow.*"
goto TheEnd
:nores
REM \masm32\bin\Link /SUBSYSTEM:WINDOWS "hideshow.obj"
\masm32\bin\polink /SUBSYSTEM:WINDOWS "hideshow.obj"
if errorlevel 1 goto errlink
dir "hideshow.*"
goto TheEnd
:errlink
echo _
echo Link error
goto TheEnd
:errasm
echo _
echo Assembly Error
goto TheEnd
:TheEnd
pause
You can see where I changed it with the REMs. Is this what you were referring to? If there's any other way of getting it down further, please let me know.