The MASM Forum

General => The Workshop => Topic started by: clamicun on December 05, 2014, 04:53:32 AM

Title: Progressbar starts too late
Post by: clamicun on December 05, 2014, 04:53:32 AM
This is a part of my own "Search Program".
It is far from beeing finished.

I am puzzled because the progressbar does not start  to run when it should ....
Very likely I do not understand some  basics.
----
I start the progressbar -(Modeless dialog)...
Immediately after - I start the proc which searches for existing directories in the choosen path...

The progressbar shows up, but starts running only after the search has finished.

Any good ideas ?

PS.
I do know that I have to "hook" the progressbar somehow to the search proc - but first things first.
If your machine goes down - enlarge the dir_array buffer. My C:\ only contents 19000 directories.


 
Title: Re: Progressbar starts too late
Post by: jj2007 on December 05, 2014, 07:04:46 AM
You need to send a message to the progress bar from the loop where you find the directories. SetTimer is not the right approach...

Attached a modified example, using a fake WM_TIMER message.

Note that I get a different count with GetFolders() (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1058), but no idea why. You might compare them with the WindowsFolders.txt file created with the snippet below (about 2MB).

include \masm32\MasmBasic\MasmBasic.inc      ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Let esi=ExpandEnv$("%WINDIR%\")      ; 21204 (JJ) vs 18624 (clamicun)
  PrintLine "Searching ", esi
  GetFolders esi
  Print Str$("%i folders found, first 10:\n", eax)
  xor ecx, ecx
  .Repeat
      PrintLine Files$(ecx)
      inc ecx
  .Until ecx>10
  Store "WindowsFolders.txt", Files$()
  Inkey "ok?"
  Exit
end start
Title: Re: Progressbar starts too late
Post by: clamicun on December 05, 2014, 10:09:34 PM
jj2007 thank you.

"You need to send a message to the progress bar from the loop where you find the directories. SetTimer is not the right approach..."

I try to organize the message - not exactely shure what kind of msg..

----------------
I made the directory selection  a bit easier...

CreateDirArray proc
pushad

xor eax,eax
mov eax,wfd.dwFileAttributes
AND eax,16

;push eax
;INVOKE MessageBox,0,offset wfd.cFileName,offset cur_path,0
;INVOKE wsprintf,offset wsprintf_msg,offset testintdd,wfd.dwFileAttributes
;INVOKE MessageBox,0,offset wsprintf_msg,offset cur_path,0
;pop eax

;.if  eax == 16 || eax == 17   || eax == 18   ||  eax == 19  || eax == 22 \
;               || eax == 48   || eax == 50   ||  eax == 51 \
;               || eax == 8208 || eax == 8212 || eax == 8214 ||  eax == 8240 || eax == 9238

.if eax != 0

;Above I included AttribValue 8212 - The count is different now - much higher
;INVOKE MessageBox,0,offset wfd.cFileName,offset cur_path,0

;--- Clean array ----
"
"
----------------
Have a good one
Title: Re: Progressbar starts too late
Post by: Tedd on December 06, 2014, 12:05:49 AM
The issue is that you only have one thread.
The search keeps the thread busy, so the window doesn't get updated, so the progress bar isn't updated.
Run the search in a separate thread and then the window can continue to be updated.
Title: Re: Progressbar starts too late
Post by: clamicun on December 06, 2014, 01:04:53 AM
JJ
Your program creates the textfile - and real fast.
But it does not give out any message and does not end. I have to kill it with the taskmanager !
So I can not compare the result to the result of my very slow proc.
----------
On my computer it works like this...
include \masm32\MasmBasic\MasmBasic.inc      ; download

.data
;------------
store_folder TCHAR 'Folders.txt',0

;cur_path    TCHAR 'D:\test\',0
;cur_path    TCHAR 'D:\arquivo\',0
;cur_path    TCHAR 'D:\software\',0
cur_path     TCHAR 'C:\windows\',0

.code

  Init

  mov esi,offset cur_path
 
  PrintLine "Searching ", esi            ;No
  GetFolders esi
  Print Str$("%i folders found, first 10:\n", eax)   ;No
 
;-----  ???
  ;xor ecx, ecx
  ;.Repeat

      PrintLine Files$(ecx)   ;No
      ;inc ecx
  ;.Until ecx > 1
  ;Store "WindowsFolders.txt", Files$()
 ;-----  ???
 
  Store offset store_folder, Files$()
 
  ;Inkey "ok?"          ;No - This causes to not end the program !
  INVOKE MessageBox,0,offset cur_path,offset cur_path,0
  INVOKE ExitProcess,0
end start

---------------------------------
Tedd
Yes - I already thought on the multithread problem. I think that is it
Title: Re: Progressbar starts too late
Post by: jj2007 on December 06, 2014, 02:51:15 AM
JJ
Your program creates the textfile - and real fast.
But it does not give out any message and does not end. I have to kill it with the taskmanager !

In case you are using qEditor or similar: You need to build it as a console application, otherwise print and inkey won't work.
RichMasm autodetects console apps, but most other IDEs don't, unfortunately.

Speedwise there is not much difference between our codes. According to my timings, GetFolder may be a little bit faster (20%?), but that doesn't really matter. For both, there is a huge difference between the first and the second time you run the program, due to the file cache. A more interesting question is why the folder counts differ - could be linked to attributes like system & hidden.
Title: Re: Progressbar starts too late
Post by: jj2007 on December 06, 2014, 02:58:30 AM
The issue is that you only have one thread.
The search keeps the thread busy, so the window doesn't get updated, so the progress bar isn't updated.

Interesting point, Tedd. My example above (console build!) works with a single thread, but the progress bar does get updated. It seems that SendMessage returns only after the progress bar has been updated.

The bigger problem is that you can't tell beforehand how many folders correspond to 100% :(

There seems no API that can do that, so apparently you need FindFirstFile & FindNextFile to find the total number of folders; which implies that you'll know what 100% means after the exercise, but during the search you'll have no idea - which makes the progress bar kind of meaningless. Unless somebody knows a magic API that can ask the NTFS directly "how many subfolders are in %WinDir%?"...
Title: Re: Progressbar starts too late
Post by: clamicun on December 06, 2014, 04:36:34 AM
JJ

Here is a fine working proc - made from yours.
S4F.zip

The differences  indeed seem to be "Windowsmade". Obviously "getfolders" does not count  folders with certain attributes.

On the progressbar I am working. If I find solution, I let you know.
Title: Re: Progressbar starts too late
Post by: jj2007 on December 06, 2014, 05:33:37 AM
Here is a fine working proc - made from yours.
Thanks :biggrin:

Quote
The differences  indeed seem to be "Windowsmade". Obviously "getfolders" does not count  folders with certain attributes.

My impression was that GetFolders counts more folders than yours, but I could be wrong, of course.

One more, just for fun:

include \masm32\MasmBasic\MasmBasic.inc      ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Let esi=FolderOpen$("Pick a folder:", "Masm is great;", "\Masm32\examples\exampl01")+"\*"
  GetFolders esi
  push eax            ; save folder count to stack
  xor ecx, ecx
  .Repeat
      Print Str$("\n%i\t",ecx), Files$(ecx)
      inc ecx
  .Until ecx>=stack
  pop eax
  Inkey Str$("\n%i folders found in ", eax), esi
  Exit
end start
Title: Re: Progressbar starts too late
Post by: TWell on December 06, 2014, 06:08:11 AM
If call something like this inside loop, GUI may work ?
Code: [Select]
CheckMsgQueue PROC hWnd:DWORD
LOCAL msg:MSG
.WHILE 1
INVOKE PeekMessageA,ADDR msg,hWnd,0,0,1
.BREAK .IF (!eax)
.BREAK .IF (msg.message == 012h) ; WM_QUIT
INVOKE TranslateMessage,ADDR msg
INVOKE DispatchMessageA,ADDR msg
.ENDW
ret
CheckMsgQueue ENDP
Correct this, if there is something wrong.
Title: Re: Progressbar starts too late
Post by: jj2007 on December 06, 2014, 09:17:23 PM
If call something like this inside loop, GUI may work ?

You should post the complete code to see how it is embedded in the rest of the application. PeekMessage is generally not such a good idea, because it can drive up CPU usage.

In the meantime, GetFolders() (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1058) has learnt to accept a callback. Below a very simple example, but you could also implement a file counter, or display all files/paths found or tested etc; edx is current count, edi is path tested with FindFirstFileEx, and eax is the result of the test.

include \masm32\MasmBasic\MasmBasic.inc     ; download version 6 December (http://masm32.com/board/index.php?topic=94.0)
  Init
  Let esi=ExpandEnv$("%WINDIR%\System32")   ; usually C:\Windows\System32
  Print "Searching ", esi, ": "
  GfCallback cbGetFiles                     ; define a callback function
  GetFolders esi
  Print Str$(" - %i folders found, first 20:", eax)
  xor ecx, ecx
  .Repeat
      Print Str$("\n%i\t", ecx+1), Files$(ecx)
      inc ecx
  .Until ecx>=20
  ; Store "Sys32Folders.txt", Files$()      ; in case you need a textfile
  Inkey CrLf$, "ok?"
  Exit

cbGetFiles:
  test edx, 31       ; edx is file or folder counter
  .if Zero?          ; every once in while
      Print "*"      ; console mode progress bar ;-)
  .endif
  ret
end start


Simple variant displaying the file counter in a constant position on the screen:

cbGetFiles:
  Print Str$(edx), Cr$
  ret
Title: Re: Progressbar starts too late
Post by: TWell on December 06, 2014, 09:39:05 PM
You should post the complete code to see how it is embedded in the rest of the application. PeekMessage is generally not such a good idea, because it can drive up CPU usage.
No code as i'm not an asm programmer.
I like use that PeekMessage in single threaded program as it make debugging easier.
Title: Re: Progressbar starts too late
Post by: clamicun on December 08, 2014, 10:04:23 PM
JJ,
"My impression was that GetFolders counts more folders than yours, but I could be wrong, of course.!

Excuse me - .Of course you were not wrong. GetFolders counted more. Not any more. I found out why.

Windows creates folders like: \.NET ,  \.!!,   \.cache   

Because of the line

.if byte ptr  wfd.cFileName != '.'

my program did not find them.

Your program GetFolders with callback does  not compile on my computer...
Syntax error : gfCallback on line 5.
----------
Tedd,
"The issue is that you only have one thread.Run the search in a separate thread and then the window can continue to be updated."

Could you or someone be a bit more explicit - I do not have the slightest idea how to start a new thread.
Title: Re: Progressbar starts too late
Post by: jj2007 on December 09, 2014, 01:15:17 AM
Your program GetFolders with callback does  not compile on my computer...
Syntax error : gfCallback on line 5.

You must have an incredibly old version of MasmBasic: Since 6 December, it understands GfCallback (note: uppercase G and C). And since right now (download again, please (http://masm32.com/board/index.php?topic=94.0)), the callback passes in ebx the address of the WIN32_FIND_DATAW structure used to do the search - see example below.

I am curious to see your latest version, to see whether they still differ, and where.

include \masm32\MasmBasic\MasmBasic.inc      ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Let esi=ExpandEnv$("%WINDIR%")      ; usually C:\Windows
  PrintLine "Searching ", esi, ": "
  GfCallback cbGetFiles      ; define a callback function
  GetFolders esi
  Print Str$("%i folders found, first 20:", eax)
  xor ecx, ecx
  .Repeat
      Print Str$("\n%i\t", ecx+1), Files$(ecx)
      inc ecx
  .Until ecx>=20
  ; Store "Sys32Folders.txt", Files$()      ; in case you need a textfile
  Inkey CrLf$, "ok?"
  Exit

cbGetFiles:
  test edx, 1023      ; edx is file or folder counter
  .if Zero?                  ; every once in while
      lea edx, [ebx.WIN32_FIND_DATAW.cFileName]
      Print edx, CrLf$
  .endif
  ret
end start
Title: Re: Progressbar starts too late
Post by: clamicun on December 10, 2014, 03:36:52 AM
Hello JJ,
here are the 2 versions. My finds 2 folders more on my C-Drive.
I didn't yet see which entries are not there, because the textfiles are 200KB - that is labourious.

Yours is better. I don't know how it finds the folders which start with '.' without explicitly naming them as my does.
What is the difference between WIN32_FIND_DATA  and WIN32_FIND_DATAW ?     
Title: Re: Progressbar starts too late
Post by: Tedd on December 10, 2014, 03:40:24 AM
"The issue is that you only have one thread.Run the search in a separate thread and then the window can continue to be updated."

Could you or someone be a bit more explicit - I do not have the slightest idea how to start a new thread.
CreateThread (http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453%28v=vs.85%29.aspx) will start a new thread; you provide the offset of your search function for lpStartAddress, and lpParameter allows you to pass in a single parameter (a value, or a pointer to something useful.)
This thread will then run in parallel with your main window thread.
So then you can update a progress value from the new thread, and have the window update to reflect that value. But try to keep shared variables to a minimum to avoid weird synchronisation bugs.
Title: Re: Progressbar starts too late
Post by: jj2007 on December 10, 2014, 04:09:15 AM
What is the difference between WIN32_FIND_DATA  and WIN32_FIND_DATAW ?

No big difference. I used the Unicode version because ANSI FindFirstFile works with the wide version but not the other way round.

Good and bad news:
- Absolutely no difference for C:\Windows, 20,000 folders
- Your version chokes for my complete C: drive. The culprit is here:

00401313               ³.  3C 40                   ³cmp al, 40
00401315               ³. 74 F7                   ³je short 0040130E
00401317               ³.  AA                      ³stosb


That is at the beginning of Clean_Dir_Array.

For the comparison of the textfiles, I used this snippet: It loads both files into an array, strips the \* from your version, sorts both arrays alphabetically and then checks if the strings are identical. They are.

include \masm32\MasmBasic\MasmBasic.inc
  SetGlobals ctc, ctj
  Init
  SetGlobals
  Recall "Folders_Clam.txt", cl$()
  push eax
  xor ecx, ecx
  .Repeat
      mov esi, cl$(ecx)
      Let cl$(ecx)=Left$(esi, Len(esi)-2)
      inc ecx
  .Until ecx>=stack
  pop eax
  QSort cl$()
  mov ctc, eax
  Recall "Folders_JJ_Callback.txt", jj$()
  QSort jj$()
  mov ctj, eax
  xor ecx, ecx
  .Repeat
      .if !Instr_(cl$(ecx), jj$(ecx))
            deb 1, "Gotcha", ecx, $cl$(ecx), $jj$(ecx)      ; no Gotcha seen for C:\Windows!
      .endif
      inc ecx
  .Until ecx>=ctc
  deb 4, "Counts", ctc, ctj
  Exit
end start


P.S.: For a better comparison e.g. with fc (=file compare), use e.g.
  mov ctj, eax
  Store "Folders_C.txt", cl$()   ; write the sorted and stripped strings to disk
  Store "Folders_J.txt", jj$()   ; write the sorted strings to disk
  xor ecx, ecx
Title: Re: Progressbar starts too late
Post by: clamicun on December 11, 2014, 03:51:47 AM
JJ,
this was a stupid mistake in Clean_Dir_Array, which I corrected.
Your "Compare File Routine" is very helpful.
Thank you for everything. I learned a lot.

A last question.

.if byte ptr FileName != '.'  || byte ptr FileName+1 == '!'   ;works on a folder  .!!OIM

Why doesn't this have the same effect?

.if byte ptr wfd.cFileName != '.'  || byte ptr wfd.cFileName+1 != '  '   ;shows the old MS-DOS '.' and '..'  folders

Am I illogic?

Now I go back and try to organize the progressbar.
 
Title: Re: Progressbar starts too late
Post by: jj2007 on December 11, 2014, 04:24:08 AM
Thank you for everything. I learned a lot.

My pleasure :icon14:

Quote
.if byte ptr FileName != '.'  || byte ptr FileName+1 == '!'   ;works on a folder  .!!OIM

Not quite sure what you are looking at, but dot folders are 2E00h (=current folder aka ".") and 2E2E00h (=parent folder aka "..") - all others are named folders or files. So you might want to check for the position of the nullbyte, e.g. via word ptr []==2E00h
Title: Re: Progressbar starts too late
Post by: dedndave on December 11, 2014, 10:51:28 AM
be aware that a valid file or folder name may have a '.' as the second char
so - that test is only good if the first char is also '.'   :biggrin:
Title: Re: Progressbar starts too late
Post by: jj2007 on December 11, 2014, 05:34:36 PM
be aware that a valid file or folder name may have a '.' as the second char
so - that test is only good if the first char is also '.'   :biggrin:

dot folders are 2E00h (=current folder aka ".") and 2E2E00h (=parent folder aka "..") - all others are named folders or files. So you might want to check for the position of the nullbyte, e.g. via word ptr []==2E00h

From the top secret MasmBasic source:

                        lea edx, [ebx.WIN32_FIND_DATA.cFileName]
                        mov eax, [edx]            ; might be ., .. or .aname
                        .if al=="."
                                    shr eax, 8                              ; aname or nullbyte?
                                    .if !al
                                          xor eax, eax
                                    .elseif al=="."
                                          shr eax, 8
                                          .if !al
                                                xor eax, eax
                                          .endif
                                    .endif
                        .endif
                        .if eax
;)
Title: Re: Progressbar starts too late
Post by: nidud on December 11, 2014, 11:04:13 PM

   .this is a legal filename
   .! and so is this
   . and this to
   ..even this is legal
   but not this "x." --> "x"

Code: [Select]
mov ax,'.' ; 002E
cmp ax,[edx] ; ".",0
je skip
cmp ax,[edx+1] ; "..",0
je skip
Title: Re: Progressbar starts too late
Post by: TWell on December 12, 2014, 01:39:38 AM
Thank's nidud.
Same as C lingo
Code: [Select]
int main(int argc, char **argv)
{
char name[] = "..";
if ((short)'.' != *(short*)&name[0])
if ((short)'.' != *(short*)&name[1])
return 1;
return 0;
}
Title: Re: Progressbar starts too late
Post by: jj2007 on December 12, 2014, 02:05:18 AM

   but not this "x." --> "x"

What exactly do you mean? Chr$(34) is illegal?

Otherwise, your code looks shorter than mine, I might steal it ;-)
Title: Re: Progressbar starts too late
Post by: nidud on December 12, 2014, 02:53:22 AM
What exactly do you mean? Chr$(34) is illegal?
I think the OS strips trailing dot’s on creation so you wont find a file named "?."
Title: Re: Progressbar starts too late
Post by: clamicun on December 12, 2014, 05:09:45 AM
What I meant was this...

I want to catch all filenames which start with '.'
and have in byte ptr+1 whatever except for the second  '.'

There are lots on my machine:  .!,  ._,  .NET,  .d, .r  and more.

That's why I asked if

byte ptr != '.' || byte ptr+1 == '!'     

is the same as

byte ptr != '.' || byte ptr+1 != '  '       ;it is not obviously

What is right to catch all filename which are like '.something ?  ! _ r N d .....
Title: Re: Progressbar starts too late
Post by: adeyblue on December 12, 2014, 05:26:11 AM
What exactly do you mean? Chr$(34) is illegal?
I think the OS strips trailing dot’s on creation so you wont find a file named "?."

They technically can be created, but you have to use NtCreateFile directly to do it. Of course since practically nothing uses that function directly you can't do anything with the file, because as you said, CreateFile and friends will get rid of the trailing dot.
Title: Re: Progressbar starts too late
Post by: dedndave on December 12, 2014, 06:25:58 AM
chr$(34) should be illegal   :biggrin:
it's often used to delimit filenames that contain spaces

anyways....
the folders "." and ".." will only show up once, unless you change the current folder
maybe that will simplify your code
Title: Re: Progressbar starts too late
Post by: dedndave on December 12, 2014, 06:29:05 AM
this program doesn't do exactly what you want, but the code may be of interest

http://masm32.com/board/index.php?topic=3468.msg36521#msg36521 (http://masm32.com/board/index.php?topic=3468.msg36521#msg36521)
Title: Re: Progressbar starts too late
Post by: jj2007 on December 12, 2014, 07:55:22 AM
That's why I asked if

byte ptr != '.' || byte ptr+1 == '!'     

is the same as

byte ptr != '.' || byte ptr+1 != '  '       ;it is not obviously

You should look at your code through the eyes of OllyDbg.
' ' is not a nullbyte, it's a space - could be a valid filename
'!' is a dangerous char because it's a MASM special character meant to handle e.g. certain situations with brackets. Depending on how macros are constructed/expanded, you may need up to FOUR exclamation marks until MASM grants you one valid one. Workaround: Chr$(31) or 1Fh.

@nidud+adeyblue: thanks for the excursion into trailing dots ;-)
Title: Re: Progressbar starts too late
Post by: clamicun on December 16, 2014, 04:58:28 AM
JJ,
! is  dangerous or not...
There are folders on my computer, which start with .!!

