CPGuide - Introduction to the Control Program

The purpose of this reference is to give information about functions, constants, and data structures. It provides information about the functions which enable the user to call functions in the C programming language.

The following information is provided:
 * The syntax and parameters for each function
 * The syntax of each data type and structure

Control Program Fundamentals
OS/2 is an advanced, multitasking, operating system for personal computers. OS/2 has a rich application programming interface (API) that supports: OS/2 also provides advanced file system features such as installable file systems, extended file attributes, and long file names.
 * Multitasking
 * Interprocess communication
 * Error and exception handling
 * Dynamic (run-time) linking
 * Graphical user interface (GUI)

OS/2 runs on and takes full advantage of the 80386 microprocessor. Features based on the 80386 microprocessor include: OS/2 provides a windowed, graphical user interface called the Presentation Manager (PM).
 * 32-bit operands and operations
 * Flat (non-segmented) 4 gigabyte address space
 * 32-bit memory pointers
 * Hardware-based memory protection and task management

Control Program Functionality
The lowest-level functions supplied by the OS/2 operating system are those provided by the kernel and the kernel's subsystems-the control programs of the operating system. The Control Program functions involve the most basic aspects of program execution, such as memory management, file handling, and process, thread, and session management. They also involve more sophisticated programming tasks, such as exception handling and interprocess communications. The names of all the system functions in the Control Program API are prefixed with the letters "Dos", as in DosAllocMem.

This book describes the following topics from the operating system's Control Program API:
 * File and disk management
 * Memory management
 * Program execution control (Process and session management)
 * Semaphores
 * Pipes
 * Queues
 * Timing functions
 * Error handling
 * Exception handling
 * Device I/O support
 * Message management
 * National language support and code page management
 * Debugging
 * Dynamic Linking

File System and File Management
The file system is the component of the operating system that supports storing information on mass storage devices, such as hard disks and diskettes. Applications view a file as a logical sequence of data; the file system manages the physical locations of data on the storage device for the application and specifies how the device and the stored information are formatted.

The file system also manages file I/O operations. Applications use file system functions to open, read, write, and close disk files. File system functions enable an application to maintain the disk that holds the files-volumes, directories, and files on the disks of the computer. Applications also use OS/2 file system functions to perform I/O operations to pipes and peripheral devices connected to the computer, such as the printer.

The file system also supports redirection of input and output, for example redirecting output from the display to a disk file or to the printer.

There are two types of file systems supported by the OS/2 operating system. The first is the File Allocation Table (FAT) file system. The FAT file system is the file system used by DOS The second type of file system supported by the operating system is the installable file system (IFS). Installable file systems are external to the base operating system and are loaded by the operating system when the computer is started. The High Performance File System (HPFS) included with the OS/2 operating system is an installable file system.

Memory Management
The key features of OS/2 memory management are paged virtual memory and a 32-bit linear (flat) address space that is mapped through page tables to physical memory. This is in contrast to the segmented memory model used in previous versions of the operating system.

An application can allocate memory for its own use or to be shared with other applications.

Program Execution and Control
Multitasking is the ability of the operating system to manage the execution of more than one application at a time. For the programmer, this includes the ability to multitask your own programs.

The OS/2 operating system supports two forms of multitasking for programs. An application can start other programs that will execute concurrently with the application. These programs can be a new copy of the application, a related program that is designed to work with the application, or an unrelated program. The operating system provides functions to communicate with and control the programs started by the application.

The OS/2 operating system also enables applications to run multiple threads of execution within the same application; separate activities can be multitasked within the application. An example of this is dispatching a separate subroutine to load a file and having the subroutine execute at the same time the main routine continues to monitor and respond to user input.

Semaphores
Semaphores signal the beginning and ending of an operation and provide mutually exclusive ownership of resources. Typically, semaphores are used to prevent more than one process or thread within a process from accessing a resource, such as shared memory, at the same time.

