917^7 Exp . May "94 Inside Windows NT Security OURNAL Windows NT ■ Turbo Vision Traps and Techniques ■ Paul Bonneau on 'Utonerilmg 32-Bit Code Develop er’SHBre vie w: The Windows ’' for Workgroups SDK^ Accessing the Keyboard from BASIC V 1 f i ? ^ 1 * / Expert Sales Assistant Hr * $ (BjjBt iii | Qfdefs Install Pfoiect Slats Mail Learn Do-It-Yourself □ i % t v ■ Reposts Puige 1 icklei 1 nt = About Piomo Home Center If you could find a way to make computers think more like people, that would be NICE. ' People shouldn't have to think like a com¬ puter to use one. That's why we developed NICE: the graphic user interface that lets you bring real computing power to real people. Working with C/C++ or Visual Basic™, NICE helps you create applications that are easy for people to learn and use. With the User Interface Design Guide, NICE leads you through an easy-to-use checklist to help you design systems that consider how ordinary people interface with comput¬ ers. That understand user apprehensions and abilities. That even realize people don't always think alike. When NICE was put to the test at a high-profile retailer, the results were impressive. Novices reached expert proficiency with only 20 minutes training—a potential savings of 80% in training costs over their current system. And experienced employees moved to the NICE system with no adverse impact on performance. Best of all, you can use NICE with Windows™ 3.1 in a wide range of computing environments. For self- service and ticketing kiosks, medical recordkeeping and insurance claims, package delivery, traditional desktop applications and more. Anywhere you need computer systems that think more like people. After all, wouldn't that be NICE? AT&T © n I C S~ miaia An AT&T Company For a free NICE demo kit, or to order NICE, call 1 -800-243-NICE, FAX 1 800-826-5399. List Price: $295. Special Introductory Price: $199. Windows and Visual Basic are trademarks of Microsoft Corporation. □ Request 167 on Reader Service Card □ C CODE FOR THE PC source code, of course Embedded DOS (full-features, real-time, multitasking, 3.31-compatible DOS for embedded system and self-bootable installations).$375 Updated! Code Base 4 (database manager, dBase and Clipper compatibile indexes & data files; Version 5.0; specify C or C++).$325 ZIP Image Processor & Victor Image Library Version 2.2 (brightness, contrast, merge images, TIFF/GIr/PCX/bin, HP ScanJet support) . . $290 The Snooper (Ethernet protocol analyzer for Novell NetVrare and LAN Manager Networks; capture packets; real-time display).$275 lUrbolfeX (Release 3.0; HP, PS, dot drivers; CM fonts; LaTjgX; MetaFont).$250 Rogue Wave tools.h+-(- or math.h++ Class Library (extensive docs).each $240 C Communications Tbolkit by Magna Carta (Version 2.0; multi-port & co-processor support, FAX, interrupt driven, emulations, xfer protocols) $210 PxSQL (SQL for Borland’s Paradox Engine; ANSI X3.135-1989 SQDDML standard; network server not required).$180 c_pslib (PostScript generation library for C programs; includes complete graphics, font, rotation & paragraph support).$170 Viewpoint (C+ + graphics library; 32-bit color, pattern fill, scroll & bitmap, coordinate tranformations).$170 TE Editor Developers Kit Ver. 3.0 (full screen editor, undo command, multiple windows; with Word Processing $230).$155 Minix Operating System (Version 1.5; Unix-like operating system, includes manual; specify 5.25” or 3.5” diskettes).$150 ViewTHeve (relational view of Novell Btrieve databases; includes EZTrieve).$150 Ddorie GCC for MS-DOS (Version 2.2.2, includes C+ +, assembler, DOS extender, 387 emulation; complete source code and makefiles) . . $150 Booter Tbolkit (floppy disk bootstrap routines, DOS file system, light-weight multitasking, windows, fast memory management) .$120 Updated! Ibrow (Version 4.0; programmer’s Windows-based editor; large files, help, undo/redo, drag-n-drop, function & type tags).$115 Dr. MD (runtime memory analyzer & debugger; find many memory corruption errors; examine memory usage).$110 Updated! 386BSD Version 0.1 & LINUX Version 0.96(two Unix clones for Intel 386) .$100 PC/IP (CMU/MIT TCP/IP for PCs; Crynwr drivers, NFS server, Bdale mailer, PCRoute/PCBridge, NDIS/ODI drivers, Beholder, more) . . . $100 Demacs (complete GNU Emacs for DOS; needs djgcc to build; based on 18.55).$100 Script Interpreter (a command script interpreter for DOS-based systems; C-like script language; lots of features).$90 NETS Version 3.0 (neural net simulator from COSMIC) .$85 Ibrow (programmer’s Windows-based editor; large files, help, undo/redo, drag-n-drop, function & type tags).$115 HorC++ Power (C+ + Class Library for Borland’s Paradox Engine).$80 ET Neural Net (back error propagation; specify DOS or Wtndows).$75 FlexList (doubly-linked lists of arbitrary data with multiple access methods; specify Cor C++).$65 LDB (Loose Data Binder; persistent data objects for C++; handles pointers between objects) .$60 Kier DateLib (all kinds of date manipulation; translation, validation, formatting, & arithmetic).$60 Coder’s Prolog (Version 3.0; inference engine for use with C programs).$60 PCCTS (Purdue Compiler Construction Tool Set; ported to Microsoft Q like YACC and LEX together with lots of additional features) . . . $60 MEM.WING (global memory manager for Wtndows, supports standard C memory allocation calls to ”wing” your old C code into Windows) . $55 BigFloat (arbitrary precision floating point arithmetic and functions; includes BCD conversion).$50 EZCalc (ASCII algebraic expression evaluator, unlimited parenthesis nesting, symbols, 32 built-in functions, easily extended).$50 Backup & Restore Utility by Blake McBride (multiple volumes, file compression & encryption).$50 SuperGrep (exceptionally fast, revolutionary text searching algorithm; also searches sub-directories).$50 NEW! Moby Crypto (encryption/decryption routines; Vol.l; DES, Lucifer, SRNG, ARNG; Vol. 2: PGP, RSA MD4, SHA; both vols. $75) . . . each $50 OBJASM (convert .obi files to .asm files; output is MASM compatible) .$50 CLIPS Version 5.1 (rule-based expert system generator; advanced manuals available at additional cost).$50 NIH Class Library & Book (basic C+ + classes & Data Abstraction and Object-Oriented Programming m C+ + in softback by Keith Gotten) $50 Editor Pack (20 public domain editors; microEmacs 3.11, Stevie, Elvis, Moke, mg2a, DTE, Jove, Origami, CE & GRIEF).$50 MicroC C Compiler (retargetable C compiler/optimizer, lots of docs, very portable, 8086 tables included; tables for 7 extra epu’s $50) .... $50 NEW! PICTOR (Video library; multi-pane windows, menus, hypertext help, serial communications; text editor example; much more).$45 TOUR (beautiful traveling salesman problem solver, finds minimum length paths quickly, includes graphics & plotting programs) .$40 DES Encryption & Decryption (2500 bits/second on 4.77 MHz PC for on-the-fly enctypuon at 2400 baud; domestic distribution only) .... $40 Database Pack (9 databases - simple to complex: isam, bplus, AVL, SDB, ID, gdbm, Requiem, Ingres89, Postgres).$35 COP (poor man’s C++; C macro package which implements C++in C) .$35 RXC & EGREP Version 2.0 (Regular Expression Compiler and Pattern Matching; finite state machine from regular expression).$35 Database Pack (9 databases - simple to complex: isam, bplus, AVL, SDB, ID, gdbm, Requiem, Ingres89, Postgres).$35 Bison & BYACC (YACC workalike parser generators; documentation; includes C and C+ + grammars) .$35 Spell Pack (6 spelling programs, a hyphenator, 2 utility packs and a 60K word list: Ispell, Microsp, Sp, Cspella, Spell, Dawg, Soundex) .... $30 Alloc-GC (a garbage-collecting memory allocation library).$30 REGX Plus (Version 20, search and replace string manipulation routines based on regular expressions).$30 GNU Awk & Diff for PC (both programs in one package).$30 Big Number Pack (7 arbitrary precision arithmetre packages in C, one in Fortran but free Fortran-to-C converter is included) .$30 Crunch Pack (30 file compression & expansion programs; now includes portable ZIP).$30 UUPC Pack (UUCP for the PC; UUPC Version 1.11V, smail & snews) .$25 PERL for MS-DOS (Version 4.019; C, sed, awk, and shell all rolled into one language; includes hardcopy docs).$25 FLEX (fast lexical analyzer generator; new, improved LEX; BSD Version 23.6 with docs).$25 GNU RCS (FSFs version of the Revision Control System; like Unix’s SCCS only better; keeps track of software development).$20 PCAL Personal Calendar (generates PostScript calendar for any month or year, lots of options, personalization file for your dates & schedule) $20 Publisher’s Interchange Language (PIL Tbol Kit, Version 5.0, API 20 by Quark) .$20 NetCDF (Network Common Data Form; general-purpose data exchange for scientific data; many tools and programs available).$20 NE W! Simple Socket Library (Unix, VMS and MS-DOS; sits on TCP/IP stack).$20 Bywater BASIC Version 1.10 (complete BASIC interpreter and interactive programming environment).$20 Data Moby Thesaurus (25K root words, 1.2M synonyms).$350 Moby Part-of-Speech (200,000 words and phrases described by prioritized part(s)-of-speech).$120 Moby Words (500,000 words & phrases, 9,000 stars, 15,000 names).$80 Moby Shakespeare (plays, sonnets, etc. ... every last word).$60 Dictionary Word List (214,932 words in alphabetical order).$60 Roget’s 1911 Thesaurus.$40 U. S. Cities (names & longitude/latitude of 32,000 U.S. cities and 6,000 state boundary points).$35 CIA World Bank II Database (13MB of maps, 5.7M vectors; coastlines, rivers, political boundaries; Africa, Asia, Europe, N. & S. America) $35 The World Digitized (100,000 longitude/latitude of world country boundaries) .$30 Lots ’O Words (160,086 German, 178,430 Dutch, 61,843 Norwegian, 60,453 Italian, 138,257 French, 53,142 English).$30 Tfext Pack (1990 CIA World Fact Book, Hacker’s Jargon File, Acronyma, Koran, Mormon Scriptures, One Liners, Mnemonics, more) .... $25 CD-ROMs FontMaster Libraty (soft fonts for HP and HP compatible laser printers, 36 different type faces; 5,200 bit mapped fonts; 300MB).$70 Prime Time Freeware (over 1 gigabyte of Unix C code).$60 Walnut Creek Libris Britannica (over 600MB of the best of British boards; not all source included).$55 NE W! Linux/GNU/X by Yggdrasil Computing (beta release; run from the CD; TCP/IP & NFS; drivers; MPEG; SCSI support; lots more).$60 Whlnut Creek C Useris Group (Volumes 100 to 364).$40 Whlnut Creek X11R5 and GNU (X11R5 with contributed and comp.sourcesx, over 120 GNU programs, complete C source).$35 W&lnut Creek Usenet and Simtel Unix-C (600MB).$35 Wfclnut Creek Simtel 20 MSDOS Archive (C source code but lots of other stuff too).$20 NE W! Sprite Network Operating System (source code & documentation of Ousterhout’s Sprite O/S; Sun and DECStation boot images).$20 11100 Leafwood Lane much more ... ask for catalog FAX: (512) 258-1342 Austin, Texas 78750-3587 USA E-mail: info@acw.com Free surface shipping for cash in advance For delivery in Texas add 7% MasterCard/VISA □ Request 332 on Reader Service Card □ Windows/DOS □ DEVELOPER'S JOURNAL April 1993 Vol. 4, No. 4 Cover illustration by spray-paint artist Maurice Perez. Copyright © 1993 Maurice Perez. Windows NT Inside Windows NT Security: Part 1.6 Learn the concepts involved in Windows NT’s object-based security system. Rob Reichel Escape from POSIX. .20 Find out how to live with the current limitations of Windows NT's POSIX support. John Richardson Turbo Vision Traps and Techniques . . 49 A look at problems and gotchas you may encounter when using Turbo Vision. Vincent Van Den Berghe BASIC Keystrokes. . 64 A little assembly language lets your BASIC program master the PC keyboard. Murray L. Lesser Developer’s Preview ___ The Windows for Workgroups SDK: A Net Gain for Developers . 33 A programmer’s view of this new Windows networking option. Victor R. Volkman Columns _ Windows Questions and Answers Paul Bonneau .... . 69 Keyboard control of comboboxes; DDE global memory handles; generating 32-bit code with MSCv7. Tech Tips LeorZolman . . 81 Avoiding VB stack space errors; increasing the Windows open file limit; output redirection in C. Departments _ From the Editor.4 Call for Papers.26 Source Code Availability.74 New Products.76 Readers’ Forum. 80 Developer’s Marketplace. 83 Advertiser Index. 88 Next Month . Windows NT Virtual Device Drivers WINDOWS/DOS DEVELOPER’S JOURNAL (ISSN 1059-2407) is published monthly by R&D Publications, Inc., 1601 W. 23rd St., Suite 200, Lawrence, KS 66046-2743, (913) 841-1631. Second- class postage paid at Lawrence, KS and additional mailing offices. POSTMASTER: Send address changes to WINDOWS/DOS DEVELOPER’S JOURNAL, 1601 W. 23rd St., Suite 200, Lawrence, KS 66046-2743. Subscriptions: Annual renewable subscriptions to WINDOWS/DOS DEVELOPER’S JOURNAL are $29 US, $53 Canada and Mexico, $64 overseas. Payments must be made in US dollars. Make checks payable to Windows/DOS Developer’s Journal. GST (Canada): #129065819 Page 2 - Windows/DOS Developer’s Journal April 1993 *•••• Save time And Money Add Sophistication and Flexibility to Your Windows Application ui'M a J : Prolessiotial toolbox For WIMm For Visual Basic "Featuring thelndustri only true With 23 custom controls - including the industry's only full-featured Spreadsheet control - and more than 300 functions, Professional ToolBox is the most complete, flexible and powerful Windows development package on the market. Visual Architect™ is a product that no Visual Basic developer should do without. Designed to accelerate your development schedule, Visual Architect™ can handle any application you're developing. The Spreadsheet control of TooiBox is unparalleled by any other package in its features, flexibility and power. New features include: • Full sorting support • Addition of a checkbox celltype and owner draw celltype • Place borders around a cell, row, column, or range of cells • Virtualized database support • Selection of multiple blocks • Overflow text to next column • Single-select, multi-select feature • Place multi-line edit within a cell • Change color of grid • Drag and drop • Plus, full clipboard support Other custom controls are Formatted Edit Controls, Tool Bar and Status Bar, 3D effects, View Pictures with animation, and Enhanced Listbox. Functions include DOS System functions, Date/Time support, String functions, and Enhanced File support. Professional ToolBox supports MSC 7.0, Borland C++, Borland C++ Owl, Turbo Pascal, Actor, WindowsMaker Pro, Borland Resource Workshop, GFA, Microsoft C++ and Dialog Editor. Price $345 (no royalties) The "true" Spreadsheet control, makes Visual Architect™ stand out from any other software package. A major design goal was to make the spreadsheet extremely flexible and powerful. It can be used within your application as a functional spreadsheet - as a simple way of obtaining variable lines of data from the user - or as an easy way of displaying tables of information from a database. Because of its extreme flexibility, the spreadsheet can be customized for each individual user. It can be optionally locked so the user can't make changes. The width and height of columns and rows may be changed. The font, color, and data type may be changed for any row, column or cell. Cells can have the following data types: edit, date, time, integer, float, static, formatted pic, combobox, button, and picture. Formulas can be added to any cell. Full-print support is built-in. Other features of Visual Architect™ include the Formatted PIC, Integer, Floating Point, Date with Calendar, Time and View Text, The Visual Architect™ manual is professionally written and contains extensive documentation. Visual Architect™ Winner of Reader’s Choice Award Development Tools Backed by Professionals "FarPoint's Visual Architect™ spreadsheet is a proven and robust tool that can easily meet the changes of mission critical real world applications. FarPoint's design and documentation made it easy to master and embed the spreadsheet in our systems. Being Vertical Application Integrators, we demand versatility from all of our tools, and FarPoint's Visual Architect™ exceeded our expectations." GregMelnick Vice President Tripled Software Triple-I has been providing consulting and technical service solutions to Fortune 500 companies for 21 years. FarPoint Technologies offers To order or receive additional FarPoint Technologies, Agency: MF Schwab & Associi Windows/DOS □ DEVELOPER'S JOURNAL Advanced. Serious. Technical. EDITORIAL Senior Editor/Publisher Robert Ward Editor Ron Burk Managing Editor Martha Masinton Contributing Editors Paul Bonneau Victor R. Volkman Leor Zolman ADVERTISING AND MARKETING Jeff Dickey-Chasins Ed Day (913) 841-1622 Donna Stucky Ward (913) 841-6733 Edwin Rothrock (913) 841-1626 Brian Osborn Hohenleuchte 10 a 2300 Kiel 17 Germany +49 431-396895 FAX: +49 431-396827 Sales Services Danelia Quiroz Advertising Services Noelle M. Martin Direct Marketing Bill Uhler PRODUCTION Art Director Susan Schuette Buchanan Graphic Artist Twyla Watson Bogaard Production Editor Ann Brocker CIRCULATION Customer Service Pam VanSchmus Order Fulfillment Jodi Leonard Subscriptions: Annual renewable subscriptions to Windows/DOS Developer’s Journal are $29 US, $53 Canada and Mexico, $64 overseas. Payments must be made in US dollars. Make checks payable to Win¬ dows/DOS Developer’s Journal. Entire contents Copyright © 1993 R&D Publica¬ tions, Inc., except where otherwise noted. No portion of this publication may be reproduced, stored, or transmitted in any form, including computer retrieval, without written permission from the publisher. All Rights Reserved. Printed in the United States of America. Quantity reprints of selected articles may be ordered. By-lined articles express the opinion of the author and are not necessarily the opinion of the pub¬ lisher. Advertising: For rate cards or other information on placing advertising in Windows/DOS Developer’s Journal, contact the advertising department at (913) 841-1631, or write Windows/DOS Developer’s Journal, 1601 W. 23rd St., Suite 200, Lawrence, KS 66046-2743. Customer Service: For subscription orders and address changes, contact Windows/DOS Developer’s Journal, 1601 W. 23rd St., Suite 200, Lawrence, KS 66046-2743. Telephone (913) 841-1631; FAX (913) 841-2624. Trademarks: Windows/DOS Developer’s Jour¬ nal, R&D Publications, Inc. UNIX, AT&T Bell Laboratories. XENIX, MS-DOS, OS/2, Microsoft C and QuickC, Windows, CodeView, Microsoft. IBM, IBM-PC, International Business Machines Corp. Turbo C, Turbo Pascal, Turbo Debugger, Borland In¬ ternational. Macintosh, Apple Computer, Inc. Zortech C++, Zortech. Windows 3.0, Microsoft Corporation. dBASE, Ashton-Tate (Borland). Marketing Director Acct. Manager, East Acct. Manager, Midwest Acct. Manager, West European Advertising Representative From the Editor The theme this month is Windows NT and we’re happy to present information that you won’t find anywhere else. I highly recommend reading Rob Reichel’s article on NT security, even if you aren’t using NT yet. Unlike most of the Win32 API, NT security is not going to look too familiar to most Windows programmers, and the conceptual descriptions in Rob’s article will help you make sense of the cryptic security information in the Win32 API specification. Another sparsely documented area of NT is the POSIX subsystem. At the moment, Microsoft’s POSIX support seems to be aimed more at helping NT win government contracts than at making it easy to port Unix applications to NT. John Richardson's article in this issue can help you work around one of the fairly severe limitations of the current NT POSIX subsystem. Just because this month’s theme is Windows NT, don't think that you won’t see another NT article until next year. We’ve been covering Windows NT since our July 1992 issue and we have lots more good articles in store. Next month’s theme is device drivers, and Paula Tomlinson has written a very good piece on using Win¬ dows NT virtual device drivers to support 16-bit hardware-dependent applications. We’ll continue to have some kind of NT article every other month or so - let us know if you want to see more or less. If you read my column last month, you may have concluded that Paul Bonneau’s amazing hack for dual-font edit controls really was too slimy for even us to print. April fool I We just didn’t have room this month so it will appear next month. Some folks simply could not wait, however, so I went ahead and uploaded the code to CompuServe (file symedt.zip in Library 7 of CLMFORUM). As I said when I posted it, this code patches Windows on the fly, so don't try this at home. I very much enjoyed the chance to shake hands with some of you at Software Development '93. Several readers had good suggestions for improving the magazine that we are still talking and thinking about. We are fortunate to have such a large pool of talented readers to draw on for ideas and (as this issue shows) excellent technical articles. Thanks for all your support. Ron Burk Editor CIS: 70302,2566-, BIX: rlburlc, Internet: ronb@rdpub.com ("... !uunet!rdpub!ronb”) Page 4 - Windows/DOS Developer’s Journal April 1993 XVT’s Portability Toolkit™ is a powerful C development environment that allows you to build a single application, then re-compile to every major GUI without rewriting code. XVT solutions also include an interactive design tool and a class library for C++ developers. •Supports Macintosh, Microsoft Windows, Windows NT, OS/2 Presentation Manager, OPEN LOOK, OSF/Motif, and Character Systems •Native look-and-feel to all target GUIs •Portability to 26 hardware systems •Access to the complete functionality of every windowing system •Easier to use than native development toolkits • Minimal size and performance overhead • Shorter development cycles •No royalties or runtime fees •Clear documentation and responsive technical support Now in its third generation, XVT is recognized as the industry leader in portable GUI development solutions and is the base document for the emerging IEEE standard. It is used by world-class software developers like • Novell •HP ‘AT&T • Digital • Lockheed ‘Kodak •Grammatik/Reference Software, because it allows them to take their applications to the widest market, quickly and cost effectively. Don’t write another line of code without gearing up to develop your application simultaneously for all GUIs. Call for technical materials and a demo. SOFTWARE INC The portable GUI development solution. 1 - 800 - 678-7988 XVT Software Inc. 4900 Pearl East Cir. Boulder, CO 80301 (303) 443-4223 FAX (303) 443-0969 For European inquiries, contact: PVI Precision Software GmbH ▲ Microsoft Windows & Windows NT ▲ OSF/Motif Shown above are four of the seven GUIs supported by XVT. A Macintosh Phone: 49 0 61 03/37 94 0 Fax: 49 0 6103/36 95 5 □ Request 112 on Reader Service Card □ Inside Windows NT Security Part 1 Rob Reichel One of the design goals for Microsoft's Windows NT operating system is that it meet the requirements for government C2 security certification. C2-level security requires the operating system to supply “discretionary access control” (or DAC) mechanisms that allow it to protect objects (such as files) from unauthorized use. Discretionary access control means that the creator of an object has the ability to permit anyone to access the object in any way. You can contrast this with such stronger forms of security as “mandatory access control," which enforces access rules that even the creator of an object may not override (for example, preventing you from copying a file marked “Top Secret” to a directory owned by someone with only “Secret" clearance). Even if you are not planning to write a security-intensive application (such as a database server or a file manager), understanding Windows NT security makes the behavior and proper administration of the system easier to understand, which in turn leads to making systems more secure. Anyone administering a system or writ¬ ing applications for a system containing sensitive information must have an in-depth understanding of how the various pieces fit together —otherwise, they will eventual¬ ly make mistakes that compromise their data. Think of it this way: the person trying to break into your system will have read every line of documentation and will have figured out all of the holes that you might have left open. The best defense against such an attack is to understand the system thoroughly enough to ensure that there are no holes to exploit. In Part 1 of this article, I describe Windows NT security and the discretionary access control mechanisms it provides. Next month, in Part 2,1 will illustrate some of these concepts with a small program that allows an administrator to override the normal security on a file. What Is Security? The goal of a security system such as Windows NT’s is to ensure that the wrong people don't do the wrong things on the computer or on the network, either unin¬ tentionally or maliciously. When a user attempts to access a file, for example, the system must evaluate two pieces of information to determine if that user may access that file: who the user is, and who is allowed to access the file. While this may seem obvious, the mechanisms that Windows NT uses to repre¬ sent who you are and who may access that file are very flexible and complex. This flexibility allows organizations to tailor their use of the security system very closely to their needs, but it puts an extra burden of understanding on application developers who plan to take advantage of it. Rob Reichel graduated from Princeton University in 1985 with a BSE/EECS, and has been working on operating systems for Microsoft ever since. He is currently working on the Windows NT security system. Rob lives in Redmond, Washington, with his wife Jackie and the cats, Moxie and Fang. You can contact him on CompuServe at 72360,3504 (72360.3504@compuserve.com from the Internet). Page 6 - Windows/DOS Developer’s Journal April 1993 Windows NT Although the details of Windows NT security are complex, the big picture is fairly simple. The main items of interest are users and objects. A user is a person or process that logs on to the system and an object is something that a user can access (for example, a file). Whenever a user wants to access an object, Windows NT security comes into play. As Figure 1 shows, Windows NT maintains security infor¬ mation for both users and objects. The answer to whether or not the security sys¬ tem will grant a user access to an object depends upon the detailed security infor¬ mation associated with both the user and the object Most of the remainder of this article explores the details of user information and object information and the algo¬ rithms by which Windows NT security uses this information to decide whether or not to grant a particular access request. User Information Overview In order to understand who you are when you are logged on to the system, Windows NT maintains a database (called the Security Account Manager, or SAM) of all the users who have accounts in each network domain. When you log on to a Windows NT system (either directly or via the network), the logon process validates your logon name and password, and if they are correct, retrieves everything that it knows about you from the database. At this point, you are what is known as a subject. A subject may either be sitting at the keyboard or accessing the machine over the network. The ability to allow multiple subjects to access a machine simul¬ taneously is the basis of Windows NT's claim to be a multi-user operating system. Despite the fact that only one user may have a Windows desktop at a time, any number of users may connect to the machine and be represented as themselves in order to access objects in the system. Each Windows NT process is associated with a subject. Windows NT itself is a special subject that is always present. This allows the parts of the operating system that run in user (or non-supervisor) mode to have a context to use when accessing objects, which means that Windows NT is subject to restrictions from its own security system. When a subject (you, for example) logs on, the first thing the system retrieves from the database is your security identifier, or SID. The SID is the Windows NT equivalent of your name, and provides just about as much information about you (that is, not much). The purpose of the SID is to identify you uniquely across all of the machines on your network in a format that is easy for the operating system to manipulate. But there is more to who you are on the computer than your SID, just as there is more to who you are in real life than your name. Windows NT supports combining users into groups, which also have names (like "Administrators” or “Power Users”) and SIDs. Groups allow a single group SID to represent an arbitrarily large number of group members, and thus are very useful. For example, if I specify that all members of the group “My Friends” can read a certain file, then I can simply maintain the membership of that group to grant access to the file. Every Windows NT user is in one or more groups, and the security system retrieves these group memberships when you log on. Finally, in addition to your SID and your groups, the logon process retrieves your privileges. Privileges are difficult to understand without the knowledge of the details of the security system, because they permit extensions and allow special overrides to the normal security mechanisms. Privileges may be granted either to an individual or to a group, and every user gets the sum total of his or her individual privileges, plus those granted to all of his or her groups. I discuss privileges only briefly in this article. April 1993 r i L J Windows/DOS Developer’s Journal — Page 7 Figure 1 Access Tokens and Security Descriptors User Information User SID Object Information Group SIDs Flags Owner Group — Privileges -— fRinhts} SACL DACL Access Token Security Descriptor Windows NT gathers all of this information (SID, groups, and privileges) together into a structure called an access token. This structure is not directly addressable by applications, but you can manipulate it in certain ways through system calls (for example, you can enable and disable privileges). It is this access token that truly represents “who you are” to the operating system. Every Windows NT process has an associated access token, if the user has logged on interactively (by sitting down at the keyboard and typing Cntrl-Alt-Del), then this access token is attached to the Program Manager when it is created. Any process created by the Program Manager will inherit a copy of the access token attached to the Program Manager, and any child process of those processes will inherit a copy, and so forth. So even though there are many access tokens in the system representing the user, most of the time they will be identical. This allows you to ignore the details and speak of “the user's token" as if there were only one in the system. The purpose of the access token is twofold: first, to keep all the necessary security information about the user together to speed access validation; and, second, to allow each process to modify its security information in limited ways without af¬ fecting other processes running on behalf of the user. An ex¬ ample of how a process may modify information in its access token would be to enable a privilege before performing a privileged operation. It would obviously be bad if all of the security information for the user were kept in one system- wide place, such that enabling a privilege for one process enabled it for all of them. Object Information Overview Knowing who you are is only half of the information the system needs to know what you can do. The other half is attached to each system object that you might want to ac¬ cess and is contained in a structure called a security descrip¬ tor. The security descriptor contains data structures that describe very precisely who (by SID) can do what to the ob¬ ject By examining the security descriptor and comparing what is in it to what is in your access token, the system can decide whether or not you are allowed to access the object in the way you want As Figure 1 shows, the security descriptor is a collection of security information about an object, just as the access token is a collection of security information about a user. I discuss these fields in more detail later, but here is brief overview of the key fields: • owner — the security ID (SID) of the owner of the object. The owner of an object can perform almost any action on that object. • group —a field that exists mainly to support Windows NT's POSIX subsystem; as a Win32 programmer, you can always ignore it. • SACL — the System Access Control List. This specifies what kinds of operations on the object should generate audit messages. • DACL — the Discretionary Access Control List. This is the main field you will be concerned with, since it grants and denies access to individual users and groups. What Are NT Objects? Most PC programmers only run into security in the context of files on a network. Under Windows NT, security is not a special concept just for files. Instead, Windows NT security ap¬ plies uniformly to several different operating system resour¬ ces, each of which Windows NT treats internally as an object. To understand the security system, then, you need to under¬ stand how Windows NT uses objects. Every entity that Windows NT creates is an object. Files are objects, as are threads, semaphores, timers, windows, and so on. Windows NT creates all of its objects in a uniform way through a body of code in the kernel called the object manager. The object manager is responsible for creating, open¬ ing, and destoying objects on behalf of applications. You can divide Windows NT objects into two groups: named and unnamed. When you create an unnamed object, you get a handle to that object, and the handle is the only way to refer to it. Named objects, on the other hand, are useful because they have a name that other processes can use to obtain a handle to the object. For example, if Process A wished to synchronize itself with Process B, it might create a named event object and pass the name of the event to Process B. Process B would then open and use that event ob¬ ject. However, if Process A simply wished to use the event to synchronize two threads within itself, it would probably choose to create an unnamed event object, since there is no need for any other process to be able to use that particular event. Any type of object other than a file may be either named or unnamed. It is up to the application to decide what best meets its needs. However, there is one important difference between named and unnamed objects in NT: all named ob¬ jects always have security information associated with them. The security information may not restrict any access to the object, but the system will always maintain internal data structures describing the security attributes of the object. Page 8 — Windows/DOS Developer’s Journal April 1993 The reason named objects have security information is the same reason that makes them useful: they may be accessed by any process by name. If Process A creates an unnamed semaphore, there is no way for Process B to ask for access to that particular semaphore. Thus, there is no need to protect it. However, Process A may create a named semaphore with the intent that only processes it knows about should be able to open and use that semaphore. To guarantee that the semaphore is not improperly used by an unauthorized process, Process A must place security information on the semaphore when creating it. Windows NT uses objects internally, but the interface that you use (the Win32 API) is a procedural one — you always manipulate Windows NT objects indirectly, by passing their handles to Win32 API functions, when your application attempts to open an object, it must pass in a bitmask describing the desired access (such as “read” or "write") to the object. If all of the desired accesses to the object are granted, the Win32 function returns a handle to the object The desired access mask you pass when opening the ob¬ ject is retained by the system and stored internally with the handle in the process's handle table. A handle may only be used in ways permitted by its desired access mask. Attempting to use the handle for any other purpose will result in an “Access Denied" error code. Planning an Access Request The fact that all handles are not created equal (since they may have dif¬ ferent access masks) is a source of con¬ fusion to many programmers who have never before written applications for a secure system. It means that your ap¬ plication has to know in advance exact¬ ly what it intends to do with a par¬ ticular object handle, and make sure it gets the access it needs up front. It also means that even though the user may have some access to the underlying ob¬ ject, if that access is not reflected in the corresponding object handle, the at¬ tempt to use that access will fail. For example, suppose user “Barts" wishes to access a word processing file that he has read and write access to. His word processor has the option to open the file for read access, write ac¬ cess, or both (it is an error to attempt to open an object for no access). If the word processor opens the file for read access only and then attempts to use that handle for writing the file, the write operation will fail even though "BartS” has write permission to the file. The word processor must know when it opens the file that it may have to read and write the file, and must request both accesses. Suppose your application does not know all of the opera¬ tions that it is going to be asked to perform on an object. You have three choices of what to do in that case: First, you could attempt to open the object for all possible accesses. This is generally a bad thing to do, because each access requested is another access that may be denied (remember that all of the accesses in the desired access mask must be granted to receive a handle to the object). This can result in unfortunate situations where the application will not let a user operate on an object in any way, even though the user has all of the access rights needed for the task at hand. Another disadvantage of asking for more access than necessary WOW! Now With OBJ, Windows, Windows VXD, OS/2, and OS/2 LX Driver Support! No Source? No Problem. W ith Dis»Doc Professional™, the most powerful disassembler available, you will be able to convert your DOS programs into de¬ tailed assembler code to recreate lost DOS program listings or find vi¬ ruses. Dis* Doc Professional was designed to be fast and easy for the first time user with an interactive mode and on-line help, but has all the power a seasoned vet needs. Interactive searching and nested calls helps you find viruses quickly and our built-in pacther makes killing them even quicker. Dis* Doc Professional con¬ tinues to be the industry leader in new features, especially in listing detail and new programs supported. PC MAGAZINE Even PC Magazine has changed its mind about "the best disassembler [theyj've ever seen" in their July 1992 issue (but then again a lot has changed since their last disassembler review in 4/26/1988. Ronald Reagan was still president for gosh sakes...) We are so confident that you will love our product, a working demo of Dis* Doc is availible free on our bulletin board (203-953-6196) along with other information. COMPARE FOR YOURSELF! Die-Doc'- V4.006 Brand X vx AUTOMATIC DISASSEMBLY Speed of disassembly (bytes/sec) 822 120 Accuracy %* 99.9 99.9 Pre-defined comment size(avg)" 60 60 Unlimited file size YES NO LISTING Interactive mode YES NO Time to customize a label 5 sec 5 min Time to change data to code 5 sec 5 min Interactive Cross Referencing YES NO Custom Label Size(max) 32 32 Custom Comment Size(interactive) 320 0 Japanese character support YES j YES MASM & TASM output YES 1 YES OPTIONS EXE Unpacker/COM2EXE YES YES OBJ Disassembly YES NO Patcher YES NO Basic Price 99. 129.95 Complete Price’” 249.95 309.80 ■ Code analysis, segment placement multiple segments, seg's and offset's S ” Interrupt Including Ml reg use, port. Wndow, OS/2, VXD, and LX services. B — Disassembler. BIOS labelng, EXE unpecker. WndowsA OS/2 support | SPECIAL OFFER For a limited time the interactive core of Dis* Doc is availible for just $99, packing all the power of Dis* Doc Professional but without OBJ, Window, OS/2 or packed EXE support. To order the Dis • Doc™ Disassembler call: 1-800-336-1961 1-203-489-5335 voice 1-203-489-5746 fax 1-203-953-6196 bbs (up to 9600 baud 8N1) or send check or money order for $249.95 (or $99 for Dis • Doc's interactive core) plus $6 s&h to: RJSwantek, Inc. • 33 Spencer Brook Road • New Hartford, CT 06057 USA MasterCard & Visa • Shipped Immediately Via UPS Blue inside USA. □ Request 108 on Reader Service Card □ April 1993 Windows/DOS Developer’s Journal - Page 9 Patrick Pearce, Software Developer, Life Care Development Corp. 44 rp* • •>•> 1 ime is money. The advantages of OS/2® are clear. “At Life Care Development Corp., we create applications for sale to physicians, psychiatrists and drug counselors for tracking patient and insurance information, and medicine and treatment goals. We make use of OS/2 s inherent development capabilities like the REXX language as well as WorkFrame/2 (IBM’s development environment), C Set/2 compiler and Borland ObjectVision? For us, OS/2 has meant heightened productivity, shortened development time and improved quality of product." Work in a customizable object-oriented environment without constraints. Enjoy true pre¬ emptive multitasking, unlike what you get with Windows™ and other DOS extenders. “With OS/2,1 can reliably run several development applications at the same time: ObjectVision edit in one window, compile in another, link in a third and test in a fourth. I’m amazed how quickly I can compile a program while print¬ ing a copy of the source code.” OS/2 gives you the capability to have mul¬ tiple configurable sessions in which to build and test your applications. 'OS/2 is easier to get into.” OS/2 Crash Protection™ helps you lose your fear of crashing and rebooting. If one app goes down due to a bug, the rest you’re working on won’t. OS/2 isolates the failure, letting you fix it and restart it with¬ out affecting other apps. Dynamic Link Libraries allow applications to share common functions, making them smaller and easier to maintain. I’ll never go back.” “I may be a small ISV, hut IBM has always treated me like a big fish." IBM’s valuable technical service and marketing support includes OS/2 Sup¬ port Line, IBMLink, the IBM OS/2 bulletin board system and several OS/2 developer forums on 19 9 2 -WINNER- PC Magazine Award for Techni cal E xcellence @1 OPERATING SYSTEMS AND SOFTWARE STANDARDS OS/2 , Version 2.0 IBM Corporation In the Workplace Shell™ you can edit source code files while compiling and debugging in the background. The no-comparison comparison chart. Windows 3.1 OS/2 Virtual memory limit 4 x physical 512MB (disk space) Memory model Segmented (64KB) Flat memory objects APIs 16 bit Full 32 bit Multitasking—DOS apps Time slicing Pre-emptive time slicing Multitasking—Windows/PM apps Cooperative Pre-emptive Priority Static (set by user) Dynamic Dispatchability Process Thread System services Serial Parallel Protectiombetween apps Unprotected Protected Kernal protection— DOS/Win/PM apps Unprotected Protected File system FAT Enhanced FAT and installable file systems (HPFS, CD-ROM) User interface Windowed Object oriented IBM and OS/2 are registered trademarks and Workplace Shell and OS/2 Crash Protection are trademarks of International Business Machines Corporation. All other products are trademarks or registered trademarks of their respective companies. ©1993 IBM Corp. CompuServe? “If I run into a problem, the OS/2 Developer Assistance Program is there to help.” The 32-bit operating system lets you break through the 64K code segment barrier and convert to a Hat memory model with up to 512MB of mem¬ ory per session for writing code. “Writing is easier and faster than ever—and bugs have never been easier to uncover and zap. u I’m actually having fun again.” But the best reason for leaving Windows and other DOS extenders is the opportunity to develop truly revolutionary OS/2 applications. You could say OS/2 has closed the door on Windows. For the free white paper on why OS/2 is the developers platform of choice, or for more information, call 1 407 982-6408. = ==T = 7 E= is that it prevents the system from helping you debug your application. Having a handle that may only be used in limited ways is a great debugging aid, because the system will detect errant uses of the handle. It is like extending virtual memory protection to files and other objects, and can be very useful. Figure 2 Security Descriptor Structure typedef struct _SECURITY_DESCRIPTOR { UCHAR Revision; UCHAR Sbzl; SECURITY_DESCRIPTOR_CONTROL Control; PSID Owner; PSID Group; PACL Sacl; PACL Dacl; } SECURITY_DESCRIPTOR, *PISECURITYDESCRIPTOR; Figure 3 Access Control List Layout ACL Header ACE Header Access Mask SID ACE Header Access Mask SID Free Space Figure 4 Access Control Entry Structure typedef struct _ACCESS_ALLOWED_ACE | ACE_HEADER Header; ACCESS_MASK Mask; ULONG SidStart; ) ACCESS_ALLOWED_ACE; typedef ACCESS_ALLOWED_ACE *PACCESS_ALLOWED_ACE; typedef struct _ACCESS_DENIED_ACE | ACE_HEADER Header; - ACCESS_MASK Mask; ULONG SidStart; ) ACCESS_DENIED_ACE; typedef ACCESS_DENIED_ACE *PACCESS_DENIED_ACE; Second, your application could open a new handle to the object each time it attempts to perform a different kind of operation on the object. This is the preferred method, since it will not deny or allow more access than necessary. However, it has the overhead of opening and closing several handles. Finally, you could attempt to open the object for as much access as the system will permit. I describe the best way to do this later in this article, via the MAXIMUM_A LLOWED access type. The advantage of this method is that the user will not be artificially denied any access to the object, but the disad¬ vantage is the same as mentioned above: the handle may have more access than it needs, which may help mask bugs. It is rare for an application not to be able to determine reasonably well what access it is going to need to an object, so you should not find yourself having to evaluate the pros and cons of the above strategies very often. SIDs in Detail As I mentioned earlier, the first piece of security informa¬ tion the system retrieves about you when you log on is your security identifier (SID). Each user and group in Windows NT is assigned an SID that the system uses to differentiate one user from another, much as the IRS uses Social Security and tax¬ payer ID numbers to differentiate taxpaying entities. This gives Windows NT a uniform way to manipulate security informa¬ tion for individual users and groups. An SID consists of a series of integers representing an “authenticating authority" (typically, “Windows NT”), a sub¬ authority (representing the network domain that will be the user's primary domain), and a “relative ID," representing a par¬ ticular group or user in that domain. For example, a typical SID might look like: S-1-5-462442-37204 where “S-1-5” means that the SID was created by a Windows NT system, “462442” represents a network domain in the or¬ ganization, and “37204" is the unique ID of an individual employee whose account is in that domain. A unique SID is created for each user when that user's account is created in a network domain. One important thing to note is that since each user’s primary domain is coded into his or her SID, switching domains forces the creation of a new SID to represent the user, which in turn causes that user to lose access to much of the information he or she had pre¬ viously been able to get to. To understand why this is desirable behavior, take the ex¬ ample of a user, “Megan," who works in the payroll depart¬ ment and has access to company payroll records. For one reason or another, Megan is transferred to some other part of the company, a part that does not normally have access to payroll records (such as the advertising department). Megan no longer needs, and in fart should not have, access to the company payroll records, yet if she kept her old SID, it might be very difficult to make sure that she can no longer access the files she used to work with. The easiest way to ensure this is to “re-create” Megan’s account from scratch and add the ability to access what she needs for her new job. Page 12 - Windows/DOS Developer’s Journal April 1993 This example illustrates that SIDs may be thought of as representing a specific job within the company rather than a specific individual. When an individual changes assignments, the security information associated with the old position should not move with the user to the new job. Privileges As Figure 1 shows, the main piece of user information you have to understand besides SIDs is privileges, which permit extensions and allow special overrides to normal security. Privileges have two states: enabled and disabled. This allows a user to have a privilege and not necessarily be able to use it. Because privileges function as security overrides, the enable/disable capability is a safety feature to prevent their accidental use, like a lock on a pistol trigger. In my experience using Windows NT and privileges, I have found that uninten¬ tional uses of privileges tend to result in damage at best, dis¬ aster at worst, and are thus to be used with care. Administrators grant privileges via the Windows NT User Manager. For example, an administrator may choose to create a group called “Backup Operators” and assign to that group SeBackupPrivilege. Users who have SeBackupPrivilege are allowed to use a backup tool and back up files that they nor¬ mally would not be able to read. Every member of "Backup Operators" would have this privilege while logged on. If there was no need for an entire group of backup operators, the administrator could just choose one or two people and grant them SeBackupPrivilege individually. It is up to the ad¬ ministrator to decide which is the best method. Security Descriptors Looking again at Figure 1, I have described some of the structure and purpose of the user information that the security system maintains. I now turn to the details of the object security information, which is contained in the security descriptor structure. The security descriptor contains control flags and pointers to an owner SID, a group SID, a system Figure 5 The Access Mask Write Owner Write DAC Read Control Access System Security Maximum Allowed Generic All Generic Execute Generic Write Generic Read Special Offer! Buy SlickEdit for DOS-alone or bundled with our SlickEdit for OS/2 or Windows NT-and receive the new full- GUI SlickEdit for Windows 3.1 in May! "SlickEdit is the only editor I use. -Dave Cutler. Director of Windows NT development SlickEdit has all the CUA standards expect in a graphical Windows application- full on-line documentation, unlimited free ? support, and a full 30-day money-back guarantees These are just a few more of its features: • Fully programmable with new C-style macro language • Truly emulates text-mode editors such as Brief and Emacs • Optional one file per window • Multiple clipboard support • Optional CUA marking • We've kept our command line! yo tec MS-DOS OS/2 Windows NT Windows 3.1 386/486 UNIX Sun Sparc IBM AIX RS6000 HP9000, DG Aviion, Silicon Graphics, EP/IX, Dynix $195 each, or any two for only $295! $425 per CPU CALL Edit For more information, call (919) 831-0662 or fax: (919) 831-0101 microEdge, Inc. P.O. Box 18038 Raleigh, NC 27619-8038 USA OS, OS/2, Windows, Windows NT, Sun Sparc, HP-9000, DG On, Silicon Graphics, EP/IX, Dynix, AIX RS6000, Brief, Epsilon, and UNIX are trademarks of their respective manufacturers SlickEdit',"the multi¬ platform editor, gives you freedom of choice! "...overall, the easiest editor to learn and use." □ Request 334 on Reader Service Card □ April 1993 Windows/DOS Developer’s Journal - Page 13 access control list (or SACL), and a dis¬ cretionary access control list (DACL). Security descriptors come in two for¬ mats: absolute and self-relative. Ab¬ solute format means that the pointers to the owner SID, group SID, DACL, and SACL fields are genuine pointers into memory. Self-relative format means that, instead of pointers, these fields contain offsets to the actual data, which has been appended to the end of the structure. The reason for the self-relative for¬ mat is that security descriptors must be stored on disk and transmitted over network connections, and a structure containing pointers is not suitable in either of these cases. If you are familiar with Remote Procedure Call (RPC) con¬ ventions, you will recognize the self¬ relative format as simply a marshalled version of the absolute format descrip¬ tor. When applications create security descriptors, they create them in ab¬ solute format. The Win32 API provides a number of functions to help you con¬ struct security descriptors, and all of them construct absolute format descrip¬ tors. When Windows NT receives an ab¬ solute format security descriptor, it con¬ verts it to self-relative format before storing it. When the application queries the security descriptor of an object, it will always get it in self-relative format. Figure 2 shows a security descriptor structure. The meanings of the fields are as follows: Revision — The Revision field allows Microsoft to revise the security descrip¬ tor structure sometime in the future without breaking existing software. Sbzl —The abbreviation “Sbz" stands for “should be zero." This means that Windows NT does not currently force these fields to be zero, but may at any future time require that they be so. This allows the Windows NT designers to start to use these fields at some time in the future without having to worry about breaking correctly written ap¬ plications. An application that uses these fields for its own purposes is al¬ most guaranteed not to work on some future release of Windows NT. Control — The flags in a security descriptor indicate what is in it. This field contains flags describing whether or not the SACL and DACL are present, whether or not they were placed on the object by a defaulting mechanism, and whether the security descriptor is in self-relative or absolute format. Owner — Every security descriptor contains an owner security ID (SID). If you don't specify an owner when you create the object, Windows NT will ex¬ amine your token and usually assign your user SID as the owner. Anyone may change the owner of an object to any SID that is in the current token. For example, if Joe is a member of groups “Power Users” and “Managers," any process he runs may only change the owner of an object to either his SID or one of the SIDs representing “Power Users" or “Managers". If the owner SID is set to either of the groups, then all of the members of the owning group are owners of the object. Why can't Joe make anyone he wants the owner of the object? Because then he would be able to cover his tracks if he has accessed the file il¬ legitimately. Users may only take ownership of objects, they may never give ownership of an object to other users. The owner can always perform one very important operation on the object: change its Discretionary Access Control List, which grants and denies accesses to the object. In essence, given this control, the owner of an object cannot be prevented from performing almost any action on the object. Group — As I mentioned earlier, the group field is for POSIX compatibility - you can ignore it. Sad -The SACL (System Access Con¬ trol List) field contains a pointer to the system access control list, which con¬ tains auditing and alarm information. This list contains access control entries (ACEs, which I discuss in detail later) that describe what operations should generate audit messages in the audit log. Applications must have a privilege (SeSecurityPrivilege) in order to read or write the SACL on any object. This is to prevent unauthorized applications from reading SACLs (and thereby know¬ ing what not to do in order to avoid generating audits) or setting them (to generate lots of spurious audits in order to cause an illicit operation to go un¬ noticed). At last! Pen Computing Without the Learning Curve Now, join hundreds of developers who’ve proven it with Pen Right! Pro Are you a C programmer looking for an easy way to try your hand at pen application development? Then PenRight! Pro is for you. For the past 3 years it's the toolkit more people have used to build custom, pencentric applications for real deployment in the field than any other. It’s easy to get started. Based on DOS, PenRight 1 Pro is completely compatible with off-the-shelf DOS development tools so there's no need to buy a new compiler or debugger to get started. If you’re familiar with event-driven programming, picking up PenRight! Pro is a snap. PenRight! Pro is a complete, easy-to-use SDK. Use DesignForm to lay out your “forms” graphically with click-and-drag ease. PenResource gives you command of your application’s resources. Prototype with CodeStart by graphically defining the flow between forms. C source code is created automatically. Over 300 API routines provide window control, handwriting recognition, field support, and much more! Your applications will run on lots of hardware. Any pen computer shipping today with MS-DOS can run your PenRight! Pro application, like those from GRiD, Fujitsu, and NCR. And thousands of people are already deploying PenRight! Pro applications for field inspections, retail sales and law enforcement. So why not try PenRight! Pr< today? For a FREE Features Demo Disk or more information on PenRight! Pro call: (800) 222-GRiD in the U.S. (800) 532-GRiD in Canada enRight!" GRiD Systems Corporation 46501 Landing Parkway • Fremont, CA • 94538 All product names and trademarks are the property of their respective owners. GRiD □ Request 129 on Reader Service Card □ Page 14 — Windows/DOS Developer’s Journal April 1993 DACL —This field is the Discretionary Access Control List or DACL (often pronounced “dackle"), a list that grants or denies specific accesses to specific users or groups of users. The DACL con¬ tains the bulk of the object security in¬ formation, and it can be one of the most confusing parts of Windows NT security to understand. Most of the rest of this article is devoted to explaining DACLs. DACLs Given a Windows NT object, you can grant or deny specific kinds of access to that object for specific users by adding entries to the object’s Discretionary Ac¬ cess Control List (DACL). An object may get its DACL from an explicit assignment or a defaulting mechanism. An explicit DACL is assigned when a user process constructs a DACL and pas¬ ses it to the system with instructions to apply it to a particular object However, most DACLs in a running system will be assigned to their objects by default. The most common defaulting mechanism is where protection on a file is inherited from that file's directory. The other defaulting mechanism is rarely employed, but occasionally use¬ ful. One of the user-modifiable fields in the access token is the default DACL. This default DACL will be applied to every object created by the process that owns the token. This mechanism is useful if a large number of objects must be created with identical DACLs, but in practice often has unintended side ef¬ fects. DACL Structure Conceptually, the DACL is just a list of entries, each of which grants or denies a set of accesses to a user or group of users. However, if you are going to write code that deals with security, it will be helpful to look at the structure of a DACL in detail. As shown in Figure 3, a DACL con¬ sists of header information followed by a variable number of structures called access control entries (or ACEs). An ac¬ cess control entry consists of header in¬ formation, a set of access bits (in the form of an access mask), and an SID that may represent either a user or a group of users. Part of what makes NT security con¬ fusing is that its mechanisms are very flexible and easy to extend. Access con¬ trol entries do not have to look like the ones described here. However, the Win¬ dows NT kernel will only recognize and interpret access control entries that it understands. The definitions of the data structures l am going to describe may look unnecessarily complex, but they are defined that way so that they may be used in many ways. Header Information A DACL is a structure of type ACL, defined as follows: typedef struct _ACL { UCHAR AclRevision; UCHAR Sbzl; USHORT AclSize; USHORT AceCount; USHORT Sbz2; } ACL, *PACL; There isn't much information here. As with the security descriptor structure, the AclRevision field and SBZ1 and SBZ2 fields exist to allow for future changes in the data structure. The Acl¬ Size field contains the total size of the structure, which may be larger than the sum total of the access control entries in the list to allow for future growth. The AceCount field indicates the num¬ ber of access control entries (ACEs) in the ACL While it is entirely permissable for you to fill in the fields of an ACL or ACE structure “by hand," it isn't necessary. The Win32 API provides Initialize- Acl(), which takes a buffer and initial¬ izes the various parts to look like a valid, empty ACL. (I will demonstrate this in next month's code example.) Access Control Entry Structure As Figure 3 shows, the DACL header is immediately followed by some number (which may be zero) of ACEs. Like the DACL itself, each ACE starts with a header: typedef struct _ACE_HEADER { UCHAR AceType; UCHAR AceFlags; USHORT AceSize; } ACE_HEADER, *PACE_HEADER; Windows & DOS V Programming Tools Sourcer, "Sourcer is the best disassembler we’ve ever seen." PC Magazine Creates commented source code and list¬ ings from binary files. Shows how programs work with detailed comments on interrupts, subfunctions, I/O functions, and more. Sup¬ ports all instructions to 80486 and V20/V30. Sourcer provides the best analysis separat¬ ing code and data. It automatically deter¬ mines data types, uses descriptive labels for BIOS and PSP data, and links data items across multiple segments. New version 5.0 makes most DOS EXE and COM files and drivers reassemble perfectly, byte-for-byte identical to the original! Top professionals depend on Sourcer for the mostjjeliable results with the least effort. v I |_»l C- \ mosypl for Windows "Sourcer combined with Windows Source should be mandatory for looking into Windows Programs." Sal Ricciardi PC Magazine Windows Sourcei.. with Sourcer generates detailed listings of Windows EXEs, DLLs, SYSs, VxDs, device drivers & OS/2 NE files. Labels, by name, export & import function calls, API calls like "GetFreeSpace" and more. See the many undocumented Windows functions used by professionals to perform tricks that are otherwise impossible. Comes complete with extra utilities for resource extraction and import analysis. Uses CodeView symbols for improved clarity. BIOS Source for PS/2, AT, XT, PC and Clones The BIOS Pre-Processor ™ with Sourcer creates commented listings for any BIOS ROM in your PC. Understand how your specific BIOS works! Adds over 75K of comments specific to your BIOS. Identifies multiple interrupt branches with special labeling like "int_10_video." Fully automatic. Sourcer -Commenting Disassembler $129.95 Sourcer w/BIOS -(save $10) 169.95 ASMtool 486-Automatic flowcharter 199.95 ASM Checker -Finds source code bugs 99.95 Windows Source -requires Sourcer 129.95 Windows Source & Sourcer-jsave $30) 229.90 Shipping: USA $6; Canada/Mexico $10; Other $18. CA residents add sales tax. © 1993 VISA/MasterCard/COD 30-DAY MONEY-BACK GUARANTEE 1-800-648-8266 order desk V Communications, Inc. 4320 Stevens Creek Blvd., Suite 275-WD San )ose, CA 95129 FAX 408-296-4441 408-296-4224 April 1993 Windows/DOS Developer’s Journal — Page 15 The AceType field may be one of two values: ACCESS_ALLOUED_ACE_TYPE and ACCESS_DENIED_ACE_TYPE. As might be obvious from the names, these indicate whether or not the access control entry is meant to grant or deny accesses. The AceFlags field holds flags describing if and how the ACE is to be inherited. As described earlier, ACEs may be marked so that if they appear on a directory and a file is created in that directory, the ACEs will be passed to that file. ACE inheritance is complex and beyond the scope of this article, but suffice it to say that it is a very powerful means of setting up a secure system in that it ensures that newly created files will be protected, even if the user creating them does not know the principles of Windows NT security. Figure 4 shows the structures that describe the "known ACEs,” which define the structure that Windows NT expects to find for the ACCESS_ALLOUED and ACCESS_DENIED ACE types. Since the Win32 API provides AddAccess- AllowedAce() and AddAccessDenied- Ace(), few applications will have to make direct use of the ACE structure. However, understanding what’s going on under the covers helps in under¬ standing how the ACEs are interpreted. The Access Mask The mask field in the access control entry is the same as the desired access mask that you pass to the Win32 API when you create or open an object. Fig¬ ure 5 shows the structure of an access mask. Bits 16 through 25 of this mask contain standard access types that are common to all objects. They are used as follows: WR/TE_DAC access allows the ap¬ plication to modify the protection on the object. This means the application can obtain the object's DACL, edit it in any way it pleases, and replace the old DACL with the new one. With this ac¬ cess, an application could even remove all protection from the object. WRITE_OWNER access allows a pro¬ gram to modify the owner of the ob¬ ject. This is useful because the owner of an object can always change the protection on the object (or, more for¬ mally, the owner of an object may not be denied WRITE_DAC access to the ob¬ ject). Remember that the SID of the owner of an object resides in a field of the object's security descriptor. RE AD_CONTROL access allows the ap¬ plication to query the owner, DACL, and certain control information from the object's security descriptor. DELETE access allows the application to delete the object. Note that even though an object may be deleted and no longer usable, the storage associated with the object in memory will not be freed until all handles to the object are closed. SYNCHRONIZE access allows the handle to be passed into UaitFor- SingleObject() and related calls. In other words, this access gives you per¬ mission to synchronize execution with some event associated with the given object. ACCESS_SYSTEM_SECUR/TY access al¬ lows modifying audit and alarm control for the object. This access may not be granted via an object's DACL, but in fact requires that the caller have a particular privilege. MAXIMUM_ALLOWED is not really an access bit that you can grant or deny in StratosWare Corporation 1756Plymouth Rood, Suite 1500 • Ann Arbor, MI 48105 • 1 -800-WE-DEBUG International (313)996-2944 • pax Lina (313) 996-2955 & (3,13) 747-8519 □ Request 153 on Reader Service Card □ And you can use MemCheck with C++ to keep your C++ apps in tip-top shape. Easy to use Developing reliable software is challenging for the best of us. Using MemCheck brings big payoffs for novice and expert alike in quality and time savings. But you be the judge—youf satisfaction is guaranteed. Call 1-800- 933-3284 (1-800-WE-DEBUG) and take the fastest , easiest approach to stomping the whoppers of C bugs. MemCheck comes ready to run — be sure to specify compiler and platform! DOS $139 WINDOWS $179 $99 MACINTOSH $179 $99 SPECIAL BUNDLES! DOS MASTERS PACK $199 r Microsoft CANt) Borland C... save $80 NDOWS GURU PACK $159 for Microsoft ( AND Borland C PC POWER PACK $ 199 any DOS version + any Windows version Sgifemm ‘MemCheck is worth its Ifif weight in gold. ” — David Thielen, author of ‘NO BUGS: Delivering Error-Free Code in C and C++’ CM YOUR C APPLICATIONS 1 - 800 - WE-DEBUG STOMP YOUR EFFORTLESSLY. Toughen up against bugs If you’re seriously interested in writing the best, most reliable C programs you can, take a giant step to increase your productivity with MemCheck. Discover how easy it is to stomp the worst, most pervasive bugs in the C language. With no source code changes, and no special compiler options, MemCheck is a rock solid defense against a whole cadre of common memory errors. Silent and deadly MemCheck operates completely automatically, interacting with the developer only to pinpoint memory errors by exact source file and line number . Otherwise it’s as quiet as an eagle on the wind. Without your DATA CORRUPTION WE USE AND SHIP QUALITY RECYCLED MATERIALS. MEMORY OVERWRITES even having to know it’s there, MemCheck is a potent weapon in all phases of development. Seamless integration MemCheck integrates seamlessly into your Windows or DOS C projects in 15 minutes. You’ll pinpoint overwrites on GlobalAllocs, LocalAllocs, and all linear memory allocations supported by your compiler (malloc, calloc, etc). Find unffeed memory, heap corruption, and more. Up to 20 times faster than other debuggers trying to do the same things. Page 16 — Windows/DOS Developer’s Journal April 1993 (3 Ifl FREE Product Information Use this postage paid card to stay up-to-date on products that affect your productivity. Just fill out the card and drop it in the mail. Windows/DOS □ DEVELOPER S JOURNAL □ YES! Send me 12 issues of Windows/DOS Developer’s Journal for only $29! □ 2 years (24 issues) for $54 □ 3 years (36 issues) for $77 □ Bill Me □ Visa □ MasterCard Number_Exp._ Signature_ Name Company Address City state Zip CountrylProvince/Mailcode 4.4 Please allow up to six weeks for delivery of first issue. Orders outside the US must be prepaid in US funds. CANADA/MEXICO subscriptions are: 1 year - $53; 2 years - $88; 3 years - $121. Overseas subscriptions are: 1 year - $64; 2 years - $120; 3 years - $174. Windows/DOS □ DEVELOPER'S JOURNAL 1601 W. 23rd St., Suite 200 Lawrence, KS 66046-9950 USA (913) 841-1631 FAX: (913) 841-2624 REQUEST READER SERVICE NUMBERS: Please help us serve you by answering the following: 1) I program: □ for a living □ as a manager □ as a hobby 2) I program in: □ MS-DOS □ Windows 3) I program most frequently in: □ C++ □ C □ Assembly □ Pascal □ Other_ Use with the April 1993 issue only. NAME COMPANY ADDRESS □ Please start my subscription to Windows/DOS Developer’s Journal for one year. Bill me $29 (U.S.); $53 (Canada/Mexico); or $64 (all other countries). CITY IS TA TE/ZIP/COUNTR Y PHONE FAX 4.4 NO POSTAGE NECESSARY IF MAILED IN THE UNITED STATES BUSINESS REPLY MAIL FIRST CLASS PERMIT NO. 682 LAWRENCE, KS Postage will be paid by addressee WindowsyPOS □ DEVELOPER'S JOURNAL 1601 W. 23rd St., Suite 200 Lawrence, KS 66046-9950 lilliiilliilliiiiliilill.ililiililmlilillinililil NO POSTAGE NECESSARY IF MAILED IN THE UNITED STATES BUSINESS REPLY MAIL FIRST CLASS PERMIT NO. 682 LAWRENCE, KS Postage will be paid by addressee Windows/POS □ DEVELOPER'S JOURNAL 1601 W. 23rd St., Suite 200 Lawrence, KS 66046-9950 CZ5 FREE Product Informatior Use this postage paid card to stay up-to-date on products that affect your productivity. Just fill out the card and drop it in the mail. lilliiilliiMiiiiliililliililiililiiililillniililil an access control entry. This is a bit that you can set in a desired access mask that modifies Windows NT's algo¬ rithm for scanning the DACL. Object-Specific vs. Generic Access Types In the diagram of the access mask shown in Figure 5, the lower 16 bits of the access mask are labeled “specific rights". “Specific" means that the mean¬ ing of these bits is different for each type of object. For example, requesting bit 0 for a file object means that you're asking for FILE_READ_DATA, while bit o for an event object is EVENT_QUERY_STA TE. There is no pattern to how these bits are used; you must know what access you need to ac¬ complish what you want to do. The fact that object-specific access bits are different for each type of object often makes them difficult to use. For example, suppose an application wishes to create several types of objects and ensure that users have “read" access to the objects, even though “read” may mean slightly different things for each object In order to protect each object of each type, the application would have to construct a different DACL for each type of object and be careful to pass the correct DACL in when creating each object. It would be much more convenient to be able to create a single DACL that expresses the concept “allow read," simply apply this DACL to each object that is created, and have the right thing happen. Generic access types allow precisely this kind of shortcut. Each object type (file, event, process, etc.) has something called a generic mapping. A generic mapping is a description of all of the accesses that correspond to the concepts of “read,” “write," “execute," and “all” access for that object. When Windows NT receives a request to place a DACL on an object, it first looks up the generic mapping for objects of that type. It then examines all of the ACCESS_ALLOUED and AC- CESSJDENIED access control entries in the DACL, examining the generic access bits in each entry's access mask. For each generic access bit it finds set, it sets the specific bits corresponding to that generic bit in the access mask and clears the generic bit. For example, for a file object, the bit GENERIC_READ maps to the standard bits READ_CONTROL and SYNCHRONIZE, and to the object-specific bits FI LE_READ_DA TA, FILE_READ_AT- TRIBUTES, and FILE_READ_EA. Placing a DACL on a file that grants someone GENERIC_READ will grant those five ac¬ cesses as if they had been specified in¬ dividually in the access mask. The DACL Evaluation Algorithm Having described the DACL structure in detail, I can now give a formal description of how Windows NT evaluates the DACL to decide whether or not to grant a particular access re¬ quest. Figure 6 shows the pseudo code for the algorithm. if a program requests access to an object that has a DACL, the operating system will walk the access control entries in the DACL in order, from first to last For each ACCESS_ALLOUED access control entry it finds, it will see if the SID in that entry is in the current token (meaning, is it the SID of the user or one the user's groups?). If so, the operating system clears the bits found in common between that access control entry's access mask and the desired ac¬ cess mask. For each ACCESS_DENIED entry, the operating system will again make sure the SID is in the current token, and if so, it will see if any of the bits in the access control entry's access mask remain in the desired access mask. This continues until there are no more access control entries (in which case the operating system denies ac¬ cess), any of the desired bits are denied (which will also deny access), or all of the desired access bits are granted. This implies two rules to keep in mind. First, all accesses are denied un¬ less explicitly granted. If there is any¬ thing left in the desired access mask after the DACL is evaluated, the request will be denied. Second, the order of ac¬ cess control entries is extremely impor¬ tant. Once an access is granted by an access control entry, it may not be denied by a subsequent access control entry. Likewise, once an access is denied, the presence of an access con¬ trol entry that grants the access further down the list is not going to change that denial. In order to guarantee that Windows Help Files So easy - it’s Magic! - -31 ■- tSI ■— — 1H — O ~ic=i f» E« Boo*nwrt IMP Contents • tS N i ** It □ -Si OUMTy ■ - , ,^n. £ The Windows Help Magician saves you • countless hours creating custom help files for Microsoft Windows Applications. %* .. I Forget about the cumbersome footnote way of creating help with Microsoft Word. Use this tool to create help files in a single, integrated environment. No need to switch out to DOS to run the Help Compiler. With the Magician, you’ll be able to write the RTF file instantaneously. And you can even import RTF files from manuals written in Microsoft Word. Highlights: □ Fully functional familiar editor □ Create jumps and popups simply by marking a word or a phrase □ Include bitmaps and hotspots □ Create browse sequences easily □ Use different fonts and colors for help type □ Import and export RTF and ASCII files □ Very FAST in generating RTF files □ Test your help file instantaneously while inside the Help Magician □ Works with all Windows languages □ Supports Windows 3.0 and 3.1 □ Only $199! Also Available: The Windows Bitmap Magician Include Wingdings and other special fonts within your help files for special effects, custom bullets, superscript, and special math symbols. Works with any help authoring tool. Only $49! Order Now! Call (800) 542-2742 SO'tFtW A^Li IN'lTHvM !/\Slr INCORPORATED 82 Cucumber Hill Rd Foster, Rl 02825-1212 Tech: (401) 397-2340 Fax: (401)397-6814 □ Request 319 on Reader Service Card □ April 1993 Figure 6 The DACL Evaluation Algorithm while (more ACEs and DesiredAccess != 0) if ACE.AceType == ACCESS_ALLOWED_ACE_TYPE if ACE.Sid is in token DesiredAccess &= ~ACE.Mask continue; if ACE.AceType == ACCESS_DENIED_ACE_TYPE if ACE.Sid is in token if (DesiredAccess & ACE.Mask) != 0 return(ACCESS_DENIED) if DesiredAccess ** 0 return(ACCESS_ALLOWED) else return(ACCESS_DENIED) an ACCESS_DENIED access control entry will have the desired effect, you have to place that entry near the front of the list. The Windows NT File Manager's ACL editor supports this convention. It builds DACLs such that all ACCESS_DENIED access control entries are at the head of the DACL, followed by all the ACCESS_ALLOUED access control entries. A DACL in this form is referred to as being in “canonical form.” Missing DACLs vs. Empty DACLs There is a subtlety to the DACL algorithm. Windows NT makes the distinction between an object having no DACL and having an empty DACL. An empty DACL is one that is struc- ^OiUnted Manage Reusable Code: Files Shared by Many Projects Coordinate Your Entire Team Start Coding in Minutes, not Days! Support Cross-platform Development for DOS, Windows, WinNT... even the Mac! Generate Complete File and Project Histories SourceSafe One Tree Software POBox 11639 Raleigh, NC 27604 800/397-2323 fax: 919/821-5222 voice: 919/821-2300 □ Request 164 on Reader Service Card □ Figure 7 No DACL vs. Empty DACL NULL DACL Pointer INULL DACL Present Set Clear Grant Grant All All Evaluate Grant ACL All turally complete, but has no access control entries in it. If an object has no DACL, the object is said to have “no security,” and all accesses to the object are granted (except for those requiring a privilege). If a DACL is present but empty, the “all accesses are denied unless explicitly granted" rule kicks in, and all accesses are denied —a completely opposite result for what would appear to be a similar situation. The decision of whether there is a DACL present is based on examining the DACL_PRESENT bit in the header of the security descriptor and the DACL pointer field. The chart in Figure 7 shows all the possible combinations. The “evaluate DACL" field may be expanded further into the cases of whether there are any ACEs present (in which case they will be evaluated) and if there are none (in which case the request will be denied). Privileges and DACL Evaluation As I mentioned earlier, privileges are basically overrides of the normal security mechanisms. They exist because there are times when the DACL security on objects should not be en¬ forced for one reason or another. For example, many com¬ panies have their MIS department perform backup and restore operations on machines in their organization. Without a back¬ up privilege that allows overriding the DACLs on files, it would be necessary for every file in the organization to grant explicit access to some account in the MIS department. In a large or¬ ganization the chances of this sort of setup working smoothly are vanishingly small, and irritating regardless. So, Windows NT provides a backup privilege that allows its holder to read (but not write) any file on the disk. Privileges are very powerful in Windows NT, because there is no mechanism to override their effects. If user Joe is in a group that normally has access to a file, it is still possible to deny Joe access to that file with another access control entry. There is no way to restrict the use of privileges, and thus they must be given out sparingly and only when there is a definite, clear need. MAXIMUM_A L LOWED Access There is one final access type that is different from all of the other access types: MAXIMUM_ALLOUED access. MAXIMUM_AL- LOUED may only be requested in a desired access mask: it cannot be granted or denied in an access control entry. Page 18 — Windows/DOS Developer’s Journal April 1993 When Windows NT sees a request for MAXIMUM_ALLOWED access to an object, it walks down the DACL of the object and computes the maximal access that the caller has to the ob¬ ject. The algorithm it uses is as follows: Denied=0; Granted=0; for each ACE if ACE.Type== \ scheme (the DACL) to specify the security on each object, providing a uniform interface to security features for a variety of different operating system resources. This article has given you an overview of security and a look at some of the detailed structures used with object security. Next month, I put this information to use with a small program that allows an administrator to override the normal security on a file. ACCESS_ALLOWED_ACE_TYPE Granted |= \ (ACE.Mask & "Denied); else Denied |= (ACE.Mask & "Granted); if Granted==0 return ACCESS_DENIED There are two special cases to keep in mind when using MAX IMUM_A L LOU ED. The first is that if any bit in the desired ac¬ cess mask is set in addition to MAXI- MUM_ALLOMED, the system will interpret that to mean that that bit is required, meaning that the access request will fail if that bit does not end up being granted by the MAXIMUM_ALL0UED algo¬ rithm. The second case is how objects that do not have DACLs are handled. If you recall, an object with no DACL may be opened for any access. What does it mean to open such an object for MAXI- MUM_ALL0UED1 In this situation, Windows NT will return the GENERIC_ALL bits for that object type in the handle and return success. MAXIMUM_ALLOWED is a cheap and easy way to deal with the situation where you don’t know what access you're going to need to an object. The downside is that you don’t know what accesses were granted to the object, so you have to be prepared for operations on the returned handle to fail with AC- CESS_DENIED. Summary Windows NT security is designed to meet the government C2 security standards for discretionary access con¬ trol. The operating system maintains security information both for users and for the objects they want to access, such as files, events, processes, and so on. Windows NT also supports privileges, which provide a way to over¬ ride the normal security mechanisms to handle special problems, such as allow¬ ing someone to back up all files. The operating system uses a flexible Fast, full-featured SQL engine for Windows Ideal for Lap-top, pen-based and LAN applications that require a high-performance and full-fledged SQL RDBMS Quadbase-SQL for Windows v2.0 is an industrial-strength SQL relational database engine that allows Windows developers to build applications using various languages like Visual Basic, Realizer, Toolbook, SQLWindows, C, C++, etc. A unique interpretive, language-independent embedded SQL interface included with the system makes using any Windows language easy. The SQL engine, implemented as a DLL, is fully ANSI SQL 89 level 2 compliant, and supports the Microsoft ODBC standard, which provides seamless, object-oriented access from Visaul Basic v2.0. Extensions include referential integrity, scroll cursors, and outer join, along with other advanced features such as multi-user concurrency control, crash recovery, transaction processing, multiple instances, BLOB data, and read-only schemas for CD ROMs. The engine is very fast and compact, and is especially designed to manage large amounts of data efficiently. Visual Basic development is enhanced by embedded SQL and custom controls for browsing and data entry. dQUERY, an award winning query tool/report writer, and VBQUERY, an interactive query tool for Windows, are included for quick prototyping of SQL statements. A 'C' language programming interface is also provided together with an embedded SQL preprocessor. The native file format is dBASE. This product is ideal for small to medium sized LAN file server systems, standalone laptop machines, or pen-based systems. Users can benefit from advanced relational database features while opening a migration path to SQL servers. Call for a free demo disk now. Find out why AT& T,Compaq Computer, Cabletron Systems, EPA, GE and many more major organizations are using Quadbase products. Quadhase Systems Inc. 790 Lucerne Dr. #51 Sunnyvale. CA 94086 Tel: (408) 738-6989 Fax: (408) 738-6980 □ Request 175 on Reader Service Card □ April 1993 Windows/DOS Developer’s Journal - Page 19 Escape from POSIX John Richardson Microsoft designed the Windows NT operating system to support multiple ap¬ plication programming interfaces (APIs) in order to capture a large portion of the existing applications base. Thus the preliminary version of Windows NT supports DOS, 16-bit Windows 3.1, the new 32-bit Win32 API, OS/2 character mode, and POSIX. The DOS and Windows 3.1 environments support many common applications, providing both text and graphical displays, network communications, and inter¬ operability with other NT subsystems through named pipes, WINSOCK, and DDE (Dynamic Data Exchange). Even though the OS/2 environment supports only text- based applications, it allows access to both the console screen control APIs and the network communication APIs. For DOS applications that access direct hardware, the developer can write a user-mode virtual Device Driver (VDD) to extend the DOS subsystem’s support for missing application requirements. This is not the case with POSIX. Many application features — such as cursor ad¬ dressing, network communications, and interprocess communication with other NT subsystems —are not supported because they are not in the POSIX 1003.1 specifica¬ tion. Also, since the POSIX 1003.1 specification does not include system integration features such as executing non-POSIX (DOS, Win32, WIN 16, or OS/2) programs, it would not be useful to port a UNIX (POSIX) shell to the POSIX subsystem. As a result, programs such as vi (needs cursor addressing), make (needs to run the Win32 com¬ piler and linker), and X client library support (needs SOCKET communications support) cannot be ported to the Windows NT POSIX subsystem. Even device access —beyond the minimal /dev/tty support —is not allowed. A POSIX application cannot open and connect to devices such as the communications ports (for UNIX-based communica¬ tions such as UUCP, and CU), the tape drives, or raw floppy disks (to support file interchange programs such as tar and cpio). John Richardson is a principle engineer for Siemens-Nixdorf at its Research and Development Division in Burlington Mass. John has over nine gears of UNIX kernel experience developing real time multiprocessing systems for non-symmetrical memory architectures. For the last few gears, his development has focused on microkernel based systems cumulating in the development of a binary compatible System V Release 4 server for MACH 3.0. He is currentlg Windows NT project leader consulting for internal hardware and software groups. Send questions to.- CompuServe: 70541,672; Internet: jr@sni-usa.com; Phone: 617-273-0480 ext 3458; Fax: 617-221-0236. Page 20 — Windows/DOS Developer’s Journal April 1993 Windows NT Given these restrictions, you can only port simple programs like cat and cp to the POSIX subsystem. You could port programs such as shell and make, but since you still could not start other non-POSIX applications, their usefulness would be mini¬ mal. To support an application requiring any of the missing facilities would entail rewriting the application for the native Win32 API —a more demanding task than porting to one of the more full-featured POSIX implementations available on current UNIX environments such as System V Release 4™. On a large application, this cost could be very high. One way to deal with these restrictions is to split the program up into multiple parts, placing the sections that require access to features not supported by POSIX in separate modules from those that use only the available POSIX services. You can develop the part that requires the more advanced services to run under Win32 and then tie the two portions of the program together using a remote procedure call model. For some applications, this approach may be simpler than just porting the entire application to Win32. An example of such an application would be a UNIX X-Window-based program that uses the POSIX fork(), exec(), File, and process group APIs, while making all of its display and keyboard I/O calls through the stand¬ ard X-Window protocol library, XLIB. On the Win32 side, you would have to write a server to translate the XLIB re¬ quests into the proper Win32 API requests. Full X-Servers will be available for Win¬ dows NT from multiple vendors: a minimal XLIB library for Win32 is available on CompuServe in the MSWin32 “Porting from UNIX" library section. With these tools, porting an existing X-Window-based UNIX program to Windows NT would require less effort than a complete rewrite for Win32. One note of caution: l am not suggest¬ ing that you modify UNIX programs to contain a mixture of POSIX and Win32 API calls, but that you implement missing POSIX functions under Win32 and make these services available to programs on the POSIX subsystem. Microsoft has emphatically discouraged the creation of “mutant” programs that contain a mixture of Win32 and POSIX APIs, and, in fact, such an application would offer no advantage. By sticking with standard UNIX APIs, you can still compile your program sources for a UNIX machine. If a significant portion of the program needs to have access to native Win32 APIs, then a full port of the program to Win32 would give you greater flexibility in the long term. April 1993 Windows/DOS Developer’s Journal — Page 21 Figure 1 Using a Win32 Server /Win32 AppV— V, (Server) J|_ - ffoSIXAppX (Client) J sAL Subsystem Windows NT Calling Remote Procedures One problem with using RPC to communicate between POSIX and Win32 is that the RPC supplied with Windows NT is not supported under the POSIX subsystem. Since the POSIX subsystem does not support other Windows NT interprocess communication features such as named pipes, Windows Sock¬ ets, or DDE, these standard client-server communications links are not available. But all is not lost. To allow the common command processor to execute programs from multiple sub¬ systems, including the transparent (to the user) piping of out¬ put from one command to the input of another command, the POSIX subsystem supports the redirection of I/O for the application's standard input and output devices. Since piping is supported between commands of the different NT subsys- "I can't imagine why anyone would program without it...not using SafeWin is like programming blindfolded.'' SafeWin • No reprogramming—just relink with SafeWin • Detects resource leaks (global handles, cursors, icons,...) • Detects bad handles, bad GDI objects, thousands of potential error conditions • Traps NFY and RIP errors • Displays complete symbolic stack for each error • Records and displays window messages by symbol and value • Interactively change error traps, view resource usage, view reported errors, and more... • Use with MoreHeap for Windows to detect memory leaks, buffer overwrites, and view heap dumps for malloc'ed allocations. • Redirect reports to message box, debug monitor, or file Compatible with Borland C+ + , Microsoft C+ + and Demo disk available. a || languages that can link 16-bit DLLs. Visa/MasterCard/CODs/ POs accepted. 30 day money back guarantee. SafeWin.$249 MoreHeap (DOS, Windows).$249 WindowsPack (SafeWin, MoreHeap).$399 □ Request 123 on Reader Service Card □ terns, a Win32 program can set up redirected I/O handles through anonymous pipes, and then start the execution of the POSIX application (see Figure 1). The POSIX application can then use its standard input and output to exchange data with the Win32 server that Started it. With this approach, since the standard input and output have been redirected to the pipes, the normal POSIX console I/O functions such as printfO would no longer display their output. Instead, any output from printfO would go into the pipe and be sent to the Win32 server. Under a normal POSIX system, you would solve this problem by opening the special device /dev/tty to gain access to the real console, not the redirected I/O handles. This would allow your POSIX applica¬ tion to use the dup() system call to reassign the pipes’ POSIX stdin and stdout file descriptors (handles) to new ones, and then use dup() again to make / dev/tty the program's new stdin and stdout. The program would then have normal printfO and getchar() access to its console, plus two hand¬ les that could be used to communicate with the Win32 server. Unfortunately, a bug in the October 1992 Windows NT Preliminary SDK makes this solution unavailable: even though opening /dev/tty succeeds, I/O is still redirected to the pipes, not the console. This is a bug according to the POSIX 1003.1 specification, and it has been reported, but there is currently no announced target date for repairing it. If you want your POSIX application to still have access to the console and key¬ board, you’ll have to use a different method to communicate with Win32 applications. One interprocess communication mechanism that the POSIX subsystem does support is POSIX named pipes. These are only available among POSIX applications and are not visible or available to the Win32 named pipes, which effec¬ tively isolates the POSIX subsystem. However, if a POSIX server application that does no console I/O were started with redirected I/O from Win32, it could create some POSIX named pipes and act as a message “forwarder” for other POSIX ap¬ plications (see Figure 2). That provides the needed com¬ munications channel to the Win32 application: all you have to do is get an RPC framework operating over it. Ui SeaBreeze SOFTWARE SYSTEMS SeaBreeze Software Systems 1330 Highway 206 Skillman. NJ 08558 Sales/Support: 609-924-6793 BBS: 609-497-4607 e-mail/CIS: 72330,705 Page 22 — Windows/DOS Developer’s Journal April 1993 The MS RPC shipped with the Windows NT Beta SDK sup¬ ports RPC over TCP/IP, LAN Manager, and a fast local connec¬ tion. As I mentioned earlier, MS RPC does not support POSIX, but the MS RPC programmer's manual does state that MS RPC will provide support for user-written transport providers at some future date. With such an interface, you can write routines that allow the interface to be used over your own connection. In the RPC programming model, a client application uses a communications link to request a service to be performed by another program (the server) on its behalf. The application must establish a connection, create a message requesting the service in the format that the communications link expects, and then send the message to the server. It then has to wait for a reply, handle any errors, and free the message buffer. To simplify the process and isolate the program from the specific details of the communications link — tools and runtime libraries that make the service request appear just like a local procedure call have been developed. To support the develop¬ ment of new services, Microsoft supplies a compiler (MIDL, for Microsoft Interface Definition Language) that takes descriptions of the service, its parameters, and its return values, and generates the actual code to deal with the communications. The compiler supplies the developer with a source file con¬ taining the subroutine stubs for linking with the application. Even without the compiler to handle the communication details, you can still use the RPC model in your program. By hand-constructing the communication stubs for the client and the server and putting them in a library, your POSIX applica¬ tion can use the RPC model to request services from your Win32 server process. Since you are communicating with another 32-bit process on the same system, the hand-con¬ structed RPCs can be much simpler than the stubs and run¬ time libraries that MS RPC generates (you do not have to deal with the data type and byte-order conversions that must occur between two different systems on a network, or when a 16-bit DOS client requests the services of a 32-bit Win32 server). Example Code The first program module (and the largest) is the Win32 server in win32srv.c (Listing 1), which sets up the redirected I/O handles, starts the POSIX server process, and then services the RPC requests from POSIX client applications. It contains the server routines for the Win32 services it wants to make avail¬ able to the POSIX application. You can add code to this server to support new services. Once the server starts to support more than a few routines, the implementation of the new services should be put into a separate source file and called from the main program. The most problematic part of this program is setting up the redirected I/O handles. Luckily, Microsoft provides an example in the Microsoft Win32 Programmers Reference-. Overviews (pp. 67-71). In this example, the main trick is to duplicate the cur¬ rent process's STD_INPUT_HANDLE and STD_OUTPUT_HANDLE, open the pipes, then set the STD_INPUT_HANDLE and the STD_OUTPUT_HANDLE to the pipes. When the POSIX server process is created as a child of the Win32 server, it is marked to inherit the parent process’s open handles, thus getting the Programming for Microsoft Windows doesn’t have to be a Pane objeet-Menu provides an object-oriented architectural framework for your application. Our intuitive architecture and natural programming syntax increase your productivity more than you ever thought possible. Seamlessly port your product between DOS graphics and Microsoft. Windows using our interface objects. Give your Windows apps a facelift: Our library includes extensive icon capability and optional Motif-st.yling not found in other Windows API’s. Create your own objects easily by extending our class library. Our goals are to simplify GUI design for the novice while providing the power and flexibility needed by an expert. Includes windows, icons, scroll bars, menus, buttons, tool bars, dialog boxes, data entry, spin control, file chooser, combo box, justified page display with embedded icons and hypertext primitives, and much more. Special features: dynamically change scroll bar resolution, mulitple line items, multiple icons for a menu item, several menu styling and item selection options, compact, natural programming syntax. Special DOS features include help and icon libraries, hypertext help system, event management, overlapped window manager. "The application's visual components have a sculpted, three-dimensional look reminiscent of Motif. ... object-Menu can use automatic placement directives to define positioning of visual components ... the [object-Menu] scroll bars here" truly scroll the items in a given window's display. ... Another unique feature is the use of tear-off menus similar to those on the MAC and Open-Look." D r. Dobbs Journal. October 1992 _ "It seems that the designer has gone to a lot of trouble to make it as easy as possible to describe GUI elements in the most succinct and yet self explanatory way possible. ... The support for the hypertext portion of the help system is nothing short of excellent." Compiler support: Borland C++, Microsoft C++ (Ask about MetaWare C++,Watcom C++, Zortech C++) Phar Lap 286/386 DOS extender DOS Graphics support: BGI. Microsoft graphics, MetaWindow, Genus GX, Halo graphics. till object-Menu " No Ris^BO^y^aarantw $898 Object-Menu Free Demo Available with source 7 Mountain Rd, Burlington MA 01803 Tel: (617)273-0421 Fax (617)270-4437 BBS (617)270-9552 □ Request 340 on Reader Service Card □ Windows/DOS Developer’s Journal — Page 23 April 1993 Listing 1 win32srv.c /* WIN32 Server Program, WIN32SRV.C */ Dupl i cateHandle(GetCurrentProcess () , hChi 1 dStdinWr, GetCurrentProcess () , &hChildStdinWrDup, 0, linclude FALSE, /* Not inherited */ linclude DUPLICATE SAME ACCESS); linclude linclude CloseHandle(hChildStdinWr) ; linclude “win32psx.h" /* Now Create the Child Process */ VOID ErrorExit(char *) ; VOID ServiceRequestLoopO; if (!CreateProcess(NULL, VOID SendAckReply(int chan); "psxagent.exe", /* name of POSIX server process */ VOID SendNackReply(int chan); 0, /* no processes security attributes */ int ReadStream(char *buf, int size); 0, /* no thread security attributes */ int WriteStream(char *buf, int size); 1, /* inherit handles */ int RunShellCmd(char *cmd_buf, int chan); 0, /* creation flags (inherit console, no detach */ 0, /* inherit current environment block */ HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup, 0, /* no new current directory */ hChildStdoutRd, hChildStdoutWr, &start_info, /* Startup info */ &proc info) /* Process information */ ) ErrorExit("Create Process FailedW); hSaveStdin, hSaveStdout; main() / i SECURITY ATTRIBUTES pipe attr; /* restore the Parents Stdin/Stdout Handles */ PROCESS INFORMATION proc info; if (! SetStdHandle ( STD INPUT HANDLE, hSaveStdin)) static STARTUPINFO start info - { ErrorExit(“Re-redirecting Stdin FailedW); sizeof(STARTUPINFO), /* cb */ 0, 0, 0, /* LPSTR res,desk,title */ if (! SetStdHandle(STD OUTPUT HANDLE, hSaveStdout)) 0, 0, /* X, Y */ ErrorExit("Re-redirecting Stdout FailedW); 80, 25, /* Xsize, Ysize */ 80, 25, /* Close our version of childs write end of the pipe 0, /* Fill attribute */ so that the childs close will be the last close of 0, /* dwFlags pipe. This is so that we will get the EOF properly 0, /* dont show window */ when the child exits.*/ 0, /* reserved */ if(I CloseHandle(hChi1dStdoutWr)) 0 /* reserved */ \. ErrorExit("Can't close pipe write endW); /» /* parent process */ /* Set the SECURITY ATTRIBUTES so the pipe ServiceRequestLoopO; handles are inherited */ pipe attr.nLength = sizeof(SECURITY ATTRIBUTES); /* Close my pipe handles to tell the child that pipe attr.blnheritHandle = TRUE; we are done */ pipe_attr.lpSecurityDescriptor = NULL; CloseHandle(hChildStdinWrDup); CloseHandle(hChildStdoutWr); /* Save the Stdout Handle */ Dupl i cateHandle(GetCurrentProcess(), /* Wait for the process */ GetStdHandle(STD OUTPUT HANDLE), if(WaitForSingleObject(proc info.hProcess, GetCurrentProcess(), ShSaveStdout, 0, (unsigned int)-l) != 0) { FALSE, /* Not inherited */ printf("Error waiting %d\n",GetLastError()); DUPLICATE SAME ACCESS); CloseHandle(proc info.hThread); CloseHandle(proc info.hProcess); i f(!CreatePipe(&hChi1dStdoutRd, &hChi 1 dStdoutWr, return(1); &pipe attr, 0)) } ErrorExit("Stdout pipe creation failedW); /* Close my child process handles */ if(!SetStdHandle(STD OUTPUT HANDLE, hChildStdoutWr)) CloseHandle(proc info.hThread); ErrorExit(”Redirecting Stdout Failed\n"); CloseHandle(proc_info.hProcess); return(l); Dupl icateHandle(GetCurrentProcess(), ) GetStdHandle(STD INPUT HANDLE), GetCurrentProcess(), &hSaveStdin, 0, /* Service Requests from the POSIX program FALSE, /* Not inherited */ This can be expanded as required */ DUPLICATE_SAME_ACCESS); void ServiceRequestLoopO { struct Request Header Hd; if(!CreatePipe(&hChildStdinRd, ShChildStdinWr, &pipe attr, 0)) int numxfer; ErrorExitC'Stdin pipe creation failed\n”); char buf[512]; if(!SetStdHandle(STD INPUT HANDLE, hChildStdinRd)) for(;;) ErrorExit("Redirecting Stdin fai1ed\n"); { /* Get a request */ Page 24 — Windows/DOS Developer’s Journal April 1993 pipe-based STD_INPUT_HANDLE and STD_OUTPUT_HANDLE. After creating the child process, the Win32 server sets its input and output handles back to their saved values. One word of cau¬ tion: if the Win32 server process tries to use the printfO function or to do any other kind of console I/O after setting its handles to the pipes, it could hang because its output would not go to the console, but instead to the pipes that it created. Once the connection to the console has been restored, the program can resume using printfO and other console I/O. Listing 1 continued numxfer = ReadStream((char *)&Hd, sizeof(struct Request_Header)); if(Hd.rh_type == RPC_REQUEST) { switched.rh_request) { case RPC_N00P: SendAckReply(Hd.rh_chan); break; case RPC_RUN_SHELL_CMD_SYNC: ReadStream(buf, Hd.rh_size); RunShellCmd(buf, Hd.rh_chan); break; default: SendNackReply(Hd.rh_chan); break; void SendAckReply(int chan) ( struct Request_Header Hd; Hd.rh_type = RPC_REPLY; Hd.rh_hdrsize = sizeof(struct Request_Header); Hd.rh_size = 0; Hd.rh_chan » chan; Hd.rh_request ■ TRUE; /* also ret. code */ WriteStream((char *)&Hd, sizeof(struct Request_Header)); } void SendNackReply(int chan) { struct Request_Header Hd; Hd.rh_type = RPC_REPLY; Hd.rh_hdrsize ■ sizeof(struct Request_Header); Hd.rh_size = 0; Hd.rh_chan - chan; Hd.rh_request = FALSE; /* also ret. code */ WriteStream((char *)&Hd, sizeof(struct Request_Header)); } int RunShellCmd(char *cmd, int chan) { int exitstatus; struct Request_Header Hd; PR0CESS_INFORMATION procjnfo; static STARTUPINFO start_info = ( sizeof(STARTUPINFO), /* cb */ 0, 0, 0, /* LPSTR res,desk,title */ 0, 0, /* X, Y */ 80, 25, /* Xsize, Ysize */ WINDOWS & MS-DOS SERIAL COMMUNICATIONS DONE THE RIGHT WAY COMM-DRV is a professional serial communication library, that includes TSRs, DLLs, and device drivers. • Support for most Smart & Dumb Multiport cards. • Link libraries into application, or TSRs, or DLLs. C, Assembly, Quickbasic, Visual Basic, Microsoft & Borland Windows SDK compatible. • Full source for X, Y, & Zmodem file transfer libraries, & screen/keyboard libraries. Remote screen management with remote ANSI emulation (window scrolling, erasing, etc.). • Unlimited number of ports active concurrently. Bauds up to 115.2K. Re-entrant code. • Asynchronous and timed callbacks to user written routines. • Real-Time serial port monitor for debugging appli¬ cation in real time. • 16550A, 16450, 8250 auto detection. • Desqview, Procomm DOS/Windows, pcAnywhere compatible. • Several Windows and MS-DOS examples. • One API to learn. All functions behave the same under Windows in all modes & MS-DOS. Library Sources, Device Driver, TSR $189.95 Develop Serial Communication Applications In English COMM-LOG is a collection of programs & TSRs for developing custom applications through our simple english like full featured script language. These programs may be spawned from user applica¬ tion or called via an API. • True background X&Y & Zmodem file transfers on several ports concurrently. • Run several scripts concurrently in the back¬ ground, foreground, or from application. • Built in script language debugging support. • Complete data logging support. Programs, TSRs and multiple examples $189.95 <9 MS-DOS Multitasking Kernel MTASK is a robust multitasking kernel for develop¬ ing cooperating multitasking TSRs and programs with several threads of execution. Full source code to multitasking libraries are included. Full task control, including mailboxes, TSR building routines, IPCs, task blocking, sleeping, RTC control, much more!!! MTASK may be linked into application or used as a TSR. TSRs, Libraries, & Examples $299.95 Multiport Cards Four Port Multiport card w/16450 $110.00 Four Port Multiport card W/16550A $170.00 Eight Port Multiport card w/16550A $225.00 WCSC Tel. 800-966-4832 2470 S. Dairy Ashford Tel. 713-498-4832 Suite 188 Fax 713-568-3334 Houston, TX 77077 BBS 713-568-6401 Visa / Mastercard / American Express / COD / CHECK/ P.O. □ Request 100 on Reader Service Card □ Windows/DOS Developer’s Journal - Page 25 April 1993 Listing 1 continued 80, 25, 0, /* Fill attribute */ 0, /* dwFlags 0, /* dont show window */ 0, /* reserved */ 0 /* reserved */ }; /* Now Create the Child Process */ if (!CreateProcess(NULL, cmd, /* comnand string from POSIX client */ 0, /* no processes security attributes */ 0, /* no thread security attributes */ 1, /* inherit handles */ 0, /* creation flags */ 0, /* inherit current environment block */ 0, /* no new current directory */ &start_info, /* Startup info */ &proc_info) /* Process information */ ) { SendNackReply(chan); /* command error */ return(1); ) /* Wait for the process */ if(WaitForSingleObject(proc_info.hProcess, (unsigned int)-1) !■ 0) { printf(“Error waiting %d\n",GetLastError()); CloseHandle(proc_info.hThread); CloseHandle(proc_info.hProcess); SendNackReply(chan); return(l); } if(1 GetExitCodeProcess(proc_i nfo.hProcess, &exitstatus)) { printf(“exit status err %d\n“,GetLastError()); SendNackReply(chan); return(l); 1 /* Close my child process handles */ CloseHandle(proc_info.hThread); CloseHandle(proc_info.hProcess); Hd.rh_type = RPC_REPLY; Hd.rh_hdrsize * sizeof(struct Request_Header); Hd.rh_size = 4; /* sizeof(exitstatus) */ Hd.rh_chan - chan; Hd.rh_request = TRUE; WriteStream((char *)&Hd, sizeof(struct Request_Header)); WriteStream((char *)&exitstatus, sizeof(int)); return(O); } /* read data from the communications stream */ int ReadStream(char *buf, int size) ( int numxfer, error; if(!ReadFile(hChildStdoutRd, Windows'“/DOS Developer’s Journal Call For Papers Windows/DOS Developer’s Journal is seeking articles on the topics listed below. In addition, we are interested in articles related to Windows NT, Win32s, and the Win32 API. If you have an idea for a related story and ex¬ perience that would especially qualify you to write on one of these topics, Object-Oriented Programming ■ Proposals due 4/12/93 manuscripts due 5/24/93 Suggested topics: A C++ bit class that uses the 80386/80486 bit-han¬ dling instructions. A compendium of techniques for connecting C++/Pas- cal objects to Windows objects. How to use C++ in DLLs. contact our editorial staff for Author Guidelines at: Windows/DOS Developer’s Journal 1601 West 23rd St., Suite 200 Lawrence, KS 66046-2743 (913) 841-1631 FAX (913) 841-2624 Visual Programming ■ Proposals due 5/10/93 manuscripts due 6/21/93 Suggested topics: Reusable forms for Visual Basic. A visual “make” utility. Translating software metrics into visual patterns. Proposals should include a short abstract, preferably followed by a one-page outline of the article. A brief resume of the author’s qualifications should accompany the proposal. Graphics ■ Proposals due 6/7/93 manuscripts due 7/19/93 Suggested topics: Understanding bitmapped file formats. A C++ library for CAD-style graphics. A Windows implementation of R-trees. Optimizing your Windows application’s graphics output. Page 26 - Windows/DOS Developer's Journal April 1993 The POSIX server program in psxagent.c (Listing 2) is started by Win32SVR. It is the only program in the POSIX en¬ vironment that communicates with the Win32 server (via its redirected I/O). This server then creates two POSIX named pipes and waits for messages on them. Whenever a message arrives in the POSIX named pipe, PSXAGENT forwards the mes¬ sage to the Win32 server through the redirected I/O handle. When a reply comes back from the Win32 server, PSXAGENT writes it back to the second POSIX named pipe. PSXAGENT has to be careful to not do any console I/O, owing to the redirec¬ tion and the /dev/tty bug. If you want to do any debugging in PSXAGENT, you could create a file at startup and log debug¬ ging information to it with fprintf(). The POSIX client library in rpcclt.c (Listing 3) takes the place of the normal MIDL-generated stubs. POSIX client ap¬ plications call these routines and link to this library. These stubs have been hand-written, as have the runtime support routines that establish connection with the POSIX server, which forwards the requests to Win32. You can add additional stubs by using the framework provided. Remember that for each client function you add to this file, you also have to add the corresponding server function to win32svr.c. win32psx.h (Listing 4) contains the operation function codes shared be¬ tween the client and the server. I supplied two example func¬ tions. One executes a command line from Win32 and returns the process's exit code. You can use this to allow POSIX ap¬ plications to run any program that can run under Win32, such as the compiler. The second function is a stub function for testing the communications link, and is used by one of the Listing 2 psxagentc - /* POSIX Agent Program, PSXAGENT.C */ strcat(OutNameBuf, NAMED PIPE PATH); strcatflnNameBuf, “RPC REQ“) ; linclude strcat(0utNameBuf, “RPC REP“); linclude linclude ret = mkfifo(InNameBuf, 0 RDWR); linclude if(ret == (-1)) { linclude if(errno !* EEXIST) ( linclude fprintf(stderr,“mkfifo failed errno %d\n“,errno); linclude “win32psx.h" exit(l); \ int ReadStream(char *buf, int size); / ) int WriteStream(char *buf, int size); ret = mkfifo(0utNameBuf, 0 RDWR); int ReadRequestStream(char *buf, int size); if(ret == (-1)) ( int WriteRequestStream(char *buf, int size); if(errno !* EEXIST) ( void ServerLoopO; fprintf(stderr,"mkfifo failed errno %d\n“.errno) ; exit(l) ; /* Hack until /dev/tty works */ ) FILE ‘logfile; } Idefine stderr logfile ) extern int errno; /* Open the named pipes. This routine will block until a POSIX client int NamedPipeln, NamedPipeOut; opens the other end. */ char InNameBuf[256], OutNameBuf[256] ; void 0penNamedPipes() void CreateNamedPipesO { { NamedPipeln ■ open(InNameBuf, 0 RD0NLY, 0); int ret; if(NamedPipeln — (-1)) ( fprintf(stderr,"Can't open pipe errno %d\n“,errno) ; InNameBuf[0] = 0; exit(l); OutNameBuf[0] * 0; ) strcat(InNameBuf, NAMED_PIPE_PATH) ; NamedPipeOut = open(OutNameBuf, 0 WR0NLY, 0); Listing 1 continued buf, size, &numxfer, 0)) { error = GetLastError(); if(error == ERR0R_BR0KEN_PIPE) /* Child exited */ ExitProcess(l); /* Success */ else { fprintf(stderr, “Error stdout %d\n", GetLastErrorO); ExitProcess(O); ) } return(numxfer); ) /* write data to the communications stream */ int WriteStream(char *buf, int size) { int numxfer; if(!WriteFile(hChildStdinWrDup, buf, size, &numxfer, 0)) ( fprintf (stderr, “Error stdin %d\n“, GetLastErrorO); ExitProcess(O); 1 return(numxfer); ) VOID ErrorExit(char ‘message) { fprintf(stderr, message); ExitProcess(O); } /* End of File */ April 1993 Windows/DOS Developer’s Journal - Page 27 Listing 2 continued If(NamedPipeOut == (-1)) { exit(l) ; fprintf(stderr,"Can't open pipe errno %d\n“,errno) ; ) exit(l) ; if(numxfer) ( } ret * ReadStream(buf, numxfer); } retl = write(NamedPipeOut, buf, ret); } ) /* Close the named pipes */ void CloseNamedPipes() { close(NamedPipeln); CloseNamedPipes(); i ) close(NamedPipeOut); } /* read data from the communications stream */ int ReadStream(char *buf, int size) f int numxfer; main() { logfile = fopenC'LOGFILE", "w"); if((numxfer * read(0, buf, size)) «■ (-1)) ( if(logfile == (FILE *)0) ( fprintf(stderr, “Error stdin %d\n”, errno); fprintf(stderr, “Can't create L0GFILE\n“); exit(l); exit(l) ; ) ) return(numxfer) ; \ /* Create the named pipes */ CreateNamedPipes (); /* write data to the communications stream */ int WriteStream(char *buf, int size) /* Perform Server Loop */ ( ServerLoopO ; int numxfer; return(0) ; if((numxfer * write(l, buf, size)) ** (-1)) { ) fprintf(stderr, “Error stdout %d\n“, errno); exit(l) ; /* Loop getting requests from the request } pipe and pass on to our stdout. return(numxfer) ; Read the replies from stdin and pass on to } the reply pipe */ /* End of File */ void ServerLoopO { Listing 3 rpccitc struct Request Header Hd; int ret, retl, numxfer; char buf[5120] ; /* POSIX RPC Client Library, RPCCLT.C */ for (;;) linclude ( linclude OpenNamedPipesQ; linclude for(;;) linclude { linclude "win32psx.h" ret ■ read(NamedPipeIn, (char *)&Hd, sizeof(struct Request Header)); extern int errno; if(ret == (-1)) ( fprintf(stderr,"REQ pipe errno %d\n".errno); int ReadStream(char *buf, int size); exit(l); int WriteStream(char *buf, int size); 1 int ServerlnputHandle; else if(ret ** 0) { int ServerOutputHandle; break; /* EOF */ } void AttachToServer() numxfer = Hd.rh size; ( WriteStream((char *)&Hd, ret); char InNameBuf[256], OutNameBuf[256]; if(numxfer) ( ret ■ read(NamedPipeIn, buf, numxfer); InNameBuf[0] = 0; WriteStream(buf, ret); OutNameBuf[0] ■ 0; ) strcat(InNameBuf, NAMED PIPE PATH); strcat(OutNameBuf, NAMED PIPE PATH); /* Get reply from WIN32 server */ strcat(InNameBuf, “RPC REQ"); ret * ReadStream((char *)&Hd, strcat(0utNameBuf, “RPC REP“); sizeof(struct Request_Header)); numxfer = Hd.rh_size; ServerOutputHandle = open(InNameBuf, 0 WRONLY, 0); retl = write(NamedPipeOut, (char *)&Hd, if(ServerOutputHandle == (-1)) { sizeof(struct Request Header)); fprintf(stderr, “Can't open pipe %d\n“,errno); if(retl == (-1)) ( exit(l); fprintf(stderr,"REP pipe errno %d\n",errno); Page 28 — Windows/DOS Developer’s Journal April 1993 example applications to measure RPC performance over the link. The next two programs are the smallest and are example POSIX client programs. These call routines are exported from the rpcclt.c library to cause Win32SVR to perform the func¬ tion on their behalf, psxclt.c (Listing 5) requests Win32 to execute the user-supplied command line to demonstrate how a POSIX program can execute non-POSIX applications. You can even start up Windows 3.1 and DOS applications from POSIX. rpctime.c (Listing 6) measures the performance of the RPC framework on a given system. A 33Mhz 80386 can execute 83 round-trip RPCs per second. This is not bad given that the requests must be forwarded to Win32 by the POSIX server program, and it will get better once direct communication is possible. The program takes a single parameter, the number of RPC calls to make. You may have to set this to a higher number to get a more accurate reading on faster machines. Limitations Since the POSIX client program is asking another program to perform the request on its behalf, you cannot use any Win32 services that modify the context of the caller —you can only use services that can be represented as "pure” functions without any side effects. For example, you can use the Win¬ dows Sockets API to construct a (somewhat) UNIX-compatible BSD Sockets interface that is available to POSIX applications. Since the interfaces are based on reading and writing mes¬ sages, they can be implemented as pure functions. Listing 3 continued ) ServerlnputHandle » open(OutNameBuf, 0_RD0NLY, 0); if(ServerlnputHandle — (-1)) { fprintf(stderr, "Can't open pipe %d\n“,errno); exit(l); } 1 /* Send a N00P RPC */ int NoopRPCQ ( struct Request_Header Hd; int numxfer; Hd.rh_type = RPC_REQUEST; Hd.rh_hdrsize = sizeof(struct Request_Header); Hd.rh_size * 0; Hd.rh_chan ■ 1; Hd.rh_request = RPC_N00P; WriteStream((char *)&Hd, sizeof(struct Request_Header)); numxfer * ReadStream((char *)&Hd, sizeof(struct Request_Header)); if(Hd.rh_type != RPCREPLY) ( fprintf (stderr, "Not an RPC REPLYW); return(O); ) return(l); ) -^^Windows-based It) IfOW Programmer’s editor Features • Instant access to help for SDK, ANSI C, MS/C, MFC • Grep built in • Multiple-object seardh/replace • One-button cut and paste * Customizable accelerators and menus * Edit huge files * Per-window fonts • Instant access to program functions and header files • Keyboard and mouse recorder • C and C++ support • Supports drag-and-drop • Common source for DOS and NT • Uses MDI, common dialogs, 3-D controls • Written in C using a hierarchy of window classes, including a cached text editor class * Mega undo/redo • Source includes Programming Windows with Class and Speed $5 demo, $49.95 binaiy, $ 179.95 source Call 617/738-1516 to order Blossom Software One Kendall Sq., Bldg 600 Cambridge, MA 02139 Fax: 617 / 566-4936 Also ask about our script-driven Windows Install program for DOS and NT, just $49.95 for source. □ Request 146 on Reader Service Card □ April 1993 Windows/DOS Developer’s Journal — Page 29 An example of something that would not work is to use the Win32 function CreateFileMappingf) to emulate a subset of the UNIX rnapO file-mapping function. This is because CreateFileMappingf) would create the mapping in the con¬ text of the Win32 server process, not in the POSIX client. The Listing 3 continued I* Have WIN32 run a command line */ int SystemRPC(char *cmd) { struct Request_Header Hd; int numxfer, exitstatus; Hd.rh_type = RPC_REQUEST; Hd.rh_hdrsize « sizeof(struct Request_Header); Hd.rh_size - strlen(cmd) + 1; Hd.rh_chan = 1; Hd.rh_request * RPC_RUN_SHELL_CMD_SYNC; WriteStream((char *)&Hd, sizeof(struct Request_Header)); WriteStream(cmd, strlen(cmd) + 1); /* wait for the reply */ numxfer » ReadStreamf(char *)&Hd, sizeof(struct Request_Header)); if(Hd.rh_type != RPC_REPLY) { fprintf(stderr, "Not RPC REPLY\n“); exit(l); } else { if((Hd.rh_size «« 0) && (Hd.rh_request »» 0)) { /* error running command or creating process */ return(1); } else if(Hd.rh_size != 4) ( fprintf(stderr, "Reply not 4 bytes\n“); exit(l); } ReadStream((char *)&exitstatus, 4); } return(exitstatus); } /* read data from the communications stream */ int ReadStream(char *buf, int size) { int numxfer; if((numxfer = read($erverInputHandle, buf, size)) ■■ (- 0 ) { fprintf(stderr,“Error read Child Stdin,%d\n“, errno); exit(l); ) return(numxfer); ) /* write data to the communications stream */ int WriteStream(char *buf, int size) { int numxfer; if((numxfer * write(ServerOutputHandle, buf, size)) -- (-D)( fprintf(stderr, “Error stdout %d\n“, errno); exit(l); } return(numxfer); ) /* End of File *7 results of the call can be returned to POSIX, but the effect would not be available. Any attempt by the POSIX client process to access the memory address returned would result in a page fault. You may notice that handles returned from created objects are actually in the context of the Win32 process, not the POSIX client This still works out because the handle's value can be passed to the POSIX client, which then provides it on every service request call. Any services that imply a handle or rely on inheritance will not work for the same reasons as CreateFileMappingf). Future Directions In order to support multiple POSIX clients at the same time, the POSIX server and client library could create a “lock” file to prevent an application from using a POSIX named pipe that is in use by another application. This file can be created with a call such as: creat(“PIPEO.LCK", 0_EXCL | 0_RD0NLY) This is guaranteed to be an atomic operation on all POSIX sys¬ tems and would prevent two programs from trying to use the same pipe. If a given pipe name is busy, then another name could be tried. Another approach would be to have the initial server first create a main request pipe, then allow every POSIX client to Listing 4 win32psx.h /* WIN32PSX.H Header file that defines the data structures and packet types used for sending requests from POSIX to WIN32 server process. */ struct Request_Header { unsigned char rh_type, Idefine RPC_REQUEST 1 Idefine RPC_REPLY 2 rh_hdrsize, /* Sizeof(Request_Header)*/ rh_pad0, rh_padl; /* alignment */ long rh_size, /* Size of user data */ rh_chan, /* unique ID */ rh_request; /* function request */ /* The data of rh_size is sent after the header */ ); /* Send a NULL RPC request and return TRUE status */ int NoopRPCQ; Idefine RPC_N00P 1 /* Request WIN32SRV to run the command line, wait, then return the exit status. */ int SystemRPC(char *command_line); Idefine RPC_RUN_SHELL_CMD_SYNC 2 /* Connect to the server */ void AttachToServer(); /* Path to the named pipes for POSIX */ Idefine NAMED_PIPE_PATH /* End of File */ Page 30 - Windows/DOS Developer’s Journal April 1993 use this pipe to request that the Win32 server start a new POSIX server for it. The Win32 server can then return the name of a new dedicated pipe for the RPC client to open. In this case, you would use the lock files to prevent contention on the main request pipe. If a client fails to get the lock file, it can wait until the current requester is finished. The wait would be relatively short, since it would last only for the dura¬ tion of the startup of another POSIX server, rather than for the entire POSIX client application's execution time (as is currently the case). When Microsoft fixes the /dev/tty bug, then the rpcclt.c library can use the dup() technique described earlier to pro¬ vide direct access to the Win32 server without having to use the intermediate POSIX server. This should at least double the RPC performance by cutting in half the number of process switches required to send a request. Also, once Microsoft documents how to write new transport providers for MS RPC, it will be possible to write one that would allow standard MIDL to construct the client and server stubs for the applica¬ tions. The server section of the Win32SVR would then use the supplied MIDL-generated server routines. Conclusion The real solution would be for Microsoft to extend the POSIX subsystem to allow support for common UNIX applica¬ tions. The November 23rd and December 14th issues of Unigram X report that Microsoft will eventually make available the internal NT APIs that allow the construction of new sub¬ systems. With this information, third parties could develop a Listing 5 psxclt.c /* Example POSIX Client Program, PSXCLT.C */ #include linclude linclude "win32psx.h“ extern int errno; main(int ac, char **av) { /* Attach to the POSIX gateway to WIN32 */ AttachToServer(); /* Send the Noop RPC to WIN32 */ NoopRPCf); /* Send a remote command execute request to WIN32 */ if(ac ■■ 1) SystemRPC(“cl386"); else SystemRPC(av[l]); return(0); ) /* End of File */ Windows Tools Development ToolsKan For C/C++/Pascal Now also available in Visual Basic 3D Chart -Over 30 of 2D & 3D Chari styles -Rotation & Scrolling -Supports printing & clipboard Status Bar -Auto scrolled text -Stretchable field width -Colored progress bar -Show date/time & key states Toolbox -Creates buttons from bitmaps or text -Supports sc rolling -3D buttons w/ color customization -Single/ multiple & no-state button groups Table -Column & row split windows -Multiple row & column selections -Check boxes/ radio buttons/ bitmaps/ editable & combobox column -Input Validation - Color customization B__!£-***___._ ■ lifraiirT’T ■n.-jt‘*t! »r Ribbon / Icon Bar -3D items w/ color customization -Supports combobox, text & buttons Field Validation -Validates date/time/numberfields and "PIC" statements □ SI HI n n o Q n . o a ^ ri 'MBS [■HWII AH with source. Royalties free. 30-Day money back guarantee. • • Consulting & Contract Programming Available • • Kansmen Corporation Tel: (408) 988-0634 Fax: (408) 988-0639 □ Request 109 on Reader Service Card □ GET IT! Do you need WYSIWYG Text Processing for your WINDOWS Application? Just get the TX Text-Control and the 1C Image-control DLLs for changing your DOS applications to high quality WINDOWS software with such features as - Multiple fonts - Paragraph formatting - Zooming - Integration of Images o I GET YOUR FREE DEMO TODAY! | Call 203-521-0881 (USA or Canada) The Aristos Company, 957 Farmington Avenue ^ West Hartford, CT 06107, Phone 203-521 -0881 Fax 203-561 -2045, CompuServe 73020,2101 1 Elsewhere contact -§ DBS GmbH, Fahrenheitstrasse 1 * 2800 Bremen 33, Germany Phone+49421 / 2208-161 Fax +49421 / 2208-273 CompuServe 100013,115 □ Request 142 on Reader Service Card □ Windows/DOS Developer’s Journal - Page 31 O April 1993 Listing 6 rpctime.c /* RPC Client Program (Timer), RPCTIME.C */ linclude /* Attach to the P0SIX server that is our gateway to WIN32 */ #include AttachToServerO; #include #include begintime = time((time t *) 0); linclude /* Send the Noop RPC to the WIN32 Server */ #include "win32psx.h“ extern int errno; for(count=0; count g 5 \ WINDOWS/DOS — 1 DEVELOPER’S JOURNAL library TTie C Users Journal & Windows/DOS Developer’s Journal CUMULATIVE I INDEX 1988-1991 THE KNOWLEDGE IS THERE. THE POWER IS YOURS! ACCESS IT QUICKLY! You already know the depth of coverage The C Users Journal and Windows/DOS Developer’s Journal put in each article. Now you can easily find 4 years worth of information (by subject) in seconds. ORDER TODAY! 1601 W. 23rd St., Ste. 200, Lawrence, KS 66046 913-841-1631 or FAX 913-841-2624 Page 42 - Windows/DOS Developer’s Journal April 1993 password-required resource without going through the manual dialog-box procedure. The WFWG SDK does provide several dialog-box-driven calls to manage security and passwords. First, the I_AutoLogon() function presents the user name and password login dialog box normally seen during WFWG startup. A parameter tells it whether or not to force the user to log in. If the user logs in, the function will both unlock the password cache and restore persistent connections. I_Logoff() performs the reverse operation. The IJChangeCachePasswordf) function puts up the dialog box allowing you to change your WFWG login password. Since this password is the password cache encryption key, presumably this function will also rewrite the password cache file. The I_ChangePassword() function lets you change your password only on the MS LAN Manager server; it is not in¬ tended to work on any other type of network. WOSA, MAIL, and SMAPI The Microsoft Messaging Application Programming interface (MAPI) specifies how applications can create, manipu¬ late, transfer, and store messages. MAPI messages are true e-mail messages and have no relationship with Windows messages handled by SendMessage () or any other SDK function. MAPI has been packaged as part of a larger add-on API known as the Windows Open Services Architecture (WOSA). The two other main components of WOSA are Win¬ dows Sockets and the Open DataBase Consortium API (ODBC). WFWG provides neither of these latter WOSA com¬ ponents. Currently, Windows Sockets is only available on TCP/IP protocol net¬ works (e.g., PC-NFS, B&W NFS, etc.). ODBC products are available from third- party vendors as regular Windows 3.1 add-on DLLs. With the introduction of WFWG, the original monolithic MAPI specification was subdivided into Simple MAPI and Extended MAPI. Simple MAPI (or SMAPI) provides just enough functionality to send, receive, and address mail. The Ex¬ tended MAPI encompasses “the genera¬ tion and handling of large and/or com¬ plex messages, large numbers of received messages, and complex ad¬ dressing information" (“MAPI 1.0: Simple MAPI,” p. 1). The WFWG SDK provides only the SMAPI level of services (see Fig¬ ure 14). In this discussion, I cover a few of the most important of these. With the off-the-shelf WFWG run¬ time, all mail is limited to the local Figure 15 MAPILogonQ Session Parameters Flags Constant/Bitmask Value MAPI LOGON UI 0x01 MAPI NEW SESSION 0x02 MAPI FORCE DOWNLOAD 0X04 MAPI ALLOW OTHERS 0X08 MAPI EXPLICIT PROFILE 0x10 MAPI_EXTENDED 0x20 workgroup. If you want to connect multiple workgroups or move mail offsite through a Message Handling Service (MHS) or LANGUAGE -lint 5.0 presents C Bug # 632 typedef int NUMBER; typedef int COUNT; COUNT index( NUMBER a[], COUNT n, NUMBER m ) { COUNT i; for( i = 0; i < n; i++ ) if( m == a[ i ] ) return m; return n; } This function operates upon an array of n NUMBER's. Can you ferret out the inconsistency? Hint: this passes Lint without complaint unless you use strong type checking. (For example: -strong (Ac )). Call if you need help. Refer to Bug #632. PC-lint will catch this and many other C bugs. Unlike your compiler, PC-lint looks across all modules of your application for bugs and inconsistencies. More than 330 messages. Includes optional Strong Type Checking and flow of control analysis. More than 105 options for complete customization. Suppress error messages, locally or globally, by symbol name, by message number, by filename, etc. Check for portability problems. Alter size of scalars. Adjust format of error messages. Automatically generate ANSI prototypes for your K&R functions. Attn: Power users with huge programs. PC-lint 386 uses DOS Extender Technology to access the full storage and flat model speed of your 386. PC-lint 386-$239 PC-lint DOS - OS/2 - $139 Mainframe & Mini Programmers FlexeLint in obfuscated source form , is available for Unix, OS-9, VAX/VMS, QNX, IBM VM/MVS, etc. Requires only k&R C to compile but supports ANSI. Call for pricing. PA add 6% sales tax. Qlmptil S®ftwargetState(sfVisible)) { aControl->setState(sfVisible.True); aControl->options |-ofSelectable; } } else if(aControl->getState(sfVisible)) { // note that we FIRST disable ofSelectable, and THEN make the view // invisible aControl->options &=~ofSelectable; aControl->setState(sfVisible,False); } ) TListViewer Problems TListViewer is one of the more use¬ ful Turbo Vision classes. Unfortunately, it’s also one of the most buggy to use. This section lists some of the quirks. A TListViewer is crippled if the vertical scroll bar is missing. If you create a TListViewer without a vertical scroll bar, then focus I tern and set- Range will never redraw the updated view. This is because TListViewer uses the cmScrollbarChanged message to do this. A solution is to define a TMyList- Viewer with the setRonge and focus- item functions like this: Concerning traps: many are due to bugs in Turbo Vision. Of course, it’s easy to correct them — just change the source codel But if many programmers use the same library, chang¬ ing the library source code can be dangerous. How can you guarantee consistency? Until the bugs are officially fixed (i.e., Borland fixes them in a future release), it’s better to use C++ inheritance to derive a new class from a buggy class and void TMyListViewer::setRange(short aRange) ( TListViewer::setRange(aRange); if(vScrollBar==0) { if(focused>range) focused=0; drawViewO; ) } Rock-Solid Support For Software Development Btrv++ $349 Exploit the power of object-oriented programming to achieve order-of-magnitude productivity gains over the use of Btrieve development tools alone! A dozen classes make developing single or multi-user LAN applications for DOS, Windows, and OS/2 a snap! Source for Btrv++ is included. Royalty free. Only Btrvgen++. $229 Combine the power of object-oriented development with state-of-the-art code generation technology! Use Btrvgen++ to generate thousands of lines of C++ class library code - automatically! Inherent referential integrity checking, cascading deletes, relational joins, access to the schema through meta-tables. Requires Btrv++. Btrvgen++ utilities allow you to import and export .DDF file format. Access your Btrvgen++ schema from Xtrieve, Netware SQL, any program that uses .DDF format! Special bundle price: Btrv++ and Btrvgen++ for $449 (save $129). Call for upgrade price. VBtrv $249 Control And Function Libraries For Novell Btrieve Under Visual Basic For Windows Or MS-DOS! Visual Basic Developers: Discover how easy it can be to use Novell’s legendary Btrieve File Manager under Visual Basic For Windows! Our full-featured Toolbox controls and function-call library offer access to the full power of Btrieve v5.1, and a lot more! Btrieve development becomes a "point and click" activity with VBtrv! It’s never been easier! Includes complete documentation and sample programs. Royalty free. NEW! Function-call library also available for Visual Basic For MS-DOS! Classic Software, Incorporated "I 3542 Pheasant Run Circle Ste. 8. Ann Arbor Ml 48108 -L| 313-677-0732 (Voice/FAX) □ Request 143 on Reader Service Card □ MS dos System Programming 2nd Edition Edited by Robert Ward NOW-You can get the informa¬ tion most programmers don’t even know about. PLUS -Gain access to a critical bibliography that will become an indispensible resource to you. HIGHLY TECHNICAL HIGHLY FOCUSED MS-dos system programming Every entry is written by working programmers for working programmers. In¬ cluded are compiler- specific insights that will save you hours of work. Find out how to exploit spe¬ cial Turbo C features to simplify device drivers. Plus a bibliography designed to help the serious program¬ mer develop a personal library of MS-dos literature. Released July 1991, 240 pp. ISBN 0-923667-20-2 DIRECTLY Windows/DOS FROM Q' edited by ROBERT WARD Nitty Gritty Coverage on These How-to Topics Critical Error Handling Customizing the DOS Boot Strap Interrupt-Driven I/O Manipulating Environmental Variables Event Timing Writing TSRs Controlling the Disk Hardware Writing Device Drivers 2 I DEVELOPER'S JOURNAL 913 - 841-1631 FAX: 913-841-2624 $ 24 95 r: Page 50 — Windows/DOS Developer’s Journal April 1993 void TMyListViewer::focusItem(short item) { TListViewer::focusItem(item); if(vScrol1Bar==0) drawView(); } Double-clicking within a TListViewer does not select the item. The reason is simple: the check for double click is done at the exit of a do-while loop: do { } whilef mouseEvent( event, evMouseMove | evMouseAuto ) ); focusItemNum( newltem ); if( event.mouse.doubleclick && range > focused ) selectltemf focused ); clearEventf event ); If the event on entry was an evMouseDown with doubleclick set, the next call to mouseEvent will clear the doubleclick. So it turns out that the doubleclick will never be seen, and therefore the cmListltemSelected message will not be generated on a double click. A double-click operation indicates the user has made a choice, so it's pointless to keep looping for mouse moves. The solution is to remove the check for doubleclick and put the following in the do-while loop just before the makeLocal call. if( event.mouse.doubleclick && range > focused ) ( selectltem( focused ); break; } Note that the THistoryViewer (which inherits from TList¬ Viewer) gets around this bug by checking for the double click before calling TListViewer: :handleEvent, instead of using the cmListltemSelected message. TListViewer documentation contains quirks. The documentation indicates that TListViewer::focusltem uses TListViewer::focusItemNum internally. This is wrong: it's the other way around. TListViewer::focusItemNum performs some range checking on its parameter and then passes control Figure 2 validView as Utility Function TView* validView(TView* p) { if( P == 0 ) return 0; if( lowMemoryO ) { TObject::destroy( p ); TProgram::application->outOfMemory(); return 0; } if( !p->valid( cmValid ) ) ( TObject::destroy( p ); return 0; } return p; TCP/IP for Windows Requires only 6KB of base memory Implemented as 100% Windows DLL (not a TSR) ■ All applications are both client and server ■ Works concurrently with Netware, LAN Manager, Vines etc. ■ Up to 64 concurrent sessions Developer Tools: Windows Socket API Berkeley 4.3 Socket API ONC RPC/XDR WinSNMP API Applications: TELNET (VT100,VT220),TN3270, FTP, TFTP SMTP/Mail, POP2, SNMP, PING, BIND, Statistics, and Custom Extensible SNMP Agent ■ Includes MIBII, Workstation,Windows and DOS agents ■ Dynamic registration of multipleagents, managers, and proxies ■ WinSNMP API developers kit available ■ Compatible with any SNMP manager ■ Free with NEWT, Chameleon, and ChameleonAWS' NFS Client/Server ■ Network drives are mounted from within Windows ■ Network printing in the background ■ Up to 24 network drives ■ Requires only 6KB of base memory ■ Included in Chameleon/VFS For overnight delivery call: ^MiMANAGE" (408) 973-7171 20823 Stevens Creek Blvd., Cupertino, CA 95014 USA Fax (408) 257-6405 □ Request 131 on Reader Service Card □ April 1993 Windows/DOS Developer’s Journal — Page 51 Build better applications now with. . . Platform** Illustrated C by Leor Zolman author of BDS C Discover the WHY and HOW of application design and development in C. Explore the construction of several different applications from start to finish. Chapter after chapter you’ll develop your skills through in-depth tutorial and detailed code. ( $ 39 — with disk) CALL TODAY! 913 - 841-1631 FAX 913-841-2624 j f' t- i ^MasterCard publications, inc. to focus Item. Keep this in mind, since focus Item does no range checking of its own. The documentation for TList- Viewer::selectltemfshort item) reads: “Selects the item’ th element of the list, then broadcasts this fact to the owning group." This is misleading. selectltem only broadcasts cmList- ItemSelected. It does not select the item’ th element. You have to do your own selection either by handling the cmListltemSelected event, or by redefining selectltem. In addition, if you want the selection to be seen, you should also redefine T- ListViewer::isSelected(short item). By default, this function returns True only if item^focused (meaning the focused item is always selected by default). It should return True only for those items that selectltem selected. Unwanted recursion in TList¬ Viewer: tfocusltem. If you compile Turbo Vision with debug information and trace through focus I tern, you will be surprised to learn that each call to focus I tern generates an extra call to the same function (when a vertical scroll bar is present). Here is what hap¬ pens: • You call TListViewer: tfocusltem. • TListViewer: tfocusltem calls vScrollBar->setValue() to update its scroll bar. • TScrollbar: tsetValue calls TScrollbar: tsetParams. • If the new value is different, TScrollBar: tsetParams calls TScrollBar: tscrol IDrawf). Figure 3 Fixing the “" Problem class TMylistviewer: public TListViewer { public: protected: void draw(); }; /* void TMyListviewer::draw() EFFECT see tv. Sadly, starting from tv ver 1.3, the list viewers display when no elements are to be viewed. */ void TMyListviewer::draw() { if(rangel-O) TListViewer::draw(); el se { ushort normal Col or; if( (state&(sfSelected | sfActive)) == (sfSelected | sfActive)) normal Col or = getColor(l); else normalColor = getColor(2); for(int i=0;i“,normal Col or); // write the line writeLine( 0, i, size.x, 1, b); ) } } Page 52 — Windows/DOS Developer's Journal April 1993 • TScrollBar: :scrollDraw() broadcasts the message cmScrol IBarChanged. • This message is received in TListViewer: :handleEvent. • TListViewer::handleEvent calls focusItemNumf). • TListViewer::focusItemNumf) calls TListViewer::focusItem. Note the recursion. This recursion stops only because the second call to vScrollBar->setValue() will be with the same value, so the cm- ScrollbarChanged message will not be generated again. TWindow::close() Coding Considered Harmful TListViewer is not the only class with problems you might encounter. This is how TUindow::close() is imple¬ mented: void TWindow::close() { frame = 0; // so we don't try to use // the frame after it's been deleted if( valid( cmClose ) ) destroy( this ); ) Listing 1 A Flexible messageBoxQ Function Idefine Uses_TDialog Idefine Uses_TStaticText Idefine Uses_TButton Idefine Uses_TProgram Idefine Uses_TDeskTop linclude linclude linclude linclude /* static TRect getTextDimensions(const char buffer[]) PARAMETER buffer buffer containing message text to display in the messageBox function RETURNS Bounding rectangle of the text. The rectangle always has topleft ( 0 , 0 ) While computing the bounding rectangle, '\n' will force a new line and '\3' will force the line to be centered on the next line */ static TRect getTextDimensions(const char buffer[]) { int i=0; int rows=l; int maxCols=0; int cols=0; But what happens if valid (cmClose) returns False) Then the window will not be closed. But because of: frame = 0; you lose the pointer to the frame! Surely the correct code would be: (continued on page 54) Figure 4 Code Fragment from handleEventQ ( ushort result=0; do ( else if( action == doSelect ) result ■ current->command; if( result != 0 && commandEnabled(result) ) ( action = doReturn; clearEvent(e); ) } while(action != doReturn ); return result; } I ADONIS Micro-Software RS232-Toolkit, SuperCom 2.1 for DOS or Windows for MS C/C++, Turbo/Borland C/C++, Turbo Pascal, VisualBasic SuperCom is the development tool for exacting serial comm¬ unication software. That means high data security and fast transmission speed. SuperCom is fast even in a multitasking operating system like Windows. Interrupt driven: transmission, reception, line status, modem status Buffers to 64K 1 Up to 115,200 bps 1 UARTS: 8250,16450,16550 FIFO 1 Simultaneous COM_1 ,.COM_32 1 Any port address ’ Flow control: RTS/CTS, DTR/DSR, XON/XOFF and user defined 1 Protocols: ASCII, XMODEM, XMODEM/CRC 1 Timer, Ctrl-Break and Exception handling 1 No resident drivers ’ Direct register programming ' Multitasking support (Windows) 386-Technology, Protected Mode Interface (Windows only) Interrupt-Sharing Multiserial board support DigiBoard PC/X, PC/Xe, PC/Xi support Modem support Full source code (C or Pascal and optimized ASM) DLL, interface for VisualBasic (Windows only) Windows 3.x (Real, Standard and Enhanced mode) SuperCom ++ (C++ or Pascal OOP) included Compiler support: C package (Microsoft C/C++, Borland/Turbo C/C++ VisualBasic) Pascal package (Turbo Pascal, VisualBasic) C or Pascal package for DOS $320 C or Pascal package for Windows $430 C or Pascal package for DOS + Windows $570 VISA/MC ADONIS Micro-Software Dipl.-Ing. Kiriakos Georgiadis Hoelderlinstr. 32 D-7133 Maulbronn, Germany Phone: 49/7043/40449 FAX: 49/7043/40440 Fine Line International 7000 Malone Rd, Forestville CA 95436, USA Phone: 1/707-887-3400 FAX: 1/707-887-1015 □ Request 116 on Reader Service Card □ Windows/DOS Developer's Journal — Page 53 April 1993 Listing 1 continued while(buffer[i]!=EOS) { if(buffer[i]=='\3' || buffer[i]==‘\n') { if(cols>maxCols) maxCols=cols; cols=0; ++rows; } else ++cols; ++i; } if(cols>maxCols) maxCols=cols; TRect r; r.a.x=r.a.y=0; r.b.x=maxCols; r.b.y=rows; return r; } /* ushort messageBox(ushort aOptions,const char title[].const char fmt[],... ) PARAMETERS aOptions message box options, analogous to the TV messageBox title message box title fmt format string (like in printf) parameters for format string void TWindow: :dose() { if( valid( cmClose ) ) { frame ■ 0; // so we don't try to use // the frame after it's been deleted destroy( this ); } } And even then, I doubt if framed is necessary, since destroyf) calls Shut- Down () and shutDownf) in TUindow is redefined to set frame to zero. Using min and max Can Be Dangerous Turbo Vision defines min and max as follows: inline int min( int a, int b ) { return (a>b) ? b : a; ) inline int max( int a, int b ) ( return (a inline T min( T a, T b ) { return (a>b) ? b : a; } tempiate inline T max( T a, T b ) { return (a Used by AT&T, Bell Canada, IBM, Intel, and thousands more ■ and now a special price!! ,The Software Factory ' O* EZ-INSTALL ....just $199 13612 Midway Road, Suite 246 Dallas, TX 75244 USA (214) 490-0835 Visa/Mastercard AMEXIDiscover Shipping $5 (US^ FAX: (214) 490-9520 Page 54 - Windows/DOS Developer’s Journal April 1993 int i=3; ushort u=40000; cout < min(u,i); The compiler will call the non-template version of min(), since min (ushort, int) cannot be generated, so you should definitely eliminate the Turbo Vision min() and max() definitions. Better still, use the _ TEMPLATES _ directive to keep the old way, should the source be compiled in a compiler that does not support templates. TFileDialog: Strange Validation Check The TFileDialog class has a strange implementation of the valid () function: Boolean TFileDialog::valid(ushort command) { char fName[MAXPATH]; char drivefMAXDRIVE]; char dir[MAXDIR]; char name[MAXFILE]; char ext[MAXEXT]; if( command == 0 ) return True; if( TDialog::valid( command ) ) ) Listing 1 continued RETURNS like the TV messageBox */ ushort messageBox(ushort aOptions,const char title[].const char fmt[],... ) ( // form the text to appear in the message box static char buffer[512]; static const char *buttonName[] = { // Message is a static class holding the title text for // the buttons Message::yesText, Message::noText, Message::okText, Message::cancelText ); static const ushort commandsf] = ( cmYes, cmNo, cmOK, cmCancel }; va_list argptr; va_start(argptr,fmt); vsprintf(buffer,fmt,argptr); va_end(argptr); // compute the bounding rectangle of the resulting text TRect textDimensions=getTextDimensions(buffer); // add some slack space Increase the SPEED, POWER, AND PERFORMANCE of your Windows and DOS applications with Windows/DOS Developer's Journal. Month after month, year after year serious Windows developers turn to our real world solutions. Windows/DOS □ DEVELOPER'S JOURNAL 913-841-1631 FAX: 913-841-2624 c and C++ DOCUMENTATION C-METRir ($59) COMPLEXITY / QUALITY • Calculates cyclomatic path complexity for functions and 'cyclomatic 1 path complexity I ■ Counts lines with comments, code, and C statements system filel nain file2 —sub2 file2 1—sub3 file2 1—sub4 filel —main (recursv) — Ibryl, Ibry2 C-CALL™($69) FUNCTION HIERARCHY ■ Tree-Diagram showing function hierarchy • Table-Of-Contents of functions versus files • Summary and detailed cross-reference of functions C-CMT ($69) FUNCTION COMMENT • Generates and inserts function comment blocks • Can be re-run to update the comment blocks • Retains any user-generated comments while (isize.x + 2; } } // adjust the width if too small to fit the title if(title!=NULL) { size_t titleLen=strlen(title)+6; if(textDimensions.b.xsetState(sfVisible,Fal se); However, that does not work as in¬ tended. After calling this function (either with False or True as last parameter), the focus is reset to the first visible and selectable view in the owner (the dialog box). This happens because the last thing setState() does if called with sfVisible is: /* view.cpp line 677 */ if( (options & ofSelectable) != 0 ) owner->resetCurrent(); A view can only be made current if it's visible and selected. If a selectable view Listing 1 continued II the message box, which will be centered in the deskTop view // We should check if the rectangle does not exceed the deskTop if(textDimensions.b.y>=deskTop->size.y) textDimensions.b.y=deskTop->size.y; if(textDimensions.b.x>=deskTop->size.x) textDimensions.b.x=deskTop->size.x; // create the dialog box TDialog *dialog=new TDialog(textDimensions, title); if (dialog==NULL) return cmCancel; // make sure it's centered in the view where we insert it dialog->options|=ofCentered; // add the static text dialog->insert(new TStaticText(TRect(l,l,dialog->size.x-2, dialog->size.y-3).buffer)); // add the buttons x = (dialog->size.x - x) / 2; for(i=0;iinsert(buttonList[i]); buttonList[i]->moveTo(x, dialog->size.y - 3); x += buttonList[i]->size.x + 2; ) // first button should be selected dialog->selectNext(False); // hold the dialog ushort ccode = TProgram::deskTop->execView(TProgram::application-> validView(dialog)); // remove it TObject::destroy( dialog ); // and return the result code return ccode; ) ' q $ zr Q. ° n q 3 a ^ Q) Q) co =3 * 1 v QJ P X O CO c" CO /f> Z n —x r—t -> ri i£. O N O W — QJ_ ^ q. 8 O co z “ O Cl | is ® I OO 21 QJ O |. & CD < 2 I to =r 00 lx o m Q. 2 QJ l 3- CD Q- QJ ft n < n G) r» S & § $ l—t —t ft) 00 c to n' Q) O U => e ^ co co to <- CD C Q_ . CO - ^CQ ro § ^ E a or o n CD o CO 3 Q) X :d > f S' OQ 3 Q ft a s- QJ ft 5 ■ O § a °- cs 2 A, ^ ^ (S) 01 QJ =! a o 3 ro •< O ■o O to 00 O' ZJ QJ 3 o 3 o 3 5' =T Q. 3 | oo TJ ■D OQ Ql I —|- cn §, 3 <* QJ S’ m rs CjQ w O ■to-3 CO OS Cn — a Q) QJ ZJ Q. a. o CT c CXJ CQ zj' CQ »—b o o April 1993 Windows/DOS Developer’s Journal — Page 57 (malloc + GlobalAlloc) < SlIiartHCcip Listing 2 A Better 7 Window Class Idefine Uses_TProgram #define Uses_TDeskTop Idefine Uses_TWindow Idefine Uses_TEvent Idefine Uses_TFrame linclude linclude linclude // new cmXXXX constants const ushort cmWindowHasNum=9500; // (int windowNum) for TBaseWindows const ushort cmReplaceTitle=9600; // (char *aTitle) for TBaseWindows class TBaseWindow: public TWindow { public: TBaseWindow(const char aTitle[].short aNumber); int replaceTitle(const char format[],...); protected: void handleEvent(TEvent &event); void setState(ushort aState, Boolean enable): private: Boolean handleBroadcast(TEvent Jevent); Boolean handleCommand(TEvent ievent); ): /* TBaseWindow::TBaseWindow(const char aTitle[].short aNumber) PARAMETERS aTitle window title aNumber window number (assumed to be !*wnNoNumber) EFFECT constructor The window position is determined by its number and the desktop size. */ TBaseWindow::TBaseWindow(const char aTi tl e[] .short aNumber) :TWindow(TRect((aNumber-l) H 10,(aNumber-1) % lO.TProgram::deskTop->size.x, TProgram::deskTop->size.y).aTitle,aNumber), TWindowlnit(TBaseWindow::initFrame) ( ) /* void TBaseWindow::handleEvent(TEvent &event) PARAMETERS event event to handle EFFECT intercepts the cmWindowHasNum broadcast. This broadcast is used when the application wants to enquire if there's a window with a specific number. This mechanism allows for the reuse of window numbers. */ void TBaseWindow::handleEvent(TEvent &event) ( TWindow::handleEvent(event); Boolean clearIt=False; // will be set to True if clearEvent should be called switch(event.what) ( case evBroadcast: clearlt'handleBroadcast(event); break; becomes invisible, and if it is the cur¬ rent view, the focus changes to the first selectable visible view of the owner, which is exactly what the above code does. There are two problems with this. First, the focus is reset even when the control becomes visible. Second, the focus is reset even when the current view is not the view that is being made invisible, it is therefore tempting to change line 677 to: if((options & ofSelectable) && lenable && owner->current==this) owner->resetCurrent(); This resets the focus only if the view is selectable and it becomes invisible and it is the current view, if it is impractical to change the source code, you could always write a small member function, as shown in Figure 1. validView Should Be a Utility Function If you create a view somewhere in a member function of a class which is not a direct descendant of TProgram and you want to use validView() to check for view validity, you have to write an ugliness like this: Idefine TProgram linclude ...TProgram::application->validView(...)... It would be more natural to make val idView() a utility function. This would encourage its use for checking creation of views. It is likely that Borland made valid- View() a non-static member function of TProgram because of the call to the vir¬ tual function outOfMemory(). But this call can easily be replaced by T- Program::application->outOfMemory () inside val idViewf). The function can then be moved out of TProgram and becomes generally available immedi¬ ately. So validView() would be as shown in Figure 2 and its prototype could be moved into util.h, which is included whenever tv.h is included. International Problems Did you ever get a call from a French client asking (in French, of course): “I have nothing in my list, but why does this strange word suddenly appear?” Why did Borland add this to Page 58 — Windows/DOS Developer’s Journal April 1993 Listing 2 continued case evComraand: clearTt=handleCommand(event); break; } if(clearlt) cl earEvent(event); ) /* Boolean TBaseWindow::handleBroadcast(TEvent &event) PARAMETERS event broadcast event to handle EFFECT handles broadcast events. Currently only cmWindowHasNum (respond if this window has the requested window number. RETURNS True if event handled False if not */ Boolean TBaseWindow::handleBroadcast(TEvent &event) { return (Boolean)(event.message.command==cmWindowHasNum && event.message.infoInt==number && (options & ofSelectable)); ) /* Boolean TBaseWindow::handleCommand(TEvent &event) PARAMETERS event command event to handle EFFECT handles command events. Currently only cmReplaceTitle, replacing the window title by whatever string infoPtr points to RETURNS True if event handled False if not */ Boolean TBaseWindow::handleCommand(TEvent &event) ( i f(event.message.command==cmReplaceTi11e) { delete (char *)title; title=newStr((char *)event.message.infoPtr); // redraw the frame (will also redraw the title) frame->drawView(); return True; ) else return False; } /* void TBaseWindow::setState(ushort aState, Boolean enable) PARAMETERS aState enable EFFECT see tv. Overridden to enable specific window commands like cascade.tile and window list */ sute^LATE^scrif 1 Graphics S_PRINT Would Text and Graphic Printer support for over 850 printers give you an edge? By including SLATE with Graphics, you can print Text and Graphics on over 850 printers. Immediately! Painlessly! You can use SLATE in your product with no royalties. It gets you out of the printer support business. Make your product more functional and competitive by using SLATE'S advanced text features: • Output to parallel printers, serial printers, DOS files and Novell network printers. • Support proportional fonts and scalable fonts. • Set exact print positions. • Kerning, leading, underlining, and strike through. • Automatic character set conversion. • Print lines and shaded areas (laser printers only), SLATE with Graphics adds advanced graphic printing features: • Print images from the screen, PCX or TIFF files, or custom image systems. • Print lines and shaded areas on all printers. • Scale and Rotate printed image. • Print grey scale and color images. • Intermix text and graphics. SLATE is a C or Basic library of over 170 text printing functions, a Database of over 850 printers, and End User configuration and testing programs. SLATE with Graphics adds over 60 graphic printing functions. Would a User Configurable Report Writer give you a more competitive product? SCRIPT is a full featured Text Formatting library that can be incorporated into your application. SCRIPT uses SLATE as its printer driver. SCRIPT lets you merge text, data, and S_PRINT formatting commands from ASCII files and your application. Enhance your product by taking advantage of SCRIPT'S features: • Allow users to alter document format. • Set exact positions, center, right adjust, and decimal align. • Fill paragraphs from unformatted text. • Add lines, shaded areas, logos, signatures, etc. • Add commands and macros. Call or FAX now for a complete catalog and developer's guide for The Symmetry Group's printer support products. Order SLATE for $299, SLATE with Graphics for $448, or SCRIPT for $199 with our risk free, 30 day return policy. The 800-346-3938 Symmetry po Box 26195 firm in J Columbus, OH 43226, USA 614-431-2667 • FAX 614-431-5734 April 1993 □ Request 333 on Reader Service Card □ Windows/DOS Developer’s Journal — Page 59 Listing 2 continued void TBaseWindow::setState(ushort aState, Boolean enable) { TWindow::setState(aState,enable); if(aState & (sfSelected | sfActive)) { TCommandSet documentCommands; documentCommands += cmTile; documentCommands +■ cmCascade; documentCommands +• cmWindowList; if(enable) enableCommands(documentCommands)j else disableConmands(documentCommands); } ) /* int TBaseWindow::replaceTitle(const char format[],...) PARAMETERS format title format string ... arguments for format string (if any) EFFECT sets the window title to 'format' (formatted like printf). RETURNS number of characters in new title */ int TBaseWindow::replaceTitle(const char format[],...) { va_list argptr; char buffer[128]; va_start(argptr, format): int cnt = vsprintf(buffer, format, argptr): va_end(argptr); delete (char *)title; title=newStr(buffer); // redraw the frame (will also redraw the title) frame->drawView(); return cnt; } The smallest available window number is then determined using the following function: /* short TMyApp::getWindowNum() RETURNS the next available window number. Window numbers of windows that are closed are reused. */ short TMyApp::getWindowNum() { short i=1; whi1e(message(deskTop,evBroadcast,cmWindowHasNum, (void *)(unsigned 1ong)i)!=NULL) ++i; return i; ) /* End of File */ TListviewer in version 1.3? The addi¬ tion is unnecessary and a nuisance in international environments. It is rather weird for a customer to see such a word appear in an all-Dutch or all- French application. Figure 3 shows how I solved this problem. Also, all classes deriving from TList¬ viewer should now derive from TMy- ListViewer. Note that this solves the problem only partially, since other clas¬ ses deriving from TListviewer (T- HistoryViewer, for one) will not be af¬ fected. A second international problem is the fact that TProgram::exitText has been defined as ~Alt-X" Exit. In French, “Exit” is Quitter, which should be Alt-Q, and in Dutch Verlaten or Beein- digen, which should be Alt-V or Alt-B. Unfortunately, the kbAltX code is hard¬ wired on line 225 of tprogram.cpp. It should be made a static variable too, as were most of Turbo Vision literal strings (see the files tv text* .cpp). Finally, it was certainly a good idea to isolate the literal text from message boxes, file save dialogs, and so on, but button sizes and label sizes should be parameterized by the length of the text strings. Some text gets longer when translated (e.g., in French, “OK" becomes Valider and “cancel” becomes an¬ nul er). Flexible messageBox() Wouldn't it be handy to have a mes¬ sage box whose size adjusts according to the string to display, instead of remaining Fixed? Listing 1 shows an al¬ most compatible messageBox(). Note that the getTextDimensions() is a use¬ ful function in itself (to predict the size of a TStaticText, for example). message () Should Be Overloaded? The last parameter of message () is a void *. That's fine, but if you want to pass something else (for example, an int), then you have to use an ugly cast. Why not provide a second message function that would eliminate the cast - or at least lessen the number of times you have to do it —like this: Page 60 - Windows/DOS Developer’s Journal April 1993 void *message(TView ‘receiver, ushort what, ushort command, void ‘infoPtr); void *message(TView ‘receiver, ushort what, ushort command,long infoLong); In addition, you could define void *message(TView ‘receiver, ushort what, ushort command); for those cases where no extra informa¬ tion is needed. Yes, I know there's an ambiguity when passing zero as the last argu¬ ment, since zero can be a long or a NULL pointer, but you should use NULL for pointers anyhow. Also, passing numeric values (char, uchar, short .ushort) to a long relies on the internal representation for getting the value in TMessageEvent correctly. This is non¬ portable, but so are casts like (void*) (long)ch. TSItem Thoughts The constructor of TSItem has two parameters: one for the text, the other for the pointer to the next TSItem (used for chaining TSIterns together, for T- CheckBoxes or TRadioButtons). My sug¬ gestion is, since the last parameter in the last TSItem is always NULL, change the constructor such that this parameter defaults to NULL when omitted: TSItem(char ‘aText,TSItem ‘aNext=NULL); Also, it would be nice to give TSI terns an overloaded “+” operator, so that they can be chained together using addition: insert(new TCheckBoxes(TRect(...), ‘new TSItem("itern ~l~")+ ‘new TSItem("item ~2~)+ ‘new TSItern("item ~3~)); The operator + would be something like: TSItem &operator+(T$Item &first,TSItem Ssecond) { first.next-second; return first; } To neatly clean things up, TClusters should be modified to accept a refer¬ ence to a TSItem instead of a pointer to a TSItem. TMenuBox Pitfalls You can use a TMenuBox as a stan¬ dalone pop-up menu, like this: TMenu ‘menu-new TMenu; ‘menu-... build menu items...; TMenuBox ‘local Menu-new TMenuBox( TRect(...),menu,0); ushort c = TProgram::deskTop-> execView(localMenu); destroy(localMenu); The command returned will be in c. However, the TMenuBox class does not have a destructor. This causes memory leaks, as the menu structure (second parameter of the TMenuBox constructor) is never deallocated. Also the a Pa rent- Menu constructor parameter does not default to 0 (as the documentation claims). And finally, here's a nasty one: a TMenuBox will correctly gray every string whose associated command is disabled. So if you position the menu cursor on a disabled item and press RETURN, nothing will happen (which is correct). However, if you press the ES¬ CAPE key immediately afterwards, the command returned from execView will be your just-disabled commandl Explaining why this is happening is a bit difficult. The real menu processing happens in the TMenuView class — more precisely, in the handleEvent function. Figure 4 shows a code fragment of that function. The reason for the bug is as follows. When the user presses the RETURN key, the action variable is set to doSelect. This causes the result variable (which holds the return value) to be initialized with the command value. What happens next depends on the command enable status. If the com¬ mand is enabled, action is set to do- Return, the while loop exits, and the correct value is returned. If the com¬ mand is disabled, the while loop is not exited, and if the ESCAPE key is pressed, action will be set to doReturn. The while loop exits and result is returned, still containing the value of the disabled command! The final if statement should be rewritten as follows: YOU CAN INSTANTLY 5 YEARS OF INFORMATION FROM The ■■ Users Journal 1 Windows/DOS • Detailed three-level subject index • Each article, letter, and question and answer listed under all appropriate indexing terms • All entries include the title, subjects, author, journal issue and page, and any references to other articles. • Select and print the entries you want SPECIAL OFFER ORDER THE ON-LINE INDEX for $29.95 and receive the printed version of The Cumulative Index, 1988-1991, for an additional $2. ORDER W63D & INDX2 TODAY! 1601 W. 23rd St., Ste. 200 Lawrence, KS 66046 USA 913-841-1631 FAX 913-841-2624 April 1993 □ Request 117 on Reader Service Card □ Windows/DOS Developer’s Journal — Page 61 Figure 6 Code That Ignores NULL Pointers { // create a progress dialog. Could fail because of low memory TView *dialog=validView(new TProgressDialog(...)); // this is OK if dialog==NULL TProgram::deskTop->insert(dialog); .. perform some operations // remove progress dialog box. Catch! TProgram::deskTop->remove(dialog); // and destroy it (harmless if dialog—NULL) TObject::destroy(dialog); } if( result !* 0 && commandEnabled(result) ) ( action = doReturn; clearEvent(e); ) el se result=0; but that means modifying the source code. You can solve the first two bugs by deriving a class from TMenuBox, as shown in Figure 5. Now the TMenu structure will be properly destroyed on exit. The last bug described forces you to do some extra checking on the return value of exec- View, as follows: if(c!=0 && commandEnabled(c)) ( // it's really a valid command! } A More Flexible TWindow I found that most of the TWindows inserted in the deskTop need the following properties: • they must be cascadable and dleable • their position should be determined by their window num¬ ber and their size should span the entire deskTop (this creates “naturally cascading” windows) • their title should be replaceable (for example, if you want to have a title like “Law Document 234b is (C:\DOCS\SAVEDOC.TXT)’’ where the filename between parentheses can change) — currently, the title is allocated in the TWindow constructor and that’s it • window numbers should be reusable: usually, window numbers are assigned using a static variable that is incre¬ mented each time, but this means that windows will stop carrying window numbers after the 10th window has been created (even if they are destroyed). Listing 2 shows a TBaseWindow class derived from TWindow that satisfies all the above properties. Boston University Corporate Education Center Proudly Presents THE INTERNATIONAL DEVELOPERS CONFERENCE FOR WINDOWS APRIL 26-30,1993 BOSTON, MA WNWD BOSTON UNIVERSITY CORPORATE EDUCATION CENTER Attend and learn how to take advantage of Windows features, learn pitfalls to avoid, polish your Windows programming skills, learn undocumented tips and techniques, touch base with movers and shakers in the field, and much more. PROGRAM FEATURES ■ Leading Edge Topics ■ Evening "Chalk-Talk" Sessions ■ 10 Tutorials ■ 24 Sessions ■ Product Information Workshops ■ Keynote Presentations INDUSTRY EXPERTS: Cameron Myhrvold, Microsoft David Intersimone, Borland Int'l Jesse Berst, Windows Watcher Said Mohammadioun, Lotus Daniel Norton, Writing Windows Device Drivers Alan Cooper, "Father of Visual Basic" and many more! HOT TOPICS: ■ Windows C++ Programming ■ High Performance Memory Management ■ Windows Network Programming ■ Windows Hooks ■ 32-Bit Windows Programming ■ Windows NT ■ Object-Oriented Windows Programming ■ Future of the Windows Operating System ■ Constructing DLLs ■ Windows Ul Design FOR A FREE BROCHURE ONWINDEV CALL 508/649-4200 Page 62 - Windows/DOS Developer’s Journal April 1993 Discardable Memory Turbo Vision has some very interesting functions to allo¬ cate and free discardable memory: TVMemMgr::allocate- Discardablef) and TVMemMgr::freeDiscardable(). If a re¬ quest for memory cannot be fulfilled, discardable memory blocks are freed either until the request succeeds or until there are no more blocks to discard. Great. In fact, you can read all about it on page 146 of the Turbo Vision guide. Sup¬ pose you want to spawn () another program from inside Turbo Vision, or you want to use that good old library that uses malloc() for memory allocation. Suddenly, you need a lot of memory. You just know that this memory will be available if Turbo Vision removes all discardable memory. Alas, there's no explicit way in Turbo Vision to free all dis¬ cardable memory. So although you may have plenty of memory left to load that program or allocate that big buffer, if you don't use new somehow, it will not work. It's simple enough to write code that frees all discardable memory since discardable memory blocks in Turbo Vision are managed by class TBufListEntry. Freeing the entire list amounts to writ¬ ing: static void TBufListEntry::freeList() { while(freeHeadO) » ) A suspend method for TVMemMgr can now be written as: static void TVMemMgr::suspend() { TBufListEntry::freeList(); } and integrated in TApplication::suspend() (for example), or called directly when you need memory. Unfortunately, you cannot do this without modifying the source code (in par¬ ticular, buffers.h and new.cpp). TGroup:: remove Should Ignore a NULL Argument Many Turbo Vision methods ignore NULL pointers, which greatly simplifies coding (see Figure 6 for an example). Alas, there’s a catch! TGroup::remove() does not check for a NULL argument, so the call to TProgram::desktop->remove() will hang the system if dialog is NULL. Summary Like any complex software product, Turbo Vision has its own set of problems and pitfalls. Looking over the list of problems and solutions presented here may save you from having to solve these or similar problems. □ End your listing errors by subscribing to Windows/DOS Developer’s Journal code listings on disk. ...HIGHER PRODUCTIVITY! Save hours of typing in long code listings and make better use of your time. Call 913-841-1631 TODAY! For only $30* you’ll receive 12 disks (one per issue) of Windows/DOS Developer’s Journal listings. You’ll save 50% off the price of buying the disks individually! If you don’t already subscribe to Win¬ dows/DOS Developer’s Journal- order both the magazine and disk for $59* Subscriptions must be prepaid and are available on 5.25" or 3.5" MS-DOS format only. WindowsyPOS □ DEVELOPER'S JOURNAL 1601 W. 23rd. St., Ste. 200 Lawrence, KS 66046-2743 •foreign prices vary (call for details) April 1993 Windows/DOS Developer's Journal — Page 63 BASIC Keystrokes By now, it seems almost instinctive to use the FI key to see a "help" screen, or the combination of Alt with a character key to pull down a menu, as you run a new application on your PC. But before the IBM PC was introduced in 1981, the seven-bit ASCII consoles we used with most microcomputers and many minicom¬ puters had neither function nor/IZt keys. The innovations introduced to the microcomputer world by the IBM PC were largely in the area of computer architecture, not the least of which was opening the input/output data paths to the full internal eight bits. This added another 128 sym¬ bols to those defined by the seven-bit ASCII standard. IBM architects defined the new symbols, including the now-familiar “text graphics," mathematical symbols, and foreign alphabetic characters, all of which could be entered from the new eight-bit keyboards, shown on the new eight-bit displays, and printed on the modified Epson printers. IBM called its PC character set "extended ASCII." Perhaps even more innovative, the 83-key PC keyboard included function keys (borrowed from mainframe terminals of the day) and the added shift key, Alt. These new keystrokes generated control symbols not available in the “extended ASCII" symbol set. They were coded into what IBM then termed an "extended code" set, another internal eight-bit code that was separate and independent of the “extended ASCII" set. Even now, over 10 years later, DOS does a very poor job of supporting the PC keyboard, and most high-level language implementations are little better. In what follows, I discuss keyboard support, primarily from the standpoint of recognizing the “extended code" functions, and describe an assembly language module (kbpeek.asm) that provides enhanced keystroke recognition. Although the module is written to be linked to compiled Microsoft BASIC programs, only minor editing is required to modify the source code for use with other high-level languages having implementations consistent with the Microsoft mixed-language programming conventions. Murray L. Lesser received a BS degree in engineering from CalTech in 1942 and earned his living as a programmer until 1954, when he joined IBM to work in what would become "systems architecture." He has been programming microcomputers and writ¬ ing books and articles about the subject since 1979 (but claims no responsibility for the IBM PC, having retired before it was announced). Page 64 - Windows/DOS Developer’s Journal April 1993 Murray L Lesser Codes and Keyboards The modern PC keyboard and its ROM BIOS support use three different coding schemes, only two of which are visible to the programmer. Distinguishing between the eight-bit codes representing character (including control character) keystrokes and those representing the non-character “extended code” keystrokes entails analyz¬ ing the contents of the AH and AL registers after calling the appropriate BIOS INT 16h function. Both the character and the extended code tables are shown in the IBM PC Techni¬ cal Reference manual and in the current (1991) edition of the IBM Personal System/2 and Personal Computer BIOS Interface Technical Reference. Terminology has changed in the interval since the PC was born; the BIOS Interface manual lists the formerly- termed “extended codes" as “scan codes.” Code tables having various degrees of accuracy are also found in many programmers' books and manuals, including the Microsoft BC versions 4.5 and 7.0 BASIC Language Reference manuals. The third coding scheme used by the original IBM 83-key keyboard is the key¬ board-generated “scan” code. Since the terminology change, there is unavoidable confusion when attempting to describe the relationship between actual keyboard “scan” codes and the renamed “scan code" for symbols representing non-character keystrokes. In what follows, I will use "extended code” for the non-character keystrokes. In the beginning, the scan code corresponded to the physical layout of the key¬ board. When a key on an 83-key keyboard is pressed, the corresponding scan code is sent to the CPU with an INT 9h\ when the key is released, that same scan code is sent again with the high-order bit set “on.” ROM BIOS interprets the combination of any active shift or lock scan codes it has seen and the incoming key code, storing the resulting character or extended code in the type-ahead buffer. For character codes, BIOS INT 16h returns the scan code in register AH and the character code value in AL. If the keystroke corresponds to one of the extended codes available on the 83- key keyboard, BIOS returns a zero for the character code in AL, and the value of the extended code in AH. For those keys pressed with no shift key code present, the extended code is the same as the 83-key keyboard scan code. Obviously, a shifted function key has to have a different extended code than its unshifted equivalent. The 255 character codes entered by holding down the Alt key and pressing three keys from the numeric keypad are identified with a zero scan code in AH and the character code in AL. Ctrl-Break is identified by zeros in both registers. One result of this architecture is that there is no way to enter an ASCII NUL from the PC keyboard. The traditional ASCII bit-paired Ctrl-@ (actually Ctrl-2 on the PC key¬ boards) returns an extended code 3 that must be translated by the program. Any keystroke combination not recognized by BIOS as being either a character or extended code is deleted as it goes by. An example for the 83-key keyboard is the 5 key in the numeric keypad when NumLock is off. 101 Keys The introduction of the 101-key enhanced keyboard brought complications. As before, the scan codes sent by the keyboard microprocessor are related to the actual keyboard layout — incompatible with the 83-key scan codes. Unfor¬ tunately, the 83-key scan codes had come into general programming use, so they had to be maintained. (The Old Tes¬ tament sage who observed that “the gods visit the sins of the fathers upon the children” must have had computer architects in mind.) So now BIOS has to translate the new keyboard’s scan codes into the programmers' old scan codes, along with the rest of the translations. In order to add further confusion, the new keyboard ar¬ chitecture allows the programmer to differentiate between duplicate keys having the same function (e.g., keypad and in¬ dependent direction keys). The extended code for the new key is the same as that of the original key, but an OEOh is returned in AL, instead of the old key's zero. Thus, all symbols read from the type-ahead buffer that return either a zero or an OEOh in AL are extended codes, with one exception: an OEOh in AL and a zero in AH is "extended ASCII” symbol 224 (a). A bit in the BIOS data area notes that the 101-key keyboard is installed. If bit 4 of the byte at 40:96 is 1, the 101-key keyboard was attached at the time POST (Power-On Self Test) was run, and may be presumed to be still at¬ tached. Thus, programs can recognize which set of INT 16h functions to use by testing that bit. Operating-system recognition of an installed 101-key keyboard is version sensitive: IBM-DOS 3.3 didn't, but IBM- DOS 5.0 does. (Quarterdeck's DESQview has recognized the 101-key keyboard since DV version 2.0, irrespective of which DOS version it is running under.) Since any keystroke not recognized by DOS will be lost, programs written in languages using DOS-based console functions for reading extended code keystrokes may exhibit changes in be¬ havior when run under IBM-DOS 5.0. Current PC implementations of Microsoft BASIC do not use DOS for key¬ board input or display output, so programs written in BASIC are not af¬ fected by the DOS change. However, the BC 4.5 version of INKEY$ does not recognize all of the new extended codes emitted by the 101-key key¬ board, nor the code for Ctrl-Break for either keyboard. If INKEY$ finds an ex¬ tended code keystroke it doesn't recog¬ nize, it returns a zero-length string and removes that symbol from the type- ahead buffer. The BC 7.1 version of INKEY$ appears to return all valid keystroke codes, including some that are missing from the manual's code chart. Reading the Keystrokes Only the assembly language programmer bothers with BIOS functions, Listing 1 kbpeek.asm .model medium .*********************************************************************** ; KBPEEK.ASM ; KBPEEK [DECLARE FUNCTION KBPEEK% ()] is a function to be linked to ; compiled BASIC programs. It looks at the next character in the ; type-ahead buffer and returns the following integer values: ; -1 if no character is pending ; 256 if an ASCII symbol is pending ; Any other returned value is the extended code symbol, which is ; purged from the type-ahead buffer. ; Based on the subroutine of the same name in the book ; "Advanced QuickBASIC 4.0," published by Bantam Books in 1988. ; Copyright (C) 1988, 1991 by Murray L. Lesser .★★★*****★****★**★★*★*★***★★*★**★★★***★***★★★****★★★***★★**★*★**★*★**★★* .code public kbpeek kbpeek proc push bp •.Safety, no arguments passed ;Test keyboard type word (as found by POST) mov ax,40h ;Set ES to ROM BIOS data area mov es,ax xor ch,ch ;83-key "read key 11 function test byte ptr es:[96h],10h ;Keyboard data area 3 jz next ;Zero if 83-key keyboard mov ch,10h ;101-key "read key" function next: mov ah.ch ;Check buffer status inc ah int 16h jz no chr ;Zero flag set if buffer empty ;Is pending character "Extended Code" symbol (AL = 0) for old keys? or al ,al jz getit ;If so, remove from buffer ;If not , test for "new" "Extended Code “ symbol (AL = OEOH, AH <> 0): cmp al,0e0h jnz next_2 or ah,ah ;ASCII code 224 [OEOH] is "a" jnz getit next_2: mov ax,256 ;Else return ASCII char signal done: pop bp ret ;Remove pending "Extended Code" symbol from buffer: getit: mov ah,ch ;Read keyboard buffer int 16h xchg ah.al ;Integer value of extended code xor ah,ah ; now in AX jmp done ;Signal no character pending: no_chr: mov ax,-l jmp done kbpeek endp end ; End of File Page 66 - Windows/DOS Developer’s Journal April 1993 although all programmers should be familiar with what they can do. The following paragraphs summarize the INT 16h (keyboard control) functions used in detecting the presence of, and reading, the keystroke codes as stored in the type-ahead buffer. For the 83-key keyboard, setting AH = 1 before calling the interrupt returns the value of the pending keystroke in the AH-AL registers, or sets the Zero-Flag bit to 1 if no keystroke is pending. Function AH = 0 waits for a keystroke if none is pending, then sets the registers as before, and finally clears the keystroke from the type-ahead buffer. AH - 2 returns a byte in AL indicating the current status of the shift (Shift, Ctrl, and Alt) and lock (Caps, Num, and Scrol l) keys. New functions were added to BIOS Interrupt 16h to handle the new keyboard. Functions o, 1, and 2, I NT 16h, will still read 101-key keystrokes that are functionally equivalent to those on the 83-key keyboard. Functions lOh, Uh, and 12h perform the same functions as 0,1, and 2, respectively, for the new keyboard, except they also "see" the returns from keys having no 83-key equivalent. If the system BIOS does not sup¬ port the 101-key keyboard, the new functions do nothing. kbpeek.asm (Listing 1) differentiates between extended code and character code in the type-ahead buffer by its Listing 2 oldkey.asm .model medium OLDKEY.ASM OLDKEY [DECLARE SUB 0LDKEYO] allows KBPEEK to operate correctly on certain old "compatibles" with 83-key keyboards that send a false "101-key keyboard installed 1 ' signal. Copyright (C) 1991 by Murray L. Lesser ★★★★★***★*★*★**★★★*★**★*★**★****★★*****★★★★*★*★★*★**★*****★*★★*★★*★★*** extrn B OnExit: far .code oldint dd 0 ; 01 d INT 16h vector, in code space newint proc ;New INT 16 handler, not a public PROC and ah.Ofh jmp cs:oldint newint endp public oldkey oldkey proc push bp push ds mov ax,3516h ;Get original INT 16H vector int 21h mov word ptr oldint. bx ; and save it for return mov word ptr oldint+2,es push cs ;Far address of FIXIT (the mov ax,offset fixit ; vector-restore routine) push ax call B OnExit ;FIXIT will be run at END mov ax,2516h ;Load newhandler vector for INT 16h push cs pop ds mov dx,offset newint int 21h pop ds pop bp ret oldkey endp fixit proc ;Not a public PROC push bp push ds push dx Ids dx.cs:oldint mov ax,2516h int 2 lh pop dx pop ds pop bp ret fixit endp end ; End i of File return value. KBPEEK returns -1 if no code symbol is present. It returns the value of the extended code (and removes the symbol from the buffer) if one is present, and returns a value of 256 if the current symbol represents an “extended ASCII" character (leaving that symbol to be identified by other means). The code is fairly straightforward, ex¬ cept possibly for the installed-keyboard test. A complicated testing procedure, discussed in the IBM BIOS Interface manual, can be used to determine whether or not a given BIOS supports the “new" I NT 16h functions for the 101-key keyboard, but this procedure Notice to Our Subscribers Occasionally, Windows/DOS Developer’s Journal makes its mailing list available to vendors of products we think our readers will find interesting. Cur¬ rent subscribers receive free in¬ formation in the mail from these vendors. If you prefer that your name not be used in these mailings, please let us know. Just copy or clip this form and send it with your name and address to: Windows/DOS □ DEVELOPER S JOURNAL 1601 W. 23rd. St., Suite 200 Lawrence, KS 66046-2743 April 1993 Windows/DOS Developer's Journal — Page 67 isn't suitable for on-the-fly use in a function module. Rather, I have assumed that if POST found the 101-key keyboard and set the appropriate BIOS data bit accordingly, nobody has removed that keyboard since power-on and the same BIOS that ran POST supports the new keyboard functions. KBPEEK tests the bit on each call and uses the corresponding I NT 16h function. KBPEEICs keyboard test doesn’t work if the program hap¬ pens to be running on an almost-compatible that has an 83- key keyboard but signals that it is using the 101-key variety. (One management problem with “backwards engineering" is that it is almost impossible to control the temptation for the backward engineers to “improve" on the original. IBM Techni¬ cal Reference manuals are not always explicit about not fid¬ dling with unused bytes in the BIOS data area. So, why not put...?) If you read the code in Listing 1, you will see that an 83-key keyboard disguised as having 101 keys will cause KBPEEK to always return a 256, thus indicating the presence of an ASCII character even when nothing is there. I have never encountered such an incompatible clone, but surmise their existence from a note in Quarterdeck's DESQview 386 v2.2 update manual pointing out that DESQview could not recognize the 83-key keyboard on some systems and men¬ tioning the command-line switch to work around the problem. This seemed to be a good idea, so I wrote an assembled BASIC subroutine containing a temporary TSR to hook I NT 16h. Getting Out Gracefully Since it is dangerous to the health of your system to leave an interrupt vector hooked after the interrupt handler hooking it has vanished, my workaround subroutine makes use of a little-known BASIC library function, BJOnExit, to guarantee the vector is eventually unhooked —even for an unexpected error termination. B_0nExit is logically equivalent to the Standard C function atexit, allowing the programmer to set up a sequence of subroutine calls to be executed just before the program ter¬ minates. It gets very little use from BASIC programmers, be¬ cause the BASIC support system does such a good job of cleaning up after itself. However, if your program includes a system configuration change made outside of the normal BASIC support, such as hooking an interrupt, B_0nExit allows the assembled module that does the dirty work to include — and execute — its own cleanup procedure. (You are asking for eventual trouble if you insist on coding “unsupported” con¬ figuration changes in any high-level language, even though the language implementation [(e.g., CALL INTERRUPT)] permits it.) My workaround subroutine, OLDKEY. ASM, is shown in Listing 2. All the temporary TSR does is intercept INT 16h and cut off the high-order nibble from the AH register, thereby convert¬ ing KBPEEICs 101-key functions back to their equivalent 83-key formats. Before setting up the TSR, OLDKEY calls B_On- Exit to register the far address of the "unhooking” FIXIT subroutine, which will be executed just before the pro¬ gram terminates. Listing 3 is a test driver, keytest.bas. In a real situation, the return from KBPEEK could be analyzed directly in a SELECT CASE structure without an intermediate variable. While the test for an errant “almost-com- patible” is built into the demo, you have to use the proper command-line switch to call for OLDKEY, thus allowing you to test for its effects even if you have the 101-key keyboard. (Try read¬ ing that 5 key, NumLock off, under KEYTEST called with and without the /OK command-line switch.) Of course, you don't have to use OLDKEY in your programs. It really isn’t a bug if your product doesn't support a poorly designed clone. You can always put the disclaimer "This program runs on IBM PCs and true compatibles" on the shrink wrap. □ Listing 3 keytest.bas ' KEYTEST.BAS - A test driver for the KBPEEK assembled function. 1 Compiled with BC 7.1, switch "/o" ' Linked to KBPEEK and OLDKEY with LINK 5.10, switch ”/e" declare function kbpeek% () declare sub oldkey () defint m defstr a if instr(command$,'70K") then call oldkey if kbpeek ■ 256 and inkey$ = ("") then print "Rerun this program with the command-line switch /OK 11 end end if print "This is a keystroke response test" print print "Symbol type", “Value", "Character" print locate ,,1 'Turns cursor on restart: let mark = kbpeek select case mark case -1 goto restart case 256 let a = inkeyS print “ASCII symbol", asc(a), if asc(a) > 31 then print a, if asc(a) » 3 then print "Control C": end case else print “extended code", mark, if mark = 0 then print "Control Break": end end select print goto restart Page 68 - Windows/DOS Developer’s Journal April 1993 ■ Windows Questions & Answers 69 Capturing Keyboard Messages with a CBS_DROPDOWN Combo Box; Generating 32-Bit Code; A Note on DDEML Q Why does the CBS_DROPDOUNLIST style of a combo box allow you to trap UM_KEYDOWN messages while the CBS_DROPDOUN style does not? The only dif¬ ference between the two styles is that the CBS_DROPDOUN style has an edit control for entering data, whereas the CBS_DROPDOUNLIST style combo box does not. Why should that matter? Is there a way for me to obtain keyboard control with the CBS_DR0PD0UN style? Jonathan Berry CIS: 70043,500 Borland C++ v3.1 Microsoft C/C++ v7.0a Zortech C++ v3.1 A A CBS_DR0PD0UN- style combo box control is composed of three windows: an edit control (class “edit"), a list box control (class "ComboLBox"), and an “owner” window to control the interaction between them (class “ComboBox"). The owner window is the one whose handle you get when you call CreateUindowf) to create a combo box. The problem is, when the owner window receives the input focus, it calls SetFocus() to give it to the edit control. As a result, all keyboard input is delivered directly to the edit control. Since the owner window is not receiving key¬ board input, subclassing it to get access to the keystrokes will not work. Paul Bonneau Send questions to Paul via Internet as paul@rdpub.com-, from CompuServe: >INTERNET: paul@rdpub. com-, or in care of this magazine at: 1601 W. 23rd St, Suite 200 Lawrence, KS 66046-2743. Paul Bonneau is a Senior Software Design Engineer at a major so/tware firm. He was a developer of HyperChem, a molecular modeling system marketed by Autodesk. A CBS_DROPDOMNLIS T-sty Ie combo box only has two win¬ dows, an owner and a "ComboLBox” list box. The combo box creates the list box for both styles as a child of the desktop window so that it will not be clipped to any other window (see the first question in the February 1992 Q&A column). That allows the list box to hang down past the bottom of the dialog box window, for example. One problem with desktop children is that they cannot be given the focus. In a CBS_DROPDOUNLIST- style combo box, the “owner” window will not call Set Focus () for the list box-, instead it keeps the focus and forwards keyboard input to the list box. This explains why you can subclass a CBS_DROPDOUNLIST combo box and receive keyboard input but not a CBS_DROPDOUN combo box. Unlike the list box, the edit control created by the CBS_DR0PD0UN- style combo box is a child of the “owner” win¬ dow. This means that you can obtain its window handle by calling Getk/indow(hwndComboBox, GW_CHILD). Once you have the edit control's window handle, subclassing it to capture keyboard messages is straightforward. Listings 1 through 4 im¬ plement an application to demonstrate catching keyboard messages from a combo box. The demonstration (see Figure 1) consists of a dialog that contains a combo box, a multiline edit control, and a pushbutton to dismiss the application. Whatever is typed into the combo box is echoed to the multi- line edit control. Listing 1 combokey.c - Demonstrate interception of keyboard messages for combo box control finclude (FARPROC)LFiIter, GetWindowInstance(hwnd))) != NULL) linclude lpfnCombo * SubclassWindow( #include "combokey.h" GetWindow(GetDlgItem(hwnd, didCombo), LPARAM CALLBACK LFi1 ter(HWND, UINT, WPARAM, GW CHILD), lpfn); } LPARAM) ; break; BOOL CALLBACK FDlgProc(HWND, UINT, WPARAM, LPARAM) ; case WM DESTROY: WNDPROC lpfnCombo; /* Subclasser's proc. instance. */ /* Remove the subclasser procedure. */ FreeProcInstance((FARPROC)SubclassWindow( #ifdef BORLANDC GetWindow(GetDlgItem(hwnd, didCombo), GW CHILD), lpfnCombo)); fpragma argsused return FALSE; lendif int PASCAL case WM KEYDOWN: WinMain(HINSTANCE hins, HINSTANCE hinsPrev, LPSTR Isz, case WM CHAR: int wShow) case WM KEYUP: /★★★★★★★★★★★★♦★★★★a****************★*★*★***★★★*******★ / /* Pass keyboard messages through to the */ /* -- Entry point. */ /* multi-line edit control. */ /* -- Displays a dialog as the main window. */ SendDlgItemMessage(hwnd, didText, wm, wParam, 1 Pa ram) ; ( break; DLGPROC lpfnDlg; if ((lpfnDlg * (DLGPROC)MakeProcInstance( case WM COMMAND: if (wParam !* IDOK && wParam != IDCANCEL) (FARPROC)FDlgProc, hins)) != NULL) ( DialogBox(hins, MAKEINTRESOURCE(dlgComboKey), return FALSE; EndDialog(hwnd, wParam); NULL, lpfnDlg); break; FreeProcInstance((FARPROC)1pfnDlg) ; ) return TRUE; } return TRUE; \ return FALSE; / ) LPARAM CALLBACK BOOL CALLBACK LFilter(HWND hwnd, UINT wm, WPARAM wParam, LPARAM 1 Param) FDlgProc(HWND hwnd, UINT wm, WPARAM wParam, j ★******★★**★★*★*★★★**★*★★*★*★★★*★**★*******★***★★**** j LPARAM 1 Param) /* -- Combo box subclass proc. */ /*★*★★*★***★★★***★******★***★★★★**★***★★*★★★★★★★★***** J y *★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★***★★★★**★*★** y /* -- Dialog proc. */ { /★★*★*★*****★★******★*★★******★★ ********************** j /* Send keyboard messages to the dialog. */ { if (wm *« WM KEYDOWN || wm == WM CHAR || switch (wm) wm =* WM KEYUP) ( SendMessage(GetParent(GetParent(hwnd)), wm. default: wParam, IParam); return FALSE; case WM INITDIALOG: { WNDPROC lpfn; return CallWindowProc(lpfnCombo, hwnd, wm, wParam, IParam); 1 / /* End of File */ /* Subclass the combo's edit control. */ if ((lpfn = (WNDPROC)MakeProcInstance( Page 70 — Windows/DOS Developer’s Journal April 1993 Just before the dialog is displayed, it receives a UM_INIT- DIALOG message. The code in Listing 1 obtains the window handle of the edit control and subclasses it using the macro SubclassWindow() from windowsx.h. Before the dialog is destroyed, Windows sends it a UM_DESTROY message, at which time the code removes the subclass function. The subclass procedure for the edit control looks for keyboard messages and sends them up the window chain to the dialog with a pair of nested GetParent() calls. When the dialog gets a key¬ board message, it sends it to the multiline edit control. Q ls it possible to generate 32-bit code in a Windows ap¬ plication using the Microsoft C7.0 compiler? A The compiler and linker work together to produce 16-bit code segments. When a 386 or 486 (and most certainly the Pentium) CPU executes code in a 16-bit segment, operand sizes and address sizes are assumed to be 16-bit, unless an override prefix is present. Prefixing an instruction with the byte 0x66 causes the processor to toggle the default size of the instruction’s operands. Operands in a 16-bit code segment become 32-bit, and vice versa. Listing 2 comobkey.h - Dialog resource IDs for combokey application #define dlgComboKey 1000 #define didCombo 1001 fdefine didText 1002 /* End of File */ Listing 3 combo key. rc - combokey application Dialog resource for linclude #include "combokey.h" dlgComboKey DIALOG 6, 18, 160, 100 STYLE OS MODALFRAME | WS POPUP | WS VISIBLE 1 WS CAPTION | WS SYSMENU CAPTION "Combo Key Interception Demo" FONT 8, "MS Sans Serif" BEGIN LTEXT "SCombo:", CO co C\J C\J CM 1 C0MB0B0X didCombo, 2 , 12, 48, 100, CBS DROPDOWN 1 CBS SORT 1 WS VSCR0LL | WS TABST0P EDITTEXT didText, 54 , 2, 104, 96, ES MULTILINE DEFPUSHBUTTON "&Done“, I00K, 2, 84, 48, 14 END J Turbocharge your C Programming with... L DataDraw DataDraw turbocharges your DOS/Windows C programming by representing data structures graphically, and generating C source code automatically. With DataDraw, you can: • Create complete object oriented C data structures in minutes. • Guarantee consistency between pictorial documentation and code. • Automatically generate binary load & save functions. • Have fast and direct access to data using a clean functional style interface. • Customize DataDraw's output, since all code generation source code is included. • Double your productivity with the object oriented programming methods supported by DataDraw... others already have! DataDraw is great for simple business applications and awesome for CPU intensive CAD. DataDraw is available now through Programmer’s Paradise for under $179.00 Call 1-800-445-7899 to order or for more information Visa & Mastercard accepted. Prices outside the U.S. may vary. 1 □ Request 111 on Reader Service Card □ Powerful tools for Windows NT™ & OS/2 Hamilton C shell™ The superior alternative to the standard command proces¬ sors. Faithfully recreates the entire UNIX® C shell language. Created from scratch for OS/2 and Windows NT. Blindingly fast. Extensively multi-threaded. Exceptionally powerful utilities. Fanatical quality. Meticulously adheres to all Windows NT and OS/2 conventions. Features: Full-screen command line editing • Filename and com¬ mand completion • History • Arrow and function keys • Unlimited size command lines • Recursive filename wildcarding • Fully nestable control struc¬ tures • Command substitution • Aliases and shell procedures • PATH hashing • Background threads and processes. Over 130 commands: alias, cat, chmod, els, cp, cut, di f f, dirs, dskread, dskwrite, du, eval, fgrep, grep,hashstat, head,history, label. Is, kill, markexe, more, mv, popd, printf, ps, pushd, pwd, rm, sed, sleep, split, strings, tabs, tail, tar, tee, time, touch, tr, uniq, vol, wait, wc, whereis, xd and others. Supports HPFS, long filenames and 32-bit and VDM applica¬ tions under OS/2. Intel, MIPS and DEC Alpha versions for Windows NT avail¬ able now. $350.00. Unconditional satisfaction guarantee. ($365 in Canada, $395 elsewhere.) Hamilton Laboratories 13 Old Farm Road, Wayland, MA 01778-3117 Phone 508-358-5715 • FAX 508-358-1113 □ Request 140 on Reader Service Card □ April 1993 Windows/DOS Developer’s Journal — Page 71 Listing 4 combokey.def - Linker definition file for combokey application NAME ComboKey DESCRIPTION 'Combo box keyboard interception demo 1 EXETYPE WINDOWS STUB 'WINSTUB.EXE' CODE PRELOAD MOVEABLE DISCARDABLE DATA PRELOAD MOVEABLE MULTIPLE HEAPSIZE 1024 STACKSIZE 10240 EXPORTS FDlgProc @1 LFilter @2 In an assembly block you can use the _ewit keyword to force the compiler to place a constant byte into the code stream. For example the following two statements: _asm _emit 0x66; _asm mov ax, 0; cause the code mov eax, 0 to be generated. At initialization, any program that contains 32-bit operand overrides should check that the processor is a 386 or better. You can use GetWinFlags() & (WF_386 | WF_486) CARE plants the most wonderful seeds on earth. Seeds of self-sufficiency that help starving people become healthy, productive people. And we do it village by village by village. Please help us turn cries for help into the laughter of hope. 1-800-521-CARE If the expression is true, a 386 or 486 is present (there is currently no UF_ con¬ stant for the Pentium). Listing 5 (32bit.c) implements a sample routine in 32-bit code. The routine, IlwFindLwRglwf) scans an array of 32-bit values looking for a given 32-bit value. While not exactly a fair comparison, the 32-bit routine ex¬ ecuted six times faster than the same routine implemented in C (even when the C routine was compiled with the optimize-for-speed flag): int IlwSearchLwRglw(DW0RD lw, DWORD far lplw[], int clw) { int ilw; for (ilw = 0; ilw < clw; ilw++) if (*1 piw++ == lw) break; return ilw < clw ? ilw : -1; ) Q We are in the integration testing phase of a software product that uses the DDEML (Dynamic Data Ex¬ change Management Library) for inter¬ process communication. We are having trouble under¬ standing how DdeCreateDataHandle() works. Per our understanding of the documentation, the function should be able to create a data handle to global DDE memory. We have registered a proprietary clipboard format “CF_CST” which contains three bytes of binary in¬ formation. The DdeCreateDataHandle() function is consistently returning a handle to 28 bytes, the first three of which are good, with the remaining 25 as garbage. Page 72 — Windows/DOS Developer's Journal April 1993 The part of the “CF_CST” clipboard format that is fixed three-byte messag¬ ing is not a big problem; however, another part of our “CF_CST" clipboard format defines a variable-length binary message. The design of our code relies on the ability to use the return value from DdeGetData() to determine the message length. For example in the code fragment cMsgSize = DdeGetData(hData, cBuffer, MAX_BUFFER, OL); we rely on cMsgSize being accurate for further processing. Our uses of DdeGetData() and Dde- CreateDataHandle() appear to be con¬ sistent with the DDEML sample server and sample client, with the exception of using the proprietary binary “CF_CST” clipboard format. Raymond Wroblewski AT&TBell Labs Naperville, Illinois r.j.wroblewski@att.com The essential problem is that DDE relies on global Lmemory handles to pass data back and forth, and since DDEML is compatible with raw DDE, it too uses global memory. DdeCreateDataHandlef) calls GlobalAlloc() to obtain the buffer. But GlobalAlloc() always allocates memory in multi¬ ples of 32 bytes. The documentation states that the return ■ Creates detailed assembly code listings for EXE, DLL, DRY, & VxDs ■ Labels Win API calls & exported functions ■ Search & locate references to specific or all Win API calls ■ Selective disassembly of exported functions or an address range R&sToRC — Only $34.95 ■ Decompiles resources directly to a JRC file ■ WinToAsm & ResToRC BOTH, Only $99.95 Eclectic Software 937 Jungfrau Court Milpitas, CA 95035 i408i 262-3264 Voite/FAX Win 3.0 EXE DLL DRV VXD SYM Win 3.1 □ Request 124 on Reader Service Card □ To claim the territory, have a (j a pt ure international markets by making your software easy to localize! Let InternaX videotapes, with Windows and Windows NT expert Dr. William Hall, show you how to design or retrofit your soft¬ ware for global success! For details, phone or fax ( 408 ) 438-2270 InternaX 6 Johnston Way, Scotts Valley, CA 95066 Windows™ is a registered trademark of Microsoft Corporation □ Request 101 on Reader Service Card □ Windows/DOS Developer’s Journal - Page 73 April 1993 Listing 5 32bit.c - Sample 32-bit routine for MSC v7.0 Urielude mov cx, clw emit 0x66 int IlwFindLwRglw(DWORD lw, DWORD far lrglwf], int clw) xor di, di ; xor edi, edi les di, lrglw /* -- Find the 32 bit value in the array of 32 bit */ emit 0x66 /* values. */ repne scasw ; repne scasd /* -- Return its index if found, else -1. */ je Found /* -- lw : Value to search for. */ mov ilw, -1 /* -- lrglw : Array to search. */ /* — clw : Number of elements in array. */ jmp Exit ^★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★^ Found: { sub di, WORD PTR lrglw int ilw; shl di, 2 dec di asm f emit 0x66 mov i Exit: ilw, di mov ax, WORD PTR lw ; mov eax, lw return ilw; _emit 0x66 xor cx, cx ; xor ecx, ecx } value from DdeGetData() is the size of the memory object associated with the data handle. One thing I find curious is that you are getting back 28 instead of 32. I wrote some test code that calls DdeCreate- DataHandle() for a three-byte object, and received 32 from a call to DdeGetData(). You might want to verify the value with a debugger (put a breakpoint immediately after DdeGetData() returns and examine the long returned in DX:AX). At any rate, DDEML does not encode the actual length of the data in its memory block, so you cannot use the return value as the length. You might consider modifying the "CF_CST” format to include another piece of fixed-length data that contains the length of the variable-length portion. □ □ Request 139 on Reader Service Card □ Page 74 - Windows/DOS Developer’s Journal Source Code Availability Bulletin Board S] /stems Phoenix Chapter ACM Library (602) 970-0474 The Programmer’s Corner (301) 596-7692 or (410) 995-6873 The Courts of Chaos (501) 985-0059 EmmaSoft Shareware Board (607) 533-7072 Cornerstone (206) 362-4283 Other Systems CompuServe GO CLMFORUM, section 7 BIX/WIX join listings, change areas to “win.dos.dev" uunet ~/published/windowsdos/19YY/monYY.zip Accessible via anonymous FTP from ftp.uu.net or via uucp from (900) GOT-SRCS (login name “uccp", no password, $.50 per minute). Code disks for each issue can also be ordered from R&D Publications, Inc. at (913) 841-1631. April 1993 Volkman - Windows for Workgroups (continued from page 48) The Print Manager passes messages to QPActionf) through the uiAct ion parameter. Figure 18 shows a complete list of messages and brief descriptions. In the remainder of this sec¬ tion, I provide just a thumbnail sketch of these messages. The first message that a QP will receive is the QP_INIT message. For QP_INIT, the IParam points to a QPINITDATA structure. The ulIdleRate member specifies how often (in milliseconds) Print Manager calls the QP. The QP can raise or lower the suggested idle rate according to its needs. A typical QP message sequence starts with QP_BEGINJOB, which is followed by a series of QP_URITE and QP_IDLE mes¬ sages. Last, the print job finishes off with QP_ENDJ0B. The QPJ/RITE messages contain the actual data to be sent out the port. The QP_IDLE messages are sent at appropriate intervals when Print Manager has no other jobs for this queue. If the QP has nothing to do, it should return from QP_IDLE with as little processing as possible. The QP_CLOSE message is the last one the QP has to hand¬ le. The QP can return TRUE if it is ready to close or FALSE if it still has work to do. Flowever, the Print Manager can force the close by setting the bMustClose member of QPCLOSEDATA to TRUE. Depending on the situation, the QP_CL0SE may or may not be preceded by a QP_QUERYCLOSE. Conclusion Windows for Workgroups is more than just a network add¬ on product for Windows 3.1. Rather, it is a blueprint for the future of all Windows platforms: Windows 3.1, the Win32 API, and Windows NT. The addition of new WNet functions for peer-to-peer networking is perhaps the most persuasive of these changes. Microsoft's existing NetDDE licensing provides for the deployment of NetDDE across all Windows platforms. MAPI is already available in Microsoft Mail 3.0 for Windows and will continue to play a strategic role. Last, you can expea to see the Common Controls appearing, albeit with a different interface, in future releases of all platforms. By increasing the number of networking options available for Windows, WFWG makes life easier for the end-user but perhaps more complex for the developer. The primary choices in client/server messaging used to be mainly between NetBIOS, Windows Sockets, and proprietary tools. Now, WFWG extends the possible choices to include NetDDE, Mailslots, named pipes, and SMAPI (see Figure 19). As ever, flexibility will be the key to successful develop¬ ment in the expanding family of Windows products. Even if your existing application is completely standalone today, you must consider the implications and opportunities offered by Windows for Workgroups. Bibliography Baker, M. Steven. "Networking Delivers.” Windows Tech Journal, August 1992 (VOl. 1, no. 7), pp. 22-29. A sobering account of the networking APIs currently avail¬ able for Windows 3.1: NetBIOS, WNet, WinSockAPI, and ven¬ dor-specific APIs. Baker succinttly describes the limitations and provides detailed bibliographic references for each of these environments. Does not cover WFWG SDK. Brockschmidt, Kraig. "Network DDE in Windows for Workgroups 3.1 Bridges Programs Between PCs.” Microsoft Systems Journal, January 1993 (vol. 8, no. 1), pp. 61-73. This article, which borrows heavily from the “WFWG Pre- SDK,” is currently the only in-depth source of information on Network DDE. The prerequisite for this is a knowledge of DDE and DDEML in the windows 3.1 environment. Keyser, Greg. “Extend the Funaionality of the Windows Control Panel with Custom DLLs.” Microsoft Systems Journal, November 1992 (vol. 7, no. 7), pp. 45-55. Although not related to WFWG, this article provides an in¬ formative guide to creating your own Control Panel applets. Microsoft Corp. Device Driver Adaptation Guide. Redmond, WA, 1990. This volume is only available as part of the Microsoft Win¬ dows Device Development Kit (DDK). This is still the only official source of documentation for the WNet API. This API provides the basic networking services of conneaing to network drives and monitoring print queues. The WFWG adds new WNet calls to this original set. Microsoft Corp. “Windows for Workgroups Lets Users Share Work, Files, Resources." Microsoft Developer News, Novem¬ ber 1992 (vol. 1, no. 2). A very broad overview of the features of WFWG and API extensions. Flints that “tools and guidelines” for developing WFWG applications will be available in “early 1993.” For subscription information, call Microsoft Developer Services at 1-800-227-4679 X11771 oremailtodevnetwk@microsoft.com. Microsoft Corp. Windows for Workgroups Resource Kit. Red¬ mond, WA, 1992. This comprehensive reference guide provides the most complete and coherent source of information on WFWG. If your primary interest is evaluating what WFWG has to offer, this book is a better bargain than the actual WFWG software. Main topics include installation, configuration, ex¬ planation of all .ini and .inf, troubleshooting, Mail and Schedule+ administration, and multiple networks. Also the only source of information on integrating applications with Schedule+ via FFAPI and .sch files. Available only from Microsoft, cost $35, call 800-642-7676 to order. Microsoft News Releases. "Microsoft and Wonderware Enter Technology Agreement to Make NetDDE Available to Win¬ dows Users.” May 6th, 1992. A brief summary of Wonderware's NetDDE and how it will be incorporated into future versions of Windows, Win32 API, and Windows NT. Note that this predates the release of WFWG by four months. This News Release is available as item Q84265 on Microsoft Online. Pleas, Keith. "Collective Windowing." Windows Tech Journal, January 1993 (vol. 2, no. 1), pp. 40-43. A broad, if rambling, overview of the elements of the WFWG SDK. □ April 1993 Windows/DOS Developer's Journal — Page 75 New Products Industry-Related News & Announcements WinRunner Provides Automated Windows Testing Mercury Interactive has released WinRunner, a tool for creating and maintaining automated tests for Windows programs. Quality assurance programmers can create tests by recording high-level, context-based processes or by recording a series of mouse and keyboard messages. Users can also program tests directly using Mercury's C-like Test Script Language (TSL). WinRunner can replay tests unat¬ tended, monitoring on-screen events and saving the results for later review. Mercury calls WinRunner a fourth-generation testing sys¬ tem based on the following classifications. First-generation testing systems are simple capture/replay/verify tools-, they cannot account for timing-sensitive events or changes in out¬ put (for example, an output screen that contains the current time of day). Second-generation systems are programmable but are still unable to deal with tasks such as “wait until this screen appears.” Third-generation systems are based on out¬ put, and can synchronize the test execution with screen events, with integrated programming and recording. By their ability to detect and react to screen events, third-generation systems can eliminate the need to predict delays and add wait states to test scripts. Mercury defines a fourth-generation testing system as one with the capabilities of a third-generation system, plus the ability to record high-level, context-sensitive events, not just keyboard and mouse messages. For example, Win¬ Runner can actually recognize the text in on-screen win¬ dows and menus, allowing it to replay a menu selection correctly by name, even if that menu item has been changed to a different position within the menu. The average price for a single WinRunner license is $6,000, including training, based on a typical basic installa¬ tion of five licenses. For more information, contact Mercury Interactive Corporation, 3333 Octavius Drive, Santa Clara, CA 95054, (408) 987-0100; FAX (408) 982-0149. RISC-based “PC'for NT Available DeskStation Technology, Inc has entered the new market for RISC-based Windows NT platforms. Windows NT not only has been ported to non-Intel CPUs, it still offers the ability to run DOS and 16-bit Windows 3.1 executables by emulating the 80x86 instruction set. These abilities have set the stage for a new generation of personal computers based on RISC CPUs. DeskStation is selling the ARCStation 1, which uses a 50Mhz (lOOMhz internal clock) R4000 MIPS CPU. Apart from the CPU and its support circuitry, the ARCStation 1 uses standard IBM AT components. The system can be configured with up to 64Mb of memory and it offers six 32-bit EISA slots. The ARCStation 1 includes an “ARCS-BIOS” - over 30,000 lines of code that support the R4000PC RISC processor and Win¬ dows NT in combination with standard PC/AT hardware. This BIOS also supports a 512Kb high-speed secondary cache for the R4000PC chip, increasing performance up to 25 percent The developer version of the ARCStation 1 costs $4,995, which includes 16Mb of memory, a 200Mb hard drive, a Super VGA adapter, and a 14" 1024x768 non-interlaced monitor. Windows NT is available directly from Microsoft (the PDK already supports the R4000). For more information, con¬ tact DeskStation Technology, Inc., 13256 W. 98th Street, Lenexa, KS 66215, (913) 599-1900; FAX (913) 599-4024. EM S Updates C++ Utility Library EMS Professional Shareware has updated its C++ Utility Library, a collection that now includes 242 public domain and shareware C++ products for professional C++ program¬ mers. The products are compressed onto 45 360Kb or 12 1.44Mb diskettes or on a CD-ROM. The library comes with an indexed database to make it easy to locate a product by vendor, name, type, or free-text search across descriptions. The library categories include Al, bugs, classes, code analysis, communications, database, date/time, debug, editor, graphics, help, Windows, make, math, memory manage¬ ment, mouse, multitasking, network, OWL, printer, screen, sound, string, text processing, user interface, and more. The library costs $59.50 on diskette or $99.50 on CD-ROM and has a 30-day, money-back guarantee. For more informa¬ tion, contact EMS Professional Shareware, 4505 Buckhurst CL, Olney, MD 20832-1830, (301) 924-3594; FAX (301) 963- 2708; Internet eengelmann@worldbank.org. Page 76 - Windows/DOS Developer’s Journal April 1993 M icroQuill Ships SmartHeap vl.5 SmartHeap is a DLL designed to provide Windows ap¬ plications with optimal memory management It includes facilities for detecting and handling memory errors, such as double-freeing, invalid parameters, memory overwrites, failure to free memory, and wild pointers. SmartHeap main¬ tains a pool of GlobalAlloc()'ed memory blocks, which it suballocates to satisfy memory requests from your applica¬ tion. This is a standard technique to avoid exhausting Windows' limited pool of global memory handles. SmartHeap also allows you to partition your allocations into “memory pools” that correspond to the working sets of your application. For example, if you know in advance that a certain set of data structures will be accessed at roughly the same time, you can group them in a memory pool so that the first access will bring the needed page into memory (if it has been swapped out) and further accesses will not require a virtual memory disk I/O. For some applications, judicious use of this feature can significantly increase performance by reducing swapping. The library provides a fixed-size allocator that offers bet¬ ter performance for structures such as linked-list This al¬ locator offers a zero space penalty per allocation and no fragmentation. Besides its own API, the DLL provides both an ANSI C mol loc ()-style interface and a C++ new-style interface. SmartHeap vl.5 costs $395; source code costs an addi¬ tional $500. Registered users of OptiMem vl.O can upgrade for $150. The product supports all Windows-capable C and C++ compilers as well as other languages that can call DLL routines. For more information, contact MicroQuill Software Publishing, Inc., 4900 25th Avenue NE, #206, Seattle, WA 98105, (206) 525-8218; FAX (206) 525-8309. Control Palette/NC Customizes Non-Client Area Blaise Computing has released Control Palette/NC, a DLL that helps programmers customize the non-client area of Windows windows. You can use Control Palette/NC to give borders, title bars, and menu bars a colorful, three-dimen¬ sional appearance. The product comes with object-oriented libraries for OWL (both Borland Pascal and Borland C++) and for Microsoft's MFC application framework. Control Palette/NC costs $169 and includes source code and an unconditional 60-day, money-back guarantee. For more information, contact Blaise Computing, Inc, 819 Bancroft Way, Berkeley, CA 94710, (510) 540-5441; FAX (510) 540-1938. Graphics Guru vl.5 Adds Windows Font Support Graphics Guru is a DOS graphics library completely writ¬ ten in assembly for maximum speed and minimum size. The library includes both low-level routines such as ellipse and polygon drawing and higher-level routines that support GIF, PCX, and Deluxe Paint files. The new version of Graphics Guru supports Windows bit¬ mapped .fon font files. Graphics Guru can display the fonts at any angle, in any of the 20 video modes and dozens of graphics adapters that the library supports. You can now use any of the thousands of existing Windows bitmapped fonts with Graphics Guru (which comes with a dozen freely dis¬ tributable fonts). Graphics Guru vl.5 costs $149.95 and includes source code (for both the library and a paint program), royalty-free distribution, and a 230-page manual. For more information, contact The South Bay Co., 47 Redhawk, Irvine, CA 92714, (800) 992-0716 or (714) 786-9357. COBOL spll GUI Tool Supports NT Flexus has released a version of COBOL spll that supports Windows NT. The GUI version of COBOL spll lets COBOL programmers easily “paint” screens to use in their Windows- based COBOL programs. Developers can also implement GUI screens using standard COBOL CALL statements. This allows developers to implement a graphical user interface from a COBOL application without learning the Windows API. Moreover, because the same COBOL CALL statements work with all the environments that COBOL spll supports (including DOS, Windows, OS/2, VMS, and others), the resulting user in¬ terface is portable. The Windows version of COBOL spll costs $795; registered COBOL spll users can upgrade for $200. For more information, contact Flexus International Corporation, P.O. Box 640, Bangor, PA 18013-0640, (215) 588-9400; FAX (215) 588- 9475. EMS Updates WINPRO Utility Library EMS Professional Shareware has updated its WINPRO Utility Library, a collection of 461 public domain and shareware products for Windows consultants and program¬ mers. The contents in the library are indexed in a database that can be searched by vendor, name, type, or free-text search. The library file categories include bitmap utilities, backup, communications, configuration, file compression, fonts, graphics, network, security, text processing, and others. The WINPRO Utility Library costs $99.50, plus shipping and handling, for either the diskette or CD-ROM version. For more information, contact EMS Professional Shareware, 4505 Buckhurst Ct, Olney, MD 20832-1830, (301) 924- 3594; FAX (301) 963-2708; Internet: eengel- mann@worldbank.org. April 1993 Windows/DOS Developer’s Journal — Page 77 VBToolsKan Offers Visual Basic Custom Controls Kansmen Corporation has released VBToolsKan, a set of Visual Basic custom controls similar to their ToolsKan custom controls for Windows. The 3D Chart module generates three- or two-dimensional charts (such as bar, area, and line charts). You can rotate about the X or Y axes and select various projection styles. The Table module allows spreadsheet-style windows with multiple column and row selections. Each column can be configured as a bitmap, radio button, check box, or combobox, and can be editable or read only. The StatusBar module provides a stretchable field with automatically scrolled text, a color progress meter showing the percentage completion of some task, and the ability to display date or time and report keyboard states. The Tool¬ box module gives you a palette of three-dimensional bit¬ mapped buttons. The Ribbon/Icon Bar module integrates comboboxes, static text (you can specify the font), and tog¬ gle/radio/push-style buttons, all with a three-dimensional look. The Field Validation module accepts COBOL-style PIC statements to validate input fields, such as date, time, and numbers. The Meter Control offers vertical, horizontal, and cir¬ cular gauges with a choice of needle or color bar as indicators. VBToolsKan has an introductory price of $99, is royalty- free, and comes with a 30-day, money-back guarantee. For more information, contact Kansmen Corporation, 2080-0 Walsh Avenue, Santa Clara, CA 95050, (408) 988-0634; FAX (408) 988-0639. FlashView Adds Support for X-32VM and M SC v7 FlashView is a new version of what used to be the Zor- tech C++ debugger, ZDB. FlashView now supports X-32VM and Microsoft C7. FlashView provides multiple debugging windows, automatic display of all local variables, full C++ name unmangling, runtime memory protection against pointer bugs, dual-monitor debugging, an unlimited number of breakpoints, structure/union/class expansion, expansion of pointers and arrays by type, runtime variable modifica¬ tion, and more. If an exception occurs while you are running your application under FlashView, it puts the cursor on the offending source line in your program. FlashView costs $250, or $150 to existing X-32VM cus¬ tomers. For more information, contact FlashTek, Inc., 121 Sweet Avenue, Moscow, ID 83843, (208) 882-6893; FAX (208) 882-7275; Internet flashtek@proto.com. Portable API Gains Connectivity Capabilities Software Transformation, Inc has released the Connec¬ tivity Series, an addition to its Universal Component System (UCS). UCS is a collection of modules designed to give your software a single interface for a variety of operating sys¬ tems. UCS supplies a superset of the features of each plat¬ form. UCS is currently available for Windows and the Macintosh. Versions for UnixWare, Windows NT, Sun Solaris, HPUX, DEC Ultrix, and OSF/1 are in beta, and an OS/2 version is under development UCS is divided into three series. The Foundation series provides system services such as memory management, event handling, printing, and graphics. The Interface series handles user interface devices such as windows, lists, tables, and buttons. The new Connectivity series provides a uniform interface to connectivity and communication, including inter¬ process communications, messaging, IPX, OLE, the Apple Edi¬ tion Manager (Publish and Subscribe), AppleEvents, and clipboard management UCS prices range from $3,500 to $10,000 per develop¬ ment system, depending on the platform and configuration. Runtime licenses are available for a one-time fee. For more information, contact Software Transformation, Inc., 1601 Saratoga-Sunnyvale Road, Suite 100, Cupertino, CA 95014, (408) 973-8081; FAX (408) 973-0989. Toolkit Provides Laser Data Collection Terminal Support Data Flarvester Developer’s Version lets software developers add portable laser data collection (LDQ terminals (Symbol Technologies, Hand Held Products, etc) to existing or new PC applications. Developers need only create applica¬ tions as usual with the Data Harvester interface, then com¬ bine one or more of those applications into a development library. This library and the Data Harvester runtime program then become a part of the existing application. The existing software issues a DOS command to execute the runtime program, with parameters indicating the name of the library, the name of the application, the COM port for serial communications, and whether to download program parameters to the portable terminal or upload collected data from the portable terminal. All functions are performed in the background. After data is uploaded from the portable ter¬ minal, the collected data is formatted into an ASCII test File using the file export setup parameters established for that application in Data Harvester. The text file is then imported into an existing data structure for further processing. For more information, contact AccuScan, Inc., 1540 High¬ way 138, P.O. Box 80037, Conyers, CA 30208-8037, (800) 950-0101 or (404) 922-1220; FAX (404) 922-0368. Windows Package Helps Monitor Defects The Software Edge, Inc, has released Defect Control Sys¬ tem for Windows, a package designed to monitor and or¬ ganize defects within software projects. The product helps development teams better control their projects by: making it easy to submit, update, and organize bug reports; giving project managers access to their defect data through graphi¬ cal and tabular reports; providing query facilities to search the project database for defects matching specified criteria; keeping team members informed of defects important to them through automatic and manual notification features. The system was designed for a workgroup environment; multiple users can access the project database simultaneous¬ ly. Workstation machines can be configured via a network in¬ stallation procedure. Defect Control System for Windows costs $995 for a single workstation license. Multi-user, custom, site, and source code licenses are also available. For more informa¬ tion, contact The Software Edge, Inc., 4420 haven Way, Colorado Springs, CO 80920, (719) 598-3713; FAX (719) 598- 3970. Page 78 — Windows/DOS Developer's Journal April 1993 WATCOM Announces SQL Products for Windows WATCOM has released two new products: WATCOM SQL for Windows and the WATCOM SQL Network Server Edition v3.1. The Network Server Edition provides an SQL database server that runs on a dedicated server machine and is avail¬ able in six-user and unlimited-user versions. WATCOM SQL for Windows provides tools for developing database applica¬ tions with WATCOM SQL The kit includes a single-user SQL database server for standalone PCs, database administration utilities, and tools for C/C++ development of SQL applications, using compilers from WATCOM, Microsoft, or Borland. WAT¬ COM SQL for Windows supports Microsoft’s Open Database Connectivity (ODBC) specification, allowing a variety of front- end tools to interface with it The WATCOM SQL database server supports ANSI-stand¬ ard SQL and provides features including: bidirectional, scroll¬ SpyWorks Brings Subclassing to VB SpyWorks-VB is a new package that extends Visual Basic v2.0 into areas that would otherwise require writing a DLL SpyWorks-VB allows any Visual Basic program to intercept the underlying Windows message stream for any Visual Basic form or control. By subclassing forms and controls, Spy¬ Works-VB allows an application to detect events that are not normally supported by the language, giving an extra de¬ gree of control over the behavior and characteristics of standard Visual Basic controls. The package includes tools to provide access to Win¬ dows API functions not normally accessible from Visual able, updatable cursors-, referential and entity integrity-, auto¬ matic cost-based query optimization, row-level locking, sym¬ metric multithreading of server requests; database compression; database encryption; ANSI-standard SQL trans¬ action logs; transaction processing; comprehensive security capabilities. WATCOM SQL for Windows costs $795 and a royalty-free, runtime redistribution license for single-user standalone ap¬ plications costs $99. The WATCOM SQL Network Server Edi¬ tion costs $795 for the 6-user version and $ 1595 for the unlimited version. For more information, contact WATCOM, 415 Phillip Street, Waterloo, Ontario, Canada N2L 3X2, (800) 265-4555 or (519) 886-3700; FAX (519) 747-4971. Basic This includes API functions that require callback func¬ tion addresses, Windows hooks, printer driver functions, and Visual Basic API functions. SpyWorks-VB also includes a set of debugging tools designed for programmers who want to use the Windows API. These tools can view both window messages and Visual Basic events as they occur, to detea API parameter errors and to examine memory and Windows resource use. SpyWorks-VB costs $129. For more information, contaa Desaware, 5 Town & Country Village #790, San Jose, CA 95128, (408) 377-4770; FAX (408) 371-3530. EMS Updates TP Utility Library TP Utility Library is a colleaion of 598 products for Turbo Pascal programmers. The products are compressed onto 58 360Kb floppies, 15 1.44Mb diskettes, or a single CD-ROM. All products in the library are described in an indexed database that accompanies the library. Categories of products in the library include Btrieve, communications, database, graphics, hypertext, math, memory management, and a variety of Windows categories. The TP Utility Library costs $79.50 on diskette or $99.50 on CD-ROM and comes with a 30-day, money-back guaran¬ tee. For more information, contaa EMS Professional Shareware, 4505 Buckhurst Ct, Olney, MD 20832-1830, (301) 924-3594; FAX (301) 963-2708; Internet- eengel- mann@worldbank.org. AccSys Adds FoxPro Support Copia International has added FoxPro support to their AccSys for dBASE database library, bringing the efficiency of C/C++ to FoxPro programmers. Programmers working in C, Visual Basic, and QuickBASIC can use AccSys for dBASE to cre¬ ate, read, write, modify, and update FoxPro Files without dealing with the internal file format peculiar to the database. The produa gives programmers control over FoxPro single- and multiple-field indexes as well as its memo fields and pic¬ Microsoft FORTAN Beta Available Microsoft has released a beta of Microsoft FORTRAN for Windows NT, a 32-bit implementation of FORTRAN that is hosted on and targeted for Windows NT. Beta users must have the Windows NT PDK as well as CompuServe access (the only channel for produa support for the beta version). The beta release offers improvements over Microsoft FORTRAN v5.1, including improved performance, additional ture fields. AccSys for dBASE is also network compatible and supports the FoxPro-specific memo format The produa sup¬ ports . idx, compaa. idx, and . cdx (combined) indexes. AccSys for dBASE costs $395, or $995 with source. For more information, contaa Copia International, Ltd., 1342 Avalon Court, Wheaton, IL 6 0187, (708) 682-8898; FAX (708)665-9841. VAX, IBM, and Microsoft language extensions, and mixed-lan¬ guage programming. For more information or to request the beta, contaa Warren Nolder at (206) 936-4021. You can contaa Microsoft at Microsoft Corporation, One Microsoft Way, Redmond, WA 98052-6399, (206) 882-8080; Telex 160520; FAX (206) 936-7329. April 1993 Windows/DOS Developer’s Journal - Page 79 Readers' Forum Hi, I have just received my first issue of Windows/DOS Developer's Journal, and I am very pleased with the quality, it seems very good. But . . . would there be any chance of purchasing back issues of the jour¬ nal? I would be interested in any back is¬ sues I can get hold of — I think they may contain information that would be useful to me now, rather than waiting for articles to be raised again. I look forward to hearing your reply, Regards, Roger Kinkead “Moorcroft” 27 Antrim Road Lisburn, County Antrim Northern Ireland, BT28 3ED Thank you for the nice words about the magazine. You may not know that this magazine started life in June 1990 as TECH Specialist. We became Win¬ dows/DOS Developer’s Journal in December of 1991 (vol. 2, no. 12). All back issues of the magazine are avail¬ able EXCEPT the following: TECH Specialist: 1.1 (June 1990); 1.6 (Nov. 1990); 2.2 (Feb. 1991); 2.5 (May 1991); 2.6 (June 1991); 2.11 (Nov. 1991). Windows/DOS Developer’s Journal: 3.1 (Jan. 1992). However, supplies of some of the available issues are quite limited. Back issues cost $7.50 each within the US; $11.00 (US) for international orders, —mm Code Correction Dear Mr. Burk, First let me thank you for publishing my article on a barcode DLL in your February issue. Flowever, there is an error in Listing 1. At the break between pages 44 and 45, the following three lines were lost: } BOOL BarCode ( I also have a Tech Tip in this issue but my address is wrong. I think the error was on my part but I'm not sure. The correct address is Michael Soflin M. R. Computing Services 4010 Harris Road, Suite C Lakeport, Ml 48059 You publish one of the best technical journals for Windows developers. Keep up the good work. Sincerely, Michael Soflin CIS: 71543,2125 Thanks for the corrections and the compliment, —rib Meanwhile, we made a couple of other mistakes, inadvertently omitting barcode, h from the published article and that file, along with some others not intended for publication, from the source code posted on CompuServe, UUNET, and bulletin board systems. We've now sent the full code to our electronic distribution channels and are printing barcode.h here. Our apologies to all who have been incon¬ venienced. —mm // ======================== // Barcode DLL header file #ifndef BARCODEH Idefine BARCODEH BOOL _export BarCode ( HDC hdcPrint, int x, int y. int iWide, int 1 SI im. int iHeight, LPSTR szBarcode); lendif Ron, In the November 1992 issue of Win¬ dows/DOS Developers Journal, Patrick Burrell wrote in his article, “Stylish Dialog Boxes,” a bunch of code that does not compile under Quick C for Windows. The function SubdassControl gets a “Segment lost" error, CALLBACK is not defined in windows.h and WNDPROC is not defined in windows.h. If you have or know where I could find fixes to this code I would be a happy camper. Thanks in advance for your efforts, David Garrison dgarr@telxon.com We have been moving toward a uniform treatment of Windows code that appears in the magazine. As part of that effort, most of the code now as¬ sumes that you have a Windows 3.1 development system and that you have defined STRICT. When STRICT is defined (for example, by using the command-line option “-DSTRICT"), windows.h uses a more type-safe set of definitions and, among other things, defines CALLBACK and WNDPROC. You will have to either upgrade to a 3.1- compatible compiler or modify the code to use the 3.0-style type declarations. As part of the effort to make the code meet some minimum standards and be vendor-independent, I have made a vendor-independent interface to the main three 16-bit Windows com¬ pilers (Borland C++ v3.1, Microsoft C/C++ vl.Oa, and Zortech C + + v3.1). That utility lets us use a single, very simple makefile for all three com¬ pilers. The makefile will then take care of getting the correct compilation op¬ tions set. This utility will first ship with this month's code disk, and we should get all the kinks out within a few itera¬ tions. Unfortunately, it was not in place for the Burrell article, and I have been foolishly assuming that everyone knew about the STRICT option. I apologize for the inconvenience, —rib Page 80 - Windows/DOS Developer’s Journal April 1993 ■ Tech Tips 81 Reader-Contributed Tricks and Hacks Edited by Leor Zolman Please send us your best tricks and /lacks —those c/ever pieces of code to make things work the way they should! You'll receive at least $50 for each tip that we print Send your submissions to.- Tech Tips Leor Zolman 74 Marblehead Street North Reading, MA 01864 leor@bdsoft.com. Transcending Limits and Harnessing DOS Redirection A Visual Basic Stack Problem Diego Cassinera General Videotex Corporation (BIX.DELPHI), Development Department 1030 Massachusetts Ave. Cambridge Ma 01721 (617) 491-3342 (ext. 392); Internet: diego@delphi.com The Symptom An “Out of stack space" error can occur when you use a LoadPicture method within a Form_Paint event. The Cause The Visual Basic stack can be exhausted when the LoadPicture method is ex¬ ecuted within a Paint event. The LoadPicture method generates a Paint event itself, and when performed within a Paint event, the program will repeat the cycle until the stack is exhausted. The code example in Listing 1 demonstrates that the Fom_Paint event is a recursive procedure when a LoadPicture method is included in the Paint event code. After you add the code to your program, run the program and note how many times the message “Form_Paint Countis displayed within the Immediate Window before you receive the “Out of stack space" error message. The Solution To remedy the situation, move LoadPicture to another event handler, such as the Form_Load event. Since these bitmaps are automatically refreshed when needed, you don't have to maintain the picture within a Paint event. Increasing Your Open File Limit Under Windows James K. Lawless 1622 Ave F Council Bluffs, IA 51501 I recently encountered an interesting problem with a commercial in¬ dexed file DLL. My Windows application initially opens several indexed files and peri¬ odically opens some fiat files using the Microsoft C _sopen() function. I found that when I had opened too many indexed files, my flat files would not open properly. Leor Zolman wrote BDS C, the first C compiler targeted exclusively for personal computers. Leor is currently an instructor on UNIX topics for Boston University’s Corporate Education Center, a regular contributor to The C Users Journal and Sys Admin magazines, and Tech Tips” editor for Windows/DOS Developer’s Journal. His first book. Illustrated C, was recent¬ ly published by R&D Publications, Inc He may be contacted at 74 Marblehead St, North Reading, MA 01864, or on Usenet/lntemet as.- leor@bdsoft.com. Illustration of Visual Basic 16K stack limit Sub Form_Pa1nt () Static Count Count * Count + 1 Debug.Print "Form_Paint Count : Count Forml.Picture * LoadPicture(“c:\windows\chess.bmp“) End Sub Listing 2 redirectc 1 I* 2 * REDIRECT.C 3 * 4 * Written by Gordon W. Lawson 5 * Test code modified by Leor Zolman 6 ★ 7 * Redirects STD0UT to STDPRN or a file, and back again. 8 ★ 9 * Tested under Borland C++ 3.1 by LZ 10 */ 11 12 #include 13 #include 14 linclude 15 16 Idefine CONSOLE 0 17 Idefine PRINTER 1 18 #define FILE 10 2 19 20 Idefine NO REDIR 3 21 Idefine QUIT 4 22 23 int redirect(int which); 24 void print this junk(void); 25 26 char Filenamef] = "TESTFILE.TXT” ; 27 28 void main(void) 29 { 30 int answer; 31 32 while(l) 33 { 34 fprintf(stderr, ”\nWhere do you want the text to go?\n H ); 35 fprintf(stderr, "0 Console\n"); 36 fprintf(stderr, "1 Printer\n"); 37 fprintf(stderr, "2 File\n“); 38 fprintf (stderr, "3 No redirection^"); 39 fprintf(stderr, “4 Quit\n"); 40 answer = getch () ; 41 fprintf(stderr, "\n\n"); 42 43 answer -■ 'O'; 44 45 switch(answer) 46 ( 47 case CONSOLE: 48 if (redirect(CONSOLE)) 49 fprintf(stderr, “Error!\n"); 50 break; 51 52 case PRINTER: My first attempt to remedy this was to check my CON¬ FIG.SYS to see if 1 had enough files reserved. Then, I inserted a call to SetHandleCount() in my program. I still encountered the problem. When I opened the flat files with the _lopen(), _hopen(), or OpenFilef) functions, the problem would go awayll The handles that these functions return are not valid, however, for the older non-Windows I/O functions such as _read and _write\ I looked in my task's PDB to see how big the handle table was after a SetHandleCountf). To my amazement, the hand¬ le table appeared to be large enough to accommodate many more files than I was using. I then traced the _sopen() call to the point where it called windows' “in¬ ternal DOS proc” I NT 21 h function to open the file. The function returned a valid handle, so something else in the standard library code was returning the error. After looking at Microsoft's startup code, I found that the global variable _nfile held the maximum number of handles that could be opened for the older I/O functions. I declared an extern reference to the nfile variable and set it to 40 after calling SetHandle- Count() with a parameter of 40. My file problems went away — for the time being. I later encountered the problem again when I tried to open yet more in¬ dexed files in my application. This time, the indexed files would not open. I was stymied for a while, but eventually figured out that since the DLL had been compiled with Microsoft C (it is dis¬ tributed in C source), it had it's own copy of _nfile in it's own instance- data. I was able to add a SetHandle- Count() call and set _nf He to an ap¬ propriate value in the LibMainf) func¬ tion of the DLL. This fixed the problem. Output Redirection From Within C Programs Gordon W. Lawson 407 E. 25th SL Houston, TX 77008 This tip is a simple one, but I haven’t seen it in any magazine or book before. As you know, you can redirect output from the console to the printer or a file from the DOS prompt In some cases, you may wish to do this in a program as well. I can think of numerous cases Page 82 - Windows/DOS Developer’s Journal April 1993 where this would be helpful, especially in small programs. You may not want to redirect from the DOS prompt (be¬ cause you have some menus to go through or for other reasons), but once you have the info you want, you would like to redirect it to a text file for later perusal or send it to the printer. This is especially useful in accounting or database programs. C automatically opens several input/output files. Most of the time this includes stdin (usually the keyboard), stdout (usually the screen), and stderr (usually the screen). On top of that, Bor¬ land C++ opens stdaux (serial ports?) and stdprn (port associated with LPT1, usually the parallel port, but could be modified by MODE. COM, etc.). I've seen in examples of how to redirect stdout to the printer, but not how to get it back —hence, my tip. DOS has several reserved words used to identify devices: “CON:,” “LPT1:,” etc. (look under MODE.COM in your DOS manual). By using the / reopen () func¬ tion in conjunction with these reserved names, you can redirect wherever and whenever you want. In my example program (Listing 2), redirectf) is the workhorse function. The main() function just sets up calls to redirect() in order to illustrate each possible usage. The menu dis¬ played in lines 36-41 offers the user a choice of options: redirect to the con¬ sole, the printer, a file, or no redirection Listing 2 continued 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 if (redirect(PRINTER)) fprintf(stderr, “Error!\n"); break; case FILE_I0: if(redirect(FILE_I0)) fprintf(stderr, "Error!\n"); break; case quiT: fcloseal1(); exit(0); case N0_REDIR: break; default: fprintf(stderr, "Please type the number * "beside your choice.. An"); continue; } print_this_junk(); int redirect(int which) ( FILE *in; int return_value; switch(which) ( case 0: /* Redirect output to the console */ if (freopen("C0N", "wt", stdout)== NULL) return_value = 1; el se return_value = 0; break; case 1: /* Redirect output to the printer */ if (freopen("LPTl", "wt", stdout) — NULL) return_value » 1; else return_value = 0; break; Developer's Marketplace w£l ^ ( CC-RIDER ) (for WINDOWS ) \ _ / SOURCE ANALYSIS, DOCUMENTATION AND BROWSING FOR ANY EDITOR I NEW FEATURES INCLUDE: * Quick March of all symbol definitions and usages, even Inherited class members, macro expansions, etc. * Windows Interface source code browser with class hierarchy chart* and function call tree diagrams * Browsers link to any text-mode or Window* editor. * Print symbol croc* reference, module summaries, function call trees, class hierarchy charts and more. * Database export to QuIckHelp, ASCII CSV (dBase). * API library lets you directly access the symbol database from your own C or C++ codel * PLUS ALL the classic CC-RIDER features to tackle those BIG unexplored programs 1 FULLY SUPPORTS CLASS NESTING, TEMPLATES, EXCEPTIONS, BORLAND C++. ZORTECH C++, MS QO+ 7 4 ALL ANSI C COMPILERS WESTERN WARES For DOS, Windows and OW) (303)327-4898 BoxC Norwood, CO 81423 ( FREE DEMO DISK > 1 MONEY-BACK GUARANTEE j _/ VB SDK FORM -1 "DLG" script Convert your VisualBasic IM Demo into a framework for your real product...in under a second! Our new STORC GOLD tool transfers VB or any other form displayed on screen into a DIALOG script, complete with font and color information! Skeptical? See our fully functional demo on CIS (go WINSDK, LIB3, STORC1.EXE) So don’t waste time reinventing your form in a dialog editor -- order STORC GOLD 1.0 today for only $39.93+6 sh/h. PractiSys ■ 4767 Via Bensa ■ Agoura, CA 91301 C Voice/Fax: (818) 706-8877 (Orders/Product Information) April 1993 □ Request 284 on Reader Service Card □ □ Request 102 on Reader Service Card □ Windows/DOS Developer’s Journal — Page 83 Listing 2 continued 98: 99: case 2: /* Redirect output to a file */ 100: if (freopen(Filename, "wt“, stdout) == NULL) 101: return value = 1; 102: el se 103: return value * 0; 104: break; 105: ) 106: return(return value); 107: i 108: 109: void print this junk(void) 110: < 111: printf(”This is the junk or stuff that you can " 112: “print in a file, the console\n"); 113: printf(“or the printer. Blah, blah, blah. Et cetera, " 114: “other stuff and well,\n“); 115: printf("you know, this stuff, too!\n“); 116: 1 /* End of File */ at all. Based on the user’s selection, main() calls redirect() (if necessary) to set up the requested redirection. Then, main() calls print_this_junk() to generate some output activity using a basic printff) function call. The ac¬ tual destination of the data generated by the printff) calls should vary ac¬ cording to the menu option selected. Note that main() always sends the menu text to the screen, regardless of any standard output redirection that may be in effect. This is because the menu text is sent to the stderr (stand¬ ard error) stream instead of to the standard output. Developer's Marketplace 2 tm The Art of Visual Basic Programming ™ This amazing new book by J. D. Evans, Jr. unlocks the secrets of Windows and Visual Basic application design and programming. It explains Windows design from a unique and easy to understand perspective. Smart Objects, Hybrid Objects, Control Coupling, Events, Focus, Event Triggering, Visibility, Form and Module Code Placement, DLL Parameter Passing, Variable Scope, Strings, and Structures are described and explained. Enlightening allegories and annecdotes make this one of the most unusual and informative Windows books ever written. This book is the Rosetta stone for Windows and Visual Basic! Book: $29.95 Companion Disk: $9.95 ETN Corporation RD4 Box 659 Montoursville, PA 17754-9433 (717) 435-2202 (Sales) (717) 435-2802 (FAX) AMEX/MC/VISA/Check/MO/PO/COD □ Request 148 on Reader Service Card □ NETWORK CONTROL LIBRARIES NETBIOS ROUTINES allows ac¬ cess to low-level network func¬ tions. Name, session, and datagram routines. Wait and no¬ wait options. $99 NETBIOS DLL for Windows $199 NETWORK MASTER provides access to Netware internal func¬ tions. Complete network control from your compiled programs! $99 Starlight Software P.O. Box 1090 Wheeling, IL 60090 (708) 394-0622 _ □ Request 170 on Reader Service Card □ COM1: - COM4: WITH WINDOWS! 1,2, OK 4 PORT RS-232 BOARDS RS-232 AND KS-422 VERSIONS XT AND AT INTERRUPT JUMPERS OTHER PRODUCTS INCLUDING LAPTOP ADD-ONS DELIVERY FROM STOCK MADE IN USA EXCELLENT TECHNICAL SUPPORT SEALEVELSYSTEMSINC. POBOX03O LIBERTY.5C29657 803 - 043-4343 iEflLEVEL □ Request 115 on Reader Service Card □ SpyWorks-VB For Visual Basic™ - Windows SpyWorks-VB allows you to do virtually anything in Visual Basic that is possible using other languages such as C. It includes controls that easily subclass VB forms and controls, detect keyboard events, and support callback functions. SpyWorks includes debugging tools to view message and event history, detect API parameter errors, Browse Windows memory and resources, and retrieve information about any window, form or control in the system. SpyWorks-VB is only $129 + $5 s&h ($15 outside U S & Canada). Visa/MC orders include phone and exp. date. CA residents add 8.25% sales tax. Dual media - Requires VB2.0 Desaw are 5 Town & Country Village #790 San Jose, CA 95128 (408) 377-4770 fax:(408) 371-3530 □ Request 113 on Reader Sendee Card □ JPEG Image Compression for Windows ■k Compress/Decompress images in 10 seconds or less. ★ Full Source Code & DLL’s Available -*• Convert & View Multiple Images ★ Royalty Free Developers Kit Available ★ PRICES START AT $99.00! Regular and Extended Dos also available ® PHONE: 1-800-966-4487 305-962-9961 FAX: 305-962-6546 Information Technologies Research,Inc 3520 W Hallandale Beach Blvd Pembroke Park, FL 33023 □ Request 299 on Reader Service Card □ Page 84 — Windows/DOS Developer’s Journal April 1993 Macro Language "To Go" Easily embed Netlogic’s full-featured J procedural language engine in your Windows application — at a fraction of the time and cost of developing it yourself. Seamless integration. Full basic syntax. Integrated editor and debugger. Extendable and modifiable. For more information: Netlogic Inc., 915 Broadway, New York, NY 10010. 1-800-638-0048. Fax: (212) 533-9090. ProMacro Netlogic's Procedural Lang uage Engine | □ Request 136 on Reader Service Card □ INGRAF supports video, printers, and plotters Over 100 routines give you complete control of axes, scaling, windows, and more Sutrasoft 10506 PtrmJtn Dr. Sugar Land, TX 77478 Info: (713) 491-2088 FAX: (713)240-6883 □ Request 286 on Reader Service Card □ Great Graphics for Scientists and Engineersl FORTRAN, C, QuickBASIC, and Pascal. Source code. No royalties. $350 CD KNOWLEDGE MEDIA RESOURCE LIBRARY ROMs EACH TOPIC DISK CONTAINS HUNDREDS OF APPLICATIONS THOUSANDS OF FILES MANY WITH FULL SOURCE CODE. GRAPHICS ANIMATION, PAINT. CONVERTERS, FRACTAL, DRAWING. JPEO. MAPPING. GIF. PLOTTING. PAINT, AUDIO CONVERTERS, MMX, EDITORS > MIXERS, MOOS, MUSIC, PLAYERS, : SNQ, speech Packers, voc, wa MULTIMEDIA AUTHOeiNe JYSItMS, l>KSSJTAT10N PWWS. CCNHNT MEDIA UBRARIES ORDER DESK: (800) 78 CD ROM ORDERS BY FAX (916) 872-3826 VISA and MASTER CARD or COD 436-B Nunneley, Paradise, CA 95969 □ Request 118 on Reader Service Card □ SDLC, HDLC OR X.25 SUPPORT ON THE PC Use the Sangoma SOLA card to provide exceptionally cost effective, full featured, stable and easy to use link support for your product or project. • Line speed to 180kbps • Compatible with all operating systems and environments • Operating statistics and built in datascope make your product easy to configure and debug • Menu driven test program included • Primary and secondary SDLC with multiple addresses • HDLC LAPB, LAPD, NRM mode • CCITT 1988 X.25 implementation • High level interfaces for X.25 under DOS, UNIX, Windows, OS/2. Sail ITlil Technologies Inc. Tel: (416) 474-1990; (800) 388-2475 FAX: (416) 474-9223 Development Utilities World’s largest and best collections of PD/Shareware for PC pros extensively indexed and ZIPed for best value. 30 day guarantee. Visa/MC/AmEx/COD. Ship/H $5US, $20Foreign. Products _ Assembler AutoCAD C (Turbo & MS) C++ (subset of above) dBase & Compilers Turbo Pascal Paradox Visual BASIC MultiMedia Object Vision Netware PC Products Database TrueType Fonts Windows Professional .44 Disks/Files Price 9/368 $59.50 13/796 $59.50 39/854 $149.00 13/277 $59.50 47/2637 $179.00 16/620 $79.50 9/315 $59.50 10/351 $59.50 10/115 $59.50 2/85 $29.50 23/649 $99.50 104,000 records $25.00 17/745 $59.50 31/564 $99.50 m CD-ROM S99.50/S295 EMS Professional Shareware 4505 Buckhurst Ct.; Olnev. MD 20832 (301) 924-3594, Fax: (301) 963-2708 □ Request 107 on Reader Service Card □ April 1993 BRIEF COMPATIBLE wasting time and money programming TCP/IP for Windows EDITOR ON UNIX & WINDOWS-NT c Socket programming has been superceded by network middle-ware for Windows that encapsulates TCP/UDP/TELNET & TFTP in an easy-to-use server! Feature rich environment. Extremely easy to use. R GENISYS Comm Pack++ 100% Keystroke Emulation. T ► 4-function DLL for your C/C++/Fortran app ► NEW Visual Basic custom controls too! ► Quickly embed TCP/IP comm in your apps - share files and messages with UNIX hosts - turn your PC into a sophisticated server ► Binary compatible with most TCP/IP stacks ► No Royalties! Evaluation Kit available. Run Existing BRIEF macros. Specify BRIEF/Unix regexp. MultiWindow Xvi emulation. Goodbye VI/EMACS!! 1 s For Windows & data networking support contact: Available On: mn GENISYS Comm. Inc. 314 South Jay St.. Rome, NY 13440 SUN/SCO/HP/I BM/SGI/INT/NT. Openlook/MotifAYindows/Char ver. p MICROSOFT; (315)339-3502 windows™ vw * y * y »* Compatible GCP++0GENISYS.com Call: VITAL at (713) 781-7406 Yoduct names are trademarks of respective holders D Request 145 on Reader Service Card D [J Request 134 on Reader Service Card O Graphics & Timing Tools PC Timer Tools - Microsecond resolution timing, delays, interrupt profiling, asynchronous thread scheduler, and timer tick interrupt management in a PC/MSDOS environment. No external hardware needed! Supports TC, TC++, BC++, MSC, Intel 386 Code Builder, Zortech, Turbo Pascal. $69.95. New! PC Timer Objects, OOP version for TC++, BC++, MSC++, ZTC++, Turbo Pascal Objects. $69.95. BGI Printer Driver Toolkit - bgi printer drivers for Borland's BGI graphics library. Epson/IBM 9 pin, Epson/IBM 24 pin, LaserJet, DeskJet, PaintJet, Postscript, HPGL, PCX, others. Not a screen dump - load our drivers with BGI's initgraph and get full hardcopy device resolution. Supports TC, TC++, BC++, Turbo Pascal $89.95. BGI For Windows - BGI compatible interface to Windows 3.x GDI. Port your Borland DOS BGI graphics routines effortlessly to Windows. Full stroke font, 256 color, hardcopy support . Supports TCW, BC++, TPW. $89.95 All toolkits include full source & object code or driver distribution license VISA & MasterCard accepted. Add $4.00 shipping USA, $7.00 elsewhere. Our 30 day "No Questions Asked" return policy guarantees satisfaction. Ryle Design PO Box 22, Mt. Pleasant, Michigan 48804 USA Voice/Fax: 517.773.0587 BBS: 517.772.2393 CIS: 73047,1765 □ Request 280 on Reader Service Card □ Simtel20 MSDOS CDROM* $24.95 640 megabytes in 9000+ files. Programming tools, DOS utilities, tech docs, comm, bbs, publishing, ham-radio, education, and much more. Dated September 1992. CICA MS Windows CDROM* $24.95 Hundreds of MS Windows programs. Utilities, games, source code, and programming tools. Dated July 1992. Source Code CDROM* $39.95 XIIR5 and GNU CDROM $39.95 Info-Mac CDROM* $39.95 OS/2 Archive CDROM* $24.95 AB20 Amiga CDROM* $24.95 Garbo MSDOS/MAC CDROM* $24.95 CDROM Caddies $4.95 * Shareware programs require separate payment to authors if found useful. Walnut Creek CDROM 1547 Palos Verdes Mall Suite 260 Walnut Creek, CA 94596 + 1-800-786-9907 +1-510-947-5996 FAX +1-510-947-1644 □ Request 105 on Reader Service Card □ Windows/DOS Developer’s Journal — Page 85 It may seem at first glance that selecting the console for standard output redirection serves no purpose, since standard output is normally sent to the console by default. However, consider the situation where the test program is invoked via the command: redirect > filename In this case, the data generated by print_this_junk() goes into the file named filename if the option for "no redirection" is chosen, while selecting the console redirection option routes the data to the screen and not into filename. In the redirect() function, the DOS device names specified in the f reopen () calls do not contain colons. Some DOS variants, such as DR DOS, do accept the colon in device names used in this context. Vanilla DOS, however, does not. Mastery of DOS redirection is a valuable tool to the ad¬ vanced programmer. For example, if you have a prepared “response file," why not redirect input (through stdin) to press the keys for you? I have implemented a crude macro lan¬ guage using this technique. In a real-world application, after your redirected processing is completed, you can turn redirection off by calling redirect() with the CONSOLE argument. This reconnects the standard output “back” to the console. □ Developer's Marketplace" f ; Windows Developer Jobs "\ Specialists in jobs for software engineers in leading edge technology. Windows, PM, GUI, Languages, AI, Mac, CASE, Video, Realtime. Nationwide contacts with both large and small companies including equity startups. Many of our clients develop and publish commercial software products. Managed by graduate engineers. Never a fee to an applicant. 1-800-231-5920 Scientific Placement, Inc. SPI-8, Box 19949, Houston, TX 77224 (713) 496-6100 SP1-8, Box 71, San Ramon, CA 94583 (510) 733-6168 SPI-8, Box 4270, Johnson City, TN 37602 (615) 926-6188 Fax: 713-496-6802 please use Fine Setting on Fax Email: Ascii preferred: Internet LSH@Scientific.com; CompuServe: 71250,3001; Genie: D.SMALL6 j □ Request 335 on Reader Service Card □ These Incredible Tools Make Windows. Easy To Use. Central™ ....Amazing—Organizes Your Com- mantis, Programs, and Files. Wind List™ .Super Task Manager $39” (Control Any Window). MagWind™ . Magnify The Screen ..$39 ,s , (The Easy Way). BilView™ ...See The Internal ..$19 ,s Structure Of Bitmaps. BtnAid™ ....Program 3-D Buttons .$15* (Graphics, Text, and Frames). . $59 M Cull Now For Free llrochiire 1-800-458-2829 No Risk 60 Day Guarantee Springtime Software 81 Amherst Avenue Waltham, MA 02154 □ Request 119 on Reader Service Card □ Page 86 — Windows/DOS Developer's Journal Opt-Tech Sort/Merge Extremely fast Sort / Merge / Select utility. Run as an MS- DOS command or CALL as a subroutine. Supports most languages and filetypes including Btrieve and dBase. Unlimited filesizes, mul¬ tiple keys and much more! MS-DOS, Windows $149. OS/2, UNIX $249. Opt-Tech Data Processing P. O. Box 678 Zephyr Cove. NV 89448 (702) 588-3737 □ Request 127 on Reader Service Card □ April 1993 eXtraHelp Windows Developer: You have just delivered your Windows Application and the user is now requesting context-sensitive help. With eXtraHelp you can provide help without adding a single line of code to vour program . eXtraHelp is a simple cost-effective method for providing easy to use professional looking help. End-User: You have just received your Windows Application. The help system explains how the program works but there is no help for the unique way your company uses it. eXtraHelp is the tool that allows you to create context-sensitive help specific to your requirements. Features: Hyper-Text, paragraph formatting, multiple fonts, tabbing, color text , pictures and works with any windows program . Microsoft Help compiler and RTF editor not needed. $79 per copy. Please call or write for site license, quantity discount or developer pricing. Timenetics Inc. 908-464-5978 39A WestviewAve. New Providence, N.J. 07974 □ Request 141 on Reader Service Card □ FAST TEXT SEARCH for C / Windows The fastest, easiest and most versatile way to add full text search capabilities to your C and Windows applications, FAST TEXT SEARCH for C is a function library enabling rapid searches of both structured and unstructured textual data with low overhead/memory requirements, low cost and high efficiency. Great with CodeBase, SoftC, AccSys, etc. No Risk 30 day Money Back Guarantee Order - (800) 334-8099 Only $189.00 Windows/DOS Developer’s Journal Special includes UltraSearch & Free 2 Day Shipping DOS (Microsoft, Borland) and OS/2 libraries & Windows DLL, royalty free integrator license, complete printed documentation, sample programs & free technical support. VISA/MasterCard/COD/Qualified PO s accepted. Index Applications Incorporated kX 8546 Broadway, Suite 208 San Antonio, TX 78217 USA 512 / 822-4818; fax: 512 / 828-5074 CGI □ Request 121 on Reader Service Card □ RELIEF from TLINK and LINK Headaches OPTLINK for Windows provides Borland developers with higher capacity linking intra-segment far call to near call conversions and Windows exe-packing. You get faster, more efficient programs. Microsoft developers get linking several times faster than LINK, Windows exe-packing and innovative build-time debugging features. It eliminates the 2nd pass of RC and generates DOS, Windows, and OS/2 programs from C, C++, Basic, and Fortran objects. Ask us about our OPTLIB Superfast Librarian too. 30-day MBG. SLR Systems, Inc. (412) 282-0864 Fax (412) 282-7965 □ Request 154 on Reader Service Card □ Visual Basic, BASIC, and PDS programmers! General Purpose Toolboxes Screen Design Cwtlmunicotions (user Printing Scientific Applications hHS and more! Crescent Software offers marry tools for QuickBASIC, PDS, and Visual Basic. All products include complete source code, bee technical support, ond royalties ore never required! KxuirMMfriKEKwowcHas CALL TOLL FREE 1 800 35 BASIC CRESCENT SOFTWARE, INC. 11 BAILEY AVENUE RIDGEFIELD. CT 06877-4505 2034385300 FAX 203 4314626 1:03 TUB “ is FASTEST! 0:41 0:19 0:09 RCS™ 4.2 PVCS™ TUB" 3.0 TUB™ 5.0 Times are to update a 45K library on a PC/XT. PVCS and TLIB 3.0 are Irom Sept 87 PC Tech Journal. MKS RCS 4.2 and TLIB 5.0 are newer. TLIB™ is BEST! “Do not be fooled by the fact that this is the least expensive of the five packages reviewed here - TLIB has features and power to spare” John Rex, Computer Language “TUB is a great system ” J. Vallino, PC Tech J . Full-Featured Version Control for Software Professionals. Check-in/out locking. Branching. Keywords. Wildcard and list-of-file support. Can merge parallel changes and undo intermediate revisions. Network and WORM support. Main¬ frame compatible deltas for Pansophic, ADR, IBM, etc.. Integrates with Opus'" MAKE & Slick'" MAKE. MS-DOS $139, OS/2 $195* shipping visa/MC 5 station LAN license $419 (OS/2 $595), call for other sizes BURTON SYSTEMS SOFTWARE PO Box 4156, Cary, NC 27519 (919)233-8128 □ Request 137 on Reader Service Card □ We Understand The Programmer's Mind When the country's top firms look for the best developers available, they turn to Bateman. Why? Because we specialize in Microsoft Windows, NT, OS/2 and Macin¬ tosh recruiting nationwide. So if it's time for a career move, give us a call. We under¬ stand your skills, and the marketplace for them... we understand you. □Bateman Inc. 5847A Uplander Way Culver City, CA 90230 Tel: 310-641 -4100 Fax: 310-641-2900 □ Request 172 on Reader Service Card □ Does your company provide tools, products, or services for advanced Windows programmers? Then reach over 27,000 serious programmers in: Windows/DOS □ DEVELOPER'S JOURNAL Call 913-841-1631 today for information about advertising opportunities in Windows/DOS Developer’s Journal. Advanced. Serious. T echnical. Brian Osborn - Continental Europe. Ed - East Donna - Midwest Edwin - West C and C++ DOCUMENTATION ! AUTOMATED DOCUMENTATION ! • C-CALL ($69) Graphic-tree of caller/called functions, cross-ref, file/function index. • C-CMT ($69) Creates/inserts/updates comment-blocks for each function, listing the functions and identifiers used by it. • C-METRIC ($59)Counts path complexity, counts comments, code, ’C statements. • C-LIST ($69) Lists and action-diagrams, or reformats into standard formats. • C-REF ($59) Creates cross-reference of local/global/define/parameter identifiers. • SPECIAL : C-DOC ($199) All 5 programs integrated as DOS program (<15,000 lines) • NEW! C-DOC Professional ($299) DOS, OS/2, Windows. 3-ring binder/case. Processes 150,000 lines, deferred reports. • 30-DAY Money-back guarantee CALL NOW SOFTWARE BLACKSMITHS INC. 6064 St Ives Way, Mississauga ONT, Canada Voice/Fax (416)-858-4466 L5N-4M1 Demos/BBS [415^58-1915 see AD INDEX for our larger ad SOFTWARE ENGINEERS Wisconsin's largest professional servicesfirm, Com¬ puter People Unlimited, has continually bucked the national trend by consistently growing and thriving in a weak economy. Because of our unique position we con offer you technical challenges in a city known for its beauty and old world charm. As a Software Engineer, you will design, code and test MS-Windows based scientific applications us¬ ing C. Coll Julie Endlich at (414) 225-4000 or 1 (800) 527-8462. You may also send your resume in confidence to: Computer People Unlim¬ ited, Dept.DJ, 732 N. Jackson St., Milwaukee, Wl 53202. fox: 414-225-4011.E0E. April 1993 □ Request 103 on Reader Service Card □ □ Request 132 on Reader Service Card □ Windows/DOS Developer’s Journal — Page 87 Advertiser Index Advertiser ... Reader Service Number .. .. .Page Advertiser ... Reader Service Number _ . Page AccuSoft Corporation . ...120 ... . 32 pC/OS . ...337 .... ...42 ADONIS Micro-Software . ...116 ... .53 NCR-NICE. ...167 .... .. . C2 Austin Code Works . ...332 ... . 1 NetManage, Inc. ...131 .... ...51 Bateman, Inc. ... 172 . .. . 87 Netlogic, Inc . ...136 .... ...85 Best Programs . Hr * . 37 Nu-Mega Technologies . ...341 .... . . ,C4 Black Ice Software, Inc . ...139 ... . 74 One Tree Software . ...164 .... . ..18 Blossom Software Corp . ... 146 . .. . 29 Online Magazine Index . . ..117 .... . . .61 Burton Systems Software . ... 137 ... . 87 Opt-Tech Data Processing . .. .127 .... . . .86 Catenary Systems . ...104 . .. .56 PractiSys. ...102 .... .. .83 Classic Software . ...143 ... .50 Quadbase Systems, Inc. ...175 .... ...19 Compass Point Software, Inc. ... ...138 ... .39 R.J. Swantek. ...108 .... ... .9 Computer People Unlimited .... ...132 ... .87 Ryle Design . ...280 .... .. .85 Crescent Software Inc. * * .87 Sangoma Technologies, Inc. * * . . .85 DataDraw. ... Ill ... .71 Scientific Placement, Inc. ...335 .... ...86 DBS GmbH. ...142 ... .31 SeaBreeze Software Systems ... ...123 .... ...22 Desaware. ...113 ... .84 Sealevel Systems, Inc. ...115 .... ...84 Eclectic Software . ...124 ... . 73 Sequiter Software, Inc . ...126 .... .. .C3 EMS . ... 107 ... . 85 SLR . ...154 .... . . .87 ETN Corp. ...148 ... .84 Software Blacksmiths. ...103 .... ...87 Far Point Technologies . ... 125 . . . .3 Software Blacksmiths. ...135 .... .. .55 GENISYS Communication, Inc. ... ... 145 ... . 85 The Software Factory . ...133 .... ...54 Gimpel Software . * * . 43 Software Interphase . ...319 .... ...17 GRiD Systems . ...129 ... . 14 Springtime Software . ...119 .... . . .86 Hamilton Laboratories . ... 140 ... . 71 Starlight Software . ...170 .... . . .84 HPI . ... 114 ... .32 StratosWare Corporation . ...153 .... . ..16 IBM Personal Software Products * * .. 10-11 Sutrasoft. ...286 .... ...85 Index Applications . ...121 ... .87 The Symmetry Group. ...333 .... ...59 Information Modes. ...295 ... .41 Timenetics, Inc. .. .141 .... .. .87 InternaX. ...101 ... .73 V Communications . * * . ..15 1PT Corporation. ...128 ... .86 VPS Software . . . .144 .... .. .48 Island Systems . ...340 ... .23 Vital Corporation. . . .134 .... . ..85 Iterated Systems, Inc. ...122 ... .47 Walnut Creek CDROM. ...105 .... ...85 ITR Vision Software . ...299 ... .84 Western Wares. ...284 .... .. .83 Kansmen Corporation . ...109 ... .31 Willies’ Computer Software Co... ...100 .... .. .25 Knowledge Media . ...118 ... .85 WINDEV EAST 1993 . ★ * ...62 Messaging Systems Group, Inc. . ...130 ... .35 XVT Software, Inc. ...112 .... ....5 MicroEdge, Inc. ...334 ... .13 ZyLAB Corporation. ...106 .... .. .39 MicroQuill Software Publishing .. * * .57 * * This advertiser prefers to be contacted directly. This index is provided as a service to our readers. The publisher assumes no liability for errors or omissions. Page 88 - Windows/DOS Developer’s Journal April 1993 FREE Product Information Use this postage paid card to stay up-to-date on products that affect your productivity. Just fill out the card and drop it in the mail. Ifl Windows"/ DOS □ DEVELOPER'S JOURNAL 1601 W. 23rd St., Suite 200 Lawrence, KS 66046-9950 USA (913) 841-1631 FAX: (913) 841-2624 REQUEST READER SERVICE NUMBERS: Please help us serve you by answering the following: 1) I program: □ for a living □ as a manager □ as a hobby 2) I program in: □ MS-DOS □ Windows 3) I program most frequently in □ C++ □ C ____ □ Assembly company □ Pascal □ Other_ address Use with the April 1993 issue only. NAME □ Please start my subscription to Windows/DOS Developer’s Journal for one year. Bill me $29 (U.S.); $53 (Canada/Mexico); or $64 (all other countries). CITY 1ST A TEIZIP/COUNTRY PHONE FAX 4.4 Windows/POS □ DEVELOPER'S JOURNAL □ YES! Send me 1 2 issues of Windows/DOS Developer’s Journal for only $29 ! □ 2 years (24 issues) for $54 □ 3 years (36 issues) for $77 □ Bill Me □ Visa □ MasterCard Number_Exp._ Signature_ Name Company Address City State Zip Country/Province/Mailcode 4.4 Please allow up to six weeks for delivery of first issue. Orders outside the US must be prepaid in US funds. CANADA/MEXICO subscriptions are: 1 year - $53; 2 years - $88; 3 years - $121. Overseas subscriptions are: 1 year - $64; 2 years - $120; 3 years - $174. NO POSTAGE NECESSARY IF MAILED IN THE UNITED STATES BUSINESS REPLY MAIL FIRST CLASS PERMIT NO. 682 LAWRENCE, KS Postage will be paid by addressee Windows/DOS □ DEVELOPER'S JOURNAL 1601 W. 23rd St., Suite 200 Lawrence, KS 66046-9950 till ml IiiIIiii ilu lill i ill lnl tin till illi ml ilil NO POSTAGE NECESSARY IF MAILED IN THE UNITED STATES BUSINESS REPLY MAIL FIRST CLASS PERMIT NO. 682 LAWRENCE, KS Postage will be paid by addressee Windows/DOS □ DEVELOPER'S JOURNAL 1601 W. 23rd St., Suite 200 Lawrence, KS 66046-9950 FREE Product Informatior Use this postage paid card to stay up-to-date on products that affect your productivity. Just fill out the card and drop it in the mail. CZ3 lill ml Ini Iimliililliil.ini ilu ilil ill mil ilil #here is a good reason why • your database language was developed in C. In fact, there are many good reasons. C code is small. C code is fast. C code is portable. C code is flexible. C is the language of choice for today's professional developer. With the growing complexity of database applications, C is a realistic alternative. Now with CodeBase 5.0, you can have all the functionality, simplicity and power of traditional database languages together with the benefits of C/C++. C speed - fast code, true executables... FoxPro, Clipper, and dBASE were written in C primarily for speed. But those compilers don't really compile, they combine imbedded language interpreters into your .EXE. Now that's slow. For dazzling performance you need the true executables of C. With CodeBase you get the real thing, C code. Consider the following statistics, from the publisher of Clipper: "Sieve of Erastothenes" Benchmark for Prime Number Generation Shows C to be incredibly faster! C size ■ small executables, no added overhead... FoxPro, Clipper and dBASE would like you to believe you need their entire development system to build database applications. But remember, those products are all written in C. So why do you need to lug all their extra code around? You don't. CodeBase is a complete DBMS, in C. No fat executables stuffed with unused code. No runtime modules. No royalties. Just quality C code. CodeBase is just what you need. data files with any logical dBASE expression. Our new Bit Optimization Technology (similar to FoxPro's Rushmore technology) uses index files to return a query on a 1/2 million record data file in just a second. Automatically take advantage of this query performance by using our new CodeReporter: C portability-ANSI C/C++ on every hardware platform... No other language exists on more platforms than C/C++. Why rewrite your entire application for DOS. Windows, Windows NT, OS/2 or UNIX? With CodeBase the complete C source code is included, so you can port to any platform with an ANSI C or C++ compiler. Now and in the future. dBASE Compatible data, index and memo files... You want the industry standard. You need compatibility. Sure, dBASE is the standard, but every dBASE compatible DBMS product uses its own unique index and memo file formats. Only CodeBase has them all: FoxPro (.cdx), Clipper (.ntx), dBASE IV (.mdx) and dBASE III (.ndx). Now it's your choice, we're compatible with you. Announcing CodeBase 5J) The power of a complete DBMS, the benefits of C NEW - Multi-user sharing with FoxPro, Clipper and dBAsE... Now your multi-user C/C++ programs can share data, index and memo files at the same time as concurrently running FoxPro, Clipper and dBASE programs. No incompatibilities. No waiting. NEW - Queries & Relations 1000 times faster... CodeBase 5.0 now lets you query related Pie Align Database Groups Global Print Query Styles Help Product Sales Sumnl Product Sales Summary Month o»: Nov, 1992 Product Quantity Value Database 63 $25.137 00 Spreadsheet 58 121.866 00 Monthly Summary 121 S47.003.00 Month: Header: Objects: S: Height: 48.0 Points F*roHuc| IQuantif^ NaM Body; Header: Objects: 3; Height: 14.0 Points Month: Footer: Objects: 4: Height 48.0 Points Month of. Dec. 1992 Product Quantity Value Database 62 $24.86200 Spreadsheet 53 $19,875.00 Monthly Summary 115 944.737.00 ^.■IhlySin.,., UlOTAt_MDOLLJ Summary: Objects: 3: Height: 3E.0 Points ISumm# [TOTAL 1 DOLLAR Summary 236 $91,740.00 To use CodeReporter, simply draw your report, then include it in any program you write. Call 403/437-2410 now for your FREE working model of CodeReporter. New - Design complex reports in just minutes... Our new CodeReporter takes the painstaking work out of reports. Now simply design and draw reports interactively under Windows 3.1, then print or display them from any DOS, Windows or UNIX application. SPECIAL - FREE CodeReporter Order CodeBase 5 before April 30, 1993 and receive CodeReporter for free! This offer includes our no-risk, 90-day money back guarantee, so order today! Coctegers® 3,0 • - -/ -ytt? j he C/C++ Library for DataBase Management Call Now 403 - 437-2410 *». ■■seaa- o»«- . HIT-- 1 SEQUITER II FAX 403*436*2999 SOFTWARE INC. 1111 33.20.24.20.14 #209,9644-54 AVE., EDMONTON. AB. CANADA T6E-5V1 01992 Sequiter Software Inc. All rights reserved. CodeBase is a trademark of Sequiter Software Inc. All other trade names referenced herein are property of their respective companies. MAdvertising by MicroArts □ Request 126 on Reader Service Card □ ANOTHER DEBUGGING BREAKTHROUGH BOUNDS-CHECKER FOR WINDOWS! The Power Of BOUNDS-CHECKER is now available for Windows NEW! BOUNDS-CHECKER for Windows is the only totally automatic solution to your Windows memory corruption, heap corruption and resource leakage problems. BOUNDS-CHECKER for Windows is an easy to use utility that automatically detects problems in your local heap, global heap, stack or data segment. It also tracks resource allocation / de-allocation, performs full parameter checking (even when not using the debug kernel) and handles all Windows faults. In one step, you can quickly and easily flush out some of the most aggravating bugs that a Windows programmer is likely to encounter. Using BOUNDS-CHECKER for Windows is simple, there are no changes to be made to your source in any way, and no linking of code or macros into your executable. When a bug is found, BOUNDS-CHECKER for Windows pops up shewing you the source code that caused the problem. BOUNDS-CHECKER for Windows quickly & easily traps: • Memory and heap related corruption problems • Library routine over-runs of strings, arrays and structures • Attempting to free bad blocks • NULL pointers the instant they are referenced • Resources that were not freed (shows your actual source line that created the resource) • Errant parameters passed to API routines • Processor Faults Order NOW! Only $199 For even more debugging power at a great value you can order BOUNDS-CHECKER for Windows in one of our package bundles that include other Nu-Mega debugging tools: BOUNDS-CHECKER for DOS & BOUNDS-CHECKER for Windows $298 BOUNDS-CHECKER & Soft-ICE (DOS or Windows versions) $ 499 Get all 4 products (BOUNDS-CHECKER & Soft-ICE for DOS & Windows) $770 — SAVE $400! We're making C/C ++ a Safe Language! Call (603) 889-2386 fax (603) 889-1135 JfrNiEMega RISK = NULL 30 DAY MONEY-BACK GUARANTEE P.O. Box 7780 Nashua, NH 03060-7780 U.S.A. TECHNOLOGIES INC 24 HOUR BBS 603-595-0386 □ Request 341 on Reader Service Card □