ERRATA that apply to Printings 2 and Beyond

    See copyright page in front of book for printing number information.

Last modified: Oct. 13, 2001

Please send comments and suggestions directly to me: jmhart@world.std.com.


Change severity ratings

    A: Important factual error or significant program defect.
    B: Clarification, better explanation, program improvement or minor defect.
    C: Minor change.

ADDITIONAL INFORMATION IF YOU ARE USING VISUAL C++ Version 5.0

Author Note: The book was developed primarily using Version 4.0, and Version 5.0 added to the supported API. Several comments mention new features available with Version 5.0, and I will add new material here from time to time. Please feel free to send me additional information at jmhart@world.std.com.


SEVERITY A CHANGES

p. 233

The statement regarding critical section performance is not entirely correct; CSs can be slower than mutexes in some circumstances. See details.

p. 281 From Cagdas Ozgenc <cagdasozgenc@hotmail.com>. When performing asynchronous I/O with threads, it is important to note that you cannot have multiple threads use the same file HANDLE, unless the HANDLE is opened in overlapped mode. A thread that is blocked performing I/O on a thread will lock the HANDLE, blocking all other threads that attempt to use the HANDLE concurrently.

There are two solutions:

  1. Use a distinct HANDLE for each thread, as recommended on Page 281 and illustrated in atouMT.c. However, there is a problem with atouMT.c as written. Do not create the separate HANDLEs using DuplicateHandle; instead, use CreateFile to create each file handle, one per thread, for each named file. Be certain to use the FILE_SHARE_READ and FILE_SHARE_WRITE flags as appropriate. This method has the advantage of working on Windows 9x/Me.
  2. Use a single OVERLAPPED HANDLE. Be certain, of course, to set the correct file positions and test for the operation completion. This technique will not work under Windows 9x/Me, and, while I have not implemented it, the logic would seem to be as complex as in atouOV.c.

Note: I have not tested solution one thoroughly on Windows NT/2000/XP, but will do so soon.

SEVERITY B CHANGES

p. 42

See atou for additional atou performance comparisons that modify and extend some of the conclusions in the text.

p. 88

