joe norton
joe norton

Reputation: 127

Win32 API - Trying to readfile, it's getting truncated -- why?

I am trying to read a file and then display the file in ASCII or HEX into hEdit. Eventually I will be running other computations on the file info but right now I just want to see it all.

Currently the code displays the first bit - "MZ" - but thats it. Somehow I am accidentally truncating the pszFileText variable, I want to be able to view the entire executable in my window.

BOOL ReadInEXEFile(HWND hEdit, LPCTSTR pszFileName)
{
HANDLE hFile;
BOOL bSuccess = FALSE;

hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
    OPEN_EXISTING, 0, NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
    DWORD dwFileSize;

    dwFileSize = GetFileSize(hFile, NULL);
    if(dwFileSize != 0xFFFFFFFF)
    {
        LPSTR pszFileText;

        pszFileText = GlobalAlloc(GPTR, dwFileSize + 1);
        if(pszFileText != NULL)
        {
            DWORD dwRead;
            if(ReadFile(hFile, pszFileText, dwFileSize, &dwRead, NULL))
            {
                pszFileText[dwFileSize] = 0; // Add null terminator
                if(SetWindowText(hEdit, pszFileText))
                {
                    bSuccess = TRUE; // It worked!
                }
            }
            GlobalFree(pszFileText);
        }
    }
    CloseHandle(hFile);
}
return bSuccess;

}

Upvotes: 3

Views: 2364

Answers (3)

Remy Lebeau
Remy Lebeau

Reputation: 596582

EXE files are binary, but you are you trying to display the raw binary data as-is, which will not work. You were on the right track thinking that you need to encode the binary data to hex before displaying it. Binary data is not displayable, but hex is.

Try this instead:

static const TCHAR Hex[] = TEXT("0123456789ABCDEF");

BOOL ReadInEXEFile(HWND hEdit, LPCTSTR pszFileName) 
{ 
    BOOL bSuccess = FALSE; 

    HANDLE hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); 
    if (hFile != INVALID_HANDLE_VALUE) 
    { 
        DWORD dwFileSize = GetFileSize(hFile, NULL); 
        if (dwFileSize != INVALID_FILE_SIZE)
        { 
            LPTSTR pszFileText = (LPTSTR) LocalAlloc(LMEM_FIXED, ((dwFileSize * 3) + 1) * sizeof(TCHAR)); 
            if (pszFileText != NULL)
            {
                BYTE buffer[1024];
                DWORD dwOffset = 0;
                DWORD dwRead; 

                for (DWORD dwFilePos = 0; dwFilePos < dwFileSize; dwFilePos += dwRead)
                {
                    if (!ReadFile(hFile, buffer, sizeof(buffer), &dwRead, NULL)) 
                    {
                        CloseHandle(hFile);
                        return FALSE;
                    }

                    if (dwRead == 0)
                        break;

                    for (DWORD idx = 0; idx < dwRead; ++idx)
                    {
                        pszFileText[dwOffset++] = Hex[(buffer[idx] & 0xF0) >> 4];
                        pszFileText[dwOffset++] = Hex[buffer[idx] & 0x0F];
                        pszFileText[dwOffset++] = TEXT(' ');
                    }
                }

                pszFileText[dwOffset] = 0; // Add null terminator 

                bSuccess = SetWindowText(hEdit, pszFileText);
                LocalFree(pszFileText);
            } 
        } 

        CloseHandle(hFile); 
    } 

    return bSuccess; 
}

Upvotes: 7

Ned Batchelder
Ned Batchelder

Reputation: 375634

Two reasons:

1) If you are reading an executable, the third byte is likely to be a zero, which might terminate the string, even though you are passing the length to SetWindowText.

2) This line is wrong: pszFileText[dwFileSize + 1] = 0;. It should be pszFileText[dwFileSize] = 0;. You are writing a zero byte some place wrong, there's no telling what that might be doing.

Upvotes: 2

Seth Carnegie
Seth Carnegie

Reputation: 75130

The way you are displaying it probably depends on the data being a NUL-terminated string, and binary data has embedded NULs in it, so you only display the data up to the first NUL.

You will need to print it by yourself and use the length of the data to know how much to print instead of depending on it being a NUL-terminated C-string.

Upvotes: 1

Related Questions