Semaphores are defined by the system and reside in an internal memory buffer. They are divided into three types, according to the functionality they provide:
 * Event semaphores enable a thread to notify waiting threads that an event has occurred.
 * Mutual exclusion (mutex) semaphores enable threads to serialize their access to shared resources.
 * Multiple Wait (muxwait) semaphores enable threads to wait either for multiple events to occur, or for multiple resources to become available.

Pipes
A pipe is a named or unnamed buffer used to pass data between processes. A process writes to or reads from a pipe as though the pipe were standard input or standard output. A parent process can use pipes to control the input that a child process receives and to receive the output that the child process produces. There are two types of pipes-named and unnamed.

Queues
A queue is a named, ordered list of elements that is used to pass information between related or unrelated processes. The owner of the queue (the server process) can choose the order in which to read incoming information and can examine queue elements without removing them from the queue. Queue elements can be added and accessed in First-In-First-Out (FIFO), Last-In-First-Out (LIFO), or priority-based order.

Timers
Timers enable an application to suspend operation for a specific length of time, to block a thread of execution until an interval has elapsed, or to post an event semaphore at repeated intervals.

Error Management
The OS/2 operating system provides functions to facilitate error processing. DosErrClass returns a classification of the error and a recommended action. DosError enables an application to prevent the operating system from displaying the default error message in a pop-up window when either a hard error or a software exception occurs.

Exception Management
A multitasking operating system must manage applications carefully. A serious error (such as an attempt to access protected memory) occurring in one application cannot be permitted to damage any other application in the system. To manage errors that might damage other applications, the OS/2 operating system defines a class of error conditions called exceptions and defines default actions for those errors.

An exception is an abnormal condition that can occur during program execution. Common causes of exceptions include I/O errors and access protection violations. When an exception is caused by the user pressing Ctrl+Break or Ctrl+C, the exception is called a signal exception.

When an exception occurs, the default action usually taken by the operating system is to terminate the application that caused the exception. An application can register its own exception handling routine and try to handle the exception itself. It might be possible for the application to correct the condition that caused the exception and continue execution.

Device I/O
A device is a piece of hardware used for input and output. Devices used with computers include the keyboard, video display, mouse, diskette and hard disk drives, and external systems, such as modems and printers. The operating system supplies functions that can be used to access and control such devices.

Message Management
For full-screen applications, text messages-used by an application to display information to the user-can be held in a message file. Keeping an application's messages in a message file simplifies changing those messages, which, for example, can facilitate marketing an application in several countries simultaneously.

National Language Support and Code Page Management
Many applications must support more than one national language, for example, French and German. This requirement is simplified through the use of such resources as string tables, menu templates, dialog templates, and accelerator tables.

A code page is a table that defines how characters are encoded. Code page management enables a user to select a code page for keyboard input, and screen and printer output before starting an application, a system command, or a utility program in the OS/2 multitasking environment.

Debugging
Debugging is the process of detecting, diagnosing, and eliminating errors in programs. A debugger program is designed to interact with the application that it is debugging. Because of the protected mode architecture of the OS/2 operating system, special steps must be taken to allow a debugging program to perform its functions in the program being debugged. DosDebug enables one application to control the execution of another application for debugging purposes.

I/O Control Functions
The OS/2 operating system provides functions to allow an application or subsystem to send device-specific control commands to a physical device driver. These IOCtls are subfunctions issued through the DosDevIOCtl function.

For a complete listing of IOCtl functions, see Generic IOCtl Commands.

Dynamic Linking
Dynamic linking permits several applications to use a single copy of an executable module. The executable module is completely separate from the applications that use it. Several functions can be built into a DLL, and applications can use these functions as though they were part of the application's executable code. You can change the dynamically-linked functions without recompiling or relinking the application.

