Click here to Skip to main content
15,881,882 members

Comments by JudyL_MD (Top 11 by date)

JudyL_MD 19-May-23 22:19pm View    
as I said, the Finalize_ call does NOT return from the call into media foundation only on Win11
JudyL_MD 19-May-23 22:10pm View    
I've seen it and the "fix" was something I've already got -- correct synchronization around usages of the sink writer.
JudyL_MD 6-May-22 9:10am View    
NOT SUCCESS. You need a working version of those IF statements. Once you get data with those IF statements, then you have success.

Your driver must NOT assume that the provided buffers are the correct length. A correctly coded driver checks the length of the buffer and never writes more data than the length indicates. If you don't get anything with the IF statements, that means there is some logic error. Probably a disconnect between how long the driver thinks a ULONG is and how long VB.net thinks a ulong is. And my math may be off on the string length leaving space for the NULL - maybe a +1 instead of a -1. Don't know. That's the kind of thing I check with a debugger to make sure I got it right.

You need to put debug statements in the driver to print out the two values it is comparing in the IF statements and see what is wrong. I can't help with this anymore since I can't run your app / driver pair of program. Time to debug and see what the driver is doing with those IF statements.

I can't emphasize enough that you MUST validate the length of the buffer before you write data to it in a driver. This is driver 101 stuff. Did you read and understand the link Dave (radnor) gave you? Do so! https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/security-issues-for-i-o-control-codes

Don't get rid of those IF statements - FIX them.
JudyL_MD 5-May-22 9:46am View    
LOL ... seriously though, based on the OP's initial "working" code, I think we can safely assume he is using METHOD_BUFFERED. In that case, no MDL mapping is needed and I added the needed length validation in my comments.
JudyL_MD 4-May-22 15:24pm View    
In general, I'm advocating splitting the retrieval of the PID and the path into two separate calls. I'd advise doing some studying on the different models of memory management used in unmanaged versus managed code. Drivers themselves are a very unique subset of unmanaged code and have their own restrictions and function calls.

Now to specifics ... You asked about my comments. I've listed the big three below.

1) I'd create a new code to make it easy in the driver to tell the difference between the ulong and the string. The code is just a number ...

You were asking if you should create another IOCTL for retrieving the path. Yes you should. Somewhere in your VB, you have IO_GET_CLIENT_PROCID defined; that value gets itself turned into the switch value SEND_TO_USER in the driver. Make a second such "ioctl code" such as IO_GET_CLIENT_PROCPATH, which you must support with a new case in the driver's switch, such as SEND_TO_USER_PATH. Your VB code then calls DeviceIoControl twice, once with each of the two IO control codes. "Just a number" refers to the code value itself -- it's just a UINT with a very specific format to its bits.

2) Your ulong VB code then needs to allocate an unmanaged buffer, call the driver using the pointer to the buffer as the output parameter, then retrieve the ulong value from the pointer

The IOCTL handling function in a driver only takes one type as input and one type as output -- a pointer to a chunk of unmanaged memory. In your old code, VB.net hid those details from you. When you had "<out> ByRef OutBuffer As ULong" describing the OutBuffer parameter, VB created an unmanaged chunk of memory and got a pointer to it, copied the value of your ulong into that memory ... or more likely just locked the memory location of your ulong variable and got a pointer to the locked location ... then passed that pointer through to the DeviceIoControl function in Kernel32.DLL.

To use DeviceIoControl properly, you're going to need to do that hidden stuff yourself. (I'm speaking C# pseudo-code here):
IntPtr p = Marshall.AllocHGlobal (sizeof (ulong))
DeviceIoControl (hFile, IO_GET_CLIENT_PROCID, Nothing, 0, p, sizeof (ulong), Bytes_IO, Nothing)
check return value from DeviceIoControl
ulong value = Marshall.ReadInt64 (p);
Marshall.FreeHGlobal (p);

For the string case, you need to allocate a string of the max possible size and then use that in your call to the driver. I've got "* 2" below since you have unicode in the driver and that takes 2 bytes per character, and "+ 1" to leave room for the NULL terminator.
numStringBytes = (MAX_STRING_SIZE + 1) * 2
IntPtr p = Marshall.AllocHGlobal (numStringBytes)
DeviceIoControl (hFile, IO_GET_CLIENT_PROCPATH, Nothing, 0, p, numStringBytes, Bytes_IO, Nothing)
check return value from DeviceIoControl
string = Marshall.PtrToStringUni (p)
Marshall.FreeHGlobal (p);

3) (Now the driver code) You'll need to revise your driver code to validate the length of the buffer against the length of a ulong

sizeof (*buffer) is not the right way to either validate input length or set return length. Remember, the driver is pure C code. For the IO_GET_CLIENT_PROCID that already exists to retrieve the process ID, your switch case should be something like:

case SEND_TO_USER:
if (outLength == sizeof (ULONG))
{
*((ULONG *) buffer) = ProcID;
status = STATUS_SUCCESS;
returnLength = sizeof(ULONG);
}

for your new ioctl code
case SEND_TO_USER_PATH:
if (outLength <= (myUnicodeString.Length / 2) - 1) // leave space for the NULL terminator
{
RtlFillMemory (buffer, nOutBufferSize, 0);
RtlCopyBytes (buffer, myUnicodeString.buffer, myUnocdeString.Length * 2);
status = STATUS_SUCCESS;
returnLength = myUnocdeString.Length * 2;
}