So I wrote it like this:
 .if byte ptr wfd.cFileName != '.'  || byte ptr wfd.cFileName+1 == 21h || byte ptr wfd.cFileName+1  > 2Eh

In case that next week there are folders like .x   or.y

I still don' understand why your prog comes to the same result without.  It has to do with MasmBasic.inc - hasn't it?
Title: SmallBasic finds different files
Post by: jj2007 on December 28, 2014, 05:34:34 AM
I got curious and installed Microsoft SmallBasic on my Win7-64 machine.

The good news: It runs just fine. The rest is mixed. The syntax is awful, but maybe I just must get used to it. Help is practically unavailable.

Then I stumbled over some awkward behaviour:
Code: [Select]
dir = "C:\Windows\System32\"
getFiles = File.GetFiles(dir)
ct=0
TextWindow.WriteLine("start")
For i = 1 To Array.GetItemCount(getFiles)
  getFile = getFiles[i]
  If 1=1 Then '(Text.EndsWith(getFile,".dll")) Then
    ct=ct+1
    File.AppendContents("TestSB.txt", getFile)
    TextWindow.WriteLine(getFile)
  EndIf
EndFor
TextWindow.WriteLine(ct+" files found")
TextWindow.Pause()

Very simple, it writes 2750 file paths to TestSB.txt
Problem is, the following yields a somewhat different set of files:

