Unauthorized Windows 95: A Developer's Guide to Exploring the Foundations of Windows "Chicago" 1568841698, 9781568841694

From the Publisher: Only renowned Windows guru Andrew Schulman could deliver the authoritative, in-depth look at Windows

124 19 92MB

English Pages 608 [649] Year 1994

Report DMCA / Copyright

DOWNLOAD PDF FILE

Recommend Papers

Unauthorized Windows 95: A Developer's Guide to Exploring the Foundations of Windows "Chicago"
 1568841698, 9781568841694

  • Commentary
  • OCR version of https://libgen.is/book/index.php?md5=B7AD932A703C5AAF2903F5C601DEC2FF
  • 0 0 0
  • Like this paper and download? You can publish your own PDF file online for free in a few minutes! Sign Up
File loading please wait...
Citation preview

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