Windows Principles
It is helpful to keep in mind some basic Windows principles. The Windows API is different in many ways, both large and small, from other APIs such as the POSIX API familiar to UNIX and Linux programmers. Although Windows is not inherently difficult, it requires some changes in coding style and technique.Here are some of the major characteristics of Windows, which will become much more familiar as you read through the book.Many system resources are represented as a kernel object identified and referenced by a handle. These handles are comparable to UNIX file descriptors and process IDs.[5]
[5] These handles are similar to but not the same as the HWND and HDC handles used in Windows GUI programming.
- Kernel objects must be manipulated by Windows APIs. There are no "back doors." This arrangement is consistent with the data abstraction principles of object-oriented programming, although Windows is not object-oriented.
- Objects include files, processes, threads, pipes for interprocess communication, memory mapping, events, and many more. Objects have security attributes.
- Windows is a rich and flexible interface. First, it contains many functions that perform the same or similar operations; in particular, convenience functions combine common sequences of function calls into one function (CopyFile is one such convenience function, and it is used in an example later in the chapter.) Second, a given function will often have numerous parameters and flags, many of which can normally be ignored. This book concentrates on the most important functions and options rather than being encyclopedic.
- Windows offers numerous synchronization and communication mechanisms tailored for different requirements.
- The Windows thread is the basic unit of execution. A process can contain one or more threads.
- Windows function names are long and descriptive. The following function names illustrate function name conventions as well as Windows' variety:
WaitForSingleObjectWaitForSingleObjectExWaitForMultipleObjectsWaitNamedPipe
In addition to these features, there are a few conventions for type names. - The names for predefined data types, required by the API, are in uppercase and are also descriptive. The following typical types occur frequently:
BOOL (defined as a 32-bit object for storing a single logical value)HANDLEDWORD (the ubiquitous 32-bit unsigned integer)LPTSTR (a string pointer of either 8-bit or 16-bit characters)LPSECURITY_ATTRIBUTES
Many other data types will be introduced as required. - The predefined types avoid the * operator and make distinctions such as differentiating LPTSTR (defined as TCHAR *) from LPCTSTR (defined as const TCHAR *). Note: TCHAR may be a normal char or a two-byte wchar_t.
- Variable names, at least in function prototypes, also have conventions. For example, lpszFileName might be a "long pointer to a zero-terminated string" representing a file name. This is the so-called Hungarian notation, which this book does not generally use for program variables. Similarly, dwAccess is a double word (32 bits) containing file access flags; "dw" denotes flags in a double word.
Note:
It is informative to look at the system include files where the functions, constants, flags, error codes, and so on are defined. Many interesting files, such as the following, are part of the Microsoft Visual C++ environment and are normally installed in the Program Files\Microsoft Visual Studio .NET\Vc7\ PlatformSDK\Include directory (or, on VC++ version 6.0, Program Files\ Microsoft Visual Studio\VC98\Include):
WINDOWS.H (this file brings in all the others)WINNT.HWINBASE.H
Finally, even though the original Win32 API was created from scratch, it was designed to be backward-compatible with the Windows 3.1 Win16 API. This has several effects that annoy programmers.
- There are anachronisms in types, such as LPTSTR and LPDWORD, which refer to the "long pointer" that is simply a 32-bit or 64-bit pointer. There is no need for any other pointer type. At other times, the "long" is omitted, and LPVOID and PVOID are equivalent.[6]
[6] The include files contain types, such as PVOID, without the prefix, but the examples conform to the usage in many other books and the Microsoft documentation.
- "WIN32" sometimes appears in macro names, such as WIN32_FIND_DATA, even though the macro is also used with Win64.
- The former requirement, no longer relevant, for backward compatibility means that numerous 16-bit functions are never used in this book, even though they might seem important. OpenFile is such a function; always use CreateFile to open an existing file.
