Why does %wZ work for both UNICODE_STRING and PUNICODE_STRING?

For example, both of the following work:
DbgPrint(“DriverName: %wZ”, DriverObject->DriverName);
DbgPrint(“DriverName: %wZ”, &DriverObject->DriverName);

If this is intended, how does the implementation know if the parameter is UNICODE_STRING or PUNICODE_STRING?

I don’t know what architecture you’re using, but compiling in x64 debug the first one ends up copying the struct to the stack and passing by pointer anyway:

VOID
PrintTest(
    PDRIVER_OBJECT DriverObject)
{
    DbgPrint("DriverName: %wZ", DriverObject->DriverName);
    DbgPrint("DriverName: %wZ", &DriverObject->DriverName);
}

Nothing!PrintTest [C:\repos\Nothing\Nothing\Nothing.cpp @ 55]:
   55 00000001`40001320 mov     qword ptr [rsp+8],rcx
   55 00000001`40001325 push    rsi
   55 00000001`40001326 push    rdi
   55 00000001`40001327 sub     rsp,38h
   56 00000001`4000132b lea     rax,[rsp+20h]
   56 00000001`40001330 mov     rcx,qword ptr [rsp+50h]
   56 00000001`40001335 mov     rdi,rax
   56 00000001`40001338 lea     rsi,[rcx+38h]
   56 00000001`4000133c mov     ecx,10h
   56 00000001`40001341 rep movs byte ptr [rdi],byte ptr [rsi]
   56 00000001`40001343 lea     rdx,[rsp+20h]
   56 00000001`40001348 lea     rcx,[Nothing! ?? ::FNODOBFM::`string' (00000001`400015f0)]
   56 00000001`4000134f call    Nothing!DbgPrint (00000001`400015b4)
   57 00000001`40001354 mov     rax,qword ptr [rsp+50h]
   57 00000001`40001359 add     rax,38h
   57 00000001`4000135d mov     rdx,rax
   57 00000001`40001360 lea     rcx,[Nothing! ?? ::FNODOBFM::`string' (00000001`400015f0)]
   57 00000001`40001367 call    Nothing!DbgPrint (00000001`400015b4)
   58 00000001`4000136c add     rsp,38h
   58 00000001`40001370 pop     rdi
   58 00000001`40001371 pop     rsi
   58 00000001`40001372 ret

So, really it only works by accident in this case.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.