Ok, i have a problem in my program. I made a question about it before, but no one really understood my problem, so im trying a new approach to it this time.
If you're curious this is my problem:
My program takes arguments in the form of
char* argv[]
, and im having trouble making a pointer to whatever is onargv[1]
usingLPWSTR
, since it only point toconst wchar_t*
objects.
This is a new thing im trying to solve my problem (i've tried multiple things but i need to know how to do what im thinking, or if its possible)
Basicly, my idea is to #define
some sort of function that take whatever is on argv[1]
and defines a const wchar_t*
with that value.
Something like this:
#define path ((const wchar_t*)argv[1])
Im not sure that is the correct way (or even if this is possible) to do what i want to do...
If you have anny better way of solving me problem, please (please) tell me how to and help me out, i've been thinking about this so a really long time!
Explanation of my program:
Im making a program that recieves arguments. The arguments are the name of the drives, for example "F:". It then uses the function
CreateFile
with the drive letter. If you go here , and see the first parameter of the function, i think you will see what i mean.... the problem is that for me to make a LPWSTR, i would need a const wchat_t* object.... I hope my question is clear this time, last time people didnt really understand what i was trying to do.
Regardless, thanks! EDIT 1: here are solve lines of my program (this is how i have to do for it to work, without arguments) (i used a fixed value in here)
int main()
{
HANDLE device;
device = CreateFile(L"\\\\.\\F:", // Drive to open
GENERIC_READ | GENERIC_WRITE, // Access mode
FILE_SHARE_READ | FILE_SHARE_WRITE, // Share Mode
NULL, // Security Descriptor
OPEN_EXISTING, // How to create
0, // File attributes
NULL);
}
This is with arguments (doesn't work)
int main(int argc, char* argv[])
{
HANDLE device;
device = CreateFile(argv[1], // Drive to open
GENERIC_READ | GENERIC_WRITE, // Access mode
FILE_SHARE_READ | FILE_SHARE_WRITE, // Share Mode
NULL, // Security Descriptor
OPEN_EXISTING, // How to create
0, // File attributes
NULL); // Handle to template
}
^ this shows what im trying to do
EDIT 2: i changed the CreateFile
to CreateFileA
, and this is the eroor codes it gives me (the drive D is a usb, its not a hard drive)
So unless im typing the wrong way to type a path, it always gives me erros. I think ill try another way to solve the problem, or if someone knows why thoes errors are happening, please tell!
EDIT 2: i changed the CreateFile to CreateFileA , and this is the eroor codes it gives me (the drive D is a usb, its not a hard drive)
This is a completely different question, and has nothing to do with wchar_t
.
In your first snipped you passed "\\\\.\\F:"
(AKA \\.\F:
once we remove the C escaping); in all your tries from the command line you never provided this path, but respectively:
D
- so it tried to open a file named D
in the current directory, and it didn't find it (error 2, aka ERROR_FILE_NOT_FOUND
);D:\
- the root directory, which cannot be opened with CreateFile
(error 3, aka ERROR_PATH_NOT_FOUND
),D:
- the current directory on the drive D:, which again cannot be opened with CreateFile
(error 5, aka ERROR_ACCESS_DENIED
);\D:
- a file named "D:" in the root of the current drive, which cannot be created given that D:
is not a valid file name (error 123, aka ERROR_INVALID_NAME
).To open a drive as a device, you must use the \\.\X:
path (where X
is the drive letter); you cannot just throw whatever floats in your mind and hope that it'll work. Call your program from the command line passing "\\.\D:"
and it'll work fine.
Of course if you want to keep it simpler for the user you can accept just the drive letter on the command line and write some code to create the string required by CreateFile
based on it.
if(argc<1) {
printf("Not enough arguments\n");
return 1;
}
const char *drive = argv[1];
char d = drive[0];
// accept both `d` and `d:` as argument for the drive
if(!((d>='a' && d<='z') || (d>='A' && d<='Z')) ||
(drive[1]!=0 && drive[1]!=':') ||
drive[2]!=0) {
printf("Invalid drive specifier: `%s`\n", drive);
return 2;
}
char path[]="\\\\.\\X:";
path[4] = d;
// now you can use path as argument to CreateFileA
What follows was the original answer, which is still valid but it addresses a completely different problem, unrelated to the actual problem OP is experiencing
You cannot make LPWSTR
point to a char *
, especially not by brutally casting the pointer - casting a pointer just makes the compiler shut up, it doesn't change the fact that what you are pointing at is not a wchar_t
string. If you want to pass a char *
to a function expecting a wchar_t *
you have to perform an actual conversion of the pointed data.
Now, you have several possible solutions:
_wmain
and receive your command line arguments directly as wide characters;std::wstring
;CreateFile
is just a macro that expands to CreateFileA
or CreateFileW
depending on the _UNICODE
macro). So, you can use CreateFileA
and pass it your string as-is.The last two solutions are not great because using local-encoding strings as command line arguments precludes your program from opening files using arbitrary Unicode characters. OTOH, using wchar_t
almost everywhere is quite a dread, since they "infect" virtually every string-processing corner of your application. The correct (IMHO) way out is to use UTF-8 everywhere, and convert on the fly when talking to the operating systems; see here for details.