【问题标题】:Win32 API - Trying to readfile, it's getting truncated -- why?Win32 API - 试图读取文件,它被截断 - 为什么?
【发布时间】:2012-07-01 00:26:33
【问题描述】:

我正在尝试读取文件,然后以 ASCII 或 HEX 格式将文件显示到 hEdit 中。最终我将对文件信息进行其他计算,但现在我只想查看所有内容。

当前代码显示第一位 - “MZ” - 仅此而已。不知何故,我不小心截断了 pszFileText 变量,我希望能够在我的窗口中查看整个可执行文件。

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;

}

【问题讨论】:

  • 您将文件内容作为零终止字符串传递给编辑控件。这意味着如果文件中间某处有一个零,它将在那里终止。因此,显然我们的文件在"MZ" 之后的位置为零。当您将 binary 文件解释为以零结尾的字符串时,这基本上是您应该期待的。
  • 无论如何,为什么你要在 binary 文件上测试你的代码???它显然只适用于 text 文件。
  • 我希望能够分析可执行文件。这就是我发现如何在 win32 gui 中读取文件的方式,所以这就是我试图增强以能够用于 exe 的方式。
  • 好吧,您将无法通过将可执行文件视为编辑控件中的文本来“分析它们”。
  • 您不需要显示数据来分析它。这是两个独立的操作。您可以直接在代码中按原样分析原始二进制数据,但如果要显示,则必须对数据进行编码。

标签: c winapi executable readfile


【解决方案1】:

EXE 文件是二进制文件,但您试图按原样显示原始二进制数据,这是行不通的。您在正确的轨道上认为您需要在显示之前将二进制数据编码为十六进制。二进制数据不可显示,但十六进制可以。

试试这个:

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; 
}

【讨论】:

  • 雷米非常感谢您的帮助。我会调查的。
  • 感谢您的帮助!不幸的是,由于在 for 语句中声明了类型,Visual Studio 给了我错误。最终我会弄清楚它想要这种格式的方式并能够试一试。我会想办法告诉你的。
  • 如果 Visual Studio 不喜欢这段代码,那么它就是愚蠢的,因为代码完全有效。在for 语句中声明变量是合法的。 Microsoft's own documentation 展示了这方面的例子。
  • 确实如此。我做了微小的改变,现在它可以工作了。干得好,感谢您的帮助。现在我正在研究如何将其转换为 ASCII 和 Unicode!
【解决方案2】:

两个原因:

1) 如果您正在读取可执行文件,则第三个字节可能为零,这可能会终止字符串,即使您将长度传递给 SetWindowText。

2) 此行错误:pszFileText[dwFileSize + 1] = 0;。应该是pszFileText[dwFileSize] = 0;。你在某个地方写错了一个零字节,不知道那可能在做什么。

【讨论】:

  • 感谢#2,现已修复。但仍然是同样的问题。如何在不提前终止的情况下尝试打印变量?
【解决方案3】:

您显示它的方式可能取决于数据是以 NUL 结尾的字符串,并且二进制数据中嵌入了 NUL,因此您只显示数据直到第一个 NUL。

您需要自己打印它并使用数据的长度来知道要打印多少,而不是依赖于它是一个以 NUL 结尾的 C 字符串。

【讨论】:

  • 我同意。所有.exe文件的前4个字节都是0x4D 0x5A 0x90 0x00,其中0x4D 0x5A是ASCII序列MZ0x90不是视觉字符。
  • @joenorton 带循环;从 0 循环到您读取的字节数并打印每个字节。
猜你喜欢
  • 2011-08-20
  • 1970-01-01
  • 2015-02-08
  • 2012-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-02
  • 1970-01-01
相关资源
最近更新 更多