Documentation updates
This commit is contained in:
parent
12439f8cd0
commit
6b5e9ef1d4
17 changed files with 626 additions and 73 deletions
|
|
@ -17,7 +17,7 @@ right_brace: "}"
|
|||
|
||||
# Build settings
|
||||
|
||||
exclude: ["index.html", "**/index.html", "**/archive", "logs", "node_modules", "**/c64", "**/private", "src", "**/src", "tmp", "videos", "web", ".git", ".idea"]
|
||||
exclude: ["index.html", "**/index.html", "**/archive", "**/c64", "blog/posts", "logs", "node_modules", "**/private", "src", "**/src", "tmp", "videos", "web", ".git", ".idea"]
|
||||
markdown: kramdown
|
||||
kramdown:
|
||||
input: GFM
|
||||
|
|
|
|||
|
|
@ -13,31 +13,31 @@ machines:
|
|||
Just for fun (because I have a warped sense of fun), I decided to revisit some of the old OS/2 software I wrote
|
||||
almost 30 years ago. But first, I needed an OS/2 development environment.
|
||||
|
||||
So I started with a clean install of IBM's OS/2 1.0 in the [8Mhz IBM PC AT](/disks/pc/os2/ibm/1.0/) machine
|
||||
So I started with a clean install of [IBM OS/2 1.0](/disks/pc/os2/ibm/1.0/) in the 8Mhz IBM PC AT machine
|
||||
below, by booting from the "IBM OS/2 1.0 (1.44M Install)" diskette in drive A and reformatting the machine's 20Mb
|
||||
drive C.
|
||||
|
||||
Next, I installed the [MS OS/2 SDK 1.02](/disks/pc/tools/microsoft/os2/sdk/1.02/). This SDK was released
|
||||
in December 1987 along with [Microsoft OS/2 1.0](/disks/pc/os2/microsoft/1.0/). I don't have any of the
|
||||
printed documentation that came with the SDK, such as the *Installation Guide*, but I do have the
|
||||
[Microsoft® Operating System/2 Programmer’s Toolkit](/pubs/pc/programming/os2/microsoft/ptk/1.0/) documentation
|
||||
[Microsoft® Operating System/2 Programmer’s Toolkit](/pubs/pc/software/os2/microsoft/ptk10/) documentation
|
||||
from March 1988, thanks to the [OS/2 Museum](http://www.os2museum.com/wp/os2-history/os2-library/os2-1-x-programming/).
|
||||
|
||||
Aside from Microsoft's assembler (MASM) and C compiler (CL), the SDK included some other useful tools, such as the
|
||||
**SDK Editor** (SDKED), which was essentially an OS/2 port of Mark Zbikowski's Editor (Z) that was used internally
|
||||
at Microsoft for many years. It was renamed to the **Microsoft Editor** (M or MEP) with the release of Microsoft C
|
||||
5.1, and it was later integrated into **Programmer's Workbench** (PWB), the text-mode Integrated Development
|
||||
Environment (IDE) that came with Microsoft C 6.0.
|
||||
Aside from **Microsoft Macro Assembler 5.00A** (MASM) and **Microsoft C Compiler 5.10 (Beta)** (CL), the SDK
|
||||
included some other useful tools, such as the **SDK Editor** (SDKED), which was essentially an OS/2 port of
|
||||
Mark Zbikowski's full-screen editor (Z) that was used internally at Microsoft for many years. It was renamed
|
||||
to the **Microsoft Editor** (M or MEP) with the release of **Microsoft C Compiler 5.10**, and it was later integrated
|
||||
into **Programmer's Workbench** (PWB), the text-mode Integrated Development Environment (IDE) that came with
|
||||
**Microsoft C Compiler 6.0**.
|
||||
|
||||
With the introduction of graphical IDEs, such as Visual BASIC in 1991, Visual C++ in 1993, and Visual Studio in 1995,
|
||||
this stand-alone, text-mode editor became obsolete, but in the 1980s, it was an essential tool.
|
||||
this stand-alone, text-mode editor became obsolete, but in the 1980s, it was a valuable tool. You can learn more
|
||||
about [SDKED](/disks/pc/tools/microsoft/os2/sdk/1.02/#using-sdked) on the
|
||||
[MS OS/2 SDK 1.02](/disks/pc/tools/microsoft/os2/sdk/1.02/) page.
|
||||
|
||||
You can learn more about [SDKED](/disks/pc/tools/microsoft/os2/sdk/1.02/#using-sdked) on the
|
||||
[MS OS/2 SDK 1.02](/disks/pc/tools/microsoft/os2/sdk/1.02/) page. I'll be adding a complete list of all the files
|
||||
that came with SDK to that page in the near future.
|
||||
|
||||
To boot IBM OS/2 1.0 and tinker with the [SDK](/disks/pc/tools/microsoft/os2/sdk/1.02/), scroll down and
|
||||
click the "Run" button.
|
||||
Our [IBM OS/2 1.0](/disks/pc/os2/ibm/1.0/) demo machine (shown below) has the
|
||||
[MS OS/2 SDK 1.02](/disks/pc/tools/microsoft/os2/sdk/1.02/) pre-installed, so check out our copy of the
|
||||
[Microsoft® Operating System/2 Programmer’s Toolkit](/pubs/pc/software/os2/microsoft/ptk10/) and then write some code!
|
||||
|
||||
{% include machine.html id="ibm5170" %}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,10 @@ digits are the day of the year (294 or October 21).
|
|||
|
||||
Directory listings of the four 1.44Mb distribution diskettes are provided below.
|
||||
|
||||
IBM OS/2 1.0 has been pre-installed on this machine's 20Mb hard disk, along with a copy of the
|
||||
[Microsoft OS/2 SDK 1.02](/disks/pc/tools/microsoft/os2/sdk/1.02/), as discussed in this
|
||||
[blog post](/blog/2015/12/27/).
|
||||
|
||||
{% include machine.html id="ibm5170" %}
|
||||
|
||||
### Directory of IBM OS/2 1.0 (1.44M Install)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<machine id="ibm5170" class="pc" border="1" pos="center" background="#FAEBD7">
|
||||
<name>IBM PC AT (8Mhz), 128Kb EGA, 2Mb RAM, 20Mb Hard Disk</name>
|
||||
<computer id="at-ega-2048k" name="IBM PC AT" buswidth="24"/>
|
||||
<cpu id="cpu286" model="80286" cycles="8000000"/>
|
||||
<cpu id="cpu286" model="80286" cycles="8000000" autostart="true"/>
|
||||
<ram id="ramLow" addr="0x00000" test="false" size="0xa0000" comment="ROM BIOS memory test has been disabled"/>
|
||||
<ram id="ramExt" addr="0x100000" size="0x160000" comment=""/>
|
||||
<rom id="romEGA" addr="0xc0000" size="0x4000" file="/devices/pc/video/ibm/ega/ibm-ega.json" notify="videoEGA"/>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ that allows the SDK installation script to finish.
|
|||
|
||||
This SDK was released in December 1987 along with [Microsoft OS/2 1.0](/disks/pc/os2/microsoft/1.0/).
|
||||
We do not have any of the printed documentation that came with the SDK, such as the *Installation Guide*, but we do
|
||||
have the [Microsoft® Operating System/2 Programmer’s Toolkit](/pubs/pc/programming/os2/microsoft/ptk/1.0/) documentation
|
||||
have the [Microsoft® Operating System/2 Programmer’s Toolkit](/pubs/pc/software/os2/microsoft/ptk10/) documentation
|
||||
from March 1988, thanks to the [OS/2 Museum](http://www.os2museum.com/wp/os2-history/os2-library/os2-1-x-programming/).
|
||||
|
||||
Other documentation is available for selected OS/2 SDK tools:
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ AAD (0xD5)
|
|||
|
||||
### Description
|
||||
|
||||
From [http://www.rcollins.org/secrets/opcodes/AAD.html](http://www.rcollins.org/secrets/opcodes/AAD.html):
|
||||
Excerpt from [http://www.rcollins.org/secrets/opcodes/AAD.html](http://www.rcollins.org/secrets/opcodes/AAD.html):
|
||||
|
||||
Undocumented: Available to all Intel x86 processors
|
||||
Useful in production source code.
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ title: "x86 Instructions: AAM"
|
|||
permalink: /docs/x86/ops/AAM/
|
||||
---
|
||||
|
||||
AAD (0xD4)
|
||||
AAM (0xD4)
|
||||
---
|
||||
|
||||
### Description
|
||||
|
||||
From [http://www.rcollins.org/secrets/opcodes/AAM.html](http://www.rcollins.org/secrets/opcodes/AAM.html):
|
||||
Excerpt from [http://www.rcollins.org/secrets/opcodes/AAM.html](http://www.rcollins.org/secrets/opcodes/AAM.html):
|
||||
|
||||
Undocumented: Available to all Intel x86 processors.
|
||||
Useful in production source code.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ ICEBP (0xF1)
|
|||
|
||||
### Description
|
||||
|
||||
From [http://www.rcollins.org/secrets/opcodes/UMOV.html](http://www.rcollins.org/secrets/opcodes/UMOV.html):
|
||||
Excerpt from [http://www.rcollins.org/secrets/opcodes/ICEBP.html](http://www.rcollins.org/secrets/opcodes/ICEBP.html):
|
||||
|
||||
An undocumented op code that will make debugging run-time code
|
||||
on an ICE easier. Normally, to set an arbitrary breakpoint in a
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ LOADALL386 (0x070F)
|
|||
|
||||
### Description
|
||||
|
||||
From [http://www.rcollins.org/secrets/opcodes/LOADALL.html](http://www.rcollins.org/secrets/opcodes/LOADALL.html):
|
||||
Excerpt from [http://www.rcollins.org/secrets/opcodes/LOADALL.html](http://www.rcollins.org/secrets/opcodes/LOADALL.html):
|
||||
|
||||
(LOADALL) An undocumented op code used by ICE host software and
|
||||
diagnostics software to test CPU functionality. This instruction
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ SALC (0xD6)
|
|||
|
||||
### Description
|
||||
|
||||
From [http://www.rcollins.org/secrets/opcodes/SALC.html](http://www.rcollins.org/secrets/opcodes/SALC.html):
|
||||
Excerpt from [http://www.rcollins.org/secrets/opcodes/SALC.html](http://www.rcollins.org/secrets/opcodes/SALC.html):
|
||||
|
||||
An undocumented op code that performs an operation common to
|
||||
every Assembly language subroutine to C and many other higher
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ UMOV (0x100F,0x110F,0x120F,0x130F)
|
|||
|
||||
### Description
|
||||
|
||||
From [http://www.rcollins.org/secrets/opcodes/UMOV.html](http://www.rcollins.org/secrets/opcodes/UMOV.html):
|
||||
Excerpt from [http://www.rcollins.org/secrets/opcodes/UMOV.html](http://www.rcollins.org/secrets/opcodes/UMOV.html):
|
||||
|
||||
An undocumented op code used by ICE host software to perform
|
||||
memory cycles to the target system during HALT mode.
|
||||
|
|
|
|||
|
|
@ -27,22 +27,22 @@ Intel provided a fix for this on later processors, by delaying the acknowledgeme
|
|||
after a `MOV SS,xxx` or `POP SS` instruction; the delay lasts only one instruction, so you're obliged to change SP on
|
||||
the very next instruction.
|
||||
|
||||
Note that Intel's fix appears to have been over-broad: *all* `MOV segreg,xxx` and `POP segreg`
|
||||
Intel's fix also appears to have been overbroad: *all* `MOV segreg,xxx` and `POP segreg`
|
||||
instructions delay interrupts, not just `MOV SS,xxx` and `POP SS`. In fact, it's been
|
||||
[reported](http://www.malinov.com/Home/sergeys-projects/sergey-s-xt/historical-notes)
|
||||
that all PUSH *segreg* instructions also have the same delaying effect, at least on selected 80C88 processors.
|
||||
[reported](http://www.malinov.com/Home/sergeys-projects/sergey-s-xt/historical-notes) that all
|
||||
`PUSH segreg` instructions may also have the same delaying effect, at least on some 80C88 processors.
|
||||
|
||||
### Interrupted String Instructions With Multiple Prefixes Do Not Resume Correctly
|
||||
|
||||
If a repeated string instruction includes more than one override; eg:
|
||||
If a repeated string instruction includes more than one override prefix; eg:
|
||||
|
||||
REP ES: MOVSB
|
||||
|
||||
and an interrupt occurs, the instruction will restart with only the last override. This was never fixed in any
|
||||
8086/8088.
|
||||
and an interrupt occurs, the instruction will restart with the last override prefix byte, ignoring any
|
||||
preceding prefix bytes. This was never fixed in any 8086/8088.
|
||||
|
||||
The recommended work-around is to ensure that the segment override immediately precedes the instruction, and to rewrite
|
||||
the sequence:
|
||||
The recommended work-around is to ensure that the *segment override* is the last prefix byte, and then rewrite
|
||||
the operation like this:
|
||||
|
||||
top:
|
||||
REP ES: MOVSB
|
||||
|
|
@ -50,6 +50,9 @@ the sequence:
|
|||
JMP top
|
||||
done:
|
||||
|
||||
If you're not sure your assembler will output the `REP` and `ES:` overrides in the order shown, then you should
|
||||
generate the override bytes manually, using **DB** or a similar assembler directive.
|
||||
|
||||
8086 Undocumented Instructions
|
||||
---
|
||||
|
||||
|
|
@ -63,11 +66,16 @@ corresponding IP.
|
|||
There is no `POP CS` instruction on later x86 CPUs. The opcode was explicitly made invalid on the 80186/80188,
|
||||
but was reused on later CPUs (starting with the 80286) as the first byte in a series of two-byte opcodes.
|
||||
|
||||
### Duplicate Conditional Jumps (0x60-0x6F)
|
||||
|
||||
Opcodes 0x60 through 0x6F decode identically to the conditional jump opcodes at 0x70 through 0x7F, respectively.
|
||||
This is not true for any other x86 CPU.
|
||||
|
||||
### MOV segreg,xxx (0x8E)
|
||||
|
||||
Similar to `POP CS`, this instruction was of limited value when the selected *segreg* was CS.
|
||||
|
||||
Note that *segreg* was encoded as a 3-bit value in the second byte of the instruction, where:
|
||||
Note that *segreg* is encoded as a 3-bit value in the second byte of the instruction, where:
|
||||
|
||||
* 0 = ES
|
||||
* 1 = CS (invalid on 80286 and later)
|
||||
|
|
@ -80,17 +88,6 @@ Note that *segreg* was encoded as a 3-bit value in the second byte of the instru
|
|||
|
||||
On the 8086/8088/80186/80188, values 0-3 were treated the same as values 4-7, and all values were allowed.
|
||||
|
||||
### SETALC aka SALC (0xD6)
|
||||
|
||||
Performs an operation equivalent to `SBB AL,AL`, but without modifying any flags. In other words, AL will be set to
|
||||
0xFF or 0x00, depending on whether CF is set or clear. This instruction exists on all later x86 CPUs, but for some
|
||||
reason, it has never been documented.
|
||||
|
||||
### Duplicate Conditional Jumps (0x60-0x6F)
|
||||
|
||||
Opcodes 0x60 through 0x6F decode identically to the conditional jump opcodes at 0x70 through 0x7F, respectively.
|
||||
This is not true for any other x86 CPU.
|
||||
|
||||
### Duplicate RET and RETF Instructions (0xC0, 0xC1, 0xC8, 0xC9)
|
||||
|
||||
* Opcode 0xC0 decodes identically to RET n (0xC2)
|
||||
|
|
@ -98,14 +95,31 @@ This is not true for any other x86 CPU.
|
|||
* Opcode 0xC8 decodes identically to RETF n (0xCA)
|
||||
* Opcode 0xC9 decodes identically to RET n (0xCB)
|
||||
|
||||
Starting with the 80186, opcodes 0xC0 and 0xC1 were reused for new shift and rotate instruction groups, and opcodes
|
||||
0xC8 and 0xC9 became the `ENTER` and `LEAVE` instructions.
|
||||
Starting with the 80186, opcodes 0xC0 and 0xC1 were reused for new shift and rotate instruction groups,
|
||||
and opcodes 0xC8 and 0xC9 became the `ENTER` and `LEAVE` instructions.
|
||||
|
||||
### [AAM](/docs/x86/ops/AAM/) (0xD4)
|
||||
|
||||
While AAM is documented, it has undocumented features (eg, its ability to divide by values other than 10,
|
||||
and its effect on the flags). See the [AAM](/docs/x86/ops/AAM/) instruction for details.
|
||||
|
||||
### [AAD](/docs/x86/ops/AAD/) (0xD5)
|
||||
|
||||
While AAD is documented, it has undocumented features (eg, its ability to multiply by values other than 10,
|
||||
and its effect on the flags). See the [AAD](/docs/x86/ops/AAD/) instruction for details.
|
||||
|
||||
### [SALC](/docs/x86/ops/SALC/) (0xD6)
|
||||
|
||||
Performs an operation equivalent to `SBB AL,AL`, but without modifying any flags. In other words, AL will be set to
|
||||
0xFF or 0x00, depending on whether CF is set or clear. This instruction exists on all later x86 CPUs, but for some
|
||||
reason, it has never been documented. Also known as **SETALC**.
|
||||
|
||||
### Duplicate LOCK Prefix (0xF1)
|
||||
|
||||
It is believed that 0xF1 decodes identically to 0xF0 (the `LOCK` prefix).
|
||||
|
||||
On newer processors, 0xF1 is an undocumented instruction usually called `ICEBP` or `INT1`.
|
||||
On newer processors, 0xF1 is an undocumented instruction usually called `ICEBP` or `INT1`. See the
|
||||
[ICEBP](/docs/x86/ops/ICEBP/) instruction for details.
|
||||
|
||||
Assorted Publications
|
||||
---
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ redirect_from:
|
|||
- /pubs/pc/programming/os2/microsoft/ptk/1.0/
|
||||
---
|
||||
|
||||
[Microsoft OS/2 Programmer's Toolkit](../../)
|
||||
---
|
||||
|
||||
Welcome
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -6,10 +6,7 @@ redirect_from:
|
|||
- /pubs/pc/programming/os2/microsoft/ptk/1.0/plguide/
|
||||
---
|
||||
|
||||
Programmer's Toolkit
|
||||
---
|
||||
|
||||
Programmer's Learning Guide
|
||||
[Microsoft OS/2 Programmer's Learning Guide](../)
|
||||
---
|
||||
|
||||
Version 1.0
|
||||
|
|
@ -17,27 +14,27 @@ Version 1.0
|
|||
|
||||
### Contents
|
||||
|
||||
* 1.0 [Introduction](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/)
|
||||
* 1.1 [Overview](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/#overview)
|
||||
* 1.2 [What You Need to Start](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/#what-you-need-to-start)
|
||||
* 1.3 [What This Guide Covers](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/#what-this-guide-covers)
|
||||
* 1.4 [The Lqh Sample Program](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/#the-lqh-sample-program)
|
||||
* 1.5 [MS OS/2 Sample Programs](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/#ms-os2-sample-programs)
|
||||
* 1.6 [MS OS/2 and the C Run-time Library](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/#ms-os2-and-the-c-run-time-library)
|
||||
* 2.0 Overview
|
||||
* 2.1 Introduction
|
||||
* 2.2 Creating an MS OS/2 Program
|
||||
* 2.3 C-Language Header Files
|
||||
* 2.4 A Simple Program: Echoing the Command Line
|
||||
* 2.5 Using the MS OS/2 Naming Conventions
|
||||
* 2.6 Using Structures: Getting the Time of Day
|
||||
* 2.7 Using Bit Masks
|
||||
* 2.8 Sharing Resources: Playing a Tune
|
||||
* 3.0 Input and Output
|
||||
* 3.1 Introduction
|
||||
* 3.2 Opening Files
|
||||
* 3.3 Reading and Writing to Files
|
||||
* 3.4 Creating a File
|
||||
* 1.0 [Introduction](chapter1/)
|
||||
* 1.1 [Overview](chapter1/#overview)
|
||||
* 1.2 [What You Need to Start](chapter1/#what-you-need-to-start)
|
||||
* 1.3 [What This Guide Covers](chapter1/#what-this-guide-covers)
|
||||
* 1.4 [The Lqh Sample Program](chapter1/#the-lqh-sample-program)
|
||||
* 1.5 [MS OS/2 Sample Programs](chapter1/#ms-os2-sample-programs)
|
||||
* 1.6 [MS OS/2 and the C Run-time Library](chapter1/#ms-os2-and-the-c-run-time-library)
|
||||
* 2.0 [Overview](chapter2/)
|
||||
* 2.1 [Introduction](chapter2/#introduction)
|
||||
* 2.2 [Creating an MS OS/2 Program](chapter2/#creating-an-ms-os2-program)
|
||||
* 2.3 [C-Language Header Files](chapter2/#c-language-header-files)
|
||||
* 2.4 [A Simple Program: Echoing the Command Line](chapter2/#a-simple-program-echoing-the-command-line)
|
||||
* 2.5 [Using the MS OS/2 Naming Conventions](chapter2/#using-the-ms-os2-naming-conventions)
|
||||
* 2.6 [Using Structures: Getting the Time of Day](chapter2/#using-structures-getting-the-time-of-day)
|
||||
* 2.7 [Using Bit Masks](chapter2/#using-bit-masks)
|
||||
* 2.8 [Sharing Resources: Playing a Tune](chapter2/#sharing-resources-playing-a-tune)
|
||||
* 3.0 [Input and Output](chapter3/)
|
||||
* 3.1 [Introduction](chapter3/#introduction)
|
||||
* 3.2 [Opening Files](chapter3/#opening-files)
|
||||
* 3.3 [Reading and Writing to Files](chapter3/#reading-and-writing-to-files)
|
||||
* 3.4 [Creating a File](chapter3/#creating-a-file)
|
||||
* 3.5 Closing a File
|
||||
* 3.6 Standard Input and Output Files
|
||||
* 3.7 Redirecting Standard Files
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ redirect_from:
|
|||
- /pubs/pc/programming/os2/microsoft/ptk/1.0/plguide/chapter1/
|
||||
---
|
||||
|
||||
Microsoft OS/2 Programmer's Learning Guide
|
||||
[Microsoft OS/2 Programmer's Learning Guide](../)
|
||||
---
|
||||
|
||||
Introduction
|
||||
|
|
@ -111,6 +111,7 @@ threads | Creates and manages threads.
|
|||
timer | Sleeps and then beeps three times.
|
||||
version | Prints the DOS version (bound).
|
||||
vioreg | Registers a Vio subsystem.
|
||||
|
|
||||
|
||||
The following sample programs are extended examples that combine many of the features illustrated in the previous
|
||||
samples:
|
||||
|
|
@ -127,6 +128,7 @@ mandel | Displays the Mandelbrot set, using EGA high-resolution graphics.
|
|||
bigben | Displays a digital clock, demonstrating the Vio functions (bound).
|
||||
setega | Sets 25/43-line mode (bound).
|
||||
chaser | Demonstrates the use of threads (requires a mouse).
|
||||
|
|
||||
|
||||
### 1.6 MS OS/2 and the C Run-time Library
|
||||
|
||||
|
|
|
|||
385
pubs/pc/software/os2/microsoft/ptk10/plguide/chapter2/README.md
Normal file
385
pubs/pc/software/os2/microsoft/ptk10/plguide/chapter2/README.md
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
---
|
||||
layout: page
|
||||
title: "Microsoft OS/2 Programmer's Learning Guide: Overview"
|
||||
permalink: /pubs/pc/software/os2/microsoft/ptk10/plguide/chapter2/
|
||||
---
|
||||
|
||||
[Microsoft OS/2 Programmer's Learning Guide](../)
|
||||
---
|
||||
|
||||
Overview
|
||||
---
|
||||
|
||||
### 2.1 Introduction
|
||||
|
||||
This chapter explains the basic steps needed to create an MS OS/2
|
||||
C-language program. In particular, it explains how to do the following:
|
||||
|
||||
+ Use the **main** function for your program starting point.
|
||||
+ Use the *os2.h* header file for function declarations.
|
||||
+ Use INCL_ constants to selectively enable function groups.
|
||||
+ Use your program's command line.
|
||||
+ Use MS OS/2 naming conventions in your program sources.
|
||||
+ Use structures in MS OS/2 function calls.
|
||||
+ Use the AND and OR operators to examine and modify bit masks.
|
||||
+ Use care in programs that access shared resources.
|
||||
|
||||
### 2.2 Creating an MS OS/2 Program
|
||||
|
||||
Creating an MS OS/2 C-language program is no different than creating any other type of C-language program.
|
||||
You use the **main** function as your program starting point and create and call as many other functions as
|
||||
you need to complete the task. The following simple MS OS/2 program copies the line "Hello, world" to the screen:
|
||||
|
||||
#include <os2.h>
|
||||
|
||||
main( )
|
||||
{
|
||||
USHORT cbWritten;
|
||||
DosWrite(1, "Hello, world\r\n", 14, &cbWritten);
|
||||
}
|
||||
|
||||
The MS OS/2 system functions use many structures, data types, and constants that are not part of the standard
|
||||
C language. For example, the data type **USHORT** is a special MS OS/2 data type that specifies an unsigned short
|
||||
integer. To access these items, you need to include the MS OS/2 header file *os2.h* at the beginning of your program
|
||||
source file.
|
||||
|
||||
The MS OS/2 system functions are not standard C functions. They use the Pascal calling convention. This means,
|
||||
for example, that they expect parameters to be passed in right-to-left order instead of the standard leftto-right
|
||||
order of C functions. Therefore, to use the MS OS/2 functions in a C-language program, you must make sure they are
|
||||
declared with the **pascal** keyword, which directs the C compiler to generate proper instructions for the function
|
||||
call. Fortunately, all MS OS/2 functions are declared within the *os2.h* file, so including the file saves you the
|
||||
trouble of declaring each function individually.
|
||||
|
||||
The *os2.h* file also declares the parameter types for each function. This is convenient since many function
|
||||
parameters would otherwise require type casting to avoid compiler errors. For example, the **DosWrite** function
|
||||
shown in the previous example requires the second parameter to be a full 32-bit (far) address to the given string.
|
||||
Since the *os2.h* file declares the second parameter as such, the cast is carried out for you by the compiler.
|
||||
|
||||
### 2.3 C-Language Header Files
|
||||
|
||||
The MS OS/2 C-language header file *os2.h* contains the definitions you need to use the functions, data types,
|
||||
structures, and constants described in the *Microsoft Operating System/2 Programmer's Reference*.
|
||||
|
||||
When you include the *os2.h* file, the C preprocessor automatically defines many, but not all, of the most commonly
|
||||
used MS OS/2 functions. The *os2.h* header file is the first file of a set of files that contains the MS OS/2 function
|
||||
definitions. Each file contains definitions for the functions, data types, structures, and constants associated with
|
||||
a specific group of MS OS/2 functions. To minimize the time required to process the many header files, each function
|
||||
group is conditionally processed depending on whether a corresponding constant is defined within the program source file.
|
||||
The following is a list of these constants with descriptions of the function groups they represent:
|
||||
|
||||
**Constant** | **Meaning**
|
||||
:----------------- | :-------------
|
||||
INCL_BASE | Includes all MS OS/2 1.0 system function definitions.
|
||||
INCL_DOS | Includes all MS OS/2 1.0 kernel function definitions (Dos).
|
||||
INCL_SUB | Includes all MS OS/2 1.0 video, keyboard, and mouse functions (Vio, Kbd, and Mou).
|
||||
INCL_DOSDATETIME | Includes all date/time and timer functions.
|
||||
INCL_DOSDEVICES | Includes the device and IOPL support functions.
|
||||
INCL_DOSERRORS | Includes the MS OS/2 error constants.
|
||||
INCL_DOSFILEMGR | Includes all file-management functions.
|
||||
INCL_DOSINFOSEG | Includes all information-segment functions.
|
||||
INCL_DOSMEMMGR | Includes all memory-management functions.
|
||||
INCL_DOSMODULEMGR | Includes all module-manager functions.
|
||||
INCL_DOSMONITORS | Includes all monitor functions.
|
||||
INCL_DOSNLS | Includes national-language-support functions.
|
||||
INCL_DOSPROCESS | Includes all process- and thread-support functions.
|
||||
INCL_DOSQUEUES | Includes all queue and other miscellaneous functions.
|
||||
INCL_DOSRESOURCES | Includes resource-support functions (not available in MS OS/2 1.0).
|
||||
INCL_DOSSEMAPHORES | Includes all semaphore functions.
|
||||
INCL_DOSSESMGR | Includes all session-manager functions.
|
||||
INCL_DOSSIGNALS | Includes all signal functions.
|
||||
INCL_NOCOMMON | Excludes any function group not explicitly defined.
|
||||
|
|
||||
|
||||
To use a function within your program function, you simply define the corresponding constant by using the #define
|
||||
directive before including the *os2.h* file. For example, the following program includes definitions for the
|
||||
memory-manager and file-system functions:
|
||||
|
||||
#define INCL_DOSMEMMGR
|
||||
#define INCL_DOSFILEMGR
|
||||
#include <os2.h>
|
||||
|
||||
main( )
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
Once you have defined a constant, you may use any function, structure, or data type in that function group.
|
||||
|
||||
### 2.4 A Simple Program: Echoing the Command Line
|
||||
|
||||
In standard C-language programs, you can use the *argc* and *argv* parameters of the main function to retrieve
|
||||
individual copies of the commandline arguments. You can use these parameters in MS OS/2 programs, but you can also
|
||||
retrieve the entire command line, exactly as the user typed it, by using the **DosGetEnv** function.
|
||||
|
||||
When it starts a program, MS OS/2 prepares an environment segment for the program that contains definitions of all
|
||||
environment variables, as well as of the command line. The **DosGetEnv** function retrieves the segment selector
|
||||
for the program's environment segment and the address offset within that segment for the start of the command line.
|
||||
|
||||
You can echo the command line on the screen by using the **DosGetEnv** function to get the address of the command
|
||||
line in the environment segment, as shown in the following sample program:
|
||||
|
||||
#define INCL_DOSQUEUES
|
||||
#include <os2.h>
|
||||
|
||||
main( )
|
||||
{
|
||||
SEL selEnvironment;
|
||||
USHORT offCommand;
|
||||
PSZ pszCommandLine;
|
||||
USHORT cbWritten;
|
||||
USHORT i, cch;
|
||||
|
||||
DosGetEnv(&selEnvironment, &offCommand);
|
||||
pszCommandLine = MAKEP(selEnvironment, offCommand);
|
||||
|
||||
for (i = 0; pszCommandLine[i]; i++);
|
||||
for (i++, cch = 0; pszCommandLine[cch + i]; cch++);
|
||||
|
||||
DosWrite(1, &pszCommandLine[i] , cch, &cbWritten);
|
||||
}
|
||||
|
||||
The command line is in two parts. The first part is the program name, terminated by a zero byte. The second part
|
||||
is the rest of the command line, terminated by two zero bytes. This sample program echoes the command line by skipping
|
||||
over the program name, then writing everything up to the next zero byte to the screen. The first **for** statement
|
||||
skips over the command name; the second for statement computes the length of the string. The **MAKEP** macro creates
|
||||
the far pointer that is needed to access the command line in the environment segment.
|
||||
|
||||
You can also examine your program's environment by using the selector retrieved by the **DosGetEnv** function.
|
||||
The program's environment consists of the environment variables that have been declared and passed to the program.
|
||||
Each program has a unique environment that is typically inherited from the program that started it; for example,
|
||||
from the MS OS/2 command processor **cmd**.
|
||||
|
||||
You can use the **DosScanEnv** function to scan for a specific environment variable. This function takes the name
|
||||
of the environment variable that you are interested in and copies its current value to a buffer that you supply.
|
||||
The following program uses **DosScanEnv** to display the value of the environment variable specified in the command
|
||||
line:
|
||||
|
||||
#define INCL_DOSQUEUES
|
||||
#include <os2 .h>
|
||||
|
||||
main( )
|
||||
{
|
||||
SEL selEnvironment;
|
||||
USHORT offCommand;
|
||||
PSZ pszCommandLine;
|
||||
PSZ pszValue;
|
||||
USHORT cbWritten;
|
||||
USHORT i , cch;
|
||||
|
||||
DosGetEnv(&selEnvironment, &offCommand);
|
||||
pszCommandLine = MAKEP(selEnvironment, offCommand);
|
||||
|
||||
for (i = 0 ; pszCommandLine[i); i++);
|
||||
for (i++; pszCommandLine[i] == ' '; i++);
|
||||
|
||||
if (!DosScanEnv (&pszCommandLine[i), &pszValue)) {
|
||||
for (cch = 0; pszValue[cch); cch++);
|
||||
DosWrite(1, pszValue, cch, &cbWritten);
|
||||
}
|
||||
}
|
||||
|
||||
### 2.5 Using the MS OS/2 Naming Conventions
|
||||
|
||||
The sample programs in this manual use the MS OS/2 naming conventions for their variables and functions.
|
||||
These conventions define how to create names that indicate both the purpose and data type of an item used
|
||||
with the MS OS/2 system functions. When you use the conventions in your source files, you help others
|
||||
who may read your sources to readily identify the purpose and type of the functions, variables, structures, fields,
|
||||
and constants.
|
||||
|
||||
The following list briefly describes the MS OS/2 naming conventions:
|
||||
|
||||
**Item** | **Convention**
|
||||
:----------------- | :-------------
|
||||
Variable | All names consist of three elements: a prefix, a base type, and a qualifier.
|
||||
| The base type identifies the data type of the item; the prefix specifies additional
|
||||
| information, such as whether the item is a pointer, an array, or a count of
|
||||
| bytes; and the qualifier specifies the purpose of the item. The prefix and base
|
||||
| type are lowercase, and the qualifier is mixed-case.
|
||||
|
|
||||
Parameter | Same as a variable.
|
||||
|
|
||||
Structure Field | Same as a variable.
|
||||
|
|
||||
Structure | All names consist of a word or phrase that specifies the purpose of the structure.
|
||||
| All letters in the name are uppercase.
|
||||
|
|
||||
Constant | All names consist of a prefix, derived from the name of the function associated with
|
||||
| the constant, and a word or phrase that specifies the meaning of the constant in terms
|
||||
| of a value, action, color, or condition. All letters in the name are uppercase and an
|
||||
| underscore separates the prefix from the rest of the name.
|
||||
|
|
||||
Function name | All names consist of a three-letter system prefix followed by a word or phrase that
|
||||
| describes the action of the function. Each word in the function name starts with an
|
||||
| uppercase letter. Verb-noun combinations, such as **DosGetDateTime**, are recommended.
|
||||
|
|
||||
|
||||
The following examples show some of the standard prefix and base types you will see in this manual:
|
||||
|
||||
/* Base Types */
|
||||
BOOL fSuccess; /* f Boolean flag. TRUE if successful */
|
||||
CHAR chChar; /* ch 8-bit character */
|
||||
SHORT sRate; /* s 16-bit signed integer */
|
||||
LONG lDistance; /* l 32-bit signed integer */
|
||||
UCHAR uchScan; /* uch 8-bit unsigned character */
|
||||
USHORT usHeight; /* us 16-bit unsigned integer */
|
||||
ULONG ulWidth; /* ul 32-bit unsigned integer */
|
||||
BYTE bAttribute; /* b 8-bit unsigned integer */
|
||||
CHAR szName[]; /* sz zero-terminated array of characters */
|
||||
BYTE fbMask; /* fb array of flags in a byte */
|
||||
USHORT fsMask; /* fs array of flags in a short */
|
||||
ULONG flMask; /* fl array of flags in a long */
|
||||
SEL selSegment; /* sel 16-bit segment selector */
|
||||
|
||||
/* Prefixes */
|
||||
PCH pchBuffer; /* p 32-bit far pointer to a given type */
|
||||
NPCH npchBuffer; /* np 16-bit newr pointer to a given type */
|
||||
CHAR achData[1]; /* a array of a given type */
|
||||
USHORT ichIndex; /* i index to an array of a given type */
|
||||
USHORT cb; /* c count of items of a given type */
|
||||
HFILE hf; /* hf handle identifying a given object */
|
||||
USHORT offSeg; /* off offset */
|
||||
USHORT idSession; /* id identifier for a given object */
|
||||
|
||||
When you are naming variables, remember that the prefix and base type are optional for common integer
|
||||
types such as **SHORT** and **USHORT**.
|
||||
|
||||
### 2.6 Using Structures: Getting the Time of Day
|
||||
|
||||
Many MS OS/2 functions use structures for input and output parameters. To use a structure in an MS OS/2
|
||||
function, you first define the structure in your program, then pass a 32-bit far address to the structure
|
||||
as a parameter in the function call.
|
||||
|
||||
For example, the **DosGetDateTime** function copies the current date and time to a **DATETIME** structure
|
||||
whose address you supply. The fields of the **DATETIME** structure define the month, day, and year, as well as
|
||||
the time of day (to hundredths of a second). The **DATETIME** structure, defined in the *os2.h* file, has the
|
||||
following form:
|
||||
|
||||
typedef struct _DATETIME { /* date */
|
||||
UCHAR hours;
|
||||
UCHAR minutes;
|
||||
UCHAR seconds;
|
||||
UCHAR hundredths;
|
||||
UCHAR day;
|
||||
UCHAR month;
|
||||
USHORT year;
|
||||
SHORT timezone;
|
||||
UCHAR weekday;
|
||||
} DATETIME;
|
||||
|
||||
To retrieve the date and time, you call the **DosGetDateTime** function and use the address operator (&) to
|
||||
specify the address of your **DATETIME** structure in the call. The following example shows how to make the call:
|
||||
|
||||
#include <os2.h>
|
||||
|
||||
CHAR szDayName[] = "MonTueWedThuFriSatSun";
|
||||
CHAR szMonthName[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
|
||||
CHAR szDate[] = "xx:xx:xx xxx xxx xx, xxxx\r\n";
|
||||
|
||||
main( )
|
||||
{
|
||||
DATETIME date;
|
||||
SHORT offset;
|
||||
SHORT i;
|
||||
USHORT usYear;
|
||||
USHORT cbWritten;
|
||||
|
||||
DosGetDateTime(&date); /* Address of the DATETIME structure */
|
||||
|
||||
szDate[0] = (date.hours/10) + '0';
|
||||
szDate[1] = (date.hours%10) + '0';
|
||||
szDate[3] = (date.minutes/10) + '0';
|
||||
szDate[4] = (date.minutes%10) + '0';
|
||||
szDate[6] = (date.seconds/10) + '0';
|
||||
szDate[7] = (date.seconds/10) + '0';
|
||||
offset = date.weekday * 3;
|
||||
for (i = 0; i < 3; i++)
|
||||
szData[i + 9] = szDayName[i + offset];
|
||||
offset = (date.month - 1) * 3;
|
||||
for (i = 0; i < 3; i++)
|
||||
szDate[i + 13] = szMonthName[i + offset];
|
||||
szDate[17] = (date.day < 10)?' ':(date.day/10 + '0');
|
||||
szDate[18] = (date.day%10) + '0';
|
||||
usYear = date.year;
|
||||
szDate[21] = (usYear/1000) + '0';
|
||||
usYear = usYear % 1000;
|
||||
szDate[22] = (usYear/100) + '0';
|
||||
usYear = usYear % 100;
|
||||
szDate[23] = (usYear/10) + '0';
|
||||
szDate[24] = (usYear%10) + '0';
|
||||
|
||||
DosWrite(1, szDate, 27, &cbWritten);
|
||||
}
|
||||
|
||||
One drawback of using MS OS/2 functions exclusively is that there are no formatted output functions,
|
||||
such as the **printf** function. This sample program, therefore, formats the data itself before displaying it.
|
||||
The program uses the integer-division operators (/ and %) to convert binary numbers to ASCII characters.
|
||||
The program then copies the ASCII characters to a string and displays the string by using the **DosWrite** function.
|
||||
|
||||
Some MS OS/2 functions require that you fill one or more fields of the structure before making the function call.
|
||||
For example, there are some structures whose length depends on the version of the operating system being used;
|
||||
MS OS/2 requires that you supply the expected length so that the function does not copy data beyond the end of your
|
||||
structure.
|
||||
|
||||
### 2.7 Using Bit Masks
|
||||
|
||||
In MS OS/2, many functions use bit masks. A bit mask (also called an array of flags) is a combination of two
|
||||
or more Boolean flags in a single byte, word, or double-word value. In C-language programs, you can use the
|
||||
bitwise AND, OR, and NOT operators to examine and set the values in a bit mask.
|
||||
|
||||
If a function retrieves a bit mask, you can check a specific flag in the bit mask by using the AND operator,
|
||||
as shown in the following example:
|
||||
|
||||
USHORT fsEvents;
|
||||
|
||||
if (fsEvent & 0x0004)
|
||||
/* Is the flag set */
|
||||
|
||||
Or you can set a flag in a bit mask by using the OR operator, as shown in the following example:
|
||||
|
||||
ULONG flFunctions;
|
||||
|
||||
flFunctions = flFunctions | KR_KBDPEEK;
|
||||
|
||||
Finally, you can clear a flag in a bit mask by using the AND and NOT operators, as shown in the following example:
|
||||
|
||||
USHORT fsEvent;
|
||||
|
||||
fsEvents = fsEvent & ~0x0004;
|
||||
|
||||
### 2.8 Sharing Resources: Playing a Tune
|
||||
|
||||
Many MS OS/2 functions let you use the resources of the computer, such as the keyboard, screen, disk, and even
|
||||
the system speaker. Since MS OS/2 is a multitasking operating system and more than one program can run at a time,
|
||||
MS OS/2 considers all resources of the computer to be shared resources. As a result, programs must cooperate with
|
||||
other running programs and must not claim exclusive access to a given resource.
|
||||
|
||||
Consider a simple program that plays a short tune by using the **DosBeep** function. This function, when called
|
||||
by a single program, generates a tone at the system speaker, but if two programs call **DosBeep** at the same time,
|
||||
the result is chaos. Try running two or more copies of the following program at the same time:
|
||||
|
||||
#include <os2.h>
|
||||
|
||||
#define CNOTES 14
|
||||
USHORT ausTune[] = {
|
||||
440,1000,
|
||||
480,1000,
|
||||
510,1000,
|
||||
550,1000,
|
||||
590,1000,
|
||||
620,1000,
|
||||
660,1000
|
||||
};
|
||||
|
||||
main( )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CNOTES; i+= 2)
|
||||
DosBeep(ausTune[i] , ausTune[i + 1]);
|
||||
}
|
||||
|
||||
The first argument to the **DosBeep** function specifies the frequency of the note. The second argument specifies
|
||||
the duration. The array ausTune defines values for the frequency and duration of each note in the tune.
|
||||
|
||||
**DosBeep** is intended to be used for signaling the user when an error occurs, such as pressing an incorrect key.
|
||||
Since the system speaker is a shared resource, a process should use the **DosBeep** function sparingly.
|
||||
148
pubs/pc/software/os2/microsoft/ptk10/plguide/chapter3/README.md
Normal file
148
pubs/pc/software/os2/microsoft/ptk10/plguide/chapter3/README.md
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
---
|
||||
layout: page
|
||||
title: "Microsoft OS/2 Programmer's Learning Guide: Input and Output"
|
||||
permalink: /pubs/pc/software/os2/microsoft/ptk10/plguide/chapter3/
|
||||
---
|
||||
|
||||
[Microsoft OS/2 Programmer's Learning Guide](../)
|
||||
---
|
||||
|
||||
Input and Output
|
||||
---
|
||||
|
||||
### 3.1 Introduction
|
||||
|
||||
Input and output are two of the most important tasks that any program carries out. This chapter explains how
|
||||
to read from and write to files on disks and other input and output devices, such as printers, modems, and the
|
||||
system console.
|
||||
|
||||
### 3.2 Opening Files
|
||||
|
||||
Before carrying out any input or output operation, you need a file handle. A file handle is a 16-bit value
|
||||
that identifies the file or device that you want to read from or write to. You can create a file handle by using
|
||||
the **DosOpen** function, which opens the specified file and returns a file handle for it. For example, in the
|
||||
following statements, **DosOpen** opens the existing file *simple.txt* for reading and copies the file handle to the
|
||||
*hf* variable:
|
||||
|
||||
HFILE hf;
|
||||
USHORT usResult;
|
||||
|
||||
DosOpen("simple.txt", /* filename */
|
||||
&hf, /* file handle */
|
||||
&usResult, /* action taken */
|
||||
0, /* size */
|
||||
0, /* file attribute */
|
||||
0x0001, /* open method */
|
||||
0x0040, /* access and sharing method */
|
||||
0); /* reserved */
|
||||
|
||||
If the **DosOpen** function opens the file, it copies the file handle to the *hf* variable and copies a value to
|
||||
the *usResult* variable to indicate what action was taken (for example, 0x0001 for "existing file opened"). To open
|
||||
an existing file, a size and file attribute are not needed, so the fourth and fifth arguments are set to zero.
|
||||
The sixth argument, 0x0001, directs **DosOpen** to open the file if it exists or to return an error if it does not
|
||||
exist. The next argument, 0x0040, directs **DosOpen** to open the file for reading only and let other programs open
|
||||
the file even while the current program has it open. The final argument is reserved and should always be zero.
|
||||
|
||||
The **DosOpen** function indicates that it successfully opened the file by returning zero. You can then use the file
|
||||
handle returned in the *hf* variable in subsequent functions to read data from the file or to check the status or
|
||||
other characteristics of the file. If **DosOpen** fails to open the file, it returns an error value. For example,
|
||||
if the file cannot be found in the current directory, the function returns the value 0x0002.
|
||||
|
||||
When you open a file, you must specify whether you want to read from the file, write to it, or both read and write.
|
||||
You must also specify whether you want other processes to have access to the file while you have it open. You do this
|
||||
by combining two values. These values specify the access and sharing methods and are described in the following list:
|
||||
|
||||
**Value** | **Meaning**
|
||||
:----------------- | :-------------
|
||||
0x0000 | Open a file for reading.
|
||||
0x0001 | Open a file for writing.
|
||||
0x0002 | Open a file for reading and writing.
|
||||
0x0010 | Open a file for exclusive use, denying read and write access by other processes.
|
||||
0x0020 | Deny write access to a file by other processes.
|
||||
0x0030 | Deny read access to a file by other processes.
|
||||
0x0040 | Open a file with no sharing restrictions, granting read and write access to all processes.
|
||||
|
|
||||
|
||||
In general, you may combine any access method (read, write, or read and write) with any sharing method
|
||||
(deny reading, deny writing, deny reading and writing, or grant any access). Some combinations have to be
|
||||
handled carefully, however, such as opening a file for writing without denying access to it by other processes.
|
||||
|
||||
### 3.3 Reading and Writing to Files
|
||||
|
||||
Once you have opened a file and have a file handle, you can read from or write to the file by using the
|
||||
**DosRead** or **DosWrite** function. The **DosRead** function copies a specified number of bytes (up to the
|
||||
end of the file) from the file to the buffer you specify. The **DosWrite** function copies bytes from a buffer
|
||||
to the file.
|
||||
|
||||
To read from a file, you must open it for reading, or reading and writing. The following example shows how to
|
||||
open the file named *sample.txt* and read the first 512 bytes from it:
|
||||
|
||||
HFILE hf;
|
||||
USHORT usResult;
|
||||
BYTE abBuffer[512];
|
||||
USHORT cbRead;
|
||||
|
||||
if (!DosOpen("sample.txt", &hf, &usResult, 0, 0,
|
||||
0x0001, 0x0040, 0)) {
|
||||
DosRead(hf, abBuffer, 512, &cbRead);
|
||||
DosClose(hf);
|
||||
}
|
||||
|
||||
If the file does not have 512 bytes, **DosRead** reads up to the end of the file and copies the number of bytes
|
||||
read to the *cbRead* variable. If the function has already read to the end of the file and there are no more bytes
|
||||
to read, it copies zero to the *cbRead* variable.
|
||||
|
||||
To write to a file, you must open it first for writing, or for reading and writing. The following example shows
|
||||
how to open the file *sample.txt* again and write 512 bytes to it:
|
||||
|
||||
HFILE hf;
|
||||
USHORT usResult;
|
||||
BYTE abBuffer[512);
|
||||
USHORT cbWritten;
|
||||
|
||||
if (!DosOpen("sample.txt", &hf, &usResult, 0, 0,
|
||||
0x0011, 0x0041, 0)) {
|
||||
DosWrite(hf, abBuffer, 512, &cbWritten);
|
||||
DosClose(hf);
|
||||
}
|
||||
|
||||
The **DosWrite** function writes the contents of the buffer to the file. If it fails to write 512 bytes
|
||||
(for example, if the disk is full), the function copies the number of bytes written to the *cbWritten* variable.
|
||||
|
||||
### 3.4 Creating a File
|
||||
|
||||
You can also create new files by using the **DosOpen** function. Once you have created a new file, you may read
|
||||
from or write to it just as you would with an existing file.
|
||||
|
||||
To create a new file, set the sixth parameter to the value 0x0010. The **DosOpen** function then creates the file
|
||||
if it does not already exist. In the following example, the **DosOpen** function creates the file *newfile.txt*:
|
||||
|
||||
HFILE hf;
|
||||
USHORT usResult;
|
||||
|
||||
DosOpen("newfile.txt", /* filename */
|
||||
&hf, /* file handle */
|
||||
&usResult, /* action taken */
|
||||
0, /* size */
|
||||
0x0000, /* normal file attribute */
|
||||
0x0010, /* Creates the file if it does not exist */
|
||||
0x0011, /* write access, share with none */
|
||||
0);
|
||||
|
||||
In this example, **DosOpen** creates the file and opens it for writing. Note that the sharing method denies
|
||||
any access to all processes, so no other process can open the file while it remains open. The new file is empty
|
||||
(it contains no data).
|
||||
|
||||
When a new file is created, the attribute argument (fifth) specifies the file attribute. In the preceding example,
|
||||
the attribute argument is 0x0000, so the file is created as a normal file. Other possible file attributes are
|
||||
readonly and hidden, which correspond to the values 0x0001 or 0x0002, respectively.
|
||||
|
||||
The file attribute affects how other processes access the file. For example, if the file is read-only, no process
|
||||
may open the file for writing. The one exception to this rule is that the process that creates the read-only file
|
||||
may write to it immediately after creating it. After closing the file, however, the process may not open it for
|
||||
writing again.
|
||||
|
||||
When a file is created, the size argument (fourth) specifies the original size of the new file. For example,
|
||||
if 256 is specified, the new file is 256 bytes long. These 256 bytes, however, are undefined. It is up to the
|
||||
program to write valid data to the file. In any case, no matter what size you specify, subsequent calls to the
|
||||
**DosWrite** function copy data to the beginning of the file.
|
||||
Loading…
Reference in a new issue