include \masm32\MasmBasic\MasmBasic.inc      ; download (http://masm32.com/board/index.php?topic=94.0)
  SetGlobals ct, fileMB$="TestMB.txt"
  Init
  GfNoRecurse=1            ; SmallBasic doesn't search in subfolders
  Open "O", #1, fileMB$
  GetFiles C:\Windows\System32\*
  For_ ecx=0 To eax-1
      mov esi, Files$(ecx)
      lea eax, [esi+Len(esi)-4]
      .if 1 ;Cvl(eax)==Mirror$(".dll")
            inc ct
            PrintLine #1, esi
      .endif
  Next
  Close
  Print Str$("%i files found", ct)      ; finds 2225 files
  Exit
end start


90% of the files coincide, but MB finds clearly less files than the SmallBasic GetFiles, and different ones. For example, SB finds an Acer.scr that MB doesn't find.
FreeCommander and the DOS prompt go with MB, while Explorer goes with SB. It is as if SB and Explorer used something different from FindFirstFile, with different results.

One more example: SmallBasic GetFiles doesn't find
C:\Windows\System32\12520437.cpx
C:\Windows\System32\12520850.cpx

MasmBasic GetFiles and the cmd prompt finds them.

EDIT: Gotcha! It's the SysWOW64 thing. Apparently FindFirstFile gets SysWOW64 when you ask for System32 on a 64-bit system. Strange though that SmallBasic gets two different results - it's a 32-bit app, too. Maybe there is some hidden Microsoft only flag that you can pass to FFF ::)
Title: Re: Progressbar starts too late
Post by: hutch-- on December 28, 2014, 10:05:04 AM
 :biggrin:

