But first, a word from our sponsor, O'Reilly & Associates...  
------------------------------------------------------------------------

Dirty Little Secrets about Windows 95


by Matt Pietrek


------------------------------------------------------------------------
This is a brief excerpt from Matt Pietrek's new book, Windows 95 System 
Progamming Secrets, published by IDG Books (November 1995, ISBN 
1-56884-318-6).
While this book is published by one of our competitors, I feel it is 
extremely important. Anyone who found my book Unauthorized Windows 95
 (also published by IDG Books) useful will want to get Matt's book too.
IDG's web page for Matt's book
Matt's previous book, Windows Internals (The Implementation of the 
Windows Operating Environment), published as part of the series of DOS 
and Windows programming books I edited for Addison-Wesley.

------------------------------------------------------------------------
Copyright (c) 1995 Matt Pietrek. All rights reserved. Reprinted with 
permission of Matt Pietrek.
Before finishing this chapter, I thought I'd throw in a list of bad 
design decisions and embarrassing information that Microsoft probably 
won't be publicizing anytime soon. Many issues that I could talk about 
in this section have already been discussed elsewhere in this chapter, 
or in other books or magazines. Into this category, I put things like 
the following:
  *	Remnants of real mode DOS code are still being used. 
  *	The shared memory address spaces (below 4MB, above 2GB) are almost 
	completely unprotected. Both Win16 and Win32 applications can scribble 
	all over sensitive system data areas. 
  *	The Win16Mutex in conjunction with badly behaved 16-bit tasks can affect 
	the overall system multitasking. 
  *	KERNEL32 does in fact call KRNL386. Andrew Schulman proved this pretty 
	conclusively in Unauthorized Windows 95. (However, the magnitude of the 
	number of calls down to KRNL386 is worth noting, and is discussed in 
	Chapter 6.) 
Instead of talking about these topics again, I'd like to focus on some 
other interesting issues in Windows 95 - issues that until now have gone 
largely unnoticed. The following list gives you a brief preview of each 
topic discussed in this section:
  *	New anti-hacking code tries to prevent you from accessing undocumented 
	KERNEL32 functions. 
  *	The lack of cooperation and communication between the Windows NT and 
	Windows 95 teams results in fewer Win32 functions in both NT and Windows 
	95. 
  *	The Free System Resources calculation changed to make it look like 
	Windows 95 has dramatically more USER and GDI heap space, even though it 
	doesn't. 
  *	Additions to 16-bit code were quietly made even though Microsoft 
	publicly states that 32-bit code is the way to go. 

Anti-hacking code

In Unauthorized Windows 95, Andrew Schulman made extensive use of 
undocumented functions in KERNEL32.DLL. Although there obviously weren't 
header files for these functions, the functions appeared in the import 
library for KERNEL32.DLL. Calling these functions was as simple as 
providing a prototype and linking with KERNEL32.LIB.
In subsequent builds of Windows 95 after Andrew's book came out, these 
functions disappeared from the import library for KERNEL32.DLL. 
(Surprise! Surprise!) At the same time, these function names disappeared 
from the exported names of KERNEL32.DLL. These undocumented functions 
were still exported, however. The difference is that they were exported 
by ordinal only.
Now, normally this would have been only a small nuisance to work around. 
You should be able to simply call GetProcAddress and pass in the desired 
function ordinal as the function name (0 in the HIWORD, the ordinal in 
the LOWORD) and get back the address. In a normal, sane world, this 
would work. However, at some point during the beta, Microsoft added code 
to GetProcAddress to see if it's being called with the ordinal form of 
the function. If so, and if the HMODULE passed to GetProcAddress is that 
of KERNEL32.DLL, GetProcAddress fails the call. In the debugging version 
of KERNEL32.DLL, the code emits a trace diagnostic: "GetProcAddress: 
kernel32 by id not supported."
Now, let's think about this. Since the undocumented functions aren't 
exported by name, you can't pass the name of a KERNEL32 function to 
GetProcAddress to get its entry point. And GetProcAddress specifically 
refuses to let you pass it an ordinal value. The Microsoft coder 
responsible for this abomination really didn't want people (Andrew 
Schulman?, myself?) from calling these undocumented KERNEL32 functions. 
Apparently, the only way you can call these functions is if you have the 
magic KERNEL32 import library that Microsoft isn't supplying with the 
Win32 SDK.
Never fear. As you'll see later in the book, I make extensive use of the 
KERNEL32 undocumented functions (for good, not evil). With a little bit 
of work, I was able to coerce the Visual C++ tools to create a KERNEL32 
import library that contains these "documentation-challenged" functions. 
Appendix A contains information about these functions and an import 
library for them.
[NOTE: In addition to the extensive discussions of the undocumented 
KERNEL32 functions in Matt's book, also see my online "KERNEL32 export" 
update to Unauthorized Windows 95.]
Another instance of anti-hacking code put into Windows 95 is the 
Obsfucator flag. In early versions of Windows 95, GetCurrentProcessId 
and GetCurrentThreadId returned pointers to the relevant process and 
thread database structures. Shortly after Andrew's book came out, these 
functions started returning values that most definitely weren't 
pointers. A bit of investigative work revealed that the return value was 
the original pointer value, but XOR'ed with a seemingly random value. 
Where does this random value come from? Each time the system boots up, 
it uses the system clock to compute a random value. Interestingly, in 
the debug build of KERNEL32.DLL, this random value is named 
"Obsfucator." Seeing as how the KERNEL32 coders misspelled "obsfucator," 
it's doubtful whether the KERNEL32 sources were subjected to a spell 
check.
As with the GetProcAddress code, there's no reason for this XOR trick in 
GetCurrentThreadId and GetCurrentProcessId, other than to attempt to 
prevent people from getting at system data structures. While Microsoft 
is certainly allowed to try and hide these things, they shouldn't 
complain when people who really need this information go in and dig it 
out anyway. Chapter 3 describes a technique for calculating the 
Obsfucator value at runtime so you can access the thread and process 
database structures.
[NOTE: In addition to the extensive discussions of the "Obsfucator" in 
Matt's book, also see my online "unobfuscator" update to Unauthorized 
Windows 95.]