Notation Conventions
The following notation conventions are used in this reference:
 * NULL:The term NULL applied to a parameter is used to indicate the presence of the pointer parameter, but with no value.
 * NULLHANDLE:The term NULLHANDLE applied to a parameter is used to indicate the presence of the handle parameter, but with no value.
 * Implicit Pointer If no entry for a data type "Pxxxxxxx" is found in Data Types, then it is implicitly a pointer to the data type "xxxxxxx". See Implicit Pointer Data Types for more information about implicit pointers.
 * Constant Names All constants are written in uppercase to match the header files. Where applicable, constant names have a prefix derived from the name of a function, message, or idea associated with the constant. For example:
 * WM_CREATEWindow ::message
 * SV_CXICONSystem ::value
 * CF_TEXTClipboard ::format.
 * In this book, references to a complete set of constants with a given prefix is written as shown in the following examples:
 * Window message:WM_*
 * System value:SV_*

Parameters and Fields Function parameters and data structure fields are shown in italics.

Conventions Used in Function Descriptions
This section provides information about the notation conventions and function descriptions used in this reference.

The documentation for each function contains the following sections:
 * Syntax:The function syntax describes the C-language calling syntax of the function and gives a brief description.


 * Programming Note
 * The functions in this book are spelled in mixed-case for readability but are known to the system as uppercase character strings. If you are using a compiler that generates a mixed-case external name, you should code the functions in uppercase.


 * Parameters
 * Each parameter is listed with its C-language data type, parameter type, and a brief description.


 * All data types are written in uppercase to match the header files. A data type of "Pxxxxxxx" implicitly defines a pointer to the data type "xxxxxxx".


 * The term NULL applied to a parameter indicates the presence of the parameter, with no value.


 * Refer to Data Types for a complete list of all data types and their descriptions.


 * There are three parameter types:


 * Input Specified by the programmer.
 * Output Returned by the function.
 * Input/Output Specified by the programmer and modified by the function.


 * A brief description is provided with each parameter. Where appropriate, restrictions are also included. In some cases, the parameter points to a structure.


 * Returns
 * A list of possible return codes or errors (when appropriate) is included in this section. Some functions do not have return codes. Refer to Errors for a complete list of all return codes and their descriptions.


 * Remarks
 * This section contains additional information about the function, when required.


 * Related Functions
 * This list shows the functions (if any) that are related to the function being described.


 * Example Code
 * An example for each function is shown in the C programming language.

Error Severities
Each of the error conditions given in the list of errors for each function falls into one of these areas:


 * Warning:The function detected a problem, but took some remedial action that enabled the function to complete successfully. The return code in this case indicates that the function completed successfully.
 * Error:The function detected a problem for which it could not take any sensible remedial action. The system has recovered from the problem, and the state of the system, with respect to the application, remains the same as at the time when the function was requested. The system has not even partially executed the function (other than reporting the error).
 * Severe Error:The function detected a problem from which the system could not reestablish its state, with respect to the application, at the time when that function was requested; that is, the system partially executed the function. This necessitates the application performing some corrective activity to restore the system to some known state.
 * Unrecoverable Error:The function detected some problem from which the system could not re-establish its state, with respect to the application, at the time when that call was issued. It is possible that the application cannot perform some corrective action to restore the system to some known state.

Header Files
All functions require an "#include" statement for the system header file OS2.H: Most functions also require a "#define" statement to select an appropriate (conditional) section of the header file, and hence, the required prototype. Where this is necessary, it is shown at the head of the function definition in the form:
 * 1) include 
 * 1) define  INCL_name
 * Note: These "#define" statements must precede the "#include " statement.

Addressing Elements in Arrays
Constants defining array elements are given values that are zero-based in C; that is, the numbering of the array elements starts at zero, not one.

For example, in the DevQueryCaps function, the sixth element of the ulArray parameter is CAPS_HEIGHT, which is equated to 5.

Count parameters related to such arrays always mean the actual number of elements available; therefore, again using the DevQueryCaps function as an example, if all elements up to and including CAPS_HEIGHT are provided for, lCount could be set to (CAPS_HEIGHT+1).

