Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTDEV

Before Posting...

Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


Declaring and using UNICODE_STRING on the Heap

OSR_Community_UserOSR_Community_User Member Posts: 110,217
Hello! I was wondering what the procedure is to declare UNICODE_STRINGs on the heap and then actually perform typical operations on them. I need to use the heap as my driver takes up too much of stack memory (and I believe it's due to the large Unicode strings I use). Here's some code (which I know doesn't work) of what I thought it might involve:

PWCHAR processString;
UNICODE_STRING uProcess = {0};

processString = (PWCHAR)ExAllocatePoolWithTag(PagedPool, sizeof(WCHAR) * 150, 'ofpr');
RtlInitEmptyUnicodeString(&uProcess, processString, sizeof(WCHAR) * 150);
RtlAppendUnicodeToString(&uProcess, L"svchost.exe");
ExFreePool(processString);

As you can see, I'm declaring the buffer on the heap, I also wondered, is there a way to put the whole Unicode string on the heap? Or is that unnecessary as long as the buffer is on the heap? I also wondered, when it comes to using typical Rtl operations for UNICODE_STRINGS, can they be applied to unicode strings on the heap or do we have to use alternative methods?

Please provide code samples with your answer so I understand it fully! I normally wouldn't ask about a topic such as this, but I couldn't find documentation on it anywhere!!

Comments

  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    I should add that I also set:
    uProcess.Length = 0;
    uProcess.MaximumLength = sizeof(WCHAR) * 150
  • matt_sykesmatt_sykes Member - All Emails Posts: 298
    Sure, just allocate a chunk of memory on the heap big enough and cast it to a UNIDOCD_STRING.
  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    @matt sykes I'm currently allocating space for the buffer on the heap. The way you're suggesting, do I only allocate space for the UNICODE_STRING on the heap? And if so, how do I specify the size of the buffer attached to that UNICODE_STRING to allocate onto the heap? Also, can I then use the normal RtlAppendUnicodeToString with my Unicode string on the heap?

    Some code samples initialising a UNICODE_STRING on the heap and then appending to it would really help my understanding here.
  • matt_sykesmatt_sykes Member - All Emails Posts: 298
    No, you can allocate one buffer big enough for the UNICODE_STRING structure and the buffer. Then point the buffer pointer member of the UNICODE_STRING to 'big buffer address + sizeof(UNICODE_STRING)'

    Or you can have the two in seperate places in memory, up to you. Just remember, a UNICODE_STRING only describes a buffer, it describes its max length, and its current usage. The buffer can be anywhere you like.
  • Doron_HolanDoron_Holan Member - All Emails Posts: 10,835
    Use the lifetime of the structure to determine if it is on the stack or from pool. Regardless of lifetime, if the buffer is large, it comes from the pool. You don't really need a separate PWSTR stack variable either, you can assign the pool allocation directly to the Buffer field of the struct.

    Bent from my phone
    ________________________________
    From: [email protected] on behalf of [email protected]
    Sent: Wednesday, April 26, 2017 4:46:37 AM
    To: Windows System Software Devs Interest List
    Subject: RE:[ntdev] Declaring and using UNICODE_STRING on the Heap

    No, you can allocate one buffer big enough for the UNICODE_STRING structure and the buffer. Then point the buffer pointer member of the UNICODE_STRING to 'big buffer address + sizeof(UNICODE_STRING)'

    Or you can have the two in seperate places in memory, up to you. Just remember, a UNICODE_STRING only describes a buffer, it describes its max length, and its current usage. The buffer can be anywhere you like.

    ---
    NTDEV is sponsored by OSR

    Visit the list online at:

    MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
    Details at

    To unsubscribe, visit the List Server section of OSR Online at
    d
  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,852
    [email protected] wrote:
    > Hello! I was wondering what the procedure is to declare UNICODE_STRINGs on the heap and then actually perform typical operations on them. I need to use the heap as my driver takes up too much of stack memory (and I believe it's due to the large Unicode strings I use). Here's some code (which I know doesn't work) of what I thought it might involve:
    >
    > PWCHAR processString;
    > UNICODE_STRING uProcess = {0};
    > ...
    > As you can see, I'm declaring the buffer on the heap, I also wondered, is there a way to put the whole Unicode string on the heap? Or is that unnecessary as long as the buffer is on the heap?

    The UNICODE_STRING structure is at most 16 bytes long. It's hardly
    worth worrying about.


    > I also wondered, when it comes to using typical Rtl operations for UNICODE_STRINGS, can they be applied to unicode strings on the heap or do we have to use alternative methods?

    Memory is memory. Once you have an address, no one knows from whence it
    came.

    --
    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

    Tim Roberts, [email protected]
    Software Wizard Emeritus

  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    Yes it is.


    #ifndef NTSTRSAFE_NO_CB_FUNCTIONS
    /*++

    NTSTATUS
    RtlUnicodeStringCbCatStringNEx(
    _Inout_ PUNICODE_STRING DestinationString OPTIONAL,
    _In_ LPCTSTR pszSrc OPTIONAL,
    _In_ size_t cbToAppend,
    _Out_opt_ PUNICODE_STRING RemainingString OPTIONAL,
    _In_ DWORD dwFlags
    );

    Routine Description:

    This routine is a safer version of the C built-in function 'strncat', with
    some additional parameters and for PUNICODE_STRINGs. In addition to the
    functionality provided by RtlUnicodeStringCbCatStringN, this routine
    also returns a PUNICODE_STRING which points to the end of the destination
    string. The flags parameter allows additional controls.


    2017-04-26 20:28 GMT+02:00 Matthew Nunes :

    > I included but it says that the RtlUnicodeStringCbCatStringNEx is undefined. Have any idea why?
    >
    > Thanks,Matthew
    >
    >
    >
  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    @Tim Roberts thank you for the concise and simplistic explanation!! That explains it for me!! For those wondering what I did, here's the code for putting the buffer of UNICODE_STRING on the heap (although as Tim explained, it can be done in fewer lines):

    UNICODE_STRING uString = {0};
    uString.Length = 0;
    uString.MaximumLength = 150 * sizeof(WCHAR);
    stringBuffer = (PWCHAR)ExAllocatePoolWithTag(PagedPool, sizeof(WCHAR) * 150, 'offu');

    Then you can use string operations as normal.

    @D. T suggested I look here for safe string functions: https://msdn.microsoft.com/en-us/library/windows/hardware/ff565508(v=vs.85).aspx

    This link was very useful BUT when I #include <ntstrsafe.h> and then use RtlUnicodeStringCbCatStringNEx, it says the function is undefined! Anyone know why this issue is occurring?

    I'm sorry @D.T, I don't fully understand your last answer? I know that function IS defined in the library (according to the documentation), but the compiler thinks otherwise.
  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    >I'm sorry @D.T, I don't fully understand your last answer?

    I've just pasted the part of the header where the function is defined. I thought I would find a prototype but that was the implementation. That is why a preprocessor definition can be used to prevent the function from being defined and integrated to the binary to save memory space once the driver is loaded.

    But by default the function should be available once the header is included.

    What IDE are you using ?
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. Sign in or register to get started.

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Kernel Debugging 9-13 Sept 2024 Live, Online
Developing Minifilters 15-19 July 2024 Live, Online
Internals & Software Drivers 11-15 Mar 2024 Live, Online
Writing WDF Drivers 20-24 May 2024 Live, Online