Функция работает, когда я использую gcc, но когда я использую компилятор Microsoft Visual Studio, она ничего не делает - PullRequest
0 голосов
/ 02 марта 2019

Когда я запускаю это с gcc, используя code: blocks, он создает registration.txt на F, если он не существует, и записывает пароль и имя пользователя, но когда я использую это в моемпроект, использующий компилятор Microsoft Visual Studio, ничего не делает.

Например, если я вызываю эту функцию, например: Write("JohnDoe", "password123"), в файле registration.txt должен появиться в строке: JohnDoe, password123.

const char *FILEPATH = "F:\\registration.txt";

int Write(char *username, char *password) {
    if (username == NULL || password == NULL) {
        return -1;
    }
    BOOL error = TRUE;
    size_t lengthUsername = strlen(username);
    size_t lengthPassword = strlen(password);
    LPDWORD bytesUsernameWritten = 0;
    char comma[2] = ",";
    char newLine[3] = "\r\n";
    LPDWORD bytesPasswordWritten = 0;
    LPDWORD bytesWrittenComma = 0;
    //if the file doesn't exist, we create it
    HANDLE file = CreateFile((LPCWSTR)FILEPATH, FILE_APPEND_DATA, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
    if (file == INVALID_HANDLE_VALUE) {
        if (GetLastError() != ERROR_FILE_EXISTS) {
            printf("0x%x", GetLastError());
            CloseHandle(file);
            return -1;
        }  //the file exist, we try to create it
        file = CreateFile((LPCWSTR)FILEPATH, FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (file == INVALID_HANDLE_VALUE) {
            printf("Couldn't open the file. Error : 0x%x", GetLastError());
            CloseHandle(file);
            return -1;
        }
    }

    //We try to write the username and the password in file, each combination on each line, in this format: username, password

    error = WriteFile(file, username, (DWORD)lengthUsername, bytesUsernameWritten, NULL);
    if (error == FALSE) {
        printf("The username couldn't have been written. Error 0x%x\n", GetLastError());
        CloseHandle(file);
        return -1;
    }
    error = WriteFile(file, comma, 1, bytesWrittenComma, NULL);
    if (error == FALSE) {
        printf("The comma couldn't have been written. Error 0x%x\n", GetLastError());
        CloseHandle(file);
        return -1;
    }
    error = WriteFile(file, password, (DWORD)lengthPassword, bytesPasswordWritten, NULL);
    if (error == FALSE) {
        printf("The password couldn't have been written. Error 0x%x\n", GetLastError());
        CloseHandle(file);
        return -1;
    }
    error = WriteFile(file, newLine, 2, bytesPasswordWritten, NULL);
    if (error == FALSE) {
        printf("The endline couldn't have been written. Error 0x%x\n", GetLastError());
        CloseHandle(file);

        return -1;
    }
    CloseHandle(file);
    return 0;
}

1 Ответ

0 голосов
/ 02 марта 2019

Ваша основная проблема - путаница между использованием Unicode и ASCII.

Все функции Windows API, которые принимают строковые параметры, имеют две версии: одна, которая работает с LPCSTR, и одна, которая работает с LPCWSTR. * 1005.*

Вы можете привести char * к LPCSTR и использовать версию ASCII CreateFileA, но вы не можете привести ее к LPCWSTR и использовать CreateFileW - версию Unicode CreateFile, как и ожидалосьстроки в кодировке UCS-16, где каждый символ занимает 2 байта.

Какая версия функции вызывается, зависит от флага компилятора.Для CodeBlocks в Windows по умолчанию используется версия ASCII, поэтому ваша функция работает.Для VS по умолчанию используется Unicode, поэтому строка пути к файлу запутывается, а файл не создается.

Кроме того, у вас есть две другие ошибки:

  1. Выиспользуя WriteFile неправильно.
    4-й параметр - это указатель, в котором WriteFile хранит количество записанных байтов.

    Вы передаете указатель NULL, поскольку вы устанавливаете переменные, такие как bytesUsernameWritten, равные 0. Но в соответствии с Документация MS , вы можете использовать там только NULL, если последний параметр, lpOverlapped не равен NULL.

    Что вы должны сделать, это объявить bytesUsernameWritten как DWORD и передать его адрес, используя & operator.
    В противном случае, даже если функция успешно создаст файл, вы не получите количество записанных байтов.

  2. Вы пытаетесь закрыть INVALID_HANDLE_VALUE
    Это не нужно, но, к счастью, оно не должно вызывать сбой вашей программы.

Наконец, нетпричина попробовать позвонить CreateFile дважды.Просто используйте один вызов с параметром OPEN_ALWAYS.Это откроет существующий файл, но если файл не существует, он создаст его автоматически вместо сбоя.

...