In functions for which the starting array element can be specified, this is always zero-based, and so the C element number constants can be used directly. For example, to start with the CAPS_HEIGHT element, the lStart parameter can be set to CAPS_HEIGHT.

Implicit Pointer Data Types
A data type name beginning with "P" (for example, PERRORCODE) is likely to be a pointer to another data type (in this instance, ERRORCODE).

In the data type summary, Data Types, no explicit "typedefs" are shown for pointers; therefore, if no data type definition can be found in the summary for a data type name "Pxxxxxx", it represents a pointer to the data type "xxxxxx", for which a definition should be found in the reference.

The implicit type definition needed for such a pointer "Pxxxxxx" is: typedef xxxxxx *Pxxxxxx; Such definitions are provided in the header files.

Storage Mapping of Data Types
The storage mapping of the data types is dependent on the machine architecture. To be portable, applications must access the data types using the definitions supplied for the environment in which they will execute.

Double-Byte Character Set (DBCS)
Throughout this publication, you will see references to specific value for character strings. The values are for single-byte character set (SBCS). If you use the double-byte character set (DBCS), note that one DBCS character equals two SBCS characters.

Programming Considerations
This section provides information you need to consider before you begin programming with Control Program functions.

Stack Size
Existing 16-bit applications (small and tiny models) must have a 4KB stack available when they enter system calls; otherwise, the stack can overflow into the data area.

Presentation Manager
The Presentation Manager component of the OS/2 operating system is based on the IBM Systems Application Architecture (SAA) Common Programming Interface-an architecture for the design and development of applications.

The Presentation Manager component implements the Common User Access (CUA) interface, which you can use to attain consistency in the appearance and behavior of your applications.

Addressing Capabilities
The operating system supports the addressing capabilities of the Intel 80386, 80386SX, 80387, 80387 NPX, 80486, and Pentium processors, with page-level memory protection. One page is 4KB (KB equals 1024 bytes) of contiguous physical memory.

C++ Considerations
This section contains several topics you should take into consideration if you are using C++.

C++ Header Files
OS/2 functions that used to take a PSZ as a parameter, and that do not modify the contents of the passed string, have been updated in the C++ header files to take a PCSZ data type parameter. The use of PCSZ allows for better optimization by the compiler and is more semantically compatible with C++. Existing code that calls functions that use PSZ will continue to work correctly.

Several of the typedefs have been changed in the C++ header files. For example, many items that are unsigned char in the C header files are char in the C++ header files. For instance, typedef unsigned char BYTE; has changed to typedef char BYTE; The existing samples that are included in the IBM Developer's Toolkit for OS/2 Warp Version 3 can be used with either set of the header files.

PCSZ Data Types

 * Note: The PCSZ data type is defined in the C++ header files included with this product. The use of the "const" keyword is not necessarily specific to C++. Certain C compilers support it as well.

If a function takes as a parameter a string that is not changed by the function, the string parameter can be declared as a "const" string or a PCSZ. PCSZ is defined in the C++ header files as a "const" pointer to a NULL-delimited string. The "const" indicates that the function will not change the contents of the string.

Declaring the parameter as PCSZ informs the C++ compiler that the function will not change the string. Therefore, the compiler simply passes a pointer to the string in the function parameter list. If the parameter is declared as a normal PSZ (not "const"), the compiler assumes that the function might change the string. Under these circumstances the compiler will add code to make a copy of the string and then pass a pointer to the copy, rather than pass a pointer to the original string.

A smaller, faster executable is often produced if the data item passed in a parameter list is declared as "const".

If the data item is declared as "const" then it must not be changed by the function.

LINK386
The C++ compiler will provide a dynamic link library which is used by LINK386 when generating error messages. This DLL will convert a compiler generated mangled name into the function prototype. If the DLL is not present, an error message will be displayed and LINK386 will display the compiler-generated, mangled name in the error message.