1

I am coding a PE file viewer in standard C by following this article. It is pretty neat, but I have a problem with the first lines:

#include "stdafx.h"
#include "Windows.h"
#include <iostream>

int main(int argc, char* argv[]) {
    const int MAX_FILEPATH = 255;
    char fileName[MAX_FILEPATH] = {0};
    memcpy_s(&fileName, MAX_FILEPATH, argv[1], MAX_FILEPATH);
    ...
}

As you can see, the author is defining the MAX_FILEPATH as 255, but I cannot do the same because the input argument I will give may be larger than that.

I decided to do dynamic memory allocation with malloc, so I can have an auto-sized array (the exact argument's length) and also, to save me the 'memcpy_s' function:

#include <stdio.h>

#include "Windows.h"

#pragma warning (disable: 6011 6386 6387) // MSVC is giving me a headache.

int main(int argc, char *argv[]) {
    int length = strlen(argv[1]); // Yes, I only care for 1 input argument.
    char* path = malloc(length * sizeof(char));

    int i = 0;
    for (; i <= length; i++) {
        if (i < length) {
            path[i] = argv[1][i];
        }
        else {
            path[i] = '\0';
        }
    }
    ...
}

I know that the 'for cicle' is probably not the best option in terms of speed, but I am not worried about it, yet. Instead, I am worried because everything seems to be fine, but when I reach the second part of the code (which is the creation of the HANDLE), it is always returning error.

HANDLE file = CreateFileA(path, GENERIC_ALL, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

if (file == INVALID_HANDLE_VALUE) {
    printf_s("Nope."); // Always throwing nopes.
}

Do you have an idea of what am I doing wrong? Maybe the way I am trying to mix up different data types or functions...?

Thank you very much, in advance.

By the way, if you have suggestions about my C coding style, or if something is not really 'C standard', please, let me know.

IF SOMEONE IS HAVING THE SAME PROBLEM...

Try to run your program as Admin... it is all about file permissions.

5
  • Make that char* path = malloc(length+1); for the terminating null character. ` Commented Mar 7, 2021 at 9:55
  • 1
    What is wrong with just using argv[1]? E.g. char *path= argv[1];? Or just forget about path at all. Commented Mar 7, 2021 at 9:58
  • Anyway, following the proper malloc just do strcpy. Commented Mar 7, 2021 at 9:58
  • Also, sizeof(char) is always one by definition. And if you're using memcpy_s() because MSVC said memcpy() was "deprecated", be aware you were effectively lied to. memcpy() hasn't been and won't be deprecated by anyone - it's standard C and it's not going away. MSVC pushes you to use the *_s functions that would be standard per Annex K of the C standard, but Microsoft's implementation is non-standard and non-portable. See open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm#impementations Commented Mar 7, 2021 at 12:16
  • Thank you for your advices; I'll fix them and keep going :) Commented Mar 8, 2021 at 4:43

1 Answer 1

1

Unless there is some other reason for it, there is no need to copy argv[1] you could just use it instead:

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h> // use normal include guards

int main(int argc, char *argv[])
{
    if (argc < 2){ // if the argument is not there the program would have undefined behavior
        fprintf(stderr, "Usage: <prog> <filename>\n");
        return EXIT_FAILURE;
    }
    
    HANDLE file = CreateFileA(argv[1], GENERIC_ALL, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    //                        ^^^^^^^
    if (file == INVALID_HANDLE_VALUE) {
        printf_s("Nope."); // Always throwing nopes.
    }
    //...
}

In any case you should check if argv[1] is really there otherwise your program will have undefined behavior.

Anyway, if you really want to do the copy there are better alternatives, here is one of them:

#include <stdio.h>
#include <stdlib.h>
#include<string.h> // maybe needed for strdup
#include <Windows.h> // use normal include guards


int main(int argc, char *argv[]) {

    if(argc < 2){ // if the argument is not there the program would have undefined behavior
        fprintf(stderr, "Usage: <prog> <filename>\n");
        return EXIT_FAILURE;
    }
    // allocates memory for the new string and duplicates it
    char* path = _strdup(argv[1]); // MSVC can complain about POSIX strdup()
    //...
    // you'll need to free path
}

Using the correct size for the array you can still use one of the memcpy or strcpy library functions or one of its variants:

int length = strlen(argv[1]) + 1; // account for null byte
char *path = malloc(length); // sizeof char is always 1 byte
memcpy_s(path, length, argv[1], length); // path is already pointer, removing &

Note that in your code, filename, when passed as argument, decays to a pointer to its first element, so you should also remove &.

Or simply use a pointer:

char *path = argv[1];

Though the pointer option would be basically the same as simply using argv[1] directly, as shown in the first code.

If there is another problem not related to the string, GetLastError() will help you pinpoint what it is.

Sign up to request clarification or add additional context in comments.

4 Comments

I have followed both approaches (using argv[1] directly and the full memcpy function) but it is still throwing "nopes", like if it was unable to read the file (file == INVALID_HANDLE_VALUE).. :(
@JulioVargas, all the 3 should work, try printing out GetLastError() to see what the exact error is, and post it here. You may have to use LPTSTR argv[] and TCHAR instead of char if you are using Unicode characters.
GetLastError() == 5, so it meant that it was all about permissions.. I ran the program as Admin and everything worked fine. Thank you for the suggestions!
@JulioVargas, indeed it is, glad you solved it, note that you can accept the answer if you think it decisively helped you solved the issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.