The Win32 API farce

While Microsoft would like you to believe that there's one big happy 
Win32 API, internally the NT and Windows 95 teams don't communicate too 
well. One result of this lack of coordination is that the number of 
Win32 functions available on both NT and Windows 95 suffered needlessly.
Exhibit 1 consists of the new Toolhelp32 functions. I've heard from many 
sources that the NT management team has vowed to never implement them. 
Yet if you look closely at the TOOLHELP32 API, you'd find there's just a 
handful of functions. Of primary interest are the process and thread 
enumeration functions. This information can be extracted from the 
Windows NT registry, as the PVIEW program from the Win32 SDK plainly 
shows. The question in my mind is: Why didn't the Windows 95 team simply 
implement the same registry keys that NT provides so that PVIEW could 
work on both? Or, why couldn't the NT team write a layer on top of the 
registry functions and put the Toolhelp32 functions on Windows NT? If 
either side really wanted to, they could come up with a portable Win32 
API way to do system information enumeration. As I'm finishing the 
writing of this book, I've heard rumblings from a member of the NT team 
that the TOOLHELP32 functions might appear in a future version of 
Windows NT.
Exhibit 2 consists of the heap functions. There are several Win32 heap 
functions that Windows 95 left unimplemented, although implementing them 
probably wouldn't have been more than an hour's worth of work. The prime 
example is the HeapWalk function from Windows NT. This function isn't 
implemented in Windows 95. Yet, if you look in TLHELP32.H, you'll find 
two functions that do exactly the same thing: Heap32First and 
Heap32Next. Rather than simply implementing an existing Win32 API, the 
Windows 95 coders went off and implemented two entirely new functions. 
The NT team will no doubt say that they're not going to support those 
functions. Lunacy!
Exhibit 3 consists of the HeapLock function. In Windows NT, this 
function simply acquires the mutex of a specified Win32 heap. As you'll 
see in Chapter 5, Windows 95 has a function that does exactly that. 
However, the KERNEL32 development team didn't export that function. 
Thus, the most likely reason the HeapLock function isn't implemented in 
Windows 95 is because somebody didn't feel like renaming the existing 
function to HeapLock and exporting it from KERNEL32.DLL.
The point is, while Microsoft is trying to convince everybody to write 
to the standard Win32 API, two teams at Microsoft are implementing only 
what they feel like. This will only hurt Microsoft in the long run. I've 
filed my share of WINBUG reports and sent numerous e-mails. It's now up 
to the market to see what happens to the supposedly unified Win32 API.

Free system resource fudging

If, after booting Windows 95, you immediately bring up the Windows 95 
Explorer and then go to the Help|About Windows 95 dialog box, you'll see 
a free system resources value that's quite high; a typical value is 95%. 
This is a much higher value than you'd see under Windows 3.1. Did 
Windows 95 suddenly gain a whole bunch of free memory in the 16-bit USER 
and GDI heaps from which the free system resources are calculated? No! 
In fact, many new items were added to USER's DGROUP segment. If 
anything, the free system resources should have gone down or stayed 
about the same in Windows 95.
So what's the story? As I describe in Chapter 4, during the Windows 95 
startup sequence, the Explorer causes the desktop window to calculate 
correct, Windows 3.1-like values for the free system resources. All 
future calls to GetFreeSystemResources are then biased by these initial 
values. Thus, when the Explorer says that there's 95% of the system 
resources available, it means 95% of the resources after the Explorer 
and other programs have started. This change in the way free system 
resources are calculated is a blatant attempt to make Windows 95 look 
better than Windows 3.1 in the eyes of the nontechnical user.

Win16 isn't dead

Although Microsoft is strongly pushing everybody to move to Win32, much 
of the underlying support for the Win32 APIs is in 16-bit code. That's 
no secret, and not worth bringing up again. However, Microsoft isn't 
making much noise about all the new API functions that were added to the 
16-bit DLLs. In many cases, these functions are 16-bit equivalents to 
documented Win32 APIs. I'm talking about useful functions like 
CreateDirectory and GetPrivateProfileSection. In some cases, these 
functions were silently added to the 16- bit WINDOWS.H without fanfare. 
In other cases, the functions are exported from the 16-bit DLL, but no 
prototype is given in the appropriate .H file. In these cases, the Win32 
documentation and some common sense can usually get you through.
If Microsoft isn't publicizing these 16-bit additions, just who's 
supposed to be using them? If everyone should be writing Win32 code, why 
is Microsoft adding new Win16 APIs? It certainly looks like Microsoft 
knows that Win16 will continue to have a fairly long life even after 
Windows 95 ships. Yet they're telling developers that Win16 is a dead 
end, and that Win32 is the only way to go. Personally, I agree that 
people should focus on Win32 programming if possible. But trying to 
force people toward Win32 programming in this manner seems like a bad 
way to go.

------------------------------------------------------------------------
For more information, visit these other O'Reilly online areas: 
Our homepage, with product information, feature articles, and more. 
WebSite Central, home of O'Reilly's hot, new, Windows Web server. 
The O'Reilly Windows Center has Win 95 programming information, 
articles, and links.  FTP site, with newer versions. 