What's wrong with this code, part 5

So there was a reason behind yesterday’s post about TransmitFile, it was a lead-in for “What’s wrong with this code, part 5”.

Consider the following rather naïve implementation of TransmitFile (clearly this isn’t the real implementation; it’s just something I cooked up on the spot):

bool TransmitTcpBuffer(SOCKET socket, BYTE *buffer, DWORD bufferSize)
{
DWORD bytesWritten = 0;
do
{
DWORD bytesThisWrite = 0;
if (!WriteFile((HANDLE)socket, &buffer[bytesWritten], bufferSize - bytesWritten, &bytesThisWrite, NULL))
{
return false;
}
bytesWritten += bytesThisWrite;
} while (bytesWritten < bufferSize);
return true;
}

bool MyTransmitFile(SOCKET socket, HANDLE fileHandle, BYTE *bufferBefore, DWORD bufferBeforeSize, BYTE *bufferAfter, DWORD bufferAfterSize)
{
DWORD bytesRead;
BYTE fileBuffer[4096];

if (!TransmitTcpBuffer(socket, bufferBefore, bufferBeforeSize))
{
return false;
}

do
{
if (!ReadFile(fileHandle, (LPVOID)fileBuffer, sizeof(fileBuffer), &bytesRead, NULL))
{
return false;
}
if (!TransmitTcpBuffer(socket, fileBuffer, bytesRead))
{
return false;
}

} while (bytesRead == sizeof(fileBuffer));

if (!TransmitTcpBuffer(socket, bufferAfter, bufferAfterSize))
{
return false;
}
return true;
}

Nothing particular exciting, but it’s got a big bug in it.  Assume that the file in question is opened for sequential I/O, that the file pointer is positioned correctly, and that the socket is open and bound before the API is called.  The API doesn’t close the socket or file handle on failure; it’s the responsibility of the caller to do so (closing the handles would be a layering violation).  The code relies on the fact that on Win32 (and *nix) a socket is just a relabeled file handle.

As usual, answers and kudos tomorrow.