In a previous post, I teased that I would explain exactly what is happening in what I believe was the most copied function of the AOL Proggie era. Adding the list of people in a chatroom to a list in your program. This is that post. Fire up your BASIC editor and open up your Win32 API manual and follow along.
Let us start with the include from the Win32 API. Visual Basic (VB) is somewhat of an interpreted language, but it has the ability to include function calls to Dynamically Linked Libraries (DLLs) written in C or another system language.
VB “compiles” to P-CODE and then is interpreted by the runtime or virtual machine of sorts. Similar to Java’s JVM and its bytecode. In VB5 there was a native compiler for x86 machine code, but before VB5, and maybe after, you could “decompile” the P-CODE and get actual source of any program. People got upset at this and there was an entire obfuscation scene dedicated to preventing decompiling of VB programs…
Interacting with AOL by reading dialogs, clicking buttons and other automations was fairly straight forward. The general flow would be: identify the window, studying its hierarchy, find the control, and send it messages.
To do this, even today in 2021, I like to use Patorjk’s Tool for Window Spying, but you could always use spy++.exe included in the tools from Microsoft. Automation of this style is similar to scraping websites now. You are reverse engineering and poking into stuff you normally shouldn’t. With most scriptable apps you have an official API. For progs, you needed to invent your own API or SDK… by essentially inspecting the window “DOM”..
Most controls could be read and written too. But there was one control that alluded us. The list of people in the chat room was some type of special control. There was some formatting that would happen and other things that prevented a standard
LB_GETTEXT from working.
In the earlier Sk8er.bas there was a call to a “311.dll” which took care of the AOL16 bit. But when 3.0 came out, which was 32bit we had to reinvent the wheel. Not sure who wrote the 311.dll, maybe we could decompile it. It probably was reverse engineered… But I know it held something that is similar to the code in question. Food for thought: Why was it in a .dll?
Ok onto the 32 bit version of this code. There are 2 main variants, but they all do the same thing. Tap into the process, read some memory and do some magic.
This dos32.bas was claimed to be completely written from scratch, it was… except for the above bit. Still searching for the original author. There is actually another variant that I saw in alpha32.bas, it is shorter and simpler, but I will focus on the tear down of dos’s copy pasta.
- Turn off error handling with On Error Resume Next (think of it as a blind try/catch on all exceptions and keep on trucking… not great, but hey)
- Find Chat Room Window, Get Thread and follow to Process ID (seems roundabout way, was there multiple threads in Aol32.exe?)
- You can see there are old-school postfix variable identifiers, I think this kept code smaller w/ Option Explicit.
- VB4 straddled both 16bit and 32bit so I am guessing that is why the integers are defined as “long” here at 32 bit. Long to me is 64bit, but 1995…
- Biggest mistake I think in this entire snippet, Iterating over a list of items while the list can change.
- It cannot be atomic I guess, we cannot lock it, but it seems very strange to call LB_GETCOUNT every loop iteration.
- Send message and get the LB_GETITEMDATA, then pad by 24… No idea perhaps that was formatting data? This listbox had embolden and italic modes for enter/leaving.
- ReadMemory from ScreenName string which is only 4 characters, must be an address/pointer
- psnHold now holds the value stored at the address stored in ScreenName
- psnHold now holds an address. Pad Address by 6… again no idea why.
- Resize ScreenName to 16 characters (largest screen name possible on AOL)
- Read Memory into ScreenName
- Last Step: Trim to null character, remember we use c-strings in VB!
Wow, we got through it. Still a lot of unanswered questions, but I think we solved most of the important bits. When I originally read this code in the 90s, it blew my mind. I just chalked it up to magic and copy and pasta’d it. It always stuck in the back of my mind though, and after I learned about memory and pointers in college it seemed to make more sense.
I promised myself I would eventually write this post to shed some light on one of the most important years of my life. What lessons are learned while you are having fun and sharing your code with friends. Thank you for reading and remember… If you don’t understand it, you don’t always need to! Copy Pasta!