I just had a quick play with small basic and its awful but funny enough it popped a 2.5k exe that only depends on a runtime DLL.
Title: Re: Progressbar starts too late
Post by: jj2007 on December 28, 2014, 10:34:00 AM
:biggrin:

I just had a quick play with small basic and its awful but funny enough it popped a 2.5k exe that only depends on a runtime DLL.

... which has 250k and in turn depends on mscoree.dll. I feel a bit ashamed for MasmBasic's 20k overhead, but compared to that it's still tiny. However, SmallBasic's runtime is really not too big compared to many other bloated stuff. Rumours say a hello world in QT needs 10MB.

I made some tests with string manipulation, it's a factor 5-7 slower than my favourite dialect :bgrin:

Apparently, Microsoft touts this as a free tool to make kids acquainted with object orientation à la VB. I hate it, but it has many fans, and for a reason.

Just for fun, attached a proggie that saves the names of both the redirected 32-bit DLLs and the native 64-bit DLLs to file. Source:

include \masm32\MasmBasic\MasmBasic.inc      ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Dll "Kernel32"
  Declare void Wow64DisableWow64FsRedirection, 1
  Declare void Wow64RevertWow64FsRedirection, 1
  GetFiles C:\Windows\System32\*.dll
  Print Str$("%i 32-bit DLLs found\n", eax)      ; 2806
  Store "Sys32_redirected.txt", Files$()
  push 0                  ; create a DWORD zero on the stack
  Wow64DisableWow64FsRedirection(esp)
  GetFiles C:\Windows\System32\*.dll
  pop eax
  Wow64RevertWow64FsRedirection(eax)
  Store "Sys32_native64.txt", Files$()
  Inkey Str$("%i 64-bit DLLs found", Files$(?))      ; 3195
  Exit
end start