The declaration of the variable Exit should be:

  • volatile static BOOL Exit = FALSE;
  • This is required as the console control handler runs in a separate thread; see Chapter 11 for a more complete explanation. The code on the disc has this fix.

    p. 199 Cagdas Ozgenc cagdasozgenc@hotmail.com  pointed out that SrvrBcst.exe (Program 9-4) fails on Windows 9x/Me. The reason is that CreateFile (..., GENERIC_WRITE | GENERIC_READ, ...) should not use GENERIC_READ (the mailslot client only writes to the mailslot). Windows NT/2000/XP, on the other hand, will execute SrvrBcst.exe properly as is. 

    This bug was never detected because the program is used with the named pipe server and was therefore never tested on Windows 9x/Me. However, there are many situations in which a mailslot client is appropriate on these systems. For example, the client application could have been written to act as a mailslot client, with the named pipe server being the mailslot server. 

    Comment: I have not retested on Windows NT/2000/XP to determine whether or not the GENERIC_READ flag is required; I suspect that it is not.

    p. 228

    VC++ Ver 5.0 ONLY - You can test a critical section with the TryCriticalSection function, which will take ownership of the critical section if possible, but will return a FALSE if a different thread owns the critical section. Thus, you can poll a critical section, but you cannot time out.

    p. 233

    Here is an additional comparison of mutexes with CRITICAL_SECTION objects. Mutex handles can participate in a WaitForMultipleObjects call (the handles in the array can be a mix of any synchronization object handles). This is desirable at times, and careful use of WaitForMultipleObjects can help to avoid the deadlocks that might occur if you waited for the individual objects sequentially. You can only wait for one single CRITICAL_SECTION object at a time, however, and you must use EnterCriticalSection.

    p. 234

    The remarks on p. 232 regarding names apply to semaphores as well. Creating a semaphore with the name of an existing semaphore means that the initial and maximum counts are ignored.

    This applies to CreateMutex, etc.

    p. 237

    The remarks on p. 232 regarding names applies to events (and semaphores) as well, but, of course, the initial state and the auto/manual reset properties cannot be changed.

    p. 246

    case CS_RQCOMPLETE is missing a closing bracket } for the if statement. It should go just before the closing bracket for the _try statement and have its own line.

    p. 248

    The utilization computation on the seventh line is inaccurate because of the way in which it is parenthesized. As it is, the utilization will stay at zero. The fix will allow the multiplication by 100 to precede the division. Alternatively, you could cast the operands to floating point. Here is an improved expression for the utilization.

        Utilization = (LONG)(100 *
            (TotKerTim.li - OldKerTim +
            TotUsrTim.li - OldUsrTim) / (10000 * CS_TIMEOUT));

    p. 293

    Eliminate the phrase at the end of the first sentence of Paragraph 4, so that the first sentence now reads:

    Obtain the names of subkeys by specifying a key to RegEnumKeyEx.

    Likewise, remove the last sentence in the second to last paragraph. The sentence to be removed currently reads "RegistryQueryInfoKey is ... index." Notice that there is a function RegQueryInfoKey, but its job is to retrieve information regarding a specified key; among other things, it will find the number of subkeys.

    Appendix C -- p. 338

    See atou for additional atou performance comparisons that modify and extend some of the conclusions in the text.

    SEVERITY C CHANGES

    p. 25

    Middle of page, last of 5 bullets, fdwShareMode should be fdwAccess.

    p. 29

    At the end of the very last line, replace _tstrcpy with _tcscpy.

    p. 65

    For more information on the C Run-Time Library, see Win32 vs. The C Run-Time Library for File I/O. comp.os.ms-windows.programmer.win32 is also an excellent place to go for additional information or to get answers to your questions.

    p. 98

    The final parameter, lpMem, has type LPCVOID, not LPSTR as shown.

    p. 108

    The allocation granularity may not necessarily be 64K, contrary to what is stated. The actual granularity is the dwAllocationGranularity member of the SYSTEM_INFO structure, which you can read using the GetSystemInfo() function.

    p. 136

    Under the heading "Example: Reading File Permissions," the first sentence should begin, "Proram 7-4..." (not 7-3).

    p. 155

    Add an additional return value, WAIT_FAILED, for the wait functions. This value, of course, indicates that the call failed.

    p. 156

    In the "Process Security" section, the access right CREATE_PROCESS should be PROCESS_CREATE_PROCESS. DUPLICATE_HANDLE should be PROCESS_DUP_HANDLE, and PROCESS_CREATE_THREAD instead of CREATE_THREAD (Use the PROCESS_ prefix on all process access rights).

    p. 187

    Windows 95/98 systems cannot be named pipe servers, although this fact is not well documented. Furthermore, under W95, CreateNamedPipe actually returns a valid handle, but a client CreateFile fails to find the named pipe. The new example program reimplementing the pipe program (Program 9-1) with named pipes demonstrates this behavior. [Go to pipeNP.c program.]

    p. 206

    In the ExitThread box, it should say VOID ExitThread (DWORD dwExitCode)

    9 lines up from the bottom of the page should say, "Windows NT Version 3.51 did not allow ..."

    p. 216

    The last sentence of the first paragraph under the heading "Thread Local Storage" should reference Program 10-1.

    p. 217

    The last line on the page should be REALTIME_PRIORITY_CLASS (there is no underbar in REALTIME).

    p. 222

    Exercise 10-7, as stated, does not make sense as TLS cannot pass data between threads.

    p. 231

    In the sixth line down, _finally { should begin with a small f (not a capital "F").

    p. 232

    p. 245

    In the middle of the page, 4th line down after "Maintaining and Reporting Server Statistics," there is a word missing:

    ...this code shows some of the essential processing...

    p. 288-289

    All references to SwitchThreadToFiber should be to SwitchToFiber. There are three references, as well as the index.

    Bibliography

    Custer's book has been updated by David A Solomon as a second edition of Inside Windows NT. The edition is updated and expanded to include file system and Version 4.0 information. The ISBN is 1-572-31677-2.