Question

I have a basic C++ program. Its goal is to display the file names contained in a specific folder. The C++ code is the following :

#include <Windows.h>
#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>

int                     _tmain(int ac, TCHAR **av)
{
    HANDLE              hFile;
    WIN32_FIND_DATA     findFileData;
    BOOL                retFindNextFile;
    TCHAR               FilePathPattern[] = TEXT("C:\\Users\\Bloodsucker94\\Desktop\\TestASM\\*.txt");

    if ((hFile = FindFirstFile(FilePathPattern, &findFileData)) == INVALID_HANDLE_VALUE)
        _tprintf(TEXT("FindFirstFile() failed with code %d\n"), GetLastError());
    else {
        _tprintf(TEXT("hFile=%d, addr=0x%08X\n"), hFile, &findFileData);
        do {
            TCHAR       beginPath[] = TEXT("C:\\Users\\Bloodsucker94\\Desktop\\TestASM\\");

            lstrcat(beginPath, findFileData.cFileName);
            _tprintf(TEXT("%s\n"), beginPath);
            //printf("%s\n", beginPath);
            retFindNextFile = FindNextFile(hFile, &findFileData);

        } while (retFindNextFile == TRUE);
    }
    getchar();
    return (EXIT_SUCCESS);
}

I want to produce the same program using MASM :

.386
.model                          flat, stdcall
option                          casemap :none

include                         \masm32\include\windows.inc
include                         \masm32\include\kernel32.inc
include                         \masm32\include\masm32.inc
include                         \masm32\include\masm32rt.inc
includelib                      \masm32\lib\kernel32.lib
includelib                      \masm32\lib\masm32.lib
include                         \masm32\include\msvcrt.inc
includelib                      \masm32\lib\msvcrt.lib
includelib                      \masm32\lib\crtdll.lib

_tprintf PROTO C :VARARG

.data

FolderPath                      TCHAR                       "C:\Users\Bloodsucker94\Desktop\TestASM\*.txt", 0
BeginFolderPath                 TCHAR                       "C:\Users\Bloodsucker94\Desktop\TestASM\", 0
FileName                        TCHAR                       "ta_mere.txt", 0

LstrcatFailed                   BYTE                        "lstrcat failed", 0
FormatPrintString               BYTE                        "%s\n", 0

FindFirstFileError              BYTE                        "FindFirstFile() failed with code %d", 0
FindFirstFileSuccess            BYTE                        "First file found with success - hfile=%d", 0
PrintStructAddr                 BYTE                        "addr=Ox%08X", 0
PrintFileName                   BYTE                        "%s", 0

.data?

hFile                           HANDLE                      ?
findFileData                    WIN32_FIND_DATA             <>
retFindNextFile                 BOOL                        ?
ErrorCode                       DWORD                       ?
FinalFilePath                   LPTSTR                      ?

.code

start:

    ;--------------------------------------------------------

    invoke  FindFirstFile,      ADDR FolderPath,            \
                                ADDR findFileData

    mov     hFile,              eax

    .IF hFile == INVALID_HANDLE_VALUE
        invoke  GetLastError
        mov     ErrorCode,      eax
        printf("%d\n", ErrorCode)
        jmp                     _quit                                
    .ENDIF

    ;--------------------------------------------------------

_loop:
    invoke  lstrcat,            ADDR BeginFolderPath,
                                ADDR findFileData.cFileName

    mov     FinalFilePath,      eax

    .IF FinalFilePath == NULL
        invoke  MessageBox,     NULL,                       \
                                ADDR LstrcatFailed,         \
                                ADDR LstrcatFailed,         \
                                MB_OK 
    .endif      

    ;invoke crt_printf,         ADDR FormatPrintString,     \
    ;                           findFileData.cFileName

    invoke  MessageBox,         NULL,                       \
                                ADDR FinalFilePath,         \
                                ADDR FinalFilePath,         \
                                MB_OK 

    ;--------------------------------------------------------

    invoke  FindNextFile,       hFile,                      \
                                ADDR findFileData       

    .IF eax == NULL
        jmp                     _quit
    .ELSE
        jmp                     _loop                       
    .ENDIF

    ;--------------------------------------------------------

_quit:
    invoke  ExitProcess,        0

end start

The compilation works perfectly. The lstrcat function does not fail too. But at the execution the message boxes display the string "-O@". I noticed the same behaviour in the c++ program when I want to print with printf and not _tprintf (because print a TCHAR Windows type does not work with printf). Maybe the problem comes from MessageBox function or maybe TCHAR type is not the good one. Only the c++ program works. I'm lost.

Does anyone can help me, please ?

Thanks in advance for your help.

Was it helpful?

Solution

First thing, your call to lstrcat is going to overwrite memory that comes after BeginFolderPath. So the value you have for FileName is going to be overwritten for sure, and if the file name is really long there's no telling what parts of your data segment will be trashed by that call. Buffer overrun is not the only possible problem with lstrcat. See the documentation at http://msdn.microsoft.com/en-us/library/windows/desktop/ms647487(v=vs.85).aspx

You might consider running this in a debugger and taking a look at memory after the call to lstrcat returns.

Also, you're mixing TCHAR and BYTE for your strings, which is somewhat confusing. It's unclear to me whether you're wanting this program to use Unicode or ANSI strings. As it's currently written, it's impossible to tell. Is TCHAR a byte in this program, or a word? If it's a word, then you need to be calling MessageBoxW.

It would be instructive for you to set the compiler switch that outputs an assembly listing file, and compile your C++ program. Take a look at the generated assembly code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top