Today, let’s look at a trace log writer.  It’s the kind of thing that you’d find in many applications; it simply does a printf and writes its output to a log file.  In order to have maximum flexibility, the code re-opens the file every time the application writes to the filelog.  But there’s still something wrong with this code.

This “what’s wrong with this code” is a little different.  The code in question isn’t incorrect as far as I know, but it still has a problem.  The challenge is to understand the circumstances in which it doesn’t work.

/*++
 * LogMessage
 *      Trace output messages to log file.
 *
 * Inputs:
 *      FormatString - printf format string for logging.
 *
 * Returns:
 *      Nothing
 *     
 *--*/
void LogMessage(LPCSTR FormatString, ...)
#define LAST_NAMED_ARGUMENT FormatString
{
    CHAR outputBuffer[4096];
    LPSTR outputString = outputBuffer;
    size_t bytesRemaining = sizeof(outputBuffer);
    ULONG bytesWritten;
    bool traceLockHeld = false;
    HANDLE traceLogHandle = NULL;
    va_list parmPtr;                    // Pointer to stack parms.
    EnterCriticalSection(&g_TraceLock);
    traceLockHeld = TRUE;
    //
    // Open the trace log file.
    //
    traceLogHandle = CreateFile(TRACELOG_FILE_NAME, FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (traceLogHandle == INVALID_HANDLE_VALUE)
    {
        goto Exit;

    }
    //
    // printf the information requested by the caller onto the buffer
    //
    va_start(parmPtr, FormatString);
    StringCbVPrintfEx(outputString, bytesRemaining, &outputString, &bytesRemaining, 0, FormatString, parmPtr);
    va_end(parmPtr);
    //

    // Actually write the bytes.
    //
    DWORD lengthToWrite = static_cast<DWORD>(sizeof(outputBuffer) - bytesRemaining);
    if (!WriteFile(traceLogHandle, outputBuffer, lengthToWrite, &bytesWritten, NULL))
    {
        goto Exit;
    }
    if (bytesWritten != lengthToWrite)
    {
        goto Exit;
    }
Exit:
    if (traceLogHandle)
    {
        CloseHandle(traceLogHandle);
    }
    if (traceLockHeld)
    {
        LeaveCriticalSection(&g_TraceLock);
        traceLockHeld = FALSE;
    }
}

One hint: The circumstance I’m thinking of has absolutely nothing to do with out of disk space issues. 

As always, answers and kudos tomorrow.