How to Converting PWSTR to UNICODE_STRING in a Kernel Driver

Forum for discussion about kernel-mode development.
Post Reply
Posts: 1
Joined: Sun Mar 18, 2018 5:25 am

Sun Mar 18, 2018 5:28 am

I am a newer programme developer of Windows Kernel project.Recently,I am having trouble in Windows kernel programme about UNICODE_STRINGS. I am writing a driver that writes an output file instead of having the name of the file hard-coded inside the driver source code, I would like to send it a file name from a user application. I using buffered I/O send the file name to driver. The user application send code is:

void Transfile(CString FileNamePath)
HANDLE device = NULL;
ULONG ret_len;
CString PreStr="\\\\??\\\\";
CString TranStr = "";
TranStr.Format(_T("%s%s"), PreStr, FileNamePath); //TranStr="\\??\\c:\\test.txt"
char *msg = (LPSTR)(LPCSTR)TranStr;

device = CreateFile("\\\\.\\micksysTestr", GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL);

DeviceIoControl(device, Com_Send, msg, strlen(msg)+1, NULL, 0, &ret_len, 0)

And then the driver do buffered I/O using DeviceIoControl code is:

NTSTATUS DeviceIoControl(PDEVICE_OBJECT DeviceObject, PIRP irp)
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(irp);
PWSTR b = L"\\??\\c:\\test.txt";
switch (irpsp->Parameters.DeviceIoControl.IoControlCode)
case Com_Send:

pWstr = (PWSTR)irp->AssociatedIrp.SystemBuffer; //DbgPrint(pWstr) is \\??\\c:\\test.txt
OutFile(pWstr); //OutFile(b)
status = irp->IoStatus.Status;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return status;

VOID OutFile(IN PWSTR FileName)
NTSTATUS status;
HANDLE hFileHandle;
WCHAR FilePath[256] = { 0 };
wcscpy(FilePath, FileName);

The display of Debug View is correct from "DbgPrint(pWstr)", the pWstr is "\\??\\c:\\test.txt". But the function of OutFile(pWstr) is not correct, however when I used the variante "b" instead of "pWstr", and then the function of OutFile(b) is right. Now I don't know how to programme the code to realize the pWstr to b? Is it right of the knowlege about ANSI to UNICODE_STRING? Thanks in advance for any assistance
User avatar
Global Moderator
Posts: 4903
Joined: Sun Mar 07, 2010 5:35 am
Location: Russian Federation

Sun Mar 18, 2018 1:58 pm

Ring0 - the source of inspiration
User avatar
Posts: 465
Joined: Sat Mar 13, 2010 9:14 pm
Location: Czech Republic

Sun Mar 18, 2018 7:26 pm

Yes, you seem to send an ANSI-character string to the driver, not the wide-character one. UNICODE_STRING is just a structure that contains:
* a pointer to the wide-character string (i.e. PWSTR),
* string length, in bytes
* maximum possible string length that fits into the buffer (the PWSTR), required only for modifying operations.

If you have a wide-character string (PWSTR), RtlInitUnicodeString initializes an UNICODE_STRING structure pointing to that string. If you have an ANSI-character string, you can similarly use RtlInitAnsiString to initialize an ANSI_STRING structure pointing to it. RtlAnsiStringToUnicodeString and RtltUnicodeStringToAnsiString sort of converts between ANSI_STRING and UNICODE_STRING structures, howerver, they can allocate and copy the ansi-character and wide-character strings which is important since you may need to free them (RtlFreeAnsiString, RtlFreeUnicodeString).

I would discourage you from passing the strings in their C form (PSTR, PWSTR) since a malicious application may simply send such as string and omit the null-terminating character. It is better to send the length of the string together with its characters, which is exactly why the UNICODE_STRING and ANSI_STRING structures exist.
Post Reply