124 19 92MB
English Pages 608 [649] Year 1994
WINDOWS 5 Developer’s Guideto Exploring
: theFoundationsBsCee
SS. .
ye U
J
ae
are
LN
oe
Andrew SCHULMAN
UNAUTHORIZED WINDOWS do “Andrew Schulman does not follow the Microsoft party line. Instead, he shows you how Windows 95 really works. You'll build better applications by understanding what's inside the Windows black box.” — Richard Smith, President, Phar Lap Software
Windows 95 will affect you. This exclusive view reveals the new Windows operating systemas only Andrew Schulmancai An entire industryis poised, trying to gauge the impact of Microsoft Windows95.
Unauthorized Windows95 is the first critical andrealistic look at what “Chicago” means for the computersoftware industryandfor
Windows programmers. You'll understand this newproductand howitaffects the way you
Andrew Schulman’s clarity of vision andhis much-praised investigative methods have earned himthe respect ~_of the Windows development community. He has written for Newsweek, PC Week,
Microsoft Systems Journal, and
pwfitesthe “Undocumented Corner” columnfor Dr. Dobb's Journal.
Your Exclusive TourInside Windows 95
Answers These Tough Questions:
+ Has Windows 95 beenwritten from the ground up?
develop software,
* Does Windows 95 push DOS aside?
A special Industry Update takes the tempera-
Is Windows 95a completely integratedoperating system?
ture of this newproduct and prepares you for
Is the 32-bit kernel completely independentof the
the effects of Windows 95. Get the scoop on what's in Windows95 andhowit will affect the PC industry.
16-bit kernel? « is DOS dead? + Is Windows 95 just WINS2s?
| +s Windows 95 radically different from Windows 3.117
+ Why do VxDs make Windows a genuine operating system? * Why is V6 Mode a form of protected mode?
COMPUTER BOOKSHELVING CATEGORY: Windows! Programming $29.99 USA
$39.99 Canada
£28.99 UK
ai
ih
The “Programmers Pres logo sa tademak and the “IDG Books” logois meister readme of Iteration Data Gro ISBN 1-56884-169-8
—
52999
BOOKS
IDG Books Worldwide An International Data Group Company San Mateo, CA 94402
9 1781568'841694'
“The release of Undocu mented Windows is one of the most important ev
ents of 1992.” — pp . Dobb’s Journal
UNAUTHORIZED WINDOWS 95°
UNAUTHORIZED WINDOWS 99 A Developer’s Guide to Exploring the Foundations of Windows™ “Chicago”
Mndreu SCHULMAN AnInternational Data Group Company Foster City, CA * Chicago, IL * Indianapolis, IN * Braintree, MA © Dallas, TX
Unauthorized Windows 95
Published by IDG Books Worldwide, Inc. An International Data Group Company 155 Bovet Road, Suite 310 San Mateo, CA 94402 Copyright
Copyright © 1994 by Andrew Schulman.Alll rights reserved. Nopart ofthis book (including interior design, coverdesign, andillustrations) maybe reproducedor transmitted in any form, by any means(electronic, photocopying, recording, or otherwise), withouttheprior written permission ofthepublisher.
Library of Congress Catalog Card No.: 94-72740 ISBN 1-56884-169-8
Printedin the United States of America First Printing, October, 1994 10987654321 Distributed in the United States by IDG Books Worldwide, Inc.
Limitof Liability/Disclaimer of Warranty ‘Theauthor and publisherof this book have used theirbest efforts in preparing this book. IDG Books Worldwide, Inc., International Data Group, Inc., and the author makeno representation or warranties with respect tothe accuracy or completeness of the contentsofthis book, andspecificallydisclaimanyimplied warranties of merchantabilityorfitness for any particular purpose, andshall in noeventbeliable for anyloss of profit or any other commercial damage,including but notlimitedto special, incidental, consequential or other damages.
Trademarks All brand names andproduct namesusedin this book are trademarks, registered trademarks, or trade namesoftheir respective holders. IDG Books Worldwideis not associated with anyproduct or vendormentionedin this book.
Publishedin the UnitedStates of America
Credits Vice President and Publisher Christopher J. Williams
Publishing Director ‘Trudy Neuhaus
Brand Manager Amorette Pedersen
Project Editor Susan Pink Manuscript Editor ‘Teresa Frazier Technical Editor
JamesFinnegan
Editorial Assistants
Berta Hyken Kate Tolini Production
Beth A. Roberts Ronnie K. Bucci
Proofreader Seth Maislin
Indexer Elizabeth Cunningham Book Design Scally Design Cover Design Kavish + Kavish
For More information For general information on IDG Books in the U.S., including information on discounts and premiums, contact IDG Books at 800-434-3422 or 415-312-0650.
For information on where to purchase IDG’s books outside the U.S., contact Christina Turner at 415-312-0633. For information ontranslations, contact MareJeffrey Mikulich,
Director, Rights and Licensing, at IDG Books Worldwide; fax number: 415-286-2747.
Forsales inquires andspecial prices for bulk quantities, contact Tony Real at 800-434-3422 or 415-312-0644.
Forinformation on usirig IDG books in the classroom andordering examination copies, contact Jim Kelley at 1-800-434-2086.
Unauthorized Windows 95: A Developer's Resource Kit is distributed in the United States by IDG Books Worldwide, Inc.It is distributed in Canada
by Macmillan of Canada, a Division of Canada Publishing Corporation; by Computer and Technical Books in Miami, Florida, for South America and the Caribbean; by Longman Singaporein Singapore, Malaysia, Thailand, and Korea; by Toppan Co.Ltd.in Japan; by Asia Computerworld in HongKong; by WoodslanePty. Ltd.in Australia and New Zealand; and by ‘Transword Publishers Ltd. in the U.K. and Europe.
Contents Preface.. Industry Update: The Impact of Windows 95.. Chapter One
Wetcome to Winnows 95... Bypassing COMMAND.COM. ...But Bypassing DOS,Too! WhyBother Refuting Microsoft's Claims? ‘Those Ubiquitous Microsoft Diagrams... ClaimingIntegration Windows 95 and DOS Sidebar: Just onelittle callback Who’s Afraid of MS-DO! WEW3.11: The Neglected Operating System. Chapter Two
Warcuine Cutcnco Boor. From WINBOOT:SYSto WIN.COM Sidebar: A complete rewrite? Fromthe Registryto XMS Sidebar: Pushing aside real-mode drivers? From IFSHLP.SYSto WIN.COM. From WIN.COMto KRNL386.EXE Inside the Virtual Machine Manage! VaDs: TSRs ofthe 19905wera From KRNL386.EXE to CAB32.EXE Exploring the Explorer...
49 52 55 57
60 62 66
78 84
91
Chapter Three
Tue Winoows-DOS Connection Windows INT 2Fh Broadcas Instance Data
Embedded VxDs
oF 101 103
FAKEWINCaveat Inside FAKEWIN. FAKEWIN.C
105 107
107
Chapter Four
A MonRINGE WADE IN REDMONDneeennnnee 115 TSRLDR.ASM. DOSInstance Data and the SDA Sidebar: What was WINA20.386? DOS’s IN_WINE Flag
117 119
122 123 124
127 Global EMMImport. The DOSMGRBroadcast AP!
128 129
130 132
FAKETSR.C....
132
Chapter Five
Tne Two Faces oF Winoows TheInnerCore of Windows... DOSExtenders and the Future of DO! DOSX: A General-Purpose DOSExtender and DPMI USEDPM| RUNDOSX RUND} Usingthe DPI USEDPMI2 MEMLOODP.... MEMLOOP.
139 139 140
146 146 152
154 156
156 157 157
Chapter Six
Prorecten-Mone DOS: WINS8E ano MSDPMI.... 16 GOWIN386.INI... GOWIN386.BAT........ Sidebar: What mode is KR)
162 163 167
DPMIINFO.. DPMIINFO.C Sidebar: WIN386 really, really is a memory manager MSDPMI..
167 168 170
173
Chapter Seven
Wuene Do 32BFA ano LFN Come From? Onward to Windows 95: VMM32 RUNVMMB2.BAT. LongFilenameSupport in Windows 9 Sidebar: The eleven kinds ofWindows disk/file drivers LFN.C ‘The DblSpace VxD Saga FourSteps Toward DOS Nirvana
vi 182 188 193 197 201
204 207
Chapter Eight
Tue CASE OF THE GnapuawyDisappearing DOS. Bypassing DOS... TEST21.C... Sidebar: 32BFA versus disk cache performance Getting and Setting the Current Drive TEST_I... CURRDRIV.ASM Windows95: Still Bypassing DOS,but Supporting TSRs INTVECT: Another Sample VxD INT 21h Hooker INTVECT.ASM GlobalandLocal INT 21h Hookers ‘The Role of IFSHLP.SYSand V86 Callbacks VXD86API.C WINBP.C. 32BFA and Networks, CD-ROM,and Floppi Replacing Real-ModeCode: It’s Not New. TEST1600.C... Another Old Example: TEST 1600. TEST2F16.C
Interrupts 101: IDT versus the IVT...
210 211 221 223
224 230 234
238 239 242
244 252 259 274 277
278 281 282 284
Chapter Nine
Wao's in Cuorce: Winnows on bos!
293
“A Thing ona Thing”? ..........-. Running DOSin Protected Mode.
293 296
‘The Virtual Machine Monitor (VM. M)
298
V86 Modeand thePE Bit BEEGaesneecamyeiiad
302 305
Chapter Ten
How Winoows Runs 0s
307
V86TEST V86TES
307 “
309
Sidetsar: Switchingfim’ VB6 mde a Peal riod IOPLand theInterrupt Flag....... bees CLITEST.C (Windows version) CLITEST2.C (DPMIversion) .
317 319 325 326
GEISFGessnsnyxenncesew
Rutioing DOSin « Virtual Machine’. Simulating versus Reflecting Interrupts ......... Options for Controlling DOS ..... ee
328
we. on Wen
331 33 3 36
Chapter Eleven
Who Nees 00S? What Does V86TESTActually Show? Windows at Work?....... 5
339 z arate
Sidebar: VxDcallouts
The Top Windows INT 21hCalls Bouncing Back into Windows.. . The Effect of 32-Bit File Access . ms What about BIOS Galls? s.iscccisuacuwesenaes
Chapter Twelve
Enproning with WUB6TEST.. Breaking All Ties with DOS?
as i
340 342 347
352 356 359 363
WinWord and DOS............. ‘The Windows95 Explorer and DOS PSPs and Other DOS Data in Windows95 .
380
Win32 FindNextFile Is INT 21h Function 714Fh.
396
MYDIR.C... The WV86TEST Code. Windows 95 and Protected-Mode DOS
404 409 415
383 385
Chapter Thirteen
Tauna! Kennei32 Gaus HRNLS8E... Launching a Win16 App fromthe Explorer......... 0000s 005 CAB32: KERNEL32 Uses the Winl6 KERNEL. DYNLINK32.C Sidebar: Win32 and the PSP... Whos Calling INT21h? Where’s the Windows 95 Current Directory CHGDIR.C. WALKWIN.C.
FromExplorer to Create PSP in Six EasySteps. The WSPY21 Code... WSPYOLC. oc ocsies Sidebar: The DOSextend Still a great pretender’ DOSMEM.C . ‘ KERNEL’s INT 21h Handler and KernelDosProc Chapter Fourteen
Choc: Mining 32-Bir ano 16-Bit Cove...
497
16/16: The Win16 Clock under WEW3.11 ........ 0000 e eee 32/16: The Windows95 Clock under Win32s.........-.0.6005 Sidebar: Thunking: Mixing 16- and 32-bit
497
code with CALL FWORDPTR.
FWORD.C..... INTSERV.C ... a 32/32: The Windows 95 Clock eee Does Windows 95 Really Call Down to DOS? And What Does It Do When It Gets There?
nia
ee
ree at eee ats,
Sidebar: The magic of Call_Priority VM_Event ..........
510 -
Unauthorized Windows 95
Win32 File Handles and Thunking. ..........060ee00eeee ees Reading the PSP from Win32.......00ec00eeceeeeeeveren ees TH32.C ..
530
WI SPSD
Using Win32 File Handles Jee
EST.ASM...
Ht AN
Leith eal
LAO eee
Really Bypassing DOS: Executable Loading and Memory-MappedFiles ........6. 0000005 MAPF WISLOCEG,
Kae
Ae), ene
533
y
538
Ae oe
543
0 0e-0e e ve e e e enete s
W32HAND.C FI
529 530
eat
pais
536
545 545
siosaeececesnwacan
Onkeaecesesbee
553 549
PREFACE No oneis surprised more often by the dynamic behavior of a program than its author.
— Russ Blake, Optimizing Windows NT
Microsoft Corp.is the author of not only Windows 95(“Chicago”) but also virtuallyall materials regarding this operating system. Microsoft has
released a 300-page “Chicago” Reviewer’s Guide, almost monthly articles in
Microsoft SystemsJournal, and severalarticles in Microsoft Developer Network News. Microsoft Press, which recently started describingitself inits ads as “The Knowledge Division of Microsoft,” has published a 475-page book, Inside Windows 95, by a former director of systemssoftware products at Microsoft, Adrian King.
Almostall other descriptions of Windows 95 in the computer trade press have been based heavily on such Microsoft-provided resources. Moreover, we — like all non-Microsoft book publishers — are required by Microsoft’s publisherrelations programto includethe following notice:
This bookis based oninformation on Windows 95 madepublic by Microsoft as of 10/19/94.Sincethis information was madepublic before the release of the product, we encourage you to visit your local bookstore at thattime for updated books on Windows 95. If you have a modem or accesstothe Internet, you can always get up-to-
the-minuteinformation on Windows 95 direct from Microsoft on WinNews: ‘On CompuServe: Onthe Internet:
GO WINNEWS ftp://ttp microsoft.com/PerOpSys/Win_News/Chicago http://www.microsoft.com
Unauthorized Windows 95
On AOL: OnProdigy: On Genie:
keyword WINNEWS jumpword WINNEWS WINNEWSfile area on Windows RTC
You can also subscribe to Microsoft's WinNewselectronic newsletter by sending Internet email to [email protected] and put the words
SUBSCRIBE WINNEWSin the text of the email.
Interestingly, the publisher’s note (September16, 1994) to Microsoft Press’s own Inside Windows 95 starts off with a somewhat different
disclaimer:
As we went to press, someaspects of Windows 95 werestill under a general nondisclosure agreement, but Microsoft had made public a great dealof information about Windows 95. This book offers an interpretation ofthatinformation, and the author's conclusions are basedon his exploration of Beta-1. [italics added] Similarly, Unauthorized Windows 95also offers an interpretation of the information Microsoft provides on Windows 95, and the conclusions are
similarly based on myexploration of Chicago’s Beta-1 (May 1994). In addition, I examined the commercially-released Windows for Work-
groups (WEW) 3.11, whose 32-bitfile access is said by Microsoft’s advertisements to be “poweredby 32-bit technology from our ‘Chicago’
project,” and I examined Microsoft’s 32-bit add-in to Windows 3.1, Win32s, which bears a far closer resemblance to Windows95 thanrepresentatives for Microsoft claim (and apparentlybelieve). Microsoft representativesalso claim, and no doubtsincerely believe, that Windows95 is “integrated,” is not based on MS-DOS,has been rewritten from the ground up,and hasa 32-bit kernel. Microsoft seeks by these statements to position Windows 95 head-to-head against the Apple Macintosh (whoseeaseofuse is widely perceived to stem fromits “inte-
gration”) andto a farlesser extentagainst IBM’s OS/2operating
system,
the avid supporters of which make much adoaboutthe fact that OS/2is a complete, “from the ground up”operating system, nota “thing on a
thing”like Windows. But,just as an authoris often surprised bythe behaviorofhis or her own program,likewise a companyis often misinformed — and hence a source of misinformation — asto the natureofits own products. Thisis why educated car buyers generally pay moreattention to ConsumerReports
than to the manufacturer’s advertising orthe salesman’s pitch. Similarly, you would no more wantto learn aboutan operating systemstraight from
the horse’s mouth than you would expectto learn abouta book by asking
Preface its author. An authoris generally the /ast person you would ask for an objective perspective on his or her work. Notsurprisingly then, many of Microsoft’s statements on Windows 95 havebeenill-informed. This book shows that Windows95 is no more integrated thanits predecessors, and doesnotrepresent a “complete rewrite” of Windows. However, although this book pokesseverallarge holes in Microsoft’s claims for Windows 95, I do not join the IBM OS/2contingentnorthe
equally small contingent marching behind Microsoft’s high-end Windows NT. The OS/2 and NT enthusiasts (who sound remarkably alike) pounce on anyproofofarchitectural compromises in Windows 95 — such as the continuinguse of 16-bit codein the kernel, or the continuing reliance on
MS-DOS — asproofthat Windows95 isn’t a genuine operatingsystem. But Windows95islikely to be a shockingly successful operating system
precisely because of such compromises.
This book will show you that Windows95 continuesto rely on DOS, that its Win32 kernel continuesto rely on the Win16 kernel, and that —
surprise! — this is okay. Mygoal is notto prove that Windows95 contin-
ues to use DOSand thereforeisn’t a genuine operating system.Instead, my goalis to show that even though Windows 95 does use DOS, Windows95 (like Windows3.x Enhanced mode beforeit) is not some “thing
ona thing,” but employsa reasonable,legitimate operating system architecture, the foundation ofwhichis Intel’s Virtual-8086 (V86) mode.
Oneof my hopesis that this book will help overcome some common prejudices as to what constitutes a proper operating system architecture. Windows and DOSareby far the mostsuccessful operating systemsin the history of computing. That they don’t conformto certain principles of operating system design mighttell us that there is something wrong with these principles. Most general-purpose computerson theplanetare running DOSand possibly Windows. Thus,like it or not, Windows and DOStogether define what operating systemsactually look like in the world today. Mygoalin puncturing someof Microsoft's claims about Windows 95 is nottofind fault with Windows 95. By understanding that Windows95
is not a complete rewrite,is still partially based on DOS,has 16-bit code
in its kernel, andsoon,youwill better understand how Windows 95 actually works. In particular,I hope this bookwill help yousee that the coolest new features of Windows95 havetheir roots in Windows3.0 Enhanced mode, first madeavailable to paying customers onthefateful day of May 22,
Unauthorized Windows 95
1990 (The Daythe Software Industry Changed). Windows95 should have beenpredictable from a careful reading of the Windows3.0 Device Driver Kit’s description of VMM services such as Hook_V86_Int_Chain, Set_ PM_Int_Vector, Allocate_V86_Call_Back,Install_V86_Break_Point, and
Call_Priority_VM_Event.
This VMM layer, whichis a genuineoperating system, and plug-in add-onsto this operating system, called VxDs, have been aroundforfive
years, yet only nowisit likely thatthe typical Windows programmerwill encounter them. Unfortunately, I suspect that few Windowsdevelopers
could tell you much about the componentsof the Windowsoperating
system such as VMM, IFSMgr, VPICD, DOSMGR, VWIN32, or IOS.
Likewise, Windows programmingbooks likewise say hardly anything aboutthis layer of Windows. KERNEL32
KERNEL
COMMDLG DDE
GDI32 USER GDI
|~— Undocumented Windows) discuss
OLE
_USER32__
Most books on Windows(even
etc.
VMM DOSMGR VWIN32 IFSMgr V86MMGR _—VPICD VFAT VXDLDR 10S etc.
this layer of Windows.
Unauthorized Windows 95 discusses
this layer.
Although Windowsis frequently referred to as an environmentrather than an operating system, a little-known part of Windowsreally and truly is a full-blown operating system. This book covers this operating system componentof Windows.
Although Unauthorized Windows 95 is largely a book about VMMand
VxDsin Windows95,it is not a bookfor device driver writers. Even thoughI hope someonewriting a devicedriver will find a lotof valuable information here, my assumptionthroughoutis that the reader has no
intention ofwriting device drivers. And althoughI discuss some important undocumentedfunctions — most notably undocumented Win32 APIs pro-
vided by KERNEL32.DLL,such as VxDCall and GetpWin16Lock — my intentionis simply to give you a taste of how Windows95 actually works.
AnotherthingI’ve tried to doin this bookis to “integrate”(as Microsoft would putit) minute technicaldetails of Windows 95 with an overview of Microsoft’s role in the PCsoftware industry andthelikely impact of Windows95ontheindustry.I’ve never beeninterested in details for their own sake. Examining the Windowscode, in some cases
Preface
downto theinstruction level, is important only because this code is running ontensof millions of machines every day. I don’t think it would be worth subjectinga less ubiquitous operating system, such as OS/2 or NT, to the samescrutiny.
Well, so much for what you can expect from Unauthorized Windows 95. Now for myfavorite part of the book, whereI getto give thanks forall
the helpI received. First, there’s myeditor, Trudy Neuhaus. Forfive years, Trudyedited
theback of PC Magazine, where authors such as Douglas Boling, Ray
Duncan, Charles Petzold, andJeff Prosise regularly appeared. Wellknownasthefinest editor in the computer-writing business, Trudyjoined IDG Booksas Senior Editor of its new ProgrammersPressdivision, and
is nowPublishing Director of ProgrammersPress Professional. I was incrediblyfortunate to have Trudyas the editorfor this book.
Richard Smith, president of Phar Lap Software, not only was tremendouslyuseful to talk with both about technical and businessissues, but also was very supportive.
JimFinnegan, a contributingeditor to Microsoft Systems Journal(check
outhis absolutelybrilliantarticles, cited in the “For Further Reading” section at the endofthis book) wasthe technical editor for this book. Jim’s eagle eye and readywit saved me from makinga fool of myselfin numerousplaces.
Geoff Chappell is largely responsible for my understandingofthe
inner workings of VMMand32-bitfile access. Paul Bonneau, Ron Burk, ‘TimFarley, Bill Lewis, David Markun, Klaus Mueller, ThomasOlsen, Walter Oney, Matt Pietrek, Brett Salter, Murray Sargent, Alex Shmidt,
MikeSpilo, and Kelly Zytaruk all helped me through phone conversations andover email. Geoff, Klaus, Tom, Alex, and Kelly provided me with huge amounts of material on VMM and VxDs, most of which unfortunately did not make it into Unauthorized Windows 95. Doug Boling wrote a wonderful
second-generation version of the WINIO library, which also did not end up in this book. I promise, guys,thatall this stuff w#// get into print! Nu-Mega Software makes the incredible Soft-ICE/Windows debug-
ger, which madethis bookpossible.
My friend Chris Williams, Vice President and Publisher of IDG Pro-
grammersPress, came upwith the title Unauthorized Windows 95, and often seemsto have understood the point ofthis book betterthan I did.
Amy Pedersenwasaggressively marketing this book long before I had writtenit. Thanks, Amy!
Unauthorized Windows 95
‘Teresa Frazier and Susan Pink transformed my chaotic manuscript into a readable, understandable book.I was very fortunate to have them on the Unauthorized Windows 95 team. Desktop publishing wizards Ronnie Bucci and Beth Roberts produced the entire book, includingthe screen shots and diagrams, and made cor-
rectionsto correctionsof corrections with good humorand accuracy. Seth Maislin proofread the book, and Liz Cunningham compiled the index, both in record time. Thanks for your sharp eyes! Kate Tolini madereservations, tracked down books, arranged couriers, anddidall sorts of otheressential things. By providing an emergency
supplyof samosasand pakoras, Berta Hyken kept me from complete
spicy-food withdrawal. Jon Erickson, mylong-timeeditor, let me wriggle out of two months worth of my “Undocumented Corner” column in Dr: Dobb’s Journal, and
at the sametime taught me Erickson’s Second Lawof the Conservation ofProse, thereby extending mylife by the twoarticles I now owe him. LarrySeltzer, Wendy Goldman Rohm,Stephen Manes, Paul Andrews, and John Markoff sometimescalled me up for some backgroundtoarticles they were writing — andI alwaysgot far more out of the conversation than theydid.
Gene LandyofShapiro,Israel, and Weiner(and author ofthe superb
Software Developer's and Marketer's Legal Companion), Richard De Bodo of Trell and Manella, DanSilver at the U.S. Federal Trade Commission, and
Stuart Taylor of The American Lawyerall helped metry to understand US. antitrust and trade-practices law. RayValdés,in addition to having taught me C programmingin the mid-1980s, is a greatfriend, andhis totally brilliant pieces in Dr: Dobb’s
Developer's Update are an inspiration.
Claudette Mooreof the MooreLiterary Agency put metogether with
IDGBooks. Back whenI was a lowly engineerat Lotus, Claudette got
mestarted writing computer books. Myson, MatthewJacob Schulman,hadto put up with myabsence for almost two monthswhile finished this book. Matthew,I’msorry, and I promise I will never again be awayfor that long.
Mywife, Amanda Susan Claiborne, during what wasalreadya difficult
time, had to be a single momfor two months. Thanksfor that, for eleventh-hourrevising ofthis preface, and for reminding methat there are more important thingsinlife than VxDs. Occidental, CA October23, 1994
INDUSTRY UPDATE
THE IMPACT OF Winnows 99 “If someonethinks we're not after Lotus and after WordPerfect and after Borland,they're confused. My job is to get a fair shareof the softwareapplications market, and to methat's 100 percent.” — Mike Maples, senior vice presidentfor applications, Microsoft (quotedin Jane Morrissey, “Microsoft applications unit seeks market dominance,” PC Week, November18, 1991).
In typical Microsoft fashion — like a very late gangbuster — Windows 95is coming. When Microsoft chairman Bill Gates announced that the next version of Windows, codenamed “Chicago,” would be aboutfive monthslate, coming out probably in April, 1995, instead of December, 1994, Microsoft's stock immediately shot up almostthreepoints. Bill Gates announces the product will be late and the stock goes up? Yes, because Gatesalso declared that Chicago will be “more of a phenomenonthan any newpieceof systemssoftware weor anyoneelse has ever done” (New York Times, July 23, 1994). That's all Wall Street needed to hear. Microsoft's Windows 3.0 announcement in May 1990 — sometimescalled “the motherof all rollouts” — changedthe face ofthe PC softwareindustry. Microsoft spent about $2 million on the Windows 3.0 rollout; apparently it is planning a $40 million campaign for Windows 95. This is nothing comparedto the potentialbillion dollars in revenues that Microsoft expects to make over a two-year period from Windows upgrades alone(Paul Andrews, “The Winds of Chicago,” Marketing Computers, May 1994). Windows 95will have a tremendous impact on the PC software industry, and almostcertainly will be more of a phenomenonthanany previouspiece of systems. software. Yet the product's significance, andits likely impact on theindustry, are somewhat different from what Microsoft portrays. Microsoft says thatits Windows 95 product is a brand-new operating system that completely replaces MS-DOSand has been rewritten “from the ground up.” Butthe fact is Windows
nN UNAUTHORIZED WINDOWS 95
applications running under Windows 95will still end up using MS-DOS. Windows 95is based on the samearchitecture as Windows 3.x Enhanced mode, which has beenavailable since 1990 (we mightas well call it Windows 90). From a technical perspective, Windows 95 is nota revolutionary product.It’s just Windows 90+5. Although thearchitecture of Windows 95isn’t brand new,the product will have a majorimpact on the PC software industry, similar to the impact Windows3.0 had five years ago.Unlike Windows 3.0, though, Windows 95 doesn’t needto be revolutionary product. The industry's experiencewith both OS/2 and WindowsNTis that, when offered an entirely new operating system, the overwhelming majority of PC users opt insteadfor the old devil they know: the combination of MS-DOS and Windows. The Windows 90 Enhanced modearchitecture was a far more radical departure from the old realmode DOSoperating system than mostof usrealized at the time. It is okay for Windows95to keepit. Microsoft also says that Windows95is “integrated.” This isn't accurate either. Windows 95 isn't integrated; instead, it “just grew.” Windows 95 does have many more features and capabilities thanits predecessors, performing manytasks thatuntil nowrequired applications andutilities produced by vendorsotherthan Microsoft. But there isn't much genuine integration at a technicallevel. It could very well turn out that the only integration we'll see with Windows 95will be Microsoft's verticalintegration, that is, the company’s further expansion throughout the software industry. In fact, this is occurring right now. Theinclusion of more applications/utilities in Windows 95,the increasingties between Microsoft Windows and Microsoft Office, the merger and acquisition fever that has taken hold ofthe PC software business, the limited U.S. Department ofJustice (DOJ)antitrust settlementwith Microsoft — these are all signs of a maturing industry; of the restructuring of an industry from onethat once had hundreds, if not thousands,of firms ofall sizes, to one with a ‘small numberof large firms. The PC software industry is going through a shakeout and consolidation, similar to what happenedin previous technology-basedindustries. For example,in theearly 1920s, there were 75 automobile manufacturersin the U.S.alone. Today, there are a handful, Nothing makes the software industry immunefrom similar consolidation. There is another aspectto this maturation of the PC software industry — the movementfrom a technology-based industry into a consumerproduct-based industry — and the very name Windows 95 suggests this productwill play a leading role. If a Windows program queries the GetVersion function in Windows95, it will get back 4.0 as the answer; a DOS program will get back the answer7.0. Indeed, Windows 95is Windows 4.0 plus MS-DOS7.0. But in its marketing, Microsoft has decidedto trade in the nerdy major.minorversion-numbering scheme(version x.0 has always given the companytrouble, anyway) for a new product-naming scheme basedonthat used by automobile manufacturers and vineyards. Windows95isn't
The Ever-Expanding Operating System Microsoft not only makes the Windows and MS-DOSoperating systems upon which mostof the world's commercial software runs,it also makes applications such as Microsoft Word, Excel, PowerPoint, Access, and Mail, which comprise the Microsoft Office suite. These competedirectly with non-Microsoft applications such as 1-2-3, WordPerfect, Quattro Pro, and dBASE. The makersofthese applications — companies such as Lotus, Novell, and Borland — worry whether Microsoft's ownership of the operating system (OS) gives its applications an advantage, and if so, whether that advantage is unfair. However, this is just one part ofthe problem. Even the Microsoft Windows and MS-DOSoperating systems themselves compete with the third-party applications and utilities that require them. At least since the incorporation of several major third-partyutilities into MS-DOS 5.0 in June 1991, Microsoft has beenputting features that once were theturf of vendors other than Microsoft into its operating systems. Windows 95is the clearest expressionofthis trend. In other words, Microsoft competes with its own customers. The Independent Software Vendors (ISVs) that make Windowsapplications andutilities are essentially customersof Microsoft. They depend on Microsoft for the tools andinformation necessary to write Windowssoftware.
we 3ivddn AwLSNaNi
foremosta technology or an operating system; it's a product. It is targeted not at developers or end-users but at consumers. What does Microsoft Windows 95 meanto you asa participant in the PC softwarebusiness? If you are a software developeror entrepreneur,the brief answeris that Windows 95 should make you nervous(unless you work for Microsoft, or have investedin Microsoft stock, or both). At the very least, Windows 95will change how you sell software and what sort of software you develop. Windows users(| mean, consumers) should welcome Windows 95 as a big improvementoverprevious versions. But this is shortterm; users too ought to worry about the long-term effect of Microsoft's growing dominance over the soft. ware industry. Windows 95is a big step towards Microsoft's stated goal of supply: ing 100 percent of your software needs. Evenif, as the DepartmentofJustice (DOJ) apparently found, Microsoft is not in serious violation of the antitrust laws of the U.S., and even if the company's goal of owning 100 percentof the industry is merely what every other company in a similar position would want, nonetheless software developers and entrepreneurs ought to fully realize the special role that Microsoft plays in the software industry: Microsoft is not only the supplier of your operating system.It is also your competition.
5
UNAUTHORIZED WINDOWS 95
Microsoft intends to greatly expand Windows at the expenseof the ISVsit is
supposedtobe assisting. Here arejust a few ofthe features Microsoft is including in Windows 95: * Networking * InfoCenteruniversalin-box (electronic mail, fax) * Explorer (a vastly improvedshell) * WordPad (a full-featured word processor) * Microsoft Paint (a full-featured paint program) * Hyperterminal(a full-featured telecommunications package) The operating system is growing and the application domain is shrinking. Future operating systemswill incorporate even more functionality that today we associate with applications such as word processors and databases. Now, Bill Gates will neverpresent his vision using the late Nikita Khrushchev's approach of banging his shoe on the podium and announcing to assembled ISVs, “Wewill bury you!”Instead, Gates will say, “look at all the work we are doingfor you.”In Microsoft's eyes,the expansion ofthe operating system doesnot entail the contraction of the application domain. Instead, by taking on more and more work, Microsoft's operating systemswill let developers beinnovative. However, an impartial observer might instead interpret Microsoft's approach not so muchas“lookatall the work we are doing for you,” but instead as “look at all the avenues weare closingfor you.” Therelationship betweenapplications andthe operating system need not be a zero-sum game, in which functionality taken on by one is necessarily lost to the other. And there's nothing particularly nefarious about Microsoft's goals to have Windows do more and more. | am surethat any oneofus in Mr. Gates's position would similarly seek global domination, or at least total control of the software industry. Even so, understanding Microsoft's larger goals helps put Windows 95in context. The president of one important software company, while reading aboutall these new features in Microsoft's “Chicago” Reviewer's Guide, started to make a list of the companies he expected to go out of business shortly after Windows 95 ships. Okay, that’s a bit melodramatic, but even staid Business Weekstatesthat Windows 95 will do far more to shape the destiny of Microsoft and the computer
industry than anything the trustbusters[in the U.S.Justice Dept.] could cook up...
If makers ofother operating systems have only a glimmer of hope, other software makers have next to none. With Chicago, Microsoft steps up its effort to build in more features that used to be sold separately —
In an InfoWorld article titled, “ISVs: Wake up,” (June 27, 1994), Windows 95 enthusiast Steve Gibsonpaintsa similar picture of the impact Windows 95will likely have on someIndependent Software Vendors(ISVs):
A system equippedwith nothing more than Chicago can be usedto perform really useful work right out of the box. Today I’m still using a trusty old DOSversion of cc:Mail Remote, a crusty old version of Procomm for DOS, and Delrina Corp.'s excellent WinFax Pro software. None is hooked together or has any hooksinto the operating system. Consequently, I'm forced to jumpthrough hoopswith these applications to do what Chicagowill do with far more ease from day one. Forthe providers of yesterday's solutions, this should be a loud wakeup call. Product developers must begin taking Chicago seriously right now to determine howto bestleverage their opportunitiesin this new area of Chicago. Those who don’t, face sure andcertain extinction.” Windows 95is the loudest and clearest delivery of this wakeupcall. The PC software industry is quickly reducing itself to just three major players: Microsoft, Novell, and Lotus. Back when Novell purchased WordPerfect, a writer for PC Week took a look around and saw that ISVs werefeeling trapped in the PC software business and looking for escape routes: Novell's $4.5 billion deal brought into sharp reflief the trends that are remaking the software industry — and forcing many ISVs to perform death-defying feats of survival. Not only are the big players — Microsoft, Novell, and Lotus — bigger than they used to be, they have come to dominate theoffice productivity scene the way Ford, GM, and Chrysler once dominated theauto industry.... The object lesson: The PC software businessis toast. “The business model from the past is unsustainable,” says Roger McNamee, a money managerwhospecializes in technology investments. But take heart. Despite a continuing wave of consolidations, there are
alternatives to just selling out...
Have a word processor? Kill it. Instead of going up against the Big Three, modify the product into a pop-up notepadfor sending messages on the Internet. Afraid of suites? Relax. Think of them asa platform for a hostof symbiotic products. Being kicked around on the desktop? Look to the server. Utilities makers such as Symantec and McAffee
Bivaddn AMLSNGNI
such as electronic-mail software. When Gates described Chicago's features to the Electronic Mail Assn., the mood was somber.“It was like a wake,” says [Steven] Holdschild [director of developer relations] of Lotus, which sells cc:Mail. “A lot of people believe that when Chicago ships, the messaging industry as we know it is gone.” — AmyCortese, “Next Stop, Chicago,” Business Week, August 1, 1994.
UNAUTHORIZED WINDOWS 95
Associates are — especially as Microsoft adds more and morefunctionality to the operating system. — Bill Snyder, “The Great Escape,” PC Week, April 4, 1994.
Thearticle goes on to note that Symantec's “core utility business is being undercut bytheeverlengtheninglist of functionsbuilt into the OS.” Now,it’s importanttoslightly qualify these fire-and-brimstone warnings oftoast and wakeupcalls. Mostof the functionality Microsoft is putting into Windows 95 isn't built into the operating system. Bundled, yes. But built in or integrated?
Not
really. Microsoft has outsourced muchof the work on these extra features to third parties. Many of Microsoft's bundledutilities are not as full-featured as the separate, commercially available products. However, even if Windows 95 doesn’t do everything that available third-party products can do, consider that most customers probably don't want full-featured products; something that does what they need and that comes ready to use with their machine, will do just fine. So if you were the maker of a fax, email, Internet, or communications package, even a stupendously good one, you would needto start worrying — and | mean lose-sleep worrying — abouttheinclusion of these capabilities in every copy of Windows 95.
Lessons (rom History: MS-DOS 5.0 and 6.0 If the PC software business as we knowit is toast, Microsoft started slicing the bread (soto speak) back in June 1994, whenit released MS-DOS5.0.Thatversion of DOSincluded 386 memory management, somewhat similar to what Quarterdeck and Qualitas had beenselling asthird-party add-ins to DOS, and a numberof disk utilities that Microsoft “licensed” from Central Point Software (now part of Symantec). | put licensed in quotation marks because apparently all Central Point received in exchangeforits software wasa license from Microsoft allowing use of the DOSshell’s “look andfeel” (Newsbytes, June 12, 1991). Asan interesting commentary on the need for competition in the operating systems market, Microsoft produced MS-DOS5.0 largely because Digital Research's DR-DOS 5.0 had been released in August 1990 and was doing quite well. DR-DOS 5.0 was being sold through normal retail channels, which Microsoft had never tried with MS-DOS, It is likely that, without competition from Digital Resarch, MS-DOS would have continued to stagnate (it had been years since the awful DOS 4.0 release). On the other hand, the MS-DOS5.0 feature set, including the bundled memory manager and diskutilities, was borrowed wholesale from DR-DOS 5.0. So perhapsit is thelate Digital Research that we should blame (or thank) forthe initial expansionof the operating system.
~
It's interesting to examine the concerns expressed when MS-DOS 5.0 was released regarding the effect it would have on companies making memory manDOS5 looked. If you wonder why I'm dredging up this stuff, remember: Those who
do not rememberhistory are doomedto repeat it. There are manyclose parallels betweenthe expected impact of Windows 95 and the known impact of MS-DOS 5.0. Let's see if we can learn something from history: As you read through what's new and great in DOS 5.0,you have to wonder what happenstothe third-party utility makers who have made millionsfilling the gaps in DOS — companies such as Qualitas (386-MAX), Quarterdeck (QEMM-386), Symantec (The Norton Utilities), and Central Point Software (PC Tools), and others. The short-term answeris that they'll be hurt, some worsethan others, but the smart utility designers have already upgraded their products to capitalize on the new features of DOS 5.0.... Symantec and Central Point may actually profit from the emergence of DOS 5.0... Makers of 386 memory managers will take a harder hit. DOS 5.0’s EMM386.EXE memory manager won't do everything 386MAX or QEMM386will do, for example, swap out slow ROMfor fast RAM to boost system performance or automatically optimize your system’s configuration to take advantage of upper memory, but thetruth is that it does the two most important things that these products do: load TSRs and drivers high and emulate LIM 4.0 expanded memory with extended memory. If you buy any 386 memory managerright now, you're paying good money just for incrementalfeatures,but like theutilities makers, the memory management vendors are currently enhancing their products to provide extra benefits. — Jeff Prosise, “DOS5: what's in it for you?”, PC Magazine, September 24, 1994. Central Point has since been bought by Symantec. Meanwhile, Symantec lost $1.1.5Min salesin 1993. ‘As for memory-management vendors such as Quarterdeck and Qualitas,there were hopes that DOS 5 would help them by legitimizing the market for their products, as Paul Sherer noted at the time in PC Week: Memory-management software vendors facing imminent competition from Microsoft Corp.'s DOS 5.0 say they are confident that the new system's shortcomingswill workto their advantage. DOS5.0fails to duplicate the automatic ability of existing memory products to move device drivers and memory-esident programsinto upper memory and place them into optimal regions of memory, according to beta testers and the DOS 5.0 manual. Slated to be announced June 11, DOS 5.0 will perform these tasks
only on a manual basis. However, it will improve on existing memory
3ivaddfn AuULSNGNI
agers, such as Quarterdeck. Let's go backin time and see howthe then-impending
UNAUTHORIZED WINDOWS 95
managers by loading portions of the operating system into the 64Kbyte High Memory Area just above 1M byte, the betatesters said. Even though other vendors’ products currently don't matchthis loading capability of DOS 5.0, vendors say DOS 5.0’s capabilities will help expand the market for memory managers. It will also encourage users to piggyback DOS5.0with the existing programs. “DOS 5.0 legitimizes what we have been doing all along,” said Mary Stanley, president of Qualitas Inc. in Bethesda, Md. More than million people use Qualitas’ memory-managementtechnology,either through 386Maxor OEM products, she said. “Ourbiggestissueall along has been market education. Microsoft [will] introduce people to this” technology, Stanley added... Existing vendors claim that once usersget a taste of DOS5.0,theywill moveto the more complete solutionsoffered bythird parties. — Paul M. Sherer, “DOS5.0 shortcoming mayhelp memorymanagement vendors,” PC Week, May 20, 1991.
Contrary to the rosy predictions in 1991, Quarterdeckis seriously hurting today. As another PC Weekarticle (this one dated 1994) reports:
After three successive quartersof declining sales and mountinglosses, QuarterdeckOffice Systems Inc. is undergoing drastic cost-cutting measuresin hopesof returning to profitability. The cuts — which so far have resulted in the layoff two weeks ago of 25
percent of its U.S. work force, or 55 employees — also prompted the resignation of founder, President, and CEOTerry Myers. Analysts said Quarterdeck is in a precarious position, given the erosion ofits flagship QEMM memory manager. “That market has dried up lot,” said Richard Davis, an analyst with Louis Nicoud Associates in San Francisco. Davis said he is not con-
vinced that the company’s Internet strategy [a Mosaic front-end and World-Wide Web server products] will be enough to turn it around. Overseeing the turnaroundefforts is industry veteran King Lee, who joined Quarterdeck’s board August 1 and is serving as interim chief operating officer. Lee pledged to get back to the basics and hasalready closed several of the company’s offices, cutting $1 million from the quarterly U.S. runrate. Although Lee has hadpast successbuilding, or rebuilding,utility companies such asFifth Generation Systems Inc. and XTree Co. — both of which were later sold — Quarterdeckofficials claimed nosell-off is planned. — Jane Morrissey, “Quarterdeck CEOresignsoverdrastic cost-cutting,” PC Week, August 29, 1994.
Quarterdeck Office Systems, little ($48 million sales) firm in Santa Monica, Calif., makes a livingfilling in gaps in the Microsoft product. Why does Microsoft leave room forthis tiny competitor? How does Quarterdeck survive? The answers to these questions provide a case study in how little firms competewith big ones... Unfortunately for Quarterdeck, both DESQview and QEMM have been eclipsed by a competing Microsoft product... Obvious question: Howis it that Quarterdeckis still able to sell its productsatall? How is it that thefirm's profit margin is a fat 23%? The answeris that (Quarterdeck founderGary] Pope's programs work much better than Windows 3.0 with the older version of application programs. Windows3.0,in contrast, works best with thelatest versionsof spreadsheets, word processors and otherapplication programs, versionsspecifically made compatible with Windows. Thus, Quarterdeckis selling to users who are beefing up older computer systems rather than starting over with spanking new machines and applications. Quarterdeck sells new, improved buggy whips while the biggerfirm busies itself with the much larger market for horseless carriages...
Buggy whips are a nice niche for a while, but what do you do when the last customer has tradedin his horse for a car? Quarterdeckis looking for other niches. Its next product, now in customertesting, allows PC users to run application programs created for Unix workstations while running MS-DOS programs in separate windows. Years hence, when DOSis passe and new machinesall run on some new operating system,it's quite possible that Quarterdeckwill still be selling this product. No doubt someentrepreneurout there is still selling replacement parts for the Model T, and making a decentliving at it. — Julie Pitta, “Buggy whip marketing: tiny Quarterdeck sells enhancementsto giant Microsoft's operating systems. How
does it survive?,” Forbes, November25, 1991.
Let's now turn the clock forward to September 1992, when newsof the forth-
coming MS-DOS6.0 (which would not be released until April 1993) was appearing in the computer trade press:
Microsoft Corp. is once again using its operating system prowess to
marchinto territory held by other software developers. This time the battlegroundis utilities. The upcoming DOS6.0,due later this year orin early 1993,is expected
to include anti-virus software, a more sophisticated backup program,
3ivadn AwLSNGaNI
It's not Microsoft's fault that Quarterdeck chose to spend several years working on its DESQview/X project. But at onetimeit looked like this was part of an intelligent strategy for competing with Microsoft. Back in 1991, Forbes ran a story onwhatit called Quarterdeck’s “buggy whip marketing”:
= Ss UNAUTHORIZED WINDOWS 95
and a disk defragmenterfor optimizing disk space and data compression, according to sourcesbriefed on the upgrade. Theseutilities are part and parcel of Microsoft's Windowsstrategy as well, sourcessaid. All of this is part of a trend that began in June 1991 with the introduction of DOS 5.0, which is equipped with a builtin keystroke and macroeditor, a DOSshell, a robust text editor, and backup andrecovery tools. Given theutility horsepower of today’s — and tomorrow's — operating systems, manycorporate sites are diminishingtheir reliance on thirdparty products in an effort to reducecosts. If the level of utilities functionality in DOS 6.0 comes within 15 percent
to 20 percentof that in third-party packages,“I'll use DOS 6.0 as my standard and make an exception for the handful of users who wantfull-
featured utilities," said Bill Ramage, a systems architect in the San
Francisco office of Bechtel Corp., an engineering and construction firm with 6,000 PCs worldwide. “Frankly,it’s free [in DOS 6.0],” Ramagesaid.“Also, I'd prefer to have
the tighterintegration ofutilities in the operating system.”
Ramage speaks from experience. Bechtel decided against standardizing on Quarterdeck Office Systems Inc.'s QEMM memory-managementprogram last year simply because DOS5.0 offered similar capabilities. Microsoft officials, however, denied theyare trying to overtaketheutili ties market, claiming the company doesn’t want to be everything to
everybody.
“We'll provide 80 percent[ofutilities’ capabilities],” said Brad Chase, general manager of MS-DOS for the Redmond, Wash., company. “There will be an opportunity for utility vendors to add value as well.” .
Companieslike Stac Electronics and Qualitas Inc. have fared reasonably well with oneprincipal utility, but many industry observers saythat times are about to change.
“Clearly, the onetrick ponies are at risk,” said Bernd Harzog, program director of personal computing for Gartner GroupInc., a marketresearch firm in Stamford, Conn. “System software will continueto include many things that today wethink of as applications, and peoplein business on that fringe should be nimble ... and find new things to move upstream.” — Paula Rooney and Paul M. Sherer, “DOS 6.0 threatens utility developers; users, however stand to benefit,” PC Week,
September 14, 1992.
Soundfamiliar? True, Brad Chase's desire for 80 percent of the market sounds better than Mike Maples's desire for 100 percent, but otherwise the concerns surroundingthe introduction of MS-DOS 6.0 — the OSis comingto include what formerly wasapplication software, one-product companiesareat risk, times are about to change — soundlike a dress rehearsal for Windows 95.
What Belongs in the Operating System? Now,I’m not asking you to cry overthedifficulties that will confront companies such as Symantec and Delrina as their core functionality is bundled for free with Windows 95. When Microsoft put disk compression into MS-DOS6,leading to nearly immediate layoffs at Stac, the response of most developers (myself included) was “Heck, disk compression belongs in the OS. Stac had a nice ride for a while. Let them find anotherline of business.” Them’s the breaks. Indeed, perhapseverything Microsoft is putting into Windows 95 and everything Mr. Gates wantsto see in a future version of Windowsreally does belongin the OS. As word processors, databases, spreadsheets, and graphics packagesall converge towardthe samebasic well-defined set of standard features, perhapsthis software belongs in the OS either as bundled programsor as reusable componentsin the form of dynamic link libraries (DLLs). Does the world really need so manydifferent word processors? How about C++ compilers? Telecommunications programs? Disk repair utilities? If you're an ISV, wouldn'tthe world be a betterplaceif the functionality of your product were providedfree with every copy of Windows 95? If an ISV makes an application orutility product that it thinks most PC users should buy, then — almost by definition — it seems that product’s functionality belongs as part of the OS. Just as a database should not include any duplicated data, likewise the software baseideally should notinclude any duplicated code. For any general-purposeapplication orutility that is widely used, it's probably only a matter of time before Microsoft considers putting that product or its functionality where it “belongs”: in Windows. Windows supports general-purpose non-Microsoft applications in the same waythat a rope can besaid to support someone whowill soon be hanged. Your product maybe a Microsoft DLLjust waiting to happen.
> = 3ivaddn AWLSNGNI
So, whatdid happento these vendorsafter the release of MS-DOS 6.0 in April 1993? Well, we've already seen that Central Point was bought up by Symantec, and that Symantec and Quarterdeck have beenlosing sales. As another example, Stac Electronicslaid off 40 people, or 20 percent of its work force, in May 1993. Manyof the concerns surrounding Windows 95have already beenplayed outin MS-DOS5.0 and6.0.If thesereleases are any guide,there's a slim possibility that Windows 95will “legitimize” the market for Windows email and fax software, for example, and thatthe next version (Windows 967)will delivera fairly serious blow. On the other hand, Microsoft appears to have learned a lot sincethe releases of MS-DOS 5.0 and Windows3.0. At least they got that x.0 out of the product name. So Microsoft might get it right thefirst time and cause serious damage to other software companies (who, remember, are not only its competitors but also effectively its customers for the operating system) as soon as Windows95 is released.
= 8 UNAUTHORIZED WINDOWS 95
But one reason behind this expansion of Windowshasto dowith anearly aberration of the PC software market. Microsoft's operating systems started out supplying users with the bare minimum necessary to use their PCs. A largethird-party industry formedtofill the many holes Microsoft left in DOSandlater in Windows.All sorts of programs, such as as shells, file managers, disk-repair programs, debuggers, and memory managers, that would on most other computers have simply been part of the OS from day one were on the PC sold as separate products by third-party vendors. This aberration played a large part in the explosion of the PC market. As one example, competition over who could produce the best disk-compression software undoubtedly led to the production ofbetter diskcompression software than would have occurred if it had simply been bundled with the OSfrom day one. Theflipside is “you get what you pay for” — that if you don’t pay for something, you probably won't get mucheither. Software bundled with the OSis likely to suffer from complacency. (Well, the software isn’t, but you know | mean.) The high quality and low price of most PC software is largely due to the fact that it wasn't bundled with the operating system Thus,evenif a piece of software “belongs”in the OS in somenarrowtechnical sense,the economicsof how to produce the bestsoftware most efficiently leads to a more complicated idea of whereit belongs. The decision about whethera piece of software should beintegrated (or at least bundled)into the OS, orinstead handled by third-party vendors through the marketplace, is similar to a “make or buy?” decision. Just as “make or buy?” should not be answered according to some narrow technicalcriteria, similarly you should not jump to the conclusion that, say, disk compression, disk repair utilities, or even a commandshell belongsin the OS. For Microsoft, the question of whether something belongsin the OS is not an entirely technical issue, but also a business decision. Windowsis sold as retail product; Microsoft continuously needs major new features to display onthe outside of the box. In addition, as we'll see later (in “Is Microsoft Office the Operating System?"), Microsoft is not above adding features to DOS and Windowsthat will makethem into betterplatformsfor the Microsoft Office applicationssuite. So, for a variety of reasons, Microsoft now wantsto bring a lot of extra functionality into Windows.This is understandable.At least in a purely technical sense (though, again, that's only part of the story), most of the features that Microsoft is putting into Windows 95 dobelong there. But the incorporation of these features into the OS is bound to have a major impact on the software industry. Windows 95 is indeed a wake-upcall. Commentingon theutilities bundled with MS-DOS 6.0, PC Magazine (September 14, 1993)noted that, “by adding theseutilities, Microsoft has clouded thedefinition of exactly what an operating system should be.” If Microsoft's definition of the OS
in the operating system. Maybeit’s just 80 percenttoday, butultimately Microsoft
wants 100 percentof the market. Some commentators see this outward expansion and the Department of
Justice's seemingrefusal to touch it as a goodthing. For example, Stewart Alsop was quoted in the New York Times (July 18, 1994) as saying, “If you really care
about improving the personal computer, you want Microsoft to take over all the
piecesof thepie.” There is a certain logic in this. For example, one reason the Apple Macintosh wasfor so long mucheasier to use than a PC wasthat Apple had a closed architecture and completely dominated the market, guaranteeing that almost everything
camefrom a single vendor. Monopoly has someclear benefits. In certain situa
tions, such as public utilities, monopoly may be the only viable industry structure,
leading to a so-called natural monopoly. Speaking of which, the superb biography Gates by Stephen Manes and Paul Andrews (p. 202) quotes a 1981statementby Microsoft chairman Bill Gates in which he noted that volume and standards in PC software can lead to a natural monopoly:
Why do we need standards? . . It’s only through volume that you can offer reasonable software at a low price. Standards increase the basic
machine you can sell into...
| really shouldn't say this, but in some waysit leads,in an individual productcategory, to a natural monopoly: where somebodyproperly documents, properly trains, properly promotes a particular package and through momentum,user loyalty, reputation, sales force, and prices builds a very strong position within that product. Gates probably understoodthis connection between volume and quality earlier than anyoneelsein the PC software industry (which industry, of course, helargely definedin thefirst place). Still, it is worrisome to hear Gates speaking of monopoly even backin 1981.If the PC operating system is a natural monopoly, if Microsoft should takeoverall the pieces of an increasingly-valuable pie, remember that companies in such favored positions generally are forced to make an important tradeoff: So-called natural monopolies are generally regulated, are prevented from expanding their monopolyinto new areas, and so on. Microsoft already has MS-DOSinstalled on about 120 million PCs in the world and Windows on about 50million. Having reached a very favorable antitrust settlement with the Department of Justice, Microsoft can move even more rapidly towardsits goal of becoming an unregulated, non-public utility providing total onestop shoppingfor all yoursoftware needs.
3 a3ivadn AuISNGaNi
was clouded at the time of the DOS 6 announcement, certainly by the time Windows 95is released therewill be few doubts: Microsoft not only has a nearmonopoly on the operating system but is also constantly expanding the definition of what belongs
= 5 UNAUTHORIZED WINDOWS 95
The Windows 95 Compatible Logo It’s long been observed that Microsoft keepsraising the stakesfor staying in the software business. For example, a New York Times (December 14, 1992)article that started off, “Can anyone besides the Microsoft Corporation make moneyin software anymore?” (answer:yes, as long asyoufind a niche “in which Microsoft is not a player”), went on to quote onefinancial analyst's explanation for why he was notcurrently recommendingany software stocks: User expectationsfor shrinkwrapped software are being reset very low in termsofprice and very high in termsoffunctionality... The problem is the marketing expenseto get share of mindis so high, and Microsoft keepsraising the ante.” In Windows 95, Microsoft is quite literally raising the ante to stay in the Windows application development game. In what might be thefirst tentative steps towards a Nintendo-style certification program, Microsoft has published new guidelines on what applications must do to qualify for the Windows 95 Compatible logo ontheir product and ads. Asspelled out in an article on “How to adapt an app for Chicago” (Microsoft Developer Network News, July 1994), the requirements are quite strict. There are too many to quote in full here, but some highlights follow: *
The application must be a Win32 executable.
*
Theprogram mustrun successfully on Windows NT 3.5 in addition to Windows 95.
* *
If the program deals with files, it must have OLE 2.0 support. If the program deals with files, it must be mail enabled, supporting at least a Send or Send Mail command on the File menu.
According to the managerof the Windows logo program at Microsoft, “we are raising the stakes by saying notonly do these products [with the Windows 95logo] work, but they create a valuable synergy with the operating system” (InfoWorld, August 29, 1994, p. 27). The question is, valuable for whom? Most of the requirements seem to have more to do with Microsoft's desires than with the potential end-user’s. For example, although the Win32 application programminginterface (API) is nice, many programs simply getlarger when ported to use 32-bit code. The NT requirement seemslike nothing more than an attempt to leverage Microsoft's control overthe upcoming Windows 95 market to assistits lacklustre Windows NT product. The OLE 2.0 requirementis odd, given that Microsoft itself hasn't used OLEfor the Windows95shell (see Chapter2). Microsoft is simply raising the cost of developing Windowsapplications, and not necessarily in waysthat will benefit end-users.
Besides the expansion of Windows to include functionality that once was the domain ofthird-party applications, a similar trend is represented by the increasing integration between Microsoft Office and Microsoft Windows. Most PCs today comewith not only MS-DOS and Windows butalso Microsoft Office preinstalled on the hard disk. Office was the top-selling software package in 1993, with revenues just under $500 million, according to Dataquest;it outsold its closest competitor, Lotus SmartSuite, by 4 to 1 in 1993. In turn, Microsoft estimates that 50 percent ofits revenue comes from Office (InformationWeek, June 27, 1994). Microsoft Office seems more and morelike part of Windows.Oris it the other way around? The Windows 95user interface appears to borrow heavily from that of Microsoft Office: The Justice Department may not have seen a connection between the
way Microsoft develops its operating systems andits applications, but
Windows users will see a clear connection once Chicago makesit to market....Many of the changesin the userinterface that Microsoft is pushingcan already beenseenin Office 6.0... One example of the changes in the operating system that were taken directly from Office is the use of theright mouseclick as a property inspector... In the next version of windows, dialog boxes will resemble the tab-cen-
tric designs used in the Office suite.
— Randall C. Kennedy, “Like Office? You'll Love Chicago!”, Windows Sources, October 1994, pp. 23-24.
Windows 95is not somenefarious Trojan horse for Microsoft Office. (One wild rumor had it that Microsoft was deliberately delaying Windows 95to let the Windowsappsdivisionfinish its next version of Office!) But in the past it has sometimes seemedasif Windows was justa platform for Microsoft Office. Microsoft has even added features to DOS and Windows to make them into betterplatforms for the Microsoft Office applications suite. For example, during the Stac v. Microsoft trial, it came out that one of the main reasonsBill Gates urged the MS-DOSgrouptoinclude disk compression wasthat, without it, Microsoft would havea hardertimeselling the disk-hungry Office suite. MS-DOS 6.0 needed disk compression notonly to compete with DR-DOS 6.0 (which included disk compression) and notonly to to have a nice starburst on the box saying “The easiest way to double your hard disk,” but also to grease the skids (or at least the hard disks) for Microsoft Office.
alvadn AuLSnNaNi
Is Microsoft Office the Operating System?
a UNAUTHORIZED WINDOWS 95
As another example, Microsoft Windows much-hyped (but not necessarily very practical) Object Linking and Embedding (OLE) feature always seemsto show upearl erin the componentsof Microsoft Office than in any non-Microsoft applications. Brian Livingston (More Windows 3.1 Secrets, p. 194)reports that Microsoft PowerPoint 2.0, which was shipping to customers in June 1990, included support for OLE — six
months before OLE documentation wasreleased to developers. On a broaderscale, OLEappears to have beendesigned largely for the convenienceof Microsoft Office. With the Office Developers Kit (ODK) and Visual Basic for Appliations (VBA),
Microsoft is encouraging developers to write Windowsapplications targeted specifically at Office. Of course, Lotus and Novell have similar programs to encourage
applications targeted specifically at their suites. But given Office’s market share — particularly the fact that it comes bundled together with Windows on most new PCs — Microsoft, unlike Lotus and Novell, has a good chance of convincing devel-
operstoviewits suite as a major developmentplatform. Similar to the Windows 95 Compatible logo, Microsoft also has an Office
Compatible logo. Paul Bonner, who has written extensively on customizing Windows, had some interesting observations aboutthis:
If you're living within a suite, and selecting applications and utilities based on how well they work with that suite, you can’t even think of Windows as your operating environment anymore. The suite is your operating environment, meaning, amongotherthings, that both you and your applications haveto live by the suite’s rules, not those of Windows... This year, Microsoft introducedthe Office Compatible logo program. For a fee of $1,000, third-party vendors gain theright to adopt the look and feel of Office applications such as Word and Excel, including their tool-
bars and menu structures.
There's only onecatch: If your software application competes with any application ortool Microsoft itself offers, you aren't eligible to take part in the Office Compatible program. Maybethat’s not surprising. The Microsoft Office and Office Compatible labels are, after all, the trademarked property of Microsoft Corp. The Office Compatible program lets participants use all kinds of copyrighted icons and toolbar designs, and all kinds of otherwise proprietary information about Office. Microsoft shouldn't have to extend those privileges
to competitors’ products, right?
Wrong. Microsoft Office is not just another application, and Office Compatible programs are not simple add-ins. WhenOffice compatibility becomes a checklist item for buyers, determines the look andfeel of applications, and extends otherwise unavailable capabilities to them, then Microsoft Office becomes an operating system untoitself, complete with a proprietary application programminginterface...
friend of mine who is president of a medium-sized software company keeps telling me, “Microsoft Office is now the operating system, and Visual Basicis its
API.” | think there's a large elementof truth to this: Microsoft really is intent on grabbing a much larger share of the applications business, and Windows 95is a keypart of this strategy, so it follows that customizing Office will be a growth indus-
try, in much the same way that customizing 1-2-3 and dBASE was once a major form of software development. An interesting question, which we'll take up later
(see “Windows 95: Dangers and Opportunities”), is whether a viable software industry can be based on writing add-ins for Microsoft Office.
Microsott and the Justice Department Now, you mayrecall that Microsoft was underinvestigation for possible antitrust violations, first by the U.S. Federal Trade Commission (FTC) and then, when the FTC became hopelessly deadlocked, bythe Antitrust Division of the U.S. Departmentof Justice (DOJ). You might have expected the trustbusters to in some way address Microsoft's increasing hold over an increasingly important industry. Well, they did address this: After what appears to have been a very thorough, aggressive, and
expensive four-yearinvestigation, the trustbusters endeduptelling Microsoft to change a few minorpractices. In essence, the U.S. government gave Microsoft the greenlight OnJuly 15, 1994, Microsoft signed a consentdecree with the Antitrust Division of the DOJ, ending a four-year governmentinvestigation into Microsoft's trade practices. At the same time, Microsoft signed a nearly identical settlement with the Directorate-General for Competition of the European Commission. The judgment lasts for 6 1/2 years in the United States, 4 1/2 years in Europe.
Microsoft agreed to immediately abandon several arrangementsfor licensing the MS-DOS and Windows operating systems to PC hardware vendors, and also agreed to
= a aivaddn AuLSnaNi
Once you begin to think of Microsoft Office as an operating system, the Office Compatible program takes on a whole newlight.... The non-competition clausein the Office Compatibility contract ensuresthatthe only applications that will be available for use with Office will be those Microsoft wants to have available. That means only applications that complement Redmond’s core applications, not any that compete with them.... Microsoft will undoubtedly convince scores of independent developers and small software companies to produce Office Compatible applica. tions, if only becauseof the marketing support it canoffer. — Paul Bonner, “Will the real operating system please stand up?”, Computer Shopper, October 1994.
sl oo
halt some “unnecessarily restrictive” clauses in its non-disclosure agreements (NDAs)
for the Chicagobeta test. The consent decree explicitly excludes Windows NT. UNAUTHORIZED WINDOWS 95
The consent decree wasfirst viewed as victory for the DOJ and Microsoft's competitors. The New York Times(July 17) carried a front-page headline, “Microsoft's
Grip on Software Loosened by Antitrust Deal,” and crowed that “the pact could reshape the world of computing... The accord could undermine Microsoft's near total
control of the market for operating systems.” The Boston Globe’s headline was equally enthusiastic: “Microsoft accord to create competition in US, Europe.” Indeed, the consent decree sounds at first as if it should cramp Microsoft's
style and lead to more competition in PC software. For years, Microsoft has provided PC hardware manufacturers (original equipment manufacturers, or OEMs) with per-processor licenses to MS-DOS and Windows, in which the vendor pays Microsoft based on the numberof machinesit thinkit will ship ratherthan the number of copies of DOS or Windowsit actually uses. In 1993, such per-processor agreements accountedfor about 60 percent of MS-DOS OEMsales, and 43 percent of Windows OEMsales. According to the DOJ, “Microsoft's per processor contracts penalize OEMs, dur-
ing the life of the contract, for installing a non-Microsoft operating system. OEMs that have signed per processor contracts with Microsoft are deterred from using
competitive alternatives to Microsoft operating systems.” The consent decree put
an immediatestop to this practice, leading to the hope that non-Microsoft operating systems would now have a shotat the desktop.
But the morningafter, nearly everyonerealizedthat, in fact, the DOJ's abortion of US v. Microsoft was a victory for Microsoft. Directly contradicting the previous
day's headline, a New York Times (July 18) news analysis by John Markoff spoke of “Microsoft's Barely Limited Future": “Rather than reining in the Microsoft Corporation, the consent decree ... frees the company to define the computer
industry's ground rules through therest of the decade.” In the first day of trading after the settlement, Wall Street made its statement on the consent decree: Microsoft stock rose $1.87, to $50.50. Rick Sherlund, an
analyst for Goldman Sachs, stated that with the settlement, Microsoft “should dominate the market for desktop software for the next 10 years.” Another frequently-
quoted analyst, Richard Shaffer, announced that “The operating system wars are over — Microsoft is the winner... Microsoft is the Standard Oil of its day.” Windows 95 needs to be viewed in the context of Microsoft's victory over the
DOJ: Windows 95 and its successors will be the primary mechanism through which Microsoft exercises its control over the desktop and defines the industry's
ground rules.
But how could a ban on an important Microsoft trade practice be viewed as cementing Microsoft's hold on the industry?
contracting practices.”
“Microsoft has usedits monopoly power, in effect, to levy a ‘tax’ on PC manufacturers who would othemise like to offer an alternative system.” said Bingaman.“As a result, the ability of rival operating systemsto compete has been impeded,innovation has been slowed and consumerchoices have beenlimited.” According to a DOJ press release, Bingaman noted that Microsoft has maintained theprice ofits operating systems evenwhile the price of other components has fallen dramatically, and that since 1988,Microsoft's share of the market has never dropped below 70 percent. This is quite amazing: Thechief U.S. trustbuster saying exactly what many in the PC software industry havesaid for several years: that there’s a Microsoft “tax,” and that Microsoft — despite the perception among consumersthatits prices are low — has in essence engagedin price gouging.
3S 3ivaddn AuLSsnaNi
First, the change from per-processor to per-copylicensing probably comes several years too late. Anne Bingaman acknowledgesthis: “I wish it werefive years ago. | know it’s late” (InfoWorld, August 15, 1994, p. 46). Despite some brave words from IBM and Novell following the consent decree,it seemsunlikely that the changewill lead to a larger presencefor OS/2. For its part, Novell almost immediately followed the DOJsettlementbyditching Novell DOS7; this wasin any case a smart move. As a spokesman for Compaq (which already offers OS/2 toits customers) noted, “Windowsis the standard — not much will change.” More important, the consent decree doesn’t address the key questions about Microsoft's role in the PC software industry. Companies such as Lotus and Borland that competewith Microsoft in the market for word processors, spreadsheets, and other applications have long asserted that Microsoft leverages its control of the operating system to unfairly benefit its applications — particularly Microsoft Office — at the expenseof non-Microsoft applications and suites. Microsoft continues to deny that it monopolozies the PC software industry. Nor has it admitted to anyguilt by consenting to the court's final judgment. The consent is explicitly “withouttrial or adjudication of any issueof fact or law; and withoutthis Final Judgment constituting any evidenceor admission by any party with respect to anyissueoffact or law.” Nonetheless, the PC software industry has beentreated to some enjoyable denunciations of Microsoft trade practices from high governmentofficials. After the signingofthe consent decree, U.S. Attorney General Janet Renosaid, “Microsoft's unfair contracting practices have denied other U.S. companiesa fair chance to compete, deprived consumers of aneffective choice among competing PC operating systems, and slowedinnovation.” The Assistant Attorney General for Antitrust, Anne Bingaman, noted that “Microsoft is an American successstory but there is no excuse for any company to try to cementits successthrough unlawful means, as Microsoft has done with its
Nn Ss UNAUTHORIZED WINDOWS 95
But forall the pleasure manyPC software developers might takein reading the accusationsin the abortive US v. Microsoft complaint, the fact remains that the consent decree addressesonly a narrow issue: OEM sales represent less than 25 percent of Microsoft revenue. The complaint notes that “At least 50,000 applications now run on MS-DOS and over 5,000 havebeenwritten to run on Windows. Microsoft sells a variety ofits own very successful andprofitable applications.” Butthat is all it has to say about applications! The complaint also notes that “All versions of Windowsreleased to date require the presence of an underlying operating system, either MS-DOSora close substitute,” but says nothing about alleged tying arrangements between Windows and MS-DOS(see Undocumented DOS, 2ndedition, pp. 3-18). Similarly, the complaint mentions “critical information about the interfaces in the operating system that connect with applications — information which the ISVs need to write applications that run on the operating system.” But the complaint doesn’t address the charge that Microsoft unfairly withholds someof this critical information totry to give its own developersexclusive use of undocumentedinterfaces. Now,it’s not asif the DOJ was unawareofthese issues. From my own meeting with DOJ attorneys Sam Miller, Don Russell, and Larry Frankel, | know that they were extremely interestedin the issues surrounding undocumentedinterfaces. We spokefor several hours about possible remedies, including whatthey referredto as “mandatory interface disclosure.” Similarly, a Civil Investigative Demand received from the DOJ requested “All correspondence, including electronic mail messages, to and from Microsoft Corporation... that discussesor relates to competition in the developmentor sale of personal computer operating systems orgraphicaluserinterfaces; the compatibility or incompatibility of any Microsoft product or any non-Microsoft product; or the disclosure or non-disclosure of information relating to software interfaces.” | was able to supply them with somefascinating email from Microsoft VP Brad Silverberg. My favorite is Brad’s explanation from October 1993 of why he must keep on expanding the Windows API: “Once Windowsis frozen and no longer moving for ward, it can easily be cloned and thus be reduced to a commodity. Microsoft doesn’t wantto be in the BIOS business.” The DOJ was well aware of, and quite interested in, the issues surrounding Microsoft's ownership of the vastly important DOS and Windows standards. Yet noneofthis is addressed in the consent decree, which ends up looking similar to what Microsoft probably could have received from the FTC a yearearlier. Even Bill Gates, who apparently denounced even the mildest FTC and DOJ questions as “communistic” and “socialistic,” had to admit that thefinal settlement was no big deal. After years of investigation, he says,“This is what they cameup with.”
important to the U.S. economy, at least when compared to companies such as IBM
or GM that make tangible goods. Although software is a crucial part ofthe world economy, consider that even “giant” Microsoft has only about 15,000 employees. Its quarterly sales are about $1.25billion, compared to $13.3 billion for IBM and even $2.5billion for Apple. What makes Microsoft different is that it has almost obscenely low costs. This
is very nice for Microsoft, butit's hard to see whatit does for the U.S. economy, especially when 45 percent of Microsoft's stock is owned by insiders. The DOJ could
have made a moderately plausible case to the American public that Microsoft, far from being a “national treasure,” is simply a grossly profitable monopolist, with few employees and few stockholders, thatgives back little to the public.
Another explanationis that the DOJ feared a repeat of US v. IBM,which dragged on for thirteen years, only to be dropped as “without foundation.” But while you could easily imagine lawyers for the DOJ not wanting to stake their careers on a losing battle, | wonder whetherUS v. IBM was such a complete washout,afterall. Even though the case waseventually dropped, for yearsit had a serious effect on IBM.
Accordingto a recent bookonthefall of IBM andtherise ofits one-time suppli-
ers, Microsoft and Intel, it was the supposedly unsuccessful antitrust case that
caused IBM to unbundle software from hardware. This opened the way for an independent software market, making roomfor software upstarts including a company called Microsoft:
The 1969 suit has been expectedfor a long time, and IBM had already begun to unbundlethepricingofits systems, makingit easier for other companiesto sell comptible devices and software...
Manyof IBM's actionsin the 1970s and 1980s, particularly its supine attitude toward small suppliers of PC components and software, can be explained as the reflexes ingrained by a decadein the courtroom’s harsh glare...
8 aivadn AuISNGaNI
Why did the DOJ settle for so little? How could they seemingly ignore the entreaties of so many PC software vendors? Onetheory is that the Clinton administration views Microsoft as a “national treasure,” and put pressure on DOJto leave Microsoft alone. The press made much of a May 25 meeting between Bill Gates and Clinton's chief economic advisor, Robert Rubin. The date is significant because just one weeklater, Gatestestified underoath before the DOJ. According to one anonymoussource, Gates pointed out to Rubin that Microsoft is responsible for a substantial portion of U.S. software exports(Information Week, June 27, 1994). But it's difficult to buy Clinton administration pressure as an explanation for the DOJ's limited settlement. Microsoft maybehighly visible, but it simply isn’t that
8 UNAUTHORIZED WINDOWS 95
After a brief negotiation, [IBM] agreed that Gates would own the system
and that they would pay him ona royalty basis, instead of with a lump sum. (Becauseof the stil-pending antitrust action, IBM was wary of owning operating system softwareforfear of suits from software writers.)
— Charles Ferguson and Charles Morris, Computer Wars: The Fall of IBM andthe Futureof Global Technology, 1993, pp. 10-11, 26.
In other words, Microsoft was direct beneficiary of US v. IBM, and “the next Microsoft" could have beena beneficiary of a US v. Microsoft case. Well, it's too late for that now. Ultimately, | think that the DOJ didn’t push for more against Microsoft for the simple reason thatit felt it couldn’t win anything else. Responding to widespread criticism of the settlement as a DOJ sell-out, Anne Bingamanprotests, “folks, we looked at every aspect of this. We brought the case that wasthere to bring.” According to the DOJ, the Microsoft settlement was “everything we could have hopedfor in a fully litigated case, and possibly more.” Unfortunately, this is probably true. Law,like politics, is an art of the possible. Although the settlementgives Microsoft's ever-expanding monopoly the green light, it's hard to see what the DOJ could have donedifferently. The DOJ's job is to enforcethe antitrust laws, not to makeindustries more competitive — and the two are not the samething. Whatall this meansis that the Microsoft practices studied by the DOJ but not coveredin thesettlementareeither notillegal or (what is much the samething) too difficult to proveillegal. Microsoft must be feeling emboldened by the limited scope of the consent decree. The company should be ableto go full:steam aheadwithits plansto greatly expand the operating system's dimensions in Windows 95. Microsoft Office will increasingly seem like an essential part of Windows.
Windows 95: Dangers and Opportunities Given that the DOJ apparently saw little wrong in Microsoft's role in the software industry, the company's hegemonyis likely to last until sometimein the next century. Windows 95will be the platform and Win32 will probably be the API, in the samewaythat Windows 3.x was the platform andthe APIthat defined the industry in thefirst half of the 1990s. Or Microsoft will be the platform and Visual Basic for Applications will be the API. Either way, Microsoft runs the show for at least the next five years. Microsoft's goal is clear: Provideall general-purposesoftwarefor the desktop. Microsoft's strategy for attaining this goal is to keep movingfunctionality into
programs, and for these programs to moveinto the operating system.
Perhapsthereis still some room in graphics and personal finance software. Microsoft Moneysuffered a much-publicized defeat at the hands ofIntuit's Quicken product, for example, and CorelDraw! is doingwell Whatother PC software companies are doing well? Bill Gates, during a presentation he gavein late 1993, rattled off a list of small software companiesthat he felt represented the opportunities available to software vendors today: Altamira Caligar EJ Bilingual Insoft ShapeWare ReportSmith Watermark
Composer image editor financed by AutoDesk; acquired recently by Microsoft TrueSpace 3.0illustration/modeling software EZ Japanese Communique teleconferencing Visio graphics software; Visio addin for Microsoft Office Client/server report writer; acquired by Borland Providing image-enabled capabilities for Microsoft
Exchange; image server for NT
The bestbetis to find areas where Microsoft doesn't have a product and where there is a chanceof a several-year window of opportunity beforeit does have a product. Onthe other hand, the only market I've ever heard that Microsoft didn't wantto get into was pornographic screen savers and adult multimedia. As one company employee told me, “We looked carefully at adult software, and decided to leave that money on the table." It’s difficult to think of any other area where Microsoft plansto leave moneyonthetable.
8 aivddn AYuLSNGNI
Windowsand to keep pushing Microsoft Office as the “integrated” application layer for Microsoft Windows. How should the restof us deal with the changesin the PC softwareindustry? It is probably stating the obvious, but thereis little point in trying to compete with Microsoft. Novell figured this out almost immediately after the DOJ settlement and decided to drop products and projects such as Novell DOS 7, OpenDoc, and AppWarethat put it in direct competition with Microsoft. Similarly, general-purpose applications and application suites look like a bad area to bein. Particularly becauseofits bundling with Windows on many new machines, Microsoft Office is rapidly becoming a quasipart of Windowsitself. Even Lotus probably haslittle chance in this area. Microsoft Office is everywhere and everything. Soforget writing the next great word processor. After all, word processingis not really an application; preparing legal documents or quarterly sales reports is. A databaseis notreally an application; the accounts payable/receivable system for a dentaloffice is. In some ways, then, it is natural for one company — it happens to be Microsoft — to have a virtual monopoly on general-purpose horizontalmarket
ny & UNAUTHORIZED WINDOWS 95
As notedearlier, one big hope is that so-called “downsizing” will expand the market and produce new opportunities in the client/server market. Manyin the computer industry view downsizing and reengineering the corporation as a direct product of advances in computing technology, and expect the PC industry to be a direct beneficiary of this corporate change. (For example, see the book Client/ServerStrategies: A Survival Guidefor Corporate Reengineers by Microsoft's director of enterprise-wide computing, David Vaskevitch.) However, this might be extremely shortsighted. Reengineering the corporation stemsnot only from the rapidly dropping cost of PCs but at least as much from the long-term downturn in the U.S. economy. Downsizingis often just a euphemismforlayoffs and budget cuts — probably not a good long-term foundation for growth in the PC software industry. At any rate,it is far from obviousthat replacing a mainframewith a network of PCs really saves a company money: onereport claimsthat buying and installing a PC network accounts for less than ten percent of the system's total cost. How aboutthe home market? There has been an increasein computer andsoftware purchasesfor the home. But unfortunately, the industry's excitement over the home market stemsless from an actual rise in the numberof families that have decided to computerize their recipes, stampcollections, and checkbooks, and more from wishfulthinking and a desperate need for somefresh bloodin the market. But let's suppose that the home market does takeoff. Is this really the holy grail that the industry has sought? Theprofit margin on a home software product is very low. As one Microsoft speakerput it in a talk about marketing multimedia titles, the margin is so low that if you takea single tech-support call, your margin’s gone. (His suggestion: Put phone numbersfor every hardware vendoryou can think ofin big letters on the package; put your own phone number in as small a font as possible.) One can have tremendous successesin this area — look at the popularity of Doom — but this doesn’t necessarily translateinto profitability. Onelast point about the home market: Microsoft is already there. As noted earlier, Microsoft Homeis shipping one title per week. The companyexpects to have overthirtytitles available (including the appropriately titled Microsoft Dangerous Creatures) before the 1994 holiday shopping season. Enough about the general stateofthe industry. What are the business dangers and opportunities from Windows95,and whatis the proper response? The dangers of Windows 95 should befairly clear: The incorporation of many features in Windows 95 will make somecurrent third-party products (and thethird parties themselves) obsolete. As for opportunities, it appears that Windows 95will provide a large numberof small opportunities. First, there's the upgrade business. Manysoftware vendors are expecting an increase in sales when Windows 95is released and they can come out with a
Whether this will translate into profitability for anyone except Microsoft is less
clear. Recall Roger McNamee’s point quoted earlier that the upgrade business seems based on the Milo Minderbinder business model: Sell at a loss, but makeit up on volume. As always, anotherinteresting area is plugging holes in the operating system. Several computer journalists have been extremely enthusiastic about the opportuni-
ties Windows 95will provide in this area. For example, Jesse Berst says “For devel
opers, Chicago is a city of golden opportunity” (PC Week, August 29, 1994): Even though the newinterfacewill disappoint experiencedusers,it will be a dream cometrueto utility vendors. It gives them dozensof opportunities for extensions, improvements, and mini-tilities.
‘As one example of these opportunities, Berst mentions the need for a fontmanagementutility. And in later article (“Chicago's a great place to build products on,” PC Week, September5, 1994), Berst writes that “Chicago's biggest opportunity lies in computer telephony Maybeit’s just me, but | don’t see how computertelephony has yet to emerge from the “gee whiz, that's cool" fad phrase. If this unproven areais truly Windows 95'sbiggest basis on which to build products,the future is truly bleak. As for utilities, Windows 95 certainly does present dozensof opportunities to extend the shell, improve the registry, and so on. But these arelikely shortterm opportunities (Microsoft will simply take over anything really vital in its next release). Andin anycase, you can’t sustain a 1000- or even 50-person company on $79.95utilities and add-ins.(Perhaps a 10-person company,though.) TheVirtual DeviceDriver (VxD)interfaces discussed in this book provide numerous ways to extend Windows 95. Perhaps somethird-party vendor will see among the hundreds of VxDfunctionsthe ingredients for an important, profitable Windows extension that for some reason Microsoft won't jumpinto for a few years. The DOS. extender business waslike that: companies such as Phar Lap prospered because Microsoft for variety of reasons didn't want to move MS-DOSinto protected mode. Steve Gibson provides an excellent example of the waysthat existing utilities vendorswill need to adapt to Windows 95.Following the discussion quotedearlier about how Chicagolets him “perform really useful work right out of the box,” and how, “for the providers of yesterday's solutions, this should be a loud wakeupcall,” Gibsonnotes,
g gZivadn AuISNaNi
Windows 95upgradeof their product. Microsoft's delays in getting Windows95 out the door have cost not only Microsoft but also manyother vendors, whose revenue stream is stalled while customers wait for Windows 95 before purchasing any further Windowssoftware. When Windows 95is released, there will be a large spurt of pent-up demand.
8
This doesn’t mean that opportunities for Chicago add-ons are gone. There is a wide variety of ways to hookthingsinto Chicago. But opportu-
UNAUTHORIZED WINDOWS 95
nities have changed. Delrina, for example, recently announced a fax
mailbox and store-and-orward services. Executives there must know that their sales of WinFax Pro will be impacted sharply by Chicago, so Delrina is evolving into a fax service provider, tapping into the features
that every Chicago user will discoverin their box.
— Steve Gibson, “ISVs: Wake up,” InfoWorld, June 27, 1994.
From a technical perspective, this soundslike exactly theright thing to do. My only question is whetherproviding add-ins to Windows95is really a soundbasis for a company’s existence. In an article quoted earlier, PC Week said that if you make a word processor, turn it into an Internet popup notepad. The article went on to point to Q+E and Shapeware asperfect examples of companiesthat have successfully turned their standalone products into components.
Indeed, there is a lot of excitement about componentbuilding in the software industry. Jon Udell has written some superbarticles aboutthis in Byte (“Visual Basic Custom Controls Meet OLE,” March 1994, and “Componentware,” May 1994). As Udell points out, one of the mostinteresting things aboutthis developmentis that a true componentindustry came not from C++ or other objectoriented languagesbutfrom VisualBasic, of all things. Similar to what 1-2-3 and dBASEdid in the 1980s,Visual Basic Custom Controls (VBXs) have spawneda subindustry of componentbuilders. A survey of “VBX Controls as Software Components” in PC Techniques (October-November 1994)lists a numberof companies who have made VBXes their business, including Crescent Software, Desaware, FarPoint Technologies, MicroHelp, and Sheridan. This is indeed an exciting development. However, it’s not yet proven what sort of business can be sustained on components, at least ones without license fees. Equally important,recall that what Microsoft giveth, Microsoft can take away. Becauseofdeficiencies in the VBX architecture, Microsoft is promoting a newinterface, OLE custom controls (OCX), which is incompatible with the old VBX interface. If VBX or OCX component building becomes a big business, don’t expect Microsoft to stay outof it. Already, Visual Basic ProfessionalEdition 3.0 includes a large number ofthird-party VBXs from Sheridan, Crescent, MicroHelp, andothers. Asnoted earlier, there are also somefascinating opportunities for customizing Microsoft Office, whicheffectively is the operating system for more and moreusers. Roger McNamee's Upsidearticle on PC software economicsspelled this out nicely: Mostsoftware executives view Microsoft as the meanest shark in the ocean. That is a mistake. Microsoft is no longer a shark. Microsoft is
8
the ocean itself, in whichall the other fish mustlive... If | were an appliFunk Software built on the 1-2-3 platform — or that the utilities vendors built around MS-DOS — and recognizethat it is only a matterof time before entrepreneurs build businesses on top of Word, Excel and the other Microsoft products. — Roger McNamee, “Sobering Up,” Upside, March 1993.
Recall that this also was the advice provided by PC Week: “Afraid of suites? Relax. Think of them as platform for a host of symbiotic products.” The idea of writing add-ins, macros,verticalmarket products, and so on for application suites, primarily Microsoft Office, dovetails nicely with the current enthusiasm in business books for something called mass customization. (See, for example, William H. Davidow and Michael S. Malone, TheVirtual Corporation, pp. 40-42, which discusses the everpopular example ofASICs, application-specific integrated circuits.) Again, however, it is not clear that viable companies can be built around the customization of mass-market products. As McNameepoints out, 1-2-3 did spawn Funk Software. But the only large by-product of dBASE that | can think of is SBT, makers of accounting modules written in dBASE. Did HyperCard on the Mac spawn anybig successes?It generated tonsof software, but any major companies? Well, Ross Perot's EDSstartedoff essentially in the customization business, so perhaps there's some hope. Aside from these specifics, what larger lessons can be drawn from the past few yearsoflife under Windows? First, accept the fact that Microsoft runs the show. I've seen developers make business decisions, such as using Borland’s OWLrather than Microsoft's MFC, simply becausetheydislike Microsoft. Thenthere's the company whosesole product was a CASEtool for AppWare; or companies whoseproducts are basedentirely around OpenDocor OS/2. Unfortunately, this just doesn't makesense.It's okay to resent Microsoft, | suppose,but don't cut off your nose to spite yourface. Second, for the vast majority of us in the PC software business, it's important to realize that systems such as Windows 95 will be important and that systems such as Windows NT won't be.Evolutionary changes are much easierfor the marketto accept. For a revolutionary upset to be accepted, it must be an orderof magnitude better than what it seeks to replace. Not 25 percentbetter or 33 percent better, but at least 10 times better. Otherwise, change hadbetter be gradual, like Windows 95. Specifically, products such as NT and Daytona (NT 3.5), and perhaps even Cairo, speak to too small a niche to be interesting. And even the NT sales that do occur don’t lead anywhere:Right now I'm running on a network with an NT
3ivagdn AULSNGNI
cation software vendor, | would look upon Microsoft products as platforms on which to build my business. | think back to the business that
UNAUTHORIZED WINDOWS 95
server, but no softwareis likely to ever be boughtfor that server.It sits in a closet that no one touchesfor weeks at a time. This is not the sort of platform on which to base your fortunes. Third, if you're choosing platforms for which to develop software, remember that what ultimately matters is not technical excellence but market penetration. The tworarely go hand-in-hand. This is not simply a matter of bowing to the foolish whims of the market, however: Market penetration leads to standardization, and standards havetangible benefits that are more important than the coolesttechnical feature. Yes, Windows 95 still uses MS-DOS; no,it’s not a pure Win32system;no, it's notparticularly integrated; no, it hasn't been rewritten from the ground up; and yes, it is lacking somenice features found in Windows NT or OS/2. But none of these compromiseswill hurt Windows 95's chances for success and somewill actually help make Windows 95 a success. Windows 95will be the standard desktop computingplatform for the next five years, and that byitself is worth far more thanthe coolest technology.
Chapter 1
WELCOME10 Winnows 99 hen you turn on a PC running MS-DOSversion 6, possibly with the intention of running Windows3.1, one ofthefirst things you see on the screen is the message “Starting MS-DOS...”.
Whenyouturn on a PCrunning Windows95, the messagethat greets
you is “Starting Windows...”. This is a dramatic demonstration (well, as dramatic as a PC sign-on message can get) of how Microsoft wants you to think of Windows. Microsoft wants you to view Windows, not MS-DOS, as the operating system:you turn on yourPC,andittells you you’re starting Windows. Onegoal behind Windows 95 (“Chicago”) is to turn the PC into a machine that no longer makes you wonder why you're not using a Macintosh (especially now that Apple’s prices have come down far enoughthat the Mac competesin the same marketas the PC). Oneof the stated missions for Windows95 is to create what Microsoft calls a “no excuses” standard for PC hardware. Adrian King states hopefullyinhis
Inside Windows 95 (p. xxviii) that with Windows 95 “Apple Computer won'tbe able to run those Windowscommercials any longer.” He’s refer-
ring, of course, to Apple’s TVcommercials portraying Windows as difficult to set up and use. This ad campaignapparentlyhad a big impact on.
Microsoft, possibly even providing the impetus behind the so-called “Plug and Play”effort. Manyreviewers have been impressed with howclose Windows 95 comes to this goal of turning the PCinto a high-volume, low-price
Windowsappliance.Inits August 1994 issue (p. 130), PC World stated:
Unauthorized Windows 95
Starting a Chicago PCis like turning on a toaster: Just hit the button. Sure, you'll still see BIOSinformation and other machine-specific hieroglyphics scroll by, but far fewer than under Windows 3.1. Andthen, instead of pausing at the nastyold C> prompt, your PC will charge directly into Chicago’s Desktop.At the bottom left, your eyes are immediately drawn to a button emblazonedwith the Windowslogo and the word Start. | say drawn because an arrow attached to a text message — “Click here to begin” — floats in from theright, gently bouncingoff the Start button. This pervasive cuteness gets stale in a hurry, but new users will neverbe left wondering what to do next. Indeed,theability to boot seemingly seamlessly into Windows is impressive. So too, as Figure 1-1 shows, is the work that Microsoft has
obviouslyput into the Windows95 userinterface. However, having used Windows 95 nearlyfull time sinc
y 1994, I confess that I still envy
my seven-year-old son Matthew’s Macintosh Quadra 660 AV(a beautiful machinethatcost less than $2,000 U.S.). Windows 95 won’t turn the
proletarian PC into a yuppie Mac. But Windows 95 definitely will
improvethe PC’s longevity, health, image, and reputation. Andthe simple matter ofbooting right into Windows when youturn on the machine is obviously an importantpartofthis effort to turn the PCinto a computing applianceorat least makeit seemlike one.
“eet Fama) est Tals Wed i = "i heading «|x [Helv
ipo
We
feetesdectones and subdirectories on # network server har ng Hes ¢ directories and subdirectories Contain these fies Trem arecory Program file (WinWe 1g setup Grommor checker(Gk
7
i a i
{[Blower-tor24 |
(iain
Figure 1-1: As seenfrom the Chicago shell, the Chicagouserinterface is substantially nicer than that in previous versions of Windows. Even old Windowsapplications, such as Microsoft Word 2.0 (shown here), look betterin Chicago. Now,what doesthis ability to boot right into Windowstell us about the architecture of Windows 95?
Chapter 1: Welcome to Windows 95 Eventhoughyoucould make a PCappearto bootrightinto earlier versions ofWindowsmerely by putting the command WINasthelast line of AUTOEXEC.BAT, Windows 95 mustbe doinga lot more than
this. In fact, it appears that Windowsis no longerstitched onto DOS with
a batchfile, but rather that Windowshas replaced DOSentirely.After all, the machine doesn’t say “Starting MS-DOS...” any more; almost from the
momentit starts up, the machine now says “Starting Windows...”. The old “Starting MS-DOS...” message is produced bya hidden MS-
DOSfile called IO.SYS. IO.SYS anda secondfile called MSDOS.SYS form the kernelof the real-mode MS-DOSoperating system: C:\odir *.sys /azh 0 NSD0S
SYS SYS.
40,566 09-30-93 38,138 09-30-93
6:20a 6:20
As youseein the following annotated hex dump from the DOS DEBUGutility, the startup record (or bootrecord,asit’s often referred to
in books on the DOSfile anddisk system) occupiesthefirst sector of the DOSbootable disk partition andcontains code to load IO.SYS: C:\WINDOWS>debug 1 : load dr: ctor 1 into addr s 100h d 100 300 bry now dum ress 100h 7431:0100 EB 3C 90 4D 53 44 4F 53-35 2E 30 00 02 10 01 00 .dir *.sys /ach WINBOOT SYS
288,030 06-10-94
4:22a
And, sure enough, the startup/bootrecordin Windows95 looksfor WINBOOTSSYSratherthan for [0.SYS and MSDOS.SYS: Windows>debug 100201 d 100 300 77AB:0100 EB 3C 90 40 53 57 49 4E-34 2E 30 00 02 08 1 00
. promptin
the DOS box has Windowswithaninitial cap, notWINDOWS. In addi-
tion to providing longfilenames and directory names, the Windows95 file systemalso preservescase.)
rst, if you've followedalong and removedor renamed CONFIC YS,observe that we've booted Windows without providing anyinstructions onhowto do so. WINBOOTSYS (whose name, interestingly — andsignificantly — MEMreports as MSDOS)clearlytook care of loading HIMEM.SYS, IFSHLPSYS, and ‘TVER.EXE.Next, we that COMMAND.COMwasloadedinto memory before WIN (and before vmm32, which we'll be discussing in ‘There's a lot going on her
Unauthorized Windows 95
detail in Chapter2). There’s another copy of COMMAND.COMloaded after WIN: this is the copyin the DOSboxfromwhich we ran the MEM utility. Finally, look at the amountofavailable memory: 592K. ei
ee ee ES Fray oe Pe] eed
Figure 1-2: Running Microsoft's MEMutility in a DOS box under Windows 95 shows someof the DOSsoftware used to boot Windows. There was an AUTOEXEC.BATfile in this configuration, so COMMAND.COMwasloadedto processit.
Now, start Windows 95 without an AUTOEXEC.BAT file: delete the one-line AUTOEXEC.BATfile, boot with F5, or press F8 for “interactive boot,” and answerYto the question “Load Graphical UserInterface?” When Windows95 comesup, open a DOSbox and run MEM/C again. ‘Theresults are shownin Figure 1-3. Notecarefully what happened. By deleting the one-line dummy AUTOEXEC.BATfile, the first copy of COMMANDnolonger appears: MEMshowsthat MSDOSloaded HIMEM, IFSHLP, and SETVER,and then started WIN, which loadedthis vmm32 thing we'll look at in Chapgain, the copy of COMMANDloadedafter WIN and vmm the DOSboxfrom which we’ve run MEM/C. There’s now 601K available DOS memory: another 9K of conventional memory. So,eliminating AUTOEXEC.BATgetsrid of COMMAND.COM. But there’s a problemwith this little experiment: we had to open a DOSbox and load a copy of COMMAND.COMjust to run MEM/C.It’s obviously confusing to load COMMAND.COMinordertorun test that tries to prove
Chapter 1: Welcome to Windows 95
that Windowsdoesn’t need COMMAND.COM. We could run MEM from a PIFfile and therebyeliminate the need for COMMAND.COM. Butyou
maysuspectthatthe veryact of opening an DOSboxtorunthetest might still have someothereffect thatdistortsthe results we're seeing. It would be
a lot betterto have a Windows programthat examines DOS memory, so we
wouldn't have to open a DOSbox.
Figure 1-3: If AUTOEXEC.BATis missing, Windows 95can bootits graphical user interface without loading aninitial copy of COMMAND.COM.
The WINPSPprogramfrom Chapter 13 is perfectfor this. The PSP (Program Segment Prefix) is a real-mode DOSdata structure; every runningreal-mode DOSprogramhas a PSP, andthe real-modeaddress ofa s its process identifier. At any giventime inrealprogram’s PSP mode DOS there’s a single current PSP, and DOSperformsfile I/O and memoryallocationin the contextof this current PSP: eachfile handle is stored in a Job File Table, a pointer to whichis stored in the PSP, and each DOS memoryblockis stampedwith the PSPof its owner. WINPSP is a protected-mode Windows programthat prints out some information about each PSP, suchasits real-mode address and the name of its owner(see the WINPSP.C source code in Chapter 13 for afuller explanation). Figure 1-4 shows output from WINPSP when Windows 95 has been booted with a dummy AUTOEXEC.BAT file COMMAND.COM
is plainly visible.
Unauthorized Windows 95
Netwad Pen) feof Myo
le Heb 08S PSPs (From WCB chain): Real Nane 1293 conten ha2 win une nna? aA KR986 Windows PSPs (Fron task List): Real Prot Nane 2462 -20A7—FREECELL 210, —-266F WINGEZHT ave 2F97 LOCK 2006 120F ~—cnBa2 20cs —197F TIMER 2727 4NSF —_HSUSRUI2 450A 0R7—“KERNELS2 2151 280F WINPSP.
4 Histor)Bcvek 1072704 |Fys2tnMusictn..| greeter Game |fSiwinpse TATA
Figure 1-4: WINPSP, a 16-bit Windows program, reveals the DOS Program Segment Prefix (PSP) structures present in Windows 95. In this example, Windows 95 was booted
with an AUTOEXEC.BATfile, so COMMAND.COM is present in memory.
on BeHe DOS PSPs (Fron MCB chain Real Nane 1292 win 1361 nna? ‘ina KRM286 Windows PSPs (Fron task List): Prot Nane 2m2e 1c? FREECELL 4F77— WINBEZHT aea7 cock 120F cana 4a7F TIMER WSF wsesRua2 oRF KERNELI2
ses7
MiNPsP
2
wina2 wina2 wins2 wina2 winaz
y
ee =f Mstart| [Block 10... | Ayszba mulBFreecen G...[Siwinese
Figure 1-5: WINPSP again shows DOS PSPson a Windows95system.Thistime, however, there was no AUTOEXEC.BAT, so COMMAND.COM wasnotneededto start Windows.
Chapter 1: Welcome to Windows 95
Figure 1-5 shows WINPSP output when there’s no AUTOEXEC.BAT;
COMMAND.COMis gone. The Windowsloader, WIN.COM,hasreplaced the DOS command interpreter,COMMAND.COM: whereas COMMAND.COMwasload-
ing in at address 05F7h, WINis nowloadingin at the nearly identical address 05F9h.
Thisis great!
.--DUt Bypassing BOS, 100? Windows 95° capability to dispense with COMMAND.COMhasbeen the source of much confusion. For example, oneparticularly ill-informed writerclaimed, before Windows95 was evenin beta, that: If no reatmode DOSdevice drivers or TSRs have beenloaded in CONFIG.SYSor AUTOEXEC.BAT,Windows should be able to removeitself entirely from realmode DOS,relying on the VMM/VxDoperating system. — Andrew Schulman, Dr. Dobb's Journal, February 1994,p. 108.
Leavingaside the curiouslyinelegant phrase, “removeitself entirely from,” andthe way he hedgedhis bets with that word “should,” this writer was obviously deeply confused. COMMAND.COMis not MS-DOS; it is
merely the DOS commandinterpreter.If there’s no AUTOEXEC.BAT file, Windows 95 can dispense with COMMAND.COM,butthis hardly
means that Windows 95 candispense with real-mode DOS. Even thoughit’s well known that COMMAND.COMand the C:\>
promptare not synonymous with MS-DOS — youcanreplace them simply by naming some other program in the CONFIG.SYS SHELL=state-
ment — manypeople whodo knowthedifference between MS-DOSand COMMAND.COMnonethelesspersist in viewing Windows 95’s capability to bypassCOMMAND.COMas somehow synonymous with bypassing the real-mode DOScode. For example, respondingto a reader’s letter that took exception toits July 1994 assertion that Windows 95 is “a com-
plete operating systeminits own right,” Windows Magazine (October 1994, p. 20) offeredthe following substantiationforthis assertion:
Here's a test anyone with a Chicago beta system can perform: Renameyour AUTOEXEC.BAT and CONFIG.SYSto AUTOEXEC.OLD and CONFIG.OLD; then shut down andrestart Windows 95. It will boot back up — into Windows.Youwill see no command prompt.... That looks to me like a full-up operating system, not an “environment” that runs ontop of such a system.
Unauthorized Windows 95
Windows95°s capability to bootright into Windowsis certainly impressive. But because the C:\> promptisn’t part of the real-mode DOS kernel, this impressivefeat tells us nothing about Windows95’s status as a
“full-up operating system.” Asa final example of this persistent confusion about Windows 95’s relation to DOS, one reader of the draft manuscript for this book noted
that “Chicago ships with MS-DOS7.0, which apparently gets executed if the user has a CONFIG.SYS and/or an AUTOEXEC.BATfile
(meaningthat the user needs support for non-Chicago, DOS-based device drivers and TSRs).” Several hours of experimentation (and several beers) later, we discovered that Windows95 a/ways uses MS-DOS 7.0, and that it is nothing more (but also nothing less) than the use of COMMAND.COMthat is conditional upon the presence of AUTO-
EXEC.BAT. Windows 95’s
capability to bypass COMMAND.COMmust,in part
at least, be responsible for the popularnotion thatinthe absence of any real-mode TSRsordevice drivers, Windows 95 can “push” real-mode
DOS off the machine. For example, on page 71 in his semi-official Inside Windows 95, Adrian King (formerdirector of systems software products
for Microsoft and a darned goodwriter) says:
Windows 95is subtly different from Windows 3.1 during this initialization phase. With Windows3.1, it's up to the userto enter the win commandandstart theinitial izationof the Windows system. Windows 95 immediately gains control and switches to protected modeto completethe initialization process after loading — no win com-
mandis needed, In either case, when Windowsswitchesto protected mode,it pushesthe real modecode aside andtakes control of the machine.
Other than the capability to skip COMMAND.COM,it’s hard to
know what “pushesthe real mode code aside” means. But evidentlythis is also what computerjournalists mean whentheysay (as we've seenearlier) that “Chicago bypasses DOS andruns completely in protected mode” or that “there is no DOS hiding under Windows anymore.”
Certainlyit’s great not having Windowsresting ontop of COM-
MAND.COM. And booting Windowsright out of WINBOOT:SYS
(duh, that must be where the name comesfrom!) makesa big difference to a user’s perceptionoftheir PC. But the idea that Windows95 “pushes the real mode codeaside,” “bypasses DOS andruns completelyin protected mode,”or “shouldbe able to removeitselfentirely from real-mode DOS,” no foundation in anyversion of Chicagothathas shippedto date and
is extremelyunlikely to have anyfoundation in the final shipping Windows95 retail.
Chapter 1: Welcome to Windows 95
As stated earlier,COMMAND.COMis not MS-DOS. It is merely the MS-DOS userinterface, the provider ofthe familiar but contemptible
C:\> prompt. Windows 95 makesit possible to run Windowswithout ever
seeing a C:\> prompt. Great! But doesthis mean,as Adrian Kingputsit in Inside Windows 95
(p. 112), that in Windows 95 “if you run only Windowsapplications, you'll never execute any MS-DOS code”and that “Windows 95 finally
breaks all ties with the real mode MS-DOScode”? No,it doesn’t.
There are numerous ways to quickly see that Windows95 neither
pushes real-mode DOSaside, nor bypasses DOS,nor runs completelyin protected mode,nor breaksall ties with the real-mode DOScode, nor
removesitselfentirely fromreal-mode DOS(whatever that was supposed to mean).
For example, as a quick test you canrunthe Microsoft MEMutility
again,this time with the /D (debug) command-line option. The following wasgenerated on a pure Windows95 system, without CONFIG.SYSor
AUTOEXEC.BAT. COMMAND.COMwasn't presenteither, because MEMwas runfrom a Windows PIF file:
Addres: s
Name
Size
o0000 000400 000500
ooo4e0 000100 aa0200
900700
00360
o00A60
NSD0S
oo1F4o
10
o014e0
HIMEM AMSIXKKO. IFSHLP —-000FDO IFSSHLPS. SETVER 0002A0
Type upt Vector munication Area Communication Area system Data System Device ce ice Device device e Device Device Device Device Device Device tem Device Data em Data
Driver Driver Driver Driver Driver Driver Driver Driver Driver Driver Ori Driver Driver
Unauthorized Windows 95
SETVERKX
005e80
wspos
eo0zz0 000130 eo0cco ev0100 000200 onosro o00BA0 00040
005€00 0sF8e 006820 o06BFo 007000 eo7ece 018620
WIN WIN vmm32 vmm32 NEM eM Mspos
000080 000890 a0a0ce evoaoe 0080 0145: 08
Installed Device Driver
System Program Environment Program Environment Program Environment, Program ee
651,264 al conventional memory 651,264 able to MS-00S 622,384 largest executable program size On this purest of pure Windows 95 systems (well, except for the fact
that in order to runMEMwe'vehadto open a DOS box — but we'll get to that in a moment), MEM/D showsthat not only has DOS not been
pushedoff the machine,butit can’t evenbesaid to be hanging on for dearlife: * MEM(andthis is the version of Microsoft’s MEM utility that comes with Windows 95) refers to “IO” and “MSDOS”. WINBOOT.SYS
is the old IO.SYS and MSDOS.SYSpasted together with some new code, a fancy ray-traced logo, and a new name. WINBOOT:SYS contains the real-mode DOS INT 21h handler. To a DOS program,
Windows 95 is MS-DOS 7.0 (both INT 21h function 30h and function 3306h return 7). ° The usual DOS device drivers, such as CON, AUX, PRN, CLOCK$,
andso on,are present. Running anysort of hex-dumporstringsdumputility on WINBOOT.SYSconfirms that these device drivers are built into WINBOOT.SYS, just as in previous versions of DOS
they were built into IO.SYS. There’s also a new built-in DOS device,
CONFIGS, which works with the Plug and Play configuration manager (the CONFIGMG VxD). *
IFSHLP.SYS is a real-mode DOS device driver required bythe Windows95 Installable File System Manager (IFSMgr) VxD, which
is the foundation for 32-bit file access (32BFA), long filenames, and
Windows95°s built-in networking support. Chapter8 discusses IFSHLP.SYSin detail.
Chapter 1: Welcome to Windows 95
For now, just note that oneof the mostvital VxDs in Windows 95 absolutely depends ona real-mode DOSdevice driver: If IFSMgr cannot find IFSHLPSYS,it fails with the error message “The Microsoft Installable File System (IFSMgr) cannotfindthe helperdriver. Please ensure that IFSHLPSYShas beeninstalled.” * The MEM/Ddisplay for FILES=, LASTDRIVEs, andso onindi-
cates thatthetraditional real-mode DOSdata structures are present. A
little snooping around with DEBUGshowed,for example, that the
DOS Current Directory Structure (CDS), whose size can beset with the LASTDRIVE= command, waslocatedin this test at 049E:0000.
Andthe real-mode DOS CDS was tracking the current directory. I
knowthis because while I was using a Windows application to browse
afolder onA: called “This is a long directory nameona floppy”, I started a DOS box and used DEBUGtoexamine the CDS at 049E:0000. Sure enough, it reflected the current directory on A:
at the time the DOSbox wasstarted: vd 49e:0 049E:0000
41
3A 5C 54 48 49 53 49-53 41 4C 00 00 00 00 00
A:\THISISAl
Of course, the real-mode DOS CDS doesn’t knowhowto handle long directory(sorry, I meanfolder) names, but at anyrate the data structureis
still present and inreasonably good working order. But running MEMrequires a DOSbox; prehaps we’reseeing real-mode because we're running a DOSapplication. However,if you've ever run
Windows NTor OS/2, you knowthatyoucan have a DOSbox,and the DOSINT 21h programming interface, withouthaving real-mode DOS. So maybe what we’re seeing when we run MEMis justtheillusion of real-mode DOS. After all, if you run MEMfrom a DOS box in Windows
NT or OS/2, you'll seethis kindofstuff, too! Forexample, here’s MEM/D output from Windows NT3.1:
Address
Name
Size
nterrupt Vector ROM Communication Area D0 Communication Area
ooo0e0 ooe4a0 000500 00700
Type
10
000370 acks com LPT LPT2
System Data
ce ce ice ice tem Device n Device m Device
Driver Driver Driver Driver Driver Driver Driver
Unauthorized Windows 95
LpT3. come coms coma
Device Device Device Device
000A70
mspos
0015Co
System Data
002030
10
g1c90 ooecie 0004E0
SystemData System Program DEVICE= Installed Device FILE FCBS LASTORIVE= STACKS=
Keo HIMEM XMSKAKXO.
e3coo 004630 ae4680 04810 04990 O1BEFO GOFFFO
COMMAND msp0s COMMAND, MEM eM soos SYSTEM
000200 00090 900060 oae7D0 000950 000070 000150 000170 017550 0840F0 028000
oca000 ace180 cease acanco 001720 001780 OoFFFO
soos MSCOEXNT RED OSX 00SX spos SYSTEM
000170 9001C0 000460 008950 e080 00830 008000
8000 ER630
0
MOUSE msp0s
Environ Environment Program Free System Program
Free System Program
Driver Oriver Driver Driver
Driver
system Data System Program ee
total conventional memory available to MS-DOS st executable program size
s total contiguous extended memory 0 bytes availabl s avail M3-DOS resident in High Nemory Area It sure looksas if, here too, real-mode MS-DOS is present. Yet we
knowin the case of Windows NTthatit’s not. So maybethe samethingis
true of Windows 95. Maybe Windows95 is emulating DOS,just as NT. and OS/2 do.
In the course ofthis book, we'll see that Windows95 does emulate DOStoalarge extent. But we'll also see that this emulation is neither
complete nornew. To the large but incomplete extent that Windows 95 emulatesratherthanrelies on the real-mode DOScode, exactly the same is true of Windows for Workgroups (WfW) 3.11 with 32-bitfile access.
Chapter 1: Welcome to Windows 95
Even moresignificant thanthe strongsimilarities between Windows 95 and WEW3.11 is thefact that the technology behind Windows95’s impressive (albeit partial) emulation of DOS goesall the way back to Windows3.0 Enhanced mode,introduced in 1990 (we mightas well call it Windows 90). Although 32-bit file access is the mostvisible manifestation of Windows’ capability to emulate DOS, the seeds for 32-bit file
access and Windows 95 were sownin a well-documentedbutlittleknown VMM service named Hook_V86_Int_Chain. This book will
spenda lotof time looking at Hook_V86_Int_Chainandspinning out its implications. In 25 words orless, however, Hook_V86_Int_Chain is the chief means by which Microsoft is turning MS-DOS into a 32-bit
protected-mode operating system. Andthis has been going on, under our noses, since the debut of Windows 90 — I mean, Windows 3.0
Enhanced mode. Although Windows can emulate some DOSfunctionsin protected mode,westill need to see whether or not Windows95rests on real-mode DOS. Let's close the DOSbox andreturn to the WINPSP program shownearlier. This is a Win16 program. If “Windows 95 bypasses DOS”
and “there is no DOShiding under Windowsanymore,”this oughtto be reflected in WINPSP’s output. Butit’s not. I didn’t say anything aboutit earlier, but when we used WINPSP to showthat Windows95 can run
without COMMAND.COM, it also happenedto show thatall Windows programsrunning under Windows95 have real-mode DOSPSPs: Windows PSPs (fro Real Prot Size 1314 FFF CAB32 wins 121 «12EF 1943 no 1347 110 0707 a0a7 100 WIN32 1379-2687 WINP 110
It’s particularlyrevealing that both a Win32 programlike the Windows 95 Cabinet/Explorer (CAB32) and the Win32 kernel (KERNEL32) should have real-mode DOS PSPs. Microsoft says, “If you run only Windowsapplications, you'll never execute any MS-DOS code” — well, here we're running only Windowsapplications, but whodo you think is creating those PSPs? We'll see in Chapter 13 that DOSis creating them, and that the Winl6 KERNELis asking DOStocreate thembycalling an undocumented DOSfunction, INT21h function 55h (CreatePS his Gade hough suniesingst Riseactuallyfollawslogically Gom other well-known aspects of the Windows95architecture
Unauthorized Windows 95
* Microsoft hassaid quite explicitly that the windowing and messaging system in Windows95, even for Win32 applications, uses the Win16 USER module: “Mostof the code in the 32-bit User DLL is little
morethan a layerthat accepts 32-bit API calls andhandsthemto its
16-bit counterpart for processing” (King, Inside Windows 95, p. 148). All WM_XXXmessages, even those intended for Win32 applications, arefirst processed in the Winl16 USER module.
* The Winl6 USER messaging system in turn depends on a Win16 KERNELdata structure called the Task Database (TDB). For ‘ample, the TDBcontainsa pointerto the application message queue(see
Undocumented Windows, pp. 379-385). Eventhe mostcursory examina-
tion of Windows 95 showsthat every process — including every Win32 process — has an associated Winl6 TDB. * The TDB, in turn, depends on the DOS PSP. In his book Windows
Internals(pp. 254-256), Matt Pietrek shows that the CreateTask function in the Winl6 KERNEL calls an internal BuildPDB function, whichin turn calls INT21hfunction 55h. (PDB, meaning Process DataBlock, is another name for PSP.)
Put these three points together, and it makes perfect sense that Windows 95 depends on the DOS INT21hinterface for PSP management if
for nothingelse, and that this has nothing to do with whetheror not you run any DOSprograms. However,just because Windows 95 is making an INT 21h call does not necessarily mean that Windows95 calling the real-mode DOS code. You needto get usedto the fact that in Windows, an INT 21h call — even
one coming from a real-mode DOS program, device driver, or TSR —
isn’t necessarily handled bythe real-mode DOScode.Just because KERNELti eation routine calls INT 21h function 55h, it doesn’t necessarily mean that KERNEL calls downtothe real-mode DOS code. There are two reasons why INT 21hain’t necessarily real-mode DOS:
* Windows runs the real-mode DOScodein Virtual-8086(V86) mode. This is not a pedantic point. As seenin Chapter9, V86 modeis hardly at all like real mode. Infact, it more closely resembles IMBprotected mode. Thebest way to wrap your mind around Windows’ relationship to DOS is to keeptelling yourself that Windows runsthe realmode DOScodein protected mode. Chapter 10explains this admittedly bizarre notionindetail. ¢ Windows avoids sending most INT 21hcalls down to the real-mode DOScode (which, as just mentioned, Windows is effectively running
Chapter 1: Welcome to Windows 95
in protected mode), because these calls — whether coming from a DOSprogramrunning in a DOSbox, or from some piece of DOS software loaded before Windows, or from a Windowsapplication — are handled by VxDs.As notedearlier, the Hook_V86_Int_Chain service provided by VMM,andused by VxDs,is the basis for 32-bit protected-mode emulationofthe DOSinterface. This book spends a lotof time looking at the far-reaching implications of Hook_V86_ Int_Chain and of another VMMservice, Set_PM_Int_Vector. These serviceslet a variety of VxDs — the mostimportant being IFSMgr — keep most INT21h calls away fromthe real-mode DOScode. You'll see throughoutthis book that the DOS PSP managementservices, including functions 50h (Set PSP), 51h and 62h (Get PSP), and
55h (Create PSP), are not among those INT 21h services that the Win-
dows 95 VxDscurrently emulate in protected mode. A third-party vendor could write a VxD, using VMMservices that have beenavailable and documentedsince 1990, that does handlethesecalls entirely in protected mode. It’s interesting to ponder whethersuch an imaginary PSP.VXD, while further cutting Windows 95 off from the real-mode DOScode base, would really qualitatively change the nature of Windows95. Atanyrate, everytime youstart up an application in Windows,be it a DOSprogram, a Win16 program,or even the newest Win32 application, Windowsasks DOS (in the case of Win32, via a complicated processdiscussed in detail in Chapter 13) to create a PSP.
I don’t see anything wrongwith this reliance on DOS(incidentally,
PSP managementis just one exampleofthisreliance). But the veryidea that Windows95 doesrely on DOSis so different from what both Microsoft and the trade press have been saying about Windows95 that you surely mustdoubtthatit’s true.
Well, let’s see. Perhaps the WINPSPoutput shown a few moments agoreflects some sort of DOS emulation layer. We've alreadyseen that
the MEMutility, when run under Windows NTT, producesresults fairly similar to those that MEMproduces whenrun under Windows95. Yet we know for a fact thatWindows NT doesn’t rest atop DOS. So what
happens if we ran WINPSP on Windows NT? Perhapsevery process in NTis trotted out with some sort of fake PSP, andthe samethingis true
of Windows 95. Well, hereis output from WINPSPrunningona heavily used Windows NT3.1 server:
DOS PSPs (from NCB chain) Name
0582 e67E
COMMAND, KRNL386
Unauthorized Windows 95
Windows Real 139F 1095
PSPs (from task list) Prot Name 0857 WINPSP WOWEXEC (0387
Task oBiF O3AF
Size 220 220
Yes, a few Win16 tasks in NT do have DOS PSPs. But meanwhile, running Microsoft’s PSTATutility from the Win32 NTSDKshowsthat overthirty different processes are running, including CSRSS (Client Server Runtime Subsystem,whichservices windowand graphics requests), LMSVCS(redirector), SFMSVC (File Server for Macintosh), SFMPRINT(Print Serverfor Macintosh), MSGSVC(Messenger), NETDDE,and RASMAN(Remote Aci ss Connection Manager): C:\WINNT>pstat | find "pid" p pris 0 (null) P pri: 8 (null) prizll SMSS.EXE prizl3 CSRS . EXE priz13 WINLOGON. prizl3 SCREG.EXE LSASS.EXE pri:10 f pri: SPOOLSS.EXE pri: 7 EVENTLOG. EXE priz 7 LMSVCS.EXE pri: NETDDE. EXE (null CLIPSRV. EXE SFMSVC. EXE SFMPRINT. EXE (nut NSGSVC. EX RASMAN. EX ups.EX! RASSRV, EXE NDDEAGNT EXE 3 PROGMAN. EXE NTVOM. EXE PRINTMAN. EXE OS2SRV.EXE 05255. EXE D. EXE NTBACKUP. EXE WINFILE. EXE CMD. EXE pid: 105 pid: d4 pri 7 PSTAT. EXE
Noneoftheseservices showed up in WINPSP. Well, why would they? Whywould Win32 services in the NToperatingsystemrequire real-mode DOSPSP: ? Obviously, they don’t. Equally obvious, I hope, Win32 pro es in Windows95 do require real-mode DOSPSPs.
Chapter1: Welcome to Windows 95
What we'releft with, then, is that Windows 95 can dispense with
COMMAND.COM,purveyorofthe nasty C:\> prompt.Thisis terrific. A Windows 95 machine can boot right into Windows without a CON-
FIG.SYS orAUTOEXEC.BAT.Fantastic! But is this what everyone meanswhentheysay that Windows 95 “doesn’t require DOS”? It would appearso. We'll soon see thatWINBOOT.SYScontainstheold real-mode DOS code, and that Windows95 calls down to this code quite frequently (albeit in V86 mode which, you'll recall, you need to keeptelling yourself
is really protected mode). Now, the VxD layer in Windows 95 does handle
most INT21h calls entirely in 32-bit protected mode, withoutcalling
DOS. This, too, deserves two andpossibly even three cheers. But 32-bit file access in WfW3.11 did the same thing and met with considerably less fanfire than Windows95. In fact we'll see in Chapter8 thatthe trade
press generallycomplained that WfW3.11’s “bypassing DOS”for 32BFA
was somesort of bug that causedall sorts of DOS compatibility problems.
So what could the “Windows95 completely bypasses DOS”claim
possibly mean?
Perhapsit simplyrefers to the packaging of Windows95. For example, the Microsoft Windows “Chicago” Reviewer's Guide (p. 275) says “Chicagowill be a complete, integrated protect-mode operating systemthat does not
requireoruse a separate version of MS-DOS.” Note Microsoft doesn’t say
that Chicagowill not require or use DOS. Microsoft says Chicago won't
requireoruse a separate version ofMS-DOS. Perhaps Microsoft is just
telling us that all the functionality formerly associated with MS-DOSwill
now be broughtout under the Windows brand name.If everything formerlythoughtto be part of MS-DOSisby executivefiat now part of
Windows, then the “you'll never execute any MS-DOS code”claim makes
sense, I suppose.
Why Bother Retuting Microsott's Claims? Thadn’t intendedto spendsolongherelooking at DOS PSP usagein Windows 95. Thisis just one part of the Windows95 architecture. However, the contrast between Windows 95% true relationship with DOSand Microsoft’s claimsthat Windows 95 bypasses DOSis representative of Microsoft’ more general claims about Windows 95. For example, Microsoft alsoasserts that the Win32 kernel, KERNEL32.DLL,‘is completelyindependentofits
Unauthorized Windows 95
16-bit ally. There is some communication fromthe 16-bit side to the 32-bit
side, but the 32-bit Kernelnevercalls across to the 16-bit side” (Inside Win-
dows 95, p. 148). As with theassertions regarding Windows95°s independence from DOS,this one regarding KERNEL32% independencefromthe Win16 kernel (KRNL386.EXE)is quite far fromthetruth. Thepoint hereis not to poke holes in Microsoft's claims for Windows 95. Few adults expect “truth in advertising,” even whenthis advertisingis packaged as technical documentation, architectural descriptions, or industry white papers. It would be pointless to expect readers to wade through a 500 page refutation of Microsoft’s marketing hype and its reflection in the computertradepress. Instead, bytaking a good hardlookatjust a fewof these claims, which we'll visit and revisit fromseveral different angles throughoutthis book, we'll get a good idea of how Windows 95 works, and howit’s different from andsimilar to previous versions of Windows and MS-DOS. An in-depth examination ofa fewselected aspects of Windows 95 — particularlythe relationship of Windowsto DOS,and of the Win32 kernel to the Win16 kernel — will illuminate manyaspectsof the product,
such as Windows’ poorly-understood VMM/VxDlayer, the Win32 API,
thunking, 32-bitfile access, executable loading, and memory-mappedfiles. If we ask just a fewveryspecific (maybeevenoverlyspecific) hard questions about Windows 95, perhapsin the end somesort of architectural overviewwill emerge. It might notbeas ordered or coherentas Microsoft's architectural overview, but it might have the benefit of accuracy.
Those Ubiquitous Microsott Diagrams Such a focusedexaminationis a goodalternative to the usual look at Microsoft-supplied architectural diagrams, which have an unfortunate tendency to induceeithersleep or a state known asMEGO(“my eyes
glazeth over”).
Atthe same time, I guess we'd better take a moment to look at two of
these diagrams.I’m sure you’vealready seen themor somethinglike them because they appear, moreorless as stamped-outboilerplate, in nearly
every computer magazinearticle on Windows 95. However,it’s worth
actuallyexamining and pondering these diagramsfor a few moments because the tendencyof most people (certainly, my tendency) on encountering one of them in a magazineis tojust let the soothing waves of tech-
nologicalbliss inducedby those arrows and boxes washover you. Such
Chapter 1: Welcometo Windows 95
diagrams, in other words, are largely a “feel good”exercise, meant to induce a feeling that the software has been designed — as opposed to what is morelikely, that the software “just grew.”
Figure 1-6 showsthefirst Microsoft diagram. This diagram seemsto be appearing everywhere, like some software-engineering formof kudzu. (The samediagramappears verbatim in Windows Magazine, July1994,
p- 187; with a prettier presentation butthe same content in PC Magazine, April 12, 1994, p. 193; and with a very prettypresentation but the samecontent in PC World, August 1994, p. 134.)
Ring 3 (System VM) Win32®
8PP_|Isyswemsrviceny
as
Wind2®))
Lo?
Kemet.
graphics
Wind2e]} Window igme
oy
NMI® ‘*pP
(MS-DOS
(MS-DOS
——__
VM)
VM)
Wels
Ring}
Bie
app
app Ring 0 Protect-modefile system VFAT, CDFS, SCSI, Network
Virtual Machine Manager Pager, Scheduler, DPMI server
Figure 26. Chicago's Integrated Architecture for Running MS-DOS.. Win16-, and Win32-based Applications.
Figure 1-6: Microsoft's boilerplate diagram ofthe Windows 95architecture Now, Microsoft’s owncaption for this diagramis little different from
the one I’ve supplied. Oneplace this diagramappears is in the Microsoft
Windows “Chicago” Reviewer's Guide (May 1994), a compelling andwellwritten 300-page documentMicrosoft has madepublicly available (and, quite deliberately, without any copyright notice, which meansthat in the next six months weshould see about 20 books published containing a largely-recycled regurgitation of Microsoft's Windows “Chicago” Reviewer's
Guide). There, Microsoft’ caption (p. 59) is “Chicago's Integrated Architecture for Running MS-DOS-, Win16-, and Win32-based
Applications.” We'regoingto have to comebackto this “integrated”phrase, because it’s a tremendouslyimportant part of the hype surrounding — sorry, I
meantechnical documentation regarding — Windows 95.
Unauthorized Windows 95
In the meantime, there’s one verynoticeable feature of this diagram: MS-DOS is missing. Now, the diagram does show two DOS boxes, but
I'm referring to MS-DOS itself,or, if you prefer, WINBOOT.SYS.
Whereis it? I hope Microsoft (and those whorecycle its artwork) isn’t suggesting that WINBOOTisjust for booting Windows(200Kis a lot of bootstrap code), and thatit somehowdropsoutofsight (or perhaps
is pushed aside) when Windowsstarts up. I hope the output from MEM
presented earlier showed that the real-mode WINBOOT.SYScode (which Microsoft’s own MEM programpersistsin calling IO and MSDOS) is still in memory while Windowsis running. So where’s WIN-
BOOTin the diagram? Similarly, where’s IFSHLP.SYS (which, as
notedearlier, is a real-mode DOS device driver that is required by the IESMgr)? These important V86-mode componentsare conveniently absent from Microsoft’s architectural diagram. Of course, a diagramis an abstraction. It cannot, and should not, show
every detail. A lot of otherthings are also missing fromthis diagram: at Ring 0, there’s no mention of the crucial hardware-related VxDs such as VPICD, VDMAD, VKD, VDD, VMD, and VTD(that’s Virtual Pro-
grammable Interrupt Control Device, Virtual Direct Memory Access Device, Virtual Keyboard Device, Virtual Display Device, Virtual Mouse Device, and Virtual Timer Device). There’s no mention of the DOSMGRor SHELLor VWIN32 VxDs; VWIN32 in particular plays an
absolutely vital role in Windows95. Nor does the diagramshowthatthe
System VM rests atop 16-bit Windowsdevice drivers(totallydifferent from VxDs), such as KEYBOARD, MOUSE, DISPLAY,or SYSTEM.
Butobviously there’s only so much that canbe crammedinto a single
diagram without inducing morethan the intended amount of MEGO. Still, I think the omission ofWINBOOT, aka MS-DOS, fromthis
diagram is significant. Notonlydoes Microsoft intendto convince end users that DOS is gone and that software on a Windows 95 PC has been
stampedoutin onepiece like an integratedcircuit, but also to convince developersofthesamething. Programmersare people too, andthey wanttofeel good aboutthe operating system theydevelopfor. So
Microsoft will let developers feel good byshowing themlots of pretty diagramsin which MS-DOS has been wishedaway.
Thesecondboilerplate diagram is shownin Figure1-7. It too appears
to have become industry standard in the computertrade press(see, for
instance,the verbatim copyin Windows Magazine, July 1994, p. 186) and
comesfrom the Chicago Reviewer's Guide.
Chapter 1: Welcome to Windows 95 debug u 19:40f8 clr 0019:40F8 FA 6Ch is max DOS function in 00S 6 CHP AH,6C 0019:40F9 B0FC6C JA 4000 ii; 1f more than 6Ch, error 0019:40FC 7702 CNP AH,33 80FC33, 0019:40FE JB 4118 7218 e019: JZ 40A7 0019:4103 7442 CHP AH,64 BOFC64 0019: JA 4118 mu 0019: 2 40 0019:410a 7485 CMP AH,51 333 Get PSP 0019:410¢ 80FCS1 JZ 4085 0019:410F 7444 3; Get PSP CHP AH,62 0019:4111 BoFCEZ JZ 4085 0019:4114 74 33 Set PSP CHP AH,S@ 0019:4116 B0FC50 JZ 4049 @019:4119 74 Wecanreadilysee that the two DOS Get PSP functions (51h and 62h) are both handled at 0019:40BS in this configuration and that the Set PSPfunction (50h)is handled at 0019:40A9. Let’s look at the real-mode DOScodefor these functions: u 19:40a9 0019:40A9 1E 0019: 40AA 2E 0019:40A8 BE1EE730 0019:40AF 89163003 0019:4083 1F 0019:4084 CF u 19:40b5 0019:4085 1E 0019:4086 2E 0019:4087 BE1EE730 0019:4088 88163003 40BF 1F 9:40C0 CF
PUSH DS. cs: MOV DS,[30E7] MOV [0330],BX POP oS TRET PUSH DS. cs: MOV 0S,C3DE7] WOV 8x,£0330) POP 0S IRET
try look at 21/50 (Set PSP) 54 get DOS OS out of DOS CS :;; put new PSP into D0S:[330h] sry look at 21/51,62 (Get PSP) i+; get DOS DS :; urn D0S:330h) in Bx
Chapter 1: Welcome to Windows 95
Thisis the code that’s executed whenever a programrunningin realmode DOSsets or gets the current PSP. We cansee that the codeis quite simple: setting the PSP involves nothing more than rammingthe caller’s BX into a variable at offset 330h in the DOS data segment, and
getting the PSPinvolves nothing more thanreturningthe value ofthis
samevariable. Offset 330h in the DOSdata segment happensto beoff set 10h in the Swappable Data Area (SDA), a DOS data structure that all
versions of Windows Enhanced mode, including Windows95, declare as instance data (see Chapter 4).
Now,the question is whetherthis same codeis also part of Windows
95, and moreimportantly, whether it plays any role in Windows 95
beyond that necessary for compatibility with real-mode DOS programs anddrivers. Let’s first verify whetherit’s in Windows95at all. The easiest way to do this is to ran INTCHAIN and DEBUGagain,this timeinside a
Windows 95 DOSbox (yes, we'll get rid of the DOSboxin just a minute): C:\UNDOCDOS>intchain 21/6200
73h is max DOS function in Windows 95 more than 73h, err:
02 B0FC33
2 Get PSP cl ae CHP AH.62 2 41fB
Set PSP 3: Get PSP 33 JZ OZ 4IAL
‘This is nearlyidentical to the MS-DOS6.20 code, except that Windows 95 supports INT 21h functions upto 73h. Now let’s see what the DOS Get/Set PSPfunctionslook like in Windows95: u 74834195 074834 0748:41 0748:4197
ti look at 21/50 (Set PSP)
t DOS DS out of DOS cS:
Unauthorized Windows 95
0748:4198 89163003 0748:419F IF 0748:4140 CF
MOV (03301, Bx POP 0S TRET
u 748:41A1 0748:41A1 1E 0748:41A2 26 0748:41A3 BE 0748:4147 BB1E 0748:41A8 LF 0748:41AC CF
put new PSP into 00S:[330h] at 21/51,62 (Get PSP) SDS urn 00S:[330h] in 8x
Notsurprisingly, this is nearlyidentical to the DOS 6.2 MSDOS.SYS implementation. Alittle poking around with DEBUGshowsthatin Windows95 this DOS code is part of theWINBOOT.SYSfile:
C:\windows>debug \winboot.sys s 0100 ffff fa 80 fe 73 1E73:£8C -u 1e73:e8¢ 1E73:E8C1 FA CLI 1E73:£8C2 80FC73 CMP AH 1E73:£8C5 7702 J 80FC50 93
Wecouldlookat the code for some more INT21h functions, butthis should besufficient to establish that the same real-mode DOScodethat previousversionsofthe operating system stored inMSDOS.SYS, Windows 95 stores in WINBOOT:SY: Sothe real-mode DOS codeis part of Windows 95. I’ve run the above
tests from a DOSboxinside Windows,soit’s obvious that thisWINBOOT codeis used for more than just booting Windows andis not“pushed aside”
by Windows. The name WINBOOT is therefore somewhatmisleading, becauseit seemsto suggest that the code’s only purpo: is to boot Windows.
In fact, WINBOOTSYSplays a much largerrole in Windows 95. For example, a Microsoft document on Plug andPlayrefers in passing to “the real mode operating systemkernel,” andthis is a goodway of describing
WINBOOTSYS: it’s the real-mode portion of the Windows95 kernel. It’s odd thatall mentionofit should be so conspicuouslyabsent from the Microsoft documents and diagramsintendedfor a wider audience. How
Chapter 1: Welcome to Windows 95
come WINBOOT.SYSdoesn’t showup in Figure 1-6? You’dalmost get the impression that Microsoft is embarrassed aboutit. Thatisn’t a verynice wayto treat a piece of codethat has earned Microsoft billions of dollars. So we knowthat Windowsdoesn’t push WINBOOTaside; WIN-
BOOTis presentfor the duration. But even though WINBOOTsticks around to handle certain DOScalls in certain circumstances, on the other hand these tests were conducted from a DOS box, in which we
ran the real-mode DOS DEBUGprogram. Although what we’ve seen already raises questions about the absence ofWINBOOT.SYSfrom
Microsoft's diagrams,it is perhapsstill consistent with one theory, which
is that Windows95 only uses the real-mode DOS codefor compatibility with DOSprograms. As pointed outearlier, there is no necessary connection, one wayor the other, between MS-DOSandtheability to run DOS programs. MS-DOSmightbe necessary to support the needs of non-DOS(for
example, Win16 and Win32) programs. Onthe other hand, you can
also have real-mode DOSprogramsrunning on an operating system other than DOS, as long as that operating system emulates the INT 21h interface. We'll see in later chapters that, for many DOS funetions, both Windows 95 and WFW3.11 are perfect examples of such
an operating system: with 32-bit file access, even INT21h calls coming from real-mode DOSsoftware are in many cases handled in 32-bit protected mode. So the idea that DOS musthangaroundto support the running of DOSprogramsis prettyridiculous. However, the assumedassociation between MS-DOS and DOS compatibility, while
fallacious, is so widely accepted that for the sake of argument we'd better temporarily acceptit. Okay, then, here’s the question rephrased: To whatextentis the realmode DOScodepresent and operational in Windows 95, when running only Windows (Win16 and Win32) applications and when Windows 95
has been booted without CONFIG.SYS or AUTOEXEC.BAT? There are no DOS boxes, nospecial real-mode drivers or TSRs: Is the DOS
codestill part of Windows 95? And, if so, what role does DOSplayin a “pure” Win32 system? Take the code that was shownearlier, where WINBOOT(nee MSDOS) handles INT 21h function 50h: If this code is ever executedin a
pure Windows95 system — if a debugger breakpointonthis codeis ever triggered — Windows95 uses the real-mode DOScode andthat’s that. Tt turns out, even whenonly running Win32 applications in Wi ne
dows95, this real-mode DOScodeis executed. Using Nu-Mega’s superb
Unauthorized Windows 95
Soft-ICE/Windowsdebugger (which Microsoft distributes with the Windows 95 Device Driver Kit), I placed a breakpoint on the WINBOOTSetPSP code:
bpx 8748:4195
Even when running only Win32 applicationssuch as the Cabinet/ Explorer, WinBezMT,and Clock, this breakpoint wastriggeredso frequentlythat I couldn’t actuallydo anything in Windows 95 until I changed the breakpointto onlytrigger every 50 times bpx 8748:4195 c=50 Even so, Soft-ICE/Windows still popped up sofrequentlyI could onlystand to run this test for few minutes. Again, this was on a “pure” Windows95 system only running Win32 applications.I didn’t start a
DOSbox,and I didn’t evenstart any Win16 applications. There were no real-mode device drivers or TSRs installed. Ah, butI did run the Soft-ICE/Windowsdebugger, though. This loads before Windows,and thus appears to Windowsto be something like a TSR. Since WINBOOT.SYSwantsto jumpdirectly into WIN -COM, L used F8to do an interactive boot, declined to load the graphical
userinterface, and from the C:\> prompt loaded WINICE, which in turn loads WIN.COMand the Windows GUI. Thus,this doesn’t look
like such a pure Win32 systemafterall. As with Werner Heisenberg’s
hypothetical “gamma-ray microscope,” the mere use of which changes what’s underthe microscope,it’s conceivable that the very presence of Soft-ICE/Windowsis
somehow causing Windows 95 to pass INT 21h
calls down to the real-mode DOScodeinsideWINBOOT.SYS,andthat Windows 95 wouldn’t be calling this real-mode DOScode were the debugger notpresent.
Well, this is certainlya plausible concern. Let’s use one more program,then,to show up the Windows-DOSrelationship. Here’s a review
of what we’ve done so far:
* We've used a DOS boxtosee that Windows95rests atop DOS, then
decided that the DOSbox might be influencing the outcome;
* We've used a Win16 application, onlyto decide that Windows 95 might simulate DOSthe same way NTdoes;
* We've used a debugger and decidedthat the debugger acts as a DOS TSR, theverypresence of which might cause Windowsto send down to real-mode DOScalls thatit otherwise would not send down.
Chapter 1: Welcome to Windows 95
Having gonethroughallthat, let’s turn to onefinal(atleast for this first chapter) demonstration of the Windows-DOSrelationship in Windows 95: WLOG?212F is a Win16 program thatlets us see which INT 21h and 2Fhcalls are generated on the Windowssideofthe fence, and
then see which ones pop up onthe V86side of the fence. By counting the numberofcalls to each INT 21h and INT2Fh function generatedin Windowsand comparing this with the numberofcalls seen down in V86 mode, WLOG?212F provides a good idea of whichcalls a given Windows environment such as Windows 95 or WEW3.11 passes down to V86
modeandwhich onesit emulatesin protected mode. Figure 1-8 shows WLOG?12F running in Windows 95. Onthe Windowsside, WLOG?12Finstallsits hooks with the DPMI
Set Protected ModeInterrupt Vector function (INT 31h function 0205h) and with an undocumented WindowsAPIcalled GetSetKernelDosProc (see Chapter 13). Thoughit can see calls down in V86 mode, WLOG212F
contains no real-modecode and does not employ a DOS box. WLOG212F creates its V86-mode hook with another DPMIfunction, Allocate Real Mode Callback Address (INT 31h function 0303h), andinstalls it with Set
Real ModeInterrupt Vector (INT 31h function 0201h). For example, in the following fragment of WLOG212F output, an
INT21h handlerinstalled with GetSetKernelDosProc has encountered 15 calls to INT 21h function 0 (Exit). However, the V86 mode hook saw no calls to this function (WLOG?212F showsblank white space instead of
the numberzero), so WLOG?212F decides the call is emulated in protected mode, rather than passed down to V86 mode:
INT 21h Func ooh
Prot mode
KernelD0SProc 15
86 mode
Emulated
Reasonable enough.It turns out that the Winl6 KERNELcontains an INT21h handler which, among manyotherthings, changescalls to the obsolete function 0 intocalls to the newer function 4Ch. This, too, is
reflected in the WLOG212F output: INT 21h Fune Prot mode KernelD0SProc V86 mode 4ch 15
Passe down
Why did WLOG212Fdecide that function 4Chis “Passed down”? Because its V86 mode INT 21h handlersaw atleast as manycalls to this functionasdid its protected-mode INT21h handlers (which,in fact, saw no suchcalls). Perhaps the WLOG212F output for the DOS Get Version functionwill makethisclearer:
Unauthorized Windows 95
fa
TOCTL (INT 21m Function sun): Prat mode Kerne2DOSProc
U86 node Enulated 66 Passed down Enulated
Figure 1-8: The WLOG212F program (running here alongside some Win32applications under Windows 95)counts INT 21h and(not seen here) INT 2Fh calls generated in protected:mode Windows, and comparesthesewith the numberofcalls sent down to V86 mode. If a call is seen in protected mode but not in V86 mode, WLOG212Findicates that thecall is “Emulated.” Onthe otherhand, if at least as many calls are seen in V86 mode as were generated in protected mode, WLOG212F indicates thecall is “Passed down.” NT 2th Func 30h
Prot mode 0
KernelD0SProc 33
V86 mode 33
Passed
an
Here, the KernelDosProchandler (see Chapter 13 for a full explanation of GetSetKernelDosProc) saw 3 DOS Get Versioncalls, and so did
the V86 mode INT21h handler. Thus,at least in this situation, Windows passesall calls to this function down to V86 mode.Simple, eh? T'll discuss the implementation of WLOG212F a little later in this chapter (and theWLOG212ECsource code is provided on the Unauthorized Windows 95 disk), but first let’s examine the output from WLOG212F andsee what it can tell us about the Windows-DOS relationship in Windows 95. It’s important to note that, according to Microsoft, the behavior
revealed by WLOG212F neverhappensin Windows95, or only happens
in the presenceofspecial real-modedrivers for which there is no currently
available protected-modereplacement. According to King’s authorized Inside Windows 95 (p. 79):
Windowsapplications on Windows95neverusevirtual 8086 mode. They executein protected modeall the way downto the bare hardware.
Chapter 1: Welcome to Windows 95
We're about to run some Windows applications in Windows95, and
WLOG212F will showthat theyfrequently use V86 mode. Ah,but the
categorical statementwejust saw is qualified with a footnote (King, Inside Windows 95, p. 79n):
This isn't strictly true since Windows 95still runs MS-DOSdevice drivers in virtual 8086 modeif there's no protected modedriveravailable. But real mode drivers are an endangered species This qualification doesn’t applyhere, though, because the following WLOG?12F output wasproduced(in Windows95 Beta-1 from May 1994) without CONFIG.SYS, AUTOEXEC.BAT, COMMAND.COM,
or a DOSbox. Since Beta-1 didn’t ship with VxDsto support Microsoft's DoubleSpace disk compression — and thus the MS-DOS DBLSPACE
-BIN driver wouldfall into King’s “endangered species”list — it’s important to add thatthis system wasn’t using disk compressioneither. On this
pure-as-the-driven-snow Windows 95 system,then,I ran Microsoft
Office 4.2, plus other parts of the Windows operating system,such as the
Explorer, and the WinBezMT and Clock Win32 applets, and, of course, WLOG2102Fitself. Here’s part of the WLOG212F output:
INT 21h Func ooh eh 19h 1Ah 1h 25h 2ah 2ch 2Fh 30h 32h 35h 36h
Prot mode 189 228 18 7 7 0 1 2 p
13410 1 20 330 6313 5182 33 7 10 6
5555 11538 33
ed down down Emulated Enulated Emulated Passed down Passed down mulated Passed down mulated emulated Emulated
Ratherthanboreyou with the entire output from WLOG?12K it makes more
sense tolook at just a few ofthe emulatedcalls, and then
focus onthe calls labeled as “Passed down.” But youcanalreadynotice
that,in this test under Windows 95 (where, you'll recall, Windows appli-
cations supposedly neveruse V86 modeunless some unusual real-mode driveris loaded), the V86 mode INT21 handleris seeing somecalls. In the case of function 2Ch (Get Time), for instance,it’s seeing a tonofcalls.
Unauthorized Windows 95
In the almost 15 minutes that WLOG212F was running, its protected-
mode INT21h handler saw almost7,800calls, its KernelDosProc handler saw over80,000calls, and its V86 mode handler saw over 26,000calls. Inthis particulartest, in other words, almost one-third of the INT21h calls from Windowsapplications ended up going down to V86 mode. In a Windows95 systemsuch as this with no CONFIG.SYS, no AUTO-
EXEC.BAT,noreal-mode DOSdrivers (otherthan the ones that Windows95 requires and loads itself), no TSRs, no DOS box, no nuthin’
except Windowsapplications,this is not supposed to happen. ‘Theonlyexplanation I can think ofis thatWINBOOT.SYSitself needsto be considereda real-modedriver (thoughyou'llrecallits conspicuousabsence from the Microsoft diagram), and thatpartofthis driver (such as Get Time) qualifies as functionality for which “there’s no
protected modedriveravailable.” In other words, no one happensto have written a VxD to replace the parts ofWINBOOT.SYS(such as the Get ‘Timefunction)thatarestill employed by Windows95. This wouldbe a quite reasonable statement — the CURRDRIV.386 and INTVECT.386 examples in Chapter 8 demonstrate how the Hook_
V86_Int_Chain service provided by VMMmakesit easy to write VxDs to handle INT 21h functions in 32-bit protected mode
but I’mpretty
sureit’s not what Microsoft or the trade press have in mind whentheysay that Windows 95 doesn’t require DOS.Foronething, if this is all that
the hooplasurrounding Windows 95°supposed liberation from DOS
really means, then the samestatementcould, and should, have been made years ago, when Windows first acquired a VMM that provided a Hook_ V86 _Int_Chainservice. The implementationof that function, and not
its apparently more extensive use in Windows95, wasthe real watershed in Windows’ relation with DOS. If Windows 95 is a genuine operating
system, then so was Windows3.0 Enhanced mode,in which
Hook_V86_Int _Chain first appeared.
As notedearlier, if WLOG212F seescalls to a function on the Win-
dows side but nocalls to this function down in V86 mode, the program decidesthat,asfar as it cantell, the function has to be emulated. For example, here’s what WLOG?212Fshowsfor the Open (3Dh), Close (Eh), Read (3Fh), and Write (40h) file I/O calls in Windows 95:
Func 3Fh 40h
rot mode
—KernelD0SProc 698 1320 10816 1817
86 mode
Emula Emu Emul Emu
Chapter 1: Welcome to Windows 95
WLOG?212F shows that Windows 95 handles these crucial INT 21h functionsentirelyin protected mode. Thisis pretty amazing. Don’tlet our
focus onthesituations in which Windows95still calls down to DOS detract in any way from thefactthat, for many key DOS functions,it
doesn’t call down to DOS.Infact, the whole point of my harping onthe cases where Windows95 still calls down to V86 mode DOS is to heighten
yourappreciation for those cases whereit doesn’t. By assessing Windows
95° relation to DOS onafunction-by-functionbasis, rather than by
uncritically parroting Microsoft's claims that Windows 95 runs Windows applicationsentirely in protected mode, mypraise for Windows95 will actuallycarry some weight.
Whether Windows 95 emulates or passes down an INT21h function is not an exclusive either/or choice, of course. Sometimes WLOG212F's
protected-modehandlers see morecalls to a function than doesits V86 mode handler, yet the V86 modehandlerstill sees somecalls. In this case,
WLOG212F just displaysthestatistics without any commentary. A good example is the DOS IOCTL (I/O Control) function: Fune
44h
Prot
mode
338
KernelDOSProc
7112
V86
mode
23
TOCTL function 44his really an umbrella for a large numberof subfunctions. I wassufficiently curious about Windows 95’s IOCTL handling that I hadWLOG212F break the function 44h results out by subfunction:
Fune ooh ash
Prot mode 338
Kernel D0SProc 34
86 mode
Eh
Emulated Emulated Enulated
Function 4409h is the Check if Block Device is Remote request. We
cansee that, onceina blue moon, Windows95passes this request down to V86 mode. Now, DOS itself handles IC
driver request packets
thatit passes
‘L calls by creating device-
to the Strategy andInterrupt routine
ofthe appropriate real-mode DOSdevice driver. So it’s possible that the
32-bit protected-mode code in Windows 95 for INT 21h function 44his
doingthe same thing.WLOG?12F onlyspies on INT21h and INT
2Fh, andwon'tsee any far calls that Windows95 VxDs might be making to DOS devicedrivers. As notedearlier, thisWLOG. 212F test was run in a Windows 95 configuration without a CONFIG. SYS andhence without any user-
Unauthorized Windows 95
installed DOS device drivers. But ofcourse therearestill the DOS
device drivers that are built into WINBOOT.SYS(such as COM1,
COM2, LPT 1, LPT2, CLOCKS, CONFIGS, andsoon), there’s the SHLP$ driver installed by IFSHLP.SYS, there’s HIME)
XMSXXXX0driver, and there’s SETVER.EXE’s SETVERXXdriver. You’d expect that some IOCTLcalls would have to be handled by pass-
ing themto the appropriate DOS device driver, even one built into WINBOOTSSYS.Indeed, a debugger breakpoint, placed for example on the commonStrategy routine sharedbythe built-in DOSdevice drivers, is triggered under Windows95. Finally, we come to the INT 21hfunctions for which WLOG212F's
V86 hookseesat least as manycalls as did its protected-mode hook. WLOG212F labels these functions as “Passed down.” I hope you’ve already been convinced that, contrary to Microsoft’s claims, Windows
applications running under Windows 95 do use V86 mode,so we can
move onto the moreinteresting questions about when and why and under whatcircumstances Windowsapplications in Windows95 still use V86
mode.I’ve edited theWLOG?212F outputbelow, replacing the “Passed down”string with the nameofeachfunction: INT 2h: Func de eh 189 Set Drive 19h 228 i 7 2ch 7 30h 10 45h 226 4ch 50h 5th 1 1 55h 15 15 5 Sah 3 3 3 65h 2 2 Internationa och 3 3 Novell NetWare Get Station Num
Now, perhaps you feel that the onlyreason Windows95 is passing these calls down to V86 modeis because my V86 modecallbackis installed. (The Heisenbergeffect rearsits ugly head again!) Butifthis is the case, how come Windows95 is so darnedselective aboutit? It doesn’t send my V86 mode callback any file I/O calls, for example. Surely if WLOG212F's V86
modecallback were responsible for these passed-downcalls, then all INT 21h calls would show upas passed down.
Chapter 1: Welcome to Windows 95
JUST One Little callback You might worry that it's a self-fulfilling prophecy for WLOG212Fto use a V86 modecallback INT 21h handlerto test whether Windows programsin Windows 95ever use V86 mode. Let's consider howthis callback is installed. The WLOG212F.C source code ondisk contains the following function: INTRFUNC GetSetRealInt(int intro, INTRFUNC new, INTRFUNC *pcallback, RMODE_REGS **pregs) INTRFUNC old: if (Cold = _dpmi_get_rmode_vect(intno)) != 0) ( RMODE_REGS *regs; INTRFUNC cal if (1 (regs = (RMODE_REGS *) calloc(sizeof(RMODEREGS), 1))) return (INTRFUNC) 0: if (1 (callback = _dpmi_alloc_rmode_callback(new, regs))) ( free(regs); return (INTRFUNC) 0; i _dpmi_set_rmode_vect(intno, callback); callback *pcallback *pregs = regs; ) return old;
The _dpmi_xxx functionscalled by GetSetRealint are simple C wrappers aroundthe equivalent INT 31h calls; in particular, _dpmi_alloc_rmode_callback is a wrapper around INT 31h function 0303h (Allocate Real ModeCall-
back Address). To assess what possible Heisenberg-like impact WLOG212Fcould have on Windows 95’srelationship with DOS,we need to understand this DPMI function.
The DPMIserver in Windows 95, asin previous versions of Windows Enhanced mode,is provided by VMM. Manyof the DPMI INT 31h functions
are themselves mere wrappers around VMM functions. This means that,
under Windows, DPMI can be seen as a wayto call certain VMMfunctions that are otherwise directly callable only from a VxD. DPMI function 0303h, which WLOG212Fusesto create a protectedmode handler for a V86 modeinterrupt, is based on a VMM service called Allocate_V86_Cail_Back. A V86callback is a small piece of code (a very
small piece — one byte) that, when called in V86 mode, thunks up to 32-
bit protected mode. By allocating a V86 callback and then installing the addressofthis callback as the V86 mode INT 21h handler, WLOG212F forces all V86 mode INT 24h calls to thunk into VMM, which passes the
call to WLOG212F.In other words, the effect of WLOG212Fis to takea call that has already appeared in V86 mode, and ship it over to protected
Unauthorized Windows 95
mode. There’s no wayit can cause thecall to appear in V86 modein the first place. Even without WLOG212F,the INT 21hchain already contains some V86 callbacks.In particular, the IFS$HLP$ device uses a V86 callback to communicate with the IFSMgr VxD, and this callback is active even when no DOS programsare running. Calling the GetOpenFileName commondialog triggers the IFS$HLP$ V86callback, for example. ‘As shown by the WINBP program in Chapter 8, literally hundreds of these V86 call backs are active in any Windows system. These V86callbacksare constantly triggered, even on the purest Windows 95 system. If Windowsapplications never execute any V86 modecode, whyis the documented V86 callbackfacility used so heavily in Windows 95, even when you're only running Windowsapplications? Here's anotherinteresting thing about DPMI function 0303h:in a sample program that shows how to use this function, the DPMI specification (version 1.0, March 1991, p. 37) contains a commentthatis both wrong andenlightening; this commentgets to the rootofthe confusion surrounding INT 21hhandling in Windows: Thefollowing code...hooks the DOS Int 21h and retums an error for the delete file function (AH=41h). Othercalls are passed through to DOS.This example demonstrates the techniques used to hook a real modeinterrupt. Note that since DOScalls are reflected from protected modeto real mode,thefollowing codewill interceptall DOS calls from both real mode and protected mode. Note the blanket assertion here that “DOScalls are reflected from protected mode to real mode,” asif this were some by-definition inherent property of protected-mode DOScalls. But every “Emulated”line output by WLOG212Fdisproves this assertion. A DOScall generated in protected modeis sent to V86 mode only if the DOS extender decides to sendit to V86 mode. More thanthis, in Windows even a DOScall generated in V86 mode(for example, by a program running in a DOS box) is sent back down to V86 modeonly if a VxD decides to sendit back down to V86 mode. Again, there is no inherent connection between INT 21hcalls and MS-DOS. Actually, this confused notion that “DOScalls are reflected from protected mode to real mode” can coexist peacefully with the opposite but equally confused notion that in Windows 95, “if you run only Windows applications, you'll never execute any MS-DOS code.” Both ideas are based on the same fundamental misunderstanding, which equates DOS software with MS-DOS. Accordingto. this notion, if there’s a DOS call it mustbydefinition be handled by MS-DOS, andconversely,if you don’t run any DOSapplicationsyou'll never execute any MS-DOScode. Thereality, meanwhile, is that (a) you can have DOS software that doesn’t require DOS, and that (b) you can have non-DOSsoftware that doesrequire DOS. An exampleof (a) is that 32bit file access in WW 3.14 and Windows 95 enables even real-mode DOSprogramsto bypass most of the MS-DOScode. An exampleof (b) is that every Win16 and Win32 application in Windows 95 requires a realmode DOS PSP;this has nothing to do with whether any DOSapplications arerunning.
Chapter I: Welcome to Windows 95 Wecan be quite confident that WLOG?212F provides anaccurate pictureofthe situations under which Windowsapplications in a pure Windows95 system use V86 mode. Here’s a summaryof the INT 21h calls that WLOG212F displays as “Passed down”: * Getting andsetting the current drive. Chapter 8 explains whythe number of function 19hcalls in V86 mode is exactly twice the number of function 0Ehcalls in V86 mode, plus the numberof function 19h calls seen by KernelDosProc; CURRDRIV.386 in
Chapter 8 shows how a VxD can handle function 19hentirely in 32-bit protected-mode.
* Getting the current date and time. Chapter 14 showsthe path taken in Windows95 from the Win32 GetSystemTime and GetLocalTime APIcalls, down to the INT 21h Get Date/Time functions, down to
the CLOCK$ device driver, and back up to the Virtual Timer Device (VTD)’s 32-bit protected-mode emulation of the ROM BIOS INT 1Ahtimefunctions. * Getting, setting, and creating PSPs. Throughoutthis book, we'll see numerousplaces where both Win16 and Win32 tasks in Windows 95
rely on the DOS PSP. Chapter 13 showsthe path from the Win32 CreateProcess API, down to the BuildPDBroutine in the Win16 KERNEL, downto the DOS create-PSP code. Task-switching
between Windows applications usually involves getting andsetting the DOScurrent PSP.
* Miscellaneous DOSfunctionsfor getting the DOSversion number, exiting back to the operating system, duplicatingfile handles, and so on. WhenyouPaste Link an
object from one document into another,
for example, the STORAGE.DLL module of OLEcalls DOS funetion 45hto duplicate thefile handle.
Now, would it be possible for a VD to handle eachofthese INT 21h fanctions in 32-bit protected mode andnotpass the call down to DOS? Yes, it would bepossible for a VxDto do this; see CURRDRIV.386 and INTVECT386in Chapter 8. So, Windows 95 currentlypasses a bunch of INT 21h calls down to V86 mode DOS, but there seemsto be no inherent reason whyit must do so. Perhaps even when Windows95 is commercially released,it won't.
Unauthorized Windows 95
Who's Atraid of MS-DOS? Aninteresting questionthenis this: If a// INT21h calls were handled by VxDsin protected mode, wouldthis fundamentally change the nature of
Windows 95? In other words, would moving these dozenorso remaining INT21h calls over to protected mode turn Windows95 into a genuine, complete, integrated operating system? I don’t think it would. For one thing, much of the VxD code that han-
dles INT 21h in 32-bit protected mode still uses the real-mode DOS
data structures.
My CURRDRIV.386,for example, manipulates the cur-
rent-drive variable in the DOS data segment. True, CURRDRIVmanipulates this variable entirely fromprotected mode,butit’s still a variable located in DOS’s real-mode data segment. WhenMicrosoftclaims that “if you run only Windowsapplications, you'll never execute any MSDOS code” (Inside Windows 95, p. 112), notice that nothing is said about
peeking or poking any MS-DOSdata.
Ofcourse,with long file and directory names, manyofthe DOSdata
structures suchas the System File ‘Table (SFT) and Current Directory Structure (CDS) becomeless useful. The Swappable Data Area (SDA), which the Windows 95 instance data manager doles out on a per-VM
basis, could be madea lot more useful wereit further doled out within the System VMona per-task basis. Butin any event we'll see throughout this book that Windows 95, even whenusing VxDs to handle DOS calls
in 32-bit protected mode, muststill quite frequently peek and poke the real-mode DOS data.
However, there’s a far more basic reason why providing VxD handlers for the remaining dozen or so INT 21h functions that Windows 95 cur-
rently passes down to DOS wouldn’t turn Windows 95 into a genuine operating system. The reason, quite simply, is that Windows 95 s already a genuine operating system, and thatits reliance uponthe re |-mode MS-DOS code does not change this. Window: 95 can be a genuineoperating system,
andstill use DOSfor someoperations.
is we've seen, Windows 95 does rely on DOS,it’s oddfor Microsoft to make total independence from DOS into some kindofcri-
teria for operating-systemgoodness. Inits technical propaganda regarding the Windows 95 architecture,I think Microsoft might be making a
big mistake by implicitly promotingthe idea that anoperating environ-
mentcan’t be a complete, integrated operating systemif it calls down to
Chapter 1: Welcome to Windows 95 DOSforany reason other than compatibility with DOSapplications and drivers. Employing the real-mode DOScode does not diminish Windows 95°s status as a genuine operating system.
These general statements are probably moresurprising than anything
I've said about this-or-thatparticular aspect of Windows 95. How can
independence from DOSnotbeall that important? Howcanit possibly be okay that Windows 95 uses the DOS Create PSP each time you run a
Win32 application, andthat task-switching even between two Win32
applicationsoften involves a Set PSPcall?
Ofcourseit’s important and notokaythat Microsoft is selling Windows 95 to the computertrade press and to programmersas an operating system in whichthe real-mode DOScodeis never executed on behalf of Windows applications. Butleaving aside Microsoft’ apparent confusion regardingits
ownproduct, howcan Windows 95 possiblyconstitute a genuineoperating
system when,as we'veseen,it relies on the real-mode DOScode? Here’s how: because Windows 95 runs this DOS code in V86 mode!
Recall that V86 modeis a form of protected mode. When Windowscalls down to DOS in V86 mode, Windows is in control and DOS is a subservient assistant. The phrase “Windowscalls down to DOS,” which
soundssofinal (jeez, I sure hope my INT 21h call is okay downthere!),is hardly the end ofthe story. Once Windows 95 sends an INT 21hcall downto the real-mode DOScode,the call can bounce back numerous times into 32-bit protected mode.
Forexample,if the real-mode DOScode loaded before Windows generates an INTinstruction (tocall a BIOS function, for instance), this traps immediately into the VMM, because that’s what INT does in V86
mode. VMMcanpass the INTto some VxD which handlesit entirely in protected mode. Chapter 14 provides a good exampleofthis: the INT 21hfunction 2Ah (Get Date) and 2Ch (Get Time) calls that Windows sends down to the real-mode DOScodeare turnedbythis code into INT1Ahfunction0 calls. All INTs in V86 modetrap into the VMM; VMMhands the INT 1Ah call off to the Virtual Timer Device, which
handlesthecall in protected mode. As another example of how Windows uses V86 mode to control the
execution ofthe real-mode DOScode, those V86callbacks mentioned earlier can be patched right on topofan existing piece of real-mode DOS
code,thereby forcing any executionofthis code totrap into VMM. These
V86 callback patchesare created with the Install_V86_Break_Pointservice provided by VMM.
Unauthorized Windows 95
Because of V86 mode, then, Windows — including Windows 95 — doesn’t run “on top of” DOS;it essentiallyuses DOSas a driver. Windows needs someone to implement INT21h functions 2Ah, 2Ch,50h, 55h, and so on. Perhaps oneday a VxD will dothis; in the meantime, a real-modedrivercalled WINBOOTSYSimplements these calls.
WIW 3.11: The Neglected Operating System It’s importantto realize that there’s nothing newin Windows 95’s relationship to MS-DOS. Windows95 isn’tthefirst version of Windows to employthe real-mode DOScodeaslittle more than a driver that implements somescattered INT21h calls. Windows95 is not even the
first version of Windowsthat deservestobe called a genuine operating system. As notedseveral timesalready, the fundamental transformation of Windowsoccursnot in 1995 with Windows95 but occurredalreadyin
1990 with Windows3.0 Enhanced mode — andperhapsevenearlier, in 1988, with Windows/386 2.0.
Windows programmers who've spent mostoftheir time with the upper-level Windows API provided by KERNEL, USER, and GDI would understandably doubt whether anyversion of Windowsprior to Windows 95 deservesto be called an operating system. But Windows 95
can onlybe plausibly considered a genuine operatingsystemif youlook at its lowerlayer, particularly VMM— andthe sameappliestoearlier
versions of Windows. Windows 3.0 Enhanced mode, Windows 3.1
Enhanced mode, and WfW3.11 all have fundamentally the same architecture as Windows95. If there’s anylogicin calling Windows 95 an operating system(and thereis, despite its use of real-mode DOS code),
then the VMM/VxD layer in Windows 3.x Enhanced modeis an operatingsystemtoo. Foryears, only a handful of VxDwriters were aware of this operating system and howit had basically replaced real-mode MSAs Chapter8 points out, we've had a 32-bit protected-modeoper-
stemsitting right under our nosesfor several years now, but
barely noticedit.
This 32-bit protected-mode operating system became a lot more difficult to ignore when WEW3.11 came outwith 32-bit file access (32BFA). WEW3.11 is surelyoneof the most under-appreciated software products ofall time. While Windows 95 clearly has manyfeatures
Chapter 1: Welcome to Windows 95 (longfilenames,threads, memory-mappedfiles, and soon) that aren’t present in WfW3.11 or that are onlypartially present in Windows extensions such as Win32s,it’s also true that the architectures of Windows 95 and WfW 3.11 are fundamentallythe same. This should come as no surprise, given that Microsoft’s ads (late 1993-early 1994) for WEW 3.11 bragged about how 32BFA wasbased on
“the 32-bit file systemfrom our Chicagoproject.” WEW3.11 includes
32-bit file system VxDs such as IFSMgr, VCACHE, and VFAT, just as Windows95 does. In other words, a major chunk of Windows 95 went
onsale aboutayear anda half before the rest of the product. While WEW3.11 sales have been impressive (finally living down WEW3.10’s
reputation as “Windows for Warehouses”), the trade presshassaidlittle
aboutthe fact that we have a 32-bit protected-modeoperating system living in our midst. The inclusion of Windows 95 VxDs such as IFSMgr in WFW3.11
was a double-edge sword, however. Onthe onehand(I mean, edge),
Microsoft made alarge chunk of Windows 95 available to the public
longbefore the rest of Windows 95 was readyto ship. At the sametime,
it’s notclear that the IFSMgrportion of Windows95 was actually ready to ship. In essence, WFW3.11 containspre-beta code from Windows 95.
It’s also worth notingthatthe only way to get any programmer's documentation for the 32BFA layer in WfW 3.11 was to enlist in the Win-
dows 95 beta: IFSMgris completely undocumented in WfW3.11.
Chapter 11 shows that when 32BFAis enabled, WfW3.11 is really a
32-bit protected-modeversion of MS-DOS. It’s particularly interesting that 32BFA couldbelifted out of Windows 95 and dropped into Windows 3.x without fundamental changes to VMM.Theservices neces-
sary to host 32BFA werealreadypart of VMMandhadbeensince Windows3.0.
Perhapsit sounds absurdthat a product such as WfW3.11, which
Microsoft apparentlydidn’t even deem worthy of morethan a .01 version numberincrease, could possibly have the same relation to MS-DOS as
Windows 95, for which Microsoft adopted a whole newversion naming scheme. However, by running WLOG212F under WfW3.11, both with and without 32BFA enabled (WIN /D: urns off 32 BFA), it’s fairly easy
to see that W£W3.11 relates to MS-DOSin muchthe same waythat Windows95 does.
Ratherthan present two morelogfiles, I’ve consolidated the
WLOG212F results from WfW3.11 and Windows 95 into Table 1-1.
Unauthorized Windows 95
Table 4-1: INT 21h Function Handling in WfW 3.11 and Windows 95
E
Pp Pp E E E Pp Pp E P E E E E E E E E E E E E S Pp E E P E E P P limmumamevi
3Dh 3Eh 3Fh 40h 41h 42h 43h 44h 45h 47h 4Bh 4Ch 4Eh 4Fh 50h 51h 52h 55h 56h 57h 59h 5Ah 5Bh 5Ch 5Dh 60h 62h 65h
Windows 95
u
3Ch
Wfw 3.11 with 32BFA
1 wv! MVVOHMVVVUMMIMHVOMMMMMMMMMMMMVIMVVImMmmMomvoIM
00h ODh OEh 11h 19h Ah 4Ch 25h 29h 2Ah 2Ch 2Fh 30h 32h 35h 36h 3Bh
1 vivivt vuvU! VVUVVUMVVVVVVVVV VV UUM! DMVVUMVHVVVIM
Function
WW 3.11 thout 32BFA
Chapter 1: Welcome to Windows 95
68h Tah DCh
5 a
P
E ec P
E P s -
5 34 il 9
23 18 3 5
27 13 2 7
P = Passed down mulated S = Sometimes passed down ~ indicates no data Earlier, I used WLOG212F mostly to showthat Windows 95 passes
some INT 21hcalls down to V86 mode DOS. Here,the keypointis that WEW3.11 with 32BFA emulates many INT 21h functions in protected
mode, without passing them down to V86 mode DOS.As seenin Table 1-1, WfW3.11 with 32BFAis almost identical to Windows 95. Asfar as their relationship with MS-DOS is concerned, there seemstobe little
difference between the two products. ‘This table makesit appearas if Windows 95 emulates a few more INT21h calls than WW3.11. However,this onlyreflects the different
INT21h calls that happened to be seen by WLOG?12Fineach test. For example, WfW3.11 passed function 0Dh down to DOS,but in Windows 95 WLOG212F happenednot to encounterany calls to function 0Dh.
We'll see in Chapter8 that if anything, Windows95is a little more tied to DOSthan was WfW3.11. ‘There’s not muchto say aboutthedifference between WfW3.11 with and without 32BFA.Clearly, with 32BFA disabled (WIN /D:C), WEW 3.11 passes almostall INT 21h calls down to V86 mode. However,it does
emulate a fewcalls, such as function 4Bh (EXEC)andfunctions 25h and 35h (Set/Get Interrupt Vector). This apparent emulation is carried out by the INT21h handler in the Winl6 KERNEL; as Chapter 13 discusses,
KERNELspecial
a few INT21h calls. For example, a function 4Bh
call from a Windowsapplicationis a request to WinExec another Win-
dowsapplication; DOS doesn’t know how toexecute Windows applications, so KERNEL handles this INT 21h functioncall, turning the executeinto a File Open, Read, Seek, andso on. For the most part, Windows 95 and WEW3.11 with 32BFApassthe same INT21h calls down to V86 mode DOS. These are mostly non-file INT21hcalls such as get Date/Time, Get/Set PSP, andso on. While
Unauthorized Windows 95
Microsoft publiclyclaims that Windows95 never, ever passes INT 21h calls down to V86 mode onbehalf of Windows applications, a confidential
iene document(“Chicago File System Features Tips &Issues,” April 22, 1994) provided with Beta-1 says something very different: Ondefault all INT 21interrupts, except file API INT 21s, are passed down to any hookerpresentin the system.
This phrase “except file API INT 21s,” is consistent with what WLOG?212F showed: Windows 95, like WfW3.11 beforeit, passes non-
file INT 21h calls down to V86 mode. Bythe colorful phrase “hooker,” Microsoft means code that has hooked INT 21h. Since WINBOOT.SYS itself is an INT 21h hooker, Microsoft here acknowledges what it seems
so anxiousto denyin its more widely publicized statements: DOSfunc-
tions not relatedtofile I/O are passed downto, andhandledby, the real-
mode DOScode.Jeez, what's so hard about sayingthat?
If hadto explain how Windows95 relates to DOS in 25 words or less, I'd saythis: Windows 95 relates to DOS the same waythat WfW3.11
Por non-file calls, it calls (in V86 mode) the real’ mode DOScode in WINBOOT.SYS. Windows 95is a
genuineoperatingsystem; so were WEW3.11, Windows3.1 Enhanced mode, and Windows 3.0 Enhanced mode.
Chapter 2
Woarcning Cuieaco Boor Hee just seen in Chapter 1 how Windows 95 actuallyrelates to realimode MS-DOS, it’s a good timeto see howall the pieces of Windows
95 fit together.
Well, the word ail is perhapsa trifle overambitious, since the Windows
95 setup deposits about a thousand files — atleast that’s how many were
on myhard disk. But we can get a good idea ofthe various discrete components that make up this “integrated” operating system by watching
whathappens while Windows95 boots up.
From WINBOOT.SYS to WIN.COMm In Chapter 1, I mentioned that the Windows 95 boot record looks for WINBOOTSSYS, just as the older DOS boot record looked for IO.SYS and MSDOS.SYS. Once WINBOOT.SYSis loaded, we can start watch-
ing the Windows95initialization process. An excellenttoolfor this is the
DOSversion of Nu-Mega’s Soft-ICE debugger. Soft-ICE (the DOS ver-
sion, not the Windowsversion) provides a BOOT commandthat resets
the machine while retaining Soft-ICE in memory. You can install some
breakpoints and then BOOT; when your machine comes back up, you
then use Soft-ICEto trace throughtheearly portionsofinitialization. As one indication ofits usefulness, this Soft-ICE BOOT command was used
byStac Electronics to reverse engineer the undocumentedpreloadinterface in MS-DOS 6.0. (Microsoft later claimed in court, under oath and
with a straightface, that this use of the Soft-ICE BOOT commandcon-
stituted “misappropriation of trade secrets”; unfortunately, the jury
Unauthorized Windows 95
believed Mier soft, but fortunately the two companies have subsequently settled out of court.)
To watch the early portion of Windows95 initialization, I set a breakpoint on the DOS File Openfunction (BPINT 21 AH=3D), the Extended
Open/Create function (BPINT 21 AH=6C),the FindFirstFile function (BPINT21 AH=4E), and EXEC(BPINT 21 AH=4B).
Since we've already
seen that Windows 95 uses INT 21h while running,it should comeas no surprise that it uses INT 21 duringits initialization. Each timeoneof the
INT21h breakpoints was triggered, I examinedthestring pointed to by the DS:DXregister pair.
‘The DOS version of Soft-ICE loadsas a device driver, so I needed a CONFIG.SYSwith the single line DEVICE=C:\SICE\S-ICE.EXE.
Noneof the other drivers seen in Figure 2-1 were mentionedin this one-line CONFIG.SYSfile. Func
File
Comment
OPEN RENAME RENAME RENAME RENAME FIND OPEN EXEC FIND OPEN OPEN
060.S¥S 10.SYS -> 10.D0S IBMBIO.COM -> I8MB10. DOS MSDOS.SYS -> MSDOS.005 IBMDOS.COM -> IBMDOS.DOS \DRVSPACE.BIN C:\DBLSPACE.BIN C:\WINBOOT..SYS \SYSTEN.DAT DA SYSTEM. CONFIGS
failed use logo inside WINBOOT watched INT 21h AH=56 too
EXEC
CONFIG.SYS C:\SICE\S- ICE. EXE C:\SICE\S-ICE. EXE : WINDOWS\HINEM, SYS \WINOOWS\HIMEM, SYS LFSSHLPS C:\WINOOWS\ I FSHLP. SYS C:\WINDOWS\IFSHLP. SYS SETVERKK C:\WINDOWS\COMMAND\SETVER.EXE C:\WINOOWS\ COMMAND! RLEXE con PRN AUTO
FIND WIN.222 FIND C:\WINDOWS\WIN. 222 NC: \WINDOWS\WIN. CON EXEC C: \WINDOWS\WIN. COM
failed failed
no DriveSpace no DblSpace either
registry real-mode portion of Plug and Play Configuration Manager; after open, do 1OCTL calls to CONF only one line, to load Soft-ICe this was *not* in CONFIG. SYS! failed this was *not* in CONFIG. SYS! faile this was *not* in CONFIG. SYS!
failed no AUTOEXEC.BAT; so no need to load COMMAND.COM either! here we go
Chapter 2: Watching Chicago Boot failed
‘SYSTEN\VMM32.. VXO
it's in \windows\system
vad VMM and VxDs
Figure 2-1: You can watchthe early stage of Windows95initialization using Soft1CE’s BOOT command.
Figure 2-1 showsonly thefirst stage of Windows95initialization. We'll be better able tofollow the next stage with the INTRSPYinterrupt-
logging programratherthan with Soft-ICE(see the “From WIN.COM
to KRNL386.EXE”section). In the meantime, what's happening during this first period of Windows95 initializatiot
As T’ve notedseveral times, WINBOOT.SYS servesthe same function in Windows95 that IO.SYS and MSDOS.SYSservedin earlier versions of MS-DOS, or that IBMBIO.COMand IBMDOS.COMserved in PCDOS and DR-DOS. Figure 2-1 shows that, every time youstart Windows 95, WINBOOT.SYS looks for these old DOS kernel files; if it finds them,
it renames them with a .DOSextension. This
resurrects Windows95 fol-
lowing an F4 bootusing IO.SYS and MSDOS.SYS to run a previous ver-
sion of DOS. Next, WINBOOTSSYStries to preload a disk-compressiondriver
named either DRVSPACE.BIN (from MS-DOS6.22) orDBLSPACE -BIN (from MS-DOS 6.0). The phrase “preload”refers to the loading of this driver before DOS processes CONFIG.SYS (and, in Windows95,
beforeit processes the registry). DBLSPACE.BIN could be Microsoft’s
own DbISpace ora disk-compression driver such as Stacker that masquerades as DbISpacetogetitself preloaded. The DOSpreloadinterface played a partin the Stac v. Microsoft case (fordetails, see Undocumented
DOS,2ded., pp. 40-42, 269-270; Geoff Chappell, DOSInternals, pp. 156-161; and “LA Law,” Dr: Dobb’s Journal, May 1994,pp. 137-139).
After attemptingtoloada disk-compression driver,WINBOOT.SYS looksforuser-definable configuration information. In previous versions of DOS, this meant processing CONFIG.SYS. In Windows95, the pre-
ferred place for configurationinformation
is the registry. Figure 2-1 shows
that WINBOOTopens the file C:\SYSTEM.DAT this is the central
registryfile. What Figure 2-1 doesn’t show(because I was watching only a
few INT 21h functions) is that WINBOOTretrievesthe registry’s path namebycalling INT 2Fhfunction 1613h,which is implemented in
another part of WINBOOT. The INT2FAPLH header file included with the Chicago Device Driver Kit (DDK)refers to INT 2Fhfunction 16h as
W386_Int_Multiplex, andhas the following entryfor subfunction 13h:
Unauthorized Windows 95
0x13. fidefine W386_Ge SYSDAT_Path * 10.SYS servi return path to SYSTEM.DAT *. It’s interesting that Windows 95 would use the real-mode DOS code in WINBOOT toimplement a nominally WIN386 function (we'll see
another example ofthis shortly), and that the DDKheaderfile refers to this, not as a WINBOOTSSYS service but as an IO.SYS service.
INT2FAPLH refers to several other INT 2Fh function 16h IO.SYS services that are new to Windows95; for example, function 160Ehis the
“TO.SYSservice for logo management.”
A complete rewrite? If you take a few minutes to ponderthe otherwise unimportant description of W386_Get_SYSDAT_Path from INT2FAPI.H, several points emerge: *
Programmers at Microsoft freely use the name 10.SYS when theyrefer to code located in WINBOOT.SYS. Clearly, they don’t see much difference between WINBOOT.SYS and the old combination of 10.SYS and MSDOS.SYS.
* Programmers at Microsoft think nothing of implementing Windows functions (remember,INT 2Fh function 16h is W386_Int_Multiplex) down in real-mode|0.SYS.
* Programmers at Microsoft don't see muchdifference between Windows 95andthe old Windows/386 product. This last point requires some explanation. INT2FAPI.H makes constant reference to Windows/386, a product that was released in 1987-88.The first datestamp in INT2FAPI.H is “10-Mar-1989 RAL” (that’s Ralph Lipe,
now Microsoft's chief architect for Windows 95); the file appears to have beencreated for what at the time wascalled version 3.0 of Windows/386. A little over a year later (May 1990), this Windows/386 3.0 became Windows 3.0 Enhanced mode. INT2FAPI.H is just one of many DDK header files that reveal an
unbroken continuity, from Microsoft's planned version 3.0 of Windows/386 all the way to Windows 95. For example, the VPICD.H header file included with the DDKis dated “13-Apr-1988 RAL”, VMDA.H is dated “05-May-1988 AAR” (Aaron Reynolds), and the all-important VMM.INC is
dated "05-May 1988 RAL”. Good chunks of Windows 95werefirst written for the Windows/386 3.xproject. So what? Well, Microsoft claims that Windows 95 has an entirely new architecture not based on any previous versions of Windows. For example: Windows nolonger can be likened to a fancy paintjob on an old MS-DOS Yugo. Becausethe entire operating system is freshly designedfrom the groundup,
Chapter 2: Watching Chicago Boot
you now havekiller features such as threads, memory-mapped files, and asynch 1/0. — Dave Edson, “Seventeen Techniques for Preparing Your 16-bit Applications for Chicago,” Microsoft Systems Journal,
February 1994,p. 20.
And, of course, the computer trade press — ya gotta believe! — happily
chimesin:
Chicagois an operating system with an entirely new architecture. — PC Magazine,April 12, 1994, p. 184. Chicagousesall-new code, written from the groundup. — PC/Computing, March 1994, p. 126. [Chicagois] an entirely rewritten 32-bit pre-emptive multitasking operating system. — InfoWorld,July 4, 1994, p. 45.
What's theorigin ofthis idea that Windows 95is freshly designedfrom the ground up, is written from the ground up, has an entirely new architec-
ture, has beenentirely rewritten, and uses all-new code?It must be wishful thinking, because not even the most casualglance at the code, nor even the mostcursory examination of the headerfiles included with the Chicago DDK — someof which are even older than INT2FAPI.H — bears outthis happy thought. In truth, I’m not sure how much of a happy thought that really is. Do
you wantto trust your program to an entirely rewritten-from-the-ground-up —
in other words,largely untested — version 1.0 operating system? didn’t think so. It might seem perverse of meto scrutinize minorpoints in an obscure
DDK headerfile, especially in light of Microsoft’s many carefully worded statementsregarding the Windows 95architecture. It’s unlikely that much thought went into INT2FAPI.H. But that’s a major reason to examine this obscurefile! Just as people are morelikely totell the truth when they're in casual situations than when they carefully consider what they're saying (which was the basis for Freud’s brilliant Psychopathology of EverydayLife),
a corporate entity such as Microsoft is likely to reveal more in offhand headerfile comments than in carefully orchestrated statementsfor the press. An otherwise unimportant headerfile such as INT2FAPI.H can tell us more about Windows 95 design and architecture than can a hundred
Microsoft pressreleases. By looking overfiles haphazardly thrown on the Chicago DDK, we learn that Windows 95 isn’t entirely rewritten from the ground up, but ratheris based on the Windows/3863.0 project, which became Windows 3.0 Enhanced mode. And the VMM core of Windows 95 made itsfirst
appearance, under the nameVirtual DOS Machine Manager (VDMM), in Windows/386 2.1:
Unauthorized Windows 95
A program thatruns in the 80386's native 32-bit protected mode and oversees a setofvirtual machinesis called a 386 control program,or virtual machine monitor. Windows/386is such a virtual machine monitor; it also provides complete device virtualization for the PC's disk controller, video adapter, keyboard, mouse,timerchip, and 8259programmable interruptcontrollers. — Ray Duncan, “Microsoft Windows/386:Creating a Virtual Machine Environment,” Microsoft Systems Journal, September 1987,p. 5. In Windows 95, the VMM managesthreads as well as virtual machines, but the Windows 95 VMM still has its roots in the Windows/386 VDMM.
Unfortunately, few programmers orjournalists paid muchattention to this
VDMM layer in Windows/386, or indeed to the VMM and VxD layer in Win-
dows3.x. This is one reason why Windows 95 appears to be newer, and a moreradical break with thepast,thanit reallyis. According to the biographical note in the backof his authorized, semiofficial Inside Windows 95, exMicrosoft employee Adrian King “managed the group that developed Windows/386, the product that pioneered the
use of software virtual machine technology in Microsoft operating systems.” King’s work on Windows/386 gives him manyinsights into Windows 95. For example, how many authors would know that Microsoft not only uses V86 modebutalso helped to design it? As King states on page 37, “Microsoft helped Intel design virtual 8086 mode and harnessed that mode initially with the release of Windows/386in 1987.” Another point King makesis that while Windows/386provides some of
the background to DOS compatibility in Windows 95, “no codeis repeated”
(p. 4n). A quick look at the WIN386.386file (dated July 1, 1988) from Win-
dows/386 2.1 seemsto bearthis out. Although there are many conceptual
similarities between Windows/386 2.1 and Windows 95 — which is why
Duncan's 1987 Microsoft Systems Journalarticle remains useful reading — Microsoft nonetheless appears to have used Windows/3862.1 asits “throw
one away” testbed for what would two years later become Windows 3.0 Enhanced modeand sevenyearslater, Windows 95. In particular, Microsoft appears to have engagedin a large rewrite cam-
paign between the Windows/3862.1release in 1987-88,andtherelease of Windows 3.0 Enhanced Enhanced mode in 1990. For example, look at some of the Windows VxDsourcefiles included with the DDK:
Fil
VPICD.INC VNETBIOS.ASM VKD.ASM
scription
“13-Apr-1988 RAL Rewrite” “25-Apr-1988 RAL Complete rewrite of network (used to be VND)” “29-Jul-1988 RAPStarted completerewrite”
So yes, parts of Windows 95 were completely rewritten — back in 1988!
Chapter 2: Watching Chicago Boot
From the Registry to HMMS Having discussed how WINBOOTlocates the registry, a few words are in order abouttheregistryitself. Unlike CONFIG.SYS, AUTOEXEC.BAT,
SYSTEMLINI, and so on — all files that it seeks to replace — theregistry is not a readable plain ASCIIfile. Users can browseandedit the registry
with the REGEDITapplication. Programs query and changetheregistry with Windows APIfunctionssuch as RegOpenKey, RegEnumKey, RegQueryValue, RegCreateKey, and RegSetValue. VMMprovidesthe actual
implementationoftheregistry-access functions; the Windows APIs call
VMMs&protected-mode API. DOSprogramscanaccessthe registry with ‘VMM*'s V86 API.
Theregistry is a hierarchical database of keys andvalues, holding everything from Object Linking and Embedding (OLE)settings andFile Viewerassociations to performance-monitoringstatistics and dynamic VxD information. Forexample,thefollowingtree (producedbyrecursively
calling RegOpenKey, RegEnumKey, RegQueryValue, and RegCloseKey)
represents information(stored in HKEY_LOCAL_MACHINE\SOFTWARE\Classes) about Microsoft Word 6.0 documents: Word.Document.6-Microsoft Word 6.0 Document. shel] ICE\WINWORD\WINWORO. EXE /w n("B1") FFICE\WINWORO\WINWORD.EXE fw pen("81") J{FilePrint()1CDoc "Gl" )ICFilePrint .Backgr
: \MSOFFICE\WINWORD\WINWORD. EXE ‘To determinethe incantationtoprint a Word6.0 document, for
instance, a programcould RegQueryValue these two keys: Word.Document.6\shel \print\conmand Word. Document..6\shel \print\ddeexe
Thevalue ofthe first key canbe passed to WinExee: C:\MSOFFICE\WINWORD\WINWORD. EXE /w
Unauthorized Windows 95
andthe value of the secondkeyis a DDE EXECstring:
[Filedpen("21")IEFilePrint()I{DocClose(2)) Notice that the programrequires no hard-wired knowledge other than the namesofthe keys. Windows95itself uses the registry to store configuration informa-
tion, for example, regarding dynamic VxDsloadedbythe I/O Supervisor: [HKEY_LOCAL, "DevLoadi
"DriverDes
HINE\System\Curren.
nt ral Se
Services\Class\fdc\0000)
ndard Floppy Disk Control ler* eIMap"=hex:00, 1c,01,24
Mercifully (I've somehow trashed SYSTEM.DAT morethan once),
Windows95 can run with a missing or corrupted registry, thoughitwill warnthat “Registry services maybeinoperativefor this session.” You can also use the F8 interactive boot to bypass the registry. Withouta registry,
Windows 95 cannotsupportfeatures such as OLE or Quick View(a
handy Exploreroption that we'll use later to examine some components of Windows95). Each time you shut down Windows 95, it writes known-
goodregistry files named SYSTEM.DAO and USER.DAO.ButI still bet someenterprising third-party vendorwill come along with much-needed registry repairtools. Returning to Figure 2-1, we see thatafter opening theregistry, Wi dows 95 opens the CONFIG$device, whichis part ofWINBOOT.SYS.
CONFIGSis the real-modeportion of the Plug and Play Configuration Manager. The protected-mode portion lives in a VxD calledCON-
FIGMG(it will probably be a while before Microsoft starts using long
filenamesfor core executable files).The CONFIGMGVxD communicates with the real-mode CONFIG$ device via theDOS IOCTL func-
tion; CONFIGMGpasses
CONFIG$ a V86callback (see the upcoming
sidebar “Pushing aside real-mode drivers?”) so thatCONFIGS can call up toCONFIGMG. Insome ways, CONFIGS canbe viewedas an
extension of the DOS6.0 multi-bootfeature. Aside fromthe point that the Plug and Play Configuration Manager
evenhas a real-mode component, it’also worth noting thatCONFIG$ provides a new interface that lets DOS device drivers and TSRs query configurationinformation. Asdescribed in a Microsoft document, “Plug and Play Device Driver Interface for Windows 3.1 and MS-DOS”
(October 5, 1993) — Microsoft andIntelprovide a Plug and Playadd-in (DWCFGMG.SYS)for non-Windows 95 systems — theinterface uses
Chapter 2: Watching Chicago Boot
INT2Fhfunction 1684h, with the value 34h in BX.It just so happens
that INT 2Fh function 1684his normallycalled to retrieve the entry
point to a VxD whoseIDis givenin the BX register; 34h is the VxD ID for CONFIGMG. Onceagain wesee a Windowsinterface implemented down in the real-mode DOSportion of Windows95. Next, if there isa CONFIG.SYSfile, WINBOOTprocesses it. I did
need a CONFIG.SYShereto load Soft-ICE,but not to load HIMEM, IFSHLP, or SETVER. WINBOOT.SYSloadedthese automatically, in muchthe same way thatMS-DOS 6.x (and as we’ve seen, WINBOOT
-SYS, too) would automatically load DBLSPACE.BIN or DRVSPACE
.BIN. Animportantdifference is that disk-compression drivers need to be loadedbefore processing CONFIG.SYS; the XMS and IFSHLPdrivers required to run Windows can be loaded after CONFIG.SYS.
‘There’s nothingparticularly sophisticated about WINBOOTSsability
tofind andloadfile drivers such as HIMEMand IFSHLP. Inhis discus-
sionof systemstartupin thebrilliant book DOSInternals, Geoff Chappell said that DOS6.0°s provisions for loading DBLSPACE.BIN,despite Microsoft's claimsof providing integrated (there’s that word again!) disk compression, “has the appearanceof a hack” (p. 156). Much the sameis true of WINBOOT’sability to bootstrap Windows. If you don’t look too hard,the ability to load Windowswithout any configurationfiles looks quite integrated; however,it involves
nothing more than sometrivial
code (find and execute HIM S, IFSHLP.SYS, and WIN.COM) hacked into SYSINIT. Like previous versions of Windows, Windows 95 requiresHIMEM.
-SYSor someotherextended-memory (XMS)driver, the V36MMGR (V86 Memory Manager) VxD supplies its own XMS services once Win-
dowsis upand running.
AMGR’s XMSserverreplacesthe onethat
mustbe present before Windowsstarts.
Pushing aside real-mode drivers? The relationship between V86MMGRand a realmode XMSserver such as HIMEM may help shed somelight on anotherone of Microsoft’s confusing
claims regarding Windows 95 — thatits VxDs “take over” from, and possi-
bly even “pushaside,” any equivalent realmodedrivers.
Unauthorized Windows 95
Adrian King's explanationofthis “take over”ideais quite reasonable: The file system design in Windows 95allows a protected mode port driverto take
control of a real mode driver and bypassit while the system is running in protected mode — Windows95canclassify the real modedriver as a ‘safe’ driver. Safe means, essentially, that the protected mode driver can offer functionality identical to the real mode driver's. In such a case, the protected modedriver will simply carry out all the /0 operations and nevercall the real mode driver. — King, Inside Windows 95, p. 307.
This makes a lot of sense: Many VxDs do provide functionality that
replaces what's provided by some real-mode driver (for example, CDFS. replaces MSCDEX, and VCACHE replaces SmartDrive). The file 1OS.INI contains a list of so-called “safe” real-modedrivers from which a VxD can take over. Here, “take over” simply meansnevercalling — that is, ignoring the presence of — the realmodedriver. However, Microsoft has at times suggested that Windows 95 will liter ally unload the safe reatmodedriver and reclaim its memory. Ralph Lipe discussedthis possibility in his presentation on the Windows 95architecture at Microsoft's Win32 Professional Developers Conference in 1993. I've also heard the specific claim that the CDFS (CD-ROM file system) VxD
will unload MSCDEXfrom memory. Certainly, this is the image conjured up by the more generalclaims that Windows “pushes the real mode code aside” (Inside Windows 95, p. 74). Ignoring something is not normally
equated with pushingit aside.
Presumably Jon Udell of Byte magazine heard the same line did: When protectedmode components like the VFAT(Virtual FAT) and CD-ROM file systems, network redirectors, and 32-bit DoubleSpace driver load, they can, in manycases, unloadtheir corresponding reatmode components from memory. DOSwill then be history... — “Chicago: An Ambitious Compromise,” Byte, March 1994,p. 22.
HIMEM.SYSisn’t an 1/0 driver, but a look at V86MMGR's interaction with HIMEM can help clear up lot of the confusion about Windows 95 pushingasidereal-modedrivers. Although V86MMGR replaces HIMEM or another realmode XMS server with its own 32-bit protected-mode XMS server, V86MMGR doesn’t “push”
the realmode XMS serveroff the machine. It doesn’t unload HIMEM, reclaim its memory, or anythinglike that. How could it? Some code that loadedafter HIMEM but before V86MMGR might have called INT 2Fh function 4310h (Get XMS Entry Point) and might be hanging on to a function
pointer that it thinks is the address of the XMS server. If V@6MMGR were
somehow to unload HIMEM from memory, the system would most likely hang the intermediate program that called this stale functionpointer. V86MMGRcan't unload HIMEM. Instead, as shown in Chapters 8 and 11, V86MMGRuses the VMM install_V86 _BreakPoint service to patch the realmode XMS driver. If anyone calls the rea-mode XMS server, they
will immediately encounter a V86 breakpoint that jumps them into V8eMMGR.
Chapter 2: Watching Chicago Boot
That V86MMGR will install a V86 breakpoint over HIMEM is a good illustration not only of the fact that Windows 95 doesn’t push real-mode codeaside butalsoofthe equally important fact that Windows95 (like previous versions of Enhanced mode)will run this real-mode code in V86 mode and alterit in various ways. It's difficult to see how Windows 95 could possibly unload any nontrivial real-mode driver or TSR from memory. Another good example is MSCDEX (Microsoft CD-ROM Extensions); it’s fairly well-known that MSCDEX patches MS-DOS (see Undocumented DOS, 2d ed., p. 463). Unloading MSCDEX would require backing out these patches.This is why the excellent MARK/RELEASEutilities by Kim Kokkonen never quite worked 100% of the time with MSCDEX. If you think about it, for Windows 95totruly unload real-modedrivers and TSRs from memory, it would have to include very sophisticated versions of MARK/RELEASE. Unloading drivers and TSRsis not just a matter of unhooking someinterrupt vectors. An examination of Kim Kokkonen's comments to MARK.PAS and RELEASE.PAS shows thatover the years it has become more and more complicated to safely unloadthis stuff.
| supposeit's possible that Windows 95 could in time incorporate a facility to release certain specific drivers or TSRs, such as MSCDEX, about whichit had intimate knowledge. However,there’s no general technique for undoingalll the nasty hooks and patchesthat drivers and TSRs might have inserted into the realmode DOS code.
The only reason the question of unloading drivers and TSRs comes up
is that Windows 95 (specifically, as we'll see in a few minutes, the WIN.COM component of Windows 95) intends for you neverto exit Windows and return to MS-DOS. When you shut down Windows 95, you can choose between shutting down the machine,restarting Windows 95,orlogging off the network; exiting back to the C:\> prompt is not an option. (This is
another way that Windows 95creates the impression of being seamlessly integrated with the machine, as thoughit were without anyintervening realmode DOScode.) Since Windows 95 never exits back to DOS,it obviously needn't worry about undoing whatever changes it makes to DOS — such as, hypothetically, unloading redundant real-modedrivers. But wait a minute! As you might know, for those few DOS programs that
won't run in a V86 mode DOS box, Windows 95offers a Single Application Mode checkbox in the DOS boxproperties. In Single Application Mode, Windows 95 saves awayits current context, puts the machineinto real (not V86!) mode, and runs a DOS commandprompt. This is very much like exit-
ing Windowsback to DOSorlike running a DOS box in Windows 3.x Standard mode. VxDs are unloaded, which is why long filename support disappearsin Single Application Mode — IFSMgrisn’t running. Windows 95 even issues the INT 2Fh function 1606h Windows Exit broadcast, so that software loaded before Windows 95 thinks — pretty much correctly — that
Windowsis exiting (see Chapter 3). When you exit from Single Application Mode back to Windows, Windows95 reinitializes, reloads VxDs, issues the
function 1605h WindowsStartup broadcast, andso on.
| 7
Unauthorized Windows 95
Given that Windows 95really can exit back to DOS, albeit via this odd Single Application Mode, it’s hard to see how Windows 95 could possibly
unload TSRs and device drivers. Windows 95 would just have to reload them again whenever a user wanted Single Application Mode. In short, not only does Windows 95 not currently push realmode code aside, it’s unlikely that it ever could. It's much more likely that for those teal-modedrivers whosefunctionality is provided by a VxD and is not required during Windowsinitialization (MSCDEX is a good example), the phrase “pushthe real-mode code aside” means little more than that the Windows 95 Setup program could remove any mention of them from CONFIG.SYS and AUTOEXEC.BAT. Howdid this humble feature get transubstantiated into the glorious idea
that Windows 95 would literally unload the “safe” device drivers and TSRs andreclaim their memory? | think this happened becauseit’s natural — even for programmers and the computer trade press — to hear what you wantto hear.
For example, a Microsoft VP once told me that Windows 95 would “shove DOSoff the machine,” and from the context of our conversation | was sure at the time that he meant Windows 95 would literally unload DOS from memory andload itself at the memory location previously occupied by DOSandby real-modedrivers. That's what | wanted to believe, anyway. In retrospect, | bet he just meant somethingtrivial such as that the Windows
95setup program removes DEVICE= lines from CONFIG.SYS,or that WINBOOT.SYS replaces 10.SYS and MSDOS.SYS. Or maybethis VPreally believed that Windows 95 can plow realmode codeoff a running machine, becausethis is what oneofhis programmers told him. The programmer, meanwhile, just meantthat the Windows 95 setup program removes....
Perhaps Microsoft's incorrect descriptions of the Windows 95 architecture are due to nothing more than a wishful-thinking variant of the gameof “telephone.”
From IFSHLP.SYS to WIt.COM After HIMEM.SYS, WINBOOTloads IFSHLP.SYS . As notedin the «But Bypassing DOS, To section of Chapter 1, the real-mode code in IFSHLPis a keypart of Windows 95° installablefile system; IFSMgr won'tloadifit can’t locate the IFS$HLP$driver. IFSMgrcalls IESHLP using the DOS IOCTL function, andpasses IFSHLP a pointerto a V86 callback that IFSHLPcanlater use to communicate with IFSMgr. (See “TheRole of IFSHLP.SYSand V86 Callbacks” in Chapter8.) WINBOOT. next loadsS which changes the DOS version numberon ape’ application ba: ck!) and, undercertaincircumstances, Microsoft’s expanded memory manage: , EMM386.E
Chapter 2: Watching Chicago Boot
Note that the V36MMGRVxD not onlyprovides XMS services but is
also an EMM. Nextin Figure 2-1,WINBOOT.SYSlooks for an AUTOEXEC.BAT file. WINBOOT. loads the DOS commandshell (COMMAND.COM)
to process
AUTOEXEC.BAT. However, as shownearlier,if there’s no
AUTOEXEC.BAT, there’s no need to load COMMAND.COM, and
WINBOOTwill proceeddirectly to load WIN.COM.This,ofcourse,is the tight integration we’veall been hearing so much about. Well, it’s nice and everything,butit’s aboutas integrated as the Boston public schoolsystem before court-ordered busing. Bypassing COMMAND.COMdefinitely saves some memory, butI don’t see anysignificant architectural difference betweenWINBOOT
-SYS's direct loading of WIN.COM,andputting WINasthelast line of AUTOEXEC.BAT. Now, it is a hugedifference that end-users don’t have
to go into AUTOEXEC.BAT (a scary process for manypeople) and add a WIN command. Butthis usability enhancement, however important,
doesn’t constitute a fundamental change in the Windowsarchitecture. In whatever way Windowsgets loaded, DOSisstill sitting underneathit.It’s just a matter of whether COMMAND.COMsits downtheretoo.
Incidentally, to autoload WIN.COM, WINBOOT.SYSmustknowits location. Although WIN.COMis usually found in C:\WINDOWS, this
locationis not hard-wired (excuse me, I mean “integrated”) into WINBOOTS.SYS. It comesfromthe registry (HKEY_LOCAL_MACHINE \Software\Microsoft\Windows\CurrentVersion\System Root).
So, yes, autoloading WIN.COM is agreatfeature:just don’tsayit invol hanging the Windows architecture. I think somesort of “Technology Rulz” prejudice makesit difficult for manyofus in the computer industry to believe that a major usability enhancementcan come about without an underlying fundamental changetothe software. Well, it can. But why autoload WIN.COM? Asis well known, WIN.COMis not
Windows. It is a small (less than 20K) program whose jobis to load
Windows(see Matt Pietrek, Windows Internals, pp. 3-8). Why doesn’t WINBOOT.SYS just load Windowsdirectly? Whybother with WIN -COM at all? We'll see in a moment that, in Windows 95, WIN.COMloadsthefile VMM32.VXD. In Windows 3.2 Enhanced mode, WIN.COM loaded WIN386.EXE and, in dard mode, DOSX.EXE. Chapters 5 through
7 showthat executables such asDOSX.EXE, WIN386.EXE,and even VMM32.EXE(if you rename it with an
extension) can be run
directly from the C:\> prompt.Soit seems that WINBOOTSSYSshould
Unauthorized Windows 95
be able to directly load VMM32.VXD, and bypass WIN.COMjust as it
usually bypasses COMMAND.COM. The file now called VMM32.VXD was called DOS386.EXE inearly pre-beta versions of Windows 95. There was a DOS=ENHANCED
switch in CONFIG.SYS(such asDOS=HIGH,UMB,ENHANCED) that IO.SYS(as it wasstill called back then) wouldinterpret as a request
to directly load DOS386.EXE. Notice that ENHANCEDwas a reference, not to Windows, but to DOS! Apparently at one time there was some consideration at Microsoft of having Standard and Enhanced modes of MS-DOS.Standard mode would, presumably,be a real-mode version of MS-DOS, and Enhanced mode would be a V86-mode version,
running under DOS386.EXE. Chapter 6 shows howtoeasily build your
own copyofthis Enhanced mode of MS-DOS,in theprivacy and com-
fort of your own home. Thus, some thoughtdidgo into bypassing WIN.COM.But WIN.COM plays an importantrole in Windows95; namely, it prevents you fromexiting back to DOS. When youshut down Windows95, it is WIN.COM that dis-
plays the message, “You can now safelyturn off the computer.If you wantto restart your computer, press Ctrl-Alt-Del.” As we'll see in Chapter7, if you run VMM32 without WIN.COM,youcanexit back to DOS.Clearly, such anabilityinterferes with the image Microsoft wants tobuild of a seamless, integrated Windows PC.
From WIN.COM [0 HRNLSBG.ENE ‘Thetail end of Figure 2-1 shows that WIN.COM runs VMM32.VXD. This contains, we'll see, the very heart andsoul of the Windows operating
system(and I do meanoperating system, not operating environment). While the BOOT commandin Soft-ICEgaveusaringsideseat to the
early stages of the Windows 95 bootprocess,it can be somewhattedious tointeract with the debugger every time Windows95 triggers a Softbreakpoint. All we really needis alist ofthe files that Windows 95 looks
for, opens, or executes; suchalis tive debugger.
is best generatedusing a non-interac-
David Maxey’s INTRSPY (Interrupt Spy) utili y from Undocumented
DOS(2d ed., pp. 229-263) is pert
ct for this. INTRSPYcanbeloadedin AUTOEXE‘ AT. Actually, I’vejust realized that you don’t need AUTOE. ‘C.BAT (and henceCOMMAND.COM) to run TSRssuch
Chapter 2: Watching Chicago Boot
as INTRSPY,because Windows 95 processes any INSTALL= commands in CONFIG.SYS. But since wealready knowthat the effect of AUTOEXEC.BATis fairly minimal(asidefrom creating a global COMMAND .COMvisiblein all VMs), we should beokay. The CMDSPY script compiler can be givena script that tells INTRSPYto log calls to the DOSFile Find, Open, and EXEC functions. For instance, to watch the DOSFile Open function (INT 21h function 3Dh), which expects an ASCII filename in DS:DX and which returnseither a file handle (ifthe carryflag is clear) or an error code (carry set) in AX, an INTRSPYscript mightlooklike this intercept 21h try utput onexit if ( sameline * Figure 2-2 shows the next stage of the Windows95 boot process, overlappedslightly with the bottomof Figure 2-1. In addition to File Find, Open, and EXECfunctions, the INTRSPYscript also loggedcalls
to Extended Open/Create(function 6Ch, shown as XOPENin Figure
2-2), toFile Create, and to the new longfilename (LFN)variants ofall these functions. However, as long as INTRSPYis a DOS TSR,it will neversee these LFN DOSca
FIND OPEN OPEN OPEN OPEN OPEN OPEN DPEN OPEN DPEN OPEN
¢ system\ndis is2sup.386 DOWS\s. NOISHLPS [FA C:\WINDOWS\system\mso sup. 386 C:\WINDOWS\system\vne 386
Unauthorized Windows 95
OPEN DPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN XOPEN FIND OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN XOPEN OPEN OPEN
C:\WINDOWS\system\wsock. 386 CONFIGS C:\WINDONS\system\vserver 386 IFSSHLPS C:\WINDOWS\system\vredir. 386 c:\andrew\vxd. 386 C:\WINDOWS\system\dva.386 C:\WINDOWS\system\ vpmtd. 386 1FSSHLPS SMARTAAR [FAIL 2] C:\WINDOWS\system\ISAPNP. vcd C:\WINDOWS\system\MMDEVLOR. vxd C:\WINDOWS\system\MSSB16. vxd C:\WINDOWS\system\VJOYD. vxd SCSIMGRS [FAIL 2] S\10S. INI c C:\WINDOWS\T0S.LOG C:\WINDOWS\system\IOSUBSYS\*. vxd C:\WINDOWS\system\10SUBSYS\apix C:\WINDOWS' TosuBsYS\cdfs C:\WINDOWS\system\ [OSUBSYS\cdtsd. vxd C:\WINDOWS' m\ TOSUBSYS\ cdvsd. vxd C:\WINDOWS\system\IOSUBSYS\di sktsd. vad C:\WINDOWS\ sy UBSYS\di skvsd.vxd C:\WINDOWS\system\ IOSUBSYS\scsi1h1p. ¥: C:\WINDOWS\system\IDSUBSYS\vol track. vxd C:\WINDOWS\system\1OSUBSYS\rmm. pdr C:\WINDOWS\NDISLOG. TXT C:\WINDOWS\system\ee16.386 C:\WINDOWS\system\netbeui .386
OPEN C:\WINDOWS\WINSTART.BAT CFAIL 2] 3: OPEN C:\WINDOWS\system\ LPTENUN. vd OPEN C:\WINDOWS\system\UNICODE.B1N OPEN IFSSHLPS EXEC C:\WINDOWS\ system\krn1386.exe
Figure 2-2: Using INTRSPY, we seethe middle stage of Windows 95'sinitialization.
Although I edited the INTRSPY output in one place — insteadof showing all the lines where Windows 95 looks for a WINSTART.BAT.
file in each subdirectory in my PATH, I’ve shownonly onesuchline,
and added a comment — Figure 2-2 is otherwiseall that INTRSPY
sawofthe Windows 95 bootprocess. Evenif you’re only vaguely
familiar with the architecture of Windows, you probablysuspect that there mustbe a lot more to Windows95 than what’s shownin Figure 2-2. Where’s the Windows 95 Explorer? Where’s GDI? What about the Win32 kernel?
Yes, there’s a ton of INT 21h file activity missing from the INTRSPY log in Figure 2-2, and no, INTRSPYis not broken. INTRSPY hasn’t
missed anything seenby real-mode DOS.
Chapter 2: Watching Chicago Boot Oh,of course: 32-bit file access! Once 32BFAis up and running, Windows 95 won't be sendingfile I/O calls down to DOS. Consequently, INTRSPY(which, again, is a real-mode DOS TSR) won’tsee thesecalls
either. INTRSPYgets the sametruncated view if youuseit to watch WEW3.11 with 32BFA. There’s a way(at least in Beta-1) to make Win-
dows 95 load without 32BFA,andI'll use this loopholelater so that
INTRSPYcan watch Windows95 bootall the way up. In the meantime, Figure 2-2 has enough materialtolast us for a while. Thetop of Figure 2-2 overlapsslightly with the bottomof Figure 2-1. WINBOOThas run WIN.COM, whichturns around to look for and run VMM32.VXD. As noted earlier, VMM32.VXD isthe equivalent in
Windows 95 of WIN386.EXE in Windows3.2 Enhanced mode. However, this mightnottell you much.It’s amazing howlittle attention has beenpaid, until Windows95, to this crucial lower half of Windows. Despiteits filename extension, VMM32.VXDis not a single Virtual
Device Driver (VxD)buta collection of VxDs. Like WIN386.EXE, VMM32.VXDuses the W3executable file format. The Unauthorized
Windows 95 disk comes with a program, W3MAP, that you can use to examine these W3files.
W3MAP, I haveto admit, is a boring-looking character-mode DOS program. Whatwe really needis a VxD “Quick View” DLL for the
Windows95 Explorer. But that’s a differentproject, for a different book. In the meantime, W3MAP’*s heartis in the right place, even if its user
interface could be better. If you give W3MAP the nameof a W3file,it spits outa list of the VxDs that comprise thatfile. For example: Cs \UNAUTHWDw. windows \system\vmm32.vxd
vwinsz VEBACKUP vom" COMBUFF IFSHGR 10S SPOOLER VFAT VCACHE
ooodiea
Unauthorized Windows 95
The Windows 95 setup program builds VMM32.VXD out of loose
VxDs,sothefile might differ from one machineto another. But VMM32
.VXDgenerallyincorporates about 45 VxDs. The hex numbernext to
each VxD nameis the offset within the file where that VxD canbe found. However,the first item shown, W3, isn’t a VxD, but rather the W3file-
format mapfor therest ofthefile. Everything beforeit (here, 10000h
bytes) is a real-mode DOS program — the program that WIN.COM runs — whosejobis to switch to 32-bit protected modeandstart the processofloading the VxDsintherestofthe file. DOS doesn’t know how to load VxDs; this DOS programat the head of VMM32.VXDincludes
the VxD bootstraploader. Starting with the VirtualMachine Manager (VMM) at offset 11000h in thefile, everythingelse is a VxD. Well, it’s not quite accuratetocall VMMa VxD, since it really managesall the VxDs in the system. But in termsofits file format, VMMlookslike just another VxD. All VxDs, and VMM, usethe 32-bit Linear Executable (LE)file format. If you dump out oneofthe locations displayed by W3MAP, you'll see an LE header: UNAUTHH>dump ooe11o0e | 4c 00011010 | 00 80 0
t Ox11000 \wir 00 00 00 00 0:
40 00 00 00
Well, this isn’t terribly interesting. You can get a better idea of what's in VMM32.VXD — orinanyother file that uses the W3 format, such as WIN386.EXE from Windows 3.1 Enhanced mode — youuse W3MAP’s -VERBOSEoption.
Inside the Virtual Machine Manager Whenpointed at VMM32.VXD, W3MAP-VERBOSEspits out almost 2,000lines ofinformation about the VxDsinthe file andthefunctions they provide. I’m notgoingtobore youbydisplayingthe full output (which would occupyabout fifty pages of this book and which you can easily produce yourselfusing W3MAP), solet’s just look at VMM. As Adrian King notes(Inside Windo 95, p. 67 Phe Virtual Machine Manageris the h art of the Windows 95 operating system. It includes software to implement all the basic systemprimitivesfor task scheduling, virtual memory operations, programloading and termination,andinter-
task communication.” Thebit about programloadingisn’t quite true
(VMM knows nothing abouteither the Win16 or Win32
executable file
Chapter 2: Watching Chicago Boot
formats), but otherwise this is a good description. VMMis the heart of Windows 95. It also was the heart of Windows 93 (WfW 3.11), Windows
92 (3.1 Enhanced mode), and Windows 90 (3.0 Enhanced mode), but we'll get into that in a moment. In additionto the variousservices it provides, VMMalso holds the primaryinterrupt,fault, and exceptionhandlersin the system. For example, all hardware interrupts from the timer, keyboard, mouse, COM ports, and so onfirst go to VMM, whichgenerally hands them off to the
Virtual Programmable Interrupt Controller (PIC) Device (VPICD) VxD.
Likewise, general-protection (GP)faults and virtual-memorypagefaults
first go to VMM, whicheither deals with themitself or doles them out to
interested VxDs. So what’s VMMlooklike? Figure 2-3 showsa small portion ofthe verbose W3MAP output:
# 0001 1 Machine 4.00 rder: 00000000 (Earliest same as VMM) trol_Proc @ a00013de DO8_V86_API_Proc @ 00001811 DDB_PM_API_Proc @ 000@1a11 D vice Table @ 0000d644 (17 010000 @ 00001008 Get_VNM_Version 010001 @ 00000e46 Get_Cur_VM. 10002 a0000e4d Test_Cur_VM_Handle 010003 @ 00000654 VM Handle 010004 @ eoo0a est_Sys_VM_Handle Validate_VM Handle eoo00 010005 010006 @ 9000312c Get_VWM_Reenter_Count ef nt_Execution 010007 @ 0000313 610008 End_Reentrant_Execut iat 10009 Install_V86_Break Point 010002 o0000 k Point 1000b @ 00000: al1_Back 01000c @ a00009d PM_Cal1_Back 010000 @ e0000290 Returns 01000 @ 00001258 Schedule Global_Event 01000f @ G0001ab8 Schedule _VM_Event Figure 2-3: A small portion of VMM, asdisplayed by the W3MAPutility.
In addition toproviding a V86 and PMprogramminginterface (accessible to DOS and Windows applicationsvia INT 2Fh function 1684h),
Unauthorized Windows 95
we see here that VMMprovides 179h (377) services to other VxDs. I’ve
listed justthefirst fewhere.
You can examine VMM‘codefor theseservices if you have a Win-
dowsdisassembler (such as my Windows Source product from V Communications) or a debugger suchas Soft-ICE/Windowsfrom Nu-Mega Technologies (which is whatI’ve usedin mostcases for this book). For example,the codeforthefirst few VMMservices namedis notparticularlyexciting, but lookingatthis code is a good way to get acquainted with VMMand 32-bit protected-mode code in general:
Get_VNM_Version 0028:Co00zA08 8800040000 0028:co002A00 0028: C00 0028:Co002A10 C3
.
NOV XOR cue RET
EAX, 00000400 CK, ECX
In Figure 2-3, W3MAP said that, in VMMon disk, Get_VMML_Version waslocated at 1A08h.Soft-ICE showsthe function at 28:C0002A08h.
Thus, VMMloadedataddress 28:C0001000. While a full address such as
0028:C0002A08hrequires 48 bits (two bytes for the segment, whichis
called a selector in protected mode, and four bytesfor the offset), 32-bit codeusually needs to worryaboutonly the 32-bitoffset. (See the discussion of thunking in Chapter14 for an interesting example in which Win32 code has to manipulatefull 48-bit addresses.) Selector 28h, whichis the code seg-
mentfor VMMandall VxDs,andselector 30h, whichis the data segment, both havea base addressof 0 andalimit (last validoffset) of OFFFFFFFFh. ‘That's a 4GB address space. VxDscan use a 32-bit offset to manipulate anything within this address space. This otherwise-boring Get_VMM_Version service helps introduce
the 32-bit register set. Instead of the 16-bit AX and CXregisters most
PCprogrammers are familiar with, this code is manipulating 32-bit registers called EAX and ECX. EAX, EBX, ECX, and so onarethe native
registers of the 386 and later microprocessors. Most ofthe benefits of 32-bit code involve using these 32-bit registers. For example, to store a 32-bit number, 16-bit code would have to
employa pair ofregisters such as DX:AX: mov mov ax, 5
In contrast, 32-bit code could store the same quantity inthe single
EAX register: mov eax,
12
Chapter 2: Watching Chicago Boot
This notonlyuses oneinstruction instead of two, but becauseit uses
only oneregister, it leaves open morepossibilities for future register use.
‘That's because 32-bit code cangenerally keep more frequently-used valuesin registers than can 16-bit code, which mustthen keep thevalues in slower memory: mov (102h] mov (100h]
Ofcourse,if a program doesn’t manipulate any32-bit quantities, it’s unlikelyto see anybenefits from movingto 32-bit code.Infact, there’s a downside to 32-bit code. Notice in Get_
|_Version that to return the
ion number(here, 0400h for Windows4.00; hmm, shouldn’t that be 05Fh for Windows 95?) in EAX, the code uses 32-bit numbers. Instead of the three bytes B8 00 04 that 16-bit code would use for MOVAX, 0400h
VMMemploysthefive bytes B8 0004 00 00 for MOVEAX,0400h.
The downside to 32-bit code, then, is that it tends to be fatter. This
shouldn’tbeat all surprising, unless youbelieve in free lunches and the tooth fairy. That 32-bit codeis fatter than 16-bit code is a major reason why Windows 95 which Microsoft decided neededto “run great” in
4MBof memory — is not a 100%32-bit system. According to Adrian
King, “a conversion to 32-bit code would have increased the memory requirement[for Windows 95] byclose to 40 percent”(Inside Windows
95, p. 150). Eventhough wegot a fair amount of mileage outof it, Get_VMM_
Versionis a pretty boring function. Here’s the code for the next VMM
service whose name W3MAP displayedin Figure 2-3: MOV RET
EBX, [C00106E4)
I notedearlier that VxDs can manipulate anythingin a 4GBaddress space, and VMM’°soffhand manipulation of [C00106E4] is a good exam-
ple. It’s obvious fromthe codethat inthis particular configuration, the four bytes (DWORD) at C00106E4hholdthe handle ofthe current Virtual Machine (VM), which Get_Cur_VM_Handlereturns in the EBX. register. In VxD code, EBX generally holds a VMhandle. ‘To call Get_Cur_VM_Handle, a VxDwriter just includes the VUM -INC header file and uses the macro VMMeall Get_Cur_VM_Handle. When the VxD source code is assembled, this turns into an INT 20h followed by the DWORD 010001h:
Unauthorized Windows 95
Veal] Get_Cur_VM_Handle 20h nt dd o1eva1h You can see in the W3MAP outputin Figure 2-3 that VMMhas VxD ID #1 andthat Get_Cur_VM_Handleis function 1; hence the magic number 10001h. Windowsuses INT 20h for VxD dynamic linking. VMM contains an INT20h handler; wheneverit encounters an INT 20h,it looks at the magic DWORDfollowingtheinstruction,uses this tolocate the 32-bit address of the function,and replaces the INT 20h DD with a 32-bit CALLtothe function:
trp INT 20h call CC
010001h
Actually, I lied. That’s what VMMin Windows 3.x would dowithcalls
to Get_Cur_VM_Handle. Things arealittle different in Windows 95. For a selected set ofheavily used small functions such as Get_Cur_VM_Handle
and Get_Cur_Thread_Handle(discusseda little later in this chapter), VMMs& dynamic linker replaces the INT 20h DD notwith a CALL tothe function, but with the actual inline contents of the function:
; INT 20h 00 010001h mov ebx [coe106e4n] Clearly, the DWORDat C00106E4his the current VMhandle: dd coole6es 0030:C00106E4 C51Z00E8 Here, the current VMhandle is C51200E8h.Byitself, this number isn’t very interesting. However, a VMhandleis a 32-bit pointer to a VM. Control Block (VMCB), so C51200E8h must be the VMCBofthecurrently running VM. Let’s see what a VMCBlookslike:
‘Thefirst few fields in the VMCBare documentedin the VMM.H and VMMLINCheader files that come with the Windows DDK: flags * of VM mapped high *
Chapter 2: Watching Chicago Boot ULONG CB_Signature If youtreatthis Cstructureas a template andlayit over the hex dump just shown,you'll see thatthesefields have the followingvaluesfor this VM: Field CB_VM_Status CB_High_Linear CB_Client_Pointer CB_VMID CB_Signature
Value 00008802h ©5000000h COEE6F70h 00000002h 62634D56h(‘VMcb’)
CB_VM_Statusholdsupto 32 flags thatindicatethe status ofthe virtual machine, such as whetherit’s running in the backgroundorin exclusive mode, whetherthere’s a protected-mode program runningin the VM (and if so, whether it’s a 32-bit program), whether the VMis cur-
rently blocked on a semaphoreorhasreleasedits timeslice, and so on. CB_High_Linear (such as C5000000hinthis case) is particularly use-
ful to anyoneinterested in communicating from one VMtoanother:it’s the base of a VM’s address space, whether or not that VM is currently running. For example,if a programin another VM wantedto access something at real-mode address 00A6:0330in this VM, it could do so with the address C5000000h + A60h + 0330h = C5000D90h,
Thefirst fourfields in the Windows 95 VMCBareidentical to the Windows3.2 VMCB. Anewfield is the ‘VMcb’ signatureat offset 10h.
‘This was introduced in Windows95 as part of VMM/VxD parameter validation. Aservice that expected to be passed a VMhandlein EBX, for example, could do a CMP [EBX+10], 62634D56h. While the VMCB has changed quite a bit in Windows 95 fromits
format in Windows3.1 (see Kelly Zytaruk, “The Windows3.1 Virtual Machine Control Block,” Dr: Dobb’s Journal, January 1994 and February
1994), and while thisis just one of many changes in VMM,fundamen-
tally the Windows95
Mis an improvedratherthan a rewritten ver-
sion of the Windows 3.1 VMM.
Indeed, Microsoft Systems Journal's first article on Chicago (January 1994, p. 15) noted that “Manyaspects of Chicagoare similar to what you
already know from Windows3.1, especially regarding virtual machines.” Thisis a far more accurate picture of Windows 95 than,say, the claim that “the entire operating systemis freshly designed from the ground up;” whichis what Microsoft Systems Journal printed the month after.
Unauthorized Windows 95
(See the sidebar, “A complete rewrite?” which waspresented earlier in this chapter). Unfortunately, however,the fact is that very few Windows program-
mersactually do know aboutvirtual machines in Windows3.1. Look in the index of several Windows programming books, and the chancesare slimthat you'll find any mentionof virtual machines, VMM, VxDs, or
86 mode. Even in supposedly “heavy metal” books suchas the one I coauthored, Undocumented Windows, the treatment of these “V”subjects is
pathetic. To find out aboutthese topics, youhad to turn to bookstargeted specificallyat device-driver writers. Unfortunately, by takingcrucial infor-
mation aboutthe core of the Windows 3.x operating system and packaging it as information onhowto write device drivers (yawn!), Microsoft
effectively excluded the vast majority of Windows programmers. Inside Windows 95 (p. 129) observes that “The Virtual Machine Manager
is the single mostimportantoperating system componentin Windows95.” Now,theinteresting thing aboutthis statementis that the same thing could havebeen said about the VMMin Windows3.x Enhanced mode.
‘This makes the general neglect of this subject prior to Windows95all the morepuzzling. Weall had a 32-bit protected-modeoperating system right in front ofour faces and nevernoticedit! Atthe sametime, VMMin Windows 95 is substantially larger than ‘VMM in Windows3.1. We sawin Figure 2-3 that Windows 95’s VMM
provides377 services; the one in Windows 3.1 provides only 241 services. So, in oneverysuperficial sense, Windows 95’s VMM is almostone-third new. Here are some of the new VMM services in Windows 95:
010079 o1e0fa 0100fD o100fc
@ @ @ @
oaoo1e 000073F4 00001b4c 0000IcIC 00002650 000265¢ 00002710 00002733 oa000de anev6c6s 00006f5@ oae7f1e 0908023 0002754 o0007F40 @ 0000085 20000e8c anon
GetThreadTimeS)icePriority et ThreadTimeS]icePri hedule Thread Event ncel_Thread_Event ‘me_Out Set_Async_Time_Ou ateThread _DestrroyMutex _GetNutexOwner Cal1_When_Thread_swi ead YNMStartThread TerminateThr: Get_Cur_Thread_Handle Tes ad_Handle Get_Sys_Thread_Handle
Chapter 2: Watching Chicago Boot You probablyaren’t shockedto see that manyof the new VMM funetionsrelate to threads and to synchronization objects such as mutexes (mutualexclusion). The Win32 thread and synchronization APIs in Windows95 are based on this VMMfunctionality. Let’s look at the code for two tiny thread-related VMMservices: ur_Thread_Handle 0028:C001E85 8830700601C0 028: COODLESB C3
mow RET
£01,(C0010670)
MoV
E01 ,(C0010674}
Get_sys_Thread_Handle 0028:COQ01E93
883074060100
0028:COOO1EAO C3
RET
Just as VxDsgenerally use EBX to hold a VMhandle,in Windows 95 theygenerally use EDI to hold a thread handle. Wecan see thatin this configuration, VMMstores the current thread handle at CO0010670h andthe system thread handle in the DWORDthatfollows it. Here, the current thread happened to bethe systemthread: 0030:C0010670 C4520298 c4520298 thread handleis a 32-bit pointer to a Thread Control Block (THCB).
We can use the debuggerto display a THCB: dd ¢4520291 0030:C4520298 0030:C45202A8 0030:C4520288 0030:C45202C8 0030:¢4520208
poo00000 CO@ODI8C 000070E8 01000000 aae0000
Cooleczc C45200E8 00000000 00000000 cOFDeDAC
Cooloc2c O12FO001 O0A70117 90000000 Coeoniec
42434854 000116 0000024 00100005 80001000
# Paacnnaraes’, ‘ eel
Other than the THCB signatureat offset 0Ch, it’s a little hard to see
what’s going on here. However, the VMM.Hfile that comes with the DDKhasa Cstructure for the THC struct teb_s ( ULONG —TCB_Flags; * Thread status flags */ /* Used internally by VMN */ ULONG TCB_Reservedl: ULONG
TCB_Reserved2;
ULONG CB Signature ULONG —TCB_ClientPtr: ULONG USHORT USHORT ULONG
ULONG
TCB_VMHandle; TCB_ThreadId; TCB_PMLockOrigSS; TCB_PMLockOrigESP;
TCB_PMLockOrigEIP:
ULONG —TCB_PMLockStackCount USHORT TCB_PMLockOrig¢S USHORT TCB_PMPSPSelector ULONG TCB_ThreadType
/* Used internally by VMM *,
* Client registers of thread */ /* VM that thread is part of */ * Unique Thread ID * * Original SS:ESP before lock stack *,
/* Original CS:EIPbefore Tock stack */ * dword passed to VMNCreateThread *
Unauthorized Windows 95
USHORT UCHAR UCHAR USHORT
/* reusable: for dword align */ i for dword align */ /* extended error Locus */ Code */ * extended error ba fo action + ie tla * pointer *, s
Thereare a fewinteresting things here — note, for example, that ‘THCBs are backlinked to VMCBs — but there’s one itemthatreally jumpsout: USHORT TCB_PMPSPSelec
Now, I ask you: How can anyoneclaim that Win32 applications don’t use
MS-DOS when, in the documented thread structure, there’s a
field that holds a PSP? We saw in Chapter 1 that Win32 tasks have
PSPs, Wesawthat this flowedlogically from USER32’s dependence on
the Win16 USER module. But, given
Microsoft’s frequentclaimsthat
“Windows 95 finally breaksall ties with the real-mode MS-DOS code,”
it’s something of a shock to see the primary DOSdatastructure, the
PSP,explicitly mentionedin the middle ofone of the key Win32 data
structures, the thread.
Butlet’s see if it’s really a real-mode DOSPSPthateach threadis connected to. Laying the VMM.H C structure over the hex dump, we see
that, for this particular thread (which, you'll recall, is the system thread), TCB_PMPSPSelector is 00A7h. The name says “PM”and “selector,” so
it must be a protected-modeselector to a PSP. Let’s look at 00A7 in a debugger: 9F 00 9A FO FE-10 @A7 0010 35 FD 01 2 [DS 1707 00A7:0020 FF FF FF FF FF FF FF FF-FF 00A7:0030 CB 18 80 00 00 00 FC 29-FF
FO 01 FF FF
82 01 FF FF
OC 00 FF FF
3C 02 B7 00
FD F2 OC . we... dk 03 FF FF 5.t 00) 02 ve honalee: 00 00 00 )
Thosefirst twobytes, CD 20,are a dead giveaway: it’s a PSP. But just to be sure,let’s seeif it has an environmentsegmentatoffset 2Ch. Here, the WORD at 2Ch
is 0OB7h:
4E49 4F44 537 5400 £49 4F44 5357 5000 5000 5441 3048
Chapter 2: Watching Chicago Boot
Lookslike an environmentsegment, all right. This is getting good. Howaboutthe parentPSPatoffset 16h? Hmm, the WORDatoffset 16h is 17D5h, which somehowlooks like a real-mode paragraph address, not a protected-mode selector. In Soft-ICE,putting an & before an address specifies a real-mode address: db 817d5:0
Sure enough, another PSP.It’s little strange that the system thread’s PSPholdsthe protected-modeselectorofits environmentandtherealmodesegmentofits parent, but otherwiseit’s a PSP. Yes, but is it in conventional memory? Werethis structure located in
extended memory, it wouldn’t matterifit lookedlike a PSP — DOS wouldn’t be able to touchit,so it would be a protected-modestructure with the mere form of PSP. To be a genuine DOSdata structure, it must belocated in conventional memory. Tosee if this PSP is located in conventional memory,we can use the debugger to examine the Local Descriptor Table (LDT) entryfor selector 00A7h:
lat a7 Q0A7
Datal6
Base=00018B80
Lim-O0Q0000FF
DPL=3
P
RW
‘Theaddress 18BBOhis definitely in conventional memory. Let’s just double check that this is a PSP: d 618b! 18BB: 0000 82 OC 3C FD F2 OC cme Ge 1888:0010 35 FD 74 01 01 02 03 FF FF 5.t 18BB:0020 FF FF F FF FF FF FF FF-FF FF FF B7 00 24 02 . rmnavek
‘Thisstructure at real-mode address 18BB:0looksprettysimilar to the structure we dumped outat protected-modeaddress 00A7:0000.It had better look similar, because it’s the exact same structure! Because selector
Azh hasa base address of 18BBOh, protected-mode address 00A7:0000
and real-mode address 18BB:0000 point to same block of memory. And this block of memoryis a DOS PSP. We'll lookat these thread PSPsin Chapter 13 (in the “Win32 and the PSP”section). Note, though, that each thread does not haveits own PSP. Instead, a PSP goes with a Win-
dowstask, and a task can have more thanonethread. Ratherthantryto figure out what’s whatin the THCBfroma rawhex dump, we can use the Soft-ICE THREAD command:
Unauthorized Windows 95
thread C4520298 RingdTCB ID intext Ring3TCB Process TaskDB PDB Owner 4520298 0001 COFD3B7C 81178314 8117B23C 0097 00A7 32 YN 01 B:000001F8 SS:ESP-OCCB:00000226 DS-0000 ES-FFFF FS=0000 GS-0000 607 EBX-00010018 ECx~00e20004 —_EDx-a0000004 80 £D1=00000090 EBP=00000000 ECODE-conde0e4 occ = vaeoaee0 vPico 0000 00000000 SHELL 004 COFDBEAS ¥ 008 - corD1a34 VWI @0DC = COFDIZ04 PAGESHAP The Soft-ICE output indicates that C4520298h is the Ring 0 THCB
for use by VxDs. A Win32 application that called GetCurrentThreadId
would get backa different handle: the one Soft-ICE identifies as the Ring 3 THCB. (See the CHGDIR.C Win32 programin Chapter 13 for an
odd use of GetCurrentThreadId.) The TLSreferred to by Soft-ICE means Thread Local Storage. We can see that some VxDs such as VPICD, SHELL, and so on, store variables on a per-thread basis. As instance data is to s (see Chapters 3
and 4), TLSisto threads.
We werelooking at newfunctions provided by VMMin Windows95.
Besides thread and synchronizationservices, anotherinteresting set of
new VMMservices provides theability to undo someofthe older VMM services. For example, VxDs have always beenable to hook I/O ports(or, “call this function whenever someone does an IN or OUTtothis I/O port”), using VMM’°s Install_IO_Handler and Install_Mult_IO_Handlers
services. Similarly, VxDs could hook the V86 interrupt chain, hook V86 faults, and even hook deviceservices. (In other words, a VxDcanintercept all calls to any VMMVxDorservice such as Get_Cur_VM_Handle, either to spy on or modifytheservice.) But there was never a provision for removing these handlers. With Windows 95 there must be such a provision, because dynamic VxDscan be unloaded andreloaded due, for example, to Plug and Playevents. So ‘VMMin Windows 95 provides new removal functionssuch as:
010116 010117 010118 010119 O1@lla 01011b @lelic
@ @ @ @ @ @
90001161 900010c5 o0000bec 00001520 a0001
Remove_10_Handler Mult_10_Handlers _V86_Int_Chain Fault L Unhook_VMM_Faul t Unhook_Device Service
But, wait, there’s more! Mostof the new Win32 memory management
functionalityin Windows95, such as memory-mappedfile I/O (which in
Chapter 2: Watching Chicago Boot
essence can make a datafile into a Windowsvirtual-memoryswapfile; see the discussion of memory-mappedfiles in Chapter14), is based on a set of new services provided by VMM: Q1011d O101ie 01011 010120 010121 010122 010123 010124 010125 010126 010127 010128
@ @ @ @ @ @ @ @ @
000001f8 00001890 @0001bc7 00001b20 ao001b99 e000 00000584 0000034) 000005¢0 00000334 @ 0000745¢ @ 00001770
_NNReserve _MMCommit _MMDecommit _MMRegi sterPager _NMQueryPagerInfo MM isterPager _MMCreatec: —_NMDestroyContext _MMAttach _MNFlush _MMCopy _MMCommitPhys
All registry access goes through a set of new VMMfunctions; the Windows registry APIs are just wrappers aroundcalls to VMM: 010148 @ 00005066 010149 @ ao00s 010142 @ 00005057 81014b 00005070 01014¢ 00005075
010144 @ oon0so84 O1014e @ 0000503
_RegOpenkey _RegCloseKey _RegCreatekey .gdeleteKey _RegEnumKey
QueryValue _RegSet Value
Then,there’s newschedulerstuff: 010160 @ ao00abb2 —Time_Slice Sys_VM_Idle 010161 @ 00008b1c Time_STice_STeep 00008784 Boost_With_Decay 010: 00008643 Set_Inversion_Pr 8 010164 000086ab —Reset_Inversion_Pri 010165 @ 00008668 —Release_Inversion_Pri
Andon,andon.... But with all this new VMMfunctionality, it’s important notto lose sightofthe fact that Windows 95’s VMMis simply the nextiteration of the same VMMthatappeared in WfW 3.11, in Windows 3.1 Enhanced mode, and in Windows 3.0 Enhanced mode. It’s quite sig-
nificant that in WfW 3.11, Microsoft could take an early pre-beta version of32-bitfile access from the Windows95 project anddropit in with an
essentially unchangedcopyofthe Windows3.1 VMM. Thefunctionality provided bythe earlier VMMprovided a solid foundation on which to build Windows 95.
Unauthorized Windows 95
VADS: TSRS of the 1990s We've just looked at VMM. Rememberthat about 40 other VxDsare also part of VMM32.VXD.The [386Enh] section of SYSTEM. INIuses asterisks to indicate VxDsthatare built into VMM32.VXD(such as device=*vpicd anddevice=*v86mmgr). These VxDsinclude the Windows hardwarevirtualization layer, which provides 32-bit protected-mode emulation of most standard PCandBIOSfunctionality. Here are just a fewexamples: VxD vpicD VDMAD VKD vob vMD vio 10S The Windowsfile
Description Virtual Programmable interrupt Controller (PIC) Device Virtual Direct Memory Access (DMA)Device Virtual Keyboard Device Virtual Display Device Virtual Mouse Device Virtual Timer Device 1/0 Supervisor (formerly BLOCKDEVandVirtual Hard Disk Device)
ystemalsolives
inside VMM.
XD;for example:
VxD
Description
IFSMgr VCACHE VFAT VSHARE
Installable File System (IFS) Manager Virtual Cache Virtual DOSFile Allocation Table (FAT) system VxD replacementfor SHARE.EXE
Let’s lookat just one of these examples in more detail. Here’s a small part ofthe verbose output W3MAPshowsfor IFSMerin VMM32
Manager
Chapter 2: Watching Chicago Boot
400006 40000.
@ @
ete, 40005F @ 400060 @ 400061 @ 400062 400063 400064 @ 400065 400066 @
0000194 0000ef7c 00002130 00000401 ao0e1628 onood « eo0099ba 00003Fd o0012 enad 00007. onoan4z 00007 0000
—IFSMgr_Get_NetTime —IFSMar_Get. IFSMgr_Setuy IFSMgr_DerefConnection —IFSMgr_ServerdO mplete
IFSMgr_DbgSet TFSMgr_Win3:
tendedHandle
Given that IFSMgritself has been publiclyavailable since the introduction of WFW3.11 in late 1993, it’s rather shocking that the program-
mer’s documentationforthisvital interfaceis available only as part of the
Chicago beta: Why should a developer sign a Chicago beta NDAto learn
aboutthefile system of a released product? Furthermore,as of this writing, the documentation in the Chicago DDKis limited to two rather incomplete headerfiles, IFSMGR.INC and IFS.H. And otherparts of
32-bilefile access, such as VFAT (whichis also part of the released WEW 3.11 product) appear to not be documentedatall. Even though the IFSMgr headerfiles included with the Windows 95 DDKarerather bare-bones,theycanstill provide us with importantinformation abouttherelationship of Windows 95 toMS-DOS. IFSMGR.INC has the same referencesto the SFT (the real-mode DOS SystemFile Table)
that wesee in the W3MAP output. There’alsoan interesting reference to IFSMgr_ServerDOSCall, which emulates the odd undocumented INT 21h function 5D00h(see Undocumented DOS, 2ded., p. 295, 723).
Wecouldspendages looking at each of the VxDs in VMM32.VXD. Besides the ones already mentioned,the following VxDsare also quite important: VxD
Description
WWwIN32 VCOND VXDLDR CONFIGMG DOsMGR V86MMGR
VxD to support Win32applications in Windows 95. Virtual CONDevice; used for Win32 Console applications Dynamic VxD loader/unloader; usedin Plug and Play Plug and Play Configuration Manager Windows DOSextender; providesprotected-mode INT 21h V86 Memory Manager; provides XMS, EMS,DOSextender translation
SHELL
\xD to access WindowsAPI; includes “Appy Time”
Unauthorized Windows 95
Well, that’s enough about VMM32.VXDforright now.It was a long time ago, but you maydimlyrecollect that we were walking through the
Windows bootprocess and had encounteredthese twolines in Figure 2-2: OPEN C:\WINDOWS stem\vam32.vxd EXEC C2 \WINDOW: system\ymm32. vxd Throughout Figure 2-2, we can see Windows 95 (whichatthis pointin the bootprocessis just a collection of VxDs) look forvarious real-mode DOSdevice drivers, most of which I didn’t haveinstalled: OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN
QENM3B65 386MAXSS SMARTAAR $DebugDD NOISHLPS IFSSHLPS CONFIGS SCSIMGRS
[FAIL [FAIL [FAIL 2 [FAIL 2) [FAIL 2
+
[FAIL
Quarterdeck QENM/386 Qualitas 386Max Sma WOEB386.EXE (Windows ke NDISHLP.SYS (for NOIS 2.0 TFSHLP. SYS CONFIGS in WINBOO
debugger)
indows95 isn’t trying to locate these real-mode DOS device drivers so
it can push themaside. Instead, Windows95is trying to locate these realmodedriverssothat, whenitfinds one ofthese drivers, a VxD will communicate withit via DOS IOCTL (INT 21hfunction 44h) calls, handit
a V86callback, andso on. Throughout Figure 2-2, we also see Windows 95 loading a wide variety of additional VxDs (with .386 or .VXDextensions) that aren’t located
inside VMM32.VXD. In this particular configuration, for example, SYS-
TEML.INIcontained device= directives to load the 32-bit protected-mode networking software:
OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN
C:\WINDOWS\ system\ vst C:\WINDOWS\system\ vr C:\WINDOWS\system\ vn: C:\WINDOWS' C:\WINDOWS\sy C:\WINDOWS\ sys C:\WINDOWS\sy: C:\WINDOWS\system\ne C:\WINDOWS\system\nd C:\WINDOWS\system\nd C:\WINDOWS\system\ms; C:\WINDOWS\system\ee
rver t access Network redirector Virtual NetBIOS (INT 5Ch, etc.) Microsoft NetWare-compatible protocol Windows Soc r Novell 1PX Windows Sockets Net ded User Interface Map between NOIS 2.0 and 3.0 “ODI support mapper for ODI MLIO" ntel Eth 16 (NDIS 3.0)
The EE16.386 VxD at the bottomof this
is what doesactual
“work”: talking to the network adaptercard. Asis typical in networking software, a packet of data must negotiate manylayersbeforeit is sent over the wire to another machine.
Chapter 2: Watching Chicago Boot
Microsoft's Windowsfor Workgroups3.11 Resource Kit contains reasonable descriptions for manyofthesefiles and for how theyall fit
together. Adrian King’s Inside Windows 95 has a complete chapter on Windows 95 networking (pp. 341-380). After leaving Microsoft, King was in
charge of developmentat Artisoft, makers of the famous LANtastic peerto-peer network,so thisstuffis right uphisalley. Returning once again to Figure 2-2: all these .386 and .VXDfiles use
the 32-bit Linear Executable (LE) file format(the LX formatused by OS/2 2.x 32-bit applicationsis a variant of the LE format). The
LEDUMPutility from the Unauthorized Windows 95 disk displays the
contents of these VxDs. For example, NDIS.386 contains the 32-bit
protected-mode implementation of version 3.0 of Microsoft’s Network Device Interface Standard (NDIS): C:\UNAUTHW>edump \windows\system\ndis. 386 aooossi2 004512 Table @ 00000eb0 (57 services) 280000 00000920 NdisGetVers aeo00cc5 —NdisATToc Lock 9000cf9 —_NdisFreeSpinLock 280 @0000cd9 —NdisAcquireSpinLock 280004 @ 00000ced —_NdisReleaseSpinLock 28002 @ @ @ 280030 @
00000d50 09000455 0000352 00003d5F
—NdisSend NdisTransferData NdisReset —NdisRequest
280039 280032 28003b 28003c
00002d5a Q0000dSt 00003478 00003d7d
NdisCompleteSend Ndi sCompleteTransferData Ndi sCompleteReset —NdisCompleteRequest
@ @ @ @
In addition to showing Windows95in the process of loading those VxDsthatare explicitly requested with device= statements in SYSTEM. INI,Figure 2-2 also shows the Windows95 I/O Supervisor (IOS) dynamically loading VxDs from the IOSUBSYSsubdirectory. Theseinclude the RMM,voltrack, and DiskSD VxDs. RMMis the Real Mode Mapper, which makes a real-modedisk driver look as though it were a protectedmode FastDisk driver. In Windows 95, 32-bitfile access requires 32-bit disk access,so if you actually have a real-modedisk driver (DBLSPACE. BIN will be the best example until Microsoft ships a DbISpace VxD for Windows 95), RMM makesit appear as though it were a VxD. The voltrack VxD takes care of volumetracking for drives with removable
Unauthorized Windows 95
media, suchasfloppydisks or tape backup. DiskTSDisa typespecific
driver responsible for mapping logical requests to physicaldisk requests. ‘Toward the bottom of Figure 2-2, we can see that Windows95 looks for a batchfile called WINSTART.BAT. Asnotedearlier, I edited the figure at this point, because INTRSPYshowed Windows95 searching for
thisfile in every subdirectory on the PATH.I don’t have a WINSTART-.BAT, so the search was unsuccessful. Whenthis batchfile exists,
though, Windows95 usesit to run DOSsoftware (generally TSRs) in the System VM. There’s a brief discussion ofWINSTART.BATat the end of
Chapter 6. Notethatit is not somevague entity “Windows95” that
looks for WINSTART.BAT, butspecifically the DOSMGR VxD within ‘VMM32.VXD.
Atthe very
end ofFigure 2-2, we see that Windows95 e
KRNL386.EXE. This is the Win16 kernel, which we'll lool
moments. Again,note that it’s not some vague “Windows 95”that loads KRNL386.EXE: the SHELL VxD within VMM32.VXDis what loads KRNL386.EXE. SHELL willload anyfile called KRNL386.EXE; we'll
see in Chapter6 thatthis is quite significant.
While we've spenta lotoftime looking at the VMMand VxDlayer
of Windows95, our examination has obviously been superficial: not a grandtour of Chicago, but a hurried and harried look at a few ofits
undergroundpassages, plumbing, and sewers. However, hopefullyit has at least given youthe flavor — or perhapsthe smell — of the Windows 95 operating system.
Notice that even though we haven’t lookedat the Win16 or Win32 kernelsyet,I’malready referring to the operating system. That's because
VMMis the Windowsoperating system. It will probably require the remainderofthis book to convince you ofthis. In the meantime,try to remembertwothingsas youread along:first, that the VMMis what
makesit possible for Microsoft to call Windows 95 a complete operating system, andsecond, that the VMMwasalso in the Windows3.x operating system. Therefore, to the extent that Windows 95 is a complete operating system, the same thingcan be said of WfW3.11, Windows 3.1 Enhanced mode, and even Windows3.0 Enhanced mode. Now, if VMMis the operating system, what are these VxDs we've seen such as IFSMgr, DOSMGR, VPICD, and soon? Thereis very
general agreement that VxDsplay an enormousrole in Windows 95. For
example, Microsoft's “Chicago” Reviewer's Guide says:
Most computer system functionality and support is handled by VxDsin Chicago rather than by real-mode codeor BIOSroutines. (p. 84)
Chapter 2: Watching Chicago Boot
Chicago's networking componentsare built as Windows VxDs. (p. 132) Virtualdevice drivers are anintegral part of the Chicago operating system and have a more importantrole than in Windows 3.1, as many operating system components. are implemented as VxDs. (p. 85)
Indeed, to a large extent VxDsneedto be considered alongside VMM. aspart of the Windowsoperating system. In anothersense, though, ‘VxDsare user-installable extensions to the Windows operating system. Asnoted earlier, Microsoft implemented32-bit file access in WW3.11
bydropping some VxDsontopofa basically unchanged VMM. This
meansthat someenterprising third-party vendor could have donethe samething,atleast in principle. In other words, then, VxDsare anintegral(sorry, I mean “integrated”) partof the operating systemthat can be supplied byanyone with a copyof the Windows Device Driver
Kit.
Hmm, VxDsare user-suppliable parts of the operating system. This kind ofcarte blanche for anyone andtheir brotherto dive in and hack the operating system might remindyouof something: the DOS memoryresident program (TSR) craze in the 1980s. Yes, VxDs are to Windows
as TSRswere to DOS. Andagain, this is true not only in Windows95, but also in Windows
3.x. Considerjust two VMMservices:
Call_Priority_VM_Eventand
Hook_V86_Int_Chain. Call_Priority_VM_Event is the whole basis for
inter-VMcommunications in Windows. As the Microsoft KnowledgeBase putsit, “Call_Priority_VM_Event is oneof the mostvaluable virtual device
(VxD)calls available.” Hook_V86_Int_Chainis the whole basis for bypassing DOS. These twoservicesfirst became available in Windows3.0, and
theyremain in Windows95 essentially unchanged (Windows 95 addsa
Call_Priority_Thread_] i here’s a tremendous amountof power — having nothingtodowith devices or device drivers — provided byjust these twoservices, andthey are only directly callable from a VxD.
(Andtheydon’t take American Express.)
Seenfrom this perspective, the names Virtual Device Driver and Device Driver Kit are unfortunate. They automatically turn off most Windows programmers, whoquite sensiblyfeel that device-driver writ-
ingis an area they wouldrather stay awayfrom. More appropriate names
wouldhave been “T'SRsfor Windows” or “Please Hack Our Operating System.”As it is, the names VxD and DDK alienate many programmers who wouldotherwise jumpat this stuff. For xample, Matt Pietrek — the
ultimate operating-systemhackerif there ever was one — hadthe follow-
ing tosay about VxDs in Microsoft SystemsJournal (August 1994, p. 30):
Unauthorized Windows 95
These days some developers are in the habit of saying things like “Chicagois all VxDs.” But while VxDsplay a big role in Chicago, Chicago is not implemented entirely in VxDs. If your programsstaywithin the Win32 API, most ofthe system code your programs usewill be primarily in Ring 3 system DLLs. Unless you have a special needfor thingslike interrupt handlers, you don’t have to write a VxD to run under Chicago.| think large-scale Chicago applications comprised of mostly VxD code will be a rarity rather than the norm. Admittedly, very few Windows programmerswill be using VxDsto write hardware interrupt handlersorto drive devices. But a short time
spent with the DDK should convinceyou that there’s a ton of documentedfunctionalityavailable to VxDsthatis otherwisedifficult or impossible to get to under Windows. Whenever a programmersays that
somethingis “impossible” in Windows,I suspect the correct replywill be “Noit isn’t. Write a VxD.”Just as TSRsallowed DOS programmersto do
the otherwise-impossible in the 1980s, VxDsare goingto let Windows
programmers go anywhere and do anything in what's left of the 1990s. Whetherthis is ultimately a good thing or a bad thing (remember “TSR RAMcram”?; remember “load melast”?) is of course another question.
From KRNLSBG.ENE (0 CABS2.EKE Atthetail end of Figure 2-2, we saw Windows95 (or to be moreprecise, the SHELL VxD) execute the Win16 kernel, KRNL386.EXE. The
Win16 kernelis obviouslya vital part of Windows 95, but I’m not going to say muchabout it here, because Matt Pietrek — yes, the same one with
whom I wasdisagreeing about VxDs a moment ago — doesa superb job discussing the Win16 kernel in his book WindowsInternals. (Matt’s cover-
ageofthe kernelis so thoroughthat the book almost oughttobe called KernelInternals.) Chapter 1 of Matt’s book (“The Big Bang: Starting Up and Shutting Down Windows,”pp. 1-78) covers KRNL386°s initialization
in greatdetail. KRNL386.EXE provides Winl6 KERNEL API functions suchas (to
choose a fewat random) GlobalAlloc, LoadLibrary, LoadResource, FindAtom,andSetSelectorBase. KRNL386 uses the 16-bit Segmented Executable or New Executable (NE)file format. In contrastto the situation
with the W3 and LEfile formats used for VxDs, there are manyutilities that knowabout the NEfile format, so there are plenty of tools you can use to examine KRNL386.EXE. For example, Borland C++ comes with
TDUMP, variousversions of Microsoft C have provided EXEHDR,and
Chapter 2: Watching Chicago Boot
my own WindowsSource product comes with EXEDUMP. (It’s a good thing that Windows 95 has long filenames: the 8.3 namespaceis starting
to get so crowdedthatit’s hard to find reasonable, unique namesforutilities that dumpout executable headers.) You canalso use the Windows 95 shell to look at KRNL386.EXE or
any Win16 executable:just right-click on the executable, and thenselect Quick View fromthe pop-up menu. (We'll see in the following “Exploring the Explorer”sectionthatthis right-click menufacility worksoff the Win-
dows95 registryandis extensible.) Figure 2-4 shows someofthe APIs
exported from KRNL386.EXE. Notall these APIs are documented; the
book Undocumented Windows, which I coauthored,waslargely about those functions exported from KRNL386.EXEin Windows 3.x that weren't mentioned in the Windows programmer’ referenceorheaderfiles. ed
estesWindowsKel neace Veron 400 NeTBIOSCALL NICHSTACKTO PAIVATEPROFILESECTION
LPROOIISTANCE SEINE SETFILEATTRIBUTES
Figure 2-4: Chicago Explorer's Quick View of KRNL386.EXE, showing a few of the more than 200APIs exported by the Win16 keel.
Well, we’ve reachedthe endof the Windows 95 boot process shown back in Figure 2-2. As I pointedoutearlier, Figure 2-2 provides a woefully incomplete picture ofthe Windows 95 bootprocess, because once 32-bit file access kicks in, Windows not only bypasses DOSfor mostfile 1/0calls but also bypasses the INTRSPYutility (whichis a DOS TSR that loads before Windows).
Unauthorized Windows 95
‘To see everything that happensafter the SHELL VxD executesthe Win16 kernel, we need to disable 32-bit file access. There’s a WIN /D:C command-line option in WfW3.11 to disable 32BFA, but this has no
equivalent in Windows95. You’re not supposed to run Windows 95 without 32BFA. However, I found quite by
accident that, in Beta-1 at any
rate, if the I/O Supervisor can’t find an IOSUBSYS subdirectory,it dis-
ables 32-bit disk access in a waythat alsodisables 32-bit file access. If 32BFAis disabled, INTRSPYsees the entire Windows 95 boot
sequence. For example, comparethe following with the bottom of
Figure 2-2 OP
WIN WIN WINDOMS FSSHL :\WIN C: \WIN \WIN C:\WIN HIN \WINDOWS\USER..DA +s \WINDOWS\USER. DAT XOPEN C:\WIN OPEN C:\WINDO WIN RNEL32. DLL WINDOWS\ sy C:\WINOOWS\ SYSTEM L386. EXE
ath for WINSTART. BAT
In particular, note the references to KERNEL32.DLL, whichis the
Win32 kernel. These references didn’t showup in Figure 2-2. Clearly,
the call to open the KERNEL32.DLLfile wasn’t sent down to DOS,and
consequently wasn’t seen by INTRSPY.
The full INTRSPY logis far toolong (about 500lines of OPENsand FINDs)to showin its entirety, so we'll just look at the highlights here. As wejust saw, KERNEL32.DLL is loaded. INTRSPYdoesn’ttell us
who loaded KERNEL32.DLL,though. Thisis aninteresting point
because of something that Adrian King says in Inside Windows 95 (p. 147):
“the 16-bit Kernel module will load the VWIN32 VxDthe first time there’s acall to any 32-bit API. VWIN32 loads the three DLLs and returns to the 16-bit Kernel, which thencalls the KERNEL32 DLL ini-
tialization function. Oncethiscall is complete, the Win32 subsystemis readyforuse.”
Given that the SHELL VxDloads the Win16 kernel,it’ quite reasonable that the VWIN32 VxD wouldload the Win32 kernel. And,in fact, it is VWIN32.VXDthat loads KERN DLL. But the statement by King that I’ve just quotedhas the following footnote:
Chapter 2: Watching Chicago Boot Giventhat the Windows95shellis a 32-bit application, the loading andinitialization of the Win32 subsystem will actually occur during the system startup phase.
Thisimpliesthatif the Windows95 shell were a 16-bit application,
the Win32 subsystem wouldn’t load until you ran a Win32 application. Ir’s easy to make the Windows95 shell a 16-bit application;all you have to do is change the SHELL=CAB32.EXE or SHELL=CAB32.EXE /NE linein the [boot] section of SYSTEMLINI. For example, Windows
is still largelya Solitaire-playing engine, and you can make Windows 95
reflect this fact by temporarily making SOL.EXE(which is a Win16
application) theshell: [boot] shel l=sol. she This produces a version of Windows 95 with which youcando nothing but Solitaire. But does it produce a pure Win16 version of Windows 95? No, of course it doesn’t. Given that KRNL386.EXEthunks up to
KERNEL32.DLLfor someoperations,it’s hard to see how loading
KERNEL32 would await the coming of a Win32 shell that (given the
ease of changingthe shell= statement) mightneverarrive. At anyrate, the VWIN32 VxDhas loaded KERNEL32.DLL. This
DLLofcourse provides the Win32 kernel API, functions generally defined in the WINBASE.H header file such as Create’Thread, MapViewOfFile, CreateFile, and so on. Asnoted earlier, in manycases these Win32 APIs
rely on VMMor the VWIN32 VxD. Win32 executables such as KERNEL32.DLL usethe Portable Exe-
cutable (PE)file format. This is a vast improvementover Microsoft's previous executable-file formats.
Unfortunately, the Windows95 shell currently doesn’t have a Quick View DLLthatdisplays PEfiles, but there are some character-mode utilities available. The Unauthorized Windows 95 disk comes with a
W32DUMPutilitythat displays the imports (APIs used) andexports (APIs provided) of a Win32 PE file. Phar Lap’s TNT product, which
supports the Win32 API under 32-bit protected-mode MS-DOS,comes
with aMAPEXE utility. And Microsoft C++ comes with DUMPBIN,a
Win32 Consoleapplication that not only displays the imports and
exports of a Win32 executable but alsoprovides a /DISASMoption. Here’s a small fragment of KERNEL32.DLL,asdisplayed by DUMPBIN; notethat I’ve just shown the Win32 kernel APIs whose
namesstart with Create:
Unauthorized Windows 95
328\BIN>dumpbin / 39 3A 3B 3C 30 3E
7 48 49 4A 48 4C 40 4E ar 50 51 52 53 54
40 41 42 43. 44 45 46 47 48 49 4A 48 4C 4D 4E 50 51 52 53
\win
s\system\kerne132.d11
CreateConsoleScreenBuffer (0002a8b7 CreateDirectoryA (00012afb) OC ectoryExA (@0012b2d) ryExW (000303c7) CreateDirectoryW (000303be CreateéventA (00012198) CreateEvent (00030340) CreateFilea (00012bf0) CreateFileMappingA (0012240) (000303e2) CreateFileMap CreateFileW (000303eb) CreateKernelThread (000116c7) CreateMailslotA (00011e CreateMailsiotW (00030340) ateMutexA (00012137) CreateMutexW, (000303c7) CreateNamedPiped (0003034) CreateNamedPipeW (000303F4) CreatePipe (00011dc1) CreateProcessA (00012306 CreateProcessW (000303fd) moteThread (000303eb) horea (0001215) Semaphore (00030. CreateTapePartition (000303¢0 CreateThread (0001169 CreateToolhelp32Snapshot (00032b81)
‘Thatlastline is a good excuse for me to point out that KERNEL32 provides a set of Win32 ToolHelp functions to enumerate Win32 processes, threads, heaps, and modules. These functions, such as Toolhelp32ReadProcessMemory, Process32First, Process32Next, Thread32-First, ‘Thread32Neat, andso on, are documented in Microsoft’s TLHELP32.H
headerfile. Naturally, not all functions exported from KERNEL32.DLLare documented(at least in the current SDK). Thefollowing are somethatI use ordiscuss in otherparts of this book: 127 127 GetProcAddress16 (000114eb 60 15F GetpWinl6Lock (0001cd3: BO 1 adLibraryl6 (@0021d52) OT_Thunk (00001 VxDCal1@ (00001 Fc Win32HandleToDosFileHandle (00023094)
VxDCall0is particularly powerful. As shown in Chapter 14 (WIN32PSPC), VxDCall0allows Win32 applicationsto call a set of Win32 services provided by VxDssuch as VWIN32, VMM,and VCOND. ‘Iwoofthe services provided by VWIN32 give Win32 applicationsaneasy way to make
Chapter 2: Watching Chicago Boot
DOSand DPMIcalls. This is important because Win32 applications normally cannotuse direct INT instructions in Windows 95. After KERNEL32.DLL loads, the next interesting thing that INTR-
SPY shows is Windows95 loading Win16 devicedrivers (these Win16 drivers should not be confused with 32-bit VxDs): XOPEN C:\WINDOWS\SYSTEM\ system.drv XOPEN C: \WINDOWS\SYSTEM\ keyboard. drv WINDOWS\SYSTEM\mouse..drv WINDOWS\MOUSE.. INI WINDOWS\ system. ini C: \WINDOWS\SYSTEM\ framebuf.drv WINDOWS\SYSTEM\DIBENG. DLL WINDOWS\SYSTEM\ sound. dry WINDOWS\SYSTEM\ comm. drv KRNL386.EXEuses run-time dynamiclinking to load these Win16 drivers (see InitFwdRefin Windows Internals, pp. 47-50). It’s curious that these Win16 drivers don’t appear in Microsoft’s archi-
tectural diagrams for Windows 95, becausethey playa crucial role in the Windows messaging system. Muchhas been written about desynchro-
nized input queues in Windows95 (Matt Pietrek has a good discussion in
“Investigating the Hybrid Windowing and Messaging Architecture of Chicago,” Microsoft Systems Journal, September 1994) and howthis differs from messaging in Windows3.x, butit’s also importantto note that many aspects of the Windows3.x message system remainrelatively unchanged in Windows95. In particular, Win16 drivers such as MOUSE.DRV, KEYBOARD.DRV, and SYSTEM.DRVarestill involved in the process
of turning hardwareinterrupts into WM_XXX messages.
Windows messages like WM_LBUTTONDOWNand WM_KEYDOWNstartlife as hardwareinterrupts, of course. Hardwareinterrupts are handled by the VPICD(the Virtual PIC Device) VxD, and other VxDs
such as VMD(Virtual Mouse Device), VKD (Virtual Keyboard Device), or VTD(Virtual Timer Device)call the VPICD_Set_Int _Requestservice to simulate the hardware interrupt into an appropriate VM. If the simulated interrupt goes to the System VM,where Win16 and Win32 applicationsrun, it is picked up by a 16-bit Windows device driver such as MOUSE.DRV, KEYBOARD.DRV,or SYSTEM.DRV.
(which handles the timer). If one of these 16-bit device drivers hooks a hardwareinterrupt,it might thinkit’s partying with the hardware, but in
fact it’s just receiving one of VPICD’s simulated interrupts. (Onthe other
hand, someofthese drivers, likeMOUSE.DRY, dotalk directly to the appropriate VxD.)
Unauthorized Windows 95
a} al ee)
User rc
fe S|
‘Nontesident Name Table [Exported Functions}
Em Tatlin Name 5 rteWindows ISRECTENPIY Useretce TMENUITEMCOUNT GeCOFFSETRECT ‘UNINSTALL
e Pee
MSGTHECONNE (SE TFOREGROUNDWINDOW Geroueuestarus INITTHREAD ‘LDeMTwiNDOWs DeSTROYMENU 2 ‘UrbaTewiNbow ISPATCHINEUT WNETUNWATCHOUEUE evra
Figure 2-5: Chicago Explorer's Quick View of USER.EXE, showing a few ofthe more than 400 APIs exported by the Win16 windowing anduser interface module. ‘Quick View
sae) G ed
25 Fpy A) Med.BIC) He
a
S)
Conta Panel Porter Foe
OFFSETVIEWPORTORGEX SETBRUSHORGEX GETTexTeXTENT SETMAPPERFLAGS GETWINDOWORGEX SELECTCUPHGN REATEREGION. SCALEWINDOWEXTEX SETWNDUWORGEX PINAEGION CREATEPENINOIRECT Uneopa’
a
Figure 2-6: Chicago Explorer's Quick View of GDI.EXE, showinga few ofthe almost 400 APIs exported by the Win16 Graphical Device Interface module.
‘Thedevice driver's interrupt handleris responsible for invoking a function in USERwhich,in turn, puts a message on the System Message
Chapter 2: Watching Chicago Boot
Queue. KEYBOARD.DRV’%s INT 9 handlercalls the Keybd_Eventroutine in USER (Undocumented Windows, pp. 467-469). SYSTEM.DRV’s INT 8
handlerinvokes anycallback routinesinstalled with CreateSystemTimer
(Undocumented Windows, pp. 602-607); the SetTimer APIprovided by
USERisbased ona callback that USERinstalls with CreateSystemTimer. in other words, all hardware events seen even by Win32 applications come from Win16 drivers such as MOUSE and KEYBOARD.
Atthis point, the INTRSPYlog shows Windows 95 loading a huge
number of DLLs. Theseinclude GDLEXE, GDI32.DLL, USER.EXE, and USER32.DLL. Figures 2-5 and 2-6 showa few of the many APIs
provided by USER.EXE and GDLEXE. We’renot going to plow throughall these DLLs;it would take far too long andit’s not clear we’d learn anything substantially different from whatwealready knowabout
Jindows 95, anyway. Huge amounts of Windowsfunctionality is provided via DLLs, and in Windows95 this includes Win32 DLLs. There’s
not a wholelotelse to say.
Exploring the Explorer Finally, we cometo the most visible part of Windows 95. Theshell, whichis also sometimes called the Explorer or the Cabinet, is shownin Figure 2-7.
5B My Comper eo 25 FeooyA} (
Pree Fede By Netied Negtcriod 2 Deekten By Bielcone
Figure 2-7: The default Chicago shell provided by CAB32.EXE (a Win32 application).
Unauthorized Windows 95
The Windows 95 shellis a Win32 application, CAB32.EXE: XOPEN XOPEN XOPEN XOPEN XOPEN XOPEN XOPEN FIND FIND FIND FIND : ... XOPEN XOPEN XOPEN XOPEN FIND XOPEN
C:\WINDOWS\CAB32. EXE C: \WINDOWS\SYSTEM\ SHELL32, DLL C:\WINDOWS\SYSTEM\ shel C:\WINDOWS\icocache. dat C:\WINDOWS\SYSTEM\DIBENG. DLL C:\WINDOWS\fonts\c C:\WINDOWS\ cabinet. in C C:\WINDOWS C:\Windows \Desktop C:\Windows \Desktop\*.* Explorer loading lots of stuff here C: \WINDOWS\SYSTEM\LINKINFO. DLL C:\Windows \Programs\Explorer. Ink C:\Windows\Desktop\Windows 95. 1nk C:\Windows \Programs\Ms-dospr. Ink C:\Windows \Recent\*.* C:\Windows \Recent\ReInotes. Ink
But the Windows 95 shell isn’t exactly part of Windows95. It’s
ridiculously easy to change SHELL=CAB32.EXEin SYSTEM.INIto SHELL=WINFILE.EXE or SHELL=PROGMAN.EXEoreven (as we
saw earlier) SHELL=SOL.EXE. Atthe sametime,the highlyattractive shell is clearly one of Windows95’s majorselling points. Another possible sign that major advances (and the Windows95shell is a major advance for the Windowsuserinterface) don’t always require a fundamentally newarchitecture. CAB32 is just an application.
Oris it? Running
DUMPBIN /IMPORTS \WINDOWS\CAB32.0LL
showsthatit appears to use a large number of undocumented Win32 APIs from SHELL32.DLL.(Oratleast, they’re undocumentedat the time of this writing.) For example, here are a few APIs that CAB32
imports from SHELL32: Regi sterShel |Hook FSNot i fy_HandleEvents 153.
SHFindComputer SHFindFiles
Running DUMPBIN /EXPORTSon \WINDOWS\SYSTEM\ SHELL32.DLL turnsupthese, plus many other functions. While a few of these do appear in SHELL.H (forexample, SHFileOperation and ShellExecuteEx), the majorityappear to be undocumented. Running
Chapter 2: Watching Chicago Boot
DUMPBIN /IMPORTS \WINDOWS\SYSTEM\
shows that, in turn, SHELL32 seems to use undocumented functionality from KERNEL32, such as MapLS, QT_Thunk,and ThunkConnect32. But of course SHELL32 is part ofthe operating system,so these are internalinterfaces. Well, perhaps CAB32 is part of the operating system
too. (“It’s Integrated!”) Insteadof using publicinterfaces, CAB32 relies on someintimate knowledge of Windows 95. Hmm,perhaps saying that
somethingrelies on undocumentedfeatures andinsider knowledgeis just anotherwayof sayingthatit’s integrated?
Onething is conspicuously absent from the DUMPBIN /IMPORTS
lists for CAB32 and SHELL32: Object Linking and Embedding (OLE)! Perhapsthiswill change before the commercial release of Windows 95 but — atleast in Beta~1 — the Windows95 shell doesn’t use OLE. This is in sharp contrast to somestatements madein thepress, such as that “Chicago’s shell uses OLE 2.0 extensively” (Ray Valdés, Dr: Dobbs Devel-
oper’s Update, March 1994, p. 6).
Microsoft appearsto have been carefulnotto saythis. In an extremely useful article on “Extending the Chicago Shell” (Microsoft Developer Net-
work News, July 1994, pp. 10-11), Kyle Marsh says merelythattheshell is similar to OLE: The design of Chicago's shell extensionsis based on the Compound Object Modelin Object Linking and Embedding (OLE) version 2.0.The shell accessesobjects via interfaces, and applications implementthoseinterfaces as shell extension dynamic link libraries (DLLs), which are similar to the In-Proc Server DLLsin OLE 2.0.
I don’t know howsignificantthis is, but besides apparently avoiding anythingbut the most abstract, conceptual use of OLE 2.0 in the Windows95 shell, Microsoft seems somewhat down on OLEin general. In
Inside Windows 95, Adrian King comesright outandsays that “Right now, adding full OLE supportto an application is an extremely complex engi-
neeringproject” and “OLEis leading edge technology. Using it nowis
expensive but could also give you a competitive edge in the Windows95 applications market” (p. 220). In an interview in the back of the book, Paul Marit: , “There’s a tremendous amountofheat andlight about ‘things object’ at the moment — mostof which hasnothing to do with
the average enduser. This is truly an industry-induced storm here, where we're just talking to each other” (p. 421). While OLE2.0 itself may amount to nothing more thana very expensive wayfor the PCsoftware industry to talk to itself, the OLE-like extensions in the Windows95 shell look like just the ticket. WhenI used
Unauthorized Windows 95
the shell to get a Quick View of KRNL386.EXE andother Win16 exe-
cutablesearlier, I didn’t mentionthat there’s nothingparticularly built-in about thisfacility. Theability to handle right-click events and add new “verbs”to the shell’s popup menuall worksoffsettingsinthe registry Once Windows95 ships, mostof the utilities for this book could be redone as Windows 95 shell extensions.
Chapter 3
Tne Winpows-DO§ CONNECTION ccording to Microsoft’s “Chicago Questions and Answers” white paper (January 1994), Windows 95 “will be a complete, integrated protectmodeoperating system that does not require or use a separate version of MS-DOS.”Althoughthis, of course, is wonderful news, the technology behind Windows 95 (“Chicago”) is actuallynotall that new:
* Windows 95% much-heralded preemptive multitasking ofthreads is based on improvementsto the old preemptive Virtual Machine
(VM)multitasker in the Windows3.2 Enhanced modeVirtual
Machine Manager (VMM). Atthe sametime, exposing the preemptive multitasker programming interface to mere-mortal application developers — thuslifting it out of its VxD confines — is a major step forward.
* Windows 95’s 32-bit file access is based on that provided much earlier in Windows for Workgroups (WfW) 3.11. To the founda-
tion laid by WEW,andontop of the venerable DOSFATfile sys
tem, Windows95 addslong file and directory names. * Windows95%ability to run Win32 applicationsis based on improvementstothe old Win32s add-in to Windows 3.1
In many ways, then, Windows 95 simply improves on — and makes users and programmers more aware of — features andcapabilities that Windowshas hadfor quite sometime(in the case of preemptive multitasking, goingall the way back to Windows/386 2.0in 1988).
Unauthorized Windows 95
That Windows95is a “complete” operating systemthat “does not
require or use a separate version of MS-DOS”andyetisn’t radicallydifferent frompreviousversions of Windowssuggeststhat perhapsthese earlier versions of Windowswerealso close to being complete operating systems. It also suggests that the connection betweenthese operating systems and MS-DOS was different from what was commonlythought at the time.
Before Windows95, Windows was frequentlydescribed not as an oper-
ating systembutas an operating environment. Afterall, Windows3.x ran
“on top of” DOS;youstarted Windowsbytyping WIN at the DOS C:\> promptor byputting WIN as the last line of your AUTOEXEC.BATfile.
In many ways Windowsseemedtobejust another DOSapplication. Somewhere between Windows 3.0 and 3.1, Microsoft changedthe description on the Windowspackaging from“graphical environment” to “operating system.” But nowthatit wants to promote Windows 95, Microsoft has suddenly discovered that the previous version of Windows
wasn’t a genuine operating systemafterall because it ran on top of DOS. A peek underthe hood showsthat,in fact, “operating system” was
quite an accurate wayto describe Windows
3. Enhanced mode. Cer-
tainly,if Windows95is to be considereda full-blownoperating system, then so must Windows 3.1 Enhanced mode, because they are not intrin-
sicallydifferent. In fact, from MS-DOS5.0 on, Microsoft maintained that Windows 3.4 was notjust some randomprogramthat ran on top of DOS,but ratherpart ofa single integrated system with MS-DOS. Forexample, in a section on “Running Windows with an Operating System Other Than MS-DOS,” the README.WRIfile included with Windows 3.1 states:
Microsoft Windows and MS-DOSworktogetheras anintegrated system.They were designed together and extensively tested togetheron a wide variety of computers and hardware configurations. Running Windowsversion 3.1 on an operating system other than MS-DOScould cause unexpected results or poor performance. ‘The README.WRIfile included with WfW3.11 addsanexplicit note that running Windows with something other than MS-DOS“is not
supportedby Microsoft.” Presumably, “not supported” meansthat running Windowswith anotheroperatingsystem, such as Novell DOS 7 or IBMOS/2, might (inthe words of a warning message inadifferent Microsoft product) “void valuable warrantyprotection provided by Microsoft on this product.” ‘To fairly as es Microsoft's claims for Windows95 as. a complete operating
system, presumablyin contrast to Windows
3.x°s
dependence on
Chapter 3: The Windows-DOS Connection
MS-DOS, youfirst need to understandthe relationship between Windows3.x and DOS: Whatwasthis “integrated system” that Microsoft wastalking about? ‘This chapter and the next examine an INT2Fhinterfacethatis just
oneofthe many ways DOS and Windows3.4work togetheras an inte-
grated system. To explore the DOS-Windowsconnection, this chapter presents a program called FAKEWIN,which examines how DOS (and DOS-basedsoftware such as TSRsand device drivers) reacts when Windowsstarts up. Using FAKEWIN,I'll establish that MS-DOS5.0 and 6.0 knewabout Windows, and that even before Windows 95, Windows was morethan just anotherpretty face. The next chapter examines the output from FAKEWINin moredetail. Other connections between DOS and
Windows, such as Windows’s extensive use of undocumented DOSfunctions and datastructures, are discussed in Chapter 1 of Undocumented DOS(2d ed.) and need not concern ushere. ‘The FAKEWINprogramreveals that, even before Windows 95,
Windows(particularly Enhanced mode) and DOSwereintegrated to such an extent that Windows was notjust anotherapplication that ran on top of DOS. Thanks to the VMMinside WIN386.EXE, it was a true
operating system that used real-mode DOSasanassistant. As Geoff Chappell, author of the book DOS Internals, putsit, “DOSandits device drivers, TSRs,etc. form a subsystem of16-bit drivers for Windows.” The mostyou can say is that, in Windows95, this real-mode subsystem plays a smallerrole thanit did in Windows3.1 and WfW3.11.
Windows INT 2Fi Broadcasts FAKEWIN,asits nameimplies, is a DOS programthatpretendsto be Windows. How does it dothis?
When Windows starts up andexits, it issues four separate INT 2Fh
broadcasts, called Startup, Startup Complete, Begin Exit, and Exit. DOS device drivers and TSRs loaded before Windows can hook INT 2Fh to receive these notifications of Windowsstartup and termination. In
response tothe Startup broadcast (INT 2Fh function 1605h), a device driver or TSR can request that Windowsload a Virtual Device Driver (VxD)or allocate instance data(you'll see what this is in a few moments).
FAKEWINpretendsto be Windowsbyissuing the same INT 2Fh
broadcasts that Windowswould issue. Individual Windows VxDs canalso
Unauthorized Windows 95
issue broadcasts (INT 2Fh function 1607h), thus allowing them to communicate with software loaded before Windows; FAKEWIN emulates one of
thesecalls, too — namely, thecall normallyissued by the DOSMGR VxD inside WIN386.EXE. Finally, FAKEWINemulates a TSR Identify broadcast (INT 2Fhfunction 160Bh) issued by the Windows USER module;
TSRscanuse this broadcast to request that Windowsload a Windowsexe-
cutable, a dynamic link library (DLL), or a devicedriver.
These INT2Fh broadcasts are documentedin Microsoft’s Device Driver Adaptation Guide, included with the Windows Device Driver Kit
(DDK), and inanarticle by David Long on “TSR Support in Microsoft WindowsVersion 3.1” on the Microsoft Developer Network (MSDN) CD-ROM. Butthere are twoserious problemswith this documentation. First, notice that DOSsoftware developers are expected to look in the Windows DDK, of all places, to find whatis basically a DOS interface. It’s true that these INT 2Fh calls are issued by Windows, but that doesn’t
make them part of the Windows API. The Windows INT 2Fh broadcasts are useful only to software loaded before Windows, thatis, to DOS
software.
As you'll see, typical users of the INT2Fh function 1605h
interface include the DOSKEY, SMARTDRY, and EMM386 utilities included with MS-DOS. For better or worse, DOS programmersin the
1990s — even ones whoresolutely “don’t do Windows”
— are going to
have to become familiar with the Windows DDK. Windows is the oper-
ating system now; DOSis just its real-mode 16-bit assistant.
Second, like 99%of the Windows programming documentation,
Microsoft’s documentationfor the INT2Fhbroadcasts explains the interfaceitself, but not howit’s usedin the real world. In this case, Microsoft doesn’t discuss which DOS device drivers and TSRsrespond to
Windows startup by hooking the INT2Fhcalls. If discussing DOSKEY, SMARTDRY,and EMM386 sounds too implementation-dependent,
note that the Windows INT2Fhbroadcasts are hooked notonly by an assortment of DOSdevice drivers and TSRs but more importantly by
S-DOSitself(version 5.0 and later). Let me repeat that:MS-DOS 5.0 andlater hook the Windows INT 2Fhbroadcast. In other words, MS-DOSknows about Windows. DOS
behaves differently when Windows Enhanced modeis running. Windows 3.x is not just any random DOS application, but (pretty much as Microsoft onceclaimed,before it was pushing Windows95) part of an integratedsystem with MS-DOS. Using the FAKEWINprogram, you'll see exactly what Windows and MS-DOS havetosayto each other. FAKEWIN prints anyinformation
Chapter3: The Windows-DOS Connection
returned by DOSsoftware that handles the WindowsStartup (INT 2Fh function 1605h) broadcast. DOSsoftware that hooksthis call can communicate with Windowsin the following (fairly unrelated) ways: * ADOSdevice driver or TSRcan tell Windowsnot to load (for example,if the software is incompatible with Windows). Employing this part ofthe function 1605h interfaceis not recommended. * ADOSdevicedriver or TSR can ask Windows to load a VxD, possibly a VxD embeddedin the samefile as the driver or TSR.(Similarly, DOSprogramscan use INT 2Fh function 160Bh toask Windowsto load Windowsexecutables, DLLs, and 16-bit Windowsdrivers; as with VxDs, these can be embeddedin the samefile as the DOSprogram.) ¢ ADOS device driver or TSR can declare some numberofbytes at some
segment:offset address as instance data. Windowsnormally treats memoryallocated beforeit started (for example, code and data belonging to
DOSorto a TSR) as global memory: a single copyof the memoryis
‘mapped (rather than copied) into each virtual machine (VM). However, this is inappropriate for any DOSdata that mustbeseparate in each DOSbox. For example, the history buffer belonging to a command-line editor such as DOSKEY— if loaded before Windowsrather thanin a
DOSbox — mustbe maintained on a per-VMbasis; otherwise, com-
mandstyped in one DOSbox wouldleak across to other DOSboxes(a probably unintentionalform ofinterprocess communications). Declaring the historybufferas instance data tells Windows to make a separate copyofthe buffer for each VM,while keepingtherest of the TSR as
global data, a single copy of which is mappedinto each VM. Mapping
aliases a block of memoryto agivenreservedlinear address. (See Klaus Mueller, “Think Globally, Act Locally: Inside the WindowsInstance
Data Manager,” Dr; Dobb’s Journal, April 1994.)
* ADOSdevice driver or TSRcan give Windowsthe addressof a functioncall to turn Virtual 8086 (V86) modeoff and on. Expanded memory
managers such as
into V86 mode
EMM386, QEMM,and386MAX putthe machine
formofprotected mode(see Chapter 9) — in order
to emulate the EMSinterface andto backfill empty Upper Memory Block (UMB) addresses. Meanwhile, Windows wants to switch the
machinefromreal mode to protected mode.It can’t dothisif the memory manageralreadyhas the machinein protected mode, so the Windows startup broadcast allows 386 memory managerstotell Windows how it can turn themoffwhenit starts up and back on again whenitexits. If
Unauthorized Windows 95
DOSsoftware has allocated memory (EMS, XMS, or UMBs), the memory manager can handoff control ofthis memoryto Windows, using an undocumented interface known as Global EMM Import. The Windowsinitialization broadcast is shown in Figure 3-1. This
broadcastis similar to the Task Switcher Identify Instance Data function (INT 2Fhfunction 4B05h) documented in Microsoft’s MS-DOS Program-
mer’s Reference. Both broadcasts expect the samestartup info structure; DOSKEYforexampleuses a single block of code to handle both calls. Called with AX = 1605h CX = 0 if okay to start Windows; nonzero if not okay OX flags (bit 0 clear if Enhanced mode; set if Standard mode) DI = Windows major/minor version number (high/low) ES:BX -> 0:0, or previous Win386_Startup_Info_Struc DS:SI -> 0:0, or (if nonzero) indicates that the V86 enable/disable callback already exists INT 2Fh Return: X= 0 if okay to start Windows; nonzero if not okay Win386_Startup_Info_Struct -> SIS_Next_Dev_Ptr = previous ES:BX ES:BX -> Win386_Startup_Info_Struc (see below) DS:S1 -> 0:0, or ¥86 enable/disable callback typedef st ( void far *11SPtr; // segment:offset of instance data WORD IIS_Size; // number of bytes ) InstanceItemStruc;
typedef struct WINFO ( WORD SIS_Version; struct WINFO far *SIS Next_DevPtr: // next startup info struct DWORD SIS Virt_DevFilePtr; // name of Vx0 to load DWORD SIS_Reference Data; 1] ref data for VxD Instance_ItemStruc far *SIS_Instance_Data_Ptr: ) Win386_Startup_Info_Struc; Figure 3-1: If a DOS device driveror a TSR loaded before Windows hooks the Windows initialization broadcast (INT 2Fh function 1605h), it can request that Windowsload a VxDorallocateinstance data.
DOSsoftware that hooks the Windowsstartup broadcastis responsible for maintaininga linkedlist of Windowsstartup info structures.
Before setting ES:BXto the address ofits own Win386_Startup_Info_
Struc, a program hookingthis broadcast mustfirst pass it (unchanged) to the previously installed INT 2Fh handler (see TSRLDR.ASMin Chapter 4 for an example).
Chapter 3: The Windows-DOS Connection
As shown in Figure 3-1, software thatuses this broadcastto return a pointer to a Win386_Startup_Info_Struc mustset the SIS_Next_Dev_Ptr
field in the structure to the address of the previous Win386_Startup_Info_ Struct, whichis returnedfromthe previous handler. FAKEWINwalksthis linked list, printing each structure. For exam-
ple, FAKEWINrevealsthatif you happen to be running the Qualitas
386MAX memory manager andthenstart Windows (or FAKEWIN),
386MAX responds to the INT 2Fhfunction 1605h with the following:
Win386, Vx0 na
ruc at O255:01E2 (386MAX$$ (Reference data: O0530A1E) col :042E
Instance a1 V86 Enable/Disable function:
036£:03D4
(386MAX$$)
Global EMM Import @ OOBDSEACh (version 1.11)
Here, 386MAXis doing several things. First, it’ telling Windows to load a virtual device drivercalled 386MAX.VXD.Second,it’s declaring onebyte ofinstance data at C001:0183. And third,it’ giving Windows the address of a 386MAXfunction to turn V86 modeoff and on. 386MAX also supports the Global EMMImport specification, and FAKEWIN prints the address andversion of the EMMimportstructure. (See Taku Okazaki, “The Windows Global EMMImport Interface,” Dr: DobbsJournal, August 1994.)
Tnoted earlier that the DOSKEY command-line editor declaresits his-
torybufferas instance data and that FAKEWINlets you see how DOSKEYcommunicatesthis information to Windows. Here’s what I wasreferring to: Wins
Inst
artup_Info_Struc at 2996:0248 (DOSKEY)
2996:025D (D0S| em_Struc 09288 (DOSKEY) 2996:0F23 0200 (
FAKEWINhas a -DUMPoptionthatprints the current contents of an instance data block in hex and ASCII. Usingthis option confirms that DOSKEY’shistorybuffer is instance data:
0200 (00SKEY) | 45 00 A | 2E 65 78
6E 20 2996:0F53 | 70 00
E.c:\eps\epsilon exe $*.p.fakewi
| n dump > tmp. tm p.rink, Fakewin >
Unauthorized Windows 95
If you had two DOSboxes open under Windowsandyouused DEBUGorsomeotherreal-mode debuggerin each DOSboxtodisplay the DOSKEYhistory buffer, you'dsee (as shownhere) that each DOS box hasits own separate history buffer, even though onlya single copy of DOSKEYwasloadedbefore Windows. 10F23 0 30 6C OF 40 44 4F 5
00 63 3A SC 65 78 65 20 59 66-6
3 5C 65 70 7, 00 67 72 69
63 3A 5C-65 70 73 5C 65 70 73 65 78 65 2A 00 64 69 72 60 00 60-65 60 00 60 65 60 00
6 :0F30 6C 6F 0 69 72
f Jon.exe $* DOSKEY fakewin
E.c: \eps\epsi lon.exe $¥.dir.d irmem.mem.men.g
‘That's the generalidea behindinstancedata; it takes a single piece of data and multiplexes it among multiple clients. Knowing the differences betweenlocal, global, and instance datais also helpful when trying to understandinstance data. These differences are shownin Figure 3-2. I'll be discussing instant data in moredetail in the “DOSInstance Data and the SDA”section in Chapter 4. Global Data
| veil |vm a j
|
ee
Local Data Windows
Instance Data
ve #l | mae| eel || DATA | (Dara) ee al
Dos
Global data is seen by all. Each VM sees the samedata that was loaded before Windows. Anychange made to this data by one VMwill be mapped to all other VMs.
Local data is allocated separately in each VM. The data in one VM has norelationto the data at the same address in another VM.
Instancedata is loaded before Windows and then copied (or instanced) to the same address in each VM. However,after the data is copied to each VM, changes madeto data in one VMare notseen by the other VM.
Figure 3-2: Thedifferences betweenglobal, local, and instance data.
Chapter 3: The Windows-DOS Connection
Embedded UxDS In thefollowing sample output from FAKEWIN,the SmartDrivedisk cache and DoubleSpacedisk compression are asking Windowsto load VxDs(DriveSpace in MS-DOS 6.22 does the samething): Struc at 2AF4:12EF MARTORV) RTORV.EXE (Referenci data: 2AF41301)
Win386_Startup_Info_Struc at 1551:3F10 (DBLSYSHS) VxD name: H:\DBLSPACE.BIN (Reference data: 15513F32 No instance data But SMARTDRV.EXE and DBLSPACE.BINdon’tlooklike namesof Windows VxDs — they’re DOSfiles, right? As mentioned earlier, DOS programs can have embedded Windows executables. Here, SMARTDRV.EXE and DBLSPACE.BINboth have embedded VxDs. (DRVSPACE.BIN in MS-DOS 6.22 hasone, too.)
Actually, it’s not quite accurate to describe these as DOS programswith embedded Windowsexecutables. They’re really Windows executables that, like every Windowsexecutable, have an embedded DOSprogram. Usually that DOS programis a small stub that prints a messagelike
“This programrequires Microsoft Windows.” However,it’s just as easy
to make the embedded DOSprogram dosomething useful. In the case of SMARTDRV.EXE and DBLSPACE.BIN,the embedded DOS program
is part of the DOSsystem software. We can use the VXDSHOWutility from the Unauthorized Windows
95 disk to the VxDs embedded in these DOSutilities. While we're at it, we can alsolook at another DOS utility with an embedded VxD, EMM386.EXE. Figure 3-3 showstheresult.
NAUTHWOvAdshow he pace. bin Dsvxo on: "Win386 DSVXD Device (Version 1.0)" @ 00000140 ono00000 Undefined) jaeoo00e 0000057
C:\UNAUTHWDvxdshow c:\dos\smartdry. exe SDVXD M “Win386 SDVKD Device (Version 2.0)"
Unauthorized Windows 95
SDVXO_DD8 @ 00000060 Start @ 000:00000000 Version 3.00 nit order: 80000000 (Undefined) DDB_Control_Proc @ 00000000 UNAUTHW>vxdsniow c:\dos\enm386.exe Module name: LoadHi cription: "Win3B6 LoadHi Device (Version 1.0)" dHi_D08 @ 0000124 Start @ 0003:00000000 Device # 001c ion 1.00 order: 00000000 (Earliest same as VMM) rol_Proc @ 0000050 rvice Table @ 00001200 1c0000 @ 0000079d —LoadHi_Get_Version Figure 3-3: Running VxDSHOW with DBLSPACE.BIN, SMARTDRV.EXE, and EMM386.EXE reveals the surprise VxDinside.
It so happens thatthese particular VxDsaren’t especially importantin Windows 95. For example, the SDVxD embedded in SMARTDRV.EXE doeslittle more than allow Windows to do a SHELL_SYSMODAL_
Messagein the event ofa seriousdisk error. However, even
SmartDrv
is loaded in Windows 95, Windowsbasically ignoresit becauseitsroleis taken over by the VCACHE VxD. SMARTDRV.EXEis listed in the
“safe driver” list, IOS.INI, which the Windows 95 I/O Supervisor
(L0S.386) consults to see which real-mode DOSdrivers can be ignored. Now, if SmartDrv is no longer needed in Windows95, why bother learning how SmartDrv communicatedits needs to earlier versions of Windows? Becausetheveryfact that SmartDrvand other DOSutilities
could communicate their needs to Windowsis significant:it’s one more sign
that Windows3.x didn’t blithely run “on top of” DOS,but instead partici-
patedin a dialog with DOSand with DOS utilities like SmartDrv. This
pointis in turn importantbecauseit helps establish that Windows 95’s bundling of DOSand Windowsina single packageis less of a radical departure from previous DOS-Wiridowsrelations than you mightotherwise think. If Windows 95 represents the marriage of DOS and Windows,
the fact remains thatthe two have already beenliving together for many
years.It’s a big step — butnotthatbig a step.
Chapter 3: The Windows-DOS Connection
FAKEWIN Caveats Although FAKEWINhelpsrevealthetruerelationship between Windows and DOS,the program is somewhatinvasive because it mightinterfere
with other programsthat use the Windows INT 2Fhbroadcasts to main-
tain an internal IN.WINDOWSflag. MS-DOSitself is one such program.For example, while Windows Enhanced modeis running, MS-DOS keepstrack of which virtual machine (VM)owns which openfile. We'll see in Chapter 4 (see Listing 4-2) that, if DOS thinks Windowsis running, DOS can makecalls into what it thinks is the DOSMGR VxD.
Unfortunately, while FAKEWIN is running, MS-DOSthinks that Windows Enhanced modeis running. There’s no way to knowhow every DOSdevice driver and TSRwill react to FAKEWIN’sphony notification that Windowshasstarted. Thus,it’s difficult to answerthe following question: “Howcan I use INT 2Fhfunctions 1605h and 1606hand be sure
I’m notmessing up DOS?”
It’s worth quoting at length from Geoff Chappell’s answerto this question, from the Undocumented Cornerarea in the Dr: Dobb’s Journal forum (DDJFORUM)on CompuServe: #: 65821 S3/Undocumented Comer 16-May-94 01:39:01 Sb: #65697-#SmartDrive API Fm: Geoff Chappell 100043,564 To: Ralph E Griffin 70323,1440(x)
It’s perfectly OKfor nonWindowsprogramsto issueint 2Fh functions 1605h and 4606handpretend to be Windowsstarting up and closing down — if they don't do anything with external consequencesbetweenthe two calls. Thesituationis less clearif external consequencesare involved. Software may, quite reasonably, reconfigure itself for operation under Windows. This software does not know that youare only pretending to be Windows.You could argue that perhaps such software should not make any changesthatcould have harmfulside-effects if in fact the signals were not coming from Windows — in other words, that the softwareshould not assumeint 2Fh function 1605h comesfrom Windows. Maybethat would bea fair point, but you've been pre-empted by Microsoft, who designed DOS5 in such a waythat the machineID (word at DOS:033€)is handled differently the moment the DOS kernel seesthe int 2Fh function. | am unconvinced that this is a goodidea on DOS's part;it may have unwelcome consequencesforfile sharing in cases wherea file consulted by Windows(before DOSMGRisinitialised)is already open when Windowsis started. This is an unlikely casein the real world where Windowsis usually run from the top-level command prompt(its likelihood is, however,sufficiently large that even the designersof IFSMGR,with its many small
Unauthorized Windows 95
bugs and incompatibilities that seemto have beenoverlooked, did not miss the need to guard againstconflicts arisingif the 16bit file system already hasfiles open when the 32bit file system is installed). My personal view is that we have (moreorless) a No-Go theorem on file access
betweena non-Windows app's int 2Fh functions 1605h and 1606h — andthis is deducedfrom reaction that we know about.If you were planningto issue these int 2Fh functionsyourself in a general environment, you would also have to contend with reactionsthat wecan't predict. Now,you mightthink that FAKEWIN doesn’t “do anything with external consequencesbetween the two calls” to functions 1605h and 1606h. However, notice in Listing 3-1 that FAKEWIN calls printf after
calling win_init_notify (1605h) andbeforecalling win_term_notify
(1606h). If FAKEWIN’s output is redirectedto file (which happened
countless times while | was writing this chapter), there’s a genuine potential problem.
Onthe other hand, the Microsoft Systems Journal has recommended that programsother than Windowsissue Windows INT2Fh broadcasts,
bothto detect Windows3.0 (Microsoft Systems Journal, May-June 1992)
andto reconfigure the SmartDrive 4.0 disk cache (Microsoft Systems Journal, September 1992). It’s difficult totell if this is our assurance that the
techniqueofissuing phony Windows INT 2Fhbroadcastsis reallyok: orif it just never occurred to Microsoft that faking the Windows broadcast might have unexpected effects on programs(including DOSitself)
that hook the broadcast. Besidestelling software that Windows hasstarted whenit actually hasn’t, there’s anotherpotential danger associated with FAKEWIN: It mighttell software that Windows has exited whenin factit’s still run-
ning. This is exactly what would happenif you ran FAKEWINinside a Windows DOS box. FAKEWIN.Cuses the is_win function from ISWIN -C to detect whether Windows is running. (ISWIN.C isn’t shownhere, but is included on the Unauthorized Windows 95 disk.) FAKEWINwill refuse to run under Windows; you must first exit back to DOS. (In Windows 95, where ‘ou normally can’t exit from Windows back to DOS,
you can run FAKEWIN inSingle Application Mode.) Finally, FAKEWIN showsonlya few aspects of the DOS-Windows
connection. For example, function 1605h isn’t the only mechanismfor declaring instance data. SYSTEM.INI has aLOCALTSRS= statement that turns entire TSRsinto instance data items, and a LOCAL= statement that does the same for DOS device drivers. (SYSTEM.INI comes preloadedwith local=CON and localtsrss= DOSEDIT,CED.) Andthe Windows VMM provides an _AddInstanceltemservice that VxDs can
Chapter 3: The Windows-DOS Connection
directly use to declare instance data. Infact, all the other instance data methodseventually turn into _AddInstanceltemcalls, so if you wanted a complete picture ofinstance data, you’d have to hook _AddInstanceltem.
Inside FAKEWIN In spite ofthe issues discussed in the previoussection, the FAKEWIN programhelps showhow Windows 3.x interacted with software loaded before it. Thesalient point about FAKEWINis thatit helps you understandthe Windows 3.x-DOSconnection — andunless you understand that,it’s difficult to appreciate the changes that are occurring in Windows 95. The source code for FAKEWINis shown in Listing 3-1. This module must be linked with several others (TEST1684.C, FAKEVXD.C,and FAKETSR.C in Chapter 4, andwith ISWIN.C, DUMP.C, and MAP.C on the Unauthorized Windows 95 disk) to create FAKEWIN.EXE. Listing 3-1: FAKEWIN.C FAKEWIN.C ew Schulman, 1994 hee Fakewance Fakevs bec -DTEST_1684 als
etsr.c dump.c iswin.c map.¢ 1
Using INT 2Fh broade AKEWINpi simulates Windows initializing and out how 00S
Opt ior WIN30 fakes Windows 3.0 VERS xxx fakes version xxx ( NDARD fakes Standard DUMP. hex dump of ir in fi #
le = 3) try to be forward compatible nWin386_Startup_Info_Struc at %Fp %s\n" + owner(winfo)) >SIS_Virt_Dev_File Ptr != 0) printf("VxO name: Fs", winfo->SI8_Virt_Dev File Ptr): printf(*(Reference data: %081X)\n", winfo->SIS_Reference_| ) if (Cinst winfo->SIS_Instance_ ta_ptr) printf(*Instance_Item Struc at £fp %s\n", inst, owner(inst)); while (inst->1IS_Ptr)
printf(* “#Fp 04x Zs\n", inst->11S_Ptr, inst->IIS_Si ze. owner(inst->1IS_Ptr)) if (do_hex_dump) dump( (unsigned char far *) inst (unsigned) inst->11S Size (unsigned long) inst->IIS_Ptr, 16): ! printf("No instance
) else
}
data\n");
recursively walk chain of startup info blocks F (winfo->SIS_Next_DevPtr I= 0 print_startup_info((FPWININFO) winfo->SIS_N printf(*Fp not a valid Win386
Dev_Ptr):
startup info structure!\n", winfo
pragma pack(1 typedef struct ( Wo é BYTE maj. min: } EMM_IMPORT: fipragma pack( void
check_emm_import( void) static EMM_IMPORT enmimport; int emm = open(*EMMXXXX0", O_RDWR | O_BINARY) f (emm -1) enm open("$MMXXXXO", O_ROWR 0 BINARY): f (emm = -1) emm = open("EMMOXXXO", O_RDWR O_BINARY); f (emm -1) return: / no EMM enm_import.addr = 1; / set first byte to enm_import.maj = emm_impo t.min 0;
Chapter 3: The Windows-DOS Connection
define IOCTLREAD 2 if (ioctl(emm, LOCTLREAD, &enm_import, sizeof(emmimport)) != 0) printf("Global EMM Import @ ¥081Xh (version 24,202d)\n" emm_import.addr, emm_import.maj, emm_import.min); close(emm) ; void fail(const char *s, sta
.) { puts(s): exit(1):
© char *usage_m usage: fakewin [-sta
d]
[-win3® |
xxx] [-dump]
4 usage(void) ( fail(usage_msg main(int argc, char *argv[]) WORD mode = ENHANCED_MODE: WORD vers = WIN3 char *s; int dummy; int i Fputs(*FAKEWIN 1.0
Simulate
/ default I) default
Windows Initialization\n®, stderr);
fputs(*Displays instance data, VxD startup, DOSMGR interface\n", stderr) fputs("From \"Unauthorized Windows\" (IDG Books, 1994)\n", stderr) fputs( "Copyright (c) An chulman 1994. All rights reserved\n\n", stderr) (i#1; iéarge: f+) f (largvlid “") | Cargvti]t07 =
wel ps ‘ANDARD" ) stromp(s, "WIN30"
STANDARD_MODE: WIN30; 0) sscanflargvi++il, *X04X", kvers); 0) do_hex_dump++; sage
"Exit back to DOS before running FAKEWIN"); printf (*FAKEWIN pretending to be Windows %u.802u %s mo \n\n", vers >> 8), (vers & OxFF mode == ENHANCED MODE) ? "Enhanced Standard"); // tell DOS/whoever that Windows is starting up if (win_init_notify(vers, mode) 0)
/ start recursive walk of info chain
if (fpinfo 0 printf(*No Windows s artup info\n
Unauthorized Windows 95
print_startup_info(fpinfo); if (switch_fune)
printf(*\nv86 Enable/Disable function: 3Fp %s\n switch func, owner(switch_func)): check_emm_import(): else
someone refused the 2F/1605 cal] (CX fail("Not allowed to start Windows");
do device callouts Vx0 init order defined in VMM. INC fake_dosmgr_callouts(): (1 do TSR identify call (2F/1608 tsr_identify():
tell DOS/whoever that Windows is done initializing win_init_complete_notify(); ifdef TEST_1684 extern void test_1684(void); test_1684()
—/
in TEST1684.C
) itendif
tell DOS/whoever that Windows is beginning termination win_begin_exit_notify() // tell DOS/whoever that Windows is terminating win_term_notify(mode) ; return 0 After reading any command-line options, the main routine in FAKEWIN.C calls win_init_notify to generate the INT 2Fhfunction 1605h
broadcast, which is normally made bythe real-mode portion of WIN386. EXE. The win_init_notify function saves the addresses of the returned startupinfo structure and V86 enable/disable functions. Assuming that no one hasrefused the Windows startup broadcast by setting CX to a nonzerovalue, FAKEWIN then calls print_startup_info, which (not
surprisingly) prints the startupinfo structure. If there’s a Next pointerin the structure (winfo->SIS_Next_Dev_Ptr!= 0), print_startup_info recur-
sively callsitself, In this way, the functiondisplays the linkedlist of
startup infostructures. Displaying the startup info involveslittle more than some calls to printf. For the name of the startup info’s owner (such as 336MAX$$,
Chapter 3: The Windows-DOS Connection
DOSKEY, SMARTDRY, and DBLSYSHSin the examplesgivenearlier), print_startup_info calls the owner function, which is provided by MAP.C (MAP.Cisn’t shown here, butis included on thedisk). If the -DUMPoptionhas beenspecified on the commandline, print_ startup_infocalls the hex dump function provided by DUMP.C,which, again,is included onthe disk.
After displaying thestartup info, FAKEWINprints the V86 enable/
disable function,if a 386 memory managerhassupplied one, andcalls check_emm_importto see if the memory manager provides a Global EMMImportstructure (see Chapter 4).
Next, FAKEWIN calls the fake_dosmgr_callouts function in FAKEVXD.Cand thetsr_identify function in FAKETSR.C. Chapter4 discusses these functions. Finally, because FAKEWINhaspretendedto everyone that Windows is starting, FAKEWIN mustnowpretendseveral more things: that Windowshas finished initializing (INT 2Fh function 1608h), that it
is start-
ingto exit (function 1609h), and thatitis finally goingto exit for good (function 1606h).
dunce toni be er as ats Watt al, nae Ani ou nl mn. etltne WTS we >
Shad
Gbiros i eta“PANdere star neg p72
beatoa sal
9 ealrelly
Shah rerio rok9 eatsTEA satireta Soho end SemTapriill 5 Prt Sa ey
ot rm
wat209 Ae QL aeneayoallaianbetrish Sear rs ny pmo ett a aly acBiol ,
is *
ns
eongens dts nun
nahi wie
ATP Wir exe Min ‘hts ati
EG =Fqnoyeethy wana He See oss o prt ea CMS oe oemalee
aie elle,
7 as
Chapter 4
A MarniageMabe In REDMOND he previous chapter introduced the FAKEWIN programanddiscussed
in general terms someaspects of the DOS-Windows connection, such as instance data and embedded VxDs. In this chapter, we’ll take a closer
look at FAKEWIN’soutput and focus on some of the ways that DOS and
Windows worktogether.
Figure 4-1 shows the complete sample output from FAKEWIN.This output happenedto be produced when running in the DOS 7.0 componentof Chicago, with a large number of TSRs loaded. Obviously, your mileage mayvary: in a different configuration FAKEWIN wouldproduce different results. Nonetheless Figure 4-1 shows how some common DOS utilities, and DOS itself, react to the news that Windowsis starting up.
FAKEWIN pretending to be Windows 3.10 Enhanced mode Win386_Startup_Info_Struc at O8Fa:125F (SMARTORV) dat : 08F41271) VxD name: C:\WINDOWS\SMARTORV.EXE (Reference No instance data Win386_Startup_InfoStruc at 08C5:0107 (TSRLDR) VxD name: C:\UNAUTHW\PIPE\PIPE.386 (Reference data: 00000000 No instance data
_Startup_Info Struc at 085€:000A (COUNTDOS) I 085E:0000
Struc at @B5E:@@1C (COUNTDOS) 0404 (COUNTDOS)
Win386_Startup_Info Instance_Item Struc 0288 E9F7:0000 EQE7:0F23 0200
Struc at E9F7:024B (OOSKEY) at E9F7:025D (DOSKEY (DOSKEY) (DOSKEY)
Win386_Startup_Info Struc at 0329:016E
Unauthorized Windows 95
VxD name: C:\386MAX\386MAX.VxD (Refereni Instance_ItemStruc at C001:0440 ceo1:0183 0001
data: QOBCE3C8)
Win386_Startup_Info_Struc at COFD:3F10 (DBLSYSHS) VxD name: H:\DBLSPACE.BIN (Reference data: COFD3F32) No instance data
Win386_Startup_Info_Struc at FFFF:1D0F (HMA) Instance_Item Struc at FFFF:1025 (HMA) 0050:0000 0001 0050:0004 0001 0050:000€ 0014 0050: 004 0070: 004 (10) 0070: 0001 (10) £833: 0948 (DBLSYSHS) £808: 8002 (DBLSYSHS) Win386_Startup_Info_Struc at 00A0:0EE1 (00S) Instance_ItemStruc at 00A0:OEF7 (DOS) 00A0:0022 0002 (00S) 00A0:0032 0004 (00S) Q0A0:01F9 0106 (DOS) Q0A0;0300 0001 (DOS) QOA0:0EBF 0022 (D0S) 00A0:0089 0001 (00S) 00Ad:008C 0002 (00S) 00A0:0086 0001 (00S) Q0A0:1288 0001 (DOS) 00A0:1289 0001 (00S) V86 Enable/Disable function: 0329:03D4 (3B6MAXS$) Global EMM Import @ phys OOBDSEACh (version 1.11) DOSMGR instance interface ON Segment of DOS drivers: 0005 Patch table: 00A0:0F47 DOS version 5.00 OSEC (SAVEDS) O5EA (SA\ 0321 (1NDOS) (USER_1D) (CRITPATCH) 8c (UMB_HEAD) Current Directory Structure = 88 bytes No DOS data structures instanced via DOSMGR API TSRInfo_Struc at 085E:0026 (PSP @84Eh) (COUNTDOS) _WINEXEC SW_SHOWNOACTIVATE \UNAUTHW\FAKEWIN\COUNTDOS.EXE /085E:0000" ID_Block: "Sample TSR / Windows App” ata Block: @85E: 0000 Figure 4-1: Running FAKEWIN with a large numberof TSRsloadedfurtherillustrates the DOS-Windowsconnection: Someutilities are making requests of Windows, and we see DOSitself communicating with Windows.
Chapter 4: A Marriage Made in Redmond
Let’s see what we havein Figure 4-1. Tostart with,thefirst Windows startupinfo structure in the chain belongs to SMARTDRV.EXE,the
DOSportion of which,as noted in Chapter3, asks Windowsto loadits
VxDportion.
Next, something called TSRLDR asks Windowsto load PIPE.386 (a
DOS-Windows communication pipe written byThomas Olsen). TSR-
LDR.ASM,whichyoucan see in Listing 4-1, is a small DOS program
illustrating how DOSsoftware can hook function 1605h to request Windows load to a VxD.
Listing 4-1: TSRLDR.ASM ASM dr.com CODE
blic org
‘CODE
100h
dw dw? label byte
W
Offset Segment it Ptr_Segment ffset egment
win386
byte vxdName
db 3,0 dw? dw? dw? dw 2 dd 0 dw 0 dw @
db PATH= db *C: \UNAUTHW\ PIPE. 386 db 128 dup(@
Int2fHandler proc far public Int2fi ax, 16 cmp je iat imp word ptr cs:oldInt2foffset
first call previous INT 2Fh, before returning our info
pushf
Unauthorized Windows 95
call
dword ptr cs:oldint2foffset
previous handler's info struct now we have pointer mov cs:S1S_Next_Dev_Ptr_S men » bx mov _cs:S1S_Next_Dev_Ptr_0
mov mov
cs:S1S_Virt_e ¢s:SIS_Virt_Dev
Te_Ptr_s le_Ptr_o
set vxdName
mov bx, cs. mov es, bx mov bx, offset Win386_Startup_Ini iret Int2fHandler endp near proc public Setup
etup CODE
mov mov mov mov mov int
bx, ds es, bx bx, es:(2Ch] ah, 49h es, bx
push pop
ds
mov int mov mov mov lea int
ax, 352Fh ah _cs:oldInt2fSegment ,es _cs:o1dInt2FOFFset, bx ax,252Fh dx, ‘Int2fHandler 2th
mov mov shr inc mov int endp
dx, offset Setup cl.4 dx,cl dx ah, 31h 2th
Free environment
NT 2Fh
ends end EntryPoint
Bytheway, in the eventof an errorin your function 1605hhandling, thereal-modeportion of WIN386uses somerather poorly chosen error messages. If a TSRtells Windowsto loada file that isn’t actuallya VxD
(for example, aninteroffice memothatfor some rea on you've renamed PIPE.386), you getthe message: “A devicefile that is specified in the SYST EMLINI file is damaged. It maybe neededto run Windows.”
Chapter 4: A Marriage Made in Redmond
‘The whole point offunction 1605h is that the VxD hasn’t beenspecified in SYSTEM.INLWithout a programlike FAKEWIN,a system administrator might have a hardtimetracking downthecauseof this error message! Likewise, if the TSRhas specified a VxD thatcan’t be foundatall, Windowsdisplays this message: Se wey see wn indoye TH line in your ITOEXEC.BAT file points to poviaais the file and has thence on pout try running
Setup to SYSTEM. IN
Again, the reference to SYSTEMLINI isless than helpful, as is the advice about the PATH.If PIPE.386is actually in C:\PIPE, and C:\PIPEis on the PATH, Windows still can’t find it.
DOS instance Data and the SDA As youcontinue examining Figure 4-1, you'll notice two Windows startupinfo structures created not by a TSR or DOSdevice driver but by MS-DOSitself. Thefirst structure, locatedin the high memoryarea (HMA), with instance data items at addresses such as 0050:0000 and 0070:0012, belongs to the IO component of WINBOOT.SYSin Windows 95 (equivalent to IO.SYSin earlier versions of DOS). The second
structure, with instance data items in segment 00AOh, belongsto the MSDOScomponent of WINBOOT.SYS(equivalent to MSDOS.SYSin
earlier versions).
Ofthevariablestypically included by DOSinits function 1605h instancedatalist, Geoff Chappell has noted, “Almostall the kernel vari-
ables that are instanced by Windowsarerelated to console operation. Mostnotably, the buffer at DOS:01F9h serves DOSfunction 3Fh as the systemequivalent tothe buffer an application supplies whenusing DOS function 0Ahtoread from a consoledevice.” In the second Win386_
Startup_Info_Struct in Figure 4-1, youcanalso see DOStelling Windowsabout this 106-byte buffer at 00A0:01F9. ManyDOS internal variables andstructures that you know Windows
mustinstance don’t show upin DOS’sinstancedatalist.
(A good exampleis
DOS’s Current Directory Structure (CDS),since different DOS boxes can
Unauthorized Windows 95
havedifferentdrive mappings.) That's because, as noted in Chapter 3, function 1605h is just oneofseveral techniquesforallocating instancedata. The IO and MSDOSinstanceitemsthat do show upin Figure 4-1 are mostly the ones that DOS knows Windowscan’tfigure outforitself using undocumented DOScalls. The DOSMGRVxDrelies heavily on undocumented DOScalls to find key DOSinternalvariables and structures that must beinstanced; it thenpasses the addressesandsizes of
these structures to the VMM_AddInstanceltemservice. A key exampleis the Swappable Data Area (SDA) in DOS. DOSMGR cancall the undoc-
umented INT 21h function 5D06h (Get SDA), which returnsthe address of a key region in DOSthat must be swapped outandrestored bya task switcher. The function also returns the number of SDAbytesthata task switcher mustswapif the InDOSflagis set, and the number of SDA bytes thatit must a/ways swap, whether InDOSissetor not. Instancedatais in manywaysjust an extension of the SDA. The SDA unfortunately doesn’t includethe full DOS“state.” Andit can’t include areas belongingto third-party TSRs. Thus, there needs to be some wayto declare areas outside the SDA that mustalso be swapped.Instancedata is basically a technique for supplementing the SDA.Infact, just as DOS function 5D06h returns both the Swap_In_DOS and Swap_Alwayssizes of the SDA,likewise the InstDataStruc used by _AddInstanceltemhas an
InstTypefield with the values INDOS_Field and ALWAYS_Field. VMM currently happensto ignorethese particular instancedata types, but in any case there’s a clear connection between the DOS SDA and Windows
instance data (whichis hardly surprising since the same Microsoft programmer, Aaron Reynolds, is probably responsible for both pieces of code). Figure 4-2 provides the code example, and Figure 4-3 illustrates howthe DOSMGRV3xD instances the DOS SDA.
05088 ospc1 e50c6
: First. call 00S 21/5006 to get SDA in DS:SI mov Lebp.C]ient_AX},5006h mov eax, 21h VMMCal1 Exec_int
esoce 05000 05003, 05007
Now, form linear address to SDA movzx eax, Lebp.Client_DS] eax.4 movzx ebx, Cebp.Client_SI] add eax,ebx b eax = (DS Fakewin -win3d Wings VxD name:
eo000000)
Remember WINA20.386? Perhaps youstill haveit sitting in the root directory of your hard disk. WINA20.386 isn’t required for Windows 3.4 (this is whyit doesn’t show upin Figure 4-1). DOS wants it to be loaded only when it’s told that Windows 3.0 is starting up. DOS wantedit in the
root directory because this madeit easier for DOSto tell Windows 3.0 what to load. The SWITCHES=/W setting in CONFIG.SYS disabled this use of function 1605h: you had to explicitly put WINA20.386in the Windows SYSTEM.INI file, but you were free to move WINA20.386 out of the root directory. WINA20.386is interesting as another example of how MS-DOSis “Windows aware”: Windowsisn’t just another program that happensto run on top of MS-DOS.If you disassemble MS-DOS5 or6, you'll see where MSDOS.SYShandles the INT 2Fh function 1605h broadcast and, among everything else FAKEWIN reveals,tells Windows 3.0 to load WINA20.386. The specific details of WINA20.386 need not concern us here{it fixed a
bug in Windows 3.0); the important thing is that DOS knows about Windows, enoughto load VxDsthat patchit. The fact that DOS’s WINA20.386 patches Windows must have been what prompted a Microsoft KnowledgeBase article on WINA20.386to oddly claim that “VxDs could be called ‘structured’ patches for Windows.”
DOS'S IN_WINGE Flag ‘The FAKEWINoutput doesn’t show whatis perhapsthe best example of DOS-Windowsintegration: When DOS5.0 andlater see the function 1605h broadcast, it not onlyreturns the DOS instancedatalist
(and,if Windows 3.0is starting up, requests that it load WINA20.386), butalso uses the 1605h broadcast from Enhanced mode asa signal to turn on an IN_WIN3E flag inside DOS. Function 1606his the signal to turnthis flag off. As discussedin more detail in Undocumented DOS (2d ed.), MS-DOS5 and 6 don’t care onewayortheother about Windows Standard mode. But while Windows Enhanced mode(or some program,like FAKEWIN, that alsoissues the Windows INT 2Fhbroadcasts) is running, MS-DOS wants tobehave as though a nerwork were running. If youthink aboutit, multiple DOSboxes in Enhanced modeare very muchlike multiple machinesona network. When Enhancedmode is running, the file /O codein DOS file owners using both the DOSPSP and thevirtual machine ID. Asy
Unauthorized Windows 95
see shortly, the DOSMGRVxDpatches this VM ID numberright into
DOS,which thencopiesit into every open-file entry. This doesn’t matter very much in Windows95 or in WEW 3.11 with 32-bitfile access enabled because these versions of Windowscandofile J/O without consulting DOS.Butthe point remains that, even when Windowsdid use DOSforfile I/O,it was a DOSthat knew about — and
containedspecial provision for — Windows.
IO.SYSalso tests the IN_WIN3E flag, andif Windows Enhanced modeis running, IO.SYSwill, under certain circumstances, call the
DOSMGRVxD.VxDscan provide APIs to DOS and Windowsapplications; calling INT 2Fh function 1684h retrieves an API entry point for the VxD whoseID (such as 15h for DOSMGR)is given in BX.
As usual, the Windows DDK documentsthis INT 2Fh mechanism, but notthe actual APIs provided by DOSMGRand theother VxDsbuilt
into Windows.
These VxD APIs areavailable evento software that, like DOS, was
loaded before Windows. Yes, MS-DOSreally doescontaincalls to INT 2Fh function 1684h. If compiled with the TEST_1684 switch, FAKE-
WINlets youtest this DOSbehaviorby calling test_1684 (shownin
Listing 4-2) to hook INT 2Fhandthen shelling out to a DOS prompt. Listing 4-2: TEST1684.C I TEST1684.¢ Just a quick hack to test DOS interaction with FAKEWIN Andrew Schulman, 1994 4
include include include
typedef unsigned short WORD:
typedef struct #ifdef __TuRBOC WORD bp.di,si,ds,es,dx,cx,bx,ax; else WORD es bp.sp.bx.dx,cx.ax endif WORD ip,cs, flags; | REG_PARANS; static WORD vxd_calls = 0 static WORD ved 0; static void far *requ = (void far *) 0;
/* same as PUSHA *
Chapter 4: A Marriage Made in Redmond static void (interrupt far *old_2f)();
void interrupt far int2f(REG_PARAMS r) if (r.ax
0x1684)
vxd_calls++; requ = MK_FP(r.cs, r.ip) vxd = P.bx
) _chain_intr(old_2f);
void tes ( void interrupt far int2f(REG_PARAMS r); old_2f = _dos_getvect(Ox2F); _dos_setvect (Ox2f, int2f); /{ should be hooking INT 24h, and so on system(getenv( *COMSPEC")) _dos_setvect(@x2F, old!2) if (vxd_calls)
printf(7\nReceived $d calls to 2F/1684 (Get VxD API)\n", printf("Request VxO #804Xh from SFp\n", vxd, requ);
d_calls):
The DOSprompt provided by FAKEWINlets yousee for yourself
that DOScalls DOSMGR.To trythis out, access the floppy drive as shownin Figure 4-4. This triggers DOS’s drive-swappinglogic. As you can see when youexit back to FAKEWIN,the program reports that INT.
2Fh function 1684h wasindeedcalled. This,incidentally, is a good example of whyissuing phony Windows INT2Fh broadcastsis a risky proposition. Asseen in the disassembly at the bottom of Figure 4-4, DOS calls
any nonzero function pointer returned from the INT2Fhfunction 1684h call.
Microsoft(R) MS-DOS(R) Version 5.00 (C)Copyright Microsoft Corp 1981-1991 C:\UNAUTHW>dir b: foo.* Insert diskette for driv
and press any key when ready
Volume in drive 8 is FAKEWIN Volume Serial Number is 3239-1303 Directory of B:\ File not found
92 bytes free
C:\UNAUTHID dir a: foo.*
Unauthorized Windows 95
Insert diskette for drive A: and press ume in drive A is FAKEWIN Volume Serial Number is 3239-1303 Directory of A:\ File not found C:\UNAUTHWDexit
any key when ready
free
Received 2 calls to 2/1684 (Get VxD AP Request Vx0 #0015h from 0070: 08E1 C:\UNAUTHW>debug u 70:8d1 8f6 oo70: 7 0070 6 o070: 3 0070 0 a070 0070: aa70 0070: 0070 0070: 0070: 0070: 0070: 0070 0070: 0070 0070:08ED 57 0070:08E 880100 0070:08F1 cB 0070:08F2 58 0070:08F3 58 0070 07 0070: 5F 0070:08F6 CB
CS. PUSH MOV AX, 0BF2 AX PUSH PUSH ES. PUSH OL MOV AX, 0001 RETF POP AX POP BY Pop POP DI RETF
push return address + push DOSMGR API address SetFocus call : call DOSMGR API : this is return address
Figure 4-4: FAKEWIN outputfor TEST_1684 and DEBUG disassembly show that DOS calls DOSMGR.
Before displaying the “Insertdiskette for drive «:” message seenin Figure 4-4, IO.SYS (or the IO component of WINBOOT.SYS) first checks the internal IN_WIN3E flag. If Windows Enhanced Mode is running, the DOS code at the bottomof Figure 4-4 calls a DOSMGR
APIto set the VM focus to ensure that the usersees the message, even if
the DOSbox wasrunning invisibly in the background. Whileatfirst it mightbe strange to see DOScalling Windows, this is just another example of how the old “Windows runs on top of DOS”
description wasn’t veryaccurate, even for the configuration of Windows
Chapter 4: A Marriage Made in Redmond
Enhanced mode with DOS5 or6. You'll see in Chapters 9 and 10 thatin this configuration, DOS doesn’t even runin real mode. And in Chapter 8 we'll use V86 breakpoints to show that DOSin fact makes frequentcalls to Windows VxDs.In someways,it would be just as accurate to say that DOSruns on top of Windows!
Returning again to the FAKEWINoutputin Figure 4-1, you can see that
a 386 memory manager(in this case, 386MAX)has provided Windows
(rather, FAKEWIN, which 386MAX thinks is Windows!) with a pointer to a V86 Enable/Disable function:
Enable/Disable function: 0329:0304 (386MAX$S)
Whenever you’re running an expanded memory managersuch as 386MAX, QEMM,or EMM386, your machine is in V86 mode rather
than in real mode. V86 modeis actually a 1MBform ofprotected mode, controlled by a V86 monitor(also called a VMM),that canrun realmodesoftware. Just as Windows Enhanced mode has VMMto control
V86 DOSboxes,likewise 386 expanded memory managersare really
VMMsthatruna single V86 DOSbox. (VMMisa generic Intel termfor
a V86 control program.) Because 386 expanded memory managers are so widely used, real modeis finally dying out. (I’mreferring here to Intel 80x86 real mode; Windows 3.0 Real modediedoutlong ago.)If you run the PE program in Chapter 9 from your normal DOS prompt,the chancesare goodthatit will report that the machine’s protect-enable (PE)bit is set. It might look like real mode, but you’rereally in V86
mode,which,to make the point again,is really a form of protected mode. Unfortunately, Enhanced mode won’tstart up when another VMM has the machine in V86 mode.(It could,if Microsoft had somehow made
WIN386 comply with the Virtual Control Program Interface [VCP]
standard. In Standard mode, Windows3.1 does comply with VCPI, but
then Standard mode and Enhanced modeare different animals.) Windows wants to be king of the heap. Thus, the 386 memory manager musteither switch V86 mode offitself when Windowsstarts or pass WIN386 a V86
enable/disable function pointer. The real-modeportion of WIN386 (or in Windows95, of WMM32) calls the function to switch V86 mode off
before jumpinginto protected mode.
Unauthorized Windows 95
Global EMM Import ‘There’s just one problemwith the scheme in which 386 memory managersallow themselves to be switched off by Windows. If any memory hasbeenallocated from the memory manager, it suddenly becomes inaccessible when Windows starts. In particular, if any DOS device drivers or
TSRsare loaded into upper memoryblocks (UMBs), they would suddenly becomeinvisible. This would probablyresult in a system crash.
‘Thus, 386 memory managersneed a way to handoffcontroloftheir
page tables to Windows. Thisis the purpose of the Global EMMImport mentioned in Figure 4-1: Global EMM Import @ phys @@BD9EACh (version 1.11) The termglobalrefers to the fact that the EMMis present before Windowshasstarted. Global EMMImport(also called V36MMGR Paging
Import) is an undocumentedinterface, though Microsoftbriefly alludes to it in the DDK documentation for the _AddFreePhysPage and V86MMGR_GetPgStatus, and makes a document available to some
memory-managervendors. Accordingto this document:
Windows/386 supports importing the current EMM handle state from a 386 LIMulator[thatis, an emulatorfor the Lotus-Intel-Microsoft expanded memory specification] whichis operating when Windows/386is loaded. This allowsthe current set of EMM users to continue to operate using their previously allocated EMM handles. There is alsoprovisionfor importation of Upper Memory Blocks and xMShandleinformation from currently operating xMSdriver. NOTE that thereis only one source for the import. Even though the statesof two different drivers are involved (xMS and EMM), the import does not have to be separated becausethere is only one bodyof code whichis doing paging, not two. The import is basically just importing a “paging state”from the currently running paging driver. The IOCTL DOScall that the V86MMGRdevice makes to obtain the pointerto the import information data structure is made with interrupts enabled.After this callit is quite possible that a current EMM/xMSuserwill “wake up” and change the EMM mapping, and/or manipulate oneof the EMM or xMS handles. For this reason the contents of the import information data structure cannotbeset at the timeof the IOCTL becausethestatethat it describes(of the EMS and xMSdrivers)is subject to change before Windows/386getsto the pointoftransition into protected mode. Forthis reasonthe “trigger” for setting the import information data structure content is not the IOCTLcall used to obtain its address, but ratherit is the Virtual ModeDisable call When WIN386is running, all EMM activity is LOCAL to the current VM, not GLOBAL. A global EMM user may have to modify his behavior to copewith this situation. In particular any mapping calls and context savecalls operate relative to the currently running VM and have no meaning in other VMs. A global EMM user who ALLOCATES
Chapter 4: A Marriage Made in Redmond
a handle while WIN386is upwill very likely malfunction because that handlewill be LOCALtothe VMit is allocatedin. Forthis reason Global EMM users need to ALLOCATE ALLtheir handles with thecorrectsize atinitialization.
The check_emm_importfunction in FAKEWIN (see Listing 3-1) simulates only the most superficial part of the EMMImport;it does this by opening the EMMXXXX0device andissuing an I/O control (OCTL)
read. Reading thestructure would require calling the V86 switch_func to
turn the memory manageroff and on,andcalling INT 15h function 87h (Block Move) to copythestructure to conventional memory. (For sample code anda full explanation of Global EMM Import,seethearticle by Taku Okazaki cited in the “For Further Reading”section.)
The DOSMGR Broadcast API Nextup in Figure 4-1, youcansee that FAKEWINproduceda block of
output relating to an interface provided by the DOSMGRVxD. Justas
Windowshas its INT 2Fhfunction 1605hstartup broadcast, VxDs can
have their own individual INT 2Fhfunction 1607h broadcasts. This is an interface that VxDsusetocall software loaded before Windows, and it should not be confused with the INT 2Fh function 1684hinterface that DOS and Windowsprogramsuse to call into VxDs. As usual, the mechanics are shown in the DDK — the VxDcalls INT 2Fhwith AX set to 1607h, BX set to a VxD ID (such as 15h for DOS-
MGR), andotherregisters usedas theparticular VxD sees fit — but
nothingis said about the actual broadcastinterfaces provided in Windows. This is a serious omission because some of these VxD broadcast
APIs, such as the one WSHELLprovides to WinOldAp,are important. As shown in Listing 4-3, FAKEWIN emulatespart of the DOSMGR
broadcast API to see whether any software loaded before Windows hooks the INT 2Fh AX set to 1607h BX=15h call to communicate with DOSMGR. The FAKEWINoutputbackin Figure 4-1 showsthat, not
surprisingly, MS-DOS itself hooksthis call. DOS usesthe interface to provide DOSMGRwiththe addresses of several DOS variables, not for
instance data this time but for patching. Most importantly, DOSgives DOSMGR the address of the USER_ID variable in DOS (located in Figure 4-1 at 00A0:033E), so that DOSMGR canpatch in the VMID. Asnoted earlier, DOS uses this VMID for file I/O.
The DOSMGR broadcast API is described in an unpublished Microsoft document, “API to Identify MS-DOS Instance Data.” Even
Unauthorized Windows 95
without this document,it’s fairly easy tofigure outthe interface bydisas sembling bothsides of the conversation: the function 1607h calls in DOSMGR, and the function 1607h hook in MS-DOS.
Listing 4-3: FAKEVXD.C FAKEVXO..C Fake DOSMGR VxD callout used with FAKEWIN Andrew Schulman For more d ils, see Chappel and Schulman et Undocument
S (2d ed. + pp. 24-30
inclu Vid. hi #include typedef unsigned short WORD: define VXD_CALLOUT(vxd_
#define DOSMGR_CALLOUT( fur sm { mov cx, func VXD_CALLOUT( 0x15)
efine NUM_PATCH names from
“SAVE
6
Microsoft document "API to Identify MS-D
SAVEBX",
MGR_CALLOUT(O
“INDOS",
“USER_ID", “CRITPAT
query
instance processing
Chapter 4: A Marriage Made in Redmond
stance interface
DOS dri
wOaX\n, Ww) SFp\n", patchtab u.202u\n (patchtabl0] & OxFF), (patchtab{a] > 8); &patchtabl1]; iTSR_Exec_Cmd_Show case TSR_LOADLIBRARY case TSR_OPENDRIVER default
‘int f(*TSR_LOADLIBRARY break ntf("TSR_OPENDRIVER "); break; printf(*"TSR Exec Flags £04xh*
Unauthorized Windows 95
ags); break
) printf(*\n\"SFs\"\n", tsr_info->TSR_€xec_Cmd): “EFs\"\n", tsr_info->TSR_ID_Block->str); ) 4Fp\n", tsr_info->TSR_Data_Block);
if (tsr_info-> printf("TSR void tsr_id
id)
TSR_Info_Struc far *tsr_info asm push vax, 160bh 2Fh word ptr tsr_info#2, es tsr_info, di do |
_info r s t ( o f n i _ r s t _ t n i pr t tsr_info->TSR_Nex tsr_info ) while (tsr_info != 0);
Just as DOS programs can hookfunction 1605h to ask Windowsto
load a VxD,theycan also use hook 160Bhto ask the Windows USER module to load a Windowsexecutable, a dynamic link library (DLL), or a Win 16 driver. USER issues this call during InitApp (see Matt Pietrek,
Windows Internals, pp. 279-281); depending on the request, USERcalls the WinExec, LoadLibrary, or OpenDriver API function.
TSR Identifyis documentedin David Long’s article “
Supportin
Microsoft WindowsVersion 3.1” on the Microsoft Developer Network
(MSDN) CD-ROM. This documentation is accompanied bya sample
programcalled COUNTDOS. The results of COUNTDOS’ function 160Bhhook canbe seen in the FAKEWIN output in Figure 4-1. Accord-
ing to the Microsoft documentation,function 160Bhis also usedbyfax software and the Windows network popuputility. COUNTDOS is aninteresting example inits ownright of DOS-
Windows interaction.COUNTDOS.EXEis a Windowsexecutable, with an embedded DOS programthat loads before Windows. The DOS pro-
gramhooks INT 21handkeeps a log ofall DOS calls; it optionally can
Chapter 4: A Marriage Made in Redmond
require the user to verify file deletes. Asseenat the endofFigure 4-1, the DOSportion of COUNTDOS.EXEhooksfunction 160Bh, so that when Windows starts, USERperformsthe following: WinExec("C:\UNAUTHW\FAKEWIN\COUNTDOS.EXE /085E:000D", SH_SHOWNOACTIVATE) The Windowsportion of COUNTDOS uses DPMI calls to talk to its
DOSportion, which is loaded before Windows. Somewhatlike the
V86TESTprogramin Chapter 10, COUNTDOSdisplays the number
of INT 21h calls; this informationis quite useful for seeing the extent to which Windows has orhas notcut itself off from real-mode DOS. It’s instructive to run Microsoft’s COUNTDOS example, with and
without 32-bit file access enabled. Figure 4-5 shows COUNTDOSin WEW3.11, with 32-bit file access disabled (WIN /D:C). With COUNT-
DOSloaded, I started Microsoft Office, ran Microsoft Word, and did a fewother things. Note the calls to DOS functions 3Dh (File Open), 3Eh
(File Close), 3Fh (File Read), and 40h (File Write): Windows uses DOS forfile /O.
Ope Close File with Handle Read File ar Device ‘alteFile or Device Duplicate File Handle Get Currentwith Directory Terminate Ret Code
Figure 4-5: Running COUNTDOSwithout enabling 32-bit file access reveals Windows’ reliance on DOS.
Next, I restarted WEW3.11 with 32-bit file ac es , andperformed roughly the same set ofoperationsas in Figure 4-5. Figure 4-6 shows howthis looked to COUNTDOS. Notice that, while there arestill
Unauthorized Windows 95
plenty of DOS calls, there are none tothe standardFile Open, Close, Read, and Writecalls, andjust a few tocalls such as IOCTL andGet/Set File Date/Time.
Tesh _Resel_Setings Help [Last Update: 0672 Pm oe 1% SelecCurent disk Disk r 1hot S07 7% 1% Getdate 2io re Getime a 1%1% tocrlDOSversion 4s ”0" Dope Fle Handte “ot 2 {oe Termintewith Me PSP SegmentRet Code s es 1% GeyserDateTime Fite eS We ares beTOTAL DOS CALLS i oe DOS ea 5152
Figure 4-6: Running COUNTDOSwith 32it file accessreveals how WfW 3.11 could bypass DOSfor mostoperations. Finally, I tried COUNTDOS in Windows 95. T put INSTALL COUNTDOS.EXE in CONFIG.SYS so that I wouldn’t need an AUTOEXEC.BAT file. When Windows 95 came up, I reset theCOUNTDOS statistics so it wouldn’t show the DOS calls that occurred while Windows
was booting up. (I did the samereset with the WEW3.11 tests, too.) If
Windows 95 does not rely on DOS, COUNTDOS shouldn’t show any
DOScalls. As Figure 4-7 shows, the results are impressive (very few INT 21h calls are being sent down to DOS), but they’re notshat impressive. Especially because, aside from COUNTDOS itself, I was running only
Win32 applications here: the Windows 95 shell, the Win32 version of
Clock, and WinBezMT. COUNTDOS shows that even Win32 applications in Windows 95 still use real-mode DOS for some operations, such as
getting the date and time andcreating andsetting PSPs.
Figure 4-7 is practically an icon for this book. Here we see a number of Win32 applications running (WinBezMT has a fewbezier threads going), and popped upin front of themisalittle program — from Microsoft, noless — remindingus that DOSis not dead
Chapter4: A Marriage Made in Redmond
28 2c 1815 30 1 44 44 ac 1 50 193 55 5 TOTAL DOS CALLS
Get date Get time Get DOS version oct Terminate with Ret Code Set PSP Segment Create PSP
Figure 4-7: COUNTDOSrunning in Windows 95 showsthat even Win32 applications still need DOS for some operations, such as getting the date andtime, and creating and setting PSPs. There’s onefinalinteresting point about COUNTDOS.This
Microsoft sample programhasa cute ConfirmDeletes option. When selected, COUNTDOS'’s INT21h handlerlooks for function 41h (File
Delete)calls, andtells the Windowspart of the programtopopupa dialog box asking you to confirmthat you really wanttodeletethe specified file. This works nicely in Windows3.1, andis a good example of how a
DOSprogramand a Windows program(embeddedin a single executable
file) can work together. When32-bit file access is enabled in WFW3.11 or Windows95, however, theCOUNTDOS ConfirmDeletes optionhas noeffect. It’s obvi-
ous why: When 32-bit file access is enabled, COUNTDOSwon'tsee any function 41h (File Delete) calls because theyareall being handled by Windows VxDsin 32-bit protected mod . COUNTDOShasno opportunityto confirm deletes because,as far it cantell, there aren’t any! This is a good example of howbypassing DOS,which sounds so good,
can have serious negative side effects. A legal DOS-Windows program —
in fact, one intended to teach programmers how to use Microsoft's
operating-systeminterfaces — has been brokenby32-bitfile a
Well, there’s no suchthing as a free lunch. But it wouldbe nice if
Microsoft fromtimetotimetoldusthe price of the meal.
Til boctesrd* oily
ee og rapt 1Athd je
ts Mess # SEB t. Sighs & ii
ie et
Pade
an AL heef Halom Pgetin
Chapter
Tue Two Faces | oF Winpows 6g
ughatwill happen to the MS-DOSproduct line?” This was posed in Microsoft's “Chicago Questions and Answers”
a question
white paper
(January, 1994). The answer seemsto suggest a radical overhaul for this nearlyancientreal-modeoperating system:
Microsoft will continue to enhance MS-DOSaslong as customers require it. Future versions will be derived from the protected-mode technology developed in the Chicago project. Whatdoes this mean? How can future versions of DOS be derived
from protected-mode software? Will this protected-mode DOSstill be
recognizable as DOS? Is a protected-mode MS-DOS(ora version of DOS“derived” from protected-mode technology, whatever that means)
even possible? In this chapter, you'll see that this protected-mode DOSalready (and in essencehasexisted for years) as part of Windows.
The Inner Core of Windows If you asked a typical Windows programmertolist the core componentsof Windows, chancesare the programmer wouldrattle off “KERNEL, USER, and GDI.” These are the names of the Windows dynamic link libraries
(DLLs) that contain the bulk of the Windows APIs used to write Windows applications. Windows APIs such as GlobalAlloc, CreateWindow, and ‘TextOut live inside these DLLs. These DLLs are important, but they don’t constitute the core of
Windows. As you'll see in the course ofthis chapter, the visible GUI por-
Unauthorized Windows 95
of Windows — the part that nearly everyone thinks of as Windows itself — is little more thanan application that happensto run on top of the actual Windows operating system. This Windowsoperating systemdoesn’t reside in KERNEL, USER,
or GDL. Instead,it’s foundlargely in file called WIN386.EXEor, in Windows 95, VMM32.VXD.Atonepoint, Microsoft calledthis file DOS386.EXE, whichindicates that it’s difficult to say whether this pro-
gramis part of Windows or part of DOS. Bytheendofthis chapter, you might come to view WIN386.EXEaspart ofa future version of DOS —
or perhaps as an Enhanced mode ofMS-DOS— that moreorless was accidentally shipped with Windowsforseveral years.
To start Windows, you run the program WIN
Mwhich, as Chap-
ter 2 showed,in turn launches another program: ° In Standard mode (WIN /S), WIN.COMruns WSWAP.EXE,which runs DOSX.EXE,whichin turn runseither KRNL286.EXE(on 80286processors) or KRNL386.EXE (on 80386andlater processors). * In Enhanced mode (WIN/3), WIN.COMruns WIN386.EXE, which is a collection of VxDs. The WSHELL VxDinside WIN386 runs KRNL386.EXE. * In Windows 95, WIN.COMruns VMM32.VXD(a collection of VxDs), whose WSHELL VxDrunsthe Win16 kernel, KRNL386.EXE. So whatsort of programs are DOSX,
WIN386, and VMM32? How do
theyrelate to the morevisible aspects of Windows?Inthis chapter and the two that followit, we'll run DOSX, WIN386, and VMM32 in an
unusual waytosee whatthese programs do for Windows.
DOS Extenders and the Future of DOS Although this book focuses on WIN386.EXE and VMM32.VXD, the
easiest way to understandthese two programsis tolookfirst at DOSX -EXE, whichis the basis for Windows 3.x 286 Standard mode. (Standard
modedisappearedin Windowsfor Workgroups3.11, just as Windows real mode disappeared in Windows 3.1.)
WIN/Slooks for DOSX.EXE and WSWAP.EXEandthen executes
WSWAP.EXE. WSWAP andanother executable,DSWAP, are just the task-switching code from DOSSHELL.EXE, the DOS 5 task switcher. In turn, DOSSHELL.E was the Windows3.0 Standard mode task
Chapter 5: The Two Faces ofWindows
switcher;it was basically lifted out “as a lump andploppedinto the DOS
5.0product” (Ray Duncan, “Programming Considerations forMS-DOS 5.0,” PC Magazine, November 12, 1991). WSWAP runs DOSX, and
DSWAP runsother DOSprograms.
DOSX.EXE, asits name implies, is a DOS extender. This meansthat DOSXprovides a protected-mode DOS interface: Thanks to DOSX,
protected-mode Windowsapplications running in Standard mode can make DOS INT 21h calls to accessfiles, allocate memory, set interrupt vectors, and so on, even though we normally think of DOS as a real-mode
operating system. Thisisillustrated in Figure 5-1. In Enhanced mode, the Windows DOS extender resides in the DOSMGR VxDlocatedinside WIN-386. ; when32-bit file access is enabled in WfW 3.11 and Windows 95, the IFSMGR.386 VxD should probably be considered part
of the DOSextender,too. Protected mode DOSApp
4
¥ DOSExtender f
INT 21h handler Extended Memory Conventional Memory
a
a
Protected Mode a Real or V86 Mode
Stub Program -
v
Programs that are on the INT 21h chain
|
a
v DOS INT 21h handler
| |
Note:The dashed arow indicates thathe DOS ‘omenderpasses only some INT 21h cls down eal moder rome ae handled i protected mode
Figure 5-1: A DOSextenderlets protected-mode applications (such as Windows programs) makeINT 24hcalls, even though MS-DOSis not a protected-modeoperating system. The DOSextenderoften(but not always) doesthis by translating the protected:mode INT 21h call into rea-modeterms,andthen reissuing (orreflecting)it in real or V86 mode.
What does a DOSextender do? As an example, consider a programthat calls DOSfunction 3Dhto opena file, passing a far pointer tothe filename in the DS:DXregisters. Ina real-mode program, DS:DXis a real-mode pointer, which DOScanreadily understand. But if a protected-modeprogram, such as a Windows application,calls INT 21h function 3Dh(either
Unauthorized Windows 95
directly or via a Windows APIfunction such as OpenFile or DOS3Call),
thefar pointer in DS:DX will naturally enough be a protected-mode pointer: DSholdsa selector, not a paragraph address. Furthermore,this selector will most likely have a base address located in extended memory, above IMB. Thefile-open code in real-mode DOS cannotcorrectlyinterpret
protected-modepointers, nor canit see extended memory. If a Windows application or other protected-mode program passed DOSa protectedmodefilename pointer, DOS would just get it wrong.
This is where a DOSextender such as DOSX.EXEcomesin. A DOS extender hooks INT 21h in protected mode andprovides protectedmode equivalentsfor all the familiar DOS functions. A DOSextender’s implementation offunction 3Dh,naturally, wouldexpect a protectedmodepointer in DS:DX and would do whateveris necessary to open the
file and return a DOSfile handle to the protected-modeapplication. In essence, the DOSextender makesit appear as though DOSwere a protected-mode operating system.
The DOSextender can implementits protected-mode INT21h functions any wayit chooses.It can translate thecall to somethingthat makes
sense in real modeandreflect this translated call to DOS, or(andthisis a crucial point thatis often overlooked)it can service the call entirely in
protected mode, withoutcalling down to DOS. As an exampleof this second option to bypass DOS,consider the DOS memoryallocation function (INT 21h function 48h). Protected-
modeprogramscalling this function(orcalling something such as malloc in C orthe new operator in C++ thatin turneventuallyrelies on function 48h) will naturally want to have DOS(or whateveris providing the
protected-mode INT 21h interface) return thema protected-modeselector to a block of memory. To provide a true DOS protected-modeinter-
face, the function would have to keep the old DOS “semantics”: the returned selector wouldhave to be immediatelyusable in a far pointer,
without requiring anysort ofnew “lock”function: unsigned short para, sel: har far *fp: _asm mov ah, 48h asm mov bx, _asm int 21h asm _asm mov fp MK_FP( Sfp = txt:
Allocate Memory functor } number of paragraphs : cal] DOS away selector create far pointer from sel / useit
Chapter 5: The Two Faces of Windows
The DOSextendercou/d implementfunction 48h by passingthecall downto real-mode DOSandthentranslating the real-mode paragraph address returned by DOSintoa protected-modeselector. But the protected-modecaller almost never wants a protected-mode selector pointing to conventional memory below 1MB. The protected-mode program wantsto getat the vast stretches of extended memory abovethe 1MBDOSboundary;this after all is the key reason to moveto protected modein thefirst place. Thus, a DOSextenderthat gives protected-mode applications a DOS memoryallocation function would zorpassthis call
down to DOS;it would servicethe call entirelyin protected modeso that
the function became a DOSinterface to extended memory. Now,if a DOS extenderdidthis all across the board, for every INT 21h function, you’d have anentirely new protected-mode operating system, albeit with the familiar INT 21h interface. This would constitute a full-blown protected-mode DOS. In fact, a DOS extender doesn’t neces-
sarily require any underlying copy of DOS,except perhaps as a convenientbootstraploader. The DOS extender could even extend the INT 21h interfaces to 32
bits (for example, function 48h would expect the numberof paragraphsin the 32-bit EBX register rather than in the 16-bit BX register, and func-
tion 3Dh would take a filename in EDX). It couldalso provide new INT 21h services(to supportlongfilenames,for instance) that real-mode DOSdoesn’t supply. This,in essence, in what Microsoft is doing to DOS in Windows95. Notice that, even if the DOS extender doesn’t carry outthe “doit all in protected mode”policy — thatis, even if the DOS extender does continue to pass somecalls down to real-mode DOS — this doesn’t really changethe essence of the DOSextenderas a protected-modeoperating system. Thedecision about whetheror not the protected-mode INT 21h is passed downto real-mode DOSis madeentirely by the DOS extender. DOSis in a subordinate position, doing only what the DOS extender doesn’t feellike doingitself. Instead of viewing the DOSextender as somethingthat “runs on top of DOS,”it’s more accurate to view DOSas little more than a 16-bit real-mode driver for use by the DOSextender.
This is particularly true when the DOSextender runs DOSin V86
, as you'll see in Chapters 9 and 10, the DOS extender can
¢ control over
what happensinside DOSandinside DOS
and TSRs.
This means that the V86 DOSextender can
provide INT 21h to real-mode programs, too. The DOScodecalled by
Unauthorized Windows 95
these real-mode programs would theneffectively runin protected mode. But I’mgetting ahead of myselfa little. With this background onthepossibilities of DOS extender technol-
ogy, and a suggestionofthefutureof the DOSinterface, let’s go back in
timeto look at the history behind DOSX.EXE. The DOSextenderin WindowsStandard mode was based on onethat
Microsoft usedearlier in its CodeView debugger; this DOSextenderin
turn wasbased on the SST debugger written by MurraySargent. Gates,
the excellent biographyof Bill Gates by Stephen Manesand Paul
Andrews, has a gooddescription of how MurraySargent and David Weise used Murray’s DOSextender to port Windowsto protected mode; muchof this worklives on in DOSX.EXE:
In 1988 the Windows group had becomea skeleton crew once Mad Dog [Steve] Ballmer begandragging peopleout the door to work on OS/2.Version 2 of Windows had been a death marchofits own, but the Windows gang wasstill plugging away. Slowly but surely, a collection of Windows appswas beginning to turn up.Still, exactly what the next version of Windows should be, or even if it should be,remained unclear. Then in June David Weise,oneof the Smart Guys from the Dynamical Systems Research acquisition, ran into anold friend..., Murray Sargent, “a world-renowned laserjock who happenstolike to grope around computers.” A physics professor from the University of Arizona, Sargent was upfor the summer to adapt Microsoft's. CodeView debuggerto a kludge known as “DOSextension” that allowed specially written programs to use extended memory on 286 and 386 machines. He had recently added Windows support and a DOSextenderto his own debugger, a program called SSTthat happenedto be Weise’s personal favorite In Weise's view, the three big problems with Windows were “memory, memory, mem-
ory.” You were always bumping up against the memory limits one way or another, and it compromised every aspect ofthe program... So Weise brought Sargentback to his office,fired up the new debugger, and starting with line one began steppingthrough Windowsto makeit run underprotected mode, thereby accessing extended memory. “We're not gonna ask anybody, and thenif we're done andthey shootit down, they shootit down.” Weise began working on it at home,then moved it to theoffice for three monthsof night and weekend work. The good news: “It turned out Steve Wood whoI'd inherited the kernelfrom had structured the whole thing to wanna be” in protected mode.... “There are all theselittle gotchas throughout[the processofbringing up Windows. in protected mode], but basically you just work through the gotchas oneat a time, you just close your eyes, and you just charge ahead. You don't think of the prob-
lems, or you're not gonna doit.... Piece by piece, it's coming. Okay, here comes the keyboard drivers, here come the display drivers, here comes GDI — Oh,oh, look, here’s USER! “Withoutthat debugger running in protected mode with the DOSextender| could not have done it.”
Chapter 5: The Two Faces of Windows A few weeksbefore a scheduled design review with the wholestaff, including Bill [Gates], Weise let Ballmer know howclose he wasto getting Windowsto run in protected mode. “Thisis interesting,” Ballmersaid,
Weise upped theante at a groupretreat in the basementof the nondecadent La Quinta motelin Kirkland, Product manager Russ Wernerhad been given his mission for Windows 3 bynoneother thanBill Gates: “Just make it great.” What, Werner kept asking his troops, would make it great? An interface that could be customconfigured by the user, said some. A cleaner look, said another. “Using protected mode,”said David Weise. “How wouldthat help?” Werner asked.
Without revealing howfar along he wasalready, Weise rattled off a couple of dozen reasons. Wernertold him to go aheadand giveit a try The night before the design review, Weisetold Ballmer to meet him in hisoffice the next morningat eight. Weise stayed upuntil 3:00 AM getting the Windows desktop programsto run in protected mode andleft the machine on whenhe walked out the door. When he camein to work a few minuteslate, his machine had crashed. He knew who had to have doneit. He ran down to Ballmer’s office and asked, “Did you seeit?”
“Yes,” Ballmertold him. “Where do we go from here?” “Steve,it’s totally up to you.” “Let's goforit,” Balimersaid. Going into the meeting, Weise was ecstatic. “It's like (George] Gamow,” he recalled, referring to the Russian-bornphysicist who had developedtheories ofstellar evolution. “His girlfriend says ‘Whatare you thinking?’ and he goes, ‘I'm the only person in the world right now who knows how the sunshine works.'" And what Weise was aboutto reveal might well be some sunshinein the middle of the [0S/2] Presentation Manager gloom.In a fashion, he was aboutto vindicate Steve Ballmer’s pledge of 1985:Write your app for Windows andyou'll be able to run it in protected modewithout any trouble atall. Othersgave their presentations, and then Weise droppedhis bombshell. Everything that had been discussed suddenly changed... little side bet against IBM might well be in order. “Okay,let’s do it,” Gates said. BallmerturnedtoBill, “Whatdo wetell IBM?” A smile spreadacrosstheface ofBill Gates. “That’s your problem, Steve.” And a problem it was. IBM had seen Windowsas an intermediate step between DOS and PM, and not muchofone atthat. Now,by overcomingtheinbuilt limitationsof DOS, Windowswaspositioning itself to undercut 0S/2 andPresentation Manager. The only thingit was missing wasship dates. — Stephen Manesand Paul Andrews, Gates, 1993,pp. 380-382.
Unauthorized Windows 95
DOSH: A General-Purpose DOS Extender and DPMServer ‘That DOSX.EXEin WindowsStandard modeis basedonearlier debug-
ger technologyindicates either that Windowsis a debugger in disguise or that DOSXis not very Windows-specific. Indeed, DOSXis a quite general-purpose piece ofsoftware. Besides its role as a DOSextender, this small (32,000 bytes) programis also a DPMIserver (or DPMIhost). DPMIstands for DOS Protected Mode Interface; DOSX supports DPMI version 0.9. Despite the name, DPMI
isn’t the samethingas a protected-mode INT 21h interface;thatis, DPMisn’t the samething as a DOS extender. Instead, DPML is a set of
INT2Fhand INT 31h services
you canuse to write a DOS extender
that’s compatible with Windows or 386 memory managers such as QEMMor 386MAX.
Forexample, oneof the services provided by DPMI serverssuchas
DOSX.EXE is INT 2Fhfunction 1687h, documentedin the DPMI
specification(available from Intel) as “Obtain Real-to-Protected Mode
Switch EntryPoint.” When a real-modeprogramcalls this service,
DPMIreturnsa far pointer to a DPMIfunction which, whencalled, switchesthecalling programinto protected mode.
i
:DPML.C)is a verysimple example of howa real-
mode DOS programcan use DPMItoswitchitself into protected mode. If DPMI isn’t available, USEDPMI fails with the message “This program
requires DPMI,”butif DPM is available (for example, when running
under 386MAX or QEMM), the programprints “Greetings from pro-
tected mode!”2” and then s. The keyis the dpmi_init function, which first calls INT 2Fh function 1687h to obtain the DPMIswitch_proc and thencalls the switch_proc. The DPMIspecification states that DPMI clients must exit using INT
21hfunction 4Ch,
Ratherthanrely on the Crun-timelibrary’s exit proce-
dure, USEDPMI calls a _dos_exit function. Butsince it’s bypassing the C run-time exit, USEDPMI explicitlycalls the flushall function to clean up
file 1/O. Otherwise, redirected output won'tget written out properly.
Listing 5-1: USEDPMI.C DP
very simple OPMI
client
Chapter 5: The Two Faces of Windows
because, once in * be compiled in smal Vis printf the real-mode run-time arge mod t yo-time would use far but USEDPMI's seg egisters are going to change out from under it when it switches to protected mode.
oid
fail(const char *s)
puts(s); exit(1 d Mode Switch Entry
h_proc, di word pt v word ptr switch_proct2, e if
for DPMI
host private data *
(dos_allocmem(ho a_para, shostdata_seg) != 0) an't allocate memory") fa
dpmi_flags B=
/* this is a 16-bit protected-m de program */
* enter protected mode asm mov hostdata_seg asm mov es, ax asm mov ax, dpm i (*switch_proc)(); * T don't think we're in Kansas return
anymore,
Toto! *
Unauthorized Windows 95
no_dpmi: _asm pop di asm pop si return 0: void print_regs( void) l unsigned short ds_reg, ¢s_reg asm mov cs. _asm mo) printf ( -204Xh DS"Z04xh\n", cs_reg, ds_ni
main(int argc, char *argv{]) ( print_regs(); if (1 dpmi_init())
switch int
fail("This program requires DPM.
ed mode, via OPM
print_reg etings from protected mode!\n"); printf( to exit from protected mode, must use 21/4C! // and since bypassing C exit cleanup, must do flushall ourselves flushall(); _dos_exit(0 Notice that, once in protected mode, USEDPMI calls the printf func-
tion from the C run-timelibraryto display the “Greetings fromprotected mode!” message. But USEDPMI startsoff as a real-mode program, andis
linked with a real-mode Crun-timelibrary. Using the real-mode C runtimelibrary in protected mode requiresthat this real-modecodebe “protected-modeclean”; this in turn requires that USEDPMIbe compiled in small model,for reasonsthat should befairly evident fromlookingat the
program’s output when run under a DPMIserver:
CS*215Ah CS=02E7h Greetin
27Fh ‘om protected mode!
The DPMIserver changed USEDPMI®segmentregisters right out fromunder it! The DPMI server has given USEDPMIprotected-mode
selectors that have the same linear base address as USEDPMI’s previous real-mode segmentregisters. Besides requiring small model, there’s another, even more fundamen-
tal assumption implicit in USEDPMI°cavalier use in protected mode of a real-modeprintf function: USEDPMisassumingnotonlythe presence of a DPMI server butalso the presence of a DOS extender
Chapter 5: The Two Faces of Windows
providing protected-mode INT21h services. The real-modeprintf that
USEDPMIcalls in protected modewill almost certainly result in an INT 21h DOScall eventually, so someone hadbetter be providing INT 21h in protected mode. DPMI servers do almost always come with DOS extenders, but the DPMIspecification says nothing one wayorthe other aboutthis. Thus, you shouldn’t assumethat youhave protected-mode INT21h services just because you have DPMI services. The DPMI server in OS/2, a vir-
tual device driver called VDPX.SYS, has a DPMI_DOS_APIsetting that can control whetherornotit should provide protected-mode INT 21h. It’s not clear whyyou would ever want DPMI_DOS_API turnedoff, but
if it is, USEDPMI(along with many other programsthat assume that
DPMIservers always provide DOSextender services) will behave improperly.
At anyrate, DPMIand protected-mode INT 21h arelogically separate services. As I said just before Listing 5-1, oneof the things you can do with DPMI is write a DOS extender. You can see howhelpful the
DPMIswitch-to-protected-mode service would be to someonewriting a DOSextender. A DOSextenderstarts out in real (or V86) mode and switches the machine into protected mode to run protected-mode programs under DOS. The DPMIservertakescare ofa lot of the messy work for the DOSextender, and makesit easier to write portable DOS extenders that canrunin environments such as Windows, OS/2, and
under386 memory managers likeQEMMand 386MAX. Oncerunning in protected mode, a DPMI client can call DPMI INT 31h services, suchas function 0 to allocate protected-mode selectors, function 0501hto allocate memory, function 0600hto lock downan area
of pageable memory, or function 0205hto install protected-modeinterrupt handlers. Thislast function is quite important to DOSextenders, which need to hookprotected-mode INT21hto provide services to theirclients.
‘To clarify, thereare threelevels ofsoftware here:
¢ The DPMIserver provides INT 2Fh and INT 31h DPMIservices.
* The DPMIclientcalls INT 2Fh and INT31h DPMIservices; in manycases, this DPMIclientis a DOSextender that provides protected-mode INT21hservices. Onthe otherhand, some DPMIclients (ike USEDPMDjust assumethat a DOSextender is also present. * The DOS-extendedapplication calls protected-mode INT 21hprovided bythe DOSextender. It canalso call DPMIservices.
Unauthorized Windows 95
In the case of DOSX.EXE, the DOS extender(a DPMIclient) hap-
pensto residein the same programas the DPMIserver. As we know,
DOSX.EXE runs KRNL286.EXE or KRNL386.EXE.In other words, KRNL286 and KRNL386 are DOS-extended programs. True, these are also Windows DLLs, containing the Windows KERNELAPI, but these
two files also contain real-modeinitialization portionsthatcall INT 2Fh function 1687hto switchinto protected mode(see the descriptionof the BootStrap routine in Chapter1 of Matt Pietrek’s book Windows Internals).
DPMIwasinitially intendedto help implementportable, compatible
DOSextenders. According to Ray Duncan,“It’s highly unlikely that you will ever needto call DPMIfunctionsdirectly in a programof your own” (Extending DOS,2d ed.). However, DPMI hasturned out to be useful not
only to the handful of DOS extender vendors butalso to developers of moretypical programs,such as Windows applications, when the normal APIdoesn’t provide everything these applications need. For example, manyWindowsapplicationscall DPMI function 0300h (Simulate RealMode Interrupt; see WV86TEST.C in Chapter 12 for an example).
According to Duncan’s excellent chapter on DPMIinthe book Extending DOS (2d ed.), Microsoft’s original intent for DPMIwasthat the specification would include protected-mode INT 21h; as the name DOSProtected ModeInterfacestill suggests, INT 21hin protected
modewasoriginally intendedas a key part of the DPMI:
| will never forget how startled | was when | encountered the DOSProtected-Mode Interface (DPM) in its primordial form forthe first time. | was sitting in a Microsoft 0S/2 2.0 ISV seminarin the Fall of 1989, with my mind only about half-engaged during anuninspiring session about OS/2 2.0's Multiple Virtual DOS Machines (MVDMs), when the speaker mentionedin passing that OS/2 2.0 would support a newinterface forthe execution of DOS Extender applications, This casual remark focused mymind remarkably... After the speakerfinished, | went up to him and asked for moreinformation, explaining that his mystery interface was about to have a severe impact on a bookproject. near and dear to myheart. In a couple of hours, the Microsoftie returned with a thick documententitled “DOS Protected ModeInterface Specification, Revision Prerelease 0.04” still warm from the Xerox machine and generously garnished with “CONFIDENTIAL” warning messages.| suspect | made a most amusing spectacle, as | flipped throughthe pages with myeyes bulging out and my jaw droppingto the floor. The document | had been handed wasnothingless than the functional specification of a protected:mode version of DOS! In retrospect, the fact that Microsoft was cooking up somethinglike DPMI should havebeenobvious. Every computerjournalist in America, not to mention thousands of beta testers, was well aware that the as-yet-unannounced Windows 3.0 was somehowable to take advantageof extended memory by executing applications in protected mode, even thoughit ran on top of DOS and usedthe DOSfile system....
Chapter 5: The Two Faces of Windows
But | never sawa word of speculation in print on how this was accomplished, and| must confess that for my own part, | never gave it a second thought... Microsoft originally defined the DPMIin twolayers: a set of low-level functions for interrupt management, mode switching, and extended memory management; and a higher-level interface that provided access to MS-DOS, ROM BIOS,and mousedriver functionality via protected-mode executionof Int 21H, Int 10H, Int 33H, and so on. The higher-level DPMI functions were implemented,of course,in terms ofthe lowlevel DPMIfunctions and the extant realmode DOS and ROM BIOSinterface..... Whendetails of Microsoft's DPMI began to leakout to the general communityof MS-DOSdevelopers, the rumors provoked more than a few hard feelings and harsh words for two very good reasons.First, the vendors ofother DOS Extenders suspected that Microsoft, having realized that OS/2 was notgoing to replace DOS any time soon, had decided to barge into the market niche they had established so painfully and elbowthem outthrough the sheerweight of its developmentresources and marketing power. Second, Microsoft had designed the DPMIwith total disregard for compatibility with the existing industry standard for DOS-basedprotected-mode software — theVirtual Control Program Interface(VCPI).... For a few months,it appeared thatthe fledgling DOS Extender market wasgoing to fragmentin two mutually-exclusive directions, resulting in additional headaches for software developers, hasslesfor end-users, and juicy fees for lawyers. Luckily, coolerheadsprevailed. Microsoft turned control of the DPMI specification over to an industry committee with open membership, and the previous backers of the XVCPI [Extended VCPI] effort decidedto join forces behind the DPMI. Intel, with its understandable enthusiasm for anything which might sell more 80386chips, was instrumentalin bringing about this reconciliation, and also tookonthe responsibility of publishing and distributing the DPMISpecification. Aspart ofthis process of accommodation, Microsoft agreed to the deletion of the portions of the DPMIwhich cross into DOSExtenderterritory, specifically, direct support of the DOS and ROM BIOSinterruptsin protected mode. Consequently, DPMIversion0.9, the first public versionof the specification which wasreleased by the DPMI Committee in May 1990, defines only the “low-level” or “building block”functions..... Naturally, the higher-level or DOSExtenderinterface of Windows3 still exists,but it has receded back into the twilight zone of semi-support and semi-documentation. The only Microsoft documentation on the Windows3 DOSExtenderis a five-page technical note,entitled “WindowsInt 21H and NetBIOS Support for DPMI,” that is mainly remarkable for what it doesn't say.”
— Ray Duncan,Extending DOS,2d ed., 1992, pp. 433-438. Indeed, the INT 21hinterfaces provided by DOSX in Standard mode and by DOSMGR andIFSMGRin Enhanced mode are practically
undocumented, though from Duncan’s accountit appearsthat this — at least in part — is an accommodation Microsoft made to DOS extender
vendors such as Phar Lap, Rational Systems, and Ergo.
Microsoft has an internal document (“MS-DOS API Extensions for DPMI Hosts,” October 31, 1990) that devotes about 30pages to the
Windows3.0 DOSextenders.
Microsoft's five-page note that Duncan
Unauthorized Windows 95
mentionsappearsto have beenboiled downfrom this moreextensive document.For example, the 1990 documentdiscusses the 32-bit DOS extender provided by DOSMGR. The DOSfile read andwrite calls (INT 21hfunctions 3Fh and 40h) have the countregister (ECX) extended to 32 bits, allowing 32-bit programsto perform DOSfile /O of more than 64K at a time.
Although DPMitselfis hardly undocumented(the DPMIspecificationis readily available at no charge from Intel and hasbeenreprintedin countless books), Microsoft barely documentsthe presence of DPMI (version 0.9) within Windows. The Windows 3.1 SDKcontainsa total offour pages on both the DOSextender and DPMI(“WindowsApplications with MS-DOSFunctions,” Programmer's Reference, Volume1: Overview, Chapter 20). This scant chapterlists a mere seven DPMIfunctions that Microsoft approvesfor use by Windowsapplications. On the
otherhand, the same document alsoclaims that Windowssupports version 1.0 of DPMI. Windows3.x Standard and Enhanced modes, as well as Windows95, actually support DPMI0.9.
I’ve stated that the DOSX.EXEportion of Windows Standard mode is a
general-purpose DPMIserver and DOSextender. But howgeneral pur-
poseis it really? After all, DOSX mighthavestarted out as code belonging to a debugger, but nowit’s part of Windows and doesn’t seemlike something you couldjust tear out of Windowsto usefor otherpurposes. Indeed, DOSXwill run only KRNL286.EXE or KRNL386.EXE, no
matter whatyouspecify on its commandline. If DOSX can’t find either
ofthesefiles, it fails with the message “Cannotfindfiles neededto run Windows in standard mode.” Worse, DOSXgrabsthe largest available block of XMS memoryand(when exiting becauseit can’t find KRNL286 or KRNL386)neglects to deallocate this XMS memo So when you try to rerun DOSX with KRNL286.EXEor KRNL386.E, DOSXfails
with a “Cannotstart Windows in Standard Mode” message
andyou have
to reboot to get back the XMS memory. This doesn’t seem very general
purposeat all. DOSX soundshopelessly attachedtothefiles KRNL286 -EXE and KRNL386.EXE. Although DOSXcan run only KRNL286.EXE or KRNL386.EXE,
on the other handit will run anyfile with one of those names! If some other file calling itself KRNL286 were to request DPMI services, use
Chapter 5: The Two Faces of Windows
DPMIto switchitself into protected mode,and issue INT 21h callsin protected mode, DOSX would runit,just as it runs the KRNL286.EXE and KRNL386.EXE files that happen to come with Windows. For example, Figure 5-2 shows the USEDPMIexample from Listing 5-1, running under DOSX. C:\WINDOWS\SYSTEM>copy \unauthw\usedpmi .exe C:\WINDOWS\SYSTEM>usedpmi his program requires DPMI Cz \WINDOWS\:
TEM>ren krn1386.exe krnl386.sav
\WINDOWS\SYSTEM>ren usedpmi .exe krn1386.exe
Greetings from protected mode! C:\WINDOWS\SYSTEM>ren krn]386.sav krn1386.exe
Figure 5-2: Renaming USEDPMI.EXE to KRNL386.EXE and executingit using DOSX demonstrates that DOSXis a general-purpose DPMIserver and DOSextender. See? DOSX.EXE reallyis somethingthat(if it didn’t constitute copyright infringement!) you couldjust tear out of Windowsto use for other purposes.
‘The example givenin Figure 5-2 relies on three assumptions:
* First, this example works only on a 386 or later machine. On 286 machines, you would have to change USEDPMI.EXE’s nameto KRNL286.EXE,since DOSXwill want to run that program rather than KRNL386.EXE. * Second, theoriginal “This program requires DPMI”messagewill not occurif you’re running under a memory managerthatalready provides DPMI, such as QEMM(with QDPMI)or 386MAX.If youare, youdon’t need DOSXto run USEDPMI. However,this is still a good
exampleofthe pointthatthe small DOSX.EXEfile is a general purpose DPMIserver and DOSextender. There’s also someinterestinghistory behind thecapability of DOSXto run undera 386 memory manager, but unfortunately thereisn’t timeto gointoit here; for
thejuicy details, see Geoff Chappell’: DOSInternals (pp. 559-569).
* Third, this exampleassumesyou're notalready running Windows. You can start DOSX only outside Windows. If you try running DOSX
Unauthorized Windows 95
from within WindowsEnhanced mode,you'll get the interesting message “Cannotstart Windowsin Standard mode. Youare usingan expanded memory manager whichis not compatible with Microsoft Windows 3.1, or which is configuredincorrectly. Try removing or reconfiguring your memory manager, or using the copy of EMM386.EXEsupplied with Microsoft Windows 3.1.” DOSX thinks
that Windows Enhanced modeis a 386 memory managerlike EMM386. Well, in manywaysit is.
Sinceit’s a pain to renamefiles as shownin Figure 5-2, I’ve written a small DOSbatchfile to take care ofthis. This batchfile, called RUNDOSX,is shownin Listing 5-2. It runs any programnamedonits command line under DOSX by temporarily renaming the programto KRNL286.EXE.(Ifa file named KRNL386.EXEis not present, DOSX will run file named KRNL286.EXEboth on 286 and 386orlater processors.) Listing 5-2: RUNDOSX.BAT @echooff rem RUNDOSX.BAT rem Requires modification to redirect output if (B1)==() goto usage f exist krn)286.exe ren krn]286.exe ken} st krn1386.exe ren krn1386.exe krn]386.z, not exist %1 if exist dosx.exe goto have_dosx \windows\s. tem\dosx.exe >nul exist X.exe goto no_dosx have_dosx py #1 krnl286.exe >nu krnl286 %2 23 %4 %5 26 37 48 29 del krn1286 f exist krn1386.z2z ren krn1386.22z krn] f exist krnl286.222 ren krn1286.2zz krnl
goto
end
usage echo RUNDOSX runs a DPMI client (a real-mode 00S program that uses to mode) under the Windows Standard mode DOS extender echo switch into pro (D0SX.EXE), by temporarily renaming the DPMI client to KRNL286,EXE echo echo DPMI clients can be created with the DPMISH library. rundosx [name of OPMI client] Cargs
t find #1
Chapter 5: The Two Faces of Windows goto end no_dosx echo Can't find \WINDOWS\SYS M\DOSX. EXE
Althoughyou canlaunchany program(even COMMAND.COM) with RUNDOSX,it makes most senseto launch DPMIclients thatrely on the Windows DOSextender, such as USEDPMI:
Incidentally, RUNDOSX \COMMAND.COMdoesn’t worklike you might wantit to work. Sure, it gives you a C:\> prompt with DOSX loadedin memory (which effectively turns DOSXinto a TSR). And sure, youcan run a DPMIclient fromthis C:\> prompt: CE\UNAUTHW>rundosx \command.com
s from protected mode! C:\UNAUTHWDexit But unfortunately, you can run a DPMIclientfrom this C:\> prompt only on
Huh?! This is one place where DOSXisn’t so general purpose afterall. DOSXassumesthereis only one DPMIclient per DOSXsession.After switching a program into protected mode, DOSX unhooksitself from real-mode INT 2Fh. The next programtocall INT 2Fh function 1687h
will believe that DPM isnotpresent, unless some other DPMIserver
such asQEMMor 386MAX also happens tobe running;in this case the DPMIclient will get that DPMI serverinsteadof the one in DOSX.
Unauthorized Windows 95
This, by the way, is why DOSprograms running under Windows Standard modecannot use the Windows DPMIserver or DOS extender;
only Windowsprogramscan. After DOSX sees KRNL286.EXEor KRNL386.EXEswitch into protected mode, it unhooksitself from INT
2Fh,so no other program can call DPMIto switch into protected mode. Windowsapplications can use DPMI INT 31h functions, and the INT. 2Fhfunctions that DPMIsupportsin protected mode, because these programsstart off in protected mode; they don’t haveto call the DPMI switch procedure. To run multiple programs under DOSX,then,just use RUNDOSX each time.
Using the DPM! Shell Library USEDPMIshowedthebasics of writing a DPMIclient. The DPMIShell
(DPMISH)library on the Unauthorized Windows 95 disk is a big improvement. For example, Listing 5-3 (USEDPMI2.C) shows USEDPMI
rewritten to use DPMISH. Listing 5-3: USEDPMI2.C USEDPMIZ.C very simple DPMI client bee usedpmi2.c dpmish.c ctrl_c.asm Andrew Schulman, 1994 */ Hinclude Hinclude #include
include "dpmish.h*
void fail(const char *s, ...) { puts(s): —dos_exit(1):
void print_regs(void) unsigned short ds_reg, cs_reg; _asm mov cs_reg, cs asm mov ds_reg, ds printf(*CS=04xh DS=804xh\n", cs_reg, ds_reg):
int real_mainint argc, char *argvC]) print_regs( return 0;
int pmode_main(int argc, char *argvt])
Chapter 5: The Two Faces of Windows
ngs from protected mode! \n");
As you cansee, a DPMISH programincludes DPMISH.H andpro-
vides two functions, real_main and pmode_main. DPMISHcalls the program’s real_main function in real (or V86) mode.If real_main returns 0, DPMISHswitches to protected mode andcalls the program’s pmode _main function. DPMISHtakescare ofeverythingelse for you.
MEMLOOP USEDPMIand USEDPMI2are unexciting programs. For a more dramatic example of what a DOS extender is good for, consider MEM-
LOOP.CinListing 5-4.MEMLOOPcalls the DOS memoryallocation function (INT 21h function 48h) in a loop, via the _dos_allocmemfunc-
tion provided by C compilers for DOS, allocating memoryuntilit (memory, not the program) is exhausted. MEMLOOPuses _fmemsetto touch eachbyte in each allocated block, both to showthatthisreally is immediately usable memory(nolock or copy function required) and to make the results morerealistic on systemsthat provide virtual memory. Each time _dos_allocmemfails,MEMLOOP chopsitsallocation requestin half in
an attemptto soak upeverylast drop of memory. When there’sreally no more memory left, MEMLOOPprintsthe total amountallocated and exits, leaving DOStofreeall the memory. If compiled for DPMI(#ifdef DPMI_APP), MEMLOOP.Cincludes
real_main and pmode_main. Otherwise,it uses plain old main. Listing 5-4: MEMLOOP.C MEMLOOP.C How much
mode: bec memloop.c prot mode: bec -2 -DOPMI_AP On machine with 12 megab: Real mn DPMI DPMI OPMI a
file)
Unauthorized Windows 95
#include : kbytes >>= 1; printf(*\nallo Hifdef DPMI_APP void fail(const
{ puts(s):
int real_main(int argc, char *argv{] fetura ¢ kay to switch to p
nt pmode_main(int argc, Helse nt main endif
dos_exit(1): ed m
char *argy
mem_loop(): eturn @
If we build MEMLOOP as a real-mode program, it not surprisingly allocates someamount of memory less than 640K, even on a machine with, say, 12MB of memory
Chapter 5: The Two Faces of Windows C:\UNAUTHW>bee mem} oop.c CE \UNAUTHWD1 in 17 blacks Here’s what happensif we rebuildMEMLOOPas a DPMIprogram and runit under DOSX.EXEonthe same 12MB machine: C:\UNAUTHW>bec -DDPMI_APP dpmish\ctr1_c C: UNAUTHW> runt mem
domish memloop.c
..\dpmish\dpmish.c
Amazing! Simply by using DOSX.EXE,the DPMIversion of MEMLOOP allocated 10MB of memory, even thoughthe almostidentical
non-DPMIversionallocatesless than 640Kon the samesystem.Yet, all we did was type RUNDOSX MEMLOOPEXEfrom the DOS command prompt, without having to switch to a newoperating system. This DOS extenderstuff is pretty great, eh? Well, DOS extender technology is the foundation for Windows 3.x
and for Windows95. It was because Windows1.x and 2.x were missing this technology — just a tiny program like DOSX.EXE — thatthey could getsolittle memory, and consequently were so worthless and performed sorelatively poorly in the marketplace. This little DOSX.EXE
programis worth a heckofa lot! I hope Murray Sargent and David Weise gota lot of stock. RUNDOSX MEMLOOP.EXEdramatically illustrates what DPMIis
and what a DOSextenderis. It demonstrates that DPMIlets a real-mode program jumpinto protected mode with a simple functioncall, and that a DOSextenderlets this program continuetouse familiar DOScalls while in protected mode butto do things(like allocate 10MBof immediately usable memory) that aren’t possible underplain-vanilla DOS. RUNDOSX MEMLOOP.EXE also showsthattherearereally two parts to Windows,andthat those twoparts are semi-independent of each other. The lower-levelpart includes the DPMIserver and DOSextender; the upper-level part includes Windows DLLs such as KRNL286 and KRNL386, USER, and GDL MEMLOOP couldjust as well be the KRNL286.EXE or KRNL386.EXEfiles from Windows. And KRNL286 and KRNL386 could, presumably, run under some DPMIserver and
DOSextender other than DOSX;you'll meet one such DOSextender in the next chapter when we discuss Windows Enhanced mode. The two parts of Windowsare only semi-independent because,as is
well known, the upper part of Windows is not a pure DPMIclient.
Matt Pietrek discusses this in his book Windows Internals:
Unauthorized Windows 95
The low level KERNELroutines are not shy about considering the LDT [Local Descriptor Table] to betheir ownlittle playpen... Why does KERNEL bypass DPMI? Wasn't DPMI created to prevent this kind of mucking with sensitive system resources? The answer is yes. However, there often comesa point where proper code and performance clash head to head. The KERNELdevelopersbuilt and testeda version of KERNELthatallocated each and everyselector from DPMI. The developers saw enoughof a performancehit with this KERNELthatthey felt hacking the code to accessthe LDT directly was worth it. The code is compatible with DOSX and WIN386,in that it still allows other programsto allocate selectors from the DPMIserver. Unfortunately, this version of KERNELcreates a hidden assumption about the way the DPMI host managesthe LOT. If another DPM! host wishes to replace WIN386or DOSX, it must organize the LDTin the same manner. However, the DPMIspecification doesn’t tell a DPMI host to manage the LDTin a particular manner, which creates ambiguity betweenthe written and real DPMI specifications. — MattPietrek, Windows Internals, 1993,p. 90.
As IBMdiscovered while working onits OS/2 for Windows product, KRNL386.EXErequires someserious patching to makeit run under OS/2’s DPMI server. Onthe other hand, an engineer at Qualitas says
that company uses KRNL386 .EXE internallyas the test program for the DPMI server in its 3836MAX memorymanager, andadds that
Qualitas had more problems with Borland’s DPMIsoftware thanit had with KRNL386! Although there are no VxDsinthis setup, running KRNL-386.EXE under 386MAX without benefit of one of the
Windows DOSextenders does work well enough torunSolitaire. Well, heck, that’s what we all use Windowsfor anyhow.
Chapter 6
Prorecteo-Mone DOS: WINS8G ano MSDPMI Ne that the experiments with DOSXinthe previous chapter have provideda solid grounding in DPMI and DOSextender technology, we
can take a close look at WIN386.EXE.As notedin the previous chapter,
‘WIN386 is a collection of VxDs. The key component of WIN386 is the Virtual Machine Manager (VMM), VxD ID #1, whichis the true core of
the Windowsoperating system. Thefile VMM32.VXDserves the same
purpose in Windows 95 that WIN386.EXE does in Windows It’s commonto read statements asserting that “WIN386.EXE is the DPMI server.” This is sort of like claiming that “KERNEL is the GlobalAlloc function.” Although VMMdoes contain the DPMI server,
this is just one small part of VMM. And VMMin turnisjust one(albeit the most fundamental) part of WIN386 (in 3.2 Enhanced mode) and VMM32.VxD (in Windows 95). VMMhas many otherresponsibilities,
such as preemptive multitaskingofvirtual machines and threads, inter-
rupt handling, and memory management. DPMisa layerontopofthis andappearsto be little more than a wayfor “normal”(that is, non-VxD)
applicationsto call some VMMservices.
In Enhanced mode, the Windows DOSextenderresides in the DOSMGRVxD, alsolocated inside WIN386.EXE; when 32-bit file access is
enabled in WfW3.11 and Windows95, the IFSMGR.386 VxD should probably be consideredpart of the DOSextender, too. Writing in Windows Tech Journal (March 1992), David Thielen, then a
Microsoft employee,noted:
Unauthorized Windows 95
Win386isn’t really even part of Windows. It’s a preemptive multitasking kernelthat controls multiple virtual machines. Once Win386 has initialized itself, it loads Win-
dows in the system VM(the main virtual machinethat alwaysexists). However,it could just as easily load COMMAND.COMinstead,resulting in a multitasking DOS. (No, | won't tell you how to do this.)
Well, after Chapter5’s discussion of how to make DOSX.EXEload something otherthan the Windows kernel, it shouldbefairly apparent howto do the same thing with WIN386.EXE. Just as DOS. E insists on running KRNL286.EXE or KRNL386.EXE, WIN386.EXE (actually, the SHELL VxD within WIN386)insists on running KRNL386.EXE
Butjust as with DOSX, WIN386will run anyfile called KRNL386.E: even COMMAND.COM, ifyou rename it! Fortesting out the DPMI
server and DOSextender in WIN386, we canconstruct the samesort of batchfile we used for DOSX. However,there’s onedifference: in addition to WIN386.EXEanda
file named KRNL386.EXE, wealso need a SYSTEMLINIfile and (in
somecases) a virtualdisplay driver. SYSTEM.INI usually requires only
an [Enh386] section,listing VxDs to be loaded. Our first versionwill just list the VxDs that come built into WIN386.EXE. Listing 6-1 shows GOWIN386.INI, which our batchfile will copy over to SYSTEM.INI.
Listing 6-1: GOWIN386.INI win386. ini
minimal system.ini for gowin386.bat
Chapter 6: Protected-Mode DOS: WIN386 and MSDPMI
ByexaminingListing 6-1, youcanalready see one way Enhanced modeis different from Standard mode: it not only provides a DOS xtender and DPMIserverbutalso a VxD loader. Depending on your configuration, you might needto add otherlines to SYSTEM.INI,such as SystemROMBreakPoint=false if you’re running with QEMM. Or,
you mightneedtoadd additional device= lines for other VxDsyouneed to use or wantto experimentwith. Listing 6-2 shows a simple DOS
batchfile called GOWIN386.BAT, whichruns anyprogram under
WIN386.EXE. Listing 6-2: GOWIN386.BAT
no_sysini copy gowin386. ini system.ini >nu
goto end echo GOWIN3B6 r witeh ho by temporarily echo Usage: gowin goto end
222 krn)3B6.exe DPMI client mode DOS program that ed mo the Windows Enhanced mode WIN386.EXE renaming the OPMI client to KRNL386.EXE with the OPMISH 1 OPMI client]
Unauthorized Windows 95
9 This program requires GOWIN3B6.INI
Find WIN386. EXE
First, let’s try USEDPMI(fromChapter 5) to see if GOWIN386 works. The results aren’t reallyvery exciting, but they do show that GOWIN386 works aboutthe same as RUNDOSX: C:\UNAUTHW>gowin386 usedpmi .exe Greetings from protected mode! Now let’s try MEMLOOP (again, from Chapter 5). If you'll recall, under DOSX, MEMLOOP onmy 12MB machinecould allocate 10MB of memory via the DOS INT 21h function 48hinterface. This is about
whatyou’d hope for on a machine with 12MB of memory,butit seemed pretty impressive because we’re normallylimited to less than 640K under DOS.
However, the results of runningMEMLOOPonthe same 12MB machine under WIN386are quite different from what we saw under
DOSX.At first, it lookslike the programisn’t working, because it grinds awaywith the hard-disk drive light on for several seconds. Thenit announces:
Your mileage may vary depending on how muchfree disk space you have, how muchphysical memoryyouhave(four times physical memory is the maximumvirtual memory WIN386will allocate), and whether there’s a permanent swap file visible when running GOWIN386 (for
example,if you copythe Windows SPART.PAR pointerfile into the directoryfrom which you run GOWIN386).
Butinthis configuration, we’veallocated 37MBof memory: Welcome
to the worldof virtual memory! Remeber that this is an unchangedbinary copy of MEMLOOP
-EXE, and that MEMLOOP is allocating memorynot via some special
Windows API but byusing the venerable DOS memory allocation function. So this is not only virtual memory, but virtual memory with a DOS interface.
Chapter 6: Protected-Mode DOS: WIN386 and MSDPMI
In a world whererelatively minor improvementsare often touted as revolutionary advances, virtual memorywith a DOSinterfaceis a refreshing change. Here’s somethingfairly newandexciting, masquerading as somethingoldandboring. The phrase “underpromise, overdeliver” comes to mind. Ofcourse,this isn’t Microsoft’s usual approach to packaging. It would have been moretypical for Microsoft to have packaged whatare fundamentally V86-mode DOSservices as Windows (WIN386.EXE), thenrealized that these services should be part of DOS (witness the name DOS386.EXEin pre-beta versions of Chicago), and
then finally reconsidered theissue andsettled on the uninteresting name VMM32.VXD. At anyrate,WIN386, DOS386, or VMM32 — whatever youwant to call it (we'll see later in this chapter that Microsoft oncecalled it MSDPMIL, too) — is really a V86-mode version of MS-DOS that supports virtual memory, device virtualization, anda host of other features, some of which (like 32-bit disk andfile access) even provide better
performance. Figure 6-1 showsthat the lowerlevel of Windowsis really an enhanced modeof
DOS; once we’ve typed GOWIN386 \COM-
MAND.COMonthe commandline, weentera world that looks exactly like a V86-mode version of MS-DOS, complete with DPMI services
and a whole host of VxDs.In fact, this is the multitasking DOSthat the Windows Tech Journalarticle quoted earlier wastalking about. True, we haveonlyone virtual machine here, but you could write a VxD thatlet the user launch additional VMs andswitch between them. Notethat in contrast tothe situation with DOSX, we can run more than one DPMI
application fromthe C:\> prompt under WIN386.
C\UNAUTHW>gowin386
\command. com
C:\UNAUTHW>usedpmi 2 ‘om protected mode! JNAUTHW>mem] oop Allocated 38096 Kb UNAUTHWD.
\wadlist\ vad] ist
Unauthorized Windows 95
Name
Vers
10
008
vent VPICD v PageFile PageSwap PARITY Reboot EBIOS voo yso veo vMo vKO BLOCKDEV INTI3, y
3.11 3.10 3.10 2.00 2.10 1,00 2.00 1.00 2,00 2.00 3.10 3.00 2.00 3.10 3.11 2.00
0001h @003h d005n 0021h 0007h 0008h 0009h 0012h 000An o00Bh 000Eh 000Ch 000Dh 0010 0020h 0018h
s0011Ae8 B000AEI4 8001CB788BO1BAE4 800225C0 80021852 8003660C 80036080 002D1EC 8002C894 80036AF4 80036A4C 80023274 80022688 BOBIF7EO 8001F 770 BO01A75C 80014058 80025238 goazsecs 80037080 80037220 80016514 B001E200 80021684 8001 F090 80036038 80035080 80010700 g0e10458 800369E0 80036890
BIOSXLAT WWETBIOS DOSMGR VMPOLL OSVXD COMBUFF vomMAD VOGHMGR SHELL
1.00 3.00 1.00 3.10 «3.00 1.00 2.00 1.00 3.00
9013h 0014h 0015 018h 0038n
80036F48 B001F62C 80031034 80031848 BOD13FF8 80038650 80024048 8002C840 80035850
vcPD
1,02
@011h
004 0006n 0017h
80038258
Contro)
v@6 API. 8001C2A0 B0OZIAE7
PM APT. 8001C2A0 800Z1AE7 80036547 80022961 g0017F0B
g0d1e450
30037275 80016450 gooz0zcé
800380BC
80036888 g001E748 BddzECF? -800315F8 —80013E28 80038248 800233F8 8002AED7 80034466
Srvc. 242 21 8 7 a a 0 2 14 2 9 3 15 7 5 0 3
80026838* 80013E7F 80032650
e 4 12 3 e e 24 ai 6
Figure 6-1: Running COMMAND.COM under WIN386.EXE switches you into V86 mode, complete with virtual memory, DPMI services, VxD services, and so on. Whatgoodis this V86-mode version of DOS? Well, even thoughit lookslike you’re in real-mode MS-DOS, you're actually in V86 mode now: DPMis resident, you’ve got a resident DOS extender that supports both 16- and 32-bit programs, and you’vegotvirtual memory and a whole assortmentof VxDs — youjust don’t have any of the GUI Windowsfeeling. Fromthis perspective, the Windows GUI (KERNEL, USER, GDI, andso on)is just another programlike MEM-
LOOPor USEDPMI. Running GOWIN386 \COMMAND.COM isn’t much different from a Windows DOS box;after all, you can run DPMIclients and DOS
extended applications in a Windows DOSbox,too. But this DOS boxis notparticularly tied to Windows. WIN386is quite separate fromthe rest of Windows, and as we’veseen,it feels much morelike part of DOS. At one pointin the Chicago beta, WIN386 was renamed DOS386; that was a more accurate name than WIN386.
Chapter 6: Protected-Mode DOS: WIN386 and MSDPMI
What mode is KRNLSBE loaded in? We've seen that WIN386.EXE will load KRNL386.EXE — anyfile we call KRNL386.EXE. WIN386 successfully loads USEDPMI, USEDPMI2, and MEMLOOP when these masquerade as KRNL386. We know that these are normal real-mode DOS executables that use DPMI to switch themselves into protected mode. But hold on a minute! We also know that WIN386.EXE
consists mostly of VxDs, which run in 32-bit protected mode(look at the addresses VXDLISTspits out in Figure 6-4). If WIN386is already running in 32it protected mode, how do the programs named KRNL386.EXE manage to start up in real mode? The answeris that they don’t: Theystart up in V86 mode. Recall that V86 modeis a simulated real mode controlled by what Intel’s documentation calls a VMM. WIN386 does put the machineinto 32-bit protected mode. But whenit starts the first Windowsvirtual machine (VM) — the System VM — it switches the VM to V86 modeto start KRNL386.EXE. WIN386 runs KRNL386in the System VM. KRNL386 (whether the one that comes with Windows or one of our DPMISH pretenders) uses the function pointer returned from INT 2Fh function 1687h to switch into 16-bit protected mode. Function 1687h is handled by VMM, which contains the Enhanced mode DPMIserver. Any DOSboxesthe user starts in Windows become additional VMs that can be used to run rea-mode DOS software, DPMIclients, and/or DOSextended applications. This isn’t very different from what happensin the
System VM: KRNL386.EXEis just like a DPMI client that the user might start in a DOSbox. Furthermore,you can run realmode software in the System VM by listing it in WINSTART.BAT. There's a lot of symmetry between DOS boxes and the System VM. For what it's worth, Windows 3.0 wasdifferent. DPMISH calls INT 2Fh
function 1686hto seeif it's already running in protected mode.If so, DPMISH doesn’tcall dpmi_init. That's because, in Windows 3.0, KRNL386.EXE expected WIN386.EXE to have already put the System VM into protected mode; KRNL286.EXE also expected to be launched in protected mode by DOSX.EXE. This meansthat, if you took a real-mode pro-
gram like COMMAND.COM, renamedit KRNL386.EXE, andranit under the Windows3.0 version of WIN386, WIN386 would try to run COMMAND.COM in protected mode. Nota pretty sight.
DPMIINFO RUNDOSXis a cute example, but GOWIN386 \COMMAND.COM is the genuinearticle: an Enhanced mode of MS-DOS. But what exactlyare
Unauthorized Windows 95
the differences between DOSX and WIN386? Onecleardifferenceis the size ofthefiles: DOSK. EXE WIN386. EXE What does WIN386do that DOSX doesn’t that wouldaccountfor an extra 540,000 bytes of code? We already know that WIN386, unlike
DOSX,supports more than one DPMIclient,providesvirtual memory,
andloads VxDs. The VxDs listed in Figure 6-1 account for most of WIN386.EXE’s bulk.
‘To get a moresystematic look at thedifferences between WIN386 and DOSX,youcan use the sample program DPMIINFO,shownin Listing 6-3. This small program(which again uses the DPMISHlibrary) calls INT 31h function 0400htoretrieve information abouttheinstalled DPMIserver, such as whetherit supports 32-bit programs and whetherit reflects interrupts to real mode or V86 mode.
Listing 6-3: DPMIINFO.C
DPMIINFO.C display information about DPMI server Andrew Schulman, 1994 #include > 8 unsigned char min vers & Ox if ((maj 0) && (min 0x90)) min
printf("DPMI version
%d.802d\n", maj, min);
printf( print print
silly Std mode bug
based DPMI host\n* & 386 286); refle
printf(*%s virtual memory\n flags & 4) "Supports" printf("%lu bytes available in
y 16-bit®
Ee
e
_dpmi_mem()):
Figure 6-2 shows DPMIINFOoutput for both DOSX and WIN386.
As you cansee, both DPMIservers support DPMIversion 0.90. But WIN386is far more capable than DOSX:It supports 32-bit programs,
reflects interrupts to V86 moderather than to real mode (see Chapters9
and10forthe,like, totally awesomesignificanceofthis), and supports
virtual memory.
Unauthorized Windows 95
No virtual 11104192 byte
able in
largest
block
grams supported PML host reflected to V86 mode s virtual menory ytes available in largest
block
V86 mod
virtual
memory
Figure 6-2: Running DPMIINFO under DOSX, WIN386, and QEMMhighlightsthe differences between these environments.
Notice that, in addition toRUNDOSX and GOWIN386,Figure6-2 also shows DPMIINFOrunstraight from the DOS commandprompt. QEMM 7.03 was loadedforthis test; as you can see,the DPMI serverin QEMM looks muchlike the one in WIN386.It even(via the DPMLSWP file) supports virtual memory, which happenedtobeset to 1OMB: DEVI
QEMM\ODPMI.SYS. SWAPE
QEMM alsoincludes a DOS extender from Ergo Computing. 386MAX supports similar features(andalso implements DPMI1.0).
WINS8E really, really is d Memory manager The fact that 386 memory managers support many of the samefeatures as WIN386canbeturned around to point out that WIN386,in many ways, resembles a 386 memory managerthat you can start up from the DOS command prompt. The V86MMGR (V86 memory manager) VxD inside
Chapter 6: Protected-Mode DOS: WIN386 and MSDPMI
WIN386 provides its own Expanded Memory Specification (EMS) and Extended Memory Specification (XMS) drivers — even if you already had an EMSprovider before starting WIN386, and even though an XMSdriveris required before starting WIN386.
You can seethis if you run a diagnostics program such as Quarterdeck’s Manifest, once before running WIN386 and again from inside WIN386. In one configuration, running HIMEM.SYS 3.09 and EMM386.EXE
4.44, you get the results shownin this table:
386
Insid
386
EMM386OF:
EMSversion XMSversion XMSdriver
None 3.00 3.09
4.00 2.00 2.05
With EMM386 ON: EMSversion VCP!version XMS/EMSsharing
4.00 1,00 Yes
4.00 None No
Microsoft seems confused on this point, because a KnowledgeBase article, “XMS Version Information in MS-DOS Window Incorrect” (Q83455, September 1992), maintains that the behavior we've just seen is some sort of error: The application retrieves the version number of the XMS driver in enhanced mode Windows, not the version numberofthe “real” XMS driver (which was present before Windowsstartup).
But this is the wayit should work. The V86MMGR VxDinside WIN386 really is a V86 memory manager; it really does supplantpreexisting XMS and EMM drivers. As far as applications running under Windows are concemed, V86MMEGRis the “real” memory manager.For example, even if an XMS 3.0 serveris present before Windows started, once Windowsis running you canuseonly XMS 2.0 functions. The fact that V86MMGR takes over EMS and XMS from any memory managers loadedbefore it has important implications for software loaded before Windows. Chapter 3 discussed the Global EMM Import specification for memory managers, but V86MMGR's assumption of all EMS and XMS. responsibilities also has serious implications for run-of-the-mill DOS TSRs that use EMS or XMSandthat expect to continue working while WIN386 is. running. V86MMGRis the “real” EMS and XMS memory manager,notonly for programsrunning under Windows but even for TSRs loaded before Windows.This is just oneof the many remarkableeffects that Windows has on software loaded before it. As Chapters 9 and 10 will show, Windows can be said to rest on top of DOSonlyin the sensethat an elephant might be said to ride on top of a mouse.
Unauthorized Windows 95
Microsoft doesget this right on the MSDN CD-ROM.David Long's excellent article on “TSR Support in Microsoft Windows Version 3.1” has a lengthy appendix, “How to Be a Good EMS/XMSClient,” that provides guidance for global (that is, loaded before Windows) TSRs and device drivers that use EMS or XMS. For example: Be aware of XMS version number anomalies. The WIN386 XMSversion number is 2.00.If the running XMSdriver at WIN386startup timeis an XMSversion 3.0 driver, the XMSversion number will change across the startup and exit boundaries. The WIN386 XMSdriverreally is a 2.00 driver. Any XMS 3.0 calls made while WIN386is running will fail Okay, nowthat we've gotthatstraight...
Given that 386 memory managers providea similar environment to WIN386(and vice-versa), what's the big fuss about running GOWIN386 \COMMAND.COM?Howcanthis be viewed as somekind ofsneak previewfor the future of DOS whenit doesn’t appearsubstantially differentfrom what's provided by commonlyavailable third-party managers? Asyou'veseen, if the 336MAX or QEMMDPMIserveris loaded, you can run USEDPMI, USEDPMI2, and MEMLOOP, just as you can from
within GOWIN386 \COMMAND.COM.Indeed, these memory managers do changethe operating systemin a far more dramatic waythan
many programmersrealize. (See the article by Ralf Brown citedin the
“For Further Reading”section at the back of this book.) However, there’s one crucial thing these memory managers don’t pro-
vide: VxDs.It’s not apparent now, butas you'll see during the course of this book, the VxDs shown in Figure 6-1, particularly VMM,constitute a
complete new operating system. Memory managers don’t have VxDs,
though Helix Software’s Cloaking API provides something somewhat analogous. Cloaking is a method for moving BIOS and DOSsystemsoftware into protected mode. For example, Helix provides protected-mode versions of the system BIOS andvideo BIOS, the Microsoft CD-ROM Extensions (MSCDEX), the Logitech mouse driver, a disk/CD-ROM
cache, and a RAMdriver. This cloaked protected-modesoftware can run under Helix’s NetRoom memorymanageror, using Helix’s generic
Cloaking driver, under any 386 memory manager. Another APIfor moving DOSsystemsoftware into protected mode
Novell’s DOS Protected
Mode Services (DPMS), used in Novell DOS for Stacker disk compression, NWCACHE, DELWATCH, and the Personal NetWare server. But whereas APIs such as Cloaking and DPMS are(sofar) being used
only to move selected systemservices into protected mode, with VxDs
Chapter 6: Protected-Mode DOS: WIN386 and MSDPMI
Microsoft is much closer to moving the entire PC/BIOS/DOSsubstrate into protected mode. However,it’s importanttorealize that, even in Windows 95, Microsoft has a long way to go beforeit can truthfully claim thatthe entire core ofstandard PC systemservices has been moved into protected mode.Besides,it’s not entirely clear that having 100% new protected-modecodeis even desirable as an ultimate goal.MS-DOS hasits share of known problems,butat least they are known problems. Andas we'll see in Chapter 9, Windowsis in anycase able to run the old real-mode DOScodein a fairly controlled V86 environment. If I seemto be waffling here — maintaining that VxDsare exciting because theywill eventuallygive usa fully protected-mode PCarchitecture, but that Microsoftis a long wayfromthis goal, andthat it’s not nec-
essarily evena totally desirable goal, and that even shortofthat notnecessarily-desirable goal Windowsis still able to fundamentally alter the
underlying PCarchitecture — well, that’s because thingsarein flux right now. The importantthing nowis torealize the direction in which VxDs are movingthe PC architecture.
MSDPMI Yanking WIN386.EXE out of Windowsandusing it to run COM-
MAND.COMprovidesan excellentpicture ofthe future of DOS and helps explain what Microsoft means whenit says that future versions of DOSwill be derived from protected-mode technology. In fact, this GOWIN386 \COMMAND.COMthing we’ve cobbled together is
nearly identical to something that Microsoftitself did a few years ago, called MSDPMI. Never heard ofMSDPMI? Well, try running Windowsfromwithin
GOWIN386 \COMMAND.COM: UNAUTHWD gow in: command. com UNAUTHHDWin. he nterface (MSDPNI) is running on this when it is running. To quit MSDPMIwasa short-lived Microsoft DPMIserver and DOSextender fromtheearlydays of the Microsoft C/C++ 7.0 (MSC7)betatest.Basically, it was WIN386.EXE,renamed MSDPML.EXEandslightlyaltered to run COMMAND.COMinstead of KRNL386.EXE. Microsoft intendedthis to host MSC7, which required DPMIand a DOS extender. Manybeta
Unauthorized Windows 95
sites protested at the inanityofhaving to load over 500K ofsystemsoftwarejust to run a compiler, so Microsoft junked MSDPMIandinstead bundled a copy of 386MAX from Qualitas with each copy of MSC7. It’s rather odd to see the retail WIN.COM(both in Windows3.1 and
Windows95)referring to this beta software that never shipped. However, the documentation for the MSC7run-timelibrary made frequent reference to “the Microsoft DOSextender,” so perhaps Microsoft really did plan to release MSDPMTIasa product. In a way, Microsoft did releaseMSDPMI: That’s what Windowsis!
Indeed, there mightbelittle reason for Microsoft to put outthis technology under the boring name MS-DOS, whenit can — andalready has — putoutthe samething underthe moreexciting name Windows. Either way, it’s the samesoftware, though perhaps Microsoft can earn more moneybypackaging this technology under the Windows moniker than by describingit as a new version of DOS. How does WIN decide that GOWIN386 \COMMAND.COM is actually MSDPMI? Disassembly ofthe WIN.CMF file used to build
WIN.COMreveals the following code: 4534: 2002 ab The MS-DOS Protected Mode Interface (MSDPMI) is running on this computer. You cannot start Windows when it is running.', 0 4534:341¢ 0 83 75 8D £8
16 1FOF FB 01 20 16 2002 2
mov ax, 1683h or bx,bx t 2Fh dx,cs:[1FDFh) : ‘The MS-DOS Protected Mode. 365
WINcalls INT 2Fh function 1683h (documentedin the Windows DDK), a service provided by VMMthatreturns the current VMID in BX.(Note, by the way, howclose this non-DPMIfunction numberis to function 1687h, which is used by DPMI. VMMdoesn’t distinguish between DPMIand non-DPMIINF2Fhfunctions, which suggests that DPMImightbelittle more than aspecification-after-the-fact codification of whatalreadyexisted in VMM, similar to the way the XMSspecification emerged from the HIMEM.SYSimplementation.) If function 1683h returns nonzero in BX, WIN knows that Windows is already run-
ning and that,if the function returns with BX=1, WINisbeing run from the System VM. WIN decidesthat thismeans MSDPMIis running.
Chapter 6: Protected-Mode DOS: WIN386 and MSDPMI
As shownin Figure 6-3, I’ve incorporated this sametest into ISWIN.C, whichis available on the Unauthorized Windows 95 disk.
define SYSTEM_VM 1 #/ unsigned short vm; /* call 2/1683 to see if DOS app running in System VM; if so, this must be some hacked version of Windows like MSOPMI, or we must be running inside WINSTART.BAT */ asm mov ax, 1683h _asm int 2fh _asm mov vm, bx if (vm == SYSTEM_VM) printf("Running DOS app in System YM: * "Must be WINSTART.BAT or hacked Windows!\n"): else printf("VM #Bu\n", vm);
Figure 6-3: ISWIN.C, a DOS programthattestsfor the presence of Windows, also includestests for MSDPMI.
Running ISWIN under GOWIN386 \COMMAND.COMprints the following message: C: \UNAUTHI in386 \conmand. com C= \UNAUTHWD 4 ‘in
Running Windows 3.10 (or higher) Enhanced mode Running DOS app in System VM: Must be WINSTART.BAT or hacked Windows! Notethe reference to “hacked Windows”: That’s certainly what we have here! Butalso notice that ISWIN,unlike WIN,refers to WINSTART.BAT.After starting the System VMandbeforestarting the Windows kernel, Windows Enhanced mode(specifically, the DOSMGR VxD)looks along the path for WINSTART.BAT. Thisis an optional ordinary DOSbatchfile that you can create to run DOSsoftware in the
System VM. WINSTART.BATis typicallyused to load TSRsthat are
needed by Windowsapplications; rather than loading the TSRglobally
before Windows, which would occupy memoryin every VM, WINSTART-.BATallows the TSR to beloadedsolelyin the System VM.
If you're perverse enough to run WIN from WINSTART.BAT under
GOWIN386 \COMMAND.COM, WIN will think you’ve gotMSDPMI:
C:\UNAUTHW>type winstart.bat echo £0 win iswin
Unauthorized Windows 95
C:\UNAUTHW>gowin386- \command. com C:\UNAUTHW>echo C: \UNAUTHW\ EXPERM\WINSTART Cz \UNAUTHW\WINST Hibwin running on this unning. To quit
Enter. s Enter to quit this MS-DOS prompt and
witch to Windows or ano jer application (or higher) Enhanced mo tem VM: Must be WINSTA
or hacked Windows!
Running WIN from WINSTART.BATproduces this MSDPMI mes-
sage onlyif you’ve run WIN386.EXE
withoutfirst running WIN.If you
start Windowsthe normal way with WIN.COM, the second instance of
WIN(the one launched from WINSTART.BAT)detects thefirst instance bycalling INT 2Fh function 160Ah and issues a moresensible “You are
already running Enhanced mode Windows”message. Butin a way, WINis correct even when it confuses WINSTART.BAT. and MSDPML. After all, if you put COMMAND.COMin WINSTART
and nevertype exit, you've essentially gotMSDPMI, whichin turn is the same thing as renaming COMMAND.
IM to KRNL386.EXE. These
are all just different ways of having WindowsEnhanced mode(the lowlevel WIN386 operating system), but without Windows. In truth, what we havehere is V86 DOS. It just sounds better tocall it Windows.
Using WIN386 as GOWIN386 or MSDPMI,orrunning COMMAND.COM from WINSTART-BATis no more thanan experiment;
this would be no waytodeliver protected-mode DOSto customers. But using WIN386 as MSDPMI does emphasize how separate WIN386 is fromthe rest of Windows. All the functionality you see inMSDPMI — V86 mode, device virtualization, virtual memory, DPMI services, a 16and 32-bit DOS extender, and so on — belongs in DOS. WIN386 really
is part of MS-DOS,except that right nowit ships with Windows, and
Microsoft has decided for sound marketing and packaging reasonstocall it Windows95.
Chapter 7
Waene Do 32BFA ano LF Come From? T WIN386.EXE from Windows Enhanced modeandusingit to run a copy of COMMAND.COM(masquerading under the name KRNL386.EXE) creates a new Enhanced mode of MS-DOS. Butthis maynot be completelyclear from the experimentin the previous chapter.
Afterall, mostofthe special functionality available under GOWIN386is
also available to anyone who uses a 386 memory manager. The point
should perhaps be madeagain that these 386 memory managersrepresent moreofa departure from standard DOS than most programmers seem to realize. Butstill, providing DPMI, protected-mode INT 21h, and even a
DOSINT 21h interface to virtual memory is fairly commonthese days and doesn’t seem to justify characterizing Windows’ DOS box as the
future of DOS. Otherthanprovidingits own (possiblyless capable) version of XMS,this setup doesn’t seem to do much for regular DOS programs. In this chapter, we'll be experimenting with a WIN386configuration that in some waysis
significantly different from the configuration we
tried in the previous chapter but whose departure fromplain-vanilla DOS is much moreapparent. This time we’ll take the 32-bit file access (32BFA) functionality from WEW3.11 anduse it to further enhance DOS. We'll use GOWIN386 -BAT again, but now we'll copy the WIN386.EXE from WfW 3.11 instead of from Windows3.1, change the SYSTEMLINI file slightly to
replace BLOCKDEVwith 108.386, and addseveral additional VxDs: *BLOC
Unauthorized Windows 95
‘These are the new VxDs: * OS.386: /O Supervisor, an enhanced version of Windows3.1’s BLOCKDEY,which in turn was an enhancedversion of the Windows 3.0 Virtual Hard Disk (VHD) VxD. * IFSMGR.386: Installable File System (IFS) Manager. * VFAT386: Virtual FAT File System(oddly, VFAT.386 containsthe description string “Win386 HPFSDriver (Prototype)”; HPFS normallyrefers to the OS/2 High Performance File System). * VCACHE.386: Virtual File Cache (replaces SMARTDRV.EXE). * VXDLDR.386: VxD Loader (for dynamicloading and unloading of run-time VxDs, such as the real-mode mapper, RMM.D32). * VSHARE.386: Virtual SHARE(replaces SHARE.EXE). ‘These VxDs must be copied overfrom the same WW3.11 directory as WIN386.EXE. (These VxDs won't loadunderthe 3.1 version of WIN386.EXE; if you try, you'll get the message “A devicefile specified in the SYSTEM.INI file is corrupted.” You also needto copyoverthe real-mode mapper, RMM.D32, anda copyof SPART:PAR,which containsa pointer to the permanentswapfile. Finally, 32BFA requires a DOS device driver, IFSHLPSYS,whichis included with WEW3.11; your CONFIG.SYSwill need a line such as: dev
=c:\wfw311\ifshlp
Notethatif the IFSMgr(Installable File System Manager) VxD can’t find IFSHLP(device name IFS$HLP$),itsilently disables 32BFA. Why is there noerror message? IFSMGR.386 doescontain code to pass the
message “The MicrosoftInstallable File System Manager (IFSMGR) cannot find the helper driver. Please’ ensure that IFSHLP.SYS has been installed.” to VMM’s Fatal_Error_Handler service. Unfortunat S
MGRhasa bugandgets confusedby
anintervening call to a different
VMMservice; rather than doa fatal exit, IFSMGR ends up with a null
function pointer to IFSHLP. Fortunately, however, the VFAT VxD also tests for IFSHLP.SYS — and this time does it properly, telling WIN386
that it can’t load(though no messageis produced).
Chapter 7: Where Do 32BFA and LFN Come From?
With IFSHLP.SYS installed, with WfW3.11’s WIN386.EXE, VxDs, INI, run GOWIN386 andwith the modified SYS and RMM.D32, \COMMAND. M. The environment this commandproduces looks just like GOWIN386 based on Windows3.1, and for the most part it is
the same. But those extra VxDs we added have a significant impact: Until
youexit from GOWIN386, they effectively replace key parts of real-mode MS-DOSwith 32-bit protected-mode code.
Howcanyoutell? Well, for one thing, your harddisk should seem
significantlyfaster thanit did before. But that proves nothing: maybethis
VCACHE.386 is simply an aggressive disk cache like SMARTDRV.EXE,
or maybe youalready had SMARTDRVloaded.
to understand what this 32-bitfile accessis all about
No,the best way
ss under WIN386translatesintofile I/Ocalls that
is to see howfil
are seen by real-mode MS-DOS. Let’s back up a moment thenand see how Windows and DOSinteract
when 32BFAis turnedoff. Exit from GOWIN386backto the real-mode DOSprompt. (You cantell the difference because WIN386flickers the
screenin a gross way whenit exits.) From the DOSprompt, loada utility r example, I used the INTRSPYutility file 1/Oca that logs INT from Undocumented DOS, along with the INTRSPYscript FOPEN.SCR: compile foper This logsall calls to the following INT 21h functions: ©
OFh (OpenFile with FCB)
©
3Ch (Create File)
* 3Dh (OpenFile) * 4Bh (EXEC) ¢
4Eh(FindFirst File)
*
6Ch (Extended Open/Create) Next, start GOWIN386 with 32BFA disabled. You can dothis either
byrunning theGOWIN386 configuration based on Windows3.1 or by temporarily di ating 32BFAin the WW3.11 configuration. You can
disable
t by putting the statemen
in SYSTEMLINIorby runningWIN /D
ALSE
milarly, you can turnoff
SE or with WIN /D:F) 32-bit disk acce: We'renot using2W.IN. G[OM here, so the /D:C switch needs to be passed
Unauthorized Windows 95
directly to WIN386.EXE.Dothis with GOWIN386byputting the /D:Cswitch after the name of the program to run: C:\UNAUTHW>Gowin386 \command.com /D:C (Yes, I knowthisis stupid, because WIN386.EXE, not COMMAND -COM, usesthe /D:Cswitch. But this is just a toy batchfile and doesn’t merit more work.) Next, from within the GOWIN386 DOS prompt,flush the INTR-
SPYbuffer so you don’t seethefiles that WIN386.EXEopened during startup: C:\UNAUTHW>cmdspy
flush
Finally, do something to generatea lotoffile openactivity, such as:
C:\UNAUTHHDcopy con foo. bar This is foo.bar C:\UNAUTHH>copy con foo.bat type foo.bar foo ig 3 C: \UNAUTHW>:
Letthissilly recursive batch file run for a few seconds, andthenpress Ctrl-C. Next, generate an INTRSPYreport: C:\UNAUTHW>cmdspy report XOPEN con FIND con XOPEN CON XOPEN foo.bar foo.bar con ‘on con foo. bat BAT BAT UNAUTHW\ FOO BAT NAUTHW\ FOO. BAT UTHW\ FOO. BAT bar UNAUTHW\ FC Recall that we loaded INTRSPYbefore starting Windows, so INTRSPYis seeing whatevercalls Windows sends down to DOS. INT21h file
Chapter 7: Where Do 32BFA and LFN Come From?
access in the DOS boxis being serviced byreal-mode DOS. But what
did you expect: that Windows would somehowhandle INT 21h file
access withoutcalling down to DOS? Well, crazyas that might seem,that’s exactly what happens when 32BFAis enabled. Exit from GOWIN386 back to real-mode DOS, then start up GOWIN386 again,butthis time get rid of whatever you did to disable 32BFA. For example, restart GOWIN386 \COMMAND.COM,
but this time without the /D:C switch. Then flush the INTRSPYbuffer,
repeat the FOO.BAR/FOO.BATtest, andgenerate an INTRSPYreport: command .com -bar et the batch file run for a few seconds, like before C:\UNAUTHW>emdspy report con on
on C:\UNAUTHW\CHOSPY.. EXE report Holy Toledo! All INTRSPYcouldsee werethe file opens from the
COPY CON commandsand from CMDSPY REPORT. If INTRSPY didn’t see them, DOS (which of course is loaded before INTRSPY) cer-
tainly didn’t see them. Noneofthat FOO.BAR/FOO.BATactivity went down to DOS! It wasall handledin 32-bit protected-mode VxD-land. That’s right, even thoughthisisn’t significantly different from the version of GOWIN386created with Windows 3.1, we’ve got something veryclose to a 32-bit protected-modeoperating systemhere. It would be nice to have a test for 32BFA that wasless empirical than seeing if INT 21hcalls make it down to real-mode DOS. Testing for the
presence of IFSMGR, VEAT, and VCACHE(perhapsusing their V86
APIs, accessible via INT 2Fh function 1684h) soundslike it would be a
goodidea, but turning off 32BFA does not prevent these VxDs from loading. Thus, althoughthe absenceofthese VxDs wouldtell you that
32BFAis definitely disabled, the presence of these VxDsdoesn’t guarantee that 32BFA isenabled.
Aside fromusing a programlike INTRSPY,howelse can youtell that
the 32BFA VxDsreplace much of MS-DOS? Well, you can use the
TEST21 programfrom Chapter8. Inthe following output from TEST21,
Unauthorized Windows 95
wesee that File Open (function 3Dh), File Close (3Eh), and File Read
(3Fh) werehandled without calling DOS. The minussign(-) atthe endof threeofthelinesindicatesthat fewer calls were received than generated.
This in turn means(as TEST21 notes in its last line of output) that “Some
INT 21h are handled withoutcalling DOS!”Thistest is explained in more detail in Chapter 8. NAUTHWD test21 ed 301 calls 1 called 100 called 100 called 100 called
Received 1 calls 1 receiv 0 received
Some INT 21h are handled without calling 00S!
Byadding a few VxDsto our GOWIN386 setup,then, we get a brand new32-bit protected-mode DOS. And we didn’t need any Windows GUI components: this GOWIN386trick is accomplishedentirely with VxDs. (Well, okay, we also needed the IFSHLP.SYS DOS device driver.)
It’s amazing that Microsoft released 32BFA as a minor upgrade (W£W 3.11) becauseit represents a far moresignificant change than manyofthe features for which Microsoft has seen fit to increment the DOS major
version number(such as DOS=HIGHin DOS5.0 and DoubleSpace in DOS 6.0). Thisis the first unmistakable sign of DOS’s evolution into a
32-bit protected-mode operating system.It’s anotherrare case in which Microsoft has underpromised andoverdelivered.
Onward to Windows 95: UMM32 We've seen a gradual evolution offunctionality from DOSX in Chapter 5 to WIN386in Chapter 6 to WIN386with 32-bit file access earlier in this chapter. Ourfinal stop is VMM32.VXD, whichis the operating systemin Windows95 (just as WIN386.EXEis the operating systemin Windows3.x). Let’s first take a look inside VMM32.VXDusing the W3MAPutility on the Unauthorized Windows 95 disk. The results are shown in Figure 7-1. C:\UNAUTHW>Ww3map \windows\system\ vmm32.vxd W3 09010000
Chapter 7: Where Do 32BFA and LFN ComeFrom?
VSHARE VWIN32 VFBACKUP, vCOMM COMBUFF veo IFSMGR 10S SPOOLER VEAT VACHE von VcoFsD 1NT13 VXOLDR VDEF OYNAPAGE CONF IGG EBIOS vO OOsNeT vPIco vr REBOOT VOMAD vs VB6MMGR PAGESWAP DOSMGR VWPOLL SHELL PARITY BIOSXLAT vMcPD VTDAPI PERF VMOUSE vPo KO VPOWERD.
00064000 00071000 0007ca00 eo0sea00 aooagaaa ooscoee 0091000 re) Geabe000 oaacs000 doodioae ovoasooe oaaddovo 0002000 00005000 000ec000 o0defo00 oooraoa 0104000 eo109000 oo1odoeo 0111000 ao1icoea 00124000 00129000 00132000 00134000 ooianooe o014F000 00163000 0016000 00172000 00174000 00182000 eo18sa00 00182000 oo1sraee 00197000 ao19caa0 do1aso0
Figure 7-1: This W3MAPutility displays information about Virtual Device Drivers inside aW3file. Using this utility to examine VMM32.VXDreveals that VMM32 is an anthology of over 40 VxDs. Some of these VxDs are new to Windows95. For example, VWIN32
providesservices to Win32 applications, and VCONDis the Virtual CONDevice.
W3MAP hasseveral command-line options that can provide more information about individual VxDs built into an executable that uses Microsoft’s W3file format, such as VMM32.VXD or WIN386.EXE.
Figure 7-2 shows one example, taken moreor less at random.
Unauthorized Windows 95
C:\UNAUTHW\N3MAP>W3map -vxd vadldr \windows\system\ vnm32.vxd Nodute name: VXDLDR VADLDR_DDB @ 00000068 Real-mode Init @0000: 00000000 Device # 0027 Dynamic Vx0 Loader Version 3.00 Init order: 16000000 DDB_Control_Proc @ 00000000 DDB_V86_API_Proc @ 00d02ic9 DDB_PM_API_Proc @ 000021c9 DDB_Service_Table @ 0000002c (OF services) 270000 @ 00000010 VXDLDR_Get_Version 270001 @ 00000000 —VXDLDR_LoadDevice 270002 @ 0000001 VXDLOR_Un1oadDevice 270003 @ 000000b7 —VXDLDR_DevInitSucceeded 270004 @ 00001137 VXDLDR_DevInitFaited 270005 @ 00000024 VXDLDR_GetDeviceList 270006 @ 0000219c VXDLDR_UnloadMe 270007 @ 00002220 PELOR_LoadModu 270008 @ 00002860 PELOR_GetModuleHandle 270009 27000a 27000 27000c 27000d 27000e
@ @ @ @ @ @
ooa0zsba 900028e0 00002910 000029F0 00002ad0 20002D90
GetEntryPoint et ProcAddress —PELDR_AddExportTable PELOR_RemoveExportTable —PELOR_FreeModule
Figure 7-2: To get moreinformation ona particular VxD in a W3file, use W3MAP"s -VXD option as shownhere.To get detailed information onall the VxDsin file, use the -VERBOSE option.
‘The VXDLDR_LoadDevice and VXDLDR_UnloadDeviceservices are used as part of Windows 32-bit disk access. In addition, according to
a Microsoft document,“the Plug andPlay architecture is dependent on dynamically loadable VxDs. Whenthe system starts, it determines what devices are present, then uses the VxD loader to load VxDsfor those devices.” From the W3MAP output, we can see thatVXDLDRalso provides a set of PELDR services that allow VxDs to dynamicallylink to Win32 Portable Executable (PE)files Justas with the earlier environments, we can take VMM32.VXD and
runit without the Windows GUI. Infact, this is precisely the setup I
used for monthsduringtheearly part of the Chicagotest period. The pre-beta version of Chicago from late 1993 wouldn’t run on my machine,
butit did appearto getprettyfar alonginits initialization. This perhaps meantthat the lower VMM/VxD layer of Windowsmightbe able to run, even thoughthe upper graphical layer didn’t. Being ableto test the
Chapter 7: Where Do 32BFA and LFN Come From?
VMMand VxD components of Chicago seemedbetter than nothing, so I renamed KRNL386.EXE to KRNL386.SAVand then copied COMMAND.COMto KRNL386.EXE. With COMMAND.COMpassing itself off as KRNL386.EXE, I could type WIN, and DOS386 (as the
VMM/VxDportion of Chicago wasthen called) would run COMMAND.COM. This gave me a V86 version of DOS 7 that worked
lexactly as you would expect from our earlier GOWIN386 experiments. But Windows 95 looks so seamless, so integrated! Howcould the
VMM/VxDportion of Windows95 be ripped out and used to run something other than the GUIportion of Windows95? To the casual user of Windows 95, Windowsappears to boot as soon
as you turn on the machine.Insteadofthe “Starting MS-DOS...” mes-
sage that MS-DOS5 and 6 display when booting, the samepoint in the
Windows 95 bootsequence displays a “Starting Windows...” message.
This small changehasa subtle but importanteffect. It makes the average user feel as if Windows has replaced MS-DOSandthatthere is no longer anythingsitting between Windowsandthe machineitself.
Yes, when you turn on a Windows95 machine,it says “Starting Win-
dows...,” but as we saw in Chapter1, it’s still moreor less the same old
real-mode DOScodethat’s runningatthis point. This portion of Windows95is really just MS-DOS 90: MS-DOSin drag, as it were. Chicago’s seeminglyseamless loading of Windows is pretty seamy,really. Whether autoloaded by WINBOOT.SYS or by COMMAND.COM, orstarted in the old-fashioned way by typing WINat the C:\> prompt, WIN.COMwill spawn VMM32.VXD, just as WIN.COMin Windows 3.x would spawn DOSX or WIN386. There’s no magic here. None, that
is, except the magic of repackaging. By taking something that has always been considered part of MS-DOS — thereal-modecode located in IO.SYS and MSDOS.SYS — andrepositioning it under the moreexcit-
ing, less generic,less technoid brand name Windows(and Windows95,
at that), Microsoft has cleverlycapitalized on what hasfor years been an n DOS and Windows. Whereexactly did uncleardivision of labor bet DOSendand Windowsbegin? Microsoft is now takingall its PC system software and calling it Windows. NewPackage! Same Great Taste!
Although Windows95 at least superficially appears seamless, and although Microsoft now appearsto regard real-mode DOSaspart of Windows(asbest illustrated, again, by the “Starting Windows...” message that Windows 95 displays whenyou're starting what would up until nowhave been called MS-DOS), the fact remains that Windows95
Unauthorized Windows 95
consists of several separate, semi-independentpiecesthatfit together in
roughly the same way that the pieces of Windowshave always fit together. This meansthat, even in Windows95, it’s possible to take the
VMM/VxDlayer from Windows 95 anduse it to create a small, selfcontained V86 modeversion of DOS. If it’s okay for Microsoft to declare
piecesof real-mode MS-DOSaspart of Windows,thensurelyit makes as muchsense forus to say certain pieces of Windowsare really a part of DOS. Recall from the preceding chapter this statementfroma former
employee of Microsoft: “Win386 isn’t really even part of Windows.” The same is true of VMM32.VXD. So let’s use VMM32.VXD tocreate a ver-
sion of DOSthat supports32-bit file access andlong filenames.
On myhardware, the Chicago setup createda directory tree containing over 1,000 files. In this Land of a Thousand Files, I wanted to find the minimal set of Chicagofiles for anon-GUI DOS386/VMM32 setup.
At the time of DOS386, it turned out that I neededonly about 50 files to
get something working. With VMMB2, even fewerfiles are needed. Althougha full-blown Windows 95 setup is a lot moreuseful thanthe minimalsetup I’m describinghere, going throughtheexercise oflocating the minimum numberoffiles neededto provide 32-bitfile access, long filenames, or some other Windows95 featureis quite instructive because
you geta real sense of whatconstitutes the core of Windows 95. Here’s what it takes to create a small, self-contained VMM32 setup:
¢ VMM32 requires DOS 7.0 or higher. Running VMM32 on DOS 5 or
6 generates the message “Cannotrun Windowswiththeinstalled version of MS-DOS. Upgrade MS-DOS toa versionthat is at least 7.0.”
‘Tryingto fake this with SETVER VMM32.VXD7.0doesn’t appear to work. © Just as with WEW3.11, you must have DEVICE=IFSHLP.SYS in CONFIG.SYS. But when running Windows95 (even the scaled-
down VMM32.VXDhack we're putting togetherhere), make sure you use the version of IFSHLPSYSthat comes with Windows 95. ‘The WEW3.11 version doesn’t know about the new INT21h Long Filename (LFN) functions. * Theregistryfile SYSTEM.DATshouldbein the root directory. If VMMB2 can’t find SYSTEM.DAT, it still runs, but it displays the warning “Registry File was not found.Registryservices maybe inoperative forthis session.”
Chapter 7: Where Do 32BFA and LFN Come From?
* You need VMM32.VXD,ofcourse. The Windows95 setup program builds this file by packing together all the VxDs(includingone called VMM32.VXD)neededfor your particular configuration into a single file (also called VMM32.VXD). This omnibusfile is generally about 1700K,considerablylarger than WIN386.EXE,and contains among otherthings a VMMthat provides many moreservices than the VMM in WIN386. (See Chapter2.) * You need a programtoplaythe part of KRNL386.EXE,such as COMMAND.COM. You'll encounter a few other requirements as you work through the rest of this chapter, but this is enoughto get youstarted.
T created a VMM3?2 subdirectory and copiedtwofiles into it:
32>copy \conmand.com krn]386.exe vMM32> vmm32
vnm32. exe
Withjust these twofiles, typing the command VMM32 worked, at
least in the sense that I got a DOS promptfrom which I could run DPMIprograms. There were noloose VxDs(setup boundall the ones required for this configuration into VMM32.VXD). There wasn’t even a SYSTEMLINIfile.
Oops, mygenuine Chicagodirectorywasstill on the path, and so VMM32 pickedup its SYSTEM.INIfromthere. This pulled in who
knowswhat. It turned out that VMM32 really did want a SYSTEM.INI
file after all.
However,there is a way to make this minimalsetup work: Run
VMM3? in fail-safe mode. This is a useful feature thatlets you boot Win-
enif your configurationfiles are hopelessly screwedup. You can triggerfail-safe mode by pressing F5 when your machineboots; you dows 95
can also enable fail-safe mode by running WIN /D:M. WIN.COM.
passes the /D:Mswitch to VMMB32, soyou can just ran VMMB2 /D:M. This works! With just VMM32.VXD(renamed to VMM32.EXEso I couldstart it from the DOS commandline) and COMMAND.COM
masquerading as KRNL386.EXE,I could runthelowerlayer of Win-
dows 95. No GUI, no .INI files, no nuthin’ except VMM32 and COMMAND.COM. Inthis hacked Windows95 environment, I could run the
usual DPMItest programs:
Unauthorized Windows 95
C:\VMN32>vmm32_/D:4 Cz \VMN32> CS=21AAh 0S=237Bh CS=0097h DS=008Fh CS base=00021AA0 limit-0000FFFF 0S base=00023780 limi t-O000FFFF C:\VMN32>dpmi info DPMI version 0.90 32-bit programs supported 386-based DPMI host Interrupts reflected to V86 mode Supports virtual menory 4014080 kbytes available in largest block
Again,this isn’t a particularly useful configuration comparedto fullblown Windows95, but you can learn a lot about Windows 95 byexperi-
mentingwith this and other scaled-downversions. For example,I was quite surprised to discover that when I wasfinished running these VMM32 experimentsI could exit back to real-mode DOS. Thecapability to exit from Windowsback to DOS seemslike an obvious
anduninteresting feature. However, whenyoustart Windows 95 in the
normal way, typing WINrather than VMM32, exiting Windows doesn’t return you to the DOSpromptfrom whenceyou came.Instead, your choicesare to restart Windows,shut off the machine, or press Ctrl-AltDel. Starting VMM32 letsusexit back to the real-mode DOS component
of Windows95, so it must be WIN.COMthat normallypreventsthis.
Given that some Windows 95 VxDsmightrelyon the supposed
impossibility of ever exiting back to DOS — perhaps some VxD patches DOSand,starting in Windows 95, doesn’t bother to put back the origi-
nal patched code when Windowsexits — you might think thatthis exitprevention would have beena bit moretightly integrated into Windows.
Ontheother hand, perhapsthepresence ofSingle Application Modein
Windows95 meansthatall VxDs mustbe readyto properly restore clobbered data anyway. Butif that’s the case, there’s no goodtechnical reason for WIN.COMin Windows 95 toprevent you fromexiting back to
DOS. It’s just Microsoft trying to make Windows95 appearto be “at one” with the PC.
To makeit a bit easierto test this minimal VMM32 environment,I cobbled together another batchfile, RUNVMM32, showninListing 7-1.
Listing 7-1: RUNVMM32.BAT @echooff runymn bat
Tande\bin
Chapter 7: Where Do 32BFA and LEN Come From?
joto usage exe goto have_vmm32 system\vmm32.vxd vmm32.exe >nul 6.exe >nu 4 35
echo Back in DOS goto done cant_get echo Ca goto done
‘ind \WINDOWS\SYSTEM\VNN32. VxD
usage echo usage: RUNYMM32 [program] [args to VNM32] done echo For example, to create the minimal VMM32 environment I’ve been
describing,just type: VNM32>runvmm32 \command.com /D:M
This grinds awayon your hard disk for a few seconds, and then you’re presented with a C:\> prompt, from which you can runa varietyof programsthat would not otherwise be supported under DOS. Wealready sawthat DPMITEST and DPMIINFOdo the rightthing in this envi-
ronment. Anothergoodtest is the MEMLOOPprogram:
C:\VN32>mem] oop Allocated 8178 Kb in 257 blocks Hmm,this doesn’t look very goodatall! Recall from Chapter6 that MEMLOOP, running under WIN386.EXE from WW3.11, couldallocate 37MB onthis same machine. Whyonly 8MBwith the presumably more advanced VMM32 from Windows 95?
Actually, this looks like a feature (anda sensible one,at that) offailsafe mode, in which VMM32 will use a pagingfile (386SPART.PAR) located onthefirst hard disk, butit won’t grow the pagingfile beyondits current size. So let’s stop using fail-safe mode. We'll need a SYSTEM.INI file to
dothis. Figure 7-3 shows the SYSTEMLINIfile I threw together. (386Enh]
le-H ngFiles:
SPAR PAR
BitDiskAccess=on
Unauthorized Windows 95
maxbps=512 mouse=*vmouse ebios=*ebjos display=*vdd keyboard=*vkd fd.vxd unauthw\generic\vxd.386 intl3 vpicd
device=*pageswap device=*dosmgr device=*vmpol device=*parity device=*biosxlat devices*ved device=*vmepd devices*combuff device=*enable
veond vedtsd device-"vxdldr device=*vdef device=*dynapage device=*vtd device=*shel vice=*vtdapi vice-*perf device-*vpd device=*vpowerd Figure 7-3: A SYSTEM.IN|file customizedfor testing a minimal VMM32environment.
In addition to the VxDs embedded in VMM32.VXD,I’m alsoloading two loose VxDshere: VFD.VXD,because VBACKUPsaidit wanted it, and VXD.386, which is my generic VxDthatwill comein handy when experimenting with VMM32. Note that the SYSTEM.INI alsoexplicitly pointsto the pagingfile.
Chapter 7: Where Do 32BFA and LFN Come From?
With this SYSTEMLINIfile, the amount of memory allocated by MEMLOOPis determinedbythe available disk space on the drive with the pagingfile. Unfortunately, I no longerhad as muchspaceavailable as when I ran the test with WEW3.11, but youcanstill see that MEMLOOP, on my 12MB machine,is definitelyusing virtual memory from the pagingfile: C:
\WMM32>mem] 0%
Allocated 16866 Kb in 528 blocks
As shownin Figure7-4, running the VXDLISTprogramfrom the Unauthorized Windows 95 disk revealed that 43 VxDs comprised this minimal configuration. Incidentally, under VMM32, VXDLISTuses a
new VMMservice (VMM_GetDDBList)to find the root of the VxD chain; it also could have used the VX_DLDR_GetDeviceListservice
whose name appeared in the W3 MAP -VXD VXDLDR output shown
backin Figure 7-2.
VAOLIST version 1.20 Displays Windows Enhanced mode Virtual Device Driver (VxD) Chain Copyright (c) 1994 Andrew Schulman. All rights reserved. Using WM function #1013F Name vu VCACHE VPOWERD VPICD vTD VXOLOR CONFIGMG VCOFSD 10s PAGEFILE PAGESWAP
Vers
4.00 3.01 4.00 3.10 4.00 3.00 4.00 3.00 3.10 4.00 2.10 1,00 2.00 1,00 2.00 2.00 3.10 veo 4 VNOUSE 2 vKO 0.1 ENABLE 34 PD 3.1 INTI3. 2 vFD 1 vMcPD BIOSKLAT 1 4. DOSMER
10
DDB
Control
001h @48Bh @026h @003h 005h 0027h 0033h @041h @010h @02ih 0007h 0008 009h 9012h 00h a00Bh O00Eh
Conde! co@32FEC CO035CAC COOLA9F8 C0033FE4 c00336C0 0036038 0033534 co0z98FO C00: COO1E958 CODIEFOC COO1B3AC 0011850 co016658 Coo1D4F4 COO1F360 coui1scs con1a3s0 COOIFDES c00357C0 covisr9c cooisesc coolr OOLEFAC COOLEB6®
cawe23ne CoO3zA8D coo35984 Co019480 C00330C6 C0033658 coo35D48 c0033428 CaaZ7E74 co0338e8 COO1EBS4 COOIEEAC Coo1Bz7C coo11828 CO011BA0 —cao1032¢ COO1FO14 §conlizrs ce017208 COBIFACF COO34FAD Coola cogie6n4 ev1FaZ8 COOLEFG4 CODLEB4
V86 APL
PM API cooozai1 ca@32e09 265860 coa1Aoe4 co26zii4
CO257EAA
0256710 ca262068
#Srvc 139 9 15 al 5 10
0014944 cozzF2e4 C023E298
—COZ3C5AB
0 8 0 16
Unauthorized Windows 95
VSHARE VMPOLL DSvVXD xD COMBUFF VWIN32 VCOMM VCOND VTDAPT VOMAD VEEMMGR SPOOLER VEAT VDE IFSMGR VFBACKUP SHELL
1.00 4.08 3.00 2.00 1,00 02 =-1.00 1,00 Q@ «2.00 1.00 1.00 0@ 3 00 3.00 4.00 4 0@
0483h 0018h 003Bh 28Coh o2An 002Bh 0038h 0442h 0004nh 0006h 002Ch 0486h 0040h 0036h ad17h
0020244 Cooz011F coo200F4 C001 —COO10F IC Co0100A3 c0011280 COOLOFAS coo1F9A8 coozz670 —C00216C8 ca@23180 CoazzEDa ~C003315C Coas3118 Ci 8 CAO34EAC CO034E83 Coa1De8c~—co01B5CC COB1E6CC COOIDA cogzacr8 cooz9c10 ~—c003285C 30C0C co033898 0033964 Cod25EB0 0023380 CO22E60 C0022814 §—cae34a70 §—C003476E
cooz00F4
1 4 a —COBLOFAG* 0 a 21! 65 35 1 27 CO2sB5E2 2 | 52 coz6s330 0 28 5 18 0 coozze48 CO2624E5
103 5 26
Figure 7-4: VXDLISTdisplays the VxDscurrently in memory. Here, VXDLIST displaysthe 43 VxDsthat make up a minimal VMM32 environment.
If you look back at the VXDLIST output in the preceding chapter (Figure 6-1), you'll see that, in contrast to Figure 7-4, Windows 3.1 (which doesn’t provide 32-bit file access) used onlyabouthalf as many VxDs as Chicago. We sawat the beginning ofthis chapter that WFW 3.11 32-bit file access requires about five additional VxDs. Although these are roughfigures — a lot depends on your individual configuration, including whether you're on a network and which graphics accelerator card you use — it seemsclear that Windows 95 relies far more heavily on VxDsthanearlier versions of Windowsdid. In the VXDLISToutputin Figure 7-4, those numbers on theright (following the exclamation marks) indicate the numberof specialservices a given VxD provides for Win32 applications; many advanced Win32 APIfunctionsavailable in Windows 95, but not in Win32s, are implementedusing these VxD Win32 services. For example, the CreateThread API provided by KERNEL32 is based on the VMMCreateThread function; KERNEL32 calls this VMMfunction via one of the Win32 services provided by VWIN32. The undocumented VXDCall0 function in KERNEL32, which is usedlater in this book, lets Win32 applicationscall these VxD-provided Win32 services.
Well, we see that Windows 95 has tonsof VxDs, andit makes sense that these would help implement manyofthe new features of Windows 95, but sofar we haven'treally seen any Windows 95 behavior that differs from WEW3.11 with 32BFA. In the next section we'll look at an aspect of Windows95 that’s a real departurefrom previous versions of Window longfilenames.
Chapter 7: Where Do 32BFA and LFN ComeFrom?
Long Filename Support in Windows 95 Sinceits inception, MS-DOShas been plagued bythe so-called 8.3 filename convention.Instead ofsensible filenames such as “3rd quarter 1994 reportfrom Cleveland” or “Piano Concerto No. 20 in D minor,”
users have to create and remember names such as CLEV3Q94.WKS and PI20DMIN.SCR. In Windows 95, youcan have longfilenames and directory names (up to 255 characters), with a maximum path length of 260 characters. The following is output from the DIR commandin Windows 95;
SRDQUART PLANOCt 2
36,517 09 8:43p 3rd qua 26 09-13-94 8:4dp Piano C:
1994 report from Cleveland No. 20 in 0 minor
Every long filenamein Windows 95 has a unique short alias automatically generated by the operating system.Inthe DIR output, 3RDQUART is the alias for “3rd quarter 1994 reportfrom Cleveland”. Windows95 is case-preserving (though case-insensitive), so essentiallyall files and directories created under Windows 95 have two forms. For example, copy foo.bar foobarsk.doc
would create both a standard FOOBARSK.DOCdirectoryentry and, even though FOOBARSK.DOC fits within the standard 8.3 filename confines, a second, case-preserving foobarsk.doc entry.
Ofcourse, Microsoft had to implementthese longfilenames in a way that didn’t break existing applications. Also, media written under Windows 95 muststill be usable underolder versions of DOS and Windows. Let’s say a DOSprogramcalls INT 21h function 47h to get the cur-
rentdirectory. According to Microsoft's DOS 6.0 Programmer’ Reference, a
programcalling this function needsa buffer ofat least 64 bytes, whichis large enough to contain thelargest possible path. The program nowfinds
itself running under Windows95, where a single directory name, not to
mentiontheentire path, can be larger than 64 bytes. What happens? The program gets the short form, of course. Otherwise, Windows 95 would break every DOS programthat had obeyed therules and allocatedas fewas 64 bytes in which to receive the currentdirectory string. This meansthat developers don’t have to worry aboutlong filenames breaking old programs.
However, many programswill need to work with thefull filenames.
Getting the longfilenameinstead ofthe shortalias requires a newset of
Unauthorized Windows 95
functions. Windowsprograms will use Win32 API functions such as Get-
CurrentDirectory and CreateFile. A DOSprogramwill be able to use a
newset of subfunctions under INT 21h function 71h, where the subfunction in AL is the same as the old DOS AH function number. Forexample,
because the old DOS Get Current Directoryfunction is INT 21hfunction
47h, the new one that knows about long pathnamesis INT 21h function
7147h; althoughthe otherregisters are identical to the oldcall, the buffers
e the maximumpointed to by DS:SI must be large enoughtore: allowedpath. As you'll see in the LFN.Cexamplelaterinthis chapter, programscancall the new Get VolumeInformationfunction (INT 21h function 71A0h)toget the length of the maximum-allowed path. Long filenames aren’t supported in the real-mode WINBOOT.SYS portion of Windows 95, which runs before VMM32.VXD. This means
that real-mode programssuch as TSRs and device drivers can’t call the new longfilename APIsif they runatsystemstartup. Similarly, the few
programsrunin so-called Single Application Modealso won't beable to
call the longfilename APIs. To determineif the new APIsareavailable, a programcan use INT 21h function 71A0h. If these new DOS INT21hfunctions aren’t available in real-mode
DOS7, whoprovides them? A VxD,of course: IFSMgr. Sincelongfile-
names aren’t provided in the real-modeportion of DOS 7, andsince they don’t require any Win16 or Win32 code, we can look at themfromour cobbled-together VMM32 environment.
But there’s a slight problem. ‘Tryingtocreate a long filenamein the
tiny VMMB2 environment doesn’t yield the expectedresults: C:\VMM32>copy data.1 "3rd quarter 1994 report from Clevela copied 1 file(s) ano Concerto No. 20 in D minor*
€
3RD QUAR PIANO
2,481 09-13-94 9:@1p 526 09-13-94 9:01p
Not onlythat, but it also just doesn’t feel as though32-bit file access
is enabled: the disk is tooslow. If LFN supportis clearly absent, it makes sense that 32-bit file
access would be absent as well, since both are pro-
vided by IFSMgr.Yet, in the VXDLIST outputshownearlier, IFSMgr is clearly loaded, as are the other main components of 32-bit file and
disk access:
Chapter 7: Where Do 32BFA and LFN Come From?
Name
Vers
10
008
TFSHGR VCACHE VFAT VSHARE 108 INT13
3,00 3.01 3.00 00 3.18 3,10
0040h —Ca025EB0 048Bh 0486h 0483h a010h ceoz9BFo 0020h_~—COO1FIC
PN API coesze09
cooz00F4 0256710
What gives? We mustbe missing one or more files — probably VxDs — that VMM32 needs to enable 32BFA and LEN support.To see what VMM32 apparentlywants in orderto enable 32BFA and LFN,we can take David Maxey’s INTRSPYutility from Undocumented DOS,load theutility before starting the RUNVMI 32 batchfile, and have INTR-
SPYlog all File Open, FindFirst, and EXECcalls. Afterstarting and exiting VMM32, INTRSPYproduced the report (which I’ve trimmed a little) shownin Figure 7-5. EXEC OPEN OPEN XOPEN OPEN OPEN OPEN
C:\VMN32\VMN32. EXE QEMM386$ [FATL 2] 386MANSS [FAIL 2] C:\WINDOWS\EMM386. EXE SMARTAAR [FAIL 2] C:\SYSTEM. DAT C:\VMN. EXE
OPEN
$DebugDD [FAIL 2]
OPEN
[FAIL 2]
OPEN NDISHLPS [FAIL 2] OPEN C:\VMM32\SYSTEM. INI FIND [FAIL 3] OPEN H:\DBLSPACE.BIN OPEN 2\vfd.vxd OPEN
OPEN OPEN OPEN OPEN OPEN OPEN FIND OPEN OPEN PEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN OPEN
SCSIMGRS [FAIL 2] C:\VMM32\10S.INT [FAIL 2] C:\VMM32\10S.INI [FAIL 2 C:\VMM32\10S.INI [FAIL 2] MM32\ LOSUBSYS\*. vad C:\VMN32\TOSUBSYS\ rm C:\VMN32\WINSTART. BAT \dos\WINSTART.BAT [FAI \bin\WINSTART.BAT [FAIL 2] C:\VMM32\UNICODE.BIN [FAIL 2] IFSSHLPS C:\VMN32\VFD.VXD C:\VMM32\KRNL3B6.€ C:\VMN32\USER..DA C:\VMM32\USER. DAT C:\VMM32\KERNEL32.DLL [FAIL 2] C:\VMM32\KERNEL32.0LL [FAIL 2]
Unauthorized Windows 95
\dos \KERNE bin\KERNE RN RNL 386. EXE COM SYSTEM. DAT STEM.dir
QUART PIANOCON 201
36,517 09-13-94 8:43p 09-13-94 :44p 126,455
report from Cleveland 194 3rd qua ano Concerto No. 20 in D minor
Youcan also have long directory names.Figure 7-6 shows some examples; I’ve deleted uninteresting portions of the DIR output.
C:\WHN32>md “this is a long directory name” C:\VHNB2>di r Tosussys THISIS=1
06-13-94 OSUBSYS 6-13-94 10:49p this is a long directory name
\VMM32>0d “this is a lo VNM32\THIS IS A LONG 0: atone
ctory name" Y NA
ong filename with a.big exten-
C:\VMM32\THIS IS A LONG DIRECTORY NAMEDdir A LONG DIRECTORY NAME
Direc ALONGFIL BIG
C:\VMNB2\THIS. 1 ALONGFIL BIG
30 06
0:50p “a
long filename with a.big extension”
DIRECTORY NAMEDdir *. "big 30 06-13-94
10:50p “a long filename with a.big extension"
Figure7-6: Directorylistings will lookverydifferent once users start creating long filenamesand directory names.
Notice that file extensions are nolongerlimited to three characters:
A file extensionconsists of anything following the final dot in a filename. Notice toothat you cando wildcard searches on these large extensions (DIR *.“big extension”).
All this is an important step upfrom WIN386, even from WIN386
with 32BFA. 32BFA in WfW3.11 provided a 32-bit protected-mode implementation of the INT 21h file I/O API but didn’t change the API
itself, at least notin such avisible way. On the other hand, you could argue that, in bypassing the DOS INT 21h chainas we sawin the TEST21 example, WfW 3.11 did change the DOS API. In anycase,
Windows 95 is obviously
providing a new DOS API, yet this API isn’t
available in real-mode DOS7. To underline the point onelast time: you
Chapter 7: Where Do 32BFA and LFN Come From?
get this new DOS APIonlyif VDsare loaded. That is an excellentillustra-
tion of the point that VxDsrepresentthe future of DOS(albeit repack-
aged under the name Windows).
As an example of howto test for the presenceof thisnew DOS API, LEN.C, shownin Listing 7-2, is a real-mode DOS programthat calls INT21hfunction 71A0h (Get Volume Information)anddisplays some
information aboutthe file system. Listing 7-2: LFN.C LEN
test presi
#include Hinclude < #include #include
Ox71A0 x4302
FS_VOLUME_C
0x4000 0x8000
int GetVolume Info mation(char far *RootName char far *Buf r, unsigned BufSize, ame, unsigned *pMaxPath) unsi d *pFl 1 unsigned unsigned rbx, rex, rdx; asm | push ds push i les di, dword ptr Buffer ds dx, dword ptr RootName BufSize £T_VOLUME_INF( MATION jc no_71A0 mov rbx, bx mov rex mov rdx, dx
) *pFlags rbx *pMaxFilename = rex: *pMaxPath rdx return 0; no_71A0 _asm xor ah, ah
Unauthorized Windows 95
error cot
in AL
main(int argc, char *argvC]) i char *RootName = (argc < 2) 2 “C:\\" char Buffer{128]; char *nai unsigned Flags, MaxFilename, MaxPath int ret
argv{1]:
if ((ret GetVolumeInformation(RootName, Buffer, sizeof(Buffer), AFlags, QMaxFilename, &MaxP: a
}
printf("ts No long filename (LEN) support\n™, RootName) printf ("error code: %d (2@2Xh)\n", ret, ret): return 1 ©
printf ("$s Long filename (LFN) support\n", RootName): printf ("File syste “Es\"\n", Buffer): printf(*MaxFilename: &d\n", MaxFilenane) ; printf(*MaxPath: d\n th); define PRINT_FLAG(T printf(
52)
AGCFS arches are case sensitive” arches are NOT ca ; PRINT_FLAG(FS_CASE_IS_PRESERVED, "Preserves case in directory entries” "Does NOT preserve case in directory entries"): PRINT_FLAG(FS_LFN_APIS, "Supports DOS long filena tions”, Does NOT support DOS long filename ful tions PRINT_FLAG(FS_VOLUME_COMPRESSED, "Volume is compressed” "Volume is NOT compressed"): RINT_FLAG(FS_UNICODE_ON_DISK, "Uses Unicode characters in file and directory name: "Does NOT us for file/directoryna urn 0;
Figure 7-7 is the output from LEN, underreal-mode DOS7 andthen in our minimal VMMB? setup. The “Uses Unicode” message is correct: Windows 95 store file anddirectorynamesusing two-byte characters. LFN) suj
Chapter 7: Where Do 32BFA and LFN Come From?
C:\VMM32>runvmm32\command..com
Cs \WNMB21 Fn C:\ Long filename (LFN) support File system name: "FAT MaxFilename: 255 MaxPath: 260 Searches are NOT case sensitive Preserves case in directory entries Supports 00S long filename functions Volume is compr: Uses Unicode charac rs in file and d rectory names exe “Long Filename Test Program.exe”
C:\VN32>"Long Filename Test Progran* m Long filename (LFN) support File system name: "FAT" MaxFilename: 255 MaxPath: 2 Searches are NOT case sensitive Preserves case in directory entries Supports 00S Tong filenane f netions Volume is ressed Uses Unicode haracters in file and directory names Figure 7-7: LFNreports that the maximumfilenamelength is 255 characters, and that the maximum total path length is 260 characters,
Probably the most interestingthingin Figure 7-7 is its use ofa long filenamefor an executable. It seemed appropriate that LFN.EXE should
have a long filename, so I gaveit the name “Long Filename Test Pro-
gram.exe”. This could be successfully launched from the VMM32 DOS prompt. However, there was one small problem(this is beta software,
after all). Notice in Figure 7-7 that, when the program was executed
usingits long filename, the programreceived a command-line argument consistingofthefinal characterof the long executable name. Longfilenamesarea great addition to DOS, Windows, or whatever youwanttocall it. They are provided not by some amorphous mass
called Windows95, but specifically by the IFSMgr VxD in Windows. A version of IFSMgr without LFN supportalsoexisted in WFW3.11. It
seemsclear that, froma purely technical standpoint, WfW3.11 could
have provided LFN support too. In one way LFN supportis an enormouschange,butin other ways it’s just a logical use of the VxD capabilities that have resided in Windowsforyears.
Unauthorized Windows 95
The DolSpace Vx Saga Tnoted a few moments agothat on machines running DblSpace or some other disk-compression software such as Stacker, 32BFA requires RMM to make the 16-bit real-mode compression software appear as thoughit were a 32-bit protected-mode disk driver. Anothersolution, however, is to put disk compression into a genuine
32-bit protected-mode driver. The Chicagopre-beta release fromlate 1993, distributed at Microsoft’s Professional Developer’s Conference in Anaheim, came with VxDs for both DblSpace (DBLSPACE.386) andfor the Microsoft Real-Time Compression Interface (MRCI32.386), which is the compression/decom-
pression engine used by DblSpace andbyother Microsoft utilities, such as BACKUP. Neither DBLSPACE.386 nor MRCI32.386 appearedin the next majorrelease of Chicago(the May 1994 beta), undoubtedly because in February 1994, a juryin federaldistrict court in Los Angeles turnedin
its verdict in the Stac v. Microsoft case, finding that Microsoft’s DbISpace infringed two disk-compression patents owned by Stac (US Patent No.
5,016,009, Doug Whitinget al., “Data Compression Apparatus and
Method,” May14, 1991; US Patent No. 4,701,745, John Waterworth
(Ferranti ple), “Data Compression System,” October 20, 1987). Thejury awarded Stac $120 million in damages. Microsoft wona second partof the case, with $13.6 million damages,
in which Microsoft argued that Stac’s reverse engineering anduse ofthe undocumentedpreload interface in MS-DOS6 constituteda tradesecrets violation (see “LA Law,” Dr. Dobb’s Journal, May 1994). OnJune 8, 1994, Federal District Judge Edward Rafeedie issued a permanent injunction that ordered Microsoft (and Vertisoft, whose DoubleDisk Microsoft licensed to create DbISpace)to “recall, erase or
have destroyed,” worldwide, all copies of MS-DOS6.0, MS-DOS6.2, Microsoft's Flash File System, Microsoft’s Windows NT Remote Access Server, Vertisoft’s DoubleDisk Gold, and “Any Microsoft product that
contains the DoubleSpace compression technology containedin the commercial version of MS-DOS 6.” Althoughnotissued until June, an oral
ruling had beenissuedseveral weeksearlier. So by the time Microsoft was readyto ship the May 1994 Chicagobeta,it was clear that the judge was likelyto issue an injunction against Microsoft’disk compression. A few weeks after the injunction, there was an interesting twist. On
June 21, Microsoft and Stac reached an out-of-courtsettlement, agreeing
Chapter 7: Where Do 32BFA and LFN Come From?
to dropall damages, payments, and appeals. Microsoft agreed to pay
Stac $1 millionper monthfor 43 monthsand to buy $39.9 million in Stac
stock (representing about a 15%stake in the company). The two companiessignedapatentcross-licensing agreement, so Microsoft is now free to use DbISpace, which the jury had foundincorporated technology covered by Stac’s patents. Stac, conversely, is nowfree to use the undocumentedpreloadinterface. Although Microsoft haslicensed Stac’s patents, notits products, there’s always the possibility that future Microsoft operating systems might borrowsomething fromStac’s superior diskcompression technology. As a sneak previewfor 32-bit protected-modedisk-compression software, I thoughtit would be useful to take the DBLSPACE.386 and MRCI32.386 VxDs from the December pre-beta release and drop them into the VMM32 setup:
pispace.386 iosu dchic\mrci32.386
PACE. 386 “EM.INI andrestarting VMM32, the VXDLIST program shows that, indeed, the VxDsare loaded: dsrve PM API V86 API Control 0B Vers 10 Name oazh
a Now, what effect doesthis have? Unfortunately, these VxDsdon’t appearto be drop-in replacementsforthe real-mode DblSpace and MRCI code. Performance is not greatly improved when these VxDs are loaded, and the real-modecode doesn’t appear tobe bypassed. For instance, by running the INTCHAINutility (included on the Unauthorized Windows 95 disk), we cansee that both the DbISpace and MRCIGet Versionfunctions are handled by the real-mode code: VM32>intchain 2f/dall/o NT 2F AX=4A11 ructions OF27 1892:0EF2 12EA:01C8 12690154 FRFF:F94F
WINICE DOSKEY HMA
Unauthorized Windows 95
DBLSYSHS XMSXXXXO IFSSHLPS
ing INT 2F A 74 instructions 1077: 0F27 1892: 06F2 12EA:01¢8 20154 FFF: POOF 0385:0017
Amongthe data returned by theMRCIGet Versionfunctionis a callable far function pointer to the MRCIserver. MRCI clientscall this
entrypoint with requests to compress and decompress blocksofinmemory data. (DbISpace takes care of moving data to and fromthedisk,
and MRCIdoesthe actual compression/decompressionof the data.) Normallythe server entrypointwill have some address such as
0385:001E. However, when MRCT32 is loaded, it changes this to an
3
odd-looking address
such as FBA1:2632. Furthermore, disassembling
this address reveals that it starts off with an illegal instruction,ARPL, which causes a GPfault ifissued from V86 mode. This ARPL instruc-
tion represents a 86 callback. When a DOSprogramexecutes the illegal instruction, this causes a trap into VMM, which can thensee where the fault came from(in this case FBA1:2632) anduse that address to locate a
piece of VxD code intendedto handle this fault. VxDs such as MRCI32 allocate these odd V86 callbacks byusing (naturally enough) the Allocate_V86_Call_Back routine supplied by VMM. Here,MRCI32 is obviously intercepting all calls to the MRCI server.
Forits part, the DBLSPACE VxDappearstointeract closely with VCACHE,presumablywith the intentionof caching compressed rather than uncompressed file data. This would nearly double the effective size
ofthe cache. What all this means is that we're definitely going to be seeing diskcompression VxDs in Windows 95, even thoughthe May 1994 beta
couldn’t provide anysuch support because of the then-impendinginjunc-
tion against DbISpaceandeven thoughthedrivers in the December1993 pre-beta appearedto have fairly limited goals.
Chapter 7: Where Do 32BFA and LFN Come From?
Four Steps Toward DOS nirvana Probably the mostsignificant feature we’ve seen hereis the support for
longfilenamesanddirectory names in Windows 95. This new DOS
interface, provided by a VxD and implemented in 32-bit protected mode, showsthe nextstep in the evolution of DOS. This new DOS interfaceis
available only when running under VxDs;real-mode DOSdoesn’t include code to support longfilenames. Howdid wereachthis point where new DOSinterfacesare being madeavailable onlyvia 32-bit protected mode? Quite gradually. In the past few chapters, we've seen slow but steady movement,all under the guise of Windows, towards a protected-mode DOS: * DOSX (like any DPMI server or DOSextender) showed that
protected-modeservices can beretrofitted onto DOS.
* WIN386provided all the basic functionality for a V86 DOS,including VMMand VxDservices with which more interesting functionality can be produ * 32BFA took advantage of VMMandVxDservices to reimplementfile access, whichis the most importantpart of DOSin 32-bit protected mode. (We didn’t getinto this much, but in Windows 3.1, 32-bit disk access did the same thing fora key part of the ROMBIOS.) * VMMB32 adds new VMMandVxDservices, andcreates an entirely new DOSinterface thatisn’t available under real-mode DOS. It seemslikely that all future additions to the foundations of DOS and Windowswill be made with VxDs;it’s hard to imagine anysubstantial additionsto the real-mode DOS codebase. Does this mean that “DOSis dead,”as so manytrade publications have announced? Notquite. While the real-mode DOScodeis unlikely to see much,ifany, improvement, the DOS INT21h interface seemsalive and kicking. We'll seein later chaptersthat even the newest Win32 application, underthe covers, makes massive use of the INT21h interface. In other words, DOS isn’t dead, nordoesit need to die. As our experiments with WIN386 and VMM32 have shown, DOS has basically turned
into a 32-bit protected-mode operating system, organized around a VMM and consisting of VxDs. In the next few chapters we'll see that these VxDs
continueto call down to the real-mode DOScode quite frequently. However, we'll see also that VxDs are on top andthat the real-mode DOS code
is playinga subservient role.
aa Oh pgm 406F aa Lier) Fol
ease cot =
robin afietn nal
aeaT
eee
Cyt he
epptaa atte wiregarrh yt deve) Saree bi eal oe ied
AOE aarp
-
sipmeméfeb >
_chain_intr(old
void interrupt far ctr]_c(REG_PARAMS r (*setv)(0x21, old_21); fail("Ctrl-C detected!");
void interrupt far crit_err(REG_PARAMS r) failed++; r.ax= 3;
// fail the operation
The code for TEST21 is fairly straightforward. The main function calls the _dos_setvectC libraryfunction (or, if -MYSETVECTis speci-
fied on the commandline, the my_setvect functiondiscussedlaterin this chapter)to install a handler for INT 21h. This handler,at the very bottom of TEST21.C, hasthe highly original nameof int21. Each time int21 is called, it uses the incoming DOS function number in AH to
index into an arrayof counters. After incrementing the appropriate
counter, int21 uses the _chain_intr functionto pass the interruptto the previouslyinstalled handler, whose address wasretrieved earlier when TEST21 called _dos_getvect or my_getvect.
Afterinstalling the int21 handler (and hooking Ctrl-CandCritical
Error to unhook INT 21h if the programterminates unexpectedly),
TEST21 then runsa loop issuing some DOS calls. Notice the #ifdef
TESTFILE.Later, we’ll defineTESTFILE onthe compiler command
line so we can use TEST21 as a generic test rig. Bydefault, however,
file, opensthefile again, writes a byte, writes . (a period) to stdout (which can be redirected to a disk file with a command such as TEST21 >
FOO.BAR), and closesthefile. For each DOScall,TEST21 increments a counter. Tf you don’t specify a differentfilename on the commandline,the file that TEST21 reads each time through the loop happensto bethe programitself, that is, TEST21.EXE. (TEST21 learns its own filename from
Chapter 8: The Case ofthe Gradually Disappearing DOS
the Cexpression argv[0].) At least for an initial test, we don’t care what
TEST21 readsor evenif it succeeds — wejust want to generate some INT 21h calls and see them showup atTEST21’s own INT 21h handler.
After the DOS-call loop is complete, TEST21 unhooks its int21 handler by restoring the previous handler and then displays the test results. Foreach possible INT 21h function number0 through FFh,TEST21 sees how manycalls to that function were issued and how manycalls its INT 21h handler received. Obviously, these two numbers should match. When TEST21 is running under plain-vanilla DOS, the numbers do
match. Given how the programis structured,this is hardly surprising. Figure 8-1 shows the ratherboringresults. : \UNAUTHWD test: a elap: enerated 701 call 1 called 40
200 called
eceived 701 calls receiv 200 200 100 200
INT 21h appears to be handled in the normal way Figure 8-1: When TEST21runs undera plain-vanilla DOSconfiguration, DOSreceivesall the INT 21hcalls madebythe program.
Aside from the “INT 21happearsto be handled in the normal way” message,indicating that — of course — DOS INT 21h handlers handle
INT21hcalls, the only marginally interestingitem in Figure 8-1 is the
“21 seconds elapsed” output. ‘The timewill differ from one configurationto the next. If you
redirect TEST21’s outputto afile, the time goes upquite a bit (in the
configuration| used here, to 29 seconds), because DOS must write each
periodtoa file on disk ratherthan to the screen. Tf you run TEST21 undera disk cache such as
icrosoft’s SmartDrv,
the elapsed time dropsradically (not surprising given that TEST21 does unbufferedreads and writes ofonlyone byteata time). In this same con-
figuration, running
21 under SmartDrvcut the timeto about 4
seconds, (or 5 seconds whenredirecting TEST21’s outputto adisk file).
Thetest in Figure 8-1 was run on a compressed DoubleSpace drive. If
runinstead on a non-DoubleSpace drive without a disk cache, the elapsed
timeagain drops dramatically, as shownin Table 8-1.
Unauthorized Windows 95
Table 8-1:Elapsedtime(in seconds) for TEST21. DbiSpace drive
TEST21 No cache Cache TEST21 > FOO.BAR No cache Cache
Host (non-DbISpace) drive
24 4
ze
29 e
10 dl
Nowlet’s take TEST 21 andrun it in a DOSbox under WfW3.11, with 32-bit file access (32BFA) enabled. To enable 32BFA, Microsoft
makes youtunnelthrougha seriesofseveral dialog boxes: run Control Panel, select the 386 Enhancedicon, select Virtual Memory(yes, Virtual Memory, eventhoughit’s unclear what this has to do with 32-bit file access, as opposedto disk access), select Change, and then check the Use 32-Bit File Access box. You must restart Windows for 32BFAto
take effect. Figure 8-2 shows the results from running TEST21 under 32BFA.
These results are quite surprising, especiallysince we only checked one box buried in an obscure Control Panel dialog box. @ seconds elapse Generated 701 calls 21/25 1 call 3D 200 called 21/3E 200 called 21/3F 100 called 21/40 200 called
100 received
Some INT 21h are handled without calling
DOS!
Figure 8-2: When TEST21runs under WfW 3.11 with 32BFA enabled, mostofthe INT 21h calls generated by the program bypass DOS. First, note that TEST21 tookless than onesecondto run. I didn’t have SmartDrv(or anyother disk cache) loadedhere. If I had, the results would
have been the same anywa ; because
dynamicallysizedfile cache (the
32BFAsuppliesits ownbuilt-in,
VCACHE VxD). On a DbISpacedrive,
21 runs faster with 32BFA but without SmartDrv than it does with
tDrv but without 32BFA.(Yes, I knowthat’s a mouthful. See the “32 BFA versusdisk cache performance”sidebar laterin this chapter.)
Chapter 8: The Case ofthe Gradually Disappearing DOS Second,notice the “Some INT 21hare handled withoutcalling
DOS!” message.Even if you assumedthat 32BFA meansthat Windows somehow “bypasses” DOS(whatever that means), these results arestill pretty amazing: TEST21’s INT 21h handler doesn’t see mostof the program’s own INT 21h file I/O calls! Oneimportantnote: If you've ran TEST21 from a floppy disk, your results will looklike Figure 8-1 rather than Figure 8-2. This indicates that WfW3.11 doesnot provide 32BFAforfloppies. We'll see later that this has been corrected in Windows 95. The minussign (-) indicates that TEST21 sawfewercalls thanit expected froma given DOSfunction. TEST21 puts upa plussign (+)if it sees more INT21h calls than it expected, which,believeit or not, can also happen. ‘TEST21 did see its owncall to INT 21h function 25h (Set Interrupt Vector), which unhooked the INT 21h handler. But while TEST21 issued 200 calls to INT 21h function 3Dh (File Open), its INT 21h handler sawzero calls to that function. Ditto for function 3Eh (File Close)
and function 3Fh (File Read).
TEST21 issued 200 calls to function 40h (File Write), butit saw only
100 calls to that function.If you redirect TEST21’s outputto a file (for example, TEST21 > FOO.BAR), TEST21 nolonger seesanycalls to
function 40h either. Empirically, 32BFA must send function 40h writes to the screen down the INT 21h chain, butit mustintercept and block
writesto diskfiles. But given thatthe int21 function in Listing 8-1 is the most recently installed INT 21h handler, this interception of INT 21h calls seems impossible. In Listing 8-1 there is practically nothing coming between the call to _dos_setvect (or my_setvect) and the call to dos_open. How
could someonehaveslipped another INT 21hhandler in there ahead of ‘TEST21?! Furthermore, if TEST21 isn’t going to see this INT 21h call, howis DOS (whichis installed muchearlier in the INT 21h chain) ever
goingto seeit? The answerto the second question is that DOSisn’t going to see these INT21h calls. Using the V86TESTprogramfrom Chapter10, I’ve confirmed that the INT 21hcalls issued by TEST21, when running under WEW3.11 with 32BFA,really andtrulyare not sent downtoanysoftware thatis loaded before Windows,including DOSitself. While TEST21 was running, V86TESTsaw the following INT 21h calls:
@B: 2433,
19: 2
1A: 1
25: 10 29: 4
Unauthorized Windows 95
2
2:3 49:1
30 48
48:1
38: 1 4C: 1
3E: 18 40: 121 44: 2 4D; 1 5D; 2
Withoutgetting into the other INT21h calls se n by V86TEST, we can see that this matches pretty well with what TEST21 itself shows: No calls to function 3Fh were detected, but over 100calls to function 40h were. If TEST21’s outputis redirectedto afile, the V86TESTlog of function 40hcalls also drops, just as you’d expect: 02: 18 08: 13. 0B: 2915 19:3 JA: 11 25: 10 29: 4 2h 2 bes 35:5 38: 1 36: 15 4 44 48:2 49:1 48 4B: 10 4€: 1 4D: 1 8D 7533 So 32BFA somehowdoes keep most file I/O DOS calls away from
DOSand, in WEW,away from eventhe mostrecently installed INT 21h hooker in a DOSbox. Well, this is pretty much what Microsoft says 32BFAdoes, so it shouldn’t come as muchof a surprise. But consider the mechanisminvolved: TEST21 has hooked INT 21h
just before issuing these INT21h calls. Yet Windows
has somehowgrabbed
INT 21h away from TEST21. You mightthink that perhaps Windowsis playing the sametrick for which SideKick was notoriousin the bad old days of DOS TSRs: SideKick would hook thetimerinterrupt and ensure uponeach timertick thatits other interrupt handlers werestill in place. However, TEST21 checks forthis possibility by verifying each time through its DOS-call loop that my_getvect(0x21) = int21. The only
timeI’ve seen TEST21 displayits “Someone grabbed my INT21h!”
message was while running within an EMACSprocessbufferin the Epsilontext editor. Clearly, 32BFA does not hook INT21h in anysimple-minded way. Indeed, Microsoft’s excellent WFW3.11 Resource Kit (pp. 1-20) notes that 32BFA works “byintercepting theMS-DOS Int 21H services in protected mode.” TEST21 shows that this is true: 32BFA is somehow
intercepting (as opposed to merely hooking) INT 21h.
I keep saying “somehow.” You might be wondering, How does Win-
dowsintercept INT 21h? I’mgoingto explainthis in moredetail in the “Interrupts 101: The IDT versus the [VT”sectionat the endofthis chapter, but the basic idea is that Windows uses the protected-mode Interrupt Descriptor Table (IDT)tointercept interrupts coming from real-mode programs running in V86 mode. As the IDTMAPprogram on the Unauthorized Windows 95 disk helps show,these interrupts goto the Windows VMMandto other VxDs.
This is true not only of INT21hbutofai/ interrupts coming from
V86 mode. Nor is this just a feature of 32BFA. Windows in 386
Chapter 8: The Case ofthe Gradually Disappearing DOS
Enhanced modehasalwaysinterceptedall interrupts coming from V86 mode, because that is how V86 mode works. All V86 environments
behave the same way: When a DOSuseris running a 386 memory manager such as EMM386, QEMM, 386MAX, or NetRoom,interrupts are
handledfirst in protected mode, before DOS or any DOS TSRsor device drivers ever see them.
Yet, if you run TEST21 with a 386 memory managerbutwithout
32BFA, TEST21 claims that “INT21h appearsto be handled in the nor-
mal way.” If 386 memory managers behave essentially the same as 32BFA, whydoesn’tTEST21 reveal this?
Theansweris simple: When a 386 memory manager (or Windows
Enhanced mode without 32BFA) intercepts an INT from V86 mode, it
sends(orreflects) this call back down to V86 mode. What makes 32BFA differentis thatit often doesn’t botherto do this: It handles many INT 21h callsentirely in protected mode,withoutreflecting the call down to V86 mode. Thecalls that TEST21 does see when running under Windows are simply those that VMMorother VxDshave chosento reflect. In the case of 32BFA, the key VxD is the Installable File System Manager, IFSMgr. Later in this chapter, we’ll examine some ofthe IFSMgr code
that produces the behavior we're seeing with TEST21.
The importantpointis that in 386 Enhanced mode, V86interrupts under Windowshave always passed through the IDT. In Enhanced mode, the DOSGetInterrupt Vector function (_dos_getvect, INT21h function
35h) has never correctly determinedwhowill first see aninterrupt; VMM
and other VxDshavealwaysseenthe interruptfirst. Figure 8-3 shows that
they have complete discretion over how to handle the interrupt. They mightvery well decide notto pass the interrupt down to real-mode programs. Back in Figure 8-2, for example, they did pass down the _dos_
setvect (function 25h)call and the _dos_write (function 40h) calls involving stdout, but they didn’t pass downany I/O calls involvingdiskfiles.
Puttingit in the strongest terms, what Figure 8-2 showsis that Win-
dowsis the operating system and DOSis a subservient subsystemthat Windows can use to handle whatevercalls it doesn’tfeellike bothering with. Andalthough the TEST21 results are admittedly unusual,this behavioris implicit both in Intel’s documentation for V86 mode and in Microsoft’s documentation for VxDs. In particular, see the Windows Device Driver Kit (DDK) documentation for the Hook_V86_Int_Chain service.
Like Mr. Jourdain in Moliere’s play Le Bourgeois gentilbomme, who one
day is delighted to discover that he’s been speakingproseall his life, it has taken 32BFAto makeusrealize that we’ve hada 32-bit protected-mode
Unauthorized Windows 95
operating system, called the Windows VMM,sitting rightin front of us all along. 32BFA makesit impossible to continue ignoringthis “new”old operating system.
Real-Mode driver(s)load before IFSHLP
file/Disk VxDs (VFAT,1O§ ete)
‘CalWhen_VM_ Returns
-—>
default
Figure 8-3: Depending on the function, a software interrupt can take several paths. If 32BFA handlesthecall in protected mode,it followsthe path from the program calling INT 21h to the protected mode IDT, VMM,ISFMegr, and back to the program.If the call is reflected to DOS, however, the path continuesthrough the VxD chain to the real-mode IVT, then downthe DOSinterrupt chain. The real-modeIFSHLP driver can sendthe calll back to IFSMgr. Onceinside MS-DOS,if there's anotherinterrupt, the path repeats recursively. All the same,it can be surprising to discover howfewpeople have checked the appropriate box in the Control Panel to enable
32BFA. And
as we'll see later, 32BFA can cause such problems. But even with these problems, when youconsider the PC industry's complaints about MSDOSand howmuchit’s supposedlyholding back Windows, it is odd that most powerusers anddevelopers tend to ignore whatis essentially a 32-
bit protected-modeversion of DOS.
Chapter 8: The Caseofthe Gradually Disappearing DOS
O2BFA versus disk Cache performance t's not clear why more users and developers didn't jump up and down about 32BFA in WiW 3.11. Certainly 32BFA has some problems. The biggest oneis that if Windows crashes, you lose all the data in 32BFA's file cache. But that’s the samerisk taken by anyoneusing a write-behind disk cache. (In fact, 32BFA can be safer than SmartDry, because there's no write-behind cachein WIW 3.11.) Anotherpossible explanation is that the performancebenefits of 32BFA are somewhat confusing. A Byte (February 1994) review of WW 3.11 by Jon Udell noted the following performancecharacteristics of 32BFA: The results can be impressive. An Advanced Logic Research Flyer 32LCT 4DX2/66with an IDE controller more than doubled its sequentialfile 1/0 throughputusing the VFAT/VCACHEcombo,while bettering its random file |/0 throughput by about a third. But, on an Everex Step 486DX2/50with an Adaptec AHA-1742 controller and an IBM PS/2 Model 90 XP 486with an IBM SCSI-2 controller, the story was quite different. Here, randomfile I/O throughput improved by 73 percent and 83 percent, respectively. These marks were closeto (for the Everex) or better than (for the PS/2) those posted by Windows NTon the same two machines. But in both cases, 32-bit file access hurt sequentialfile |/0 performance. The PS/2 losta fifth ofits 16-bit throughput; the Everex lost a fourth. This degradation made application load times noticeably slower on the two SCSI machines.
How does 32BFAdifferfrom a disk cache?I've received reports saying thingslike “Surprisingly, with a reasonably sized SmartDrv cache (which is otherwise disabled by default by WFW), 16-bit mode is faster for most operations.” In my admittedly limited testing with SmartDrv 5.0 on about half a dozen machines, TEST21 doesn’t confirm these reports. For example, in a DOS box under WW 3.11, on both a compressed DbISpace drive and its non-DblSpacehost drive, | ran TEST21 3000 > FOO.BAR on a 486SL with an IDE hard-disk controller and collected the following results: Configuration 32BFA, no SmartDrv ‘SmartDrv, no 32BFA No 32BFA, no SmartDv * Elapsed time in seconds
Host drive* 5 15 281
DblSpace 8 Are 800
In addition to SmartDry, | also tried Helix Software’s protected-mode CacheCik. Although it was certainly faster than SmartDry, it too did not even approach the 32BFA times. In this test, 32BFA is a clear winner over a disk cache, not to mention over raw DOS, on both DbISpace drives and
non-DbISpacedrives.
Unauthorized Windows 95
Of course, TEST21 is somewhat contrived.| also tried a morerealistic example usinggrep to search for a non-presentstring (“foobish”) in 3210K of data from Ralf Brown’s interrupt list (\UNDOCDOS\INTRLIST\INTERRUP.*). | performed the search twice so that a cache would optimize the second searchif the data were already in memory. In the results listed here, 1 and 2 indicate the first and second searches. | performed the
searches both on a compressed DblSpacedrive and on its non-DblSpace hostdrive. Configuration
(A) Real-mode DOS,no cache Search 4 Search 2 (B) 32BFA,no disk cache Search 1 Search 2 (C) CACHECLK 3400 Search 1 Search 2 (D) CACHECLK 3287 Search 1 Search 2 (E) CACHECLK 1800 Search 4 Search 2 (F) CACHECLK 1750 Search 4 Search 2
drive*
DbISpace
15.4 15.4
16.9 16.8
12.6 10.4
17.5 10.4
16.0 10.4
16.7 13.0
16.1 16.0
16.9 13.0
16.4 16.1
16.8 13.0
16.1 16.0
16.8 16.8
* Elapsed time in seconds.
Theseresults give a better picture of one 32BFA benefit: It dynamically resizes its file cache, based on available memory and the user's needs. In
test B, 32BFA was able to optimize search 2 on both the DbiSpace and non-DbISpace drives without any end-user fine-tuning of the cachesize. Notice also that, whereas search 1 took a good deallonger on the DblSpacedrive, in search 2 32BFAlargely erased the usual performance hit from DbiSpace: The data came out of the 32BFA file cache, so DbISpace basically dropped out of the picture. At the same time, also note that
32BFA made search 4 takeslightly longer on the DblSpacedrive. In test C, | used Helix Software’s CACHECLK with CACHESIZE=3400.
Since DIR reported 3210K ofdata, it isn’t surprising that the disk cache could optimize search 2 on both the DbISpace and non-DblSpacedrives.
Note that CACHECLKturnedin the sametime as 32BFA for search 2 on the non-DblSpace drive. On the other hand, 32BFA appearstosolidly outperform disk caches (even a goodone like CACHECLK) on DbISpacedrives.
Chapter 8: The Case ofthe Gradually Disappearing DOS
Next, in test D, since DIR reported 3,287,421 bytes of data, | naively set CACHESIZE=3287. As you can see,for the non-DblSpacedrivethis cachesize was too small: search 2 took aslong as search 1. This points to a majorbenefit of 32BFA over disk caches: Whereas a disk cache will be worthlessif its size is evenslightly smaller thanthe user's file 1/0 “working set,” 32BFA adaptsitself to the user's file I/O patterns. But why, with an apparently insufficient cache size for the non-DbISpace drive in test D, was CACHECLKstill able to shave 3.7 secondsoff search 2 onthe DbISpacedrive? Because CACHECLK was caching the compressed data, which fit into the same 3287K cachein which the noncompressed data wouldn’t go. Test C showed that CACHESIZE=3400 wassufficient for the noncompressed data, and DIR /CH reported a 2.0:1.0 compressionratio. Nonetheless, when tried CACHESIZE=1700,it was too small to have anyeffect on search 2. Tests E and F reflect a binary search that | did to find the proper cachesize for the compressed data; it turned out that CACHESIZE=1750 was too small and that CACHESIZE=1800 wassufficient. By playing around with cache sizes in this way, you can seethatthe true compression ratio must be about 1.8:1.0 (3400/1800). Anyway,the pointis that 32BFA seemstoeliminate the need to manually fine-tune cache sizes. Besides, 32BFA provides nonperformance benefits. For example, longfilename (LFN) support in Windows 95is really a by-product of IFSMgr’s capability to bypass the old DOSfile system code. At the sametime, 32BFA’s performance resembles the performance of a fancy cache. The cache aspect of 32BFA is managedby a VxD called VCACHE. Although VCACHE(like all the other 32BFA components,including IFSMgr and VFAT) is undocumentedin WfW 3.11, both IFSMgr and VCACHE are supposed to be documentedin Microsoft's Device Driver Kit (DDK) for Windows 95. This might provide someinteresting opportunities for thirdparty developers to improve on VCACHE, in the same waythat they improved on SmartDrv.
Getting and Setting the Current Drive {As an alternative to the open/tead/close/open/write/close sequence of INT 21hcalls we've beenusing, TEST21’s DOS-call loop can instead include a file designatedon the compiler’ commandline with -DTESTFILE=“filename”(see Listing 8-1). This allows TEST21 to be used asa rig for other INT 21htests. As just one example, which we'll examine in considerable detail, the little test in Listing 8-2 is a standard piece of DOS codetoget the LASTDRIVEs
setting. It does this by calling INT 21h function 19h
Unauthorized Windows 95
to get the currentdrive and bypassingthis valueto function 0Eh (Set CurrentDrive), which also happensto return the value ofLASTDRIVE
(see Undocumented DOS, 2d ed., pp. 68-69). Listing 8-2: TEST_1
1* TESTA for TEST21.C 21/19 (Get Current Drive) and 21/0E (Set Current Drive) */
_asm mov ah, ‘asm int 21h _asm mov dl, asm mov ah, _asm int 21h 7* LASTDRIVE
19h al OEh now in AL *
calledtox19}++; called{Oxde}++: total_called += 2: If you recompile TEST21 with -DTESTFILE=“test_1” and run the new TEST21 under 32BFA,you don’t get the “Some INT 21h are han-
dled withoutcalling DOS!” message. Windowsdoesn’t bypass DOSfor these Get/Set current-drive calls. Yet the results are distinctly odd, as you
can see in Figure 8-4. Generated 201 calls 21/0E 10 called 21/19 100 called 21/25 1 called
Received 301 calls 100 received 200 received + 1 received
Some extra INT 21h calls are occurring! Figure 8-4: In this example from WfW 3.11 with 32BFA, DOShasreceived morecalls than TEST21 generated.
Someone, somehow,is generating extra calls to function 19h, But who? How? Why? This provides us with a good excuse to sneak a peak at the codein the Installable File System Manager VxD, IFSMgr. We'll see that even when Windowsdoes let DOSdoits thing, it keeps DOS on a short leash. Duringits device initialization, IFSMgruses VMMservices toinstall handlersforall INT 21h calls that occur in either V86 or protected mode (PM).Figure 8-5 shows a fragmentofthe IFSMgrinitialization code. Install V86 INT 21h handler OCFAO mov eax, 21h Oca’ mov esi,offset V86_INT21_PROC
Chapter 8: The Case ofthe Gradually Disappearing DOS OCA
VNMcal1 Hook_v86_Int_Chain
t: Get previous PM INT 21h handler ocrBe mov eax.21h ocrBS VMMca11 Get_PM_Int_Vector ocrBB mov dword ptr PREV_INT21_PM_VECT_SEG,ecx ocrci mov dword ptr PREV_INT21_PM_VECT_OFS,edx ty Install ocrc7 ecrce ocro2 ocrDS ocro7 OCFDA ocror
new PM INT 21h handler mov esi,offset PM_INT21_PROC VMMcal1 AllocatePM_Call_Back movzx edx,ax mov ecx,eax shr ecx, 10h mov eax, 21h VWMcall Set_PM_Int_Vector
Figure 8-5:IFSMgrcodeforinstalling V86 and protected mode INT 21h handlers.
The V86_INT21_PROCand PM_INT21_PROCroutinesin IFS‘Mgr arenearly identical. Simplifying slightly, the IFSMgr V86 and PM INT21h handlers take the DOSfunction numberfrom the caller’s AH register (which is available to VxDs inside a Client Register Structure pointed to bythe EBPregister) and, as shown in Figure 8-6, useit to index into a table of IFSMgrhandlers that provide preliminary handling ofthe INT 21h functions. 01947 01950
movzx ecx,byte ptr febp.Client_AH] cmp cl,60h ts in Windows 95, 72h functions jae short elsewhere call dword ptr INT21_TABLecx*4] ;:; table @ IFSMgr+1700h nc short elsewhere? retn elsewhere
Figure 8-6:This fragment showsthestart of the IFSMgrINT 21h handler.
Thetable called INT21_TABin Figure 8-6 is quite importantfor understanding how IFSMgrhandles INT 21h. In one WW3.11 configuration, this table happenedtobeat linear address 800A5600h (which is
IFS-Mgr+1700h); I used the PROTTAB program from the Unauthorized Windows 95 disk to dumpthistable,filtering outall the default entries.
Theresulting output, sorted by address, gives a goodinitial picture ofthe INT21h calls that IFSMgrtakes someinterestin. In Figure 8-7, I’ve rearranged the outputslightly to point out IFSMgr functions that handle
multiple DOSfunctions. (For example, the function at IFSMgr+1AFFh
Unauthorized Windows 95
handles INT21h functions 1Ch, 32h, 36h, and 47h, all of which expect a drive numberin the DL register.) C:\UNAUTHW>prottad 80035600 64 4 int21 80da589¢ TFSMgr=800a3F00 | ; Table at 8005600" Filter al] out entries B00A5B9Ch SMar=B00A3F00 BOQA58AO —int21_0040 ; IFSMgr+19A0 8 int2i_0048 ; 1FSMar+1900 8 int21_005F IFSMgr+19E4 8 int21_00 MartlAds int21_00 NgrtLA58 int21_oa Mgr+1A76 int21_0044 jgr+1A04 int21_001F ; IFSMgr+1AFB int2looic r+LAFF 1c 32 36 47 int21_ooaF SMgr+1B25 int21_o04s rt B7E 45° 46 int21_003e Mgr+188C 36-40 42 57 5C 68 int21_0011 ; IFSMgr+18D1 11-1317 BO0ASBSC int 21_006C ; IFSMar+1C5C BQ0A5B63 int 210039; IFSMgr+1C63 43 5B 800A5004 —int21_005D ; 1FSMar+1E04 BOQASEGO int 21_0000 ; IFSMar+1F60 8O0A5E80 int 21_000B ; IFSMar+iF8@ Figure 8-7:This IFSMgr INT 21h handlertable from WfW 3.11 is a goodindication of the INT 21hcalls IFSMgris interested in.
Figure 8-7 hardlypresents a complete picture of IFSMgr’s INT 21h
handling, butit’s a goodfirst approximationof the DOS calls that WEW 3.11 can handle in 32-bit protected mode. Now, we were wondering why TEST_1 makes100calls each to INT
21h functions 0Eh and19h andyet receives 100additional calls to func-
tion 19h. Frominspecting Figure 8-7, it seems that IFSMgrdoesn’t do
anythingspecial with function 19h;it has a default handler that PROTTAB has filtered out. However, there is a handler for function 0Eh, located at IFSMgr+1A76h. Figure 8-8 shows what we find whenwe dis-
assemblethe codeat that address.
O1A76 O1ArC
near iy Set Current Drive test dword ptr Cebx.CB_VM Status], YMSTAT_PH_EXEC jnz short {21 jone 32 121_0E_CALL_WHEN_RE 1_When Return: i: carry set
pass to next handler
Chapter 8: The Case ofthe Gradually Disappearing DOS B1ABC retn i21000E endp
Figure 8-8:A disassemblyof IFSMgr’s INT 21h function OEh (Set CurrentDrive) handler.
In the codein Figure 8-8, IFSMgr is checking whether the function OEhcall camefrom protected mode (for example, from a Windowsapplication). Ifit did (the VMSTAT_PM_EXECbitis setin the current virtual machine's statusflags), IFSMgr doesn’t do anythingspecial: it sets thecarryflag, indicating thatthecall should be passedto the next protected-mode INT 21h handler.If the function 0Ehcall came from V86 mode, IFSMgralso passesthecall along to the next handler — and, eventually, all the way down to DOS — butfirst it calls a VMMservice, Call_When_VM_Returns,passingit the address of another function in IFSMgr. Call_When_VM_Returns,asits nameimplies,installs a handler that MMcalls whenthe currentvirtual machine (VM)returnsfrom an interrupt handler. This service, documentedin the DDK,forces an IRET to return notto theinstructionafter the INT but to VMM. Even though TEST21 seemsto indicate that function 0Eh “appears to be handledin the normal way” (TEST21 sees allits owncalls to function 0Eh), the
IFSMgrcode showsthat something oddis nonetheless happening. IFS-
Mgrwill intercept function 0Ehafter passingit down to DOSand to DOSprogramssuch as TEST21. This is known as a post-reflectionhook.
This brings up an important point. Although TEST21’s “Some INT 21h are handled withoutcalling DOS” messageisreliable, the example of function 0Eh showsthat the “INT 21h appearsto be handledin normal way” message means little more than that: To TEST21, INT 21h
handling appears normal. DOSis still possibly being subjected to
strange VxD practices like post-reflection hooks. That IFSMgr uses a post-reflection hook to handle function OEh — that IFSMgrevencan interceptin such a way — is a goodindication that the Windows-DOS relationshipis notat all the simple, straightforward “Windows runs on top of DOS”situation that manyusers and developers seemto expect. Sowhat does IFSMgrdo when it receives control after DOS has returned from handling INT 21h function 0Eh? Youcansee what it does
by examiningFigure 8-9, which showsthecallback functionthat IFSMgr installed with Call_When_VM_Returns.
proc T21_0E CALL_WHEN-RET Push_Client_State 0180
near
Unauthorized Windows 95
01AB4 O1ABA
+ Ge
mov eax WwicaT mov 41.) mov ec, mov by’ VWMc
Drive
issue INT 21h AH=19h : AL = current drive per-VM data } save new current drive endp
Figure 8-9: IFSMgr’s Call_When_VM_Retumshandler for INT 21h function OEh. Wewere wondering why TEST_I receivesextra calls to INT 21h
function 19h. Well, Figure 8-9 shows exactly why. After a V86 mode
application calls function 0Ehtoset the currentdrive, and after DOS handlesthecall, IFSMgrgets control,issues a function 19h to get the currentdrive, andstores this value in a data structureit keeps on a perVMbasis in the VM Control Block (VMCB; VxDsuse the VMM_
Allocate_Device_CB_Area service to allocate memoryin the VMCB). To issue the INT 21h function 19h, IFSMgruses the standard set of MMservices showninFigure 8-9: Begin_Nest_V86_Exec, Exec_Int,
andso on. ThephrasesI’ve beenusingin this chapter such as “Windows calls down to DOS” and “Windowsreflects the interrupt to V86 mode”
arereally just nebulous-sounding descriptionsfor this sequenceofcalls
involving Begin_Nest_V86_Exec and Exec_Int.
Infact, when running under Windows Enhanced mode with or without 32BFA, any andall INT 21h calls seen by TEST21’s INT 21h han-
dler — infact, any andallinterrupts seen by anyreal-mode program’s interrupt handler — got there only because VMMor some VxDcalled Begin_Nest_V86_Exec and Exec_Int. Notice that this meansthere is no
necessarycorrelation between the INT21h callsissued under Windows andthose seen by DOS.
Incidentally, IFSMgrshould have beenableto usea singleservice, Exec_VxD_Int, insteadofthe longer sequenceofcalls just shown. Unfortunately, though, Exec_VxD_Int is nearly unusable due to a bug in anotherservice, Begin_Nest_Exec. (Geoff Chappellhas discovered the simple coding error underlying this persistent bug and has posted a corTFIX.A in the CompuServe WINSDK forum.) rection called N Okay, so we see that whenever a V86 modeprogramcalls INT 21h function 0Eh, IFSMegrfollows it with a Begin_Nest_V86_Exec and
Exec_Int of INT21h function 19h. We canalso see that IFSMgrtakes
Chapter 8: The Case ofthe Gradually Disappearing DOS thevalue returned from function 19h andstores it in its DEVICE_CB_ AREA+0Ah. But why? If IFSMgr wantsto store the current drive on a per-VM basis (which is sensible enough), whycan’tit just take the intended new
current-directory value the userpasses in DLto function 0Eh?Instead of the i21_000E function shown,withits roundabout scheduling of another functionto becalled later on,it seemsasif IFSMgrcould have simply performed the following:
wrong_i21_000E proc near mov di,byte ptr Cebp.Clien mov ecx.dword ptr DEVICE CB_ mmov byte ptr Lebx+BAh]Cecx],d1 ste
retn wrong_i21_000E endp
: DL = new current drive
er-WM data ave new current drive : carry set pass to next handler
What's wrongwith this picture? What's wrongis that there’s no guaranteethatthe value the user passedto function 0Ehis valid! Unfortunately, function 0Ehdoesn’t have an error return(instead, it rather irrelevantly returns LASTDRIVEin
AL). Thus, the only waytotellif a call to function 0Eh succeededis to
call function 19h. And thatis precisely what IFSMgris doing.
Whydoesn’t IFSMgrdo this when a VMis running in protected mode (VMSTAT_PM_EXEC)? Without any special protected-modehandling
for function 0Eh, VMMautomatically sendsthecall to the V86 interrupt hook chain. Thus, IFSMgr sees the function 0Ehcall a second time, and at thattimeit cancall function 19h andsavethe current-drive value.
In other words, for every PM call to function 0Eh,there’s an additional V86 modecall to function 19h. The WLOG212F programon the Unauthorized Windows 95 disk confirmsthis. As we saw in Chapter 1,
WLOG212F is a protected-mode Windowsapplication that hooks INT 21h inthreeplaces: twice in protected modeand once(using DPMIcall-
backs) in V86 mode. WLOG212F can then comparetheinterrupts issued in protected modewith those seen down to V86 mode. After run-
ningseveral Windowsapplications,WLOG212Freportedthe following results for INT 21h functions 0Eh and 19h:
Fune oh 19h
Kerne1D0SProc (Prot mode) 688 674
v86 mode 688 1362
Passed down Passed down
WLOG212F detected 1362 V86calls to function 19h. But only 674 of thesecalls were issuedin protected mode. Wheredidthe extra function
Unauthorized Windows 95
19hcalls come from? Well, 1362 — 674 = 688, which is the number of
protected-modecalls to function OEh. Just as you'd expect from the IFS-
Mgrcode, there’s an extra V86call to function 19h for every PMcall to function 0Eh. Thepointthat emerges from this close look at function 0Ehis this: Evenfor a simple INT 21h call that Windowspasses down to DOS, it’s
really Windows’ VMM/VxDlayerthatis in control. The IFSMgr VxD saw thecall before DOS, andit saw the call again when DOS was fin-
ished with it. The only reason DOSsawthecallatall was that IFSMgr let it see the call. IFSMgrcan even take one INT 21h call (function 0Eh)
and generate another(function 19h). To makethe point one moretime,
there is no necessary correlation between the INT21h callsissued under Windows — even by DOSprogramssuch as TEST21 — and the INT 21h calls that eventually wendtheir way downto real-mode DOS. Tr’s also importanttorealize thatthecalls that are passed down to
DOSdepend on what VxDshappento be loaded. Although IFSMgr comesbuilt-in to WfW3.11 and Windows 95, the capability to write VxDsthat bypass DOSis a standard part of the VMM programming interface and is documented in the DDK.
Take function 19h, for example. As noted in Undocumented DOS (2d ed., p. 69), real-mode DOS’s implementation of this functionistrivial.
It just movesthe contents of DOS’s CURR_DRIVvariable,located at offset 336h in the DOSdata segment(offset 16h in the Swappable Data Area [SDA]),into the AL register: u fdc9:4c64 FDC9:4C64 A03603 FDC9:4C67 C3
MOV RET
«AL, [0336];
DOS_DS:0336 = CURR_ORIV
‘Thus, a VxD that handles this function entirely in 32-bit protected modeis a piece of cake. CURRDRIV.ASM,shownin Listing 8-3, is a VxD thatdoes just this. We've talked a lot about how VxDshave becomethe operating system andhowthey can handle DOScallsin protected mode,soit would be useful to examine one small VxD to see howalll this works, Listing 8-3: CURRDRIV.ASM
xO that handles one INT 21h function entirely in protected mode INT 21h Function 19h (Get Current Drive) masm5 -p -w2 currdriv.asm
Chapter 8: The Case ofthe Gradually Disappearing DOS
urrdriv.obj,currdriv currdriv.386 put de: ce=\unauthw\c
ni (386Enh]
currdriv.def: LIBRARY CURRDRIV DESCRIPTION "INT 21h Function 19h Handler’ EXETYPE 6 SEGMEN _LTEXT PRI NONDISCARDABLE LDATA PRELOAD NONDISCARDABLE TTEXT CLASS *ICODE' DISCARD: IDATA CLASS *ICODE" DISCARt TEXT CLASS 'PCODE" NONDISC: ATA CLASS *PCODE’ NONDIS! EXPORTS CURRORIV_DDB @1 386p JE YNM. INC INCLUDE V86MNGR. INC ; This will become CURRDRIV_ODB are_Virtual_Device CURRDRIV, 1, 0, Control_Proc, Undefined Device_I Undefined_Init_Order TASEG iss need to add in linear 00S data in_CurOry dd 0336h
segment
TALENDS Vx0_CODE_SEG
BeginProc movzx mp je
add mov mov cle ret
EndProc
IntZ1ve6 eax, Cebp al, 19h short D ; keep locking eax, [Lin CurDrv] eax, [ebx.CB_High_Linear al, byte ptr byte ptr a : done, I've
Int 21V8¢
Unauthorized Windows 95
Do_Device_Init ent_Sta Begin_Nest
get SysVars : but just use DOS data seg
Lin_CurDrv, eax End_Nest_Exec t_State mnov m VwMcal] Hi EndPro}
add linear DOS
set32 Int21V86 nt_Chain
Do_Device Init
1CODE_ENDS VXD_REAL_INIT_SEG
nit proc near xor ax, ax xor edx, edx it endp WxD_REAL_INIT_END:
Like all VxDs,CURRDRIV.ASM has a Declare_Virtual_Device statement, whichwill eventually become the VxD’s Device Descriptor Block (DDB). Thisincludes a pointer to CURRDRIV’s Control_Proc routine. VMM calls each Control_Pro
in each VxDfora varietyof events, such
asthe creation ortermination of a VMorthread.
Chapter 8: The Case ofthe Gradually Disappearing DOS
‘Theonly event CURRDRIVcares aboutis Device_Init. CURRDRIV’s Do_Device_Init routinefirst uses the standard Begin_Nest_ V86_Exec/Exec_Int block ofcode to issue an INT 21h function 52h call
in V86 mode. This DOSfunction returns with ES:BX pointing to the undocumented DOS SysVarsstructure (the List of Lists). However,
CURRDRIVignores BX and uses ES as the DOS data segment.It shifts ESleft by 4 to forma linear address and addsit onto CURRDRIV’s Lin_CurDrvvariable, which is predefined as 0336h. Lin_CurDrv now
containsthelinear address of DOS’s current-drive variable.
Once Lin_CurDrvis properlyset up, CURRDRIV uses VMM’s
Hook_V86_Int_Chain servicetoinstall the Int21V86 routine as a handler
for INT2th.At this point, CURRDRIV is dormantuntil an INT 21h call comes in. Note that CURRDRIV’s INT 21h handlerwill be called
notonly for INT 21h calls coming from V86 modebutalso for any
Exec_Int 21h calls made by VxDsin a nested V86 Exec block, such as that shownback in Figure 8-9. The Int21V86 routineuses [ebp.Client_AH] to see which INT 21h
functionis being called. For any DOSfunction other than 19h, CURRDRIVsets the carryflag. Thisis a signal to VMMtopassthecall to the next VxDin the V86 hookchain. Whenan INT 21h function 19h call comes in, CURRDRIVjumps to
the Do_GetCurDrv routine. This reads the currentdrive
out of
Lin_CurDrv, moves it intothe caller’s AL register (ebp.Client_AL), and
returns withthecarryflag clear. Thisis a signal to VMMthattheinter-
rupthas beenserviced and shouldneitherbe passed on to any other VxD (such as IFSMgr) in the V86 hookchain nor passed down to the DOS
interrupt chain in V86 mode.(It’s crucial to understand the difference between these twochains:thefirst is maintained by the Hook_V86_Int_ Chainservice and consists of 32-bit protected-mode VxD code, and the
secondchainis the familiar one from DOS programming.) ‘That's it: INT 21h function 19h is now being handled entirelyin 32-bit
protected mode, bypassing DOSandany other VxDsthat might have beeninterested inseeingcalls to this function. After using the DDKtools to build CURRDRIV.386 (see the instructions at the top of Listing 8-3) and putting device=currdriv.386 in the [386Enh] section of your SYS‘TEMLINI, you can run the TEST_1 version of TEST21 again tosee that,
indeed, CURRDRIVisbypassing DOS: Rec a1 calls Generated 100 received 21/0E 101
Unauthorized Windows 95
21/19 21/25
100 called called
ived ved
Some INT 21h are handled without calling DOS!
Notethe change from Figure 8-4:Instead ofgetting the message
“Someextra INT 21hcalls are occurring!” we nowget the message
“Some INT21h are handledwithoutcalling DOS!” — all because ofthe simple code in CURRDRIV.ASM. CURRDRIV.ASM doesn’tuse anyfeatures of 32BFA. The VMM servicesit uses, especially Hook_V86_Int_Chain, haveall been around since 1990. Yet CURRDRIVis doingbasically the same thing as 32BFA,
although on a much smallerscale. All the resources necessary to make DOSdisappear have been quietlysitting in VMM,just waiting to beused.
Windows 95: Still Bypassing DOS, but Supporting TSR Sofar, we've used TEST21 onlyto experiment with 32BFA in WFW 3.11. Nowwe need to run TEST21 under Chicago, which ofcourse also
supports 32BFA.Figure 8-10 showstheresults ofthattest.
3E 21/3F 1/40
1 calls Ved Ned led 100 called 200 called
INT 21h appears to be hi
00 00 00 200 received d in the normal way
Figure 8-10: Running TEST21 underChicago.
What?! The “INT21h appears to be handledin the normal way” message in Figure 8-10is unexpected under Windows95, giventhat 32BFA in WEW 3.11 (which Microsoft’s own advertisements said was “poweredby 32-bit technology fromour ‘Chicago’ project”) triggers TEST21% “Some INT 21h are handledwithout calling DOS!”message. Furthermore, the V86TESTprogramfrom Chapter 10, which loads before Windows, showsthat when running TES 21 (or anyother
Chapter 8: The Case ofthe Gradually Disappearing DOS
programthat hooks INT21h) in a DOSbox, Windowsis sending these calls down to DOSoratleast to global (thatis, loaded before Windows) DOSprogramssuch as V86TEST. While running TEST21 locally (that is, in a DOSbox), V86TESTdetected the following INT 21h calls: 02; 42 08: 5 e930: 1 40: 203 44: 1
0B: 1846 35 38:1 48: 2 49: 1
2a 4A: 1
5D: 2
Notethatthe calls to functions 3Dh—-40h (File Open, Close, Read, and Write) match up reasonablywell with the calls made by TEST21. Recall from earlier in this chapter that in 32BFA under WfW3.11, V86TEST only saw TEST21°s function 40h writes to stdout.
At leastin terms ofits apparent reliance on DOS,these TEST21
results make Windows95 appear to be a step backward from W£W 3.11! Hold on a moment: Although TEST21’s INT 21h did see all the pro-
gram’s INT 21h calls, the “0 secondselapsed” message in Figure 8-10
calls into question whether MS-DOS itself really could have seen these
calls, no matter what TEST21 and V86TESTseem toindicate. Back in Figure 8-1, TEST21 on the same machine took 21 seconds without 32BFA. IfTEST21 takes roughly the same amount of time — which was no time at all — under Chicagoasit did under WfW3.11 with 32BFA,
it’s a goodindication that the “INT21h appears to be handled in the normal way” message is in some waymisleading.
Also, if you install the CURRDRIVVxD from Listing 8-3 under Windows95 and then run the TEST_1 version of TEST21 (Listing 8-2), you'll see the “Some INT 21h are handled without calling DOS!” mes-
sage that CURRDRIVhassuccessfullytrapped and emulated INT 21h
function 19h, just as under WfW3.11. Clearly there’s nothing wrong
with the fundamental Hook_V86_Int_Chain mechanism for emulating
INTcalls in 32-bit protected mode, so there mustjust be something different about Windows 95’s implementation of 32BFA. We need the TEST21 -MYSETVECT option to see Windows 95’s true colors. With -MYSETVECT, TEST21 will get and set its interrupt vectors not with INT 21h functions 25h and 35h (_dos_ setvect and _dos_
getvect) but instead with my_setvect and my_getvect, two functions that
directly poke and peek the low-memoryIVT. (See Listing 8-1 and the
“Interrupts 101: IDT versus the IVT”sectionlater in this chapter.) Guess what? As Figure 8-11 shows, running TEST21 -MYSETVECT under Chicago produces the same “Some INT 21h are handled without calling DOS!”results as running TEST21 under WfW3.11 32BFA.
Unauthorized Windows 95
C:\THIS IS A LONG WINDOWS 95 DIRECTORY NAME>test21 -mysetvect > test21.10g C:\THIS IS A LONG WINDOWS
‘ORY NAME>type test21.1og calls
a d without calling DOS!
Figure 8-14: Running TEST21 -MYSETVECTunderChicago produces these results. Onceagain, V86TESTconfirms that these INT 21h function 3Dh-
40hcalls are not sent down to DOS: 02: 12 8: 11 OB: 2 608 3 Wel Shr ae: 40:30 44:1 48: 2 49:1
4A: 1
4B: 1
4C:
1
40: 1
5D: 2
Whydid using my_setvect rather than _dos_setvectto install TEST21’s INT21h handler make sucha difference?
Empirically, the Chicago version of IFSMgr mustbe hooking INT
21h function 25h (Set Interrupt Vector) and usingit to set somesortof flag, indicating that DOScalls must be sent down the INT 21h chain for
agiven VM. Indeed, using the PROTTAB programto generate an IFSMgr table
for Chicago, similar to the one for WfW3.11 back in Figure 8-7, shows that the IFSMgr INT 21h table in Chicagodoes contain a handler for
function 25h. Without boring youwith the entire newtable, here are the differences between the Chicago and WfW3.11 IFSMgr INT21htables: * Four FCB-related functions are handled in WfWbutnot in Windows 95: 11h, 12h, 13h, and 17h. ¢ Five functions are handled in Windows 95 but not in WfW: 1Bh, 25h,
60h, 69h, and 71h. Function 1Bh gets allocation information for the currentdrive. Function 60his the undocumented TRUENAME, function (see Undocumented DOS,2d ed., pp. 148-151, 428-430).
Function 69his an undocumentedcall to get andset the disk serial number. Function 71h is new; it provides long filename (LFN) support in Windows95. For example, since function 60h isTRUENAME, function 7160his the LFN version.
Chapter 8: The Case ofthe Gradually Disappearing DOS
Anyway, we’reinterested in function 25h. Just as we'd expect from
the different results we got from running TEST21 and TEST21 -MYSETVECT, inspection of the IFSMgr code for function 25h shows
thatif the caller is setting the INT 21h vector, the handler for function 25h setsor clearsa flag in IFSMgr’s DEVICE_CB_AREA.As noted earlier, the DEVICE_CB_AREAis part of the VMCB, so thereis a separate
flag for each VM. IFSMgr’s INT 21h handlers in Windows 95 are somewhatdifferent fromthe ones in WfW3.11 (see Figure 8-6). For one thing, the INT 21h handlers in Windows95 check theflag that function 25hsets. If theflag is set, indicating that the VMhas hooked INT21h, IFSMgr passes down the INT 21h call. Thisis evidently Microsoft’s response to widespread complaints about the failure of 32BFA in WfW3.11 to pass down INT 21h. For example,
the same bypass-DOS 32BFA behavior we saw in TEST21 broke Stacker disk compression in WFW3.11! According to PC Week (“Stackerclashes with WFW’sfile access; Stac working on fix,” March 7, 1994), “VCache blocks certain DOScalls to the Stacker driver.”It’s not clear why VCache is singled out as the culprit — it’s IFSMgr, not VCache, that handles INT 21h — butthe phrase “blocks certain DOS calls”certainly has a
familiar ringtoit from the output shown by TEST21 and V86TEST.
under WfW3.11.
Microsoft has a dilemma here: 32BFA entails bypassing MS-DOS, but bypassing DOS meansthat key DOS utilities such as Stacker won’t see the stream of INT 21hcalls that they expect. Were TEST21 a genuinely useful programthat did more than simply log INT21h calls and whose functionalityactually depended on seeing INT 21hcalls, we wouldn’t be so sanguine aboutits capability to detect the presence of 32BFA in WfW3.11. We wouldinsteadsay that Windows had broken TEST21. Thetradepresslikes to beat up on Microsoft for what seemslikeits
failure to move morerapidly awayfromreal-mode DOS. Yet when Windowsdoes take giant steps aw mreal-mode DOS,as in 32BFA, the trade press again beats up on Microsoft, or the vendorof the broken DOSutility, or both — onlythis time, they view such movement away
from DOScompatibility as a bug! What everyone wants, apparently,is
DOScompatibility but not DOS.
Well, that’s reasonable enough. Sort of. Microsoft must bypass DOS yet support DOSprograms(such as Stacker) that need to see DOScalls.
Unauthorized Windows 95
We'll seelater that 32-bit disk access (32BDA,also knownas FastDisk),
introduced in Windows3.10, hada clean solution to a similar problem. In Windows 95, 32BFAuses a not-so-clean solution. Note howeasy it was for TEST21 -MYSETVECTto trick Windows 95 into thinking that
we hadn’t hooked INT 21h. Although the my_setvect code might seem contrived,it’s not uncommonfor DOSprogramstodirectly manipulate the low-memory IVTratherthan call functions 25h and 35h. As only one example, Windowsitselfdoesthis. As I write this, Chicagois still in beta. It’s possible that Microsoft will correct the my_setvect loophole by the time of Windows 95’s commercial release.If so, the time elapsed while runningTEST21 will be the only indication of 32BFA, and TEST21 -MYSETVECTwill falsely declare
that “INT 21h appears to be handled in the normal way.” Frankly, TEST21 should makethis false declaration. TEST21 demonstrates 32BFAso nicely under WfW3.11 onlybecause of a flawin 32BFA.
Thisflawremains in Windows 95 but is notas big. Apartfromtheelapsed timeto performfile I/O, 32BFAis supposedto be “transparent”(thatis, invisible to applications), yet we've detected the presence of 32BFA with TEST21, a perfectly “legal” DOS programthat doesn’t use any undocumentedor underhandedtricks.
INTVECT: Another Sample VAD INT 21h Hooker As another example of howeasyit is to defeat IFSMgr’stest that a VMis hooking INT 21h, consider a VxD that grabs function 25h calls before
IFSMgrgets tosee them. Inaddition to beating the -MYSETVECT
horsejust a little more thoroughly, a VxD that hooks function 25h (and 35h too, while we're at it) is even more important as an additional
demonstration of how VxDs can handle DOSin protected mode. ‘The CURRDRIVVxD (Listing 8-3) showed howeasyit is, at least
for simple INT21hcalls, to bypass DOS. INTVECT.ASMin Listing
8-4 is another VxD like this. INTVECT.ASM hooks INT 21hfunctions 25h(Set Interrupt Vector)
and 35h (GetInterrupt Vector), handling these twocalls entirelyin
32-bit protected mode. INTVECTbasicallyuses the my_setvect and my_getvect code fromListing 8-1, translated into 32-bit assembler.
Chapter 8: The Case ofthe Gradually Disappearing DOS
Listing 8-4: |NTVECT.ASM
comment % INTVECT.ASM Sample VxD that handles two INT 21h functions entirely in protected mode INT 21h function 25h: Set Interrupt Vector INT 21h function 35h: Get Interrupt Vector (Same basic instructions, .def file as 5
|RRDRIV. ASM)
386p INCLUDE VHM. INC INCLUDE V86NMGR. INC IFSMgr_Init_Order
€QU @A0011000h ; found by running VXDSHOW IFSMGR.386
tri this will become INTVECT_00B DeclareVirtual_Device INTVEC Control_Proc, \ Indefined_Device ID, \ IFSMgr_Init_Order+10000H, . .\ VxD_CODE_SEG
BeginProc movex cmp je cmp je ste ret
Int21V86 eax, Lebp.Client_AH] al, 25h short Do_SetVect al, 35h short Do_GetVect.
t: chain to previous handler
Do_Setvect movzx movzx shi moy mov mov cle ret
interrupt number eax, Cebp.Client_AL] t: get interrupt handler edx, Lebp.Client_0S t: from caller's DS:0X edx, 16 dx, Cebp.Client_0X] —-ecx, Lebx.CB_High_Linear] dword ptr Cecx + (eax * 4)], edx ; shove into IVTLeax] don't chain! i: done
Do_GetVect movzx mov mov mov shr moy cle ret EndProc
si eax, [ebp.Client_AL] ecx, Cebx.CB_High_Linear] edx, dword ptr [ecx + (eax * 4)] 3: _Lebp.Client_BX], dx _edx, 16 _[ebp.Client_ES], dx 3: Int2ive6
interrupt number get handler from IVT[eax] put into caller's ES:BX done
don't chain!
Unauthorized Windows 95
Vx0_CODE_ENDS Vx0_LOCKED_CODE_SEG
BeginProc Cont Proc ch Device Init, Do_DeviceInit Control_0 Control_Proc
BeginProc Do_Device_Init mov eax, 2 move: set32 Int21V86 VMMcall Hook V86_Int_Chain EndProc
Do_Device_Init
Vx0_ICODE_ENDS VXO_REAL_INIT_SEG real_init proc near Pax, ax xor bx, bx Psi, si . edx real VXO_REAL_INIT_ENDS END
Aswith the earlier CURRDRIVexample(to which INTVECThas a morethan passing resemblance), INTVECT’s Do_Device_Init routine uses the VMMHook_V86_Int_Chain serviceto install Int21V86 as a handler for V86 INT 21h. Unlike CURRDRIV, though, INTVECT has to worryaboutits order in the V86 INT21h hook chain. We knowthat IFSMgrin Windows95 hooksfunction 25h; that’s the reason I’ve chosen this example. For reasonsthat will soon becomeclear, I want INTVECT tosee (and deal with) function 25h before IFSMgr gets a chance to. A VxD%s location in the V86 INT 21h hook chain depends on when the xDcalled Hook_V86_Int_Chain. ‘This in turn depends in part onthe VxD%initialization order, so P’ve given CURRDRIVaninitialization orderslightly higher than IFSMgr’s. Manyaspectsof 32BFA depend on VxDinitialization order. Gosh, this VxD programmingis just like
Chapter 8: The Case ofthe Gradually Disappearing DOS working with TSRs, except that VxD writers get to play “load melast” gamesinstead ofrequiringthat users do so.
When INTVECTreceives acall to function 25h,it jumps to the Do_SetVectroutine. This routine takes the interrupt number from
[ebp.Client_AL] and the newhandler from [ebp.Client_DS] and {ebp.Client_DX]. INTVECTis goingto shove the new handler right into the low-memory IVT, just as the my_setvect function backin Listing 8-1 did. VxDs have a 4GBflat address space representing the entire machine, and the current VM’saddress space is mappedin at linear address 0, so INTVECTcould access the IVT with an expression as simple as DWORDPTR[intno * 4]. However, the current VM’s address
spaceis also available via the [ebx.CB_High_Linear] field in the VMCB, and INTVECTaddsthisin. In the eventof a function 35h call,INTVECTgoes to Do_GetVect, which pulls the handler address out of the IVT and returnsit in [ebp .Client_ES] and [ebp.Client_BX]. Thisis similar to the my_getvect code in TEST21.C. After building andinstalling INTVECT.386,it’s timetosee if it works. Recall that TEST21 has alwaysseen its own call to function 25h. With
INTVECT386installed, you can run TEST21 and — voila! — TEST21 no longersees function 25hcalls. See how easyit is to bypass DOS? As a moreinterestingtest, install INTVECT.386 in Windows 95’s
SYSTEMLINI and run TEST21 again,this time withoutthe -MYSETVECTswitch. Now TEST21 outputsits “Some INT 21h
are handled withoutcalling DOS!” message, indicating the presence of 32BFA.
What’s happeningis that INTVECT grabbedfunction 25h aheadof IFSMgr,servicedthe function by poking the IVT, andcleared the carry flag so that VMMwouldn’tpassthecall to anyoneelse. This capability of VxD V86 INThandlers to bypass not only DOS and TSRsbutalso other VxDsis powerful butdistressing. It shows that VxDsplay the same role in Windows that TSRsplayed in DOS: You have the samekind of powerbutalso the samekind of confusing interactions that should be fully expected when thousandsofthird-party developers have been given free reign to hack the operating system.
VxDsbecomea true part of the Windowsoperating system. Thisis botha blessing and a curse. Theblessing is that at the VxD layer, Windowsis a relatively open system. The curse is that at the VxD layer Windowsis a relatively open system! A crucial system componentsuch as IFSMgrcan makecertain assumptions (suchas that local INT21h
Unauthorized Windows 95
hookers can be detected by hooking INT 21h function 25h), and some
third-party VxDsuch as INTVECTcan comealong and,in a perfectly legal fashion (accordingto the laws laid downin the Windows DDK),
undermineits
assumptions.
Thus, bypassing DOSisn’t really all that difficult. Wedid it for two key (albeit simple) DOSfunctionsin about100 linesof code. But we've also interfered with IFSMgr’s rather simple-mindedtest for local INT
21h hookers. Bypassing DOSmight beeasy, but supportingothersoftware(including other VxDs) that expects to see a stream of INT 21h calls
is a difficult and — giventhe thousandsofdevelopers writing VxDs — unboundedproblem.
Global and Local INT 21h Hookers Far more important than the my_setvect loophole, IFSMgr’s function. 25h handlercan’t do anything about programssuch as Stacker that hook
INT21h before Windowsstarts. IFSMgr detects the presence of an INT
21h hookersolely by monitoring calls to function 25h. Because IFSMgr
beginsits monitoring long after programssuchas Stackerhavecalled
function 25h, it concludes that INT 21h neednotbe passed down. Indeed,this policyis deliberate. A Microsoft white paper by Russ
Arun, “Chicago File System Features — Tips & Issues” (April 22, 1994) containsthe following explanation: Ondefault all INT 21 interrupts, exceptfile API INT 21s, are passed downto any hookerpresentin the system. Thefile API INT 21s are just passed to VM(local) hookers, but not to global (AUTOEXEC.BAT)type hookers. This is done because there are new file APIs (new INT 21s) that support longfile namesfordelete, rename and soon that anolder hooker won't understand anyway.Furthermore notall file API calls are INT 21 calls. Specifically servercalls and swappercalls to the file system are not INT 21 calls. Althoughthis statement explains muchof the behavior we’ve seen in Windows 95 with TEST21, it raises more questions than it answers(it
also raises some eyebrows regarding the “global hooker,” “local hooker,” and“older hooker”phrases, but we won’t getintothat):
* “Ondefault all INT 21h interrupts, exceptfile API INT21s, are passed down to any hookerpresent in the system.” Since MS-DOSitself (WINBOOT.SYS)is an INT 21h hooker, doesn’t this meanthat all DOS functions not relatedtofile I/O are passed downtoand handled by DO Doesn’t this contradict Microsoft’s frequent claimsthat
Chapter 8: The Case ofthe Gradually Disappearing DOS
Windows 95 doesn’t require DOS?(Indeed,to anticipate thepoint of Chapter 10, the V86TEST outputshownearlier certainly seems to confirm that Windowsdoes use DOSfor a wide variety of INT 21h calls, including functions 2Ah and 2Chtoget the date and time.) * “Thefile API INT 21s arejust passed to VM(local) hookers, but not to global (AUTOEXEC.BAT)type hookers.” Isn't it precisely global hookers such as Stackerthat would most need tosee file-related INT 21h calls? Whythespecial treatmentfor these so-called local hookers? * “This is done because there are newfile APIs (new INT 21s) that support
longfile namesfor delete, renameand so on that an older hookerwon't understand anyway.” Butif that’s true for global hookers,isn’t it equally true for local hookers? Why are global hookers presumed to be older?
© “Furthermore not allfile APIcalls are INT 21 calls. Specifically server calls andswappercalls to thefile systemare not INT 21 calls.” This refers to the
fact that some VxDsin Windows95, such as the DynaPagereplace-
mentfor PageFile, makedirectcalls to IFSMgr. But as Geoff Chappell hasnoted,“if there are non-trivial DOS hookersin global memory, theywill be as [expletive deleted] about not seeing VxDs’file activity as they would be aboutnotseeingint 21h.” How would a global INT 21h hooker knoworcare abouta file I/O call originated from within Windows? To a global INT 21h hooker, all of Windows, andall programs running under Windowslooklike one big DOSprogram. These major questionsaside, we can at least see that Windows 95
intendsto support global INT 21h hookersfor non-file calls and local INT 21h hookers for all calls. IFSMgruses function 25h to check for local INT 21hhookers. Microsoft doesn’t intendto send file-related calls to global INT 21h hookers. But wait a minute! Although V86TEST didn’tsee file calls from ‘TEST21 -MYSETVECT, it did seeall file calls from TEST21 (that is, without the -MYSETVECToption). Yet V86TESTis a global INT 21h
hooker, loaded before Windows, to which, so say Microsoft, file INT 21h’s won’t — and shouldn’t! — be delivered. So why did V86TEST see file I/O calls from1
212
Because TEST21, like any reasonable hooker, chains to the previous
handler(see Listing 8-1). Anycalls sent to TEST21 will eventually be sent to V86"
as well. Thus, when IFSMgrlets a local hooker
like TEST21 see a call, global hookers such as V86TESTwill also see
it. This means that, although Windows 95 doesn’t intend tosendfile
Unauthorized Windows 95
INT21hcalls to global hookers, this will nonetheless happenif there are anylocal hookers.It would be simple to write a DOS TSRthat does nothing but hook INT21hand chainto the previous handler. Running this TSRin each VMwould force Windows95 to deliver all INT 21h, includingfile calls, to global hookers.
The Role of IFSHLP.SYS and U86 Callbacks But there’s a remaining mysteryhere: Although running a local hooker such as TEST21 entails the delivery of INT 21h calls to global hookers
such as V86TEST, and although MS-DOSitself clearly qualifies as a
global INT21h hooker,-nonetheless Windows95 can’t let MS-DOS see file-related INT 21h calls. Allowing DOS to handle these calls would not
onlycause tremendousconfusion,but also wipe out all the performance improvementsfrom 32BFA.
The TEST21 “0 secondselapsed” message backin Figure 8-10 shows
that, indeed, Windows 95 doesn’t let thesecalls goall the way down to
DOS. Yet, the V86TEST TSR sees thesecalls, and (as you can see from V86TEST.Cin Chapter 10) this reasonable hooker chainsthese calls to
the previous handler. How can TSRs such as V86TEST seefile INT 21h
calls and chain themon to the previous handler — and yet MS-DOS itself doesn’t see them?
IFSHLP.SYS, a DOS device driver supplied both with Windows 95 and with WfW3.11, is the answer, 32 BFA requires IFSHLP.SYS, and will
not load without it. If it fails to find IFSHLP (whose device name is
IFS$HLP$)IFSMgrdisplays the message: “The Microsoft Installable
File System Manager (IFSMgr) cannotfind the helper driver. Please
ensure that IFSHLP.SYShasbeeninstalled.” Running the INTCHAIN programfrom Undocumented DOS (2d ed.,
pp- 302-308) shows that IFSHLP sits between MS-DOS (including the DbISpace driver) on the one side and TSRs such as V86TEST on
the other: 21/3000
2032:098 0206 0408
Chapter 8: The Case ofthe Gradually Disappearing DOS O1eEF 0023 0A29:1956 00A0:0FAC FEQE:4249
b: DBLSYSHS bos HMA
Now,what does IFSHLP do whenit receives a DOScallthat’s been passed on from a hooker such as TEST21 or V86TEST? Knowing from
INTCHAINthat IFSHLP’s INT 21h handlerin this configuration happensto be located at real-mode address 0215:04A8, we can use a debug-
ger such as Soft-ICE/Windowsto place a breakpointon this address. The next time someonegenerates an INT 21h call that for whatever rea~ sonis sent downto the V86interruptchain, the breakpoint on IFSHLP is triggered, and wecantrace through thecode. I generated the log in Figure 8-12 bycontinally pressing F8(trace) in Soft-ICE,using WLOGtosavetheresultsto file, runningthefile through the VXDNAMEutility from the Unauthorized Windows 95 disk, and then adding comments. Thistrace of about 100 instructions is a
remarkable example of how WindowsVxDsinsinuate themselvesinto DOS,and of howeventhe lowliest DOS call — one which Windows reflects down to DOS — ain’t whatitusedto be. 0215:0448 0215:0448 0215:0440 0215:0483 0215:0485 0215:0488 0215: 0405 0215:0409 0215:0408 0215: 0480 0215:0462 0215: 0483 0215: 0486 215:0527
CHP JAE TEST J TEST a PUSH PUSH Nov Mov Mov Mov Pop ADD CALL
AH, 72 : inside IFSHLP INT 21h handler n this particular case, AH = OBh o4eB BYTE PTR $:[0035],02 045 (No JUMP) BYTE PTR CS:[0035],0C e405 (ouNP) aX 8x AH, 00 By AX. O4FC aX
table of INT 21h handlers 2 AX 28h ti call handler (O4FCh + 28h =
BYTE PTR CS:(0035],02 ;;; handler for 08,00,0,71 (JUMP) aro aX Bx BLAH 8H, BH ¢s:(0012) [BX+SI+
(JUMP) i: put INT 21h func number in BX +i jump to VB6 callback V86 callback at FBCA:23A2
Unauthorized Windows 95
vMn240) ViM+243 VMe2aa vM+249 veM+280 ViM+2B1, VeM+283 VM+287 V#28B Vi+280 VWM+2BF VMM+2¢5 veM+2c7 veM+2c0 vMM+200 ve+205
suB PUSHAD nov MP. cL nov nov TEST vz vo noV wow wo XCHG PUSH OMe.
ESP, +04
iri IDT INT @6h handler (i11egal opcode)
ES1,00000018 ViM+280
rip Bh = 6 * 4
vwe928 ViM+929 VwM+920 VMM+92F VNMe932 VNN#935
STi wovax nov wo SHL ADD
tr INT 6: invalid opcode EAX,WORD PTR [EBP.Client_CS] sii FBCAn ECX, EAX EOX,CEBP.Client_E1P) inh23A2h EAX,04 EAX, EDX try FBCAOh + 23A2h = FEO42h
vne937 VNN+93C VNM#93E VNMe94a VWM+94B
CMP ONZ SUB wow MP
EAX, O0OFEO42 al) V86 callbacks == FEO42h ViM#952 (NO. JUMP) ECX,o00aFRO4 iri FBCAh FBQ4h (base) = @céh EOX,(C410B004+8ECX)] ::; table of V86 CB ref data (C4108000+8"ECx] goto handler for this V86 CB
gr +480 IFSMar+4B6
IFSMgr+48C IFSMgr+4C0 TFSMgr+4C4 IFSMgr+4C7 TFSMgr+4C9 IFSMgr+4CE TFSMgr+403
IFSMgr+408
TFSMar+F6C IFSMgr+F72 IFSMar+F74 IFSMgr+F7A IFSMar+F7¢ TFSMgr+F81 IFSMar+F85 gr+Fe8 lgrtFBC grt FOr TFSMgr+F93 IFSMartF96 TFSMgr+F99 IFSMgr+F9) IFSMgr+FA2
+ VMM generic INT handler
EBP,ESP DI,0030 BYTE PTR [EBP.Client_EFLAGS+2],02 VMM+320 (NO JUMP) DS, 01 EBX, [VNM+F6E4] tri current VM handle £5.01 EOI, [VMM+F670) iit current thread handle sy Switch stacks ESP, [EDI+48) VWM+2E0 return address (see below) LEST+VMM+E410) goto INT 6h handler
CALL CALL wovzx nov coe, JAE Nov nov nov CALL
[Simutate_Pop} {Simulate_tret] ECX,WORO PTR [EBP.Client_BXJ ;;; IFSHLP put func in BX [EBP.C1ient_BX],AX CL.72 TFSMgr+4E1 (NO. JUMP) EDX aooaaoez ESI, FFFFFEFF EAX, 0000021 CIFSMgr+C78*4*ECK)] ::; call handler for INT 21h func
TEST NZ TEST NZ nov wovex SHL wovax SH wovax LEA
DWORD PTR CEBX},00000020 TFSMgr+FB6 EDX, 00000001 TFSMgr+B6 EAX, [1FSMar+3908) EAX,WORD PTR [EAX+10] EAX,04 EDX,WORO PTR [EAX+36] EDX,04 EAX,WORD PTR [EAX#34] EOX, [EAX+EDX] EDX,BYTE PTR [EDX] CIFSMgr+2E80) [EBX+04) BYTE PTR LEDX+EDI+2E],04
—;:; inside 21/08 handler (NO JUMP) (NO JUMP)
Chapter 8: The Case ofthe Gradually Disappearing DOS TFSMgr+FA? IFSMgr+FB6 IFSMgr+FB7
OZ STC RET
IFSMgr+F86
IFSMgr+40F IFSMgr+507 IFSNgr+500 IFSMgr# TFSNgr+# IFSMgr4521
JB MOV MOV ovzx CALL RET
LFSMgr+507 EDX, CIFSMgr+2ERO]
VM+2EO VMM+2EF VMM+2F5 VWM+2F7 VMM+2FA VMM+2FC VWM+2FF vMM+300 VMM+303.— O1F6:0023 038C:1956 038C:1957
MOV MOV CLI XOR CMP JNZ TEST JNZ XCHG POPAD ADD IRETD IMP PUSHF STI
(OUMP) (OUMP) :; 2174 IFSHLP table ; O1F6h prev INT 21h 0023n Frame] ts not shown
EBX, [VMM+F6E4] ;;; back in VMN, at pushed ret addr EDI, [VNM#F670) EA, EAX =«EAX, [VMM#DC88] YNN#304 BYTE PTR [EBX],20 VNN#35B «ESP D1+483
(NO JUMP) (NO. JUMP)
ESP -038C:1956
Figure 8-12: This outputfrom Soft-ICE demonstrates that IFSHLP can send INT 21h calls back to IFSMgr. Withouttrying to understandevery line in Figure 8-12, here’s the basic idea: In thefirst block of code, for example, IFSHLP.SYSis examininga call to INT 21h function 0Bh (Get KeyboardStatus). As we have seenin someofthe sample output from V86TEST, when COMMAND
-COMis running in a Windows DOSbox,it calls function 0Bh often. IFSHLPuses the INT 21h function number(OBh in this case) as an
indexinto a table ofbytes, located in Figure 8-12 at 0215:042A. For INT 21h function n, table[n] + 4FChis the address of a small piece of code thattells IFSHLP howto handle the INT 21h function.It’s helpful to dumpout this table andsortit by addre: C:\UNAUTHW>Ftab 215:42a 72 121 1 sort | massage table(n] + 4FC INT 21h function n 4FC 510 520 527 532
5F 5E Q0-0A, OC, OF-30, 41, 43, 45, 46, 48-56, 58 5D, 60-67, 69-70 0B, 0D, OE, 71 44
Unauthorized Windows 95
a7
550 570
3F, 40, 42, 57,
C, 68
As you can see, IFSHLPusesthe codeatoffset 520h to deal with most INT21h functions:
2EFFZEECOS
POP POP
AX AX
UMP
FAR CS:(04EC]
4 c 0215:04EC 01F6:0023
In the INTCHAIN outputshownearlier, 01F6:0023 belonged to a block device driver controlled by DblSpace, which wasloaded before IFSHLP. In other words, for the majority of INT 21h functioncalls that
for whatever reasonfindtheir way to IFSHLP, IFSHLPsimplychains
thecall to the previous INT 21h handler. Thecall eventually makesits wayto the real-mode DOScode. The remaining INT 21hfunctions (OB, OD, OE, 3E, 3F, 40, 42, 44, 47, 52, 57, 5C, SE, SF, 68, and 71) are possible candidates for IFSHLP to
send to IFSMgr.
In our case, IFSHLPsendsthe function OBhcall to IFSMgr. How IFSHLP, whichis 16-bit real-mode code (running in V86 mode),calls
IFSMgr,whichis 32-bit protected-mode code,is pretty interesting and merits the following extremely long digression on V86 callbacks and breakpoints. Atthe end ofthefirst block of code in Figure 8-12, there’s aJMP FAR CS:[0012], which takes us to the odd-looking address FBC: is an odd address because it’s in the ROMBIOS; why would IF
jumping into the ROMBIOS? Furthermore, on most machines, the address IFSHLP jumpsto is not only in the ROM BIOS — it’s in the
middle of the ROMcopyright message! E OF F 0 61 4C 69
6C FF 6F 74
6F-67 FE-FF 72-61 65-20
69 FF 74 56
65 FF 69 65
73 £9 GF 72
20 3B GE 73
4C 20 OD 61
74 64 46 45 0A55 00 00
—chnologies Ltd NE C Corporation. .U itraLite Versa
What the...? Well, if you lookat the Soft-ICEtrace in Figure 8-12, you'll see that the data at FBCA:23A2 can,like all data, be interpreted (or misinterpreted) as code:
ARP
[BX+S1+6E],BP
Chapter 8: The Case ofthe Gradually Disappearing DOS It so happensthatthe letter c, ASCII code 63h, correspondsto an ARPLinstruction.It’s not necessary to get into whatthis instruction is supposed to do. The importantthingis that this instruction in #/egal in 86 mode.
So what happenswhena program running in a DOSbox under
Windowsexecutesthis illegal instruction? Windows mustdisplay a dialog box saying “Theapplication has committed a heinous crime and by
thewill of the people will be terminated,” right? No. Illegal instructions, GP faults, page faults, and thelike, aren’t nec-
essarily crimes against humanity. They are merely triggers for interrupts.
In ourcase, executingtheillegal ‘c’/ARPL/63h instruction generates an INT 6,whichis theillegal opcodefault. If someone has hooked INT6 and choosestointerpret the fault as a crime,then they can certainly put up a frightening-looking dialog and proceed to annihilate the DOS box (perhaps using a VMMservice called — I’m not making this up — Nuke_VM). But another, more sanguine INT 6 hooker might take a morerelaxed view of the matter.
In the code in Figure 8-12, the INT 6 handlerlives in VMM,which as you knowby now,is 32-bitprotec...
Notice what's just happened. Recall that there was some question about how IFSHLP, whichis 16-bit real-mode code (running in V86
mode), could manageto hoistitself into 32-bit protected mode in order
to call IFSMgr. Well, IFSHLP just did it. Merely by executinganillegal instruction, IFSHLP has switcheditself out of 16-bit V86 modeinto 32bit protected mode.
Prettyclever, eh? Soclever,in fact, that a numberof top programmers at Microsoft, including Phil Barrett, Ralph Lipe (RAL), and Aaron Reynolds (AAR), managedto secure a patentonit:
U.S. Patent 4,974,159 Control transferring method for multitasking computer system - writing virtual machine break point instruction into executable codeof selected disk operating system (DOS) routines.
Patent Assignee: MICROSOFT CORP ‘Author(Inventor): HARGROVE R; BARRETT P R; LIPE R A; REYNOLDSA R; WILSON M D The method provides forthe insertion of a virtual machine break point (VMBP) instruction into the DOS code at a point where DOSwill be executing in such a state,referred to a BreakPoint Locations (BPL). Whenthe VMBPinstruction is executed, the 80386 transfers control from the DOSto Virtual machine control (VMM). When the VMM receives control, it determines that the transfer was caused by the execution of a VMBP. instruction. The VMM is then free to start another task or perform otherfunctions with-
out corrupting the DOSdata structures. A VMMthatmodifies a DOSis referred to a virtual DOS monitor machine (VDMM).
Unauthorized Windows 95
Pref., the VDMM usesa copyofthe contents of a selected routine where a break point is to be stored to locate the selected routine within DOS.Alternatively, the VDMMcould load froma file the BPL addressesfora particular version of DOS under whichthe application programs are to execute. Alternatively, the BPL addresses could be hard coded into the VDMM. ADVANTAGE- Avoidsinefficiency causedbycalls of indefinite duration. Clevernessis notbyitself a valid basis for securing a patent, however. Anothercriteria is originality. Microsoft’s use ofanillegal instruction to makethe hyperspace jumpfrom 16-bit real mode to 32-bit protected modeis remarkably similar to a well-knowntechnique dating back over twenty years to IBM’s VMoperating system, which usedanillegal instruction as a supervisor call. A nonexistentinstruction, often referred
to as DIAGNOSE,forced an exception within a virtual machineso that the exception could be caught by the VMkernel and interpreted as a
service request. Sound familiar? (For moreinformation on the history ofthis great hack, see the letters to the editor in Windows/DOS
Developer's Journal, July 1993, pp. 99-100).
Atanyrate, this ARPLtrick is one of the underpinnings of Windows, including Windows 95. VxDs such as IFSMgrcan call a VMM service,
Allocate_V86_Call_Back, passing in ESI the address ofa 32-bit protected-modecallback procedure (such as offset 4B0h in IFSMgr).
Allocate_V86 _Call_Back returns with EAX holding a V86 mode segmentioffset address, such as FBCA:23A2. This address points to the ARPLinstruction. The VxDcan thenpass the segment:offset address to any V86 modeclients, such as IFSHLP, that might want to call in to the VxD. The ARPL is what Microsoft sometimes(not quite accurately)
calls a thunk,in this case a thunk from 16-bit V86 mode to 32-bit protected mode. In the IFSHLP/IFSMgr example, IFSMgr during its initialization
called Allocate_V86_Call_Back, passingit the address IFSMgr+4B0h. Allocate_V86_Call_Back returned the address FBCA:23A2. IFSMgr then
passed this address to IFSHLP. IFSHLP nowknows that FBCA:23A2 is a stand-in or thunk for IFSMgr+4BO0h.
‘Thatphrase “passed this address to IFSHLP”is rather vague. How
does IFSMgr pass the V86callback’s address to IFSHLP? By using an
importantbut unfortunately undocumented backdoor IOCTLinterface.
Geoff Chappell (as usual!) has written a thorough descriptionofthis interface for WEW3.11. Geoff's document needsto be brought uptodate for
Windows95 andpublished in full, but in the meantime here’s a portion that explains how IFSMgrpasses the V86callback address to IFSHLP:
Chapter 8: The Case ofthe Gradually Disappearing DOS INT 21
IFSHLP.SYS GET API ENTRY POINT AX 4402h BX = file handle for device “IFSSHLPS" CX = 0008h DS:0X -> buffer for entry point record clear if successful AX = number of bytes actually read (should be 0008h) CF set on error AX error code
Format of entry Size DWORD DWORD
point record return: Description EF703734h address of entry point
Note: This structure can be obtained by an IOCTL READ, IOCTL WRITE or a normal READ. In the IOCTL cases, the first dwol buffer must be 3734E97@n onentry. ‘SHLP entry point with: ‘ACK: WORD function number (0000h-000Ch) Some functions have an additional DWOR argument pushed before the mandatory WORD argument STACK unchanged si,di,bp,ds preserved bx corrupt FSHLP function 00h Call IFSHLP function @1h with STACK: OWORD address of trap WORD @001h (function "Set Trap") Return: dx:ax = 0000:0000 suc 0000:0001 failure (trap already set) Dx,0x s corrupt
Notes:
The trap routine suppliedby the IOCTL caller will receive contro) when interrupts 8h, 17h, 21h, 2Ah and 2Fh occur in circumstances that IFSHLP considers interesting Ints 21h a 2Fh are hooked trivial (a simple far jump to the previous handler replaces the first five by tes of the 111 handler) when IFSHLP.SYS is installed. This cal] non-trivialises those handlers by restori the first five bytes Ints @8h, 17h and 2Ah are hooked when this CTL call fs made.
f the byte at offset 11h in the table given by IOCTL t 0 set. When the rap routine is called, al registers are as they would be had the routine got contr directly, except for bx, whose original value is on the stack, underneath a default trap would therefore be to POP BX then IRET interrupt return ddre:
least, that’s the gen ral principle (there are some exceptions, but this is complicated enough already). This list is not meant t suggest that IFSHLP traps
Unauthorized Windows 95
all conditions of the type given, just that if the trap is called with a particular value in register BX, then the reason is described as follows: bx < 0069h 0076h 3].u.CALLBACK.cal back:
printf(*\nV86 and PM callbacks:\n") printf("BP # Callback Ref Data printf(* -
mM
va6 -
v86_seg = first_v86_bp_s v86_ofs = first_v86_by pm_ofs = 0x200; (i=0, cbs ptab; iu.V86.FF I= Oxtf) if (cb->u.CALLBACK.cal1back continue; // skip blanks -BOBIX OB1X printf("s04x cb->u.CALLBACK.cal Iback, cb->u. CALLBACK. refdata vB6_seg, v86_ofs, pm_seg, pm_o if (cb->u-CALLBACK. callback
OAK: BO4X
OAK: BOA",
api_cb_addr)
DWORD far *fp = (DWORD far *) map_linear(cb->u.CALLB .refdata, sizeof(OWORD)
Chapter 8: The Case ofthe Gradually Disappearing DOS f (1 fp) fail(*Couldn't map API callback addr"); printf(" -> $0B1X", *fp): / show actual API callback addr free_mapp inear(fp) printf("\n");
) if (ctrl_c_hit done:
free_mapped_linear(cb_tab); return 0
// call the Windows "Get Device Entry Point Address" function Interrupt 2Fh Function 1684n
FP GetVxDAPI(WORD vxd_id) _asm | push di push es xor di, mov es, mov ax, mov bx, int 2fh mov ax, mov dx pop es pop di
di di 1684h vxd_id di
/ return value in DX:AK
fipragma pack(1 typedef struct WORD rp WORD ti: 1 WORD index 13; struct { WORD Timit BYTE base_hi, | DESCRIPTOR
limitrts_hi, bas
// Global Descriptor Table (GOT) register typedef struct | WORD limit; OWORD base; | GDTR
Unauthorized Windows 95
ESCRIPTOR far *get_gdt (WORD *plimit) void sgdt(GOTR far pq static DWORD get_desc_base(DESCRIPTOR far *desc) static DWORD get_desc_limit(DESCRIPTOR far *desc) OWORD GetGOTSelec Base(WORD seg ( SELECTOR sel = *((SELECTOR *) &seg): DWORD base H GOT elt WORD gdt_limit; PTOR far *gdt = fgdt_limit if ((seg & ~B) > gdt_limit fail ("Invalid Gi selec base = get_desc ase(&gdt[sel .index]) mapped_linear(gdt) base urn basi
// LOT: oh what the heck GetSelectorBase(seg);
it for them
TSelectorLimit(WORD seg SELECTOR sel = *( (SELECTOR *) &seg); OWORD Timit: if (sel.ti 0) eoT
WORD gdt_limit; DESCRIPTOR far *gdt = get_gdt(&gdt_limit): eg & > gdt_limit)
amit = return limit
what the heck, get it for them )
when done, free with freemapped_linear RIPTOR *get_gdt(WORD *plimit) DESCRIPTOR far *gdt: GOTR gdtr WORD se * get the linear base address and size (limit) of the 6 Descriptor Table (GOT), using the Intel SGOT instruction */ sgdt(ag oR *) map_linear(gdtr.base, gdtr.limit + 1); if (1 gdt ‘ouldn't map GOT!"); *plimit limit rn gdts
Chapter 8: The Case ofthe Gradually Disappearing DOS
void sgdt(GOTR far *pgdtr) { _asm les bx, padtr _asm sgdt fword ptr es:[bx] ) DWORD get_desc_base(DESCRIPTOR far *desc) return ((OWORD) desc->base_xhi base_lo; DWORD get_desc_limit(DESCRIPTOR far *desc)
DWORO limit = ((DWORD) (desc->limitrts hi & OxOF) 1imit_lo if (desc->limitrts_hi & 0x80) —// page granularity imit *= 4096; return limits
I wish I hadtimeto explain exactly how WINBP works, such as howit calculates the MaxBPs= value and howit relates V86 breakpoints to V86
callbacks, but this would take manypages. Well okay, let me just give you
the formula used to calculate MaxBPs: pm_api = GetVxDAPI(5); rLimit(pmseg) +1;
ox100
// get any PM callback i i ment. (38h) // get segment size
J get MaxBPs=
Calling INT 2Fhfunction 1684h (GetVxDAPI) in protected mode will return a PMcallback. All we’re interestedin is the segment. All PM
callbacks come outof the same segment, andthesize of this segmentis directlyrelated to the MaxBPsvalue. It would benicetogetthesize of this segment with the GetSelectorLimit Windows API(or its DPMI
equivalent, INT31h function 8). However, these work only with the Local Descriptor Table (LDT), and this segment’s selectoris
in the
Global Descriptor Table (GDT), so WINBP.C supplies its own GetGDTSelectorLimit and GetGDTSelectorBase routines (WINBPuses the non-privileged SGDTinstruction to access the GDT). Each PM
callback is two bytes (an INT 30hinstruction is CDh 30h), so WINBP divides the segment size by two. It then subtracts 0x100, becauseVMM alwaysreserves that amount (see Chapell, DOS Internals, p. 71). If you run WINBBP, it spits out a few statistics: V86 breakpoints @ O0OFEOAZh (*chnologies Ltd.') ih PM breakpoints @ C4
Unauthorized Windows 95
768 (0300h) MaxBPs First V86 BP FBOd 3002 86 BP = FE04: 0002 Last BP table @ Ca1DB000h Tr’s also useful to run WINBP when SystemROMBreakPoint=off: V86 breakpoints 2 0001D6C0h ('c") ints @ C41 0C800h 768 (03h) A6 3000 aoe
If you run WINBP -VERBOSE,it prints out all V86 breakpoints and all V86 and PMcallbacks. It's useful to run the outputthrough the VXDNAMEutilityso thatinstead ofaddresses suchas C00735ACh, you can deal with addresses such as IFSMgr+4BOh. Forexample: V6 Breakpoints BP # —V86 addr
Repl
CB #
aaoce: 5 00010734 00010731 oooin720 00010733 010721 001072: 00000953, OO01DAFC QO01DAFS 00010400 00010406 aooine0c
90 98 99 FF 90 90 90 90 90 90 90 90. 0
Q0cA ace act 00C0 00BF a0BE
02F1 o2re 02F3
V86 and PM callbacks Bp # Callback
SHELL.10+01C Ve6MMGR.9+000 VBEMMGR.3+1314 VE6MMGR.3+2777 VB6MMGR.3+12F5 V86MMGR.3+12E@ VA6NMGR.3+12¢4 388 54 12E
VMM.9+264 VMNE2248 vMM+2268 VMM. 24088
aocs
LFSMgr+4B0 0000000
cose0003 ooeooooe 02000000 oeo0e000 gaoae000 00000000 0000000 oa000a17 00000000 oaonoo0e 0000000 0000000 e0a00e00
8 v86
0000 000 ne2 a03—
VM+32E4 VNN+32E4 N3ZE4
Data
PM, 0038:0200 0038: 020: 0038:0204 0038:0206
MM+0044 vPIC vTD+3 voo+4 vMous' 10S+1A98. OSMGR+1C8 ELL+9E8
0038:0
0038: 0038 0038
Vii#1A11 PIco+FEs VT0.3+000 voo+2044 VMOUSE. 247 I 241864 OSMGR.12+000 24005
Chapter 8: The Case ofthe Gradually Disappearing DOS oe OOEE O0E ooo 00F1 oor2 00F3 oor oor OOF6 OOF? OOF8 OOF9 OFA OOFB OFC
VPOWERD+34 2132 VXDLOR+084 2122 vcomme2cc aul CONFIGMG+30C 22102 NABLE+3§ 20F2 NO+060 2082 VXDHLEC 22002 IFSNgr+2C18 FBFB WINICE+24F28 FBF9:2 VMM+32E4 VSHARE+3FCFBFA VMM+32E4 VCACHE+5DCFBFB:2 VMM+32E4 VFINTD+25C FBEC VMM+32E4 VXD+320 FBFD=21 VMM+32E4«CR3¥050 FF VMM+32E4 —-PSVXD+80C —FBFF: VMM+32E4 VTD+340 «F082
0038: 0038 0038:
> > > > > > > > > > > > > > > >
VPOWERD. 2+000 VXDLOR,3#1¢9 VCONM. 24148 CONFIGNG. 3+008 ENABLE. 242C4 VCOND.2+000 DsvxD+057 C VSHARE+290 VCACHE+520 VEINTD+022 vxD+OzA cR3+002 PSVXD+0E3 vT0.3+000
Thefirst section shows V86breakpoints. For example,recall the earlier quotation from the DDK documentation abouthowthe V86MMGRV3xDuses a V86 breakpoint to take over XMS. Now that we
have WINBB,it’ easy to see how this works.First, use a debugger to call INT2Fhfunction 4310h (Get XMS Driver Address) and walk the XMS
handlerchain (see Chappell, DOSInternals, pp. 505-512, for a good explanation ofthislittle-known aspect of XMS): C:\>symde + 4310
bs=7¢00 7c@0:0103 cD: F
0000 0 $5=7C00 CS=7C00 INT 2
BP-9000 SI-0000 D1-0000 NV UP ET PL NZ NA PO NC
BX-OOCF CX=0000 DX=0000 SP=82E2 BP-0000 Si-o000 DI-0000 NV UP EI PL NZ NA PO NC C5=7C00. £9=0313 95 7C0D:0105 0000 ADD [BX#S1] AL DS:@0cF=00 u es:bx 0313:00CF EASSO06FID JMP_—«106F 0045.
u 1d6f:45 1D6F:@045 EB03 106F 0047 90 1D6F :0048 90 1D6F 0049 90 1D6F:004A 63
004A IMP NOP Nop NOP DB 63
There’s ARPL (which SYMDEBoutputs as DB 63) at 1D6F:0044. 1D6F0h+ 4Ah = 1D73Ah. Sure enough, WINBPcantell us about this V86 breakpointat linear address 1D73Ah:
Unauthorized Windows 95
IW\WINBP>wi 0001073A
0
| grep 1073A caz39eBC 00ene000
se | grep 1073A vxdname C: \UNAUTHW\WINBP>winbp o2F2 0001073498 2 VBEMMGR.9+000 onddd000 What all this means is that there’s a V86 breakpoint on 1D73Ah (we
knewthat!) corresponding to V86 callback 90h, thatARPL replaced the byte C2h, and that C0239EBCh (or offset 0 in segment 9 of V86MMGR)is the XMS handler.
Nowwecan put a breakpoint(a debugger breakpoint, I mean) on C0239EBCh, do something that uses XMS, and see if the breakpoint is
triggered. I ran the DOS MEMutility, which amongotherthings reports the amountofavailable XMS memory. Sure enough, the breakpointin
V86MMGRwastriggered,and I couldsee a variety of XMScalls coming into V36MMGR. For example, there wasa call to XMS function 6 (Local Disable A20),
followed by one to XMSfunction 5 (Local Enable A20). On receipt of these XMS calls, V36MMGRturned around andcalled theVMM_
MMGR‘ToggleHMAservice. Actually, these two calls have nothing in particular to do with the DOS MEMutility; for reasons we don’t have
timeto getinto here (but see Chappell, DOSInternals, pp. 207-209), DOScalls these functions wheneverit loads an executable.
Thesecalls,
fromdeepinside the DOSkernel, end up being servicedin 32-bit protected mode by LMMGR_ToggleHMA.
MEMitself called XMS function 8 (Query Free Extended Memory). ‘To service this call, V36MMGR in turncalled PageSwap_Get_Version,
PageSwap_Test_IO_Valid, and _PageGetAllocInfo. Once again, DOS ends
up calling Windows.
Neat,let’s look at the V86 and PMcallbacks section of the WINBP output. Muchearlier in this long digression on V86callbacks, the
VXD86APIprogramrevealed the presence of some V86 VxD APIs: 0001n 001sh o027Th
—FBE:2 FREF:2 —FRF2:2
code that services the V86 VxD API request. Instead,there’s nothing at these addresses but ARPLs. (In fact, as we saw,it’s all the same ARPL at the is the actual code that provides VMM'°s or DOSMGR’s or VXDLDR’s V86 API? Just search through
WINBP’s output for an address such as FBE9:21B2 or FBEF:2152, and
you'll find the location where the 32-bit protected-mode coderesides:
Chapter 8: The Case ofthe Gradually Disappearing DOS
QOES OOEB
OOEE
VMM+32E4 VMM+32E4
VMM+DC44 DOSMGR+1C8
VMME32E4
FBE9:2 2 FBEF:21 52
—VXOLORH084FBF2:2 2
0038:03CA 0038:0306 0038:030C
-> VMMEIALL => DOSMGR.12+000 -> VXDLOR.3+1¢9
Let's look briefly at DOSMGR.In Chapter 4, we saw that DOSin certain situationswill call function 1 (Set Focus) of DOSMGR’s V86 API. Examining the code at DOSMGR.12+0(here located at C023DADOh), we see DOSMGRtakingthe function numberspecified
in AX,andusingitto indexinto a table of functionpointers: ru c023dad0 0028:C023DAD0 0028:CO23DAD4 0028:C023DA09 0028:CO23DADB 0028:COZ3DAE2
~MOVZX CMP JAE CALL RET
EAX,WORD PTR CEBP.Client_AX] AX, 06 C0230 [C020 380CAX]
Wecan use the PROTDUMPutility to examinethis table; the CMP
EAX,06tells us that DOSMGR’s V86 API supports six functions: C:\UNAUTHW\ PROTDUMP>protdump c02c380c -dword c02c380c | CO23DAEE Co23DAFD COZ30807 Coz30B24 CO2C381C | CO23DB3D CO23DB42
Thecode that DOS sometimescalls for function 1 is quite simple; it basically just calls the VMMSystem_Controlservice with AX=0Fh: 2 cO23dafd 0028:C823DAFD CALL (0238524 0028:C023DB02 AND «©—BYTE PTR [EBP#+2C],FE 0028:C0230806 RET 24 00230524 0028:C0238524 0028:C0238529 0028:C023852B 0028:C0238520
MOY XOR XOR INT
——~EAX, 0000000F «EDK, EDX ——=ESI,EST 20 VXDCall System Control
System_Controlsends a control message to every VxDin the system. Message OFh is Set_Device_Focus. If EDXis zero(asit is here), a// VxDs receive the focus. Incidentally, there’s a nearlyidentical function, INT 2Fhfunction 168Bh, that uses System_Control Set_Device_Focusto set the inputfocus to a specified VM. David Longdiscussesthis functionin detail in an excellentarticle, “T'SR Support in Microsoft WindowsVersion 3.1,” on the MSDN CD-ROM. According to Long, “This service
has someinherentrisks” whensetting the focus to a windowed DOS box because the keyboard and executionfocus are set to the specified VM,
but (because the DOSboxis windowed) the display and mouse focusare set to the System VM.Long’article includes “some rainy-dayexperiments you can performwith SetFocus in the privacy of your own home.”
Unauthorized Windows 95
At any rate, MS-DOS'’s call to DOSMGR,madevia an ARPLinstruc-
tion, endsupcalling System_Control Set_Device_Focus. Repeatingthe
point made in Chapter4, the fact that DOScancall Windowsis an excellent example of howthe old “Windowsruns on top of DOS”description was neververyuseful. Poppingback to our IFSHLP example,after this long but necessary digression about Windowsbreakpoints andcallbacks, let’s see what WINBP can tell us about that ARPL located at FBCA:23A2 wayback in
Figure 8-12:
: from trace in Figure 8-12 FBCA:2342 ARPL —-[BX+S1+6E], BP
: from WINBP | VXDNAME 0C6 §=—TFSMgr+4B0 00000007
ts: VB6 callback at FBCA:23A2
FACA:23A2
0038: 038C
Sure enough, WINBPtells us that when IFSHLP executes the ARPLat FBCA:23A2, it will call into IFSMgr+4B0, just as we saw in Figure 8-12. Ta-da!
Nowthat IFSHLPhaspassed the INT 21h function OBhcall up to IFSMgr, IFSMgrdeals with the upward-reflected INT 21h call in what-
ever wayit sees fit. In somecases, IFSMgrwill absorb thecall in 32-bit protected mode.In othercases, IFSMgrwill wanttoreflectthe call back down to the DOS interrupt chain in V86 mode. Of course, it does no
goodto sendit back downto the head of the INT21h chain, because then IFSHLP will see it again. IFSMgrneeds to send the call to the
INT21h handlerthat wasinstalled before IFSHLP.In Figure 8-12, you can see IFSMgrgetting readyto dothis by passing the previous handler’s segment:offset address to the Build_Int_Stack_Frame service. IFSMgr
knowsthe address of the INT 21h handlerinstalled before IFSHLP because IFSHLP keepsthis addressin a table;it gives IFSMgra pointer to this table.
TFSMgr nowreturns to VMM, which eventually does an IRETD.But instead ofreturning to whatever V86 code originallyissued the INT 21h that got us started on this whole mess, the IRETDinstead “returns” to
the address that IFSMgr passed to Build_Int_Stack_Frame. This takes us to the INT21h handler installed before IFSHLP. Even when an INT 21h
call is sent down to DOS(as happens with the DOS box’s frequentcalls to
function OBh), the call often bopsback into VxD-landfor some handling. To makea ridiculouslylong story short, one role for IFSHLP.SYSis to preventcertain reflected INT21h file calls from reaching DOS.
Geoff Chappell hasputit:
Chapter 8: The Case ofthe Gradually Disappearing DOS Int 21h etc. can bereflectedinto the VM, knowing that IFSHLPis there to wrest control backto ring 0 beforeit reachesthe nasty,ugly, old DOSkernel. IFSHLPis the cutoff: everything that hooks int 21hafter it gets supported, everythingthat hooked before IFSHLPgets replaced.
IFSHLP.SYS wears severalother hats, including keepingsimulated INTL (seethe “Replacing Real-Mode Code:It’s Not New”section laterin this chapter) from reaching DOS. IFSHLPSYSalso hooks several other interrupts besides INT 21h, including INT 08h,17h, 2Ah, and 2Fh. Figure 8-13 presents a schematic view of the path taken by a V86 INT 21h call in Chicago. INT 21h in 00S program => VN > VB6 hook int chain => . (other VxD INT 21h hooks, 1ike VMPol1 and SHELL) > TFSMgr if (VM hooked INT 21h via 21/25)* -> local INT 21h hookers (such as TEST21) > global INT 21h hookers (such as VB6TEST) > IFSHLP. SYS => (via ARPL) ¥MM > TFSNgr if (file function that IFSMgr emulates) emulate it else pass to V86 handler underneath IFSHLP ‘This is the test IFSMgr use , but it probably ought to instead be if (INT 21h vector != original IFSHLP.SYS INT 21h vector) Figure 8-13:Thepath of a V86 INT 21hcallin Chicago.
Oneimportantpoint: The TEST21 results back in Figure 8-10 showedthat even with INT21h calls reflected to INT 21h hookers, 32BFAis still significantly faster than letting DOS handle the file I/O. In addition, whereas TEST21 -MYSETVECT3000 > FOO.BAR took 12 secondsin onetest under Chicago, TEST21 3000 > FOO.BAR(without
-MYSETVECT)tookonly3 secondslonger. I was quite surprised by
this, and I asked Geoff Chappell what he madeofthe fact that reflected INT 21h calls, blocked and rerouted by IFSHLP, werenearly as fast as absorbed INT 21h calls. Here’s his explanation:
Well, yes, | expect it to run nearly as fast. Thereflection of interrupts into VMsis not likely to be a serious delay in the overall context of DOSoperations. 32BFA picks up its performance gain by replacing the DOS kernel, which as we know executes large tracts of codein critical sections and, worse, sees toits device driver calls one at a
time, always waiting for completion. True, write-behind disk caches help out with this last matter by making it seem like the device driver has completedquickly — but
Unauthorized Windows 95
this works only for write operations, whichare relatively infrequent compared to reads (for which waiting is inescapable). Bynow,youno doubtfeel that Windows95’s solution to the “support DOSTSRswithoutcalling DOS”problemis far from ideal. Whyall this complexity?It’s interesting to contrast how Microsoft handled the equivalent problemin 32-bit disk access (32BDA). Just as 32BFAbypasses DOSforfile-related INT 21h calls, 32BDA bypasses the BIOS for INT 13h direct disk access. And,just as with
32BFA, Windows must somehowtryto support INT 13h hookers and yet
still keep INT13h calls away from the BIOS.But, in contrast to INT 21h andthe situation with 32BFA,thereis a simple solution for INT 13h: The
V/O Supervisor (IOS) VxD,previously known as BLOCKDEY, uses an undocumentedcall, INT 2Fh function 13h, which manipulates the INT 13h chain underneath IO.SYS’s handler. This functionis described in greatdetail in Geoff Chappell, DOS Internals, pp. 57-95(also see the DDKdocumentation for the Int13_HookingBIOS_Intand Int13_ Unhooking_BIOS_Int services, which IOS/BLOCKDEYVcalls when
manipulating the INT 13hchain). Figure 8-14 showstheroutetaken by an INT13h call under 32BDA. INT 13h in 00S program > NM > VFO (Virtual Floppy Device sees if it's INT 13h for a floppy) > BLOCKDEV/10S >-any IN hook in DOS -> > Handler installed with INT 2Fh function 13h BLOCKDEV/10S Figure 8-14: The path of an INT 13h with 32-bit disk access. Incidentally, this form of INT 13h handling means that if we wanted to write a TEST 13 programto showoff 32BDA,similar to TEST21 for 32BFA, we couldn’t just hook INT13h. We would have to use INT
2Fh function 13h. Unfortunately, MS-DOS doesnotinstance (see
Chapter 4 oninstance data) the INT 13h hookfunction pointerit keeps at 0070:00B4,and so calling INT 2Fh function 13h under Win-
dows makes it blow up. Once again, I asked Geoff Chappell aboutthis.
Here’s his response:
Yes, it is as simple as having Windowsinstancethe pointersin !0.SYS. Really,| think 10/MSDOSshould dothis via 2F/1605.... If you want to write a VxD to support 2F/13 being used bya VMtoinstall local code as an int 13h handler under 10.SYS, then you musteither know/determine the addressesofthe relevant pointers (see
Chapter 8: The Case ofthe Gradually Disappearing DOS 10S.386for an example of how to test the assumptions about 0070:0080/0106 and 0070:00B4)or hook 2F/13in the V86int chain (and then confront the complicated problem of emulatingtheinterfaceas if it had beenlocalall along). | claim that doing all this is Windows’ responsibility, precisely because a program using 2F/13 in a VM cannotarrangeonits ownfor the interface to be usable.
Especially since Windows95 sports a supposedly newversion of DOS (WINBOOT.SYS),it’s a shame that INT 2Fhfunction 13h can’t be safely called within a Windows DOSboxandthatthereis no equivalent INT 2Fhfunction 21h interface to manipulate the INT 21h chain.In the absenceofsuch a function, IFSHLP.SYSacts as sort of a DOSequivalent
to INT 2Fhfunction 13h. Here’s Geoff Chappell again:
IFSHLP’sonly possible claim to existenceis to terminate the int 24h chainin virtual machines. 32BDAaimsto replacethe BIOS's int 13h handling, much as 32BFA aimsto replace DOS’sint 21h. The endof the int 13h chain,thatis, just before it whizzesoff to the BIOS,canbelocatedeasily, albeit through an undocumentedinterface (int 2Fh function 13h). There is no obvious wayto find the end ofthe int 21h chain, thatis, just beforeit reaches the DOS kernel. Thisis theonly sensible role for IFSHLP. Some Microsoft developerofferingsilly excuses for WfW 3.11claimedthat the choice wastoreflect alwaysorto reflect never — and that Microsoft was indeed attending to concemsbyoffering the choice to enable/disable 32BFA.
Instead, whenthey get the interrupt in ring 0, they should lookat the V86 int vector: if it hasn't been hooked away from IFSHLP, then sure,it would only hit performance to reflect, but if someonehas hookedit, then they can reflect into the VM and support the old softwarefor thepriceof a slight hit.Instead,they've presentedtroubled users with a stark choice betweentheir old driver/TSR or the wonderful new 32BFA. | wouldn’t putit past some people in Microsoft to have thought that the presumably shortlived WiW 3,11 could notonly keep the market interested while Chicago was being developedbut could also accelerate the death of these awkward DOSdrivers/TSRsandthereby give the Chicago developers less to worry about. You know something,| think they've very nearly gotten away with it, too.
Certainly, Microsoft does wantto move developers awayfrom TSRs and towards VxDs. For applications that needto track file access in Windows 95, IFSMgrprovides a new FileHook API, whichcan only be called
(directly, at any rate) from a VxD.
In truth, 32BFA in WfW3.11 appears more and moreto be apre-beta
test for Windows 95. Microsoft's ads for WfW3.11 said that the product
was “powered by32-bit technology fromour ‘Chicago’ project.” Given that Chicago wasnoteven in alphatesting at the time,this should have producedat least some concern aboutthestate of the 32BFA code in
WEW 3.11, as should the description string “Win386 HPFS Driver (Pro-
totype)” in the WFW 3.11 commercial release of VFAT.386. Prototype?!
Unauthorized Windows 95
Now,puttingpre-alpha Chicago 32BFA code into WEW3.11 was a great waytoget millions of users banging on the Chicago code. Butit’s notclearthat these users should have had topay for Microsoft’s prototype code, especially when the standard Microsoft response to any complaints about 32BFA in WfW3.11 wasthat the user should disableit. As one Microsoft representative put it in the WINSDKforum on Com-
puServe, 32BFAis “a nice feature, IMHO[in my humbleopinion], but it is kind of a caseof‘if it interferes with your life, disable it.” This was
Microsoft’s major shipping version of Windows atthetime.Infact, as I write this, WfW3.11 withits prototype version of 32BFAisstill
Microsoft’s majorshipping version of Windows.
O2BFA and Networks, CD-ROM, and Floppies Youmay by now,have a naggingfeeling about the TEST21 results we've spentso longporingover. Although we've run TEST21 in a numberof
environments — plain-vanilla DOS, DOS with a disk cache, WfW 3.11 with 32BFA, and Windows 95 — all of our file access has involved a hard
disk. Earlier, we did compare
32BFAon a DblSpace and non-DbISpace
(host) drive, but we haven't saidanything about other media, such as floppydisks, CD-ROM,RAMdisks, and most importantof all, networks. First, 32-bit networkfile access bypasses DOSin the same waythat
32-bit disk file access bypasses DOS. Under WfW3.11, the message
“Some INT 21h are handledwithout calling DOS!”is produced both by Tested punniig on a network server that’smung Windows.NT GoneWwEw 3.11 machine.
Should this comeas anysurprise? Onthe most prevalent networks for
the PC, NetWare 2.x and3.x, workstations run the NetWareshell,
NETX, which hooks INT 21handlargely replaces large chunks of DOS (see Undocumented DOS, 2ded., pp.-195-205). You wouldexpect network file access to bypass DOS. But the NETXapproach ofhooking INT21h ahead of DOS, while typicalin the sense that NetWareis the dominant PC network,isn’t typical
whenyoulook at the whole range of PC networking software, including
NetWare4.x. Rather than hooking INT 21h, workstation shells for DOS are supposedto use the undocumented but well-known Network Redirectorinterface (see Undocumented DOS,2d ed., pp. 494-540, 769-783).
Chapter 8: The Case ofthe Gradually Disappearing DOS ‘Theredirector operates underneath DOS: programs make INT 21h file I/Ocalls to MS-DOS, andif thecall is intended for a network drive, DOS generates an INT 2Fhfunction 11h. Redirectors hook INT 2Fh,
look forcalls to function 11h, and handle various subfunctions, such as 1108h (Read from RemoteFile), 1109h (Write to RemoteFile), 111Bh
(Find First RemoteFile), and 111Ch (Find Next RemoteFile). The redirector generally sendsthis request over the network to another machine,
waits for the response, and returns from the INT2Fh. DOS thenpasses the information back to whoever madethe original INT 21h call. So, with 32BFA on network drives, we might have expected to see
INT 21h calls passed onato DOS, with netwwork 32BFA aly ee not howit works, ateast for network ee
Microsoft's CD-ROMExtensions (MSCDEX) also use the redirector interface, and if
MSCDEXis loaded before WfW3.11, IFSMgrpasses
down all INT 21hcalls (except attemptedfunction 40h writes) involving the CD-ROM drive. The INT 2Fh function 11h calls that DOS gener-
ates whenit receives an INT 21h for a CD-ROM drive (or any redirector drive, for that matter) are also passed down. Curiously, in 32BFA under WfW3.11 (but not in Windows 95), hard disks are markedas network redirector drives. IFSHLP.SYS has an INT
2Fh handlerand canship redirectorcalls over to IFSMgr, which also has an INT2Fhhandler. This should all change in Windows95, which has a
CD-ROMVxDdriver that is supposedto replace MSCDEXby providing 32-bit protected-mode CD-ROMaccess. (Actually, you canget that today without Windows95 by using the Cloaked version of MSCDEX
that comes with Helix Software’s Multimedia Cloaking product.
Returningto 32BFA ona truenetwork drive (as opposed to CD.
ROMdrives, whichMSCDEX pretendsare networkdri
tant to understandthat applicationsstill use INT 21hcalls.
mpor/indows and
Win32 applications — both in Windows3.x and in Windows 95 — use the INT21h interface either directly with an INT 21h or a DOS3Call or indirectly with a Windows API functionthat in turn uses DOS (such as the CommDlg functions GetOpenFileName and GetSaveFileName). Anticipating somewhat the WV86TEST and WSPY21 programsdis-
cussed in Chapters 12 and 13, note that Windows applications accessing
files, seuanesfiles onthe network, think they’re ce DOS. For exam-
Teeseee GriDis eis including thefollowing:
Unauthorized Windows 95
(51) GET PSP (2f) GET OTA TA 4CCF:79DA (50) SET PSP Q0a7 ) FIND FIRST \\T_NEUHAUS\TRUDY\MSS\ANDREW\DIRTYWIN\ JUNK. DOC (3d) OPEN E:\MSS\ANDREW\DIRTYWIN\JUNK. 00C
Similarly, MS Mail uses INT 21h to access post-officefiles on the server (which here happenedto be running Windows NT): signature, SIGNATUR
* hook INT 21h and INT 2Fh * ald _dos_getvect (0x21 _dos_setvect(Ox21, int21): old_2F = _d vect (Ox2F etvect (Ox2F, int2f): spawnvp * unhook INT 21h, 2Fh ney 5 dos_setvect (0x2 isplay_results(fpstat
. fargvtl]):
@
nih
Chapter 10: How Windows Runs DOS
k_state(i
intno, int ah, int al,
int bx)
dealls[statel++
if
WINLINIT_DONE)
/* The following is a little confusing. V86TEST is normally able to make Windows INT 2Fh calls (such as vmid()) from inside an INT 2fh handler, wit sing an endless loop, because V¥M gets these INT 2Fh calls and doesn't reflect them back to V86 mode. Thus, V86TEST mode's INT 2Fh handler never sees calls such as 2F/1680 and 2F/1683. However, it's useful to test VB6TEST with programs other than Windows, such as FAKEWIN In this case, the 2F/168x calls would wind up right back at V8ETEST, causing an endless loop if called from inside the INT 2Fh handler. So if genuine Windows V¥M isn't running (as determined by the 2/1680 call), V86TEST doesn't call 2F/1683 2F/1680 is called just once; logging is turned off for that one call to prevent an endless loop if something other than Windows VM is running. */ int cur_vm: tatic int atic int is if (logging = else if (is_win
Oxff) / one-time init
ogging 0: win = win3é(): ogging = 1: cur_vm =
(is_win) 2 vmid()
0
tats->vmE(cur_vm < VMLMAX) ? cur_vm VM_OTHERI+; only collect this while Windows running! stats->iopl_countLiop) (++:
j if Cintno == 0x21)
ts->int21Lah]+ f (intno Ox2f) ahlt+:
Unauthorized Windows 95
stats->int2flétal +: if (al == 7) / 2f/1607/18 is most popular (VMPOLL) stats->int2f1607[(bx < x100) ? bx VXO_OTHER]+:
void interrupt far int21(REG_PARAMS r) )
check_state(Ox21, r.ax >> 8, r.ax & Oxff, r.bx); _chain_intr(old);
void interrupt far int2f(REG_PARAMS r) switch (r.ax) case WIN_INIT_NOTIFY:
state = WIN_INIT_BEGI break; case WIN_INIT_COMPLETE: state = WIN_INIT_DONE; time(astats->start); break: case WINEXITBEGIN: state = WINFINI_BEGIN; time(&stats->end) ; brea case WINEXIT_NOTIFY: state WIN_FINI_DONE; break: res FP_SEG(fpstats); case GET_STATS r.bx = FPLOFF(fpstats); break;
1 // -FILTER option ignores 2f/1607/18 (VMPOLL) if (not_filter | (r.ax != @x1607 && r.bx != 0x18) check_state(@x2f, r.ax >> 8, r.ax & Oxff, r.bx); _chain_intr(old_2F);
Since the goal of V86TESTis to demonstrate that Windows calls DOSin V86 mode, it doesn’t make sense to run V86TESTif the machineis already in V86 mode. All interruptcalls would be in V86 mode anyway, whether or not you ran Windows, so V86TESTwould reveal little about the Windows-DOSinterface. Therefore, V86TESTchecks the PE bit at startup. If the PEbit is already set (probably because you're running undera 386 memory manager such as EMM386, QEMM,or 386MAX), V86TESTdisplays an error message andexits. Except whenhandling the -VERBOSE and -CLEARcommand-line options discussedin the next chapter, V86TEST also fails with an error messageifyou're alreadyrunning under Windows. An interesting alternative mightbe for V86TESTtoforce the machine from V86 modetoreal mode and then spawn Windows, but this is more
Chapter 10: How Windows Runs DOS
complicatedthan it sounds(see the “Switching from V86 modetoreal mode”sidebar). Because the next chapter uses V86TESTfor a somewhat different
purposethan detecting the mode in which Windowscalls down to DOS,
V86TESTalso provides an -OKV86 switch that forces the program to run evenif the processoris already in V86 mode.
Switching (rom VBG mode to real mode If the machine is in V86 mode when V86TESTstarts up andif the user hasn't specified -OKV86,the program fails with this error message: Already in V86 mode test would be pointless Remove 386 memory manager from CONFIG.SYS and reboot
An interesting alternative would be for V86TEST to force the machine out of V86 mode and backto real mode before spawning Windows. Memory managers such as EMM386 and QEMM generally provide an OFF command-line option to disable the memory manager, soit seems like V8GTEST should beable to call somefunction in the memory managerto deactivate the memory managerand return to real mode. Indeed, Windows
itself must call such a function when it starts up. Windows Enhanced mode can’t switch to protected modeif the machineis already in protected mode (thatis, V86 mode). As seen in FAKEWIN in Chapters 3 and 4, the INT 2Fh function 1605hbroadcast allows an installed memory manager to give Windows the address of a V86 switch function.
Like FAKEWIN, V86TESTcould pretend to be Windows and issue an INT 2Fh function 1605hto get the address ofthe switch function. It could then call this function to switch from V86 mode back to real mode before spawning Windows.If the memory managerhas already been turned OFF, orif the switch function has already beencalled to disable V86 mode,the memory manager should return NULLforthe switch function address. However, the V86 switch function that memory managers return via INT
2Fh function 1605hisn't exactly like EMM386 OFF or QEMM OFF. Whereas those command-line optionsfail if the memory manager is currently providing UMBs (Upper Memory Blocks) or EMS, the V86 switch function just does what it's told and disables V86 mode. What this means, unfortunately, is that some key devicedriver or TSRthat has beenloaded high will suddenly becomeinvisible — and thisis likely to result in a crash. What does Windowsitself do in this situation? As shown in Chapters 3 and 4, the V86MMGRVxD in Windows uses a Global EMM Import interface to take over the memory manager's page tables. Rather than get into the
Global EMM Import business,it makes more sense for V86TEST — which,
after all, is just a test program — to simply fail if it detects that the
machine is already in V86 mode.
Unauthorized Windows 95
Asnoted earlier, V86TEST keepsstatistics that indicate how many calls it has seen and howmanyofthesecalls occurred in V86 mode rather than in real mode. Figure 10-2 shows some sample output from V86TEST;to increase the number of DOScalls, I temporarily disabled 32-bitfile access. (Actually, the /D:C switch to disable 32-bit file access
was unnecessary here, since redirecting Windows’ stdouttoa file will do that anyhow.)
C:\>v86test /D:C > v86test.1og C:\>type vB6test.1og Before Windows started: 109 INT 21/2F calls, @ in V86 m During Windows init 5216 INT 21/2F calls, 354 in VB While Windows running: 174712 INT 21/2F calls, 174 During Windows exit 13 INT 21/2F calls, 10 in V After Windows exiti 12 INT 21/2F calls, 0 in V86 While Windows running Windows active for 256 seconds 682 INT 21/2F calls/second 10) 2929 calls oP! - 171783 calls VW #1 135326 calls VM #2 39386 calls INT 2Fh AH=16h calls seen V86TEST: 00: 2 05: 1 06: 1 O7: 125887 08: 1
09: 1
OA: 2
OB: 2
BA
Figure 10-2: Sample output from V86TEST, a program that shows Windowscalls DOS in V86 mode. Thethirdline of the output in Figure 10-2 tells us that every one of the 174,712 INT 21h and INT2Fhcalls made while Windows was running occurred in V86 mode. No DOS calls occurred in V86 mode either
before Windows started or after Windows completedits exit procedure. It’s apparentfrom this figure that the switch fromreal mode to V86 mode occurs sometime during Windowsinit and that the switch back to real mode occurs sometime during Windowsexit. Well, that’s sensible enough. While Windowsis running, V86TEST,in addition to testing the PE
bit, also checks the processorflags to get the I/O privilege level (OPL) andcalls INT2Fh function 1683h (Get Current Virtual Machine ID) to
get the current Virtual Machine ID number (VMID).
You mightbe asking, nay, demanding: Howcan V86TESTmake
an INT 2Fhcall frominside an INT 2Fh handler? Thisis an excellent question, and the answergets to very heart of how Windowsexercises control over programsrunning in V86 mode. Staytuned forthe exciting explanation.
Chapter 10: How Windows Runs DOS
Butfirst, to understand the next part of the V86TESToutputin Figure 10-2 (the twolines showing numbersfor IOPL=0 and IOPL=3), weneedto take whatwill atfirst appear to be a detourto look at the /O Privilege Level on the Intel 80386 andlater microprocessors.It’s not a pretty sight, but here goes.
LOPL and the Interrupt Flag ‘The Intel 80x86 architecture has a dizzying array of protection and privilege mechanisms. Books onthe subject typically bombard the reader with
termslike Requestor Privilege Level (RPL), DescriptorPrivilege Level
(DPL), Current Privilege Level (CPL), and I/O Privilege Level (OPL). Oneofthe mostintelligent books on microprocessors,after the obligatory section onIntel 80386 privilegelevels, presents a sectiontitled “Is All This Worthwhile?” Theauthors observe, Theprevious section is virtually incomprehensible. You probably have to read it several times to understand it, and it is still easy to get the DPLs, CPLs, and RPLs hopelessly mixed up. No other commonly used microprocessors have anythinglike this protection complexity, and we canlegitimately raise the question of whether these features are useful and worthwhile (the Intel position) or represent design gone berserk (the position of many others). — Robert B.K. Dewar and Matthew Smosna, Microprocessors: A Programmer's View, pp. 95-96. I’mnotgoingto bore you with yet anotherdiscussion of the baroque privilege-level mechanismonIntel’s 80386, 80486, and Pentium micro-
processors. If you want, you can read aboutthis in the Intel manuals (or in manywidely available books that have been cribbed fromthe Intel
manuals) or in someofthe few genuinely good books on the subject, which I’ve listed in “For Further Reading.” But we do need to look at one aspect of this mess: the IOPL. ‘To sim-
plify matters somewhat(which I must do to avoid draggingin a discus-
sionofthe CPL), the IOPL determines whichinstructions a program
running in V86 mode can execute. If the I/O Privilege Levelis less than 3
(such as IOPL=0), programsrunning in a DOSboxcannotexecutethe followinginstructions: Instruction
Description
PUSHF POPF
Pushflags Pop flags
Unauthorized Windows 95
INT n
Softwareinterrupt
IRET cL stl
Interrupt return Clearinterrupt flag (disableinterrupts) Set interruptflag (enable interrupts)
You might wonder whatthesesix instructions have to do with each otheror with an I/Oprivilegelevel. Furthermore,since these instructionsare all commonly used in real-mode software, you might wonder what possible use there could be in a V86 modeconfiguration that runs real-mode software but doesn't allow execution of these instructions. ‘To deal with these points in reverse order (poppingthestack,asit were), let’s first dismiss any “cannot execute” concerns you mighthave. Wheneverdiscussionsof the Intel processors say that something “can’t
happen,”it just meansthatan exceptionis generated.Inthecase ofthese can’t-executeinstructions,all that happens is that a General Protection (GP)fault is triggered. In other words,if a real-mode program running in V86 mode with IOPL=0 generates, say, an INT 21hto call MS-DOS,
this triggers a GP fault. AGPfault?! That doesn’t sound verygood. GPfaults are what make Windowsdisplay its ominous-looking “Unrecoverable Application Error! Do Not Pass Go! Do Not Collect $200!” message boxes. How is generat-
ing a GP fault any different fromsayingthatthe instruction can’t execute? Relax: don’t get your knickers in a twist over GP faults. The GP fault
is really just an INT ODh. The protected-modeoperating system(such as VMM in Windows) will have an INT0Dh handlerthat will catch this GPfault and do with it what it wants. VMMcouldterminate the offend-
ingapplication, ignore theinstruction, emulate theinstruction, whatever. Soa real-mode program running in a Windows DOS box with IOPL=0. that generates, say, an INT 21hto call MS-DOS will trap intoVMM’s
GPfault handler.
This GPfault handler doesn’t necessarilydisplay an error message
and terminate the application. In fact, Windows’ GP fault handlers
almostnever respondthis way to GP faults. That’s because GP faults,
along with Invalid Opcode exceptions, are a normalandcrucial part of the underlying systemarchitecture of Windows, and VMM’s GPfault handler silently deals with many GP faults per second. Let’s return to what the six illegal instructions — PUSHF, POPE, INT n, IRET, CLI, and STI — have todowith each other. Whyare
theseinstructionsdifferent fromall other instructions? Because theyall affect the Interrupt Flag (IF). CLI and STI of cours
arand set IF, but
Chapter 10: How Windows Runs DOS
so can POPFand IRETin the course of poppingthe topofthe stack into theflags register. The PUSHF and INT (which doesan implicit PUSHEF)instructions don’tdirectly affect the flags register, but they are
symmetrical to POPFand IRET. (That’s not quite the real reason for their inclusion, but the real reason won’t make sense for a few moments.) Okay, then what's so importantaboutIF thatIntel would gotoall this trouble? As already notedat the end of Chapter9, all other things being equal,it’s a bad idea for protected-mode operating systemsto let a V86 processturn off the processor’s actual IF, because doingsodisables interruptsforall processes. If a program running in a DOSbox could freely
execute CLI or use POPF or IRETtodisable interrupts, it could disable interrupts for every other program too,including Windowsapplications and other DOSboxes. This would notbe good. So Intel gives protected-mode operating systemsthe option oftrapping these instructions. If IOPLvB6test -verbose /D:C > ve6 log \>type v86test. 10g Before Windows started NT 21/2F calls, @ in V86 mode During Windows init NT 21/2F calls, 362 in V86 mode While Windows running: 400183 INT 21/2F calls, 400183 in V86 mode During Windows exit: 13 INT 21/2F calls, 10 in V86 mode After Windows exited: 12 INT 21/2F calls. @ in V86 mode
While Windows running: Windows active for 275 seconds 1455 INT 21/2F calls/second TOP! 4384 calls TOPL=3 395799 calls
WM #1
400183 calls
NT 2Fh AH=16h calls seen by V6 00: 2 05:1 06 391147 08: 1 2th 153 1 5 6 7 7
09: 1
OA: 2
OB: 2
0D: 256 OE: 288 19: 81 1A: 409 2h: 492 2C: 2760 2F: 9 30: 22 6 344 3E: 245 3F: 1906 4 47: 86 48: 8 4A: 3 3 44051: 4 52: 10 55: 1 5F: 3 62: 99 65:
32: 40: 4B: 4 3
16: 391158 43: 7
7A: 2
4
15: 5
46: 1
4A: 7
18; 391133 21: 2
BA: 1
2 33: 6 3449 3 57: 125
FE: 2
vxO>#0100: 1
Figure 11-1: Taking a censusof INT 21h and 2Fhcalls from Windows; no DOSboxis. running.
Notice that although Windows madeplentyofcalls to INT 21h functions 40h (Write File), 2Ch (Get Time), and 42h (Move File Pointer), the overwhelming majority ofits calls were to INT 2Fh function 1607h,with BX=18h. Function 1607h is documented in the DDK as Device Call Out. VxDscan issue this call to communicate with software loadedbefore Windows; since V86TESTis loadedbefore Windowsand has caught these calls, we cansee that this works, The BX register holds the ID number of the VxD issuing the broadcast. The JMM.INCfile included with the Windows DDKlists many VxD IDs; it turns out that 18h is VMPoll.
Unauthorized Windows 95
According to VMPOLL.INC (alsoincluded with the DDK), this VxD issues the INT 2Fhfunction 1607h callout when Windowshas nothing
better to do:
:
Int 2Fh call-out API when system is AX = 160) BX = VMPol1_Device ID CK = VMPo11_Cal1_Qut_Sys_Idie
:
If TSR or device driver wants to "eat" the idle call, they should Set AX = @ and not chain to other Int 2Fh hooks. Otherwise, chain.
;
VMPoll_Call_Out_sys idle
£Qu
0
2k = 0
TSRsordevice drivers can hookthiscall to receive notification that Windowsis idle and perhapsuse this opportunity to do some background proces ing. VMPoll takes the function that makesthis callout and registers it with the V. AMCall_When_Idleservi 00_2F_1607_18: 00246 Push_Client_State cal :: set up VM for ¥86 mode ViMcal] Begin Nest_V86_Exec 00255 00258 mov word ptr [ebp.Client_EAX],1607h 002 mov word ptr [ebp.Client_e8 :: VMPoll_Device_IO 00267 mov word ptr Cebp.Client_| : VMPol1_Cal1_Out_Sys_Idle 00260 mov eax. 2Fh a0272 VWMeaT Exec_Int : uses Simulate_Int 002 mmo sword ptr Cebp.Client_e "eat™ idle call? 002: VWical] End_Nest_Exec ona! Pop_Client_State jecxz short IDLE_EATEN 0 ste :; VWwill call next idle callback 00294 retn 00295 IDLE_EATEN: 00295 cle $; YM won't cat] other al Tbacks 00296 retn 00_DEVICE_INT mov esi,offset 00_21 VWMical] Cal1_When_
Whenit decides that the systemis idle, VMMcalls the functionsin its call-when-idlelist, such as the function installed by VMPoll, andthe function the PageSwap VxDinstalls to asynchronouslywrite changed virtual-memory pagestodisk (_PageOutDirtyPages). VMMdecides the system is idle based oncalls it receives to INT 2Fh function 1689h (Windows KERNELidle). As Matt Pietrek explains in Chapter 6 of
Windows Internals, the idle loop in the KERNEL schedulercalls INT 2Fh function 1689h, thussetting offthe chain ofevents that eventually
Chapter 11: Who Needs DOS?
results in a VMPollcallout. KERNELalsocalls INT 28h, the DOSidle broadcast and, as one would expect, software loaded before Windows sees
about as many INT 28hcalls as VMPollcalls (see Figure 11-9 later in this chapter). As seenin the disassembly of VMPoll, the VxD makesthis broadcast using the Begin_Nest_V86_Exec and Exec_Intservices provided by ‘VMM. Exec_Int in turn uses the Simulate_Intcall, which consults the
low-memory Interrupt Vector Table (IVT) — assuming no VxD intercepts the interruptfirst via Hook_V86_Int_Chain. This is how Windows
makesall its calls down to DOS. Thus, although V86TESTsetout to
showthepossibility for VMMinterruptinterceptionvia the IDT, whatit really shows is VMMinterruptreflection via the IVT. Oddly, even though thetest in Figure 11-1 seemedto be exercising Windows(the Clock was running, and WinWord wasaskedto crank throughfour large documents), VMPoll generated over 1000idle broadcasts per second! These V86TESTresults make it seem as if Windows spends mostofits time twiddling its thumbs. But that’s not true: Sometimes people use WindowstoplaySolitaire. On a moreseriousnote, these figures probably do make somesense. During the sameperiod, even though Windowsappearedto be furiously busy, Microsoft’s power-managementdriver, POWER.EXE,reported that the CPU wasidle more than 25%ofthe time. Nowlet’s run thetest again, this time opening a DOSbox. There’s no
needto actuallydo anything in the DOSbox (whichis a good thing, since
it’s difficult to do anything in the DOS boxwhenits outputis redirected to V86TEST.LOG). Figure 11-2 shows the result.
Before Wind: During Window: running White Win During Windows exit: After Windows exited:
L INT 21/2F calls, @ in V86 352 in
While Windows running Windows active for 187 seconds t 107 INT 21/2F ¢ TOPL=0 2403 20477 lopL=3 197551 calls VM #1 9623 calls VM #2 INT 2Fh AH=16h calls seenby V
mode VB6 mode 4 in V86 mode
Unauthorized Windows 95
INT 21h calls 02: 93 16:4 34: 5 4: 6 ac: 7 58: 9
2319-47 4F: 1 50: 3 s0: 3) SE: 4
INT 2Fh calls QB: 1 11: 799.12: 6 ide Fkee Bie)
13: 4 SRE Sse
6c: 1
INT 2Fh AX=1607h calls 6: 1 QC: 2 10: 2 14:1
16: 190303 43: 9 18: 5
46: 1
18: 190278 21: 2
48:1
4A:
VxD>#O100: 1
Figure 11-2: A censusofINT 21h and 2Fh calls from Windows,with one DOS boxrunning.
Notice that there now are a large number ofcalls to INT 21h function OBh (Check KeyboardStatus). Furthermore, this number roughlycorresponds to the number ofcalls in VM #2. COMMAND.COMusesfunction OBh to poll the keyboard; V86TEST shows that Windowspasses these calls down to DOS. One waythat VMPoll detects idle VMs is to hook INT 21handlook for calls to function Bh. VMPoll and other VxDs will see the function OBh call long before V86TEST or DOSseesit. Since these idle broadcasts occur so muchmore frequentlythan any them. Thecalls still occurat the same rremendous rate, but at least aoe don’t clutter the V86TESTresults. As for actually eliminating the calls,
T’'ve used WINICEto assemble NOPs over the Exec_Int 2Fh call from VMPoll (see VMPoll+272hin the code fragment shownearlier) and com-
mented-out the device=*vmpoll statementin SY M.INI, both without ill effect. Although power managementonalaptopcouldrely on the
VMBPoll callout asa signal to issue a HLTto power-downtheprocessor, in practice the VMPoll callout seems togo to waste. For example,
Microsoft's POWER.EXEdoesn’t knowabout the VMPoll broadcast, and
instead looks for idle calls
such as INT 28h and IN1
PeekMessage loop in your Win16 application (as many Windo gramming books recommendifyou needto do backgroundprocessi you'll prevent KERNEL fromissuingits INT 2Fhfunction 1689h call:
Chapter 11: Who Needs DOS? for
while (PeekMes: ge(’msg, NULL,
NULL,
NULL, PM_REMOVE)
Message(8nsg) (89); In Windows Internals, Matt Pietrek shows that PeekMessage prevents the Windowsscheduler fromfalling intoits idle loop. The scheduler’s
idle loopis responsible for both the KERNELidlecall and INT28h so PeekMessage prevents KERNELfromissuingtheseidlecalls. But who cares? Several discussions of this subject (see “For Further
Reading”) have noted that PeekMessage can disable power management on battery-poweredlaptops. Although Microsoft’s POWER.EXEdoesn’t knowabout VMPoll broadcasts, the interesting POWER.ASMcode
included with theMS-DOS OEMAdaptation Kit (OAK) does hook INT 28h as one partof idle detection. Also, some TSRsrely on INT 28h calls
(see Undocumented DOS, 2d ed., pp.
564-565).
Butthere’s anotherissue herethat’s more important than power management or TSR friendliness. As noted, VMMreceives the INT 2Fh function 1689hcalls anduses themas a trigger to walk the Call_When_
Idle list. Consequently, whenever a Windowsapplicationis in a PeekMessageloop, therebypreventing the KERNELschedulerfrom issuing
the INT 2Fhfunction 1689h “heartbeat,”all VMMCall_When_Idle processingis suspended.In onestandard configuration, four VxDs had established Call_When_Idle handlers: IFSMGR, VMPoll, PageSwap, and
VTD.Asnotedearlier, for example, PageSwapusesits idle handler to doa _PageOutDirtyPages operation. This useful backgroundprocessing will
neveroccur while a Win16 application is in a PeekMessageloop.
We've seen that a lot of the interaction that Windows has with software loaded beforeit involves little more than a “not much going on” callout made by the VMPoll VxD. How about thoseother VxD callouts shownin the lastline of Figures 11-1 and 11-2?
INT 2Fh AX=1607hcalls 06: 1 OC: 2 10:2 14: 1
18:5
18: 190278 21: 2
VxD>#o100: 1
In Windows 95, V86TESTseesa slightly different set of VxD callouts:
INT 2Fh AX=1607h calls 06:1 0D: 1 10:1 (14: 1
18: 3
18: 156133
Ql:
40: 7
Unauthorized Windows 95
Thesecalls that VxDs make to software loaded before Windows are important to understanding DOS-Windowsinteraction. Besides, examining these VxD callouts provides a good opportunity to look over the Windows source code provided with the DDK. Although the DDK doesn’t provide source for such core components as VMM, IFSMGR, DOSMGR,VFAT, VPICD, or V86MMGR,it does provide source codefor the virtual display (VDD), keyboard (VKD), and mouse (VMD)devices and for VxDs such as PageFile, PageSwap, INT13, and VDMAD.Even the vast majority of Windows programmers who have nointention of writing a replacement VDDor VKD(or,indeed, of everwriting any VxD) would benefit from studying this code. There’s no better way to get a feel for how the Windowsoperating system operates. First, what are these other VxDs (besides VMPoll) whose callouts V86TEST detected? Let's match up the VxD ID numbers shown by V86TESTwith the namesofthese VxDsprovidedin the DDK: xD
Name
0006h
V86MMGR — V86 Memory Manager
000Ch
VMD — Virtual Mouse Device
000Dh
VKD — Virtual Keyboard Device
0010h
BLOCKDEV in 3.1; 10S (I/O Supervisor) in WW 3.21 and Windows 95
0014h
VNETBIOS — Virtual NetBIOS Device
0015h
DOSMGR — DOS Manager
0018h
VMPoll — Idle detection
0024h
Pagefile — Demand Paging File
0040h
IFSMGR (Installable File System Manager) in
>100h
Windows 95
IFSMGR in WfW 3.14 (0484h)
Additional VxDs besides these probably also issue INT 2Fh function
1607h, butthese are the ones detected by running V86TESTin fairly standard WiW 3.11 and Chicago configurations. We just covered VMPoll, and Chapters 3 and 4 discussed the DOSMGR callout API. Let’s take a quick look at the other callouts detected by
V86TEST. The V86MMGRcallout is named V86CallOut_LclA20forGibIHMAin the V86MMGR.INCfile included with the DDK. What this long name meansis that the state of the A20 addressline should be local to each VM even if the High Memory Area (HMA)is global (that is, sharedby all VMs). This is distinct from (but possibly related to) the odd XMScalls for local and global
A20enable and disable.If any software loaded before Windowsrespondsto this call, it has the sameeffect as if a VxD called the V86MMGR_SetLocalA20service, which is documented in the DDK:
Chapter 11: Who Needs DOS?
Whenthere is a global HMA user, the A20state associatedwith the HMA is alsoglobal. Changing 420in a virtual machine changesit in all virtual machines simultaneously. Someglobal A20 users (such as MS-DOS5.0) desire that the A20 statebe local even though the HMA is global.
If DOS=HIGH (as determinedbycalling INT 24h function 3306h), DOSMGR in Windows 3.1 andlaterwill automatically call V@6MMGR_ SetLocalA20. The VMD (Virtual Mouse Device) has two callouts that are defined in VMD.INC as VMD_CO_API_Test_Inst and VMD_CO_API_Get_Call_Back. Although these descriptions aren't terribly helpful, the DDK also comes with the source code to VMD; the sourcefile, INT33.ASM, shows exactly what these callouts do. A commentin the Get_Mouse_Instance routine in INT33.ASM notes thatthe Test_Inst callout allows a DOS mousedevice driver to declare its own instance data (using the INT 2Fh function 1605h interface described in Chapter3), rather than have VMD instancetheentire mouse driver. The Int33_Init routine in INT33.ASM issues the Get_Call_ Backcallout to give a DOS mousedriverthe chance to provide mouse support in a windowed DOSbox. The VKD(Virtual Keyboard Device) callout seen in Chicago isn’t cur rently documented, but a brief examination of MS-DOS 7.0 shows that WIN-
BOOT.SYS looks forthis callout and returns a pointer to a keyboard buffer in ES:DI. The BLOCKDEV VxD wasintroduced in Windows 3.1 as a replacementfor the VHD (Virtual Hard Disk Device) and wasin turn replaced in WAW 3.41 and Windows 95by10S(the 1/0 Supervisor). The BLOCKDEV callouts, which are also used by IOS, are described in the DDK documentation and in Chapter 2 of Geoff Chappell’s DOS Internals (pp. 7677). BlockDev_API_Hw_Detect_Start informs DOS TSRs and device drivers that a FastDisk device such as WDCTRL is performing hardware
detection (the TSR ordriver could use this as an opportunity to disable a write-behind cache, for example); BlockDev_API_Hw_Detect_Endindicates that hardware detection has been completed. More interesting than these text descriptions, though, is the source codeincluded with the DDK. Although the DDKdoesn’tinclude the BLOCKDEV source,it does provide the source for the WDCTRLFastDisk device, which uses BLOCKDEVservices and which issues the BLOCKDEVcallout. The WDCtri_Real_Mode_Init routine in WORMINIT.ASM attempts to detect the presenceof a standard AT-type Western Digital hard-disk controller by monitoring changesto the cylinder registerafter various reads. A comment to this routine reads: Now do lots of party stuff to make sure cache programs flush orat least don't try to lazy-write any data while we do this test. To make sure of this we will do the following Broadcast the BlockDev hardware detection API Int 2Fh
Unauthorized Windows 95
Do an Int 13h read of sector @ on both drives Do a 00S disk reset on drives C-2 (may flush) Set the InD0S flag (The word “party” seems to be standard Microsoft lingo for any low-level activity.) Although there is scant documentation for the VNETBIOS VxD, once
again the DDKprovides source code, andthis clearly makes up for any lack of documentation. A comment in VNETBIOS.ASM says “This virtual device serves two purposes: It buffers asynchronous network requests and
translates netbios calls for protected mode apps.” VNETBIOS.ASM issues. the VxD callout to “request information about network extensions.” A NetBIOS driver can return the address in ES:DI of an “extended NETBIOS table,” which tells VNETBIOS how to handle each NetBIOS INT 2Ahor INT 5Ch call.
Whenreading VNETBIOS.ASM,it’s particularly interesting to see howit
uses V86 breakpoints to handle the post routine for NoWait NetBIOS calls. There is also an (apparently otherwise undocumented) NoWaitNetlO=true setting, which converts all NetBIOS commands to NoWait. As with all the
DDKsource code, the changelog at the top ofthefile (almost always by RAL,RalphLipe) also makesinteresting reading: 25-Apr-1988 RAL Complete rewrite of network (used to be VND) 27-Oct-1988 RAL Updated to use new Get_Crit_SectionStatus 06-Nov-1988 RAL Redesigned to use remap instead of buffering 09-Mar-1989 RAL Real mode stub to not load if no redirector 05-Apr-1989 RAL This sucker actually works! 07-Apr-1989 RAL Added Int 2Fh API to get extended NETBIOS table 04-May-1989 RAL Works with 32-bit Build_Int_Stack_Frame 24-May-1989 RAL Test for NETBIOS instead of redir when loading 12-Jun-1989 RAL Fixed horrible page fault of doom bug 01-Sep-1989 RAL Make POSTS go to the RIGHT VM!!! 08-Oct-1989 RAL Fixed horrible InD0S assumption bug 29-Oct-1989 RAL Finished exit cancel code and documentation 04-Dec-1989 RAL Fixed critical section bug for non-hooked NCBs
Next up in the V86TESTlog of VxD callouts is PAGEFILE, which manages the virtual-memory swapfile (in Windows 95, there is another pagefile device, called DYNAPAGE). Once again, the DDKincludes source code for this VxD.
No other PageFile is loaded, Get Bimbo info about cache lock pointer. mov ax, (W386_Int_Multiplex SHL 8) OR W386_DeviceBroadcast mov bx, PageFileDevice ID xor cx, ¢x int 2Fh or ax, ax : if ax not @, then... nz SHORT PF_RI_No_Bimbo ; ...Bimbo did not respond
+ Bimbo mov sh mov
responded to int2Fh dx, edx, 16 dx, di
pointer to cache lock byte is in es:di.
Chapter 11: Who Needs DOS?
imp SHORT PageFileRI_Exit PF_RI_No_Bimbo:
Bimbo not around, get SmartDrv info about cache lock pointer
The Pagefile_Real_Init routine in PAGEFILE.ASMtries to make an IOCTL call to SmartDrv toretrieve a pointerto a disk cache lock pointer. However, in case SmartDry isn’t loaded, PAGEFILE makes the VxD calloutto allow a disk cache other than SmartDrv to return a cachelock pointer in ES:DI. (By theway, it seemsthat “Bimbo” is Microsoft's name for any non-SmartDrv disk cache. This is mildly amusingin a nerdy kind of way, since for years the generalindustry namefor SmartDry has been DumbDrv. In WIW 3.11, V86TEST sees two PAGEFILE callouts because the VMPoll VxD (which, as notedearlier, does a _PageOutDirtyPages operation when the system is idle) also triesto retrieve a disk cachelock pointer.
Finally, we cometo the callout issued by IFSMGR,theInstallable File System manager, which is the foundation for 32BFA and long filenames. Although IFSMGR played a key role in WfW 3.14, it is documented only in Chicago, and even there only with an incomplete (at least at the time of this writing) IFSMGR.INCfile. Even without proper documentation or source code for IFSMGR, a disassembly of IFSMGR showsthat its VxD callout retrieves the size of the DOS Current Directory Structure (CDS); this is immediately obvious from the numbers 51h in DOS 3 and 58h in DOS 4 andlater:
ocaac cogs OCI1A6 BclAc acig2 ocigs ociBE acica acics acicr acini acio7 oc109 0c100 OC1DF Oc1DF acieo Oc1E6 ocie7 aciec OclEF aciFi QciF4 ocira acz6z 0c268
Push_Client_State VMMcal1 Begin_Nest_V86_Exec mov word ptr Cebp.Client_AX),1607h moy word ptr Cebp.Clien| mov word ptr Lebp.Client_Cx moy word ptr Cebp.Client_DX mov eax,2Fh VMMcal1 Exec_Int cmp word ptr Cebp.Client_AX],0897Ch ne short NO_API_RESPONSE cmp word ptr Cebp.Client_DX],0AZABh jne short NO_API_ RESPONSE Lebp.Client_CX] movzx ecx,word imp short GOT_COS SIZE —NO_API_RESPONSE: push ebx ;; returns VMMcal) Get_Machine.Info seh
i740 in Windows 95
31 DOSMGR magic ; DOSMGR magic
DOS major version in AH
z: 58h = CDS size in DOS 4+ + DOS version > 327
t GOT_COS_SIZE 31 58h-7=51h = CDS size in 00S 3 sub ecx,7 GOT_CDS_SIZE mov dword ptr CDS.SIZE,ecx VMMcall End_Nest_Exec Pop_Client_State
Unauthorized Windows 95
What makesthis otherwise pedestrian codeinteresting is that, even in Windows 95, IFSMGR cares about a DOSinternal structure like the CDS. This makes perfect sense(andin any case IFSMGR.INC mentionsa different service which “Updates the CDSsinall the VMs” when a new volume appears in the system), but it isn't what you'd expectafter hearing the claim “Windowsnolonger uses DOS.”
The Top Windows IT 21h Calls Nowthat we’ve examined the VxDcallouts that Windows makesto software loadedbeforeit, let’s focus on the DOS INT 21h calls that Win-
dows sends downto software loaded beforeit. Back in Figure 11-1, V86TESTprovideda census of INT 21h calls made by Windowswhile I ran Clock and used WinWordtosearch
through four large documents (1.7MBofdata, containing the text for DOSInternals). Figure 11-2 showedthe samething, exceptthatI also opened a DOS box.
Inbothcases, 32 BFA was disabled (in a few moments,
we'll repeat the same test, with 32BFAenabled). In Figure 11-3, I’ve taken the INT21h censusfromFigures 11-1 and 11-2 and compared them
using a diffutility. The similarities between the twotests give us some confidencethat the results aren’t random;the differences hopefully show
the impactof running a DOSbox. < 6: 153 09: 1 > 02: 93 06: 153 09: 1
OB: 9424
€1C: 1 >1C: 1
25: 12 29: 4 25: 18 29: 8
2A 2A: 430 2C:
4:5
2 12 38: 2
41: 6 41: 6 >
153043 151 43
44: 44
40
85 93
316 1
3 3
BC:
1 1
88:1 5B: 1
1742
56 OE: 288 19 QE: 289 19:
1A: 409 1A: 102
2F OF
32: 2 32: 2
48: 8 48: 13 49:1
4h: 4) 4A: 6
3B: 26 3C: ¢ 38: 20 3C: 6
42:
42:
oc aC
50:1 5D: 3
i 56 SE: 1
SF: SF: 3
52: 10 55: 4 52: 10 S84
48 4B: 4
572
62 62
oe oc
Figure 11-3: Comparing the resultsof the INT 21htests presented earlier.
125 13
Chapter 11: Who Needs DOS?
In Figure 11-4, I’ve sorted these INT 21h calls, starting with the most frequent, to showthe top DOScalls made by Windows in this standard non-network configuration when 32BFA is disabled. Where opening a DOSboxseemsto makea significantdifference,I've noted this. 40h 2th 3Fh 42h 2ah
le or Device Read File Move File Pointer ( n File trol (LOCTL) t File Set Default Drive Close File
Task switch: Fewer with 00S box Fewer with DOS More with DOS box Almost none with DOS box???
Task switch d for DOS
urrent Get Default 0 Get/S Change Current 0 Get
Figure 11-4: The top WindowsINT 21hcalls without 32BFA. What does all this mean? To answer that question, let’s first look at
the functions in which opening a DOSboxclearly doesn’t makea significantdifference: * Without 32BFA, Windows uses DOSforfile I/O. Naturally! © Without 32BFY , Windows uses DOSto Get andSetthe currentdrive and directory. * Windows(particularly the Windows Clockapplication,orapplet, as Microsoft referstolittle applications) uses DOSto get the current date and time. Windows asks DOSwhatdayit is, almostas frequently as it asks DOS for the time: whenever Clock receives a WM_TIMER
message,it calls INT 21h functions 2Ah and 2Ch.(Thisis also true for the Win32 version of Clock,butit calls the DOS functionsin a more roundabout fashion; we'll get tothis later on.)
Opening a DOSboxaffects onlya few DOSfunctions. This is an important point, because you sometimeshearassertions that Windows
Unauthorized Windows 95
relies on DOS inorderto run DOS programs. Figures 11-3 and 11-4
showthat running DOSprogramshaslittle to do with the WindowsDOS relationship. Windowsrelies on DOS for certain services required
by both DOS programs and Windowsapplications. Conversely, if Win-
dows can bypass DOS while providing services to Windows applications, it can dothe samething for DOS programs:just because a real-mode DOSprogramrunning in V86 mode makes an INT 21h doesn’t mean that Windowshasto pass that INT 21hcall down to real-mode DOS running in V86 mode. Whenwediscuss 32BFA in moredetail, we'll see
that, in protected mode, Windows canservice many INT 21h calls coming from DOSprograms. The few differences that do occur when a DOS boxis opened(see Figure 11-4) mostlyturnoutto reveal things about the Windows-DOS relationship in general, rather than about DOSboxesin particular:
* Whena DOSboxis open, Windowspasses the Check Keyboard Status call (INT 21h function 0Bh) down to DOS.Butthis doesn’t mean that Windows absorbs function 0Bh when it comes from a Windows
application! Thefactis, no normal Windowsapplicationcalls function OBh; this is the only reasonit didn’t showup in Figure 11-1. COM-
MAND.COMcalls function Bhtopoll the keyboard; this is why it showed up in Figure 11-2. If a Windowsapplication happened to call function 0Bh, Windowswould pass the call down to DOS, just as it
does when a DOSprogramsuch as COMMAND.COMcalls this
function. (Yes, I’vetried this.) A DOS programcouldsimilarly bypass the DOSinput services, and many do. Windowsis a fairly typical DOSprogramin this regard. Windowsapplications don’t call INT 21h function OBh becausethey get keyboardinput via the Windows
keyboarddriver, whose INT 9
handler calls the Keybd_Event function in USER, which in turn
places keystrokes in the Windowshardwareevent queue, eventually to endup at a Windowsapplication’s WndProcas a messagelike WM_KEYDOWN, WM_KEYUP, or WM_CHAR. (Seethe descrip-
tion of Keybd_Event andthe
System Message Queue in Undocumented
Windows, Chapter 6.) This is a good example of how, from the very
beginning, Windowshas bypassed many DOS“services” (if you want to call them that).
* The samestoryapplies tofunction 02h (Display Character). Ifa Windows application used this call, Windows would pass the call down to DOS, just as occurs when COMMAND.COMusesthiscall in a DOS
Chapter 11: Who Needs DOS?
box. Windowsapplications use a different mechanism — the Windows Graphics Device Interface (GDI) — fordisplaying output; they have bypassed DOS’feeble assistance eversince Windows1.0. A DOSprogramcould similarly bypass the DOSoutput services, and manydo. Vith INT21h functions 50h (Set PSP) and 62h (Get PSP), it’s first of
all quite significant that Windows makesthesecalls, whether or not a DOSboxis running. The Windowskernel uses the DOS Program SegmentPrefix (PSP) to task switch between Windowsapplications (though,as noted in Chapter 5 of Undocumented Windows, KERNEL
postpones making the Set PSP call until the Windows application has
made an INT 21h call). In Figures 11-1 and 11-2, the kernel was switching between WinWordand Clock. Win32 applications, even in
Windows 95, have DOS PSPs(see the WINPSP programin Chapter 13). Examples like the PSP show that Windows95 requires DOS —
and bypasses DOS — tojust aboutthe sameextentas did previous
versions of Windows. Microsoft has simply chosen forthefirst time to makea big deal about a capability that Windowshashad ever since Windows 3.0 Enhanced mode.
Oddly, starting a DOSbox in Figure 11-2 caused fewer Set and Get PSPcalls than we saw in Figure 11-1, in which we performed the same
operationsbut withoutstarting a DOSbox.This is surprising atfirst: you’d expect morePSPcalls, since the DOSboxis an additionaltask. However, KERNEL uses DOS PSPsfor switching betweentasksin
the System VM,that is, for Win16 and Win32 applications. A DOS boxis a separate VM, and VMMtask switchingisdifferent than kernel task switching. When VMMswitches between VMs, PSPs must also get switched, but to do this VMMuses instance data. (The “DOS
Instance Data and the SDA”section in Chapter 4 notedthat Windows
instances the DOS Swappable Data Area [SDA]; whichincludes DOS’ current-PSP variable.) Okay, so VMMusesadifferent mechanismfor keeping PSPsstraight from what KERNELuses. But why does DOSsee fewer Get and Set PSP calls whenwestart a DOS box? Simplybecause, with the extra VM, the System VM wasn’t scheduledas often, so the sub-scheduler
within KERNELdidn’t have to switch between WinWordand Clock as often. Whena DOSboxis running, DOSalsoseesfewercalls to function 1Ah,Set Disk Transfer Address (DTA), for the same reasonthatit
Unauthorized Windows 95
sees fewer Get and Set PSPcalls. The KERNEL sub-scheduler has to switch DAs when it switches PSPs, Onthe other hand, the VMM schedulerrelies on instance data to keep DTAs, like PSPs, in syne with VMs. When multiple VMsare running, the System VMnaturally doesn’t run as often, so the KERNELsub-scheduler doesn’t kick in as ofteneither. The one significantdifference between the DTA andPSPcalls is that with 32BFA, Windows handles Set DTA without calling down to DOS.In contrast, as we'll see, Windows(even with 32BFAandevenin Windows 95) still passes GetandSet PSP calls downto DOS. * In comparing Figure 11-2 to Figure 11-1, we can see that Windows seemsto send moreI/O Control (IOCTL; INT 21h function 44h) calls down to DOS when a DOSboxis running. However, this is just a testing “artifact”; I unintentionally allowed Windowstorun for a little longerin Figure 11-2 thanin Figure 11-1. Morecareful examina-
tion shows that Windowspasses the same IOCTLcalls down to DOS,
whether they come from a Windowsapplication or a DOSapplication. Without 32BFA, the two major IOCTLcalls Windowssends
downto DOS are 4408h (Does Device Use Removeable Media?) and
4409h (Is Drive Remote?). © Theonly truly surprisingresult in comparing Figures 11-1 and 11-2 is that with the DOS box running in Figure 11-2, Windows sent almost
no Find Next File (function 4Fh) calls down to DOS, whereas there
wereover 300 when performing roughly the sameoperation without a
DOSbox! Fortunately, there’s a simpleexplanation: when I brought WinWordupthe second time, thefull pathnamesof the four files I
wantedto open (Parts 1-4 of DOS Internals) were already
showing in
the File menu,left over fromthefirst test. Rather than use the File
Opendialog again,I just selected the fourfiles straight from the
menu. It all makes sense. Whew! I was worriedthere for a minute.
One last point before we move ontosee the effect of 32BFA: Remember that, even when Windowsdoes call down to DOS, it does so in V86
mode. This meansthat even these INT 21hcalls that are sent downto DOSaren’ at all like the good old INT 21hcalls you’re usedto:
Chapter 11: Who Needs DOS?
* Before the call showsup at the DOSinterrupt chain, the call will already have been preprocessed by any VxDsthat have used VMM’s Hook_V86_Int_Chain service Chapter8). * Whenthe call returns,it will be postprocessed by any VxDsthat have used VMM?’s Call_When_VM_Returnsservice. * Any further interrupts madeinside DOSor a TSRor a device driver will vector throughthe IDT to VMM,which will sendthe interrupt on to any VxDs that have called Hook_V86_Int_Chain. * One or more Windows VxDsmighthave placed V86 breakpoints on the code. As discussed in Chapter 8, VMM’°sInstall_V86_Break_Point
service patches a specified segment:offset address with an ARPL
instruction, which causes a GP fault into VMM, which then calls a handler associated with the V86 breakpoint. VxDs canuse this service
to control real-modecode in whatever way they want. ¢ If DOS makesa device-drivercall, the device driver’s Strategy and
Interruptroutines might have been V86 breakpointed. For example,in WEW3.11 RMM.D32, the real-mode mapper VxD that provides a 32-bit disk access (32BDA)interface on non-FastDisk devices places a
86 breakpointon the Strategyroutinefor everybuilt-in device driver. * IfDOS ora TSR or a device driver performs an IN or OUTto an
I/Oport, you might once again bop into VMM-and VxD-land. VxDs can hook 1/Oportaccess, using the InstallIO_Handlerand Install_
Mult_1O_Handlersservices provided by VMM. * Windows installs some handlers in the DOS interruptchain; these
handlers canuse various backdoorprotocolsto pass calls back up to
Windows. For example, we saw in Chapter 8 (in “The Role of
IFSHLP.SYSand V86callbacks”section) that IFSHLP.SYSuses a V86callback to pass some DOS calls up to the IFSMGR VxD. Thus, while you're in the middle of some INT 21hcall that Windows
has passed down to DOS,you'relikely to bounce backseveral times into Windows VMM- and VxD-landbefore the call returns. ‘Totake just one example, we’ve seen that Windowspassed INT 21h
function 19h (Get Default Drive) down to DOS; we'll soonsee that 32BFA doesn’t change this behavior. But following the DOS INT 21h
chainwithautility such as INT'CHAIN(provide on the disk) shows that even once “inside” DOS, the call can bounce back into Windows
multiple times.
Unauthorized Windows 95
:\UNAUTHHDIntchain -a20off 21/1900 > tmp.tmp UTHW>type tmp. tmp TFSSHLPS.
; IFSHLP doesn't send 21/19 to IFSMGR
checks A20 » 80 DOS calls XMS akpoint y2
-> VB6MMGR XMS handler
00S INT 21h handler in HMA : INT 24h AH*82h -> > V6 BP -> DOSMGR VBE API -> Begin Crit
10 ARPL ARPL HMA 10 ARPL HMA
3 RNM.032 py NM VB6 by
breakpoint on 10 Strategy
ti V86 breakpoint (on CON Interrupt routine??)
Here, I forced A20 off beforecalling function 19h in order to demonstrate one of these V86 breakpoints. MS-DOS’s INT 21h handler checks whether DOS=HIGH but A20 is off;
in this situation, DOS calls XMS
function 5 (Local Enable A20). This code lives inside MS-DOS(see
Undocumented DOS,2d ed., Figure 6-6), so if you get here,it certainly seemslike you're “in DOS.” However, as notedin Chapter 8,the
‘V86MMGR VxD providesits own XMS services, regardless of the XMS server you hadloaded under DOS, and it uses Install_V86_Break_Point to
patch the XMSfunction whose address is returned by INT 2Fh function 4310h. Thus, when MS-DOS’s INT 21h handlercalls the XMS function, it winds upexecuting 32-bit protected-mode codeinside V36MMGR.
Windows called down to DOS to handle this trivial function 19h call, but DOS called back into Windows several times. This is one reason why
the distinction between DOS and Windowsseemsso fluid and whythe
“Does Windowscall down to DOS?”question can seemso meaningless. Even when Windowsdoes call down:to DOS, it’s a DOS over which
Windowshaspretty tight control. All the same, it’s easier to see the true Windows-DOS relationship
when Windows bypasses DOS than when Windows calls down to DOS and then DOS bops back into Windows
| times.
Solet’s now look
at 32BFA, where according to Microsoft, Windows bypasses DOS.
V86TESThelpsus substantiate this claim, while also pointing to the places where Windows still relies on DOS (albeit, as we’ve just seen, a
heavily V86-breakpointed DOS).
Chapter 11: Who Needs DOS?
TheEffect of 32-Bit File Access I tookseveralfalse steps before I came up with a reasonable way to use V86TESTtoshow off 32BFA.First, I repeated thetest in Figures 11-1 and 11-2, butthis time without the /D:C command-line switch thatdisables 32BFA: C:\UNAUTHWAVB6TEST>vB6test -verbose win > va6test.1og However, I found that the V86TESTresults were nearly identical to those produced when using the /D:Cswitch! No, 32BFAis ota crock. Instead, redirecting Windows’ stdout turns
off 32BFA,so thatleaving off the /D:Chad noeffect. Since I wouldn’t be able to start V836TESTbefore Windowsandredirect stdout, and I wastoolazy to change V86TESTto write out a log file, I next tried running V86TEST -QUERYfromwithin a DOSbox. Sure enough, there weresignificant differences between WIN /D:C and Windowswith 32BFA. But the difference was that 32BFA generated more
DOScalls than WIN /D:C! It turns out that the systemgoesidle more often with 32BFA, and VMPoll thusissues more VxD broadcasts. SoI ran the test again using V86TEST -FILTER, and this time got some reasonable-looking results.
Under W£W3.11 with and without 32BFA, I used WinWord to open and save a 340K document, and ran V86TEST -QUERYfrom a DOS
box, redirecting its outputtoa file. I used a diffutility to compare the V86TEST results with and without 32BFA;the results are shown in
Figure 11-6, to which I’ve addeda large numberof comments. < vB6test -filter win /D:C (no 32BFA) > v8étest -filter win (32BFA) < During Windows init > During Windows init:
5203 INT 2 5198 INT 21/2
< While Windows running: 25574 INT 21 > While Windows running: 17146 INT 21
means ni > means with a 344 in VB6 x 9 in VB6 mode
in VB6. mode 46 in V86 mode
‘Once filter out MPO}? 25574 17146 = 8
Same operation
77
< 253 INT 21/2F calls/second
24 seconds less with 32BFA (24
Unauthorized Windows 95
> 222 INT 21/2F calls/second If YMPo11 were counted, 32BFA would show more 21/2F per second VM #1
4007 calls 438 calls
Aside from VMPoI1, almost no 00S calls from System VM with 32BFA! Would be good to know what those few remaining calls are, Unfortunately, in the INT 2Ih census below, they are combined with 00S calls from the DOS box (VM #2). How ever, most 00S box calls are to 21/08. See HV86TEST in Chapter 12 for a census that doesn't include 00S box. WM #2
21569 calls 16708 calls
With 32BFA, a lot fewer DOS calls from DOS box too: whatever 32BFA can do for Windows applications, it can do for DOS boxes INT 2Fh AH=16h calls seen by VB6TEST 00: 2 05:1 08: 1 OA: 2 0B: 2 > 00: 2 05: 1 08:1 OA: 2 0B: 2 INT 21h calls < 02: 149 06: 194 08: 55 09: 1 > 02: 151 06: 150 08: 57 09: 1
BA: 1 BA: 1
OB: 21159 08: 16359
ac 2 ac. 2
OD: 255 OE: 289 19: 87 00: 257 OE: 289 19: 87
Figure 11-3 demonstrated that 21/08 (Check Keyboard Status) is used by the DOS box only. With 32BFA, almost all calls from the DOS box (VM #2) were 21/0B: 16708
16359 = only 349 other DOS calls from 00S box under 328FA
(1A: 79 25: 17 29: 16 > 1A: 19 25: 17 29: 16
A: 15 2: 17 2F: 9 A: 1S 2: 17 2F: 9
30; 24 32: 2 30: 24 32: 2
33: 4 3d: 6 33: 4 34: 6
With 328FA, a lot fewer calls to 21/1A (Set DTA) « >
3 3
38: 18 3C: 4 3B: 1 3C: 1
30: 307 3: 221 3F: 1614 3D: 110 3E: 90 3F: 266
40: 3480 40: 3416
41: 3
With 32BFA, a lot fewer calls to: 21/38 (Change Current Directory) 21/30 (Open File) 21/3 (Close File) 21/3F (Read File)
In 32BFA, most 21/40 (Write File) appear to be passed through. But wait a minute: the numbers don't add up 16359 (21/08) + 3416 (21/40) = 19775 calls to these two functions alone. Yet summary above says only 17146 calls under 32BFA There's a simple explanation I generated this log under an older version of V86TEST that didn't “freeze” the stats before printing them out. So alma t all these 21/40 calls reflect V86TEST's own printf to stdout. In 32BFA,
Chapter 11: Who Needs DOS? writes to stdout are passed down to DOS. But wait again: V86TEST output was redi rected toa file. No, I lied: it wasn't! I captured V86TEST output in an Epsilon process buffer. So it was a write to stdout, which 32BFA passed down. We'll confirm later that in 32BFA, most 21/40 are not passed down 42: 1238 > 42: 226
43: 19 44: 244-45: 147: 86 48: 43: 1 44: 35 45: 1 47: 9 4B:
49: 2 2
4A: 7 48:7
4B: 5 4B: 5
With 32BFA, a lot fewer calls to: 21/42 (LSEEK) 21/43 (Get/Set File Attributes) 21/44 (1OCTL) 21/47 (Get Current Directory) 23 50: 197 $1: :1 50: 196 51:
7 7
52: 10 55:3 52: 10 55: 3
56:2
5
62: 48 63: 1 62: 48 63:1
65: 4 65: 4
6C: 2 6C:1
71: 4 DC: 5 71:4 DC: §
16: 9 16:9
46: 1 46:1
48: 2 48: 2
4a: 6 4A: 6
59: 2 5958
7
2BFA, a lot fewer calls to. d First File)
«5B: 3 >
SE: 1 5E: 1
SFr 3 SF: 3
INT 2Fh calls < 08: 1 11: 692 12: 11 13: 4 > 08: 1 1: 39212: 11 13:4 With 328FA, a lo}
43: 8 43: 8
(Network Redirector)
< 55: 1 7A: 2 > 55: 1 7A: 2 The cal? to 2F/FF is VB6TEST’s call to V86TEST stats from resident copy. Figure 11-6: Running V86TESTin WfW 3.11, with and without 32BFA. Figure 11-6 is a dramatic demonstration of how Windows and DOS
truly relate under 32BFA.It provides mostof the answersto this chapter’s
question; Why does Windows need DOS?
© Aside from VMPoll broadcasts (and the INT28hidle calls that we
knowgo along with them), the most frequent DOScall for which
Windowsuses DOS is function 0Bh (Check Keyboard Status). This
call is used only to poll the keyboard in a DOSbox.
* Aside from function OBh, a fairly I/O-intensive operation (opening
and saving a documentwith WinWord)generatedonly a few hundred
DOS calls. Without 32BFA, the sameoperation generates several thousand DOS calls.
Unauthorized Windows 95
¢ Aside fromfunction 40h Write File calls to stdout (which wouldonly
occur in a DOSbox), almostall DOSfile I/O calls are handled in 32-bit protected mode withoutcalling down to DOS. Figure 11-7 shows some INT 21h calls that 32BFA generally absorbs; this list is not complete andjust reflects what we’ve seen using V86TEST.
* Evenwith 32BFA, a scattering of INT 21h calls are still sent down to DOS. These are shownin Figure 11-8; compare this with Figure 11-4, which showed the top INT 21h calls without 32BFA. t Directory
et File Attributes
1OCTL Get Current Directory Find First File Find Next File Set File Date/Time name functions
Figure 14-7: Some majorINT 21h calls that 32BFA handlesin protected mode, without calling DOS. Keyboard Status Drive jefault Orive Get Default Drive Get Date Get Time . 62h
Get P Get SysVars (undoc
Figure 11-8: The top INT 21h calls that 32BFA sends downto DOS.
Now, there’ nothingparticularly magical about 32BFA:it’s just a collection of VxDssuch as IFSMGR.386, VCACHE.386, VSHARE, and VEAT.386. In WEW3.11, Microsoft wasable to plopthese VxDsontop of anessentially unchanged VMM.These VxDs could have been written by anenterprising third-party developer.All the capabilities for bypassing
Chapter 11: Who Needs DOS? DOShave been present all along in VMM,mostnotably in its Hook_ V86_Int_Chain and Set_PM_Int_Vectorservices. 32BFAjust makes moreextensive use of these services. The entire Windows-DOSrelationship is quite fluid, andreally comes downto how the VMMservices are employed. Thisis just another wayof saying that VMMis the operating system.
What about BIOS Calls? Withall this talk about the relationship between Windows and MS-
DOS,it’s natural to wonder how Windowsrelates to the ROMBIOS.
HOOKINT.C in Listing 11-1 is a simple program that reports on any
program’s usage of the BIOSsoftware interrupts.I also included the DOSINT25h and26h disk read and write calls and the INT 28hidle call; it’s easyto add additionalentries to HOOKINT. Listing 14-1: HOOKINT.C
d short WORD ong DWORD:
Hels fend
1.ds.e5.dx,cx,bx,ax; WORD es.ds.di.si,bp.sp,bx.dx.cx,ax; WORD ip.es, flags REG_PARANS:
typedef void (interrupt far *FUNCPTR) (REG PARAMS) ;
Unauthorized Windows 95
typedef struct { FUNCPTR old, new: OWORD count, *func; int intno, has_func char *str: } INT_OATA; extern INT_DATA int_dataL];
int check windows = 0, in_windows = 0; int int_ndx{0x100] (0) ;
#idefine INT_HANDLER(rax, intno) { \ INT_DATA *pid = &int_datafint_ndxCintno]]; \
if Cinwindows || (! check_windows)) | \ if (pid->has_func) \ pid->func[rax >> 8]++; \ pid->count++; \ VA _chain_intr(pid->old); \
void void void void void void void void void void void void void
interrupt interrupt interrupt interrupt interrupt interrupt interrupt interrupt interrupt interrupt interrupt interrupt interrupt
far far far far far far far far far far far far far
int10(REG_PARAMS intl1(REG_PARAMS int12(REG_PARAMS intl3(REGPARAMS intl4(REGPARAMS intl5(REGPARAMS intl6(REG_PARAMS int17(REG_PARAMS intlA(REGPARAMS int25(REG_PARAMS int26(REG PARAMS int28(REG_PARAMS int33(REGPARAMS
INT_OATA int_dataC] 1 old, new, count, 8, intld, 0, 0, a, intll, 0, 0, 6, intl2. 0, 0, 8 intl3, 9, 0, 0 intl4, 0, 0, a, intl5, 0, 0, a intl, 0, 0, a, intl7. 0, 0, a, intlA, 0, 0, 0 int25, 0, 0, a int26, 0, 0, 0 int28, 0, 0, a int33, 0, 0, define NUM_INT
r) r) r) r) r) ry r) nr) r) r) r) r) r)
INT_HANDLER(r ax,0x10); INT_HANDLER(r. ax,0x11); ) INT_HANDLER(r ax,0x12); INT_HANDLER(r. ax,0x13); INT_HANOLER(r. ax.0x14); INT_HANDLER(r. ax,0x15); INT_HANDLER(r. ax,0x16); ) INT_HANOLER(r ax,0x17); INT_HANDLER(r. ax,0x1A); ) INT_HANDLER( nr. ax,0x25); ) INT_HANDLER(r. ax,0x26); INT_HANDLER(r ax,0x28); ) INT_HANDLER(r ax,0x33);
intno, x10, Oxll, x12, ox13, oxi4, x15, @x16,> Oxi7, OxlA, x25, 0x26, 0x28, 0x33,
has_func, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0 0, 0, 1,
str "Video", "Equipment List", “Memory Size", “Disk”, "Serial", “system Services", "keyboard" "Printer "Time", "DOS Disk Read”, "DOS Disk Write", "Idle", “Mouse”,
sizeof(int_data) / sizeof(INT_OATA))
FUNCPTR GetSetInt(int intno, FUNCPTR new)
Chapter 11: Who Needs DOS?
FUNCPTR old _dos_getvec intno) _dos_setvect(intno, new) return old: FUNCPTR prev_2f =
TR) 0;
define WINI iidefine WIN_EXIT_BEGIN
0x1608 0x 1609
void interrupt far int2f(REG_PARAMS r) i if (r.ax WIN_INIT_COMPLETE) in_windows++; else if (r.ax WIN_EXIT_BEGIN) in_windows: _chain_intr(prev_2f); 4 fail(const char *s) { puts(s); exit(1); | main(int argc, char *argv[]) ( int i, ds INT_DATA *pint: FILE *f;
rnemp(strupr(argv(1}), *-WIN",
check_windows++; argv++; argc /* set up func counters */ for (i=0. pint=int_data; ihas_func) if ((pint->func (OWORD *) calloc(@x100, sizeof(DWORD))) == 0) fail("Insufficient memory");
* initialize int_ndx */ for (i=0, pinteint_data; iintno] 4; /* instal] handlers */ for (i=0, pint=int_data: i0ld = GetSetInt(pint->intno, pint->new) if (check_windows) prev_2f = GetSetint(Ox2f, int2f): /* run the command */ if (argc < 2) system(geteny("COMSPEC")); else awnvp(P_WAIT, argv[1], &argv[1]);
Unauthorized Windows 95
/* restore previous handlers */ if (check_win Ss) (void) tInt(Ox2F, prev_2f): for (i=0, pint=int_data; iintno, pint->old) /* open log file to display results */ if (f fopen("HOOKINT. LO printf( "Creating HOOKINT.LOG\n"): tdout:
* show command line * for (i*l; icount, pint->str); fprintf(f."\n"); * if INT has functions, show individual function counts * for (i=0, pint-int_data: ihas_func && pint->count
+ JFun fprintf(f,"RO2K/%02K: 1u\t" int->intno, J, pint->funetj1); forint f(f
If you run HOOKINTwithout any command-line parameters, it spawns a commandshell; when youexit fromthe shell, HOOKINT reports the usageofthe hooked interrupts. Ratherthan send its outputto stdout, which wouldthen have to be redirectedto a file with the possibly disruptive results we sawearlier in V86TEST, HOOKINTinstead writes outa file,HOOKINT:LOG. Youcan also specify a program for HOOKINTtorun, such as WIN or WIN /D.C.Finally, an optional -WIN command-line switch tells HOOKINTtoonlytrack interrupts while Windowsis running (oratleast in between calls to INT 2Fh functions 1608h and 1609h). Figure 11-9
Chapter 11: Who Needs DOS?
shows a typical HOOKINT.LOGfile after using WEW3.11 for a while, In this configuration,32-bit disk access (32BDA)was enabled; I ran a large number of Windowsapplications(including WinWord,Solitaire, the Win32 version of FreeCell, Control Panel, Print Manager, and File Manager), but I didn’t open a DOSbox.I didn’t use the HOOKINT -WIN switch, so this log includes calls Windows made duringinitialization and termination. NT INT INT INT INT INT INT INT INT INT
10h 11h 12h 13h 15h 16h An 25h 28h 33h
10/00: 10/12: 10/F3: 13/0: 15/53: 16/01: 1A/00: 33/00:
quipment List Memory Size Disk System Services Keyboard Time DOS Disk Read Idle Mouse 7 10 12 1 98 9 3
10/01: 1 1O/1A: 1
18/@E: 100 10/0F: 4 (1O/6F: 2 10/FO: 4
10/10: 4 LO/F1: 6
«10/11: 6 10/F2: 3
3
15/' 0: 4067 16/91: 4085 15/00: 2 14/02:
11/03: 1
15/C1: 1
1A/O5: 1
Figure 11-9: Sample HOOKINTresults generated under WfW 3.11.
Thereare a few noticeable features in Figure 11-9. First, there are many INT 28h idle calls; this matches what we saw earlier in the VMPoll broadcasts. The “Reschedule” function in KRNL386 makes these INT 28h calls.
Second,there are a hefty number of INT15hcalls, but these don’t necessarily come from Windows. INT15h function 53h belongsto the Advanced Power Management (APM)specification; I had Microsoft's
POWER.EXEloadedhere. Functions 90h and91h are the BIOS Device
Busyand Device Post operatingsystemhooks. The BIOScalls these
functions, and an operating system such as Windows canintercept them; the IOS VxD can use INT 15h function 90hasa signal to call the Enable_VM_Intsservice. INT 15h function 87his the Copy Extended
Memory
service; Windows uses this duringinitialization.
Othercalls, such as INT 10h video, INT 16hkeyboard, and INT33h
mouseservices, are calledfar less often thanis typical in a full-screen DOSapplication (which,in a way, is what Windowsis). In one completely
Unauthorized Windows 95
scientific comparison,I ran a full-screen DOSprogram(the Borland C++ integrated developmentenvironment)very briefly under HOOKINT — certainlyfor a muchshorter periodthan IT had run Windows — andthere were almost 200,000calls each to INT 16h functions 11h and 12hto poll the keyboard, over 11,000 calls to INT 33h to get the mouse status, and over 1000 calls to INT10hfunction2 to set the cursor posi-
tion. This is quite different from what happensin Windows. Third, andlast, we come to INT 13h disk reads and writes. Here there’s actually something importantto say. Starting in Windows 3.10, Microsoft provided32-bitdisk access (32BDA), often referredtoas FastDisk. Thisis frequently confused with 32-bitfile access, butis quite separate: 32BFA handles DOSfile I/Ocalls in 32-bit protected mode, whereas 32BDAhandles [NT 13h disk reads andwrites in 32-bit pro-
tected mode. So howcan we summarize Windows’ relation to the BIOS? First,
Windowsapplicationshave long bypassed the BIOSservicesfor video,
keyboard, printing, and soon; as notedearlier, the Windows API pro-
videsits own services. Of course,the occasional Windows program does uses BIOSservices; a good example is Microsoft’s CodeViewdebugger. The source code for the Windows DISPLAYdriver includedwith the DDK (DDK\286\DISPLAY\8PLANE\V7VGA\SRC\VGA.ASM)
contains the following note: why
wld a windows app do a INT 10h you ask? CodeView does so we need INT 10h
Second, examining the source code included with the DDK shows that Windows device drivers such as DISPLAY and KEYBOARD (these are Win16 DRVfiles, not to be confused with 32-bit VxDs) make occasional use of BIOS calls, for example, INT 10h and INT 16h.
Andthird, an examination of the VxDsource code included with the DDK showsthat a number of VxDs hook the BIOS interrupts in V86
andprotected mode. The VDD(Virtual Display Device) hooks INT 10h; the IOS (I/OSupervisor; called BLOCKDEVin Windows3.1)
hooks INT 13h; VKD (Virtual Keyboard Device) hooks INT 16h; VPD (Virtual Printer Device) hooks INT 17h; VTD (Virtual Timer Device) hooks INT 1Ah; and VMD (Virtual Mouse Device) hooks INT 33h. For example, VKD uses Hook_V86_Int_Chain to hook INT 16h in V86 mode. VKD will thus see INT 16hbefore any real-mode software does. VKD also uses Call _When_VM_Returns to install a “post-reflection
hook”thatwill be called whenthe real-mode BIOSattempts to IRET
Chapter 11: Who Needs DOS?
back to whatit thinks its caller. Why does VKD hook INT 16h? The INT 16h handler in VKD.ASMexplains why: :
;
DESCRIPTION: int
This software interrupt handler will convert blocking Ting int 16s. If no key is ready then VMs time slice will be given up
Push_Client_State Wwcall Begin_Nest_Exec
+ Nest execution level
jov dh, Lebp.Client_AH] inc dh Polling int 16 (0 1) 3 extended polling (10h 11h) 16_Pol1_Loop mov Cebp.Client_AH], dh mmo 16h vit. TestMem [ Flags], ZF_Mask : 0: Key ready? jz Ys Done VWMCa11 Release jmp 116_Po11_Loop VMMeal1 End_Nest_Exec Pop off executio Pop_Client_State st Reflect blocking int 16 now
ret
As another example, VDDINT.ASM
attemptsto emulate (rather than
reflect) a number of INT10hvideocalls, including functions 2 and 3 (get andset cursorposition), functions6 and7 (scroll up and down), function 9 (write character and attribute at cursorposition), and function 0Eh
(write TTY).It’s well worth reading this code (DDK\386\VDDVGA\ VDDINT.ASM) to see how Windows VxDs cantake over not only from
DOSbutalso from the BIOS.For example: Emulate this Get Cursor
Position call, if possible
vileGetcurs call VDD_Int_Can_Emulate jnz VI10_Reflect movex _ecx, Lebp.Client_BH] BEGIN Touch_Ist_Meg mov ax, WORD PTR DS:[460h mov [ebp.Client_CX] mov ax, WORD PTR DS:[450h+ecx*2] END_Touch_1st_Meg mov Cebp.Client_OX1.ax jmp VI1Exitemves
;0: can emulate INT 102 : ON : ECX = output page + get top & om lines of cursor ; Client CH,CL = cursor type get row/column Client DH.OL = cursor posn ; Call emulated, exit
Asa final example, VFD.ASMhooks INT 13h:
Unauthorized Windows 95
This Device hooks INT 13's and checks for the hig bit to be clear in the drive specification (DL). If the bit is clear, then Begin_Critical_Section ; is called and timer port trapping is disabled. When the bios INT 13 handler IRET's, then timer port trapping is reenabled and End_Critical_s + is called. INT 13's that have the high bit L set are simply reflected so that VHO can handle them
; Also if the INT 13 is a format command (AL=5), then VOMAD is called to disable OMA channel #3. This done, because the BIOS programmes the DMA channel for a large random OMA transfer that never occurs (the disk controller never actually performs DMA during a format. track operation) By ignoring this random programming of the OMA channel, YOMAD is able to work with allocating a smaller (more realistic) DMA buffer Whatthis all meansis that even BIOSinterrupts coming from DOS applications and from DOSsoftware loaded before Windowswill be handledin 32-bit protected mode by some VxD. In mostcases the VxD does some preprocessing,reflects the interrupt to V86 mode, and then possi-
bly does some postprocessing(via Call_When_VM_Returns).
In other words, Microsoft is effectively movinglarge parts of the BIOS into32-bit protected mode VxDs. In fact, this movement has been
going on for some time, probably withlittle realization outsidethe relatively small circle of VxD writers. For example, the VDD code to emulate rather than reflect some INT 10hcalls appears to have been written
in 1988, presumably for the Windows/386 3.x project. The more things
change, the moretheystaythe same.
Chapter 12
EXPLORING WITH WUSGTEST the V86TEST programusedin theprevious chapterhelpedillustrate the situations under which Windows does and does not need DOS. Inthis chapter we're goingto further explore the Windows-DOSrelationship by enhancing V86TESTin several ways. ¢
Using V86TESTrequires either redirecting Windows’ output to file, whichsilently disables 32BFA, or running V86TEST -QUERY, which pollutes the V86TESTresults with INT 21h
calls coming from the DOSbox.It’s true that Windowsdoesn’t treat DOSboxesin a substantiallydifferent way than does the
System VMin which Windowsapplications run, but DOSprogramsdotend to makecalls — suchas function 0Bh topoll the keyboard — that Windowsapplications don’t. Thesecalls clutter
up the V86TESTresults.
Thefirst issue — havingto redirect V86TEST’s outputto a
file — couldbeeasily addressed by changing V86TESTtowrite
out a logfile, as I did with the HOOKINTprogramback in Listing 10-1.
The second e — having to open a DOS box inorderto run V86TEST-QUERY— has a solution which, in a book ostensi-
bly about Windows programming,shouldbe obvious: write a
Windows version of V86TEST (WV86TEST). This isn’t really
a matterof putting a graphical userinterface on V86TEST. Instead, WV86TESTincreases the accuracy of V86
INT 21hlog.
Unauthorized Windows 95
¢ V86TESTlumpstogether DOScalls coming from Windowsapplications, from DOSapplications running under Windows, and from Windowsitself. Every time we run V86TEST,wesee the entire his-
tory of DOScalls, including those that Windows madeduringits initialization.
Althoughthis problem couldbepartially fixed by making V86TEST collect only INT 21h statistics during the period that Windowsis
truly up and running — V86TEST.C(Listing 10-1) could checkif
(state == WIN_INIT_DONE)before logging INT 21h calls — WV86TESThasa better solution: a Show Changes menuitemthat will let us focus on the DOScalls made by particular Win16 and Win32 applications. © Recall my complaint fromthe precedingchapterthat,bydefinition, V86TEST knowsnothing about INT21h calls that are not passed down to DOS. Just because V86TEST doesn’t see some INT 21h call, it doesn’t mean that Windows emulates thiscall in 32-bit pro-
tected mode.It’s equally possible that no one is making the INT21h call in thefirst place. V86TESTcan’t tell the difference betweencalls that Windows emulates andcalls that no one makes.
‘To solvethis last problem, the next twochapters will use WSPY21, a Windowsprogram that hooks INT 21h anddisplays the DOScalls that a Windowsapplicationthinksit’s making or that some DLLis making on
the application’s behalf. Using WSPY21, we’ll examine the DOSactivity generated by some common Windowsapplications. This chapter presents the code for WV86TESTand shows some
samplesessions with the program. The next two chapterswill then spend
a lotof timelookingat the Clockapplet in both Windows3.1 and Win-
dows 95. Comparing the output generated by WSPY21 with that generated by WV86TESTwill give us a much better idea of the DOScalls that Windowshandles — anddoesnot handle — in protected mode. Thenext twochaptersalso take several lengthyside trips to examine
somefascinatingsights in Windows95, including memory-mappedfiles,
thunking between 16- and 32-bit code, and demand-paged virtual memory. Thesesidetrips are all inspired by some odd-lookingresults displayed by WV86TESTand WSPY21.
Chapter 12: Exploring with WV86TEST
Breaking All Ties with 0S? WVS86TEST,as shownin Figure 12-1, is a Windowsapplication that communicates with the DOSversion of V86TEST(see Listing 10-1) loaded before Windows.
86 node /second
Ale un eee INT 240 canis: 2A: 674 20: 674 58: 19 55:4
Psien|fRwvecrest
“clock toma
_|
Figure 12-1: WV86TEST,running under Windows 95alongside the Win32 clock, shows the INT 21hcalls from Clock that Windows 95 sends down to V86-mode DOS.
Forexample, afterstarting WV86TESTunder Windows 95 and selecting the Show Changes andRefreshoptions, I used the WordPad toread in a 78K WinWord application that comes with Windows -DOC file andsave it out as a plain-AS' II TXT file. WV86TEST shows howthis lookedto real-mode DO
6 mod
Unauthorized Windows 95
Notice that thereare 7calls to the INT 21h functionsthat open,
close,read, or writefiles. At the sametime,there are plenty ofcalls to INT21h functions 0Eh, 2Ah, 2Ch, and 50h.
In another test, I started Calc, Microsoft’s calculator applet, did a few
calculations, browsed Calc’s on-line help (this starts the WinHelp program), exited Calc, and did a WV86TEST Refresh. Here’s how the slightly more than two minutes of CALC.EXE and WINHELP.EXE
activitylooked to DOS under Windows95, as logged by V86TESTand
reported by WV86TEST: 138 seconds elapsed 200 calls, 200 in V86 mode 1 INT 21/2F calls/second 10PL=3 200 calls VM #1 -- 200 calls INT 21h calls QE: 44 2A: 3
2C: 14 30: 2
AC: 2
5B: 129 55: 2
INT 2Fh calls 1:4
I happenedto still have myCURRDRIV.386from Chapter 7 loaded here, so function 19h (Get Current Drive)calls that normally would have
been sent down to DOSwereinstead consumedby the VxD in 32-bit protected mode.Evenso,this isn’t much DOSactivity to showfor running two Windowsapplications. DOShasseen two PSPscreated with undocumented function 55h (Create PSP), lots of function 50h (Set PSP)
activity, two programsexiting with function 4Ch,andsoon. Butthere’s
nofile I/O,aside perhaps from four network redirectorcalls (INT 2Fh function 11h).
Windows95is evidently bypassing DOS for mostservices. But there’s nothing brand newor Windows 95-specific about this. WfW3.11, with 32BFAenabled, showsjust aslittle DOSactivity for roughly the same
level of Calc and WinHelp activity:
185 seconds elapsed 59 call 6 mode @ INT 21/2F cal1s/second I0PL=3 9 calls VM #1 59 calls INT 21h calls 2h: 2 2: 2
30: 2
AC: 2
50: 43 55: 2
59
Chapter 12: Exploring with WV86TEST
Notonly is Windows 95’s capability to bypass DOSnothing new, but in this admittedly unscientific test, WfW3.11 bypassed DOSto a greater extent than Windows 95. Notethat, even though the WfWtest ran for a little longer than the Windows95 test, there were somewhat fewer Set PSPcalls than in Windows95 and no function 0Eh (Set Disk) calls.
But which DOScalls — regardless of whether DOS or Windows eventually handles them — are Calc and WinHelp generatingin thefirst place?
Running WW3.11 without 32BFA provides one wayto see the DOS
activity that 32BFA evidently absorbs. Here’s the same Calc/WinHelptest, this time under WW3.11 with 32BFA disabled (WIN /D:C):
223 seconds elapsed Is: 3 2:3 38: 2 2 PO 4C: 2
3B: 3 46: 7
30: 20 3E 90: 39 55
2 165 42: 131 57: 12 $9: 3
INT 2Fh calls i: 42 Here wesee the DOSfile I/Ocalls — such as function 3Dhto open files, 3Eh to close them,3Fh to read from file, and 42h to movethefile pointer — that Calc and WinHelp muststill be making when 32BFA is enabled, but that DOS won't see because IFSMgrhas usurpedits role. Table 12-1 presents the three sets of WV86TESTresults for Cale. Table 12-1: WV8GTESTresults for Calc/WinHelp Function
Windows 95
WfW with
WFW without
32BFA
32BFA
OEh Ah 2Ah 2Ch 30h 3Bh 3Dh 3Eh 3Fh 42h 43h
44 os 2 14 2 a = =
1 4 2 -
7 a 8 2 3 20 43 165 134 8
44h
=
=
24
4Th 4Ch
2
2
10 2
Unauthorized Windows 95
4Eh 50h 55h 57h 59h
129 2 -
35 2 2
7 39 2 12 5
All three environmentspass function 55h (Create PSP) and function 4Ch(Exit Program) down to DOS. Windows95 is generatinga lot of
calls to function 0Eh(Set Disk) andto function 2Ch (Get Time). And of the three environments, Windows95 appears to be makingthe heaviest use offunction 50h to set the current PSP.
Thisis all very strangeinlight of Microsoft's claims regarding Win-
dows95’s relationship to MS-DOS. For example:
Chicago is a 32-bit operating system. Windowsno longercanbe likened to a fancy paint job on an old MS-DOSYugo.Becausethe entire operating system is freshly designed from the ground up, you now have killer features such asthreads, memorymappedfiles, and asynch 1/0. — Dave Edson,“Seventeen Techniques for Preparing Your 16-bit Applications for Chicago,” Microsoft Systems Journal, February 1994, p. 15.
Oneof the cardinal rules of marketingis to push what youhave to sell todayrather than whatyou'll have tomorrow. Giventhatthis statement was writtenat least a year before the generalavailability of Windows95, it’s odd to see Microsoft notonly selling whatit won’t have until tomor-
row butpositively trashing (unless you think the Yugo is a good car) what
it has for sale today. Yes, we have no bananas!
Thekey assertion hereis that Windows95is “freshly designed from the groundup.” In fact, Windows95 is built on the foundation ofthe VMMcodewritten by Ralph Lipe, Aaron Reynolds, andothersin early
1988. For example, the VPICD.H header file included with the DDKis dated “13-Apr-1988 RAL,” VMDA.H is dated “05-May-1988 ARR,” and the all-important VMM.INCis dated “05-May 1988 RAL.” The core code in Windows 95’s VMMis anything but fresh. But thi: isa
goodthing, because the devil you knowis preferable to the devil you don’t know. However, we shouldn’t make too big a deal out of this “freshly
designed”claim from February 1994. The article carries a prominent
disclaimer that “The informationpresented hereis based on an early
prerelease of Chicago. Anything and everythingis subject to change.”
Furthermore, oneofthe files includedwith thearticle contains a truly wonderful 20-line disclaimer:
Chapter 12: Exploring with WV86TEST
Consult your physician before using this program. Batteries notincluded. May causedrowsiness,Not availablein all states.... Keep this and all software out of the reachof children. Parental guidance suggested. The buyer assumes all risks associatedwith using this product.(Actually, that one is very closeto the true state ofaffairs in software.] In caseofirritation,flush eyes with cold water and consult yourphysician. Not insured by the Federal Deposit Insurance Corporation. PLEASE NOTE: Some quantum physicstheories suggest that when the consumer is not directly observingthis product,it may cease to exist or will exist only in a vague and undeterminedstate.
Well, we've been warned, Let’s then turn to another Microsoft Systems Journalarticle thatisn’t so hedged with warnings: Thebig difference in Chicago's relationship with MS-DOS from that of Windows 3.1
is that if you only run Windows-basedapplications, you'll never execute any MS-DOS code. — Adrian King, “Windows, the Next Generation: An Advance Lookat the Architecture of Chicago,” Microsoft Systems Journal, January 1994,p. 18.
In the Calc/WinHelptest, we’re only running Windows-based applications(this was why we needed WV86TESTinthefirst place), yet
Table 12-1 shows that Windows95is quite clearlystill calling down to DOSto roughly the same extent that WfW 3.11 did. Atthis point, you might be very concerned about whatare sometimes called (as we'll getinto later) “Heisenberg”effects. WV86TESTtalks to V86TEST, whichis a real-mode DOSprogram. Microsoft Systems Journal quite specifically said “if you only run Windows-based applications, you'll never execute any MS-DOScode.” Perhaps V86TEST, although it loads before Windows,violates this condition. More generally, perhaps the DOSactivity that these programsreveal wouldn’t occurin thefirst place if these programsweren’t running. I address these concernsin detail in Chapter 14, where we’ll see conclusively that Windows95 calls down to DOSto the same extent whether or not V86TESTis loaded. For now, though,let me showthe “steady state” when only WV86TESTand V86TESTare runningso that I can try to assure you that WV86TESThaslittle effect on the Windows-
DOSrelationship:
1 seconds elapsed 2 calls, 2 in V86 mode 2 INT 21/2F cals/sec TOPL=3 - 2 calls WM #1 2 calls INT 21h calls 2a: 1 2C: 1
Unauthorized Windows 95
These two DOScalls, which get the date andtime, appear whenever
youselect Refresh from the WV86TEST menu. Thedisplay_results
function in WV86TEST.Clater in this chapter (Listing 12-2) calls the C time function, which in turn calls INT 21h functions 2Ah and 2Ch. These
twocalls need to be subtracted from any WV86TEST results. But in the Calc/WinHelptest, this still leaves us (both in WfW3.11 and in Windows 95) with calls to Create PSP, Set PSP, DOS exit, and a fewothers.
So what's the “big difference in Chicago’s relationship with MSDOS”? Adrian King’s Microsoft Systems Journalarticle cited previously
does address this issue:
‘As successive versions of Windows have appeared, each has supported more and moreof the MS-DOSINT-based software services, and Windows-based applications have had an ever-lessening needto switch in and out ofvirtual-86 modeto execute MS-DOScode.The big exception to this (until Windowsfor Workgroupsversion 3.11) was the support forthe file system services
This is certainly an accurate history of Windows’relationship with MS-DOS. Butin the nextsentence, the article says:
Chicago finally breaksall ties with the real-mode MS-DOScodeand, with few exceptions, even existing 16-bit Windows-based applicationswill follow a protected-mode path through the newFile Management Subsystem to the disk and back. WV86TEST showsthatthis sentenceis almost exactly wrong:
* The merefact that Windows 95 sends Set PSP calls involving Windowsapplications down to MS-DOS indicates that Windows95 hasn’t
brokenall ties with real-mode DOS.I don’t see any good reason why Windows 95 shouldbreak all ties with real-mode DOS, but Microsoft
oughtto stop claimingthatit has.
¢ The “new File Management Subsystem”isn’t new. IFSMgr, VFAT,
VCACHE,andso onin Windows 95 arelargelythe same as IFSMgr, VEFAT, VCACHE,andsoon in WW3.11. This should comeas no surprise, since Microsoft's ads for WFW3.11 explicitlysaid that its
32-bit file access came from Chicago:“Usingthe 32-bit file system fromour Chicago project, Windows for Workgroups performs 50% faster on disk-intensive tasks” (Microsoft advertisement, InfoWorld,
January10, 1994, p. 55).
Now, 32BFA in Windows 95 should be an improvement over that in
WEW3.11. After all, the flip-side to Microsoft’s boast that WfW3.11 in January 1994 included 32-bit code from Windows 95 (a product that wouldn’t be readyforatleast anotheryear) is that WW3.11
Chapter 12: Exploring with WV86TEST
contained pre-beta code. And, as a result of the way it used the WfW.
3.11 commercialrelease as a widespreadtest for its pre-beta code, Microsoft has improved 32BFA in Windows95.
But someofthese improvementsentail the re-knotting of someties to DOS that were too hastily broken in WW3.11: Windows95 is a lit-
tle more tied to DOSthan was WfW3.11. For example,recall from Chapter 8 (the “Global and Local INT 21h Hookers”section) that WEW3.11 wouldn’treflect file INT 21h calls to local hookers, but that Windows95 will.
* Having just told us that “Chicagofinally breaks all ties with the realmode MS-DOScode,” it’s hard to knowwhat to make ofthe next phrase: “with fewexceptions, even existing 16-bit Windows-based applicationswill followa protected-modepath.” Perhaps I’mlooking too carefully at some hastily chosen wording,butthere is a direct contradiction between“all” and“withfew exceptions,even.”Either Windows 95 breaksall ties with the real-mode MS-DOScodeorit doesn’t. WV86TESThas already shown usthat it doesn't. ‘Theextent of Windows95's separation fromreal-mode DOSis already quite impressive, and Microsoft doesn’t needto exaggerateit. Nor, having already advertised that WFW3.11 containeda significant chunk of the Windows95 project, should Microsoft now turn around
and claim that Windows 95’s relationship to DOS marksa significant departure from WFW3.11. Besides, the experience of WfW3.11
showsthat breaking too manyties with real-mode DOScan produce compatibility problems. Perhapsall Microsoft Systems Journal was trying to say was that Windows 95 keeps someties to DOSforthe sake of old DOS and Win16
software, but DOSis goneif the user runs only Win32 applications. The phrase, “with few exceptions, even existing 16-bit Windows-based applications will followa protected-mode path” seems to implythat without exception Win32 applicationswill never leave the 32-bit protectedmodepath. However,we'll see shortly (in “The Windows 95 Explorer and DOS”
section)thatthis isn’t reallytrue, either. Although Win32 applications can bypass DOStoa greater extent than Win16 applicationscan,the ties are still there. Win32 applicationsrely onessentially the same small but sig-
nificant core of real-mode DOScalls that Win16 applicationsrequire.
‘There’s absolutely nothing wrongwiththis reliance on a codebase that
Unauthorized Windows 95
has provenitself on somethinglike 100 million machines, and Microsoft should stop pandering to operating-systempurists by claimingthatrealmode DOSis gone.
WinWord and DOS In Figure 12-2, I used WinWordto open andsave a large documentin WEW3.11, both with and without 32BFA. I then saved WV86TEST’s
output toa file and comparedtheresults with diff, Unfortunately, I
neglected to use V86TEST -FILTER,so those pesky VMPoll broadcasts discussed in Chapter 11 (in the “Windows at Work?”section) showup in
the results. However, since we’re focusing on INT21h calls here, it does-
n'treally matter. < win /D:C (32BFA disabled) > win (32BFA enabled) < 62 seconds elapsed > 42 seconds elapsed < 41076 calls, 41076 in V86 mode > 47318 calls, 47318 in V86 mode < 662 INT 21/2F calls/second > 1126 INT 21/2F calls/second < 10PL=0 > TOPL=0
339 calls 403 calls
< T0PL > IOPL=3
40737 calls 46915 calls
VM #1 > WM #1
41076 calls 47318 calls
INT 21h calls 1A: 28 2A: > < 40: 60 >
14 2C: 16 3 1
30: 1
42: 596 43: 5
C4E: 28 50: 150 55: 1 > 50: 150 55: 1 NT 2Fh calls 1: 80 16: 39206 16: 47090 >
56: 2
3B: 8
3C: 3-30: 28 3E: 25 3F: 708
44: 42 45:1 45:1 14 1
1 1
47 47 58: 2
62: 41 DC: 1 62: 41 OC: 1
Chapter 12: Exploring with WV86TEST
INT 2Fh AH=16h calls < 07: 39206 > a7: 47090
Figure 12-2: WinWord File Open/Save, with and without 32BFA. In Figure 12-2, notice that the same operation took twenty seconds less with 32BFAenabled:
< 62 seconds elapsed > 42 seconds elapsed
This 32 percent(20 outof 62) performance improvementis consistent with InfoWorld’s findings (August 1994, 1994, p. 66) in an extensive review
of peer-to-peer network operating systems: With 32-bit file (32BFA) and disk (32BDA) access enabled, InfoWorld saw an improvementof between 30 and 33 percent over WfW3.11 without 32-bit access. With 32BFA and
32BDAenabled, WW3.11 gave better performance than any other peerto-peer networktested, including Artisoft’s LANtastic. (Novell’s Personal NetWare camein deadlast, taking 2:29 hours to completea task that WFEW3.11 completed in 1:48 without 32-bit access and 1:23 with
32-bit access; LANtastic took 1:43.)
Figure 12-2 indicates that Windowsgenerated morecalls to V86 mode with 32BFA enabled,butthis is entirely due to the VMPoll VxD broad-
casts. With 32BFA,the systemevidently goes idle more often. Notice that all calls came from VM#1, indicating that no DOSboxwasopen. I won’t say much about the IOPL=0 counts shown by WV86TEST,
sincethis topic was discussed in Chapter 10 (in the “IOPL andthe InterruptFlag” section). As mentionedthere, VMMemploys IOPL=0in V86 mode as part of the Call_When_VM_Ints_Enabled service. This
VMMserviceis used primarily by VPICDtosimulate hardware interrupts, such as the timertick, into a VM.To behavelike a genuine hardware PIC and to make VMslooklike genuine machines, VPICD mustnot send an interrupt to a VMthathasdisabled interrupts. It’s easy for VPICDtotell when a VMhasdisabledinterrupts (just check [ebp.Client_FLAGS)]), but howcanit gain control when the VMdecidesto reenable interrupts? With Call_When_VM_Ints_Enabled, naturally. By setting IOPL=0,this service causes the CLIinstruction to generate a GP fault. When VMMcatches this GP fault, it calls VPICD’s handler and resets IOPL=3.
Unauthorized Windows 95
By comparing the INT 21h calls logged with and without 32BFA,we can draw up a list of some INT21hcalls that can bypass DOS when 32BFAis enabled: Function
Number
Function
1Ah 3Bh 3Ch 3Dh 3Eh 3Fh 40h 44h 42h 43h 44h 4Eh 56h
Set Disk Transfer Address (DTA) Set CurrentDirectory Create File OpenFile Close File Read File Write File Delete File MoveFile Pointer (Lseek) Get/SetFile Attributes 1ocTL Find First File RenameFile
57h
Get/SetFile Date/Time
5Bh
Create NewFile
Notice that these are merelycalls for which Windowscan bypass DOS. Theabsenceof a call from the 32BFA portionof Figure 12-2 is
no proofthat 32BFA always bypasses DOSforthatcall. For example, if
WinWordhere had beenreading and/orwriting to a floppydisk, under WEW 3.11 — which, unlike Windows 95, does not provide 32BFA for
floppies — WV86TESTwould have shown Windowspassing many of the INT 21h file I/O calls down to DOS.
As another example, consider INT21h function 44h OCTL). Although some IOCTLcalls such as 4408h (Does Device Use Removable Media?) and 4409h (Is Drive Remote?) can be handled by 32BFA,it
seemsobviousthat there must be somedriver-specific I/O controlcalls that Windowspasses down to DOS device drivers.
In other words, WV86TEST’s
outputbyitself meanslittle.
WVS86TESTneeds to be used in conjunction with some other program, such as WSPY21, that indicates which INT 21hcalls have been gener-
ated on the Windowssideofthe feence. Returning to Figure 12-2, we can see that the following INT 21h calls are at least sometimes passed down to DOS, even with 32BFA:
Chapter 12: Exploring with WV86TEST
Function Number
Function
2Ah 2Ch 30h 45h 47h 50h 55h 59h 62h Dch
GetDate Get Time Get DOSVersion Duplicate File Handle Get Current Directory Set PSP Create PSP Get ExtendedErrorInformation Get PSP Novell NetWare: Get Connection Number
Figure 12-2 makes an extremelymisleading suggestion about the handling of network redirector (INT 2Fh function 11h)calls. Note that WV86TEST shows80 such calls without 32BFA and no calls with
32BEA. This seemsto suggest that 32BFA doesn’tpass networkredirec-
tor calls down to V86 mode. Butthis is false. Instead, in this particular test, when 32BFA was enabled, no INT2Fh function 11h calls were
generated inthefirst place. DOS itselfusuallyissues these calls; when 32BFAbypasses DOS, the networkredirectorcalls are also bypassed.
But when 32BFAcan’t bypass DOS(forexample,if you’re using a
CD-ROMdrive managed byMSCDEX under WfW3.11), Windows
will see the network redirectorcalls generated by MS-DOSandpass them back down to V86 mode.
The Windows 95 Explorer and 00S Cale, WinHelp, WordPad,and WinWord are all 16-bit Windows (Win16) applications. Because Microsoft seemsto imply that Win32 applications really and truly break all ties to the real-mode MS-DOScode, I also used WV86TESTwith the excellent Find File feature of the Windows 95 Explorer, which is a Win32 application (CAB32.EXE). I shut down every otherprogram except WV86TEST. The Soft-ICE/Windows (WINICE) ‘TASK commandconfirmedthat nothing wasrunning besides WV86TEST andthe standardtasks that are ahvays presentin Windows 95: S8:5P StackTop StackBot Stacklow TaskDB hQueue Events 0900:0000 90737000 0740000 1EEE EFF 0000
Unauthorized Windows 95
* 9000:0000 07:1F 8 KERNEL32
201C 3078 604
20)
0000 2000 e000 000 0000
Of these, BATMETER, CAB32, and KERNEL32 are Win32 tasks, and MSGSRV32 and TIMER are hidden(windowless) Win16 tasks that
Windows95 loads automatically. MSGSRV32 is describedinthe file MSGSRV32.EXEas the “Windows32-bit VxD Message Server” and “Microsoft Windows DOS386 WShell Server.” TIMER comes from
MMTASK.TSK(“Multimedia backgroundtask support module”). With V86TEST and WV86TESTloaded, I used the Explorer'sfile
finder(located on the Tools menu) tolocatethe *.Cfiles on myharddisk that contain thestring “foo”. Thereare 20 suchfiles on myharddisk;to find them, the Explorer mustlook through about 500directories andread840.C files. WV86TESTshowed how this furiouslevel ofactivity lookedto the real-mode DOScomponentof Windows95: 136 36 c @ INT 21/2F call 1OPL=3 3 36 calls VM #1
INT 21h calls War 2 Ar 3°
2Cr 348s 24 AED 180:
INT 2Fh calls
iM: 2
Before we get upset that a Win32 application under Windows 95 is
still calling the ostensibly defunct real-mode DOS code (“I’m not dead yet!”), let’s first take a moment tonotethat, in fact, the results shown by WVS86TESTare excellent: for a massively disk-intensive operation, real-
mode DOS sawalmost nothing. is quite amazing. Still, despite Microsoft's propaganda, we can see that Chicago (at least in this beta release) continues to use DOS toget the date andtime, to
manipulate the PSP, andso on But there’s somethinginteresting here: Whenthe searchis completed, if youkeepthefilefinder open onthe desktop, do a WV86TES refresh, and then performthesearch again, WV86TEST sees almost no
DOSactivity:
Chapter 12: Exploring with WV86TEST
Wow! And remember that one pair of function 2Ah and 2Chcalls
belongs to WV86TEST. Thus, once Explorer had loadedthefile finder, it took only threecalls to real-mode DOSto look through 500 directories and open840files; all the othercalls detected by WV86TESTmust have occurred when Explorer wasloadingthefile finder. Furthermore,it turns outthat the function 2Ah and 2Chcalls have nothingto do with findingfiles. If you turn on the CAB32 Show Clock option, when CAB32’s TrayClockWClass window receives a WM_TIMER message (which occurs once a minute), CAB32 calls Get-
LocalTime. As we'll see in Chapter 13 when we examine the Win32 version of Clock, GetLocalTime generates function 2Ah and 2Chcallsthat are sent downto real-mode DOS. What’left, then, is a single function 50h (Set PSP)call while the
Explorer plowed throughthe *.C files on myharddisk.
Thisis just one single measly DOScall, but trying to uphold
Microsoft’s “you'll never execute any MS-DOScode”claim in the face of
this callis like saying someoneis“just a little bit pregnant.” In Windows
95, you will execute some real-mode MS-DOScodeevenif youstick to
WVin32 applications.
PSPS and Other DOS Data in Windows 95 Set PSPis
aboutas close to DOSasyou can get. As I probably should
have explainedearlier, the Program Segment Prefix (PSP) is a DOS data
structure whose handleserves as the DOSprocess ID (PID). The PSP
itself is a 100h-byte structure (120h bytes in Windows95) containing
per-application “state” such as the openfile handletable and environmentsegment. Mostfile I/O operations in DOS mustbe performedin the context ofa particular PSP. MS-DOS has only one current PSP at
anygiven time; programschangeit bycalling INT 21h function 50h. For example, a DOS TSRthat popsup while another programis running mustcall function 50h to change DOS’s PSP before performinganyfile I/O(see Undocumented DOS,2d ed., pp. 560-561).
It’s significant that each Win32 application running in Windows 95
has not only a process ID, one or more thread IDs, and a surrogate Win16 task ID butalso a PSP. Thi: genuine DOSPSP located in conventional memory(thoughoffset 2Ch does contain a protected-mode selector to the environment segment).
Unauthorized Windows 95
Youcanseethisif you run the WINPSPprogram from Chapter 13 under Windows 95. There’s somethinga little unusual about that one function 50h (Set PSP)call that V86TESTdetected, though. To skip
aheadabit, even though V86TESTseesthiscall being sent down to real-mode DOS, the WSPY21 program, which hooks INT 21h onthe
Windows side ofthe fence, doesn’t see anyone generatingthiscall! Figure 12-3 shows what WSPY21 sawfrom CAB32, in its entirety, during
the two minutesit was grinding through myhard disk.
LFW (AE) Find First “C:\WINDOWS\cabinet .ini* Set DIA gon7: 0080 LFW (38) chDir"\ LEN (1) Find Close TOCTL (09) Is Dru Renote? 3 (osn) JOCTL (08) Is Drv Renoveadle? 3 (oan) TOCTL (OE) Get Log Drv Hap 3 (an) Lseek2 732 09600000 Lseek® 732 o9000000 saRead 722 (20h), © (#600) [cose 732 (ezocn)
Figure 12-3: WSPY21 showsthe INT 21hcalls from the Chicagoshell that are passed through the Win16 KERNEL.
WSPY21 sees INT21h calls generated onlyin a Windowsexecutable or by a Windows DLL onbehalfof a Win16 or Win32 executable. If a
VxD generates an INT 21h on behalf of a Win16 or Win32 executable, WSPY21 won't see it. This is what happened with the function 50h (Set
PSP)call. The DOSMGR VxD is generating the Set PSP call on CAB32’s
behalf. Some backgroundinformationis requiredto understand why. Windows Enhanced modehas always given each VMits ownseparate instance data copy of the DOS Swappable Data Area (SDA), which among otherthings contains DOS’s current PSP variable. (See “DOS
Instance Data and the SDA”in Chapter4.) Thus, even though real-mode DOSisasingle-tasking operating systemwith the notionofonly single
Chapter 12: Exploring with WV86TEST
current PSP, the miracleof instance data gives each VMits own version of the current PSP. However, multiple Windowsapplications, each with their own PSP, all run within the single System VM,and thusall share the single instance data copyof the DOS currentPSPvariable in the SDA. Thesin-
gle current PSPvariable in the System VMis multiplexed amongall
Win16 and Win32 tasks. Instance data works only on a per-VMbasis and so providesnoassistance to the multitasking that goes on within the Sys-
tem VM.Thisis typicalofthe separation between Windows’ upper API
layer andits lower VxDlayer. In Windows 95, the DOSMGR VxD’s handler for protected-mode INT21h calls does something new:If a protected-modeprogramiscalling INT 21h fromthe System VM, DOSMGR checksif the caller has a different PSP fromthe previouscaller. If it does, DOSMGRtakes whatever INT 21h call the Windows application wanted to make and temporarilyturnsit into a function 50hSet PSP call! Whenthis returns, DOSMGR switches back to the original INT 21h call andlets it go through. In this way, DOSMGR ensures that the INT21hcall is lined up with the correct PSP. The codeis fairly interesting: AH]
oA MOVZX MOV cup NZ
max INT 21h function number
Too_High EDX, [X}at_s EDX, [Xlat_Scrip VM_Handle] INT 21h coming from System VM? No: nothing special for prot-mode in ction’
EDX ECK,WORD PTR [Pre PSP_Okay first time through: don't ha EDX, [Ptr_This_PSP OX, COX] last time? CX, DX : same PSP PSP_Okay ; : Previous PM INT 21h cal ; different PSP. So hav
n System VM (Win app) had itch PSP
¢ Set PSP (21/50) EAX 08005000 FAX, CEBP.Client_AX] ; temp change call into 21/50 BX put new PSP into EDX, [EBP.Client_BX] Nested V86_IN
Unauthorized Windows 95
XCHG mov voy
X,CEBP.Client_8X] ; get back origina r next time v_PSP], DX [EBP.Client_EAX],EAX ; restore or
PSP_Okay CALL
[V86MNGR_XTat_API]
UMP
[End_Critical_Sectio
Do_Xlat UMP Ely
pat this point,
[V86MNGR_XTat_API]
Too_High: Mov EDX, Ca2coF7a oMP cazzB160 INT21 EAX [Begin_Nest_V86_Exec] EAX , oaaed, [Exec_Int]
[End_Nest_Exec] FAK
In Windows3.x, the KRNL386 Win16 DLL had to do something similar to keep INT21h calls from Win16 applicationsfromaccidentally misusing the PSP of other Win16 applications. KERNELhasits own protected-mode INT21h handler, which issues a NoHookDOSCall of function 50h during the first INT 2th call following a task switch (see Undocumented Windows, pp. 346-347). Why doesn’t KERNELjust switch PSPs wheneverit switchestasks? Matt Pietrek has a goodexplanationin Windows Internals (p. 422): Reschedule() now turns to the task of wakingup the incoming task... Note however that INT 21h function 50his not invoked to switch what DOS thinks is the current
PSP... Since Windowsrelies so heavily on the PSP and DOSforfile 1/0 [this was written before WW 3.11], you mightthink thatit would call DOS to change the current PSP each time a task switch happens. Asit turns out, KERNEL delays switching the PSP until it absolutely hasto, such as during a file 1/0 operation. Switching the PSPrequires a transition to DOS, a relatively slow process.If the only reasonfor a particular task switch is to deal with an intertask SendMessage(), it would get expen-
sive. Thus, KERNELholds out switching the current PSPuntil it's unavoidable. This causesproblems onoccasion, as the current PSP in DOS maynot match the current TDBin Windows.
Sothis mechanism hasbeen in place for years as part of KERNEL. Whythen does Windows 95 include PSP tracking in DOSMGRinstead ofjust continuing to use the KERNELcode? Because Win32 programs in Windows 95 don’t gothrough KERNELS INT 21h handler, Win32
Chapter 12: Exploring with WV86TEST
applications can’t issue direct INT 21h calls and mustinstead ask the ‘VWIN32 VxDtoissue INT 21h for them(see “Win32 File Handles and ‘Thunking”and the WIN32PSP.C example in Chapter 14). Thus the PSP tracking mustbe located in a VxD. This PSP-tracking code inside DOSMGRprobably explains why WV86TESTsees Windows 95 making heavier use than WEW3.11 of the Set PSP call. On the other hand,it’s importantto realize that DOSMGRdoesnot switch PSPsfor every single INT 21h call. It does this only for those INT21h calls thatwill be sent down to real-mode DOS. Thatis not a deliberate decision that DOSMGR makes, however. By the time DOSMGRsees an INT 21h call, that call will be sent downto real-
mode DOS. Thereasonforthis is simple: IFSMgr hooks the V86 INT 21h hookchain after DOSMGR,andtherefore sees INT 21h callsbefore DOSMGR.When IFSMgr decidesto handle call in protected mode,its INT 21h handlerclears the carry flag (CLC) before returning to VMM. As explained in the DDK documentation for Hook_V86_Int_Chain,
when a VxD’s V86interrupt hookclears the carry flag, VMM won’t pass theinterrupt to any other VxDs: If the hookprocedureservices the interrupt,it must clear the carry flag to prevent the system from passingthe interrupt to the next hook procedure. Thus, when IFSMgrdecides to handle a call in protected mode, it not only keepsthe call away from real-mode DOS butalso keepsthe call
awayfrom any VxDsthatinstalled INT 21h handlers before IFSMgrdid. In fact, 32BFA’s consumption of INT21h calls in protected mode and its failure to reflect INT21h calls to real-mode DOS are reallyjust inciden-
tal by-products of IFSMgr’s decision notto pass these INT 21h calls onto previously loaded VxDs, such as DOSMGRand VMM, that would
reflect thecall to real-mode DOS. Because IFSMegrwill have already picked offall INT 21h callsthat it intendsto service in protected mode, DOSMGR will only do its Set PSP switcheroo for those INT 21h calls that are going down to DOS. In this
case, IFSMgr’s blockage of INT 21h calls from other VxDs works out
well. In other cases,it has produced unintended consequences.
For example, DOSMGR’s INT 21hhook also tracks DOS file /O
calls to support the FileSysChange feature in Windows.If FileSys-
Change=ON in SYSTEM.INI, DOSMGR broadcastsnotifications of file
anddirectory creation, deletion,and so on to the WindowsFile Manager,
orto any other program thathascalled the FileCdr function (see Undocu-
mented Windows, Chapter 4, and WM_FILESYSCHANGE in Chapter 6).
Unauthorized Windows 95
But there’s one problem:If 32BFAis enabled,the FileSysChange=ONsetting hasnoeffect because IFSMgrdoesn’tpassthe relevant INT21h calls along to the VxDs(such as DOSMGR)thatcalled Hook_V86_Int_Chain beforeit. The order of VxDsin the V86 interrupt hook chain can make an
enormousdifference.(It’s just like the load-order dependency of DOS
TSRsin the early 1980s.) IFSMgr’s preemptionof FileSysChangeis just oneofthe unintendedeffects of 32BFA. And 32BFAin turnreallyis just a side-effect of the ability Hook_V86_Int_Chain functionshaveto refuse
previously-loaded VxDstherightto see interrupts. Butbackto the topic of PSPs. Windows 95 has additional mecha-
nismsfor manipulating the PSP. Since DOS’s implementationofthe Get andSet PSPfunctionsareso simple (see Undocumented DOS,2d ed., pp. 287-288), and sinceit’s easy to manipulate DOS variables from a VxD (see CURRDRIV.386 in Chapter 8), it isn’t surprising that VMMin Windows 95 provides a Get_Set_Real_DOS_PSP service:
Input AX EB VWicall Get. Output (EDX destroyed) AX = PSP (if getting)
Although undocumented, this serviceis hi ily used by the VWIN32 VxD. VWIN32 calls VMM"s Call_When_’ k_Switchedservice, passing it the address of a function. Whenever V vitchestasks,it then calls this VWIN32 function, which switches PSPs: CALL_WHEN_TASK_SWITCHED_PROC $3 WIN32 xor eck ViMcall Gi Handle ;: loader turns into mov ebx, [SysVMHandlel! VMMcaT1 a|_D0S_PSP mov [es mov ax r Cedx+56h WV ecx VM_Handle loader turns into mov ebx, [SysVMHandlel! Get_Set_Real_D0S_PSP VWNicall ContextSwitch
t:
loads CR3 (Page Directory Base register)
Get_Set_Real_DOS_PSPdoesn’t directly manipulate DOS’s currentPSPvariable, which is locatedat offset 10h in the SDA.Instead, it manipulates the VM’instancedata copyof the SDA. When the VMis next switchedin, VMM‘s page-fault handlercopies this instance data — including the current-PSPvariable — into low DOS memory. When
Chapter 12: Exploring with WV86TEST
Windows 95 swapscontexts, it must keep DOSinformed. The DOS SDA wasdesignedforjust this sort of thing: building a multitasking operating systemontop of a thin layerof single-tasking DOS. As explainedin the “DOS Instance Data and the SDA”section of Chapter 4,
the DOS SDA and Windows instance data go hand-in-hand.
With Get_Set_Real_DOS_PSP, VMMis supplying 32-bit protected-
modecodeto indirectly manipulate DOS data. Such manipulation of real-mode DOS data from 32-bit VxD codeis a frequent occurrence in
Windows 95. For example, duringinitialization, the Windows 95 IFSMgrcreates protected-modepointers to several key DOSinternal data
structures, including the SDA and SysVars (also known asthe “List of Lists”). It is worth examining this grungy undocumented DOScode:
50436 5043A 5043F 50445 50449 50440 S04de 50451 50453
; fragment of Windows 95 IFSMgr initializ on (6 InDOS flag) to get linear address try Use INT 21h func 34h si; of DOS SDA. LIN_SDA u: d all over IFSMgr! moy byte ptr Cebp.Client_AH].34h mov eax,21h :; Call INT 21h fune 24h (Get InDOS Flag vWMcal] Exec_Int Vient_ES] movzx ecx,word ptr movzx eax,word ptr ptr! . dec eax name); Tused DOSDIR and LFNDIR totest all the standard environments.
(The functions used by LFNDIR are available only in Windows 95.) In
all cases, the programlogged 494 Find First Calls (I didn’t create any new subdirectories while runningthe tests) and between 11,311 and 11,319 Find Next calls (I must have created a few newfiles duringthetest). For
each environment,I ran the programs twice to include anycacheeffect. Table 12-2 summarizes theresults ofthis test. The Clocks column showsthe time (in standard 55 millisecond clocks) for each run, plus the combinedtimefor the tworuns.
Unauthorized Windows 95
Table 12-2: Walking a Directory Structure Configuration
Real-mode MS-DOS SmartDrv WIW 3.11 32BFA Chicago DOSDIR Chicago LFNDIR Ou)
Clocks
Calls/Clock
Seconds
17 24 36 17 24
72 58 34 74 50
659+654=1313 548+513=1061 538+82=620 953+409=1362 699+216=915
Just to be compulsive, I used V86TESTto see what real-mode DOS activity LFNDIRwasgenerating in Windows 95. There was almost no such activity, showing once again that even real-mode DOSprograms don’t necessarily require real-mode DOS: VM #2 -~ 121 calls
INT 21h calls: 19:5 1A: 2 25: 16 29: 6 3E: 30 40: 10 44: 3 48: 4
2A: 1 49: 2
2: 1 AAD 2
30: 2 ABs 2
35: 8 3B AC: 2D: 2
In contrast, DOSDIRhits DOSplenty oftimes under Windows95: VM #2 - 48879 calls
INT 21h 19:5 35: 8 4C: 2
calls: 1A: 28628 «25: 16 29: 6 2A: 1 2:1: I 38: 2 3: 30 Ad: 10 44: 3 48: 449: 2 40: 2 4F: 11819
Since DOSDIR and LFNDIRareessentially the same program, the difference between 74 seconds for DOSDIR and 50 secondsfor
LFNDIRgives someideaofthe true cost of a real-mode DOScall. Or perhapsthisis just Microsoft’s subtle way of getting programmersto use Win32 or the new DOS LEN services. At the same time, WfW3.11 comes out as the clear winner here: DOSDIR ran significantly faster under WfW’s 32BFAthan even
LFNDIRdid under Chicago's. Ofcourse,it’s important to remember that Chicagois still in beta andthatthe final Windows 95 may well performbetter than this. Still, even this beta aberrationtells us something: The idea that Windows 95 “breaksall ties with the real-mode MS-DOScode”is almost
meaningless, because breakingties with MS-DOSis doneona case-by-
case, function-by-function basis.If one day the verylast INT 21h call that usedto be shipped downto real-mode DOSisfinally handled bya protected-mode VxD, would that constitute a qualitative transformation in
Chapter 12: Exploring with WV86TEST
Windows? No. Thereal transformation took place years ago, when Ralph Lipe, Aaron Reynolds, and others were writing VMMandgivingit functions such as Hook_V86_Int_Chain. Everything you need to know about Windows’relationship to DOS, you can learn by reading and re-reading that one sentence quotedearlier from the DDK documentation for Hook_V86_Int_Chain:“If the hook procedure [such as IFSMgr’s INT 21h handler] services the interrupt, it mustclear the carryflag to prevent the system from passingtheinterruptto the next hook procedure.”
The WUBGTEST Code Having spent sometime examining WV86TEST’s output, we should now look at how the programproduces this output. Listing 12-2 shows thesource code for WV86TEST, which uses the WINIOlibrary (provided on the disk). WINIO lets Windowsapplicationsuse C stdio functionssuch as printf and provides functions such as winio_setmenufunc and wmhandler_set, which makeit easy to create menus and handle messages. To retrieve statistics from the resident DOSversion of V86TEST, WV86TESTuses the real_int86x and map_realfunctions from the PROTlibrary (also on thedisk). WV86TESThasa .DEFfile containing the following statement: STUB ‘v86ti
tiexe’
This binds the DOS and Windowsversions togetherin a single executable. There’s a lot more that could be accomplished with this: V86TESTcould hook INT 2Fh function 160Bh (TSR Identify) and tell Windowsto automatically start WV86TEST;this is what the COUNT-
DOSprogram discussed in Chapter 3 does. Conversely, if WV86TEST finds that V86TESTisn’t resident (the get_stats functionfails), WV86-
TESTcould use the WindowsAPI functions ExitWindows(EW_ RESTARTWINDOWS) andExitWindowsExecto give the user the option ofrestarting Windows under V86TEST. Theseexercises areleft
for you to pursue in yourfree time. Listing 12-2: WV86TEST.C /* take over INT 21h and INT 2Fh, count calls in V86 mode WYQ6TEST.C winiobe wvB6test prot B6test.exe Uses wv86test.def with STUB '\unauthw\y
#include
Unauthorized Windows 95
#include finclude #include #include nelude clude
"windows.h” de “winio.h" “wmhand| rh" ude “prot .h*
typedef uns ned short WORD def uns ned Tong OWORI VM_MAX define GET_STATS define SIGNATURE
OxOFFFF > *V86TEST*
fidefine VXD_MAX He VXDLOTHER
—Ox100 VXD_MAX
typedef enum ( NO_LWIN, WIN_INIT_BEGIN WIN_INIT_DONE, WIN_FIN WIN_FIN NUM_STATES STATE:
got / got / got got
static char *state_str[NUM_STATES) Before Windows starte: During Windows init", hile Windows running "During Windows exit" "After Windows exited",
WIN_INIT_NOTIFY WIN_INIT_COMPLE WIN_EXIT_BEGIN WIN_EXIT_NOTIFY
WIN_INIT_NOT WIN_INIT_COMPLETE WIN_EXIT_BEGIN WIN_EXIT_NOTIFY
#pragma pack(1)
typ lef struct char signature(8 DWORD calls{NUM_STATES], v86_cal1s{NUM_STATES] DWORD iopl_count [4]; DWORD vnc VM_MAX+1] DWORD int2i{oxiea); WORD int2ftaxiaa], in f1600x100), int2f1607LVXD_OTHERH] art, end:
display_changes = 0 sh = 0; do_auto_r
Chapter 12: Exploring with WV86TEST
INT htimer = & STAT
void display_results(STATS far *fp2)
F (1 (delta = et'sizeof(STATS)))) fail(*Insufficient memory"); Show chang : first copy the new stats over to delta _fmemcpy(delta, fp2, si F(STATS)) Then the previo s stats to get changes ime(&del ta~>end): elapsed de d fp->end delta->cal1s(WIN_INIT_DONE] fp->callsCWIN_INIT_DONE]; 6_calls{WIN_INIT_D fp->v86_cal1s{WIN_INIT_DONE]; conds elapsed\n", elap: calls, Slu in 6 mode\n", cal 1s(WIN_INIT_OONE ta->v86_cal]sCWIN_INI 1/2F calls/second\n" sTWIN_INIT_OONE] / elapsed):
for (1-0; 14;
14+! count{i] -= fp->iop]_countl {]: J tp->vmli
delta->vm{VM_OTHER] -= fp->vmCVM_OTHER] for (i-O; 1int2fti] -= fp->int2ftil: ta->int2fl6li] -= fp->int2#l6lid: get VAD_OTHERtoo int2fleg7{i] -= fp->int2flea7tt) a; have display_results work on delta ‘mem
for (i=NO_WIN; icalls(WIN_INIT_OONE} / elapsed)
for (i=; 164: i++) if (fp->topl_count[i]) printf("I0PL=8d
%lu calls\n", i, fp->iopl_count(i]);
for (1-0; ivmlil) printf("VM #84 lu calls\n", i, fp->v if (fp->vmLVM_OTHER]) printf("VM > #%d - $lu calls\n", VM_MAX, fp->vm[VM_OTHER]);
define PRINT_CALLS(s, fp) { \ DWORD *p: \ printf(*\nts:\n", (5)): \ for (i=0, p-fp; iint21); PRINT_CALLS(*\nINT 2Fh calls", fp->int2f) PRINT_CALLS(*\nINT 2Fh AH=16h calls", fp->int2fl6) PRINT_CALLS(*\nINT 2Fh AX=1607h calls", fp->int2f1607); if (fp->int2f16@7[VXD_OTHER])
printf("VxO>#204X: STu\n", VXO_MAX, fp->int2F1607CVXD_OTHERT):
printf("\n\n"); fmemepy(stats, fp2, sizeof(STATS)): time(&stats->end) if (display_chang ) free(delta);
STATS far *get_s ts(void) ( union REGS r struct STATS Pom:
call resident copy of V86TEST
Chapter 12: Exploring with WV86TEST
Memset(&s, @, sizeof(s)); real_int86x(Ox2f, &r, &r, &S) // real_int@6x in PROT.C if (s i) return @ fp = MK_FP(s.es, r.x.bx) if ((fp = map_real(fp, sizeof(STATS))) 8) / map_real in PROT.C return @ return (_fstremp(fp->s ature, SIGNATURE) 0)? fp: 0 void free_stats(HWND hwnd) free_mapped_linear(fp); | etercreteeeetreereteeeeceeree ceegeeerccerreeeccecerectcsteeetetea] * MENU HANDLERS (see MK_MENU in main) */ void refresh(HWND hwnd, int wID) ( winio_clear(hwnd) display_results(fp); void clear(HWNO hwnd, int wID) ( _fmemset(fp, @, sizeof(STATS)); |
void show_changes(HWND hwnd, int wI0) (
CheckMenultem(gmenu, 3, display_changes ? MF_UNCHEC ED: display_changes = | display_changes refresh(hwnd, wID);
MF_CHECKED
ong on_time(HWNO hwnd, unsigned message, WORD wParam, LONG 1Param) winio_clear(hwnd);
dispiay_results( fp); void auto_refresh(HWNO hwnd, int wID) if (do_auto_refresh)
// on, turn off
do_auto_refresh = 0: KillTimerChwnd, ntimer); CheckMenultem(gmenu, 4, MF_UNCHEC|
else
, turn on do_auto_refresh 1 wnhandler_set (hwnd, WM_TIMER, on_time}; if (1 (htimer SetTimer(hwnd, 1, 5000, NULL))) fail("Can't create timer"); CheckMenultem(gmenu, 4, MF_CHECKED);
every 5 seco
Unauthorized Windows 95
main(int argc, char *argvC]) ( HWND hwnd; int i; // only one instance: should put INT handler in OLL if (__hPrevinst) fail ("WV86TEST already running"): hwnd = winio_current(); gmenu = CreateMenu(); // global fidefine MK_MENU(id, str, func) { \ AppendMenu(gmenu, MF_STRING | MF_ENABLED, id, str); \ winio_setmenufunc(hwnd, id, func); \ "aClear*, clear) . "&Show Changes", show changes); . "hAuto-Refresh", auto_refresh) InsertMenu(winio_hmenumain(hwnd), 1, NF_STRING | MF_POPUP | MF_BYPOSITION, gmenu, “&Test"); DrawMenu8ar( hwnd) ;
if (1 (fp = get_stats())) ( JI Instead of failing, could do ExitWindowsexec of // VBGTEST and then ExitWindows( EW_RESTARTWINDOWS) . fail(*Can't get V86TEST statistics") 1 winio_onclose(hwnd, free_stats); if (1 (stats = malloc(sizeof(STATS))}) fail(*Insufficient memory"): display_results(fp): return 0; In WV86TEST.C, main (WINIOlets Windows programsuse a
standardmain function rather than the odd WinMain proposed bythe Windows SDK)installs some menu handlers, using a MK_MENU
macrothatcalls AppendMenuand winio_setmenufunc.For example, MK_MENU(1, “&Refresh”,refresh) meansthat, when a userselects Refresh from the WV86TEST menu, WINIO’’s WM_COMMAND
handlerwill call a function namedrefresh. Asnotedearlier, WV86TESTgets a protected-modepointer to the
V86TESTstatistics via the real_int86x and map_realfunctions from the PROTlibrary on the disk. These functionsin turn rely on DPMI INT 31h function 0300h (Simulate Real-Mode Interrupt) and on the Windows
APIfunctionsAllocSelector, SetSelectorBase, and SetSelectorLimit.
Chapter 12: Exploring with WV86TEST
WVS86TEST uses winio_onclosetoinstall a handler that, just before the program exits, frees up the selector used for the mapped-instatistics. The workhorse of WV86TESTis display_results, whichis called from each of the menu-handling functions. This normally just copies the mapped-instatistics to a local buffer anddisplaysthestatistics using WINIOSprintf function. WV86TESTfirst copies thestatistics, rather than workoff the mapped-in“live” ones belonging to V86TEST, so that thestatistics don’t change outfromunder the program if more DOScalls are generated in the middleofdisplay_results. If the user selects the Show Changes menuitem, WV86TESTsets the display_changesvariable. If this variable is set, the display_results function copiesthestatistics to a “delta” buffer, from whichit subtracts the previously-refreshedstatistics, and then it proceedsto displaythis delta buffer. ‘The Auto Refresh menu iteminstalls a timer, using the WindowsSet-
Timerfunction. Everyfive seconds (assuming no one has reprogrammed the timer), the timer goesoff, and theWMHANDLERmoduleof WINIOcalls WV86TEST’s on_timefunction, which WV86TEST installed with wmhandler_set. The on_timefunction simplycalls winio_ clear and display_results, therebyrefreshing the WV86TESTdisplay every five seconds.
Windows 95 and Protected-Mode DOS Here’s what we’ve learnedso far: * In Windows 95, non-file INT 21h calls from Win32, Win16, and DOSapplications are sent downto real-mode DOS. Windows95 doesn’t break “all ties with the real-mode MS-DOScode.” © Windows95 also doesn’t break all (or even many)ties with the real-
mode DOSdata. Windows 95 relies heavily on real-mode DOSdata structures such as the SDA, PSP, and DTA. However, IFSMgr does
accessthis datadirectly from protected mode.
© Windows95 relies heavily on INT21h calls, though usually these calls are serviced by IFSMgr in 32-bit protected mode. Althoughit isn’t true that Windows95 “breaksall ties with the real-mode MSDOScode,”it is true that protected-mode MS-DOSisheretostay. In
Windows95, you’rerunning a protected-mode version of MS-DOS
that uses the real-mode DOScodeand dataas a subservientassistant.
Unauthorized Windows 95
¢ To the large extent that Windows95 is not dependent on real-mode DOS, though,the sameis true of WfW 3.11. If anything, WFW is less
dependent on DOSthan is Windows 95. WE£W’s hostility to realmode DOScaused problems in someareas, so Windows95 backsoff a bit from this aggressive stance. ¢ Programsthat use the Win32 APIor the DOS LEN services can bypass DOStoa significantly greater extent than programsthatstick to the old DOS APIs. In addition to the Win32 file-management
API’s bypassing ofreal-mode DOScode(butnot, as wesaw, of INT
21h services), we'll also see in “Executable Loading and MemoryMappedFiles” in Chapter 14 that Win32 applications can bypass both the real-mode DOS code and protected-mode INT 21h by using memory-mappedfiles: But even Win32 programscontinueto implicitly use real-mode DOSdatastructures such as the SDA, PSP, and DTA. ¢ Win16 programs and DLLsthatavoided direct use of INT 21h or Dos3Call and instead used WindowsAPIfunctionssuch as _lopen or higher-levelservices such as the GetOpenFileName and GetSaveFileName commondialogs will end up using the new LFN services. Notice that while we’re discussing Windows-DOS relationsin gen-
eral, the subject of how Win32 applications relate to DOS keeps coming up. This in turn takesusinto the subject of how the Win32 and Win16 componentsof Windows95, particularly the Win32 and Win16 kernels (KERNEL32.DLL and KRNL386.EXE,respectively), relate to each
other. This subjectis discussed in detail in the next two chapters.
Chapter 13
Tuna! HeRnets2 Cais ARNLSB6 he WV86TESTprogram in the previous chapter was a big improvement (if I do say so myself) over the plain real-mode DOS-based V86TEST from Chapter 10. WV86TESTprovides somereal insights into how Windows and Win32 applicationsinteract with real-mode DOS. However, as I pointed outearlier, WV86TESTbyitself doesn’t tell
you much about those INT 21h calls that are absorbed inside protectedmode Windowsrather than passed down toreal-mode DOS. The problem is that WV86TESTdoesn’t know anything about which INT 21h
calls protected-mode Windowsapplications and DLLsare generating in thefirst place. This chapter presents WSPY21, a Windowsprogram that hooks INT 21h inside protected-mode Windows rather than down in V86 mode
DOS.For example, Figure 13-1 shows WSPY21 logging some INT 21h
calls made by the Windows 95 Explorer (which here happensto launch a
Windowsapplication with a long filename, contained in a folder with a long directory name). Because WSPY21 hooks INT 21h on the Windows side of the fence, the program can display the DOScalls that a Windowsapplication makes, or which a DLL is making on the application’s behalf. In contrast, V86TEST and WV86TESTwereoblivious to any INT 21hcalls that
Windowsdidn’t send downto real-mode DOS, and had noidea which part of Windows an INT21hcall was coming from. For example, since 32-bit file access in WfW3.11 and Windows 95 - wouldn’t absorbs most INT 21h file calls, V86TEST and WV86T!
see any ofthe following randomlyselectedcalls logged by WS PY21:
Unauthorized Windows 95
(4E) Find First '\\PROGPRESS1\EDIT\IDGREPOR\PP_MTM\*.txt* *\\PROGPRESS1\EDIT\INTERNET\DUMMIES\*. txt! (4E) Find First (3D) Open 'C:\WINDOWS\SYSTEM\COMPOBJ.OLL* (3D) Open 'C:\WINDOWS\SYSTEM\OLE2.DLL" (3D) Open ‘C:\WINOOWS\SYSTEM\STORAGE.OLL" (3D) Ope WINDOWS\SYSTEM\OLE2DISP.DLL* (3B) ChDir ‘\MSOFFICE* (30) Open 'C:\WINDOWS\SYSTEM\CTL3DV2.DLL" (3D) Open ‘C:\WINOOWS\SYSTEM\MSFFILE.OLL* (3D) Open 'C:\WINOOWS\SYSTEM\SDM. DLL" *(4B) Exec 'C:\NSOFFICE\MSOFFICE.EXE* (28) tocte (0) Gee Log ore hap (ean) PP (SF) Read 61% (8266n), 64 (O4On) envae). (3) (4) head Useekee1H61sCazeeny, eovovinebe (a0Kon) | envae> | SChose> =(35) (Gr) meas etm reste (azeen),tSP'7500 9s Canzon) |
(onde) CDHrn), 256 (0100)| Senoa2> (71) “(in) Lim Set 01m Donk: Unauthorized Vindows 95\Wind (a0) enbies : (Ea) Set fst 7s (on,
Sp... (1A) Set DTA 1C5F:0080 (71) LFN (6C) Open/Create C:\WINDOWS\HELP\CALC.HLP* LEN (6C) Open/Create \WI JDOWS\CALC. ANN’ Extended Error I °
(71) LEN (6C) Open/Create 1 WINDOWS \HELP\CALC. G10"
(2F) (1A) (4E) (1A)
Get DTA Set DTA 1B07:353E WINDOWS \HELP\CALC. CNT" Find First Set DTA 1C5F:0080
(71) LFN (6C) Open/Create
DOWS\SYSTEM\commctr] diy!
(50) Set PSP 7263 (1C5Fh) (42) Lseek® 5 00005619 (0005h) 9 (9009h) (3F) (42) L: 5 00005622 5 (0005h), 14 (@00En) (3F) i peg ete (00) 7 (OOATh) (50) S (@2EEh) (3E) C (00) Exit 167 (O0A7h) (50) Set PSP (o2e8h CALCD (3E) Clos
Before wegetintothespecifics of this output — in particular, why a Win32 application such as CAB32 is calling the INT 21h EXEC func-
tion, creating a real-mode DOSPSP, setting the current PSP and DTA,
and generally cavorting aboutlike a cheap DOS program — it’s important to first understand a fewgeneral points aboutthe outputthat WSPY21 produces. ‘Thefirst pointis that the name that WSPY21 showsfor each INT 21h call, such as CAB32, CALC, or WINHELP, is the module name
Chapter 13: Thunk! KERNEL32Calls KRNL386
belonging to the currenttask at thetimeof the INT 21h call. WSPY21 extracts the namefromoffset OF2h inthecurrent ‘Task Data Block (TDB; see Undocumented Windows, Chapter 5). WSPY21.Cuses code somewhat like the following: printf("", MK_FP(GetCurrentTask(), Oxf2), 8
But when WSPY21 calls GetCurrentTask, whydoesn’t this just get back WSPY21’s owntask handle? Becauseit isWSPY21’s INT 21h han-
dlers that call GetCurrentTask. When WSPY21° interrupt handlers are running, WSPY21 is not necessarily the currenttask. Like some Windows APIcallbacks, interrupt handlers runin the context of whatever task was currentat the time ofthe interrupt. Since WSPY21 makesfew
INT21h calls, this will usually be some task other than WSPY21. During initialization, WSPY21 uses GetCurrentTask to get its own
task ID;the interrupt handlerswill filter out any INT21h calls coming from WSPY21 itself. WSPY21 usuallyonly calls INT 21h when you save
the WSPY21 log outto file. To digressslightly, you won’t see any code for this in WSPY21.C (shown inthis chapter), because WINIO automat-
icallygives all WINIOprogramsa File/Save Buffer... menu item. The WINIOcode to support this menuitemuses the GetSaveFileName commondialog, and then saves out the WINIO buffertodisk with the _Icreat, _Iwrite, and _Iclose APIs. The _Icreat call turns into an INT 21h function 716Ch, so WSPY21 (or any other WINIO program)can save
files with long names in Windows 95, even thoughthis was never a considerationin the design of WIN his wouldn’t work if WINIO had employed direct INT21h calls or the C run-timelibraryinstead of the _boxx APIs (which, incidentally — how’s this fora second-level digreswere once undocumented;see the section on “Undocumented sion? File I/O Functions”inthefirst [1988] edition of Charles Petzold’s classic
Programming Windows).
See? It pays to use the Windows APIs, even once-undocumented
ones. However, while WINIO applicationscanwrite out a long filename in Windows95, like other old Win16 applications they cannot reada long filename back in — darn confusingforthe user! Popping backtothe task namesdisplayed by WSPY21, all Win32 applications have a Win16 TDB surrogate, so WSPY21’s technique for
getting task namesalso works for Win32 applications, whether running in Windows3.x with Win32s orin Windows 95. In a moment, we'll see
whyall Win32 applications come to have a Win16 TDBin thefirst pla the reason is significant.
Unauthorized Windows 95
When WSPY21 shows a task’s module name such as CAB32 or
CALCassociated with an INT 21h call, it usually means not that the applicationitself called INT21h but that some dynamiclinklibrary (DLL)called INT 21h on the current task’s behalf. DLLs aren’t tasks (though, interestingly, the KERNEL32 DLL in Windows95 does have
an associated KERNEL32 task). Whenanapplication calls a Windows API, the DLL providing that API doesnot temporarily become the currenttask (as it mightina client/server operating system). Instead, the current task just “steps aroundto the otherside of the counter”(as Gor-
don Letwin nicely explains this point in his Inside OS/2) and runs the API code in the DLL.
Onefinal general point about WSPY21’s output: as we'll see when we examine WSPY21.C towardthe end of this chapter, WSPY21 has two
INT21hhandlers. Oneis installed with the DPMISet ProtectedMode Interrupt Vector function (INT 31h function 0205h), andthe other is installed with an undocumented Windows API, GetSetKernelDosProc
(Undocumented Windows, pp. 188, 271-273). The DPMIcall lets WSPY21 stick a protected-mode INT 21h handler before the one in the Win16
KERNEL;GetSetKernelDosProclets WSPY21 insert another handler after KERNEL,but before the first VxD-based protected-mode INT 21h handler. All this will be explainedin the usual gory detail towardthe endofthe chapter. For now,all that mattersis that an asterisk (*) in WSPY21’s out-
put meansthat the INT 21h call wasfirst seen at the spotcalled KernelDosProc, where KERNEL is about to hand INT 21h off to the VxD protected-mode INT21hchain.A blankindicatesthe call wasfirst seen
earlier(or higher, depending on howyoulookatit) in KERNELINT.
21h handler.If the INT 21h handler sawacall,WSPY21 doesn’t bother
showingit again at KernelDosProcunless you specify the WSPY21 -SHOWALLswitch.
Later, -SHOWALL will let us see that some INT 21h functions in
Windows bypass real-mode DOS — andforyears andyears have bypassedreal-mode DOS — because KERNEL (rather than a VxD such as IFSMgr) consumes them. Thebest example is INT 21hfunction 4Bh (EXEC). Neither real-mode DOS nor even a Windows VxD would know what to do with the E. f a Win16 executable, and so KERNEL
INT 21h handler deals with this call (decomposingit, naturally, into other DOScalls, such as File Open; see “Win32 File Handles and
Thunking”in Chapter14).
Chapter 13: Thunk! KERNEL32 Calls KRNL386
CABS2: HERMELS2 Uses the WintG KERNEL ‘The WSPY21 log shownin the preceding section startedout in CAB32, the Windows95 Explorer/Cabinet. The log shows that whenI clicked on the Calc icon, Explorer (or a DLL actingon its behalf) called function 4Bh to start CALC.EXE,called function 5h to give ita PSP, and so on. ‘We knowfrom WV86TESTthat Windowswill handle the function 4Bh execcall itself (for the reason just givenat the end of the preceding section). Onthe other hand, we also knowfrom WVS86TESTthat Windows will send the function 55h Create PSP call down to DOS. Cale is a Win16 application. What happens when weuse a Win32 application such as CAB32 to run another Win32 application? Although Win32 applications such as CAB32 do not use INT 21hfunction 4Bh to run other Win32 applications, WSPY21 will see a Create PSPcall whenever you launch a Win32 application. This, as I’ve said,is significant; we'll soon see why. Thefollowing WSPY?1 log shows someof the INT 21h activity generated whenI launched Clock, WinBezMT, andFreeCell from the Windows 95 Explorer, let them runfor a while, and then closed them.I also used Find File and ControlPanel, which are built into the Explorer. SP 7431 (1007h), 256 (0100) LFN (38) ChDir *\WENOOWS* PSP 4719 (126Fh) t PSP 167 (O0A eekd 730 000003 Read 730 (02DAn), 217 (00D9h) e@A7h) PSP 7
1CAFh), 256 (0100h) . 256 (8100h)
Ox808X\n", 6(0x808X, \"85 printf("GetProcaddr mod, argv(2}, fp):
JI major cop-out:
1 should show how to cal QT_Thunk!
Unauthorized Windows 95
You can tryout Win32-to-Win16 dynamic linking bytyping a module nameand function nameon the program’s commandline. Forexample: C: \UNAUTHW>dyn1nk32_ keri 1 getselect kernel") 000001 2F getselectorbase") ==> 0x01174BE0 C:\UNAUTHW>d:
LoadLibrary
GetProcAddre:
cplapplet™) ==> 0x226F029¢
It’s all well and good for SHELL32!Control_RunDLL, a Win32
function, to owna selector:offset function pointer to SYSDM!CplApplet, a Win16 function. (“That's nice, dear.”) Butbyitself, SHELL32’s possession of a far 16-bit function pointer to SYSDM is like a telephone
number withouta telephone, or an address without a modeoftransportation. How’s a Win32 DLL like SHELL32 going to call down to a Winl6
DLLlike SYSDM? Gee, somehowthis question remindsmeofa foolish
pop song aboutan “uptowngirl” (Win32) and a “downtown boy” (Win16), but perhapsI’mjustbeing fanciful.
Howare these two going to get together?It’s fairly simple,really. SHELL32!Control_RunDLL can call SYSDM!CplApplet in the same
waythat KERNEL32!LoadLibrary16 called KERNEL!LoadLibrary or that KERNEL32!GetProcAddress16 called KERNEL!GetProcAddress:
via QT_Thunk (whose workings we'll examineindetailalittle later). In Windows 95, thunks are what make the world goaround.
In additiontotelling us how the Win32 Control Panelcalls the CplApplet routinein Win16 .CPLfiles, the very existence of the LoadLibrary16 and GetProcAddress16 functions in KERNEL32 is significant.
Here we have KERNEL32 APIs (which, although undocumented, are heavily used by the rest of the system), whoseentire purposeis to thunk downto their Winl6 KERNEL equivalents.
In fact, KERNEL32°scapability to thunk down to KERNELis the basis forall other 32/16 thunking in Windows95, such as communication between USER32 and USER andbetween GDI32 and GDI, because ini-
tialization of these thunks requires LoadLibrary16 and GetProcAddress-
16. A debuggerbreakpoint placed onthese routines during Windows 95 zation reveals the following thunk-related dynamiclinks: ization yl6 GDI .EXE cAddres iThkCon FT_GdiFThKTAI FdThkConnect ionDataSL
Chapter 13: Thunk! KERNEL32 Calls KRNL386
IemThkConnect j onDatast LoadLibraryl6 USER. EXE GetProcAddress16 UsrThkConnectiondatals MsgThkConnectionDataLS FT_UsrF ThkThkConnectionData FT_UsrF2ThkThkConnectionData Usr32thkConnectionDataSt Start Clock: LoadLibrary16 COMMDLG.OLL GetProcAddress16 Dl gThkConnect jonDataLs Start Font Manager: LoadLibrary16 SYSTHUNK.OLL GetProcAddress16 FT_L2FThkThkConnectionData Examine File Properties: LoadLibrary16 VER.DLL GetProcAddress16 FT_VerFThkThkConnect ionData
Besides LoadLibrary16 and GetProcAddress16, other KERNEL32 APIs based on the Winl6 KERNELinclude FreeLibrary16, GlobalAlloc16, and GlobalLock16.In addition, the KERNEL32 thunktable mentionedearlier containspointers to many Winl6 KERNEL (KRNL386)
routines whose namesdon’t appear in the Windows95 binaries. To see howextensively these KERNEL32->KRNL386 thunks are used, you can
place a debugger breakpoint on the code where KERNEL32 has a thunk numberin the CLregister and is aboutto index into the thunktable: 0137:BFFB7C44 «XOR CK, ECK 0137:BFFB7C46 MOV CL, LEBP-04] ; thunk number ; thunk tabl EDX, (00030464+4*ECK] 0137:BFFB7C49 MOV 0137:BFFB7C5O MOV EAX,BFF71247 : offset32 Ott 0137:BFFB7C55 UMP EAX A breakpointplaced on this codeis hit almost twenty times when
starting up a Win32 application such as Clock and aboutan equal number oftimes whenexiting the Win32 application. Mileage mayvary depending on the Win32 application, of course, but for whatit’s worth,
thefollowing indicates the KERNEL32->KRNL386activity generated bystarting and exiting the Win32 Clock: 31, 32,
26,
36, 34, 3€ (x3), 1E (x6), 1C (x5)
Clock appears on display
ock now running (no K32->K16 thunks while running) Close Clock 1B (x3), 2F, 30 (x3), 33 (x2), 29 (x2), 30
Of these, thunk 30h is the Set PSP/Exit cleanuproutine mentionedpreviously, 36h is LoadLibrary16, and 34h is GetProcAddress16.
Unauthorized Windows 95
I’ve been emphasizing these cases where KERNEL32 thunks downto
KRNL386 mostly because Microsoft has claimed such thunks don’texist. Therearealso plentyof important cases where KRNL386thunks up to
KERNEL32, just as Microsoft says. For example, in the preceding chapter (in the section titled “Win32 FindNextFile is INT 21h Function 714Fh”) wesaw that the FindNextFile API in KERNELthunksupto
FindNextFileA in KERNEL32.
That's enough poring over this one WSPY21 log. It’s clear that
WSPY21 canalert us to someimportantplaces in Chicago that we probably wouldn’t otherwise have seen. An operating system purist might say
that WSPY21 reveals someof the seamysides of Chicago.I wouldn’t
agree that WSPY21 reveals anythingparticularly seamyordistasteful about Chicago,butcertainly the program does showseams: places where Win32 is stitched onto Win16 and where Win16 is stitched onto realmode DOS. ‘Whathavewelearned so far?
* The Windows 95 Explorer, a Win32 application,uses INT 21h function 4Bh (EXEC)to launch Win16 applications. Thiscall is not passed downto real-mode DOS,but(likeall calls seen by WSPY21) it doesinvolve the Winl6 KERNEL. Thisis significant because Win32 applications in Windows 95 are not supposed to employ the Win16 KERNELatall. * Win32 applications in Windows95rely on variety of INT 21h calls. WSPY21 doesn’t see mostofthese calls because they’re made using VxDCall0. However,the calls that WSPY21 doesseeare significant
because they showthat even a pure Win32 Windows 95 environment
relies on the Win16 kernel.It is significant that someofthesecalls are sentall the way down to real-mode DOSbecauseit shows that even a pure Win32 Windows95 environmentrelies on real-mode DOS
(which Windowsis running in V86 mode, however). * The Windows 95 Explorer, a Win32 application, uses INT 21h function 55h (Create PSP) not only to support Win16 applications but also to support Win32 applications. We'll see thatthis call, too, involves the Winl6 KERNEL. We've already seen from WV86TEST thatthecall is sent all the way down to DOS. Thus,every running
Win32 application in Windows95, like every running Win16 application, has a real-mode DOSPSP, created downin the bowelsofreal-
mode DOSbyfunction55h.
Chapter 13: Thunk! KERNEL32Calls KRNI386
Wins2 and the PSP By using a Win16 program, WINPSP.C, it’s easy to see that every Win32 task in Windows 95 has a genuine realmode DOS PSP. This program is based on, butfairly different from, the version of WINPSP that appeared in Undocumented DOS (2d ed., pp. 151-155). Figure 13-12 shows WINPSP under Windows 95, when running Explorer, Clock, WinBezMT, and three Control Panel windows (System, Telephony, and the New Device Installation Wizard), which show up as RUNDLL32.
EMBs VESTS OS PSPs (From NCB chain): jReaL Nane ose WIN, 9690 nna? 9707 krniae6 windows PsPs (From task List): RUMDLLI2
wINesP
Figure 13-2: The WINPSPprogram showsthat every task in Windows95, including every Win32task, comes with a realmode DOS Program Segment Prefix (PSP).
‘As you can see, each Win32task has a corresponding realmode DOS PSP.While the PSPstructure itself doesn't appearto be heavily used in Windows 98,its address is heavily used asthe source for a DOS processID. In the WSPY21 logs shown earlier, you probably noticed lotsofcalls that set the current PSP to OA7h, set the current DTA to 00A7:0080, and
s0 on. Many butnotall of thesecalls came from CAB32.From WINPSP’s display of the WindowsPSPchain, we can seethat protected-modeselector OA7h corresponds to real-mode address 07D7:0000,andthat this PSP belongs to KERNEL32. If you look back at the DOS PSPchain in Figure 13-2, you can see that O7D7h belongs, as far as realmode DOSis concerned, to a DOS application called KRNL386, which has allocated 9829 paragraphs (over 600K).
Unauthorized Windows 95
WINPSP.C, as shownin Listing 13-2, is a Win46 application that uses the WINIO library: Listing 13-2: WINPSP.C Is WINPSP..C Andrew Schulman, 1993 (Undocumented DOS, 2d ed.. pp. 151-155) Revised 1994 (Unauthorized Windows) Ay
#include #include Hinclude #include
#include “windows .h”
#include “prot.h" #include *toothelp.h* d#ifdef
extern
__cplusplus
"C* BOOL FAR PASCAL IsWinOTdApTask(HANDLE Task);
else
extern BOOL FAR PASCAL IsWinOldApTask(HANOLE hTask);
dendif
define MAP(ptr, bytes) fdefine FREE_MAP(ptr) fdefine GET_REAL(ptr)
map_real((ptr), (bytes)) free_mapped_linear(ptr) get_real_addr(ptr)
pragma pack(1) typedef struct | BYTE type; WORD owner, size; BYTE unused[3], name[8}; ) MCB; pragma pack() WORD get_first_meb(void) RMODE_CALL r memset(&r, @, sizeof(r)); r.eax 0x5200; if (dpmi_rmode_intr(0x21, 0, 0, ar) ( 1/ Extract seg of first MCB from SysVars. Note that this is // at sysvars{-2]. You can't call map_real() on sysvars, and // then back up 2! You must map in sysvars-2 to begin with. WORD far *tmp = (WORD far *) MAP(MK_FP(r.es, (WORD) r.ebx-2), 2): WORD first_mcb = *tmp: FREE_MAP( tmp); return first_meb; else
Chapter 13: Thunk! KERNEL32Calls KRNL386
}
return 0;
void display_dos_psp(WORD psp_seg, BYTE far *psp, MCB far *mcb) ( printf(“Z04x\t *, psp_seg): if (Losmajor >= 4) { char buf[9];
_fmemepy(buf, mcb->name, 8);
buf{8)
‘\0
if (buf) printf (*\t8-8s", buf): else printfc"\t\t");
)
printf(*\tz04x\n", meb-»size)
void display_win_psp(WORD prot_psp, char *szModule, WORD hTask) ( BYTE far *psp = (BYTE far *) NK_FP(prot_psp, 2); WORD real_psp = GetSelectorBase(prot_psp) >> 4; WORD flags; Printf("ROSX\tBOSK\te-Bs\teOax\eziXrt",
real_psp, prot_psp, szModule, hTask, GetSelectorLimit(prot_psp) + 1):
1 WinOldAp flag in Windows PSP flags = *((WORD far *) &psp{0x481); if (IsWinOldApTask(hTask) 8& (! (flags & 1))) /* insanity check */ fail("IsWinOldApTask flag weirdness!"); if (flags & 1) printf("00S ");
}
1f Win32 flag in TOB flags = *((WORD far *) MK_FP(hTask, Ox16)); Tags & Oxl0) printf (*WIN32"): printf(*\n");
{I void fail(char *s) { printf("%s\n", s); exit(1); | main() { TASKENTRY te; BYTE far *maybe psp; MCB far *mcb; WORD meb_seg, mapped; BOOL ok; printf( DOS PSPs (from MCB chain):\n"): printf( 1\t \tName —\tParas\n");
7/ walk 00S MCB chain, looking for PSPs
=n
Unauthorized Windows 95
if (1 (meb_seg = get_first_meb())) fail(*Can't get MCB chain!");
meb = (MCB far *) MAP(MK_FP(mcb_sea, 0), sizeof(MCB)); maybe_psp - (BYTE far *) MAP(MK_FP(mcb_seg + 1, 0), 2); 11 does it look like a PSP? { if ((meb_seg + 1) =* mcb->owner) // regular DOS app PSP displaydos_psp(mcb_seg + 1, maybe_psp, mcb); } FREE_MAP(maybe_psp): if (mcb->type 'Z") break; 11 end of list meb_seg = mcb_seg + mcb->size + 1; // walk Vist FREE_MAP(meb) : } ‘ FREE_MAP(mcb); Hf free last one if ((mapped = get_mapped()) != 0) printf(*ERROR! Su mapped selectors remaining! \n", mapped); printf(*\nWindows PSPs (from task list):\n"); \tTask\tSize\n"); printf("Real\tProt\tName /1 now walk Windows task list, and extract PSPs te.dwSize = sizeof( ok = TaskFirst (te); white (ok) ( BYTE far *tdb = (BYTE far *) MK_FP(te.hTask, 0); WORD prot_psp = *((WORD far *) &tdb[x60)); P*really a PSP? */ if (*C(WORD far *) MK_FP(prot_psp, 0)) == @x2@cD) display_win_psp(prot_psp, te.szModule, te.hTask): ok = TaskNext(&te); 1 return 0;
WINPSPfirst walks the DOS MCB chain, looking for PSPs. WINPSP employs fairly standard MCB.walking code, except that WINPSP is a protected-mode Windows program and therefore needs to map real-mode addressesinto its address space. It doesthis using the map_real function from the PROTlibrary on disk (also see Undocumented DOS, 2d ed., pp. 131-138). For each PSP encountered, WINPSP calls a routine named display_dos_ps.
Next, WINPSP uses ToolHelp to walk the Windowstasklist. For each task, WINPSPextracts a protected-mode selector to the PSP from offset 60h in the task database (TDB), seesif it’s really a PSP by checking that
thefirst two bytes are CDh 20h, andcalls the display_win_psp routine. This in turn calls GetSelectorBase to compute a real-mode paragraph
Chapter 13: Thunk! KERNEL32 Calls KRNL386
addressfor the PSP (all PSPs mustbe located in conventional memory, and therefore must havevalid return values from GetSelectorBase). The module name associated with the PSP comesfrom information that Tool Help supplies aboutthe task. Finally, display_win_psp checks twoflags in the TDB: the WinOldAp (“DOS”) flag and the Win32 flag. ‘As Windowstakes on more of the responsibilities once performed by realmode DOS, more “DOS programs” will in fact be Windows programs that look something like WINPSP. Welcome once again to the notso-new worldof protected:mode DOSprogramming!
Who's Calling INT 21h? ‘We knowfrom the preceding chapter that Win32 applicationsin Win-
dows95 rely far more on INT 21hthan Microsoft would suggest happens
even with Win16 applications. But does CAB32.EXEreally contain INT
21h instructions? No, it doesn’t. So how then is the launching of a Win16
applicationfromthe Explorer turning into a function 4Bh EXEC? And
how doesthelaunchingofanyapplication, whether Win16 or Win32, end
up creating a real-mode DOSdatastructure like the PSP? Significantly, these very DOS-like events do not occur throughthe
VxDCall0 2A0010h 21h mechanismdiscussedin the preceding chapter. If someone in Win32-landwere issuing an INT 21h function 4Bhor 55h via VxDCall0, WSPY21 wouldn’tsee it. As noted earlier, WSPY21 hooks INT21h at the Winl6 KERNELlevel. But wait a minute! If WSPY21 hooks INT 21h at the Winl6 KER-
NEL level, and if WSPY21 is detecting INT21hcalls occurring while a Win32 applicationis the current task, this means that KERNEL32 must call over (or “thunk down”in Microsoft parlance) to KRNL386. Yet, as we've seen, Microsoft claims that KERNEL32 never thunks down to
KRNL386. There’s more, though. Both when CAB32 starts CALC, and when CALC starts WINHELP, wesawthat the parent task uses function 55h
to create a PSPforthe child task.It’s natural enough toexpectthiscall when CALC uses WinExec to startWINHELP, since Matt Pietrek has
showninhisindispensable Windows Internals (pp. 229-256) that: Winkxec > INT 21h function 480 Opendpo nv -> CreateTask -> Bui
> LoadModule -> LWCheckHeade! NT 21h function 55h
eate PSPcalls coming Butin the case of CAB32, where are these from?Pietrekis talking about the Win16 version of WinExec here.
Unauthorized Windows 95
WSPY21 is seeing CAB32 call INT21h function 55h even when CAB32 launches a Win32 application such as Clock or WinBezMT. How the
heck (and why?) is CAB32 issuinga function 55hcall? Again,it can’t be using VxDCall0, or WSPY21 wouldn’tbeseeing it in the first place. Well, the answeris staring usright in the face. Pietrek showsthat the internal CreateTask function in KRNL386calls anotherinternal function, BuildPDB (PDB, whichstands for Process Data Block, is another
namefor PSP), whichin turncalls function 55h. Of course! (Sound ofone handclapping.) Some KERNEL32 code must becalling Create’Task in KRNL386! Later on, we'll see how KER-
NEL32 is doingthis.
Wealready knowthatall Win32 applications have corresponding
Winl6 TDBs (WSPY21 relies on this to display a name such as CAB32).
And,evenif we didn’t already knowthis, it wouldbe easy enough to stumble upon whenrunning any Windowsdiagnostic toolthat displays Win16 tasks, using the ToolHelp TaskFirst and TaskNext APIs or the task-walking methodsdescribed throughout Undocumented Windows. For example, Matt Pietrek’s WINWALKincludesa TaskWalk function (Undocumented Windows, pp. 646-647); note that this uses the old Win16
‘ToolHelp APIs, and notthe new ToolHelp32 API: void TaskWalk( void) TASKENTRY tes BOOL ok
f from WINIO library SK HMOD HINST PARENT\n"):
te.hModule, te.hIns le(te.hTaskParent) uses ModileFindHandle, TaskFindHandle
ok = TaskNext(ate);
Running CAB32, Clock, WinBezMT, and the Win32 versionof FreeCell, but no Win16 applicationsexcept for WinWalkitself, this code produces the following output in Windows 95: Task list NAME HTASK HMOD HINST PAREN
Chapter 13: Thunk! KERNEL32 Calls KRNL386
TIMER MSGSRV3:
‘Thecode just walks the Win16 task list. It knows nothing about Windows 95 or about Win32 processes, yetit sees the name of each Win32
process. Thus, each Win32 process in Windows95 has a corresponding
Win16 TDB. (Windows Internals, p. 226, notes that a 10h flag in the WORD at offset 16h in the TDB indicates a Win32 task. WINPSP.C
shownearlierrelies on this, as does the WALKWIN.C programwe'll examine a little later.)
Onthe otherhand,it’s also importantto note that the Win16 TDB for a Win32 task differs somewhat from one that a Win16 task has (which,in
turn, differs somewhatfromthe Windows 3.x TDBformat; see the following section, “Where’s the Windows 95 Current Directory?”). For example, the parenttask handle at offset 22h is 0 in a Win32 TDB (notice that WINWALK wasunable tolocate any Win32 task’s parent).
There’s another keydifference between Win32 and Win16 tasks: Although a Win32 task’s TDB hasa protected-modeselector to the PSP
at offset 60h, just like the TDB for a Win16 task, the actual PSP (as opposedtoits selector) is ot locatedat offset 210h in the TDB, the way it is for Win16 tasks in Windows95. (In Windows 3.x, this embedded PSP was locatedat offset 100h in the TDB.) Because a Win16 task’s ‘TDB includes (and acts as anextensionto) a real-mode DOS PSP, the entire[DB must be located in conventional memory. Again, Pietrek shows this in WindowsInternals (p. 254):
locate the TOB below IMD, so that it can be accessed by DOS TDB = GlobalDosAlloc(tdb_alloc_size) In contrast, here are typical TDB andPSP valuesfor both a Win32 task and a Win16 task running under Windows95 Sel
TDB Base
Size
Wwint6 1BDF 00030E00 320 win32 1BC6 800E0B20 210 *Win16 PSP base = Win16 TDB base + 210h
Sel
PSP Base
4AB7 1B1F
00031010* 110 00031120 120
Size
Unauthorized Windows 95
Although the Win32 task’s TDB is notallocatedin conventional memory,its associated PSPstill is. This is significant. If you place a breakpointon the GlobalDosAlloc routine in the Winl16 KERNEL and start up a Win32 application under Windows95, the breakpointis hit. Each Win32 task’s PSP is allocatedwith the Win16 GlobalDosAlloc API. ‘Thus, Windows 95’s Win32 kernelreally does call down notonly to realmode DOSbutalso to the Win16 kernel. In the Win32 API, you launchapplications with CreateProcess. You can also use a Win32 version of the older WinExeccall; this in turn calls aninternalversion of CreateProcess. Whenyou considerthat each Win32 process has a Win16 TDB, it seems plain that CreateProcess must somehow becalling down to CreateTask in KRNL386 notonlyfor Win16 applications but even for Win32 applications. We'll see later that the CreateProcess API in KERNEL32 doescreate a TDBbycalling theinternal CreateTask function in KRNL386. This makesperfectsense. It is surprising only because Microsoft claims that such things don’t take place in Chicago. But really, howelse would each Win32 process wind up with a Win16 TDB(albeit one that as we've seen differs a little from the TDBthat Win16 tasks get andfrom the TDBin Windows3.x)?
Where’s the Windows 95 Current Directory? Windows95 makes another important change to the TDB layoutfor both Win32 and Win16 tasks. In Windows 3.x, the TDB maintains the current drive and directory
in a 68-byte buffer at offset 66h, and there’s an embeddedPSPatoffset
100h(see Undocumented Windows, pp. 366-368).
In Windows 95, however, the current drive numbercontinuesto reside
in the byteat offset 66h in the TDB butthe currentdirectory has been moved tooffset 100h. As we’ve seen, the PSP, which formerlyresided at offset 100h, has been moved out either to offset 210h (for Win16 tasks) or
into anentirelyseparate conventional-memorysegment(for Win32 tasks). This movement ofthe current directory from the 67-byte bufferat offset 67h (remember, the byte at 66his the current drive) to the 272
(110h) bytesat offset 100h has to do with long directoryandfile names,
as youprobably guessed.
Chapter 13: Thunk! KERNEL32 Calls KRNL386
The Winl6 KERNEL must maintain the current drive and directory on a per-taskbasis. This is just another exampleofthe problem, noted in Chapter 12 (in the “PSPs and Other DOS Data in Windows95”section),
that the upper andlowerlayers of Windows are remarkably separate from eachother. As far as IFSMgris concerned, there is one current directoryper virtual machine (VM); DOSMGRlikewise instances DOS’s
current-drive variable on a per-VMbasis. But the System VM runs mul-
tiple tasks, each of which canhaveits own current drive and directory. VxDsdon’t really knowanything about whathappensinside the System VM;all the different Win16 and Win32 applicationslooklike one big application, called KRNL386.EXE.As wesawin Chapters 6 and 7, this separation betweentheupper and lowerlayers of Windows means, potentiallyat least, that the VMM/VxDlayer can run somethingother than the Windowsgraphical user interface and, conversely, that the Win-
dows GUIcan run on something other than Microsoft's VMM/VxD layer. Loosely coupledsystemsare generallypreferableto tightly coupled “Gntegrated” ones. However, the benefits to such modularity maybe outweighedby the duplication ofeffort it entails. The kernel in the System VMoften has to fake out the lowerlevels of Windows, making thembelieve thereis only a single application running — onethat justlikes to switch the current PSP, DTA,drive, and directorya lot!
In time, the upper and lowerlevels of Windowsshould become more tightly integrated. VxDswill come to know more about Windowstasks andwill be used for mainstream Windows programming. The Appy Time
and run-time dynamiclinking services — such as SHELL_CallAtAppy-
‘Time, SSHELL_LoadLibrary, SHELL_GetProcAddress, and_SHELL_
CallDIl — provided by the SHELL VxD in Windows95 are an important step in this direction. During so-called AppyTime(application time), a VxD can make Windows API calls.The VWIN32 VxD in Windows95
also appearsto be a step toward greaterintegration between Windows
applications and Windows VxDs.
In Windows95, VxDs do know aboutthreads as well as about VMs,
andas we saw back in Chapter1, VxDscan use Thread Local Storage (TLS). But the currentdrive and directory aren’t appropriate to maintain
ona per-threadbasis. Therefore, the single currentdirectory that IFSMgr provides to the System VM, andthe DOS current-drive variable instanced
by DOSMGR,must be multiplexedat the kernellevel rather thanat the VxDlevel among all Win16 and Win32 tasks. When there’s a task switch, KERNEL might haveto switch the current drive anddirectory too. Thus,
it makes sense to keepeach task’s current drive anddirectory in itsTDB.
Unauthorized Windows 95
Sofar,all this remains unchanged in Windows 95. Win32 tasks in part
need Win16-style TDBstostore their currentdrive and directory. The
difference in Windows95, however,is that longfilenames anddirectory
names makeit impossible to continue using the current-directory buffer at offset 67h in the TDB. Windows 95 keeps the task’s possibly longer
currentdirectoryatthe location where Windows 3.x keeps a PSP. The current-drive byteis still kept at offset 66h. Whydo TDBs for Win16 tasks need the extra currentdirectory space too? Because Win16 applicationscancall the INT21h function 71h LFNfunctions. In addition, the Win16 kernel (KRNL386) contains
functions such as SetCurrentDirectory and GetCurrentDirectory, which thunk upto the equivalent functions in KERNEL32 (whichthen just turn around and call INT. 21hfunctions such as 19h and 7147h for
GetCurrentDirectory and 0Eh and 713Bh for SetCurrentDirectory). As notedearlier, the Win16 common dialogs in Windows 95 can
sometimescall these LFN functions onbehalf of a Win16 application withoutthe application knowingit. (Userswill just see that they can save outlong filenamesand directory names.) This only applies to out-bound
(Set) calls. Silently replacing an application’s old in-bound (Get) call with a new one thatpotentially returns moredata (a longerfile or directory
name)could overrunits buffers.
The pointhereis that even Win32 tasks store their currentdrive and directory in a Winl16 TDB. This canbe easily demonstrated with a small Win32 Console application, CHGDIR.C, showninListing 13-3.
Listing 13-2: CHGDIR.C CHGDIR.C Win32 Console app // Shows that Win32 tasks keep Hinclude Hinclude define #include
WIN32_LEAN_AND_MEAN "windows.h*
DWORD (WINAPI *VxOC211)(DWORD srvc, #define #define define define define
t drv/dir in Winl6 TDB
GET_PR WWIN32_INT21 WWIN32_INT31_CALL DosCall( DPMICall(eax, ecx)
DWORD eax, DWORD ecx);
GetProckddress(GetModul ela od), (func)) 0x2A0010 Ox2a002 vxDCaT1 (VWIN32_INT ) VxDCal1(VWINS2_INT31_CALL, (eax), )
char curdir(MAX_PATH], DuF{MAX_PATHI, bufupr[MAX_PATH]: void fail(const char *s)
{ puts(s); exit(1); }
Chapter 13: Thunk! KERNEL32 Calls KRNL386
main() HANDLE id; BYTE *tdb_drv, *tdb_curdir, *tdb_base: WORD tdb, psp
/ Thread Id == Ring 3 THCB (Thread Control Block) id GetCurrentThreadid(); printf(*Thread 1D: £081xh\n", // Winl6 TOB is at offset Ch in Ring 3 THCB // I'ma little surprised it’s so easy to get at this! tdb *((WORD *) (((BYTE *) id) + Oxic printf(*TDB: $04Xh\n", tdb); // Use run-time dynamic linking to turn rings // into callable function pointers if ((VxDCal] = GET_PROC("KERNEL32", "VxDCa11@"))) // Get linear base address for TOB by calling / DPMI INT 3ih function 6 (Get Selector Base) / Even though we're a 32-bit app, we get the 16-bit // OPMI services, PMI indirectly asm mov bx, tdb DPMICa11(0x0006, 0); _asm mov word ptr tdb_base+2, cx asm mov word ptr printf(*TDB base: 208
// Call DOS INT 21h function 62h (Get PSP) DosCail(@x6200, 0): asm mov psp, bx p intf("PSP: BO4xh\n\n", psp): // Sanity check: is TOB{60h] PsP? if (*C(WORD *) (tdb_base + @x60)) fail(*TDB and PSP don't match!");
1 else
// Current dry at offset 66h in TD8, curr dir at offset 100h SetCurrentDirectory changes these // Note: Current drv/dir on per-task basis, not per-thread. tdb_curdir = tdb_base + 0x100; tdb_dry = tdbbase + 0x66 printf(*Warning: Can't access VxDCal1@\n\n
for (; ( if (GetCurrentDirectory(MAX_PATH, curdir) == 0) printf("invalid>"); else intf("[%s] ",
curdir);
gets(buf) if ((bufLO] = "\O") | (ufEO] == ‘\n"))
Unauthorized Windows 95
strepy(bufupr, buf); strupr(bufupr): *NOTE! CHGDIR.C and CHGDIR. EX n disk have a bug: instead of sizeof cmd)-1, they just have siz cmd). Need to recompile CHGOIR, tting in for this pi work.* . sizeof(cmd)-1) = fdefine MATCH(cmd) (strcmp (bufupr
if (1 SetCurrentDirectory(abufl3])) int f("CD failed else if (tdb_curdir) printf(*TOB+66n: %02Kh\n" printf(*TOB+100h: \'Es\"\n", ) else if (MATCH("MD " ) else
if (1 Createdi printf("MD failed Win€xec(buf, SW_NORMAL)
printf (*done\n* return 0; Asyoucan see, CHGDIRconsists oflittle more than a loop thatlets
theuser type in a few commands: MD (makedirectory), CD (change
directory), EXIT, or a commandthat will be passed through to WinExec. There’s a promptthatprints (within square brackets) the current drive and directory returned by the GetCurrentDirectory Win32 API.
Before entering the loop,though,the program doesa few odd-looking
things that you probably don’t expect to see in a Win32 program. For example, CHGDIR calls the GetCurrentThreadId Win32 API
and interprets the returnedthread ID as a Ring 3 Thread Control Block (THCB). Atleast in the beta version of Chicago this bookis based on,
the WORD at offset 1Ch in the Ring 3 THCBis the Winl6 TDB. (Of
course, any orall of this might changein thefinal released version of Chicago.) The Win32 application can dereferenceits own thread ID (a 32-bit near pointer such as 810FE91Ch)
andretrievea selectorto its
‘TDB without anyproblem. Notice that because CHGDIRis a 32-bit
program,it doesn’t needfar pointersto access this external data: WORD tdb = *((WORD *) (((BYTE *) GetCurrentThreadId()) + OxiC))
Chapter 13: Thunk! KERNEL32 Calls KRNL386
A selectorto its own TDB won't do a Win32 application much good, however. CHGDIR needsthe 32-bit linear address ofits own TDB. In a Win32 program, this
32-bit linear address (such as 800E0A80h) can be
used as a near pointer, assumingthatthelinear address is mapped into
youraddress space. The GetSelectorBase function from the Win16 API is not supported in the Win32 API, so we'll have to use somethingelse. DPMIprovides a function (INT 31h function 6, Get Segment Base Address)that, given selector, returns its linear base address:
, *tdb_curdir, *tdb_base; (0x0006, 0); —// Get Selector Base -asm mov word ptr tdb_base+2, cx _asm mov word ptr tdb_base, dx
DPMICall is just a wrapper around the undocumented VxDCallservice provided by KERNEL32 (see “Win32 File Handles and Thunking”
in Chapter 14). CHGDIRuses GetProcAddress to get a function pointer to VxDCall (whose actual name in KERNEL32 is VxDCall0):
H1 Use run-time dynamic linking to turn strings // into callable function pointers define GET_PROC(mod, func) GetProckddress(GetModuleHandle(mod), (func)) fidefine VWIN32_INT31_CALL 0x2A0029 #define DPMICal](eax, ecx) VxDCal1(VWIN32_INT31_CALL, (eax), (ecx)) DWORD (WINAPI *VxDCal1)(DWORD srvc, DWORD eax,
DWORD ecx);
VxDCall = GET_PROC("KERNEL32", “VxDCal10");
After using DPMICall, CHGDIRshould have a readily usable 32-bit flat pointer to its own TDB. Just to make sure, CHGDIRcalls INT 21h function 62h (again with VxDCall, this time using Win32 service 2A0010h) to getthe PSP, and compares the returnedselector with the WORDatoffset 60h in what, we hope, is the TDB.As explainedearlier, offset 60hin the TDB holds a protected-modeselector to thetask’s PSP. This is true for Win32 as well as Win16 tasks: WORD psp; DosCal1(0x6200, 0);
// Get Current PSP
janHee gp, assert (((WORD *) (tdb_base + 0x60)) == psp): Finally, just before enteringits read-eval-print loop, CHGDIRcreates pointers to offset 100h in the TDB,where thecurrentdirectoryis stored, andto offset 66h, wherethe currentdrive is stored: tdb_curdir = tdb_base + 0x100 tdb_drv = tdb_base + 0x66:
Unauthorized Windows 95
Inside the loop, whenever the user does a CD (SetCurrentDirectory), CHGDIRprints the contents ofTDB+66h andTDB+100h: SetCurrentDirectory(&buf(3]);
printf("TOBH66h: ¥O2Xh\n", *tdb_drv); printf(*TOB+100h: \"Bs\"\n", tdb_curdir):
Here’s some sample output from CHGDI. Thread 810FF300h TDB: 1CA6h TDB base: 800E0CAQh PSP: 1CEFh
[C:\UNAUTHW\TEST] md This is a long directory name [¢: \UNAUTHH\T ST] cd This is a long directory nane TOB+66h: 82h TDB+100h: ‘\UNAUTHW\TEST\This is @ long directory name [C:\UNAUTHW\TEST\This is a long directory name] md This is another long \ directory name {C:\UNAUTHW\TEST\This is a long directory name] cd This is another long \ directory name TOB+66h: 82h TDB+100h: '\UNAUTHW\TEST\This is a long directory name\This is another Jong directory name’ [C:\UNAUTHW\TEST\This is a long directory name\This is another long directory name] cd TOB+66h: 82h TOB+100h: *\" {C:\] cd unauthw\test TDB+66h: 82h TOB+100h: '\unauthw\test’ {C:\unauthw\test] cd h: TOB+66h: 87h TOB+100h: *\"
th:\] cdc ToB+66n: 82h Tos+100h: *\" Indeed, TDB+66h holdsthe currentdrive (in the form described in the earlier discussion of the internal KERNEL SaveState function), and
TDB+100h holdsthe currentdirectory. Notethat the SetCurrentDirectory and GetCurrentDirectory APIs
manipulate notonly the directory butalso the drive. There isn’t a separate SetDrive or SetVolumefunction in the Win32 API.If you wantto
changedrives, you call SetCurrentDirectory. (Note the CD H: and CD
Chapter 13: Thunk! KERNEL32Calls KRNL386
in the preceding CHGDIRoutput; this is not legal in Windows 95’s COMMAND.COM,bythe way.) SetCurrentDirectoryalso supports \\servername\sharename (UNC)disk designators. The absence of a separate change-drive function does have one unusual effect, which can be seen at the end of theCHGDIR output: if
you're at C:\unauthw\test(note that the namesare case-insensitive but
case-preserving), andcall SetCurrentDirectory(H:), andthen SetCurrentDirectory (C:), you'll wind up not at C:\unauthw\test but at C:\.
Fromthis one example, Windows 95 appearstohave nobuilt-in notion of multiple current directories on different drives. MS-DOSin contrast gives each drive its owncurrentdirectory, maintainedin the internal Current Directory Structure (CDS; see Undocumented DOS, 2ded., pp. 163-167, 443-449), To see how CHGDIR looksto real-mode DOS, I ran the program
with V86TEST.A wide variety of INT 21hcalls appeared. To try to understandall these INT 21h calls showing up at V86TEST, I wrote a Win32 Console application, NOTHING.EXE, whichconsisted of
nothing but
main() | return 0; I thenran that under V86TEST and compared the V86' Toutput * output from NOTHING. CHGfrom CHGDIR with the V8" DIR is responsible for onlythree different INT21hcalls:
‘The large numberofcalls to function 06h (Console I/O)represent time CHGDIRspendsinside the Cgets function, waitingforinput. (Hmm,whythe spin cycle? Why not block the VMuntil someinput is ready?) The Microsoft C 32-bit run-time library implementsgets with a call to ReadFile. Reading fromthe console nerates a VxDCall to the VCOND (Virtual CON Device) VxD. The tual function 06hcall is generated in V86 mode by CONAGENT-EXE which, in turn, is Consoleapplication. launched by VMM32 whenyoustart a Win32 ‘The function 40h (Write) calls come from CHGDIR’s printts to stdout, Andthe function 62h(Set PSP)call isCHGDIR’s VxDCall(0x2A0010, 0x6200, 0).
Without dwelling on the fact that a Win32 application(albeit a character-modeone)usesreal-mode DOSfor input (remember, Windows 95 supposedlydoes away with real-mode DOS), the importantpoint hereis that V86TE:
T
andtherefore real-mode DOS — didn’tsee anycalls
Unauthorized Windows 95
to getorset the current directoryor the current drive. Although these Win32 APIs might have moreinvolvementwith the Win16 kernel than Microsoft cares to acknowledge, we can at least see that they aren’t call-
ing downto real-mode DOS, even thoughinternally they use INT 21h function 71h. What does WSPY21 think of this Win32 Console application? If a
Win32 Consoleapplication calls FreeConsole to detach from the current
console(usually a DOS box) andcalls AllocConsole to create a separate
one(in Windows95, these consoles are just VMs), WSPY21 will see the Win32 application call INT 21h function 4Bh to start CONAGENT.EXE. Butin the case of CHGDIR, WSPY21 sees nothing
special. In fact, WSPY21 displays the sameresults for CHGDIRasfor NOTHING:
*(50) (55) *(1A) *(71) *(50) *(50) *(00) *(50)
67 (00A7h) Create PSP 7407 (1CEFh), 256 (0100h) DTA 1657:008 (3B) ChOir ‘\WINDOWS* 7h) Fh)
167 (OATH)
Note that the PSP created by WINOLDAP (here, 1CEFh) matches
the PSP that CHGDIR displays whenitstarts up.
But why do Win32
processes need Win16 TDBs in the first place?
For one thing, Win32 applications require Win16 TDBs to work with the existing Win16 messaging system in USER. A lotofattention has beenpaid to the fact that Windows 3.x hasa single input queue shared by all tasks — so a task that doesn’t yield will lock out every other task — andtothe solution in Windows95 ofgiving each threadits own input queue. Microsoft refersto this as input desynchronization. However, one pointhasn’t been stressed enough: the Windowsmessagingsystemstill resides in Win16-land. MattPietrek has pointed this out in Microsoft Systems Journal (“Inves-
tigating the Hybrid Windowing and Messaging Architecture of Chicago,” September 1994, p. 17):
Even though the window procedure for a 32-bit program windowis written in 32-bit code, existing 16-bit applications... expect any window, regardlessof whetherit's 16 or32 bits, to act just like it would in Windows 3.x. Consider somethinglike window subclassing.... If Chicago were to store a 32-bit linear address in the WND structure, things would quickly go up in smoke. To preventsuch problem scenarios, Chicago goes to greatlengthsto makeall windowsbehave asif they were 16-bit windows.
Chapter 13: Thunk! KERNEL32 Calls KRNL386
Oneofthe lengths to which Windows 95 goes to make Win32 win-
dowsbehave like Win16 windowsis to give every Win32 task a Win16 TDB with a Win16 task queue. Furthermore, every Win32 WndProc hasa corresponding Win16
WndProe.As far as the USER windowing systemis concerned,all win-
dowsare 16-bit, with 16-bit WndProcsand16-bit message queues. You caneasily see this with any Win16 program that walks the windowlist. For example,WALKWIN.Cin Listing 13-4 is a simple WINIOapplication that uses the GetWindowAPIto walk the windowlist: Listing 13-4: WALKWIN.C
17 WALKWIN.C #include #include #include #include #include #include
"window: "toolhelp *wini
void print_hwnd(HWND hnd, int level ( char taskname[9] char wndproc_owner[9];
GLOBALENTRY *pge; HANDLE htask, hi
void far *wndproc *classname char *wnd int flag, i: if (1 Gwndtext = (char *) malloc(128))) fail(*Insufficient memory"): if (1 (classname (char *) malloc(128)) fail(*Insufficient memory" get information about this window ntask GetWindowTask( hwnd); GetWindowText (hwnd, wndtext, 128) GetClassLong(hwnd, GCL_WNOPROC) wndy GetClas Name(hwnd, classname, 128); flag32 = *((WORD far *) MK_FP(htask, Ox16)) & Ox10; 0x20)) htaskq = *((WORD far *) MK_FP(htask, _fmemcpy(taskname, MK_FP(htask, OxF2), 8); taskname(@] = *\0" // use ToolHelp to get module name of WndProc owner wndproc_owner[0] = "\0" if (1 (pge = (GLOBALENTRY *) malloc{sizeof(GLOBALENTRY)))) fail(*Insufficient memory") pge->dwSize = sizeof (GLOBALENTRY) if (GlobalEntryHandle(pge, FP_SEG(wndproc)))
Unauthorized Windows 95
NODULEENTRY *pme if (1 (pme = (MODULEENTRY *) malloc(sizeof( fail("Insufficient memory"); pme->dwSize = sizeof(MODULEENTRY); if (ModuleFindHandle(pme, pge->hOwner)) strepy(wndproc_owner, pme->szModule) free(pme);
LEENTRY))))
free(pge): // print information W Task hWnd hTask TaskQ WndProc (owner) Wnd Class Wnd Text // for example: // 32 CAB32 0188h 1276h 207Fh O79F:3E66 (USER) ‘Static’ "ANamed:" idlevel: i++)
pri("Es printf 2 %s ¥04Kh $04Kh HO4Kh Ep (Zs) \"Bs\t * Flag3 me,2 "32 : "16" taskna c, hwnd, c_hotwansekr., h sk ame); wndproxt wndpro xt) classn if (wndte (*\&"&ts*\w"n"d,te pr(i"n\tnf"); wndtext) ; printf free(classname); free(wndt
void walkwin(HWNDhwnd, int level) // recursive depth-first walk { if (hwnd == 0) return; hwnd GetWindow(hwnd, GW_HWNOFIRST): white (hwnd
print_hwnd(hwnd, Tevel walkwin(GetWindow(hwnd, GW_CHILD), hwnd GetWindow(hwnd, GH_HHNONEX main(int argc, char *argv[ i winio_setpaint(__hMainknd, FALS
printf(cts\n",
"W
Task
hWnd
hTask
TaskQ
WndProc
(owner)
walkwin(GetWindow(GetDesktopWindow(), GW_CHILD), winio_setpaint(__hMainwind, TRUE);
Wnd Class
0)
Wnd Text");
This Win16 program caneasilyfind the window handle, the TDB(from whichit can extract the task name and message queue address), WndProc,
class name, and windowtitle not onlyofother Win16 applicationsbut also
Chapter 13: Thunk! KERNEL32Calls KRNL386
of each running Win32 application. Here’s a small portion of output from WALKWIN while I was running the Clock, WinBezMT, and FreeCell Win32 applications(along with WALKWIN itself): CAB32 8ODGh 1276h 207Fh 167F:0022 (KERNEL) 'tooltips_class32" 2 CAB32 OOC4h 1276h 2O7Fh 167F:0022 (KERNEL) 'tooltips_class32" CAB32 OOB4h 1276h 207Fh 167F:0114 (KERNEL) 'Shel)_TrayWnd* 2 CAB32 OOBBH 1276h 207Fh O79F:3E61 (USER) ‘Button 2 CAB32 OOBCh 1276h 207Fh 167F:O1AE (KERNEL) ‘TrayNotifylnd’ 2 CAB32 OOCOh 1276h 207Fh 167F:01C4 (KERNEL) ‘TrayClockWClass’ 32 CAB32 OOCBh 1276h 207Fh 167F:01DA (KERNEL) 'MSTaskSWwWClass* 32 CAB32 OOCCh 1276h 207Fh 167F:007A (KERNEL) ‘SysTabContro}32" 16 MSGSRV32 @088h 13EFn 1677h 0797:06A2 (USER) "#32768" 16 MSGSRV32 @084h 13EFh 1677h 0777:0005 (USER) ‘#32771 16 WALKWIN Q5D0h 2787h 272Fh 2847:2B1B (WALKWIN) 'winio_wemain’ "WALKWIN" 16 WINOLDAP @45Ch 1E07h ICFFh 1227:0069 (COMMCTRL) ‘tooltips_class* 16 WINOLDAP 0450h 1E07h ICFFh 1€87:0B07 (WINOLDAP) ‘tty’ "COMMAND" 32 FREECEI L 0128h 1846h IB1Fh 167F:05FA (KERNEL) ‘FreeWClass* “FreeCell Game 32 WINBEZNT 014Ch 1A56h 1B4Fh 167F:0702 (KERNEL) ‘winbezmt' "32-bit Multi-Threaded WinBez" 32 WINBEZMT 0150h 1A56h 1B4Fh O7E7:0000 (USER) 'MDICTient* 32 WINBEZNT @228h 1A56h 184Fh 167F:0718 (KERNEL) ‘ThreadClass’ “Thread Window 1 32 WINBEZMT 0224 1A5Gh 1B4Fh 167:0718 (KERNEL) ‘ThreadClass’ "Thread Window 2
32 CAB32 O15Ch 1276h 207Fh O79F:3E70 (USER) '#3270' "Find: AIT Fites* 32 CAB32 0184h 1276h 207Fh O79F:3E70 (USER) ‘#32770' “Name & Location” 32 CAB32 O188h 1276h 207Fh O79F:3E66 (USER) ‘Static’ "&Named:*
32 CLOCK 0120h ICAEh 1C6Eh 167F:04F2 (KERNEL) *Clock* *Clock™ 167F:02FB (KERNEL) ‘BatteryMeter_Main‘ LF9Eh IFA7h 32 BATMETER 0008h “Battery Meter” 32 BATMETER @0OCh 1F9Eh
IFA7h O79F:3E61 (USER) ‘Button’ “Power Status”
CAB32 @@D4h 1276h 2O7Fh 167F:016C (KERNEL) 'ProxyTarget’ CAB32 OOBOh 1276h 207Fh 167F:016C (KERNEL) ‘ProxyTarget* CAB32 O0ABH 1276h 207Fh 17D7:503E (DDEML) ‘DMGFrame* CAB32 009Ch 1276h 207Fh 1707:5104 (DDEML) ‘DMGClass’ 832 0110h 1276h 207Fh 1707:52EA (DDEML) *DMGHOIdingClass* 0894n 1276h 207Fh 167F:00FE (KERNEL) 'OTTimerClass* 16 MSGSRV32 0090 13EFh 1677h 1307:0458 (MSGSRV32) "Windows 32-bit VxD Server R OOBCh 130Fh 12CFh 1377:0332 (MMSYSTEM) "#42" 0098h 1276h 207Fh 167F:012A (KERNEL) 'Progman’ “Program Manager” 32 CAB32 O0ASh 1276h 207Fh 167F:0156 (KERNEL) ‘SHELLDLL_DefView' 32 CAB32 @OASh 1276h 207Fh 167F:O04E (KERNEL) 'SysListWiew32" 32 CAB32 QOACh 1276h 207Fh 167F:0064 (KERNEL) 'SysHeader32"
32 32 32 32
WALKWIN uses the Win32 flagat offset 16h in the TDB to determinewhether the windowbelongs to a Win16 or Win32 application.
Apartfromthat flag (shownas 16 or 32 at the beginning ofeach line) and
Unauthorized Windows 95
your knowledge of whichapplications are Win16 or Win32, there would be no wayof knowing an application’s “bitness” from looking at the other items WALKWINdisplays. And that is the whole point here: Asfar as
the Windows 95 windowingsystemis concerned, Win32 applications
look muchlike Win16 applications, downtotheir use of KERNEL structures such as the TDB andtask message queue. To makeit 100 percentclearthatall windows belonging to Win32 applicationsreally do have Winl6 WndProcs, WALKWINusesthe ToolHelp APIto retrieve the name ofthe ownerofthe segmentin which each WndProcresides. As you can see from the WALKWINoutput, the WndProcsfor the built-in Win32 windowclasses such as Button, MDIClient, and Static are located in the Winl16 USER module, and the
WndProcsfor the Win32. application-specific windowsbelongto the Winl6 KERNEL. Win32 applications such as CAB32, WinBezMT, Clock, and FreeCell are all calling the Win32 version of RegisterClass from USER32.DLL, and all install 32-bit WndProcs. ButWM_XXX messages in Windows95
always go to 16-bit WndProcs. These 16-bit WndProcsthunkup to the 32-bit WndProcs installed by Win32 applications. (This message-thunk
mechanism is explained in the September 1994 Microsoft Systems Journal article by Matt Pietrek.) Similarly, USER32 APIs such as GetMessage thunk down to their Win16 counterparts in USER. Thisall looksfairly similar to the schemeused in Win32s. In Windows 95, if you trace through a message thunk, fromthearrival of a
WM_XXXmessage at a Win16 WndProcproxy tothedelivery of the
message to the Win32 WndProc,you'll encounteracall to function in KERNEL32 named W32S_BackTo32. For what it’s worth, a function with the same name appearsin the Win32s W32SKRNL.DLL module. Running WALKWINwith some Win32 applications under Win32s, fur-
thermore,reveals the same basic approach we saw in Windows95: In the
case of the built-in windowclasses, Win16 WndProc proxies belongto USER;the Win16 proxies for application-specific Win32 WadProcs belong to WIN32S16.For example: 32 WINBEZMT 256Ch 1067h 102Fh
1FO7:0042 (WIN32S16)
67h 102Fh O6FF:1 USER Fh 1DD7h 1FO7:002C (WIN32S16) 125Fh 1167h 74F:0429 (USER)
‘winbezmt*
32-bit
Chapter 13: Thunk! KERNEL32 Calls KRNL386
FREECELL 2370h 125Fh 1167h @74F:2313 (USER) ' "System Resources: 32 FREECELL 2388h 125Fh 1167h O74F:2313 (USER. 32 FREECELL 2400h 125Fh 1167h O74F:1A12 (USER) *
32 FREECELL 1698h 125Fh 1167h 1FO7:0016 (WIN32S16) Game #7260" Despite important changessuch as inputdes
sagingsystemin Windows95 remainsresolutely 16-bit, muchas it was
in Windows3.x. The schemefor supporting Win32 messages looks much
asit does in Win32s, Win32 applicationsparticipate in Windows 95 messagingbyvirtue oftheir Win16 proxies. Now, the Win16 USER messagingsystemis totally dependent on
Winl6 KERNELdata structures,especially the task message queue. As Undocumented Windows(p. 380) notes, it is sometimes hard to decide where USER ends and KERNEL begins:
Because messagesare really postedto a task, not a window,it makes sense that the Task Queue itself is a KERNELratherthan a USER data structure. On the other hand, many routinesinside USER have intimate knowledge of the Task Queue structure; theseinclude ReplyMessage(), InSendMessage(), GetMessageTime(), GetMessagePos(), and PostQuitMessage().... Actually,it is difficult to decide whether the Task Queueis a KERNELor a USERdata structure.Really, it’s shared between the two modules,and in fact provides most of the glue between KERNELand USER. The GetTaskQueue() and SetTaskQueue() functions are in KERNEL, but the Task Queueitself is created by the InitApp() function in USER. Put together these two facts — Win32 message support depends on
Win16 message support, and Win16 message support depends on Win16 KERNEL data structures — anditis clear that Win32 support in Windows 95 must rest on the Winl6 KERNEL. The idea that USER32
thunks down to USERbut that KERNEL32 doesn’t thunk down to
KRNL386is absurd. Indeed, in a Windows95 systemrunningonly
Win32 applications, a data-access breakpoint (BPR in Soft-ICE/Windows) placed on the TDBsandtask queueswill be triggeredall the time. Well, so what? Win32 applications need Win16 TDBs for compatibil-
ity with the Windows messaging system.Andin any event, Windows95 needs the Win16 kernel to run Win16 applications. What’s wrongif KERNEL32 sometimesuses the code thatalreadyexists in KRNL386?
There’s nothingatall wrong withit, except that Microsoft claimsthat, unlike USER32 which almost always thunks down to Win16 USER, and
GDIB2 which frequently thunks down to Win16 GDI, supposedly KERNEL32 never thunks down to KRNL386:
Unauthorized Windows 95
Most ofthe code in USER32 is little more than a layer that accepts 32-bit API calls and handsthemoff toits 16-bit counterpart for processing..... [This is] a sensible way of using tried and trusted code — afterall, the 16-bit API implementationshaveto be there for compatibility. GDI32 offers comesignificant performanceimprovements. Consequently, the 32-bit GDI handles a lot of AP! calls directly. The KERNEL32 module is completely independentofits 16-bit version. There is some communication from the 16-bit to the 32-bit side, but the 32-bit KERNEL never calls
across to the 16>it side.This is as you'd expect, since most of the code (for example, memoryallocation and thread management)is quite different. — Adrian King, “Memory Management, the Win32 Subsystem, and Internal Synchronization in Chicago,” Microsoft Systems Journal, May 1994,p. 58.
‘The statements that KERNEL32 is “completely independent” of the 16-bit KRNL386andthat “the 32-bit KERNELnevercalls across to the 16-bit side” are simply untrue, as we'll soonsee. And, as with the simila “never” statementsregarding Windows and MS-DOSquoted in the preceding chapter — such as“if you only run Windows-basedapplications, you'll neverexecute any MS-DOScode” — what comes to mindare a few lines from Gilbert andSullivan’s HMSPinafore. The ship’s captain sings that henever, everswears, and the chorus questions whether this is reallytrue:
Chorus: What, never? Captain: No, never. Chorus: What, never? Captain: Well, hardly ever. Unfortunately, the computertrade press often performsas a quite different kind ofchorus: When Microsoft mentions some Windows 95 compromise, such as Win16Lock(see “Win16 Everywhere” in Chapter 14), the press getsall bent out of shape. However, if Microsofttells the press somethingit wants to hear, such as that somepiece of16-bit codeis gone, there seemsto belittle attempt made to verify whetherthisis true.
ThePCtrade press sometimesseemslike a chorus ofparrots with invertedpriorities.
Insteadofbeating Microsoft upover necessary compromises suchas
Win16Lock, andthen turning aroundand wholeheartedly believing the companywhenit says that real-mode DOSis goneorthat the Win32 ker-
econdguess Microsoft’s architectural compromises, nor believe the company nel doesn’t rely on the Win16kernel, it would be betterto neither
whenit claimsthat it has eliminated such necessary compromises.
The computertradepress has dutifully repeated Microsoft's claims
regarding the Win32 kernel’s supposedtotal independenceof the Win16
Chapter 13: Thunk! KERNEL32 Calls KRNL386
kernel. As one example, Windows Magazine, in “A Revealing Lookat the Architecture”(July 1994,p. 186), presents a diagram purporting to showthat thunks in Chicago go USER 32-516, GDI 3216, but
KERNEL 32protdump #1 30464 -dword Ox100
(4430464 C4a30474 4430484 (4430494 C44304A4 4430484 (44304C4 4430404 (4430: C44304F4 (4430504 (4430514 (4430524 4430534 4430544
|
| | | |
O1LFEGCE 01272588 01170105 01270525 O11775FO O11F@4CD 011F0387 011F02BD
O11FOBSB 01272538 01177544 01 01177506 011FO410 011F0458 011FO3AD
011F4396 01272527 011765AB 27017F 01177648 011F0317 011F0355 011F0230
0127236: 01272513 01170300 01270155 01177624 011F048D 011FO3DF 011700F1
| 01170144 01170175 01170158 01170004
| 01170119 01170088 O11FOLEF O11F0074 | 01270533 O11F4062 0117470C 01176580
| 011760A7 01176078 0117605A 01176048,
| 01176553 0117653F 01176568 01174956
| 01176432 O11F0018 O11FOOER 91170190 | 01170189 @117022C 01170218 01271331
4430554 01271430 01271073 01271CE6 01271095 don't know quite where table ends
Every oneofthesesixtyor so entries represents a thunk from KER-
NEL32 down to KRNL386: you know,the stuff that supposedly never happens. Noteverythunkin thistable is necessarily still used in Windows 95; someofit could bejust scaffolding that will be removed or
ignored when the commercialrelease of Windows95 is ready. To figure
out what someof these KERNEL32 -> KRNL386thunks do, and whetherthere are any morethatare useful or importantbesides the few we've stumbled across already (LoadLibrary16, GetProcAddress16, and the CreateTask thunk wejust examined), it’s sometimeseasier to look for code in KERNEL32 that employs the thunk,rather than at the KRNL386 code whose address appears in the preceding table. Huh? Well, here’s what I mean: KERNEL32!F indAtomA 37:BFFB25E9 PUSH EDI param validation stuff O137:BFFOLD4E
MOV UMP
CL,06 -BFF91060
Unauthorized Windows 95
KERNEL32! LoadLibrary16 0137:BFF91052 MOV —CL,36 0137:BFF91D54 UMP BFF 91060 KERN 0137: 0137
leteatom 7F MOV 81 INP
CL,05 BFF91D90
KERNEL32!6]obal Free 1 F9108B MOV Fg91080 JMP
CL,23 —-BFF91090
KERNEL32!G]obalDeleteatom 0137:BFF91D97 MOY CL,11 0137:BFF91099 JMP ~=—BFF91090 KERNEL32! InitAtomTable 37:BFF91DE6 MOV CL,03 0137:BFF910E8 UMP BFF910EC
This all makessense. For example, LoadLibrary16 is thunk #36; entry #36 in thetableis at 30464+36*4 = 3053Ch, which points to 011F:00EB.
Thisis the address of the LoadLibrary API in Winl6 KERNEL.Similarly, FindAtomA is thunk #6; entry #6 in the table points to 0127:2527.
Thisis the address of a routine in KERNELthatcalls FindAtom. In short, thereareall sorts of circumstances in which KERNEL32
calls down to KRNL386. The table we’ve examined provides KERNEL32 with the 16-bit selector:offset address for various routines in KRNL386; KERNEL32 uses QT_Thunktocall the routines. It’s diffi-
cultto believe that anyone would deny that KERNEL32 thunks downto KRNL386. We'vejust seenthatthere’s a fairly elaborate mechanism whosesole purposeis to dojustthat.
A similar mechanism allows Win16 code in KRNL386 to thunk up to the Win32 code in KERNEL32. For example, I noted earlier (in the “Where's the Windows 95 Current Directory?” section) that KRNL386
contains functions such as SetCurrentDirectory and GetCurrentDirectory that thunk upto the equivalent functions in KERNEL32. Now,there’s absolutely nothing wrong if KERNEL32 needstocall down to the Winl6 KERNEL. Microsoft surely knows that KERNEL32
does thunk downto the Winl6 KERNELandthat, ifnothingelse,this followslogically from the combination of USER32’s dependence on Win16 USERand Win16 USER’s dependence on the Winl6 KERNEL. So why the big claims thatKERNEL32 doesn’t need the Winl6 KERNEL?
Onereason, I think, is psychological. Microsoft is known for being a
tremendouslyinnovative marketing organizationthatis fantastically good
Chapter 13: Thunk! KERNEL32Calls KRNL386
at exploiting whatever opportunities come along. But not manyin the software industry think of the companyasparticularly innovative techni-
cally. Microsoft has aninferiority complex aboutits most successful operating systems, MS-DOSand Windows.Foryears, the company has been tryingto showthatit, too, can build what mightin somecirclesbecalled a “real man’s”operatingsystem, and what others might simply dismiss as a case of “second system syndrome.” Perverse though it maysound, Bill Gates keepstryingto actlike Steve Jobs.
Microsoft has produced wonderfully successful operating systems
which have becomethedefacto standards for mass-market desktop computing (and the UNIX community, with its boutique-sizedinstalled base, talks of “open systems”!), but this isn’t good enough. From Bill Gates on
down, Microsoft wants everyoneto think thatits products not only domi-
nate the desktop but also meet someartificial purist criteria for operating system goodness. Henceatleast someof the exaggerated claims regarding Windows 95’s independencefromtheold, wildlysuccessful, “tried and trusted,” DOSand Windowscode base. And hence, too, Microsoft’s doth-protesttoo-much assertions that “Chicago is not Win32s!”(referring to a much-
despised but perfectly workable add-onthat allows Windows 3.12 to run some Win32 executables; see Chapter14), While Microsoft keepstrying
to assert thatit has produced “newtechnology,” I feel a lot safer knowing that it hasn’t. Butaside from purely psychological motivation, there are also some
firmlypracticalissues here. For one thing, muchof the misinformation
surrounding the Windows 95 architecture comes from Microsoft's nat-
ural desire (discussedin detail in Chapter1) to portray Windows95 as
integrated, and therefore as a no-excusesalternative to the highlyinte-
grated, appliance-like Apple Macintosh.
Anotherreason, probably less important, has to do with Microsoft’s strangerelationship with the computertrade press. The sametrade press
that won’t attemptto independentlyverify Microsoft’s claimsalso likes to deride Microsoft over relatively silly issues. In the case of Windows95, all the partisans of operating systempurityhave been complaining that Windows95 isn’t sufficiently like Windows NT. The following quotations aren’t perfect examples, because their authoris a superb journalist whosearticles frequentlyhit the nail on the head, but they are somewhatrepresentative of the heat that Microsoft
takes simply because Chicago isn’t NT
Unauthorized Windows 95
Chicago's Win16 support is a potentialAchillesheel... If you use Chicagoto run Win32 applications only,it will more closely approximate an ‘NTlite’...
Chicago, when running a mixture of DOS and Win46applications,will behave much like Windows3.x with a few improvements.... Even at its best, though, Chicago is notthe pure 32-bit operating system that NT is. Instead,it is a 16- to 32-bit hybrid. At the Decemberconference in which Microsoft distributedits second preliminary developerkits, programmers who hadn’t yet worked with NT were,in general, more impressed with Chicago than those already familiar with NT. — Jon Udell, “Chicago: An Ambitious Compromise,” Byte, March 1994, p. 23. Notice that, while obviously critical of Microsoft’s quite sensible plans
not to model Windows95 after the lacklustre NTboutique operating system, Udell’s article appearstofully accept Microsoft’s distinction
between a Windows 95 running only Win32 applications andone also running a mixture of DOS and Win16 applications. The suggestionis that thereis a qualitative difference between these two environments.
Inanotherarticle (“TheFix Is In for Chicago,” Byte, September 1994,
p. 193), Udell states that “Chicago systems running Win32 applications should prove much morestable than Chicago or Windows 3.4 systems
running mostly DOSand Win16 applications.” Althoughit’s likely that he’s referring here primarily to Windows 95°s capability to give each Win32 application its ownprivate address space, I thinkit’s important to realize that a Windows 95 system, atleast as presently constructed,is never purely running Win32 applications. Forone thing, MSGSRV3 é
Win16 task, is always running.If youtake a Windows 95 machine running only Win32 applications andthenstart a Win16 application, there
isn’t muchof a qualitative changethat takesplace. As one example, belowI listedall the loaded modules on a Windows 95 system running nothing except the Explorer. I’ve droppedfontfiles (which are modules) fromthe followinglist, which was producedwith the MODcommandin WinICE: O10F 24 0297 6
Header
EXE File Name C:\WINDOWS\SYSTEM\KRNL386. EXE c:\ws_chi \wssys.drv WINDOWS\SYSTEM\system.drv Cs \WINDOWS\SYSTEM\ keyboard.drv drv WINDOWS\ SYSTEM C: \WINDOWS\SYSTEM\ vga .drv WINDOWS M\sound.drv WINDOWS
Chapter 13: Thunk! KERNEL32 Calls KRNL386
125E 1256 124E 1F5E 1F06 1FOE
013F :8FF70080 013F:810F8564 013F:810F8B20 O13F :810FBABC 013F :810F8D3C 0136:810F9A80 013F :10FAS5C 013F:810FA878 13F:810FAB18 013F:B10FAF@B O13F:810FBBFS 013F:810FBB34 Q13F:810FC71C 013F:810FD264 @13F:810FD60C
USER DDEML MSGSRV3, MMSYS TIMER POWER SHELL COMMCTRL SHELL WIN87EM COMMOLG KERNEL32 GDI32 ADVAPI32 1CM32 USER32 WINMM MPR MSPHL3Z NETLIB32 CAB3Z COMCTL3: SHELL32 LINKINFO BATMETER CRTOLL
€ \WINDONS\SYSTEM\user -exe c WINDOWS\SYSTEM\DDEML. DLL \WINDOWS\SYSTEN\MSGSRV32.. EXE C:\WINOOWS\SYSTEM\mmsystem.d11 ¢ WS\SYSTEM\mmtask. tsk c \SYSTEM\power .drv c SYSTEM\SHELL. DLL C:\WINDOWS\SYSTEM\commetr? .d11 C:\WINDOWS\SYSTEM\shel116.d11 Cs \WINDOWS\SYSTEM\WENB7EM. DLL \WINOOWS\ SYSTEM) CONMOLG. DLL WINDOWS \SYSTEM\KERNEL32. DLL WINDOWS \SYSTEM\GDI32.DLL : \WINDOWS\SYSTEM\ADVAPI32. DLL : WINDOWS SYSTEM\1CM32. DLL = \WINDOWS\SYSTEM\USER32. DLL 2 \WINOOWS\SYSTEM\WINMM. DLL C: \WINDOWS \SYSTEM\MPR. DLL : WINDOWS\SYSTEM\MSPHL32 DLL SYSTEM\NETLIB32. DLL WS\CAB32. EXE = \WINDOWS\COMCTL32. DLL : WINDOWS SHELL32. DLL = \WINOOWS\SYSTEM\LINKINFO. DLL : \WINDOWS\ BATMETER. EXE C: \WINDOWS\SYSTEM\CRTDLL. DLL
So this is our Windows95 “steadystate,” at least in the current implementation. Notice the large number of modules for which the PEHeader field is blank; these are Winl6 DLLs. Next, I started three Win32 applications: Clock, WinBezMT, and the
Win32 version of FreeCell. The following additional Win32 modules
showed up: 27CE 2706 26C6 232E 1C3E OBCE 27DE
013281103988 013F:81104164 013F:811043E0 013F:81100294 013F:81105208 013F:81105D04 O13F:81105F40
CLOCK CONOLG32 WINBEZMT MSNET32 FREECELL CARDS SHELL32
C:\WINDOWS\CLOCK. EXE : YWINDOWS\SYSTEM\COMDLG32. DLL C: \WINDOWS \WINBEZMT EXE C: \INDOWS\SYSTEM\MSNET32. DLL C: \WIN32APP\ FREECELL\FREECELL. EXE C:\WIN32APP\FREECELL\CARDS DLL C\WINDOWS\SYSTEM\ SHELL32. DLL
Next, I started WSPY21, which is a Win16 application. No additional modules showed up other than WSPY21 itself: C: \UNAUTHW\BINW\WSPY21. EXE wsPy2i 276F
No new Win16 modules were required to run this program. Finally, I started the WinScope debugger. This loaded three WinScope modules and draggedin three Win16 DLLs — WIN87EM, TOOLHELP, and COMMDLG— that didn’t show up when we were running only Win32 applications:
Unauthorized Windows 95
1EBF 1677 1657 Lear 1E4F oaar
WINSCOPE wsco WSMISC WIN87EM TOOLHELP COMMOLG
C:\ws_chi \winscope.exe c: C:\ws_chi\WSMISC. DLL C: \WINDOWS\SYSTEM\WIN87EM. DLL C: \WINDOWS\SYSTEM\ TOOLHELP.. DLL C: \WINDOWS\SYSTEM\COMMOLG. DLL
I wasparticularly concernedtosee the effect of loading WinScope because anothertestI did for 32-bit purity employedthis debugger. While running the standard set of Win32 applicationsalreadylisted countless timesin this chapter — Clock, Explorer, FreeCell, and WinBezMT — andno Win16 applications besides WinScopeitself, I had WinScope hookcallsfrom all DLLsto all APIs in the Winl6 KERNEL DLL.After two or three minutesofthis, I sorted the WinScope log and had an AWK program countthe numberofcalls to each Winl6 KERNELfunction: 14367 total calls to KERNEL 02422 01263 01091 00747 00371 00294 00250 00247 00198 00155 00141 00132 00108 00078 00052 00046 00037
GlobalUnlock strlen LocalFree PrestoChangoSelector LocalUnlock IsBadReadPtr PostEvent hmemepy GlobalATToc Oldvield LoadResource Istrepyn IsBadHugeReadPtr LocalSize GlobalReAl loc AddAtom IsBadCodePtr
02278 01167 00823 00424 80371 00250 00250 00241 00188 00144 00141 00126 00081 00056 00050 00040 00032
Global Lock LocalAlloc GetCurrentTask GetExpWinVer Local Lock Waitevent GetéxePtr FindAtom GlobalFree LockResource FindResource GetAtomName FreeResource Istrepy GetAppCompatFlags IsBadStringPtr NoHookDOSCa11
Thesignificanceofthis list is that no Win16 applications other than WinScopeitself were running,yetin just two or three minutes there wereover 14,000 calls to the Winl6 KERNEL API. Assuming that Win-
Scopeisn’t skewingtheresults too badly (which we'll get into in a
moment), this would showthat the whole notion of a pure Windows95
system that runs only Win32 applicationsis fairly meaningless.
Tt waseasy to confirmthatthe vast majority ofthesecalls occur whether
Win16 application such as WinScopeis loadedornot. I used WinICE (which runsoutside Windows)to put breakpoints on someof the Win16 KERNELfunctionsthat WinScopedetected in the semi-pure Win32 configuration.I then unloaded WinScope, so no Win16 applications were
Chapter 13: Thunk! KERNEL32 Calls KRNL386
running.I couldn’t get rid of the TIMER and MSGSRV32 WinI16 tasks,
but these are built into Windows95. Therefore,this is probably as pure a Win32 setup as one could hopefor, at least in the current implementation of Windows 95. Here’s whatthe configuration lookedlike:
rtask TaskName WINBEZMT * clock BATMETER cAB32 TIMER MSGSRV32 KERNEL32 thread RingOTCB COFESSFO COFES3A0 COFESI50 corDsi94 COFD3E30 corD0140 coropo74 COFDFOFA COFDE2IC COFDCEBA COFDBE74 COFOBACE corDg16c COFDOEL4 4520298 COFESTEA coFD5308
StackTop 00737000 00737000 00737000 00756000 ooR2 one? 00034880 1D 0014 0013 0012
Context COFD48E8 COFD4BEB COFD48E8 COFD4BEB COFEOZF4 COFDCBIC COFEOIIC COFOCBSC OCB9C COFESBIC COFESBIC COFEBBIC COFESBIC COFEBBIC COFEBBIC COFDCB9C COFDCB9C
StackBot StackLow TaskDB 90740000 2666 00740000 2798 90740000 IFLE 0760000 1276 201¢ 201¢ 130F 3314 30ce BEF 900448AF 0097
Ring3TCB SIOFFCEC S1OFFAZC SIOFF7EC B1OFF52C B10FE7D8 810FD960 810FDOZ4 B1FC224 S10FB6BB B10FAZ6C 810F9820 B1OF95EO B10FBFDC B1OFBZCd 810F7344 81100280 811000E4
Process B1OFFIB8 B10FFI88 S1OFFI88 B1OFFI88 B1OFE438 B10FB30C S1OFCC74 B1OFB30C B10FB30C 81OFSFI8 810F7Z6C S1OF9Z8C 810F726C B10F726C 810F726C 810FB30C 810FB30C
TaskDB 2666 2666 2666 2666 279E 1276 1F1E 1276 1276 130F 0097 13EF 0097 0097 0097 1276 1276
POB 26DF 260F 260F 260F 2747 126F 1F2F 126F 126F 1307 —@OAF 13E7 OOF OOAF QOAF 126F 126F
hQueue Events 26C7_-—— 0000 27770000 1EF7 (0000 207F 0000 -12CF_~—0000 16770000 «©1677 000 SZ 32 32 32 32 32 32 32 32 32 16 32 16 32 32 32 32 32
* * * * * *
Owner WINBEZMT WINBEZMT WINBEZMT WINBEZMT CLOCK CAB3Z BATMETER CAB32 CAB3Z TIMER KERNEL32 MSGSRV32 KERNEL3Z KERNEL3Z YN O1 CAB CAB32
In this configuration — no 16-bit tasks or threads runningother than TIMERand MSGSRV32 — putbreakpoints on some of the Win16 KERNELcalls that WinScope had detected.
It turned outthat WinScope had skewedtheresults a bit. For exam-
ple, many (though by no meansall) ofthe calls to GetCurrentTask simply disappeared when WinScope wasn’t running. Thesecalls camefrom ‘ToolHelp, which was present only because WinScoperequired it. However,the vast majority of the Winl6 KERNELcalls logged by WinScopedid continue to occur when no Win16 application was run-
ning. Hereare a few examples: * All thosecalls to PrestoChangoSelector (see Undocumented Windows, pp. 39-40, 343-346)occur whether or not any Win16 applications are loaded. PrestoChangoSelector can turn a codeselectorinto a data selectororviceversa.It is used to implement self-modifying code or
Unauthorized Windows 95
executable data. The DISPLAYdriver’s BITBLT module calls
PrestoChangoSelector to compile bitblts on thefly. (See the sample source code in the Windows DDK,such as \DISPLAY\4PLANE\ BITBLT\BITBLT-ASM.)
* GetExePtris called from FindResource and LoadResource, which are called from LoadString, which in turnis called via QT_Thunkfrom
USER32!LoadStringA.(Whichbegat...)
LoadString appearsto be
called constantly in Windows95, perhaps to produce thos
ver
bouncing “Hint:”items at the bottomofthe screen. At any rate, there are constant calls to the Win16 GetExePtr function, which, given
almost any kindofglobal handle, will find the module handle with whichit’s associated. (See Pietrek, Windows Internals, pp. 474-476:
“GetExePtr() is one of my favorite undocumented functions.”) ¢ The 32 NoHookDosCallsall come from the InquireSystem function in SYSTEM.DRV(see Undocumented Windows, pp. 339-340, 608-609).
‘This in turn is called by the GetDriveType API in KERNEL. Wecould go on and on, examining each Winl6 KERNELcall that
appearsin a “Win32 applications only” Windows 95 environment, but you getthe idea: Even in the purestcase, there are tonsofcalls to the Win16 KERNEL. Thisis perfectlylogical, given that the Win16 versions of GDI and USERbothcall down to KERNEL. Moreand more, it seems that Microsoft’s claim that the 32-bit KER-
NELnevercalls across to the 16-bit KERNELisnotonlyfalse, but possibly even meaningless. Think aboutit for a second: Evenif you accepted Microsoft’s claim (which we know tobefalse) that KERNEL32 never directlycalls across to KRNL386, Microsoft hassaid that USER32 calls USER and that GDI32 calls GDI. It’s obvious frominspection with a
tool such as Microsoft’s EXEHDRorthe EXE Quick View in the Windows 95 Explorer that USER and GDI both call KERNEL. For example,
theyrely heavily on the GlobalLock, GlobalUnlock, LocalAlloc, and LocalFree memory-managementservices. Thus, even when running only Win32 tasks, the Winl6 KERNELis in constant use because USER32 and GDI32 call USER and GDI, whichin turnrely on KERNEL.
So, even if KERNEL32 didn’tdirectly thunk down to the Win16 KERNEL,orevenif you wantedto dismiss as unimportantthecases in whichit does, the Winl6 KERNELremainsa crucial part of Windows
95, even ifyou runonly Win32 applications.
Byclaiming that even though USER32->USER and GDI32->GDI, at
least KERNEL32 !-> KRNL386, Microsoft is obviously trying to win
Chapter 13: Thunk! KERNEL32 Calls KRNL386
over operating system cognoscenti (“armchair OS designers,” as Udell refers to them) whobelieve there is something inherently preferable abouta pure 32-bit operating system. Surely developers at Microsoft know that there’s nothing inherently preferable about a brand-new operating system that doesn’t rely on the “tried-and-trusted” (though far from bug-free) DOS or Win16 code base. Andsurely Microsoft knows that manyofthe claims made about Windows95 — that it eliminates real-mode DOS, that the Win32 kernel
doesn’trely on the Win16 kernel, that running only Win32 applications presents a qualitativelydifferent configuration from one running a mix-
ture of DOS, Win16, and Win32 applications — are simply untrue.
Butperhaps Microsoft can brushall this off: “Oh,that didn’t quite makeit into Windows 95; we'll take careofit in Windows 96.” Indeed, with each version of Windows, Microsoft can remove, and has removed, more and more dependenceonreal-mode DOS. Microsoft can start on the same path awayfrom dependence on Win16 code. So if one day thelast drop of 16-bit or real-mode codeis gone from Windows (“hey, we finally got aroundto creating PSPsin protected
modeandstoring themin extended memory”),is that some kind of importanttransformation? No. Thereal transformation occurred with
Windows 3.0 Enhanced modein May 1990. And,although important, the crucial aspect of this transformation in 1990 wasn’t the technical change of basing Windowson a protected-mode DOSextender. Recall that asimilar important technical change took place in 1987-88 with Windows/386 2.x (which forms the basis for much of VMM), without transforming the PC desktop. Far more important than
the newtechnology in Windows3.x wasthe fact that Windowssales took off in 1990. On the other hand, this explosion in sales would never have
happened had Windowsnotincorporateda protected-mode DOSextenderthatfinally providedsufficient memory to make Windowsuseful. With massivesales,all things becomepossible. There’s an interesting parallel here to the ongoinghistorians’ debate over the Industrial Revolu-
tion: Was it a “wave ofgadgets,”orwas it more importantly an explosion in sales, consumption, population, and market size?
WhenUdell says “programmers who hadn’t yet worked with NT were, in general, more impressed with Chicagothan those already familiar with NT,” I have to wonder whatthese programmersalready familiar with NT are thinking about. What is
impressive about Win-
dows is notthis or that technical feature,but its installedbase. If you want technical excellence, I’msure you can doa lot better than
Unauthorized Windows 95
Windows. If you wantto developapplicationsthatwill potentially be
used by millions of people, Windowsis the wayto go. In other words, a
massiveinstalled base will get you through timesof unimpressive tech-
nology better thanimpressive technology will get you througha small
installed base. Windows 95 will outsell NT byat least an order of magnitude. Microsoft knows thatthis is what matters most about Windows 95. The
coolest features matterlittle without the massive presence on the desktop
required to make developingfor the operating system worthwhile. As the StarKist commercialputsit, “We don’t want tuna with goodtaste; we
wanttunathattastes good.” Windows95's reliance on DOSand on Win16 code is not an “Achilles
heel.” Instead,eliminating real-mode and Win16 code would be a Pyrrhic victory. Windows would attain 32-bit nirvana andlose a large number of customers. The movie Field ofDreamshasit all wrong: You can build it but they won't necessarily come.
The WSPY21 Code This long tirade of mine, you maydimlyrecall, was inspired by a few scant lines of WSPY21 output. I had originally intended WSPY?21 to illuminate
the DOS-Windowsrelationship, butit turned outto beatleast as useful
in shedding light on thepossibly more important (and by now certainly moreinteresting) question of the Win32-Win16 relationship. As we'll see,
Y21 also clarifies some otherwise-confusing features of the
protected-mode INT 21h handlerthat lives inside the Winl6 KERNEL.
Solet’s lookat the code that producedthose fewlines of output that
we've pored over for so long.Figure 13-3 shows a calling tree for WSPY21.
main
IN1T_REQUBUF GetCurrentTask get_vect set_vect (install IntHandler) e_vect (INT 31h AX=0205h) vect (INT 31h Ax=0204h) © (install IntHandler2) Getsetk display_ints winio_openwindows wnhandler_yield (GetMessage, etc.) read data
Chapter 13: Thunk! KERNEL32 Calls KRNL386
IS_REQI BEGIN IT_SEC —fmemcpy, _fstrnepy END IT_SEC SET T display_ int
prin
IntHandler tCurrentTask wr tedata BUFFER_FULL N_CRIT_SEC ‘memcpy, _fstrnepy verr sel_size (GetSelectorLimit) MAYBE_COPY verr sel_size SET_NEXT END_CRIT_SEC PostMessage _chain_intr IntHandler2 GetCurrentTask SAME_CALL writedata (see above) nintr Figure 13-3:Calling tree for WSPY21. Asthecalling tree suggests, the program consists of three semi-independentpieces:
¢ The main functioninstalls the interrupt handlers andcalls display_ints, which calls read_data to retrieve items froma circular
buffer. (WSPY21 is a WINIOapplication, andso starts off in main
rather than in WinMain.) If not spying on INT 21h (you canspecify an alternate interrupt on the WSPY21 commandline; INT31h for
DPMis particularlyinteresting) or on encountering an unknown INT21h call, WSPY21 produces plain register dump. ¢ IntHandleris the primary INT 21h hook. For each INT 21h call
IntHandlersees,it calls write_data to place a packetof information aboutthe call in the same circular buffer from which display_ints reads. This information includes the name ofthe current task at the
timeofthe INT 21h;the interrupt handler in WSPY21 runs aspart of this othertask. (As explainedearlier, this is why GetCurrentTask
Unauthorized Windows 95
doesn’t get WSPY21’owntask handle.) IntHandler posts aWM_ NULLmessage to WSPY21’s window, so that wmhandler_yield (which calls GetMessage) will return anddisplay_ints candisplaythe next INT 21h call, IntHandler chains theinterrupt to the previous handler, whichis generally KERNEL’ INT21hhandler. * IntHandler? is almost the sameas IntHandler, exceptit installs with GetSetKernelDosProc andtherefore sees INT 21h at a slightly lower level than IntHandler, IntHandler2 uses a SAME_CALL macroto determine whether IntHandlerhas already seen(referring to a muchdespised but perfectly-workable add-on thatallows Windows 3.1x to run some Win32 executables) a call and therefore that it neednot be displayed again (unless you run WSPY21 -SHOWALL; seebelow). Listing 13-5 shows the code for WSPY21. This code is basedloosely on
the WISPY(I Spy for Windows) program from Undocumented Windo:
(pp. 180-188). A majordifference is that WISPY usedonly GetSetKernelDosProctoinstall a single INT 21h handler, but WSPY21 installs two
INT 21h handlers. WISPY therefore missedall calls, such as function 4Bh (EXEC), that are absorbed in KERNELINT 21h handler, but WSPY21
sees thesecalls. ‘Thevery fact that KERNELcanabsorbor change some protected-mode INT 21h issignificant; we'll get to that soon.
Listing 13-5: WSPY21.C WSPY21.C Andrew Based
#include #include #include #include #include include
Iman, 1994 ly on WISPY.C from Undocumented Windows
"windows." "wmhand)r.h* “winio.h"
#oragma pack(
typedef struct |
Chapter 1
}: Thunk! KERNEL32Calls KRNL386
This gives us about 550 entries in the buf still frequent (REQUEST define MAX_STR a fefine MAX
overflows
har dsdx{MAX_STRI, dssifMAX_STR]
MAX REQU) next=@; else nexttt; ) buftnext].type REQU_ S_REQUEST (buf)
a,b)
((void far *)(((DWORDI(a) (Oxf2+8))) return (char far *) MK_FP(hTask, Oxf2); else return none:
int WRT_REQUEST(REQUEST far *buf, REGPARAMS far *pr, HANDLE task, int flag) static int next 0 unsigned char ah; void far *fp; if (BUFFER_FULL(buf)) return 0; BEGIN_CRIT_SEC(): _fstrncpy(&buf(next].taskname, GetTaskName(task), 8): buf{next].taskname[8] = "\0"; —fmemcpy(&buf(next].r, pr, sizeof(REG_PARAMS)) ; buf{next].type = REQU_USE
#ifl fdefine MAYBECOPY(str, rl, r2) I \ _fmemset(str, @, MAX_STR): \ if (verr(rl) && (sel_size(rl) > r2)) \ _fmemepy(str, MK_FP(r1. r2), min(MAX_STR-1, sel_size(rl)-r2)); \ } Helse // IsBadStringPtr works by causing GP faults which KRNL386 catches // But this seems use unexpected page faults in Win32s! define MAYBE_COPY(str, rl, r2) { \ _fmenset(str, 0, MAX_STR); \ Fp = MKFP(rL, 72); \ if (1 IsBadStringPtr(fp, 256)) \ _fstrnepy(str, fp, min(_fstrlen(fp), MAX_STR-1)): \ Hendif
Chapter 13: Thunk! KERNEL32 Calls KRNL386
( top
pr-dax >> 8; (ah >= FIRST_FUNC && ah ds, pr->dx) // else if (copyflagsCah] == COPY_DSSI) MAYBE_COPY(Abuf[next].dssi, pr-2ds, pr->si) //: else if (copyflagsLah] == CHECK_AL) { ah (pr-dax & Oxff) FIRST_FUNC; f
(copyflagsfah] !=
goto top:
CHECK_AL)
buf{next].flag = flag SET_NEXT() END_CRIT_SEC(); PostMessage(__hMainWnd, WM_NULL, 0, 0); // just to keep moving! return 1
nt, RO_REQUEST(REQUEST far *buf, REG_PARAMS *pr, LPSTR ptaskname, PSTR Ipdsdx, LPSTR Ipdssi, int far *pflag) static int next = 0: 1S_REQUEST( buf) return 0 BEGIN_CRIT_SEC(); fmemcpy(pr, &buflnext].r, sizeof(REG_PARAMS)); _fmemcpy(ptaskname, &buf{next].taskname, 9) fstrncpy(Ipdsdx, &buf{next].dsdx, MAX_STR) py(Ipdssi, &buf{next].dssi, MAX_STR): *pflag = buf{next).flag; buf{next].type REQU_FREE; RIT_SEC SET_NEXTO): return REQUEST far *INIT_REQUBUF( void)
QUEST) GlobalLock(GlobalAlloc(GMEM FIXED | GMEM ZEROINIT ZE * sizeof(REQUEST))))) return 0 for (i=BUF_SIZE, p=buf; i--; pH) p->type = REQU FREE return buf;
Unauthorized Windows 95
FARPROC (FAR PASCAL *GetSetKernelDosProc)(FARPROC DosProc)
0;
typedef void (interrupt _far *INTRFUNC)( INTRFUNC _dpmi_ { ivs
jode_vect(int intno
mov ax, 0204h mov bl, byte ptr intno int 31h ic error iv#2, cx y word ptr ov word ptr iv, dx
) return fv; error return (INTRFUNC) 0;
void _dpmi_set_pmode_vect(int intno, INTRFUNC (asm ( mov ax, 0205 v bl, byte ptr intno mov cx, word ptr iv+2 mov dx, word ptr iv int 31h ) /{ _asm jc error #define get_vect(intno) (
iv)
_dpmi_get_pmode_vect (int:
nt set_vect(WORD intno, INTRFUNC handler /
e INT 2in f because “s INT 21h han Ih, 24h PMI inst v dal undoc NoKookDOSCa / which bypasses most KERNEL's special INT 21h handling dpmi_set_pmode_vect (intni handler); intng mot
void _ nterrupt _fa rrupt _f void static stati static static void o
HANDLE wspy21_task; int intno 0x21; INT 21h default INTRFUNC old 0 FARPROC old_dos = (FARPROC) @ ose(HWND hwnd
Thunk! KERNEL32 Calls KRNL386
winio_warn(FALSE, "WSPY2 "g08lu\tintercepted\n "08lu\talready seen in first handler\n" "S08lu\tabsorbed first handler\n™ "SOBlu\tlost through buffer ov "S08 1u\twe rem own calls\n calls, already, (intno = 0x21) ? calls ost, mi if
f
set. tint winio_warn(FALSE,
already
0,
old)) "WSPY21"
uldn't restore Int $02xh", intno);
((intno x21) && old_dos) GetSetKernel0 sPrac(old_dos)
void display_int(REG_PARANS *pr)
AK=RO4K BX=B04x CK=804x OX=O4x DS=%04x ST=¥04x DI-tOdx * TP=404x:804xh", bx, pr-dex, pr->dx r->si, pr-rdi, pr
define define define define
PRINT_STR PRINT_2 STR(sI, 52 PRINT STRWORD(s, w) PRINT_2 WORD(S, wl, w2)
didefine PRINT_STR_BYTE(s, b) #define PRINT_STR_FP(s, fp
02x)",
printf printf ), (82)) printf Gs). 00, printf(*&s fu (8O4Xh), Su (X04Xn)", (3), (WL). (WL). (W2), (w2)) intf("Rs ku (BO2xH)", (Ss), (b), (b)) rintf("Bs Bp", (s), (fp))
al
PRINT_STR_BYTE(*Is Drv Remo 9: PRINT_STR_BYTE(*Is Drv Remote?” case OxOE: PRINT STR_BYTE("Get Log Drv Ma /. boring list of TOCTL functions
lay_dos_int(REG_PARAMS *pr, char *dsdx, char *dssi) int ahs
// 1DoBel ievelUsedAGoTaStatement ah >ax >> 8; printf("(@O2K) ah): switch (ah) / CantBelievelus |ASwitchStatement
Unauthorized Windows 95
Or
case case case case case case case case case case case case case case case case case case case case
0x00: OxOE: 0x19: Ox1A: 0x25: Ox2A: Ox2C: Ox2F: 0x30: 0x32: 0x35: 0x36: 0x3B: Ox3C: 0x3D: Ox3E: 0x3F: 0x40: 0x41: 0x42:
PRINT STR(*Exit™); break: PRINT STR_BYTE(*Set Disk", pr->dx & OxFF); break: PRINT_STR(*Get Disk"); break: PRINTSTR_FP(*Set OTA", MK_FP(pr->ds, pr->dx)): break PRINT STR_BYTE("Set Vect™, pr->ax & OxFF): break: PRINTSTR("Get Date"); break; PRINT_STR("Get Time"); break: PRINT_STR(*Get OTA"); break; PRINT_STR(*Get DOS Vers*); breaks PRINT STR BYTE(*Get DPB", pr->dx & OxFF): break: PRINT STRBYTE(*Get Vect", pr->ax & OxFF); breaks PRINTSTR_BYTE("Get Disk Space”, pr->dx & OxFF); break: PRINT_2STR(*ChDir™, dsdx); break: PRINT_2STR("Create", dsdx); break: PRINT_2STR(*Open", dsdx); break: PRINT_STRWORD(*Close", pr->bx); break; PRINT_2 WORD("Read”, pr->bx, pr->cx); break; PRINT_2 WORD( "Write", pr->bx, pr->cx); break: PRINT_2STR(*Delete", dsdx); break: printf("Lseek$d ku 204x804x", pr->ax & OxFF, pr->bx, pr->cx, pr->dx); break: PRINT_2STR(*Get/Set File Attr", dsdx); break
case 0x43: #ifdef SHOW_TOCTL case 0x44: print_ioctl(pr): break: Helse case 0x44: PRINT_2 WORD("IOCTL", pr->ax & OxFF, pr->bx); break; fendif case 0x47: PRINT STRBYTE(*Get Curr Dir", pr-2dx & Oxff); break: case Ox4b: PRINT_2_STR("Exec", dsdx); break: case Oxdc: PRINT STR_BYTE(TExit", pr->ax & Oxff); break; case Ox4e: PRINT_2_STR(*Find First", dsdx); break; case Ox4f: PRINTSTR("Find Next"); break: case 0x50: PRINT STR_WORD("Set PSP", pr->bx); break; case 0x51: case 0x62: PRINT_STR(*Get PSP"): break: case 0x55: PRINT 2WORD("(Undoc) Create PSP", pr->dx, pr->si); break: case 0x57: PRINT STR_WORD("Get/Set File Date/Time", pr->bx); break: case 0x59: PRINT STR("Get Extended Error Info"); break: case Ox5A: PRINT_2STR("Create Temp File", dsdx); break: case Ox5B: PRINT 2STR(*Create New File", dsdx); break; case 0x60: PRINT 2 STR(*Truename", dssi); break: case 0x65: PRINT STR_BYTE( "International", pr->ax & OxFF): break: case 0x68: PRINT STR_WORD( "Commit", pr->bx): break case Ox6C: PRINT_2 STR(*Open/Create", dssi); break: // for 21/71XX, do what IFSMgr does: mark as an LEN function // and then turn into 21/XX. case Ox71: printf(*LFN "); pr->ax < = 8; goto top: case OxAO: PRINT_2 STR(*Get Volume Info", dsdx); break; case OxAl: PRINT STR(*Find Close"): break: display_int(pr); default: void display_ints(void)
Chapter 13: Thunk! KERNEL32 Calls KRNL386
tic char dssi (MAX int flag: / This loop looks for, extracts, and displays messages queued up by the interrupt handler. The only way we know to // terminate the function is that the window closes while (winio_openwindows()) i wmhandler_yield(); while (RO_REQUEST(requ, &r, &modname, &dsdx, &dssi, &flag)) printf(* ic", modname, flag): if Cintno 0x21) display_dos_int(&r, dsdx, dssi): else // Could do formatted display of other INT like OPMI display_int(ar); printf("\n");
main(int argc, char *argvt]) { char buf{128], num[8] if (__hPrevinst fail("Sorry, only one WSPY2i at a time"); winio_setbufsize(__hMainWind, (WORD) 32768, TRUE); if (1 (requ = INIT_REQUBUF())) fail ("INIT_REQUBUF fai]!"); winio_about("WSPY21"); winfo_onclose(__hMainwnd, (DES ROY_FUNC) on_close) wspy21_t GetCurrentTask(); if (argc < 2) ntno = 0x21 else int i: for (ial; i¢arge; i+ if Cargvli}{e] = '-") if (strnemp(strupr(BargvCil[1]), "SHOWALL™, 4) ow_al ++; else fail("usage: wspy21 [-showall] [intno]
sscanf(argv(il, "BX", &intno); old = get_vect(intno);
Unauthorized Windows 95
ntno, (INTRFUNC) Int ct failed!")
#define GET_PROC(Mod, func) GetProcAddress (GetM dle(mod), (fun) f (Cintno == 0x21) && (GetSetkerne]DosProc = GET_PROC( "KERNEL", "GETSETKERNELDOSPROC"))) old_dos Kerne]DosProc((FARPROC) IntHandler2 sprintf(buf, “Windows Interrupt Spy: INT %02xh", intno); winio_settitle(__hMainWnd, buf): disp ay_in return 0
c REG_PARAMS prev_r = (0) c int was_prev = 0
CSIP can be different define SAME_CALL(r1, r2) ((rl)-des (r2)->es) && (rl)->di (r2)->di) && (r1)->bx (r2)->bx) && (rL)->ex (r2)-dex) BB
((rl)->ds ((r1)->si ((r1)->dx ((r1)-rax “=
dds) && >si) 8 >dx) 88 (r2)->ax)
void interrupt _far IntHandler(REG PARAMS r { HANDLE task = GetCurrentTask() if
Cl
all) | prev_r = rs was_pr
if
1 else
* don't show my own ints * if (! WRT_REQUEST(requ, &r, task, INTZ1)) ost++; * buffer overflow */ calls+ mines;
chainantota
void interrupt _far Int HANDLE
= GetCurrentTask();
if (C1 show_all) && was_prev-©
REG_PARAMS 1)
already++ goto done:
&& SAME_CALL(&r, &prev
/* saw this already in IntHandler
if (task == wspy2l_task)
* don't show my own 4
*
Chapter 13: Thunk! KERNEL32Calls KRNL386
requ. &r, * buffer
ELDOSPROC))
The most important point about WSPY21 is that, unlike V86TEST,
it sees INT21hcalls generated in protected mode by Windowsapplications in the System VM. WSPY21 won't see INT 21h calls made from
DOSboxes, norwill it see any that are first generated somewhere in
‘VxD-land and then sent down to V86 mode. (For this, see the WLOG-
212F programdiscussed in Chapter 1.)
Toinstall a handler for INT 21h callsissued in protected mode, a program running under a DOSextender such as Windowswould normally call the same DOSfunctionthat a real-mode program would call to hook INT21hinreal mode: Set Interrupt Vector (INT 21h function 25h).
The purpose of a DOSextender is to providea familiar INT 21hinterface to protected-modefunctionality and to make DOSseem to be a protected-mode operating system. (Althoughperhapsseem is no longer really the right wordhere; see the sidebartitled “The DOS extender: Still a great pretender?”)
The DOS extender: Still a great pretender? Imagine for a momentthat you don’t know anything about protected-mode INT 21h or DOS extenders. When you open a documentin WinWord, open a spreadsheet in Excel, or do somethingsimilar in any protected-mode Windows application,either the application itself or a DLLit calls generates the equivalent of an INT 21h File Open call — in protected mode. Yet MSDOS,as weall know, is a realmode operating system. How then is protectedmode INT 21h handled? Thenaive conception among a surprising numberof Windows and DOS programmersis that since the request involves an INT 21h, Windows musttherefore service the request “bycalling down to DOS.” As a random
Unauthorized Windows 95
Cr
example of this widespread misconception, one programmer asserted (Windows/DOS Developer's Journal, April 1994) that a certain technique for watching DOSfile 1/0 calls “is possible becauseall file opening is donethrough the real-mode DOS INT 21h services.” | hopeit is clear from examples such as TEST21 in Chapter8 that this ain't necessarily so, evenforinterrupts coming from realmode DOS programs in V86 mode. Thus, there is certainly no reason whyit should be true for protected-mode Windowsprograms. If Windows has complete discretion over how to handle interrupts comingfrom real-mode DOS programs that know nothing about Windowsor protected mode, imagine whatit can do with interrupts — even supposed DOSinterrupts such as INT 21h or INT 2Fh — coming from applications that were designed for protected mode and that know about Windows. To request OFFFEh pararaphs of memory, a Windows application could issuethe following request: _asm _asm _asm asm _asmi
mov ah, 48h ; DOS function 48h: Allocate Memory mov bx, OFFFEh OFFFEn * 16 = 1,048,544 bytes int 21n 3 "DOS cal}* (bu necessarily call DOS!) jc alloc_error carry flag set indicates error mov segment, ax save away address of allocated memory
alloc_error:
Win46applications are supposedtoallocate memory not by calling INT 21h function 48h but with a Windows API function such as GlobalAlloc or LocalAlloc. Humor me for a moment.The preceding code can be placed inside a Win16 application. What's more, when placed inside a Win16 application, this code succeedsin allocating OFFFEh paragraphs (1,048,554 bytes) of memory. What's so strange about that? Well, if you think back to the days of
realmode DOS,you might recall that requesting a large numberof paragraphs such as OFFFEh or OFFFFh was guaranteedtofail. Calling INT 21h function 48h with BX set to such an “impossibly high” number was the standard technique to determine the size of the largest block that could be
allocated. Evenif there were megabytes of free memory in the machine,
real-mode DOS could only allocate substantially less than a megabyte of
so-called conventional memory.
But INT 21h function 48h doesn’t behavethis way when called by a Win46application. To demonstrate,Listing 13-6 shows DOSMEM.C, a tiny Windows program thatcalls the DOS Allocate Memory function.
Listing 13-6: DOSMEM.C
Chapter 13: Thunk! KERNEL32 Calls KRNL386
Hinclude Hinclude *windows.h*
define MK_FP(seg,ofs) ((void far *)(((DWORD)(seg) *(2F) Get DTA (50) Set PSP 6799 (1ABFh (2F) Get OTA *(1A) Set DTA 3107:8B8E 'C:\WEWS1L\WIN. INI’ *(4E) Find First *(1A) Set DTA 1A8F:0080 (3D) Open 'C:\WFW311\CLOCK, INI"
*(2A) (5@) (2A) *(2C)
Get Set Get Get
Date PSP 6799 (1ABFh) Date Time
Unauthorized Windows 95
To run a Win32 application, Windows 3.1” must load the Win32s
subsystem. This processis described in my Microsoft Systems Journal
(April 1993) article on Win32s (see especiallythe “How DoesIt Work?” section on pp.24-29)and in Matt Pietrek’s Windows Internals (pp. 244, 292-293).
Briefly, here’s how Win32s loads: Wheneveryouselect a program to run under Windows3.x (for example,byclicking anicon in Program Manager), whatevershell you’re usingcalls the WinExec APIfunction, whichin turncalls LoadModule. LoadModule hasan error return code indicatingthatthe specified module was a Win32 Portable Executable (PE)file rather than a Win16 NewExecutable (NE)file. When WinExec
seesthis error return,it calls a function in KRNL386.EXEthat’s called ExecPE.Yes, Windows3.1 had built-in knowledge of Win32 PE executables; Win32s was nottackedonlater as an afterthought.
is an importantpoint because if Win32s was in some way“inte-
grated”into Windows3.1, then suddenly Windows 95 looksa lot less
like a brand-new version of Windowsanda lot morelike a vastlyimproved version of Win32s. When someone makesthis point, the programmersworking on Windows95 at Microsoft protest that “Chicagois not Win32s!” This wasa frequentrefrain at the December 1993 Win32 developer's conference at Disneyland, for example. They assertthat in contrast to Win32s, Windows95 is integrated, seamless, andall sorts of
other good things. But Microsoft doth protest too much. When Win32s first came outin late 1992, the companywhistleda different tune: “Win32s and Windows 3.1 system-codeare tightly coupled. Win32s is a true systemextension to
the Windows3.1 operatingsystem code”(Microsoft KnowledgeBase
article, “Coordination Between Windows 3.1 and Win32s,” 1992). It’s a
stretch to call a small hook in WinExec “tightly coupled,”butthis the samestretch that Microsoft makes with each newsystemsoftwarerelease.
The newsoftwareis always “integrated,” “seamless,” and“tightly coupled,” andits predecessor suddenlyturns out notto have been.
Perhaps wewill one daybe hearing how Windows 2000is trulyinte-
grated and how Windows 95 wasn’t. I predict that at the December 1998 developer's conference (whichI furtherpredictwill be held at the Coney
Island Cycloneat Astroland Amusement Park; see Microsoft Systems Journal, July 1994), Microsoft developerswill tell the assembled 20,000 ISVs
Chapter 14: Mixing 32-Bit and 16-Bit Code
(all writing Microsoft Office add-ins in Visual Basic), “Windows2000is not Windows95!”
Returningtoreality, and to the WSPY21 log, ExecPEloads W32SYS.DLL(a Win16 DLL), which in turn loads WIN32S.EXE.This is a tiny Win 16 executable, whichacts as the proxy for a PEfile in the 16bit world. Another Winl6 DLL, WIN32S16.DLL, containsthe 16-bit
side of the Win32skernel. In addition to codethat can load PEfiles into memory under Windows3.1, resolve their fixups, and so on, WIN32S16
also contains the 16-bitside of the code that allows Win32 APIs to be implemented ontopofthe existing Windows3.1 16-bit DLLs. WIN32516 loads W32SKRNL.DLL, which is a Win32 DLL.
With the fundamental 16/32-bit communication portion of Win32s loaded, WIN32S16 can now proceedto load the Win32 executable (here, CLOCK.EXE) and any Win32 API DLLsit uses (here, COMDLG32, KERNEL32, USER32, GDI32, NTDLL, and SHELL32). For example,
KERNEL32.DLL contains the GetSystemTime and GetLocalTime Win32 APIservices that Clockwill need to call whenit receives a WM_
TIMERmessage.
Now,the WV86TESTlog showsthat DOSsees almost noneofthis furiousactivity involved in bootstrapping the entire Win32s subsystem. The combination of 32BFA and Win32s turns WfW3.11 into something
that beginsto looklike a genuine 32-bit protected-mode operating system, much like Windows95. Indeed,aswill be discussedin detail at the end ofthis chapter, Windows95 looks a lotlike a Win32s “doneright”;it
certainlyisn’t the “NT Lite” that some in the computertrade press have wishfully thought. Now, WV86TESTsees INT 21h function 2Ah and 2Chcalls from
the Win32 version of Clock. Rememberthatthis is the CLOCK.EXE that comes with Windows95. It is unlikelythat this executable contains direct INT21h calls. Actually, it’s more than unlikely;it’s impossible: putting an _asmint 21h in a Win32 executable causes a GP fault under
both Win32s and Windows 95. So how does WV86TESTsee INT21h function 2Ah and 2Chcalls coming from Clock? Asjust noted, Clock’sWM_TIMER handlercalls the GetSystemTime and GetLocalTime Win32 API functions, which are exported from
KERNEL32.DLL. If you use the Win-ICE BMSG(breakpoint on message) command to set a watch WM_TIMER messages going to Clock and, when the breakpoint is hit, trace (F8) through the code, you eventu-
ally get to this block of code in KERNEL32:
Unauthorized Windows 95
nov
The numbers being movedinto the AH register, 2Ah and 2Ch, should look familiar: These are the numbers of the INT 21h Get Date and Get Time functions.It’s a safe bet that the function at 80BDC3E4h does INT 21hcalls on behalf of Win32 applications. Jumping through several more levels of code, youget to a 32-bit instruction in W32SKRNL.DLL:
2197:808927B3 FFIDF4008980
CALL FWORD PTR [80B9D0F4]
‘The odd-looking FWORDPTRrefersto a farpointer. In 32-bit code, a far pointer is 48 bits, in the form 16:32 (16 bits for the selector and 32 bits for the offset).FWORD PTR indicates that the processorwill use a 48-bit address (16-bit selector and32-bit offset). As we'll see later, Win-
dows 95 uses the sameinstruction when 32-bit codehasto call down to
16-bit code. Windows NTuses the same mechanismaspart of its WOW
(Windows on Windows) subsystemfor running Win16 applications. For an excellent discussion, see Jim Finnegan’s article on WOWinthe June
1994 Microsoft
SystemsJournal, especially the sidebar on CALL FWORD
PTR(pp. 34-35).
In ourcurrent example, theCALL FWORDPTRinstructionwill interpret the six bytes at 80B9DOF4h as a 16:32 address tocall:
dw Bongdar4 2197808900 4 02C5 0000 1137 In otherwords, executing CALL FWORDPTR[80B9DOF4H]will generatea far call to 1137:000002CS. In this configuration, selector
1137h contains 16-bit code, belonging to WIN32S16: 6
—-Base=BOB3A620
Lim-0000057F DPL=3 P Owner WIN32S16
RE
Type Code
Thus, whenthe 32-bit part of Win32s executes the CALL FWORD
PTRinstruction,it calls into the 16-bit part. If you use a debugger to trace through the single CALL FWORD PTRinstruction in
W32SKRNL, yousuddenlyfind yourselflookingat 16-bit codein WIN32S16. The code at 1137:02C5 generates an honest-to-goodness INT 21honbehalf of its 32-bit caller.
Chapter14: Mixing 32-Bit and 16-Bit Code
Thunking: Mixing 16- and 32-bi code with COLL FWORD PTR CALL FWORD PTR(opcodes FFh 1Dh) is Win32s’s wayofletting 32-bit code call down to 16-bit code. Microsoft somewhatincorrectly uses the term
thunk to describethis mixing of 32- and 16-bit code.
You can use FWORD.C(Listing 14-1) and INTSERV.C (Listing 14-2)to experiment with these 32-to-16 thunks. FWORDis a simple Win32 program that doeslittle more than make a CALL FWORDPTRto the address you specify on the program's commandline,using whatevervalues you specify for EAX, EBX, ECX, and EDX.
lude #(62) BG (62) cet ~(62) =(62) Get "(62) Get > =(62) Get iFsMgr
b DOSMGR|
b> ol chain
86 Interrupt Hook Chain pb DOsMGR| p> see > IFsMer chain 86 Interrupt Chain p Restof > VacTEST] p> IFSHLP chain Vv Dos Figure 14-4: How the Win32clock gets the date and time, part 3. The Exec_PM_Int service in VMM sendsthe simulated INT 21h function 24h and 2Chcalls to the protectedmodeinterrupt chain.If no protected-mode INT 21h handlerservicesthecalls, they are next sent to the VxD INT 21h hookchain. If no handler here services thecalls either, they are sent to the V86 interruptchain, and eventually to MS-DOS.SeeFigure 14-5 for the exciting conclusion,revealing what happenstothe calls inside DOS.
Figures 14-2 through 14-5 certainlyreveal a mechanismthat is far more complicatedandinteresting than a plain INT 21h, but the result is still that DOS sees an INT 21h function 2Ah or 2Chcall —
shown by the WV86TESToutput that got us started on this subject in
thefirst place.
Does Windows 95 Really Call Down to DOS? And What Does tt Bo When It Gets There? Bynow, you must have a few nagging doubts andworries about whether Windows 95 really andtrulycalls down to MS-DOSto implement Win32 APIfunctionssuch as GetLocalTime.
Unauthorized Windows 95
First, just because V86TEST has seen Windowsissuing calls to INT 21h functions 2Ah and 2Ch, doesthis really mean that DOS sees these
calls too?It’s true that V86TESTchainsall calls to the previous interrupt handler (see V86TEST.C in Chapter 10). But we knowfromprevious chapters that IFSHLP.SYSsits between V86TEST and DOS, and that one of IFSHLP’s main responsibilities is to divert DOS calls away from.
DOSand toward IFSMgr(see “The Role of IFSHLP.SYS and V86 Callbacks” in Chapter 8). So perhaps V86TESTsees thecalls but DOS doesn’t. I'll addressthis issue in a moment. Second,there’s what we mightcall the Heisenberg worry. As part of
the explanation for his uncertainty relations(for example, that you can’t determinesimultaneously,for a given degreeofcertainty, both the position and the momentumofa subatomicparticle), Werner Heisenberg came up with a “thought experiment”involving an imaginary gamma-ray microscope. Using Heisenberg’s microscope,the veryact of observing a particle diverts it from the position or momentum it would havehadin
its unobservedstate. Andthefiner the resolutionof the microscope, the moretheact of observation perturbsits subject.
There’s a nice analogy (but nothing morethan that) to computing: Whenyouuse onepiece of software to examine anotherpiece of software
with whichitinteracts, you must be careful not to build a Heisenberg microscopethat changesthe behavior of what you’retrying to observe. Now,is V86TESTa Heisenberg microscope? Does the mereact of
loading V86TEST before Windowsperhaps change the way that Windowsinteracts with DOS? Doesthe presence of V86TESTcause Windows to send INT 21h calls such as functions 2Ah and 2Ch downto DOS? If V86TESTwere notpresent, would Windows still do this?
‘These questionsare important because Microsoft hasasserted for the
longest time that Chicago would completely
bypass DOSunlessthere
was an INT21h hooker pov other than DOSitself) on the system. The presenceofeven a single TSR that hooks INT 21h would then
presumably cause Chicagoto sendall DOScalls down to the INT 21h chain. So perhaps V86TESTis that TSR andperhaps, without
V86TEST, Windows would be behaving quite differently.
There are several waysto addressall these concerns. First, though it
does contradict other Microsoft statements intended for the goyim (that’s
“for public consumption”in Yiddish), Microsoft has explicitly stated that Windowswill pass downall non-file /O INT 21h calls. Once more,
recall the Microsoft documenttitled “Chicago File System Features,” quoted in Chapter 8: “On default all INT 21 interrupts,exceptfile API INT21s, are passed downtoanyhookerpresentin the system.”
Chapter 14: Mixing 32-Bit and 16-Bit Code
In this book,I could have perhapsjust quoted this sentence a few
moretimes — each time reminding youthat DOSitself is an INT 21h hooker — and not bothered with any experiments. With this one sentence, Microsoft says that Windows 95 — including Win32applications running under Windows 95 — calls down to DOS for non-file services,
suchasgetting andsetting the date and time. But the document’s description of Windowsinteraction with INT 21h hookers doesn’t really hit you (atleast,it didn’t hit me) until you’ve performed the experiments and seen
what the documentis getting at. This sentenceis such a glaring contra-
diction with Microsoft’s “Windows95 doesn’t require DOS”propaganda that most readers probably focus on the “exceptfile API INT 21s”part and gloss over the broader statementbeing made about INT 21h in general. Forall the talk of Windows95 not requiring DOS, what Windows 95 actually doesin relation to DOSis precisely what WfW 3.11 does: provide 32-bit file access. Atany rate, Microsoft’s statementis consistent with our finding that Windows 95, like Win32s, implements certain Win32 API functions by
calling (albeit in a highly baroque andcircuitousstyle) down to the realmode MS-DOScode (which Windowsrunsin V86 mode). Second, by comparing output from WV86TESTand WSPY21, we’ve seen that many DOScalls are not passed down, even when V86TEST is loaded. Again,this is consistent with the Microsoft documenton the Chicagofile system: “Thefile API INT 21s are just passed to VM (local) hookers, but not to global (AUTOEXEC.BAT)type hookers.” V86TESTis a global INT 21h hooker. We’ve seenthat, indeed, Windows
doesnotpassit any file INT 21h calls. It seemsa fair presumption,then, that the fewcalls that are passed down would still be passed down evenif V86TESTweren't loaded. Third, by running without V86TESTandputting a debugger breakpoint on the real-mode DOScode, we can confirm that the INT 21h calls seen by V86TEST, suchas functions 2Ah and 2Ch,really really are sent down to DOS, even when V86TESTisn’t running. It’s worth look-
ing at this not only to prove that V86TESTis not a Heisenberg micro-
scope (were youreally all that worried?) butalso becauseit helps make a critical point about Windows-DOSinteraction. Here goes. I started Chicago without V86TESTand from a DOS box ran the
INTCHAIN program(see the Unauthorized Windows 95 disk), usingit to locate DOS’s INT 21h handler. Starting from when INTCHAIN issues the INT instruction given onits command line (such as “21/200”for INT 21h function 2Ah), until the interrupt returnsto the line of code
Unauthorized Windows 95
after the INT instruction, INTCHAINsingle-stepsthroughtheinterruptchain,displaying key addresses such as when the segment changesor whenanother INTis encountered. I’ve added commentstothe following output from INTCHAIN:
C:\UNAUTHW>intchain 21/2200
ts do INT 21h func 2ah (Get Date)
Tracing INT 21 Ax#2A00 494 instructions Skipped over 5 INT 0337:04A8 IFSSHLPS O1eF:0023 0498:1956 DBLSYSHS OFAC DOS 2429 HMA 4339 HMA INT 2Ah 5354 HMA INT 2Ah 0166 «10 8979 HMA QOEE 10 e040 HMA Q8DA HMA INT 1Ah 2985 HMA 5383 HMA INT 2Ah
ty IFSHLP.SYS BLSPACE.BIN low-memory stub for DOS in HMA (DOS=HIGH) 00S's INT 21h handler in HMA AX=8200h End critical sections 0-7 AX=8002h Begin critical section 2 i: Device driver generic Strategy routine +3 CLOCKS Interrupt routine in here AX=0000h ;; CLOCKS calls 14/00 (Get System Time) AX=8102h :; End critical section 2
We'll examine this DOS -> CLOCK$ -> INT 1Ah chain in more
detail momentarily. Right now, we need onlyonepieceofinformation: FE9E:4249is the location of DOS’s INT21h handler. We can use WinICE to set a breakpoint on this V86-mode address (BPX & FE9E:4249).
Sureenough, the breakpointis triggered, showing that Windowsreally
doescall down to DOS. This answersthefirst question, about whether
IFSHLPperhaps ships all INT 21h calls to IFSMgr — it doesn’t. Well, why would it? IFSMgr handles only aboutforty different INT 21h functions. In the absence of other VxDsthat handle INT 21h, such as my CURRDRIV.386 and INTVECT.386 from Chapter8, the remaining sixty orso less frequently used andless expensive INT 21h functions must be sent down to DOS; the Win-ICE breakpoint on DOS’s INT 21h han-
dler showsthattheyare. So we now know that Windows95 really does call down to DOS, even in the absence of an INT21h hooker such as V86TEST. We could leaveit at that, treating DOSas a monolithic black box. But rather than rest content with a vague statementlike “Windowscalls down to DOS,” let’s peerinside (“drill down” seemstobe the current Microsoft lingo)
DOS’s INT 21hhandler. Byseeing what happensinside DOSduring an
Chapter 14: Mixing 32-Bit and 16-Bit Code
INT 21h function 2Ah call from Windows,we’ll see whyit’s so important to remember that Windows runs DOSin V86 moderather than in real mode, and whythisis like taking the real-mode DOScodeand runningit in protected mode. If you trace through DOS'’s INT21h handler, you eventually hit something thatlookslike this: FE9E:000042F1 MOV BLAH FEQE:000042F3 SHL BX, 1 t: BX = 2* INT 21h func number FE9E:00004354 FE9E:00004359 FEQE:0000435E FE9E:00004363
MOV XCHG MOV CALL
BX, [BX+3FE1] ; index into table BX, SS: [0 : call handler for INT 21h func
This crucial bit of DOScodeis explainedin excruciatingdetail in the “Disassembling DOS”chapter of Undocumented DOS (2d ed., pp. 291297). Briefly, the BX register holds the INT 21h AH function number (such as 2Ah) multiplied by two. This numberis used to index into a table, here located at offset 3FElh in the DOScode segment. This table holdsnear function pointers to DOS’s handlers for each INT 21h function. The preceding coderetrievesandcalls this function pointer. With a
utility such as FTAB(the real-modeversion of PROTTAB), you can
dumpoutthis table and locate the handlers for the INT 21h Get/Set Date/Time functions: C:AUNAUTHW>Ftab fe9e:3Fel 73 121 2 ;; show 73h words at FESE:3FE1
212A i21_28 i212c i21_20
Now wecan put a breakpoint on the INT 21h function 2Ah handler at FE9E:48B8 andgoback to running Clock.If the breakpointis hit, it meansthat Windows95 calls down to DOS. Here’s someofthe WinICEtrace, which I saved to file, ran through the VXxDNAMEutility, and then decorated with myusual Talmudic commentary: Break Due to BPX &FE9E:000048B8 C=01
FE9E:00004888 FE9E:00004889
PUSH POP
SS. DS.
tii hit DOS code that does 21/24
: Prepare device-driver request packet. Device-driver function 4 (Read). Buffer points to a 6-byte CLOCKS transfer record
FE9E:00008980
CALL
FAR SS:[0378]
:;
00S calls CLOCKS dev driver
Unauthorized Windows 95
0070:000000EE
CALL
O1AF
trp this is CLOCKS Interrupt routine
070:0000018F FFFF:00000040
JMP PUSHA
FAR CS:(013A]
_; go to HMA (DOS=HIGH)
FFFF;00000808 FFFF:000008DA
SUB INT
—AH,AM 3 CLOCKS calls INT 1Ah fn 0 (Get Sys Time) 1A
Thus, Windows95is calling DOS.In turn, DOS’s handlerfor function 2Ah is calling the Interrupt routine for the CLOCK$ device driver. This in turn (assuming you haven’t supplied a new CLOCKSdriver) gets the currentdate and time for DOS bycalling ROM BIOS INT 1Ah
function 0 (Get System Time). Whydoesn’t CLOCK$just consult the BIOS data area, which includesa tick counter at 46Ch (0040:006C) and a midnightflag —
unfortunatelyfor those wholeave their machines runningfor days at a time, thisreallyis a flag and not a counter! — at 470h (0040:0070)? The
source code for CLOCK$ included in Microsoft’s DOS 5.0 OEM Adaptation Kit (OAK)hasthe following comment:
11/26/91 NSM M101: We lose date sometimes under windows. To fix this do Int 1a's to get tick count instead of looking at 40: 6ch and if we get rollover, then go & update : and time from CHOS Thisis from PTIME.ASM,whichis the source for the power-management version of CLOCK$ in POWER.EXE.Butthe standardversion of CLOCKS, in MSCHAR.ASM,also calls the ROMBIOS INT 1Ah to get
the time, presumablyfor the same reason. Well, at least CLOCKS thinksit’s calling the ROM BIOS. In fact,
because we're running in V86 mode under Windows, all interrupts vector through the IDT (see Chapter 9). The IDT entry for INT 1Ah points to VMM. Thus, when the DOS CLOCK$ device driver calls INT
1Ah,it’s actually calling into VMM. Windows mighthave called down to DOS in V86 modeto handle the INT 21h function 2Ah, but DOS (with-
out knowingit) is goingto call right back into Windowsto handle the INT1Ahfunction0.If you press F8 (trace) to drill down through the INT1Ah instructionin Soft-ICE, you can see a dramatic demonstration
of this. From the INT 1Ah inside DOS’s CLOCKS device driver, you suddenly switch into 32-bit protected mode and windupat the next instruction inside VMM:
FFFF:000008DA INT lA ts VMN hooks INT 1Ah via IOT jode DOS right bit protected mode VMN! ; INT takes us from ¥ 0028: vMN+2E44 eturn addr is VNM+2E49
Chapter 14: Mixing 32-Bit and 16-Bit Code
When it receives this INT 1Ah call from DOS, VMMdoes some
genericinterrupt-handling setup, and then walks the V86 interrupt
hookchain: 0028:vNM+000 0028: vMM+001 0028:VNM+002 0028:VNN+006 0028:VNN+008 0028:VNM+00E 0028:VNM+010 0028: VNM+014 0028:VNM+016 0028:VNN+018 0028: VNM+O1E 0028: VNM+021 0028: VMM+027 0028: VNM+028 0028: VNM+020 0028:COFCELBC
CLD PUSHAD MOV SUB SHR MOV MOV MOV MOV MOV XCHG MOV ST PUSH JMP CALL
sii in VMM generic INT handler —-EAX, LESP+20] —-EAX,VMN+2079 -EAX,03 -EBP, ESP BX, 0030 DS, BX —ES,BX EDI, LVNM+F670) ESP, [ED+48] EBX, [VMM+F6E4]
iti return address (2649h) ©: s; sub base of INT handlers sii (addr-base)/8 = intno (1Ah) make Client Register Struct iii get VMM data seg
EDI = current thread handle switch to thread's stack EBX current YM handle re-enable interrupts YNN#+2E0 push return address (see below) MM+0228+4*EAX} ;: go to V86 INT 1Ah hook chain VTO#1CO sri V86 int hook chain
VxDs install themselves on the V86 int hook chainbycalling, naturally enough, Hook_V86_Int_Chain. During Windowsinitialization, the Virtual Timer Device (VID)calls Hook_V86_Int_Chain with EAX=1Ah
and ESI=VTD+1CO0h. So now that VMMhasreceived a V86-mode INT
1Ah,it’s goingtocall the routine at VTD+1C0h:
0028:VMN+020 0028:COFCEIBC
IMP CALL
TVMM+D228+4*EAX] 3 ; go to V86 INT 1Ah hook chain VTD+1C0 +33 V86 int hook chain
‘Thus, an INT 1Ah function0 call, from deep inside DOS’s CLOCK$
device driver, ends up at the Windows Virtual Timer Device’s 32-bit pro-
tected-modehandler for INT 1Ah: 0028:VTD+1C@ 0028: VTD+IC4
CMP JB
BYTE PTR CEBP.Client_AH],10 VTO+1C8. zai INT 1Ah func < 10h?
0028. 0028: VTD+ICE
JA JB
VTD+1F8. VTD+1E2
0028: VTD+1CB
«CMP
0028: VTD+E2 0028: VTD+IE7 0028: VTD+IEB 0028:VTOFIEE 0028: VTD+IF2 e28:VTDHIF6
MOV MOV SHR MOV MOV CLC
0028: VTD+1F7
RET
«BYTE PTR CEBP.C1ient_AH],01 t a3
INT 1Ah func > 1? INT 1Ah func = 200hrefer to a separate IFSMgr file table. This can be seenin the following fragmentfrom a SoftICE/Windowstrace through an INT 21h function 3Fh read on an extendedfile handle: IFSMgr2+7A60 MOV EST, CEBP+0C] ry fhandle IFSMgr2+7A63 CMP ESI,00000200 3: a normal file handle? TFSMgr2+7469 MOV ECX, CEBP+08] IFSMgr2+7A6C JL _IFSMar2+7A80 (NO JUMP) ss1 From here on, IFSMgr dealing with fhandle >= 200h IFSMgr2+7AGE MOV CECX+06],SI is fhandle IFSMgr2+661 IFSMgr2+665 TFSMgr2+66A IFSMgr2+66C IFSMgr2+66E IFSMgr2+671 IFSMgr2+678 IFSMgr2+67A IFSMgr2+67C IFSMgr2+67E TFSMgr2+681
MOVZX SUB JB MOV SHR MOV OR JZ XOR LEA MOV
EAX,WORD PTR [EDX+06] fhandle EAX, 00000200 minus 2000 IFSMgr2+6AE (NO JUMP) EBX, EAX EBX, 08 i: find which table it's in EBX, [IFSMgr+3818+4*EBX)] ;; table of tables EBX, EBX TFSMgr2+6AE (NO. JUMP) AH, AH EBX, [EBX+8*EAX] ti each entry 8 bytes EAX, [EBX]
This test for 200his frighteningly easy to break. Geoff Chappell examined this in WEW 3.11, where IFSMGRassumes thatall handles >= 200h must have beencreated through ServerDOSCall. Chappell wrote a short test program (shown in Listing 14-6) that uses Dup (DOSfunction 45h) to create more than 200hfile handles, This program is contrived, perhaps, butit’s legal and uses only documented DOSfunctionality. The
Chapter 14: Mixing 32-Bit and 16-Bit Code
program works fine in DOS, but under 32BFA (WW 3.11 or Chicago) it outputs the message“Invalid handle error while readingfile with handle >= 0200h.” (Unfortunately, this program toofailed to make its way onto the Unauthorized Windows 95 disk in time.) Listing 14-6: FILETEST.ASM comment $ FILETEST.ASM Geoff Chappell ([email protected]) 8 March 1994 Assemble, link and use EXEHOR to set maxalloc to the minimum ML FILETEST.ASM LINK. FILETEST: EXEHDR /MAX:0 FILETEST. EXE 5
MODEL STACK DATA config buffer no_problem
SMALL, FARSTACK a100h db db db
something_wrong
db
something_very_wrong
db
"c:\config. sys” 2 0h, OAh, "Just to confirm everything worked OK", @bh, OAn, *$* Dh, OAn, “This shouldn't happen. Something's gone ", wrong with the test rig.", ODh, Ah, “$* 0h, OAn "Invalid handle error while reading file *, ‘with handle >= @200h.", 00h, @Ah, "S*
cone STARTUP
Use DOS function 67h to increase this program's file handle count to more than 0200h bx, 0400h mov mov ah, 67h int 21h je no_increase
Open a file. CONFIG.SYS in the root directory of drive C is taken as a convenient hard-wired name dx, OFFSET config mov ax, 3000h mov 21h int no_open Je bx,ax mov Ouplicate the file handle @200h times. This is just so that we can eventually end up with a handle >= 0200h cx, 0200h mov
Unauthorized Windows 95
ea:
moy int Jc Try reading, but using the open a new file and read cmp jbe
no_increase: no_open: no_dup not_enough
invalid_handle
ok: done EXIT
ah, 45h 2th no_dup last handle. The test could be varied to just as long as the handle >= 0200h ax, 0200h not_enough
me mov
bx,ax dx, OFFSET buffer cx,0001h ah 3Fh 2in ok
cmp iz
ax, 0006h invalid_handle
mov mov int mp
dx, OFFSET something_wrong ah, 09h 2h done
mov mov int imp
dx, OFFSET something_very_wrong ah, 09h 2th done
mov mov int
dx, OFFSET no_problem ah, 09 2th
aoh
END
If you runthis program outside Windows, or under Windows3.1, you'll get the OK message(“Just to confirm everything worked OK”). Butif drive C:is a 32BFA drive, you'll get the following message: Invalid handle error while reading file with handle >= 0200h
‘This error occurs not onlyin the betas of Chicago (which would be entirely understandable), but also in theshipping commercial product, WEW 3.11.
Chapter 14: Mixing 32-Bit and 16-Bit Code
Really Bypassing DOS: Executable Loading and Memory-Mapped Files Apart fromthe use of Win32 file handles, which ensures that DOS is
bypassed forallfile I/O required for loadingan executable file orits resources, Win16 programs and DLLsotherwise appearto loadfairly normally under Windows95. Notso with Win32 executables. Win32 programs and DLLs use the Portable Executable (PE)file format. When Windows95 loads a Win32
executable into a process’s address space,it uses a memory-mappedfile.
Unlikea lot of what we'veseenin otherparts ofthis book, memory-
mappedfiles aren’t just a wrapper arounda layer around seriesof indirections to an INT 21h call. Memory-mappedfilesreallyandtrulybypass DOS.
A memory-mappedfile, as its name suggests,is a file that’s mapped into memory. Okay, so that’s not a particularly helpful explanation.But the essential point about a memory-mappedfile is that you accessthefile using, not read and write andIseekcalls, but instead memorystores and
loads (what a BASIC programmerwouldcall peeks and pokes). To a program, a memory-mapped file looks like an array. Totryto makethis simple but unfamiliar idea more concrete, Listing 14-7 shows a small Win32 Console program, MAPFILE.C. This pro-
grammerely prints out the contents of whateverfile you nameonits commandline. Listing 14-7: MAPFILE.C
mapfile.c
Win32
Ve app
Vibsho io.h> “windows. h void fail(const char *s) { puts(s); exit(L): main(int argc, char *aravC})
}
Unauthorized Windows 95
// Nes, in Win32 you open files with CreateFile(OPENEXISTING). if ((f = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) fail("CreateFile failed"); GetFileSize(f, NULL);
// Get handle to read-only memory-mapped file if ((f2 = CreateFileMapping(f, NULL, PAGE_READONLY, @, size, NULL)) NULL) fail("CreateFileMapping failed"); // Map in entire file, get pointer if ((p = MapViewOfFile(f2, FILE_MAP_READ, 0, 0, 0)) fail("MapViewOfFile failed");
NULL)
// file 1/0 (drive light on, etc.) happens in here! for (i=0, pa=p: i