Using ntintsafe.h is a great idea, but I don't know how readable the results are

The addition of ntintsafe.h for detecting integer overflow/underflow is a great addition to the WDK. It unifies how everyone detects these math errors, leading to common code that anyone can pickup and see what it does...BUT, I have found it does have a "tax." What is actually being computed can be become unclear! For instance, let's take this sample before we convert it to detect any math errors:

     USHORT cbImageNameLength;

    cbImageNameLength = ((USHORT) wcslen(wsImageName)) * sizeof(WCHAR) + sizeof(UNICODE_NULL);

It is relatively straightforward and clear (depends on the viewer I guess) that we are computing the number of bytes to wsImageName requires. Here is the safe (and longer! ) version of the unsafe computation:

     USHORT cbImageNameLength;
    NTSTATUS status;

    do {
        status = RtlSizeTToUShort(wcslen(wsImageName), &cbImageNameLength);
        if (!NT_SUCCESS(status)) {
            break;
        }

        status = RtlUShortMult(cbImageNameLength, sizeof(WCHAR), &cbImageNameLength);
        if (!NT_SUCCESS(status)) {
            break;
        }

        status = RtlUShortAdd(cbImageNameLength, sizeof(UNICODE_NULL), &cbImageNameLength);
        if (!NT_SUCCESS(status)) {
            break;
        }

        // cbImageNameLength has now been computed...
    } while (FALSE);

Needless to say, that is not the most transparent code I have read or written. I certainly would not go back to the unsafe vesion and I cannot use safeint object which throws execptions on error because this code runs in the kernel. The only remedy I could think of is to create a comment at the top of the block which contains the plain version. (This rule is in the KMDF coding style guidelines.) As a result, the final source would look like this:

         //
        // cbImageNameLength = ((USHORT) wcslen(wsImageName)) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
        //
        status = RtlSizeTToUShort(wcslen(wsImageName), &cbImageNameLength);
        [...]

I think this is a decent tradeoff between correctness and readability. Another change you could make is to add begin/end comments around the entire computation block to further clarify the scope of which calls belong to which overall computation.