"Tony Lambregts" tony_lambregts@telusplanet.net wrote:
For the benefit of those of us who are a little thick could someone explain what that means. I understand that the TEB has TlsSlots for local storage but.. there is so much I do not understand. A little help...
The TEB (see include/thread.h) has a specially reserved buffer (StaticUnicodeBuffer) with the size of MAX_PATH+1 unicode characters and UNICODE_STRING structure (StaticUnicodeString) pointing to that buffer. That space could be used for in order to speed up things by avoiding memory allocation.
Here is a sample implementation of CreateDirectoryA that uses TEB static unicode buffer. I have created a helper function asciiz_to_unicode which takes an ASCIIZ string, converts it to unicode and returns a pointer to the UNICODE_STRING structure (i.e. it also returns the size of the resulting unicode string). I think that using a helper can save a bit of memory isolating a commonly used code into a single place, and makes it simpler to modify the code if we will later decide to change the implementation.
Feel free to use it as a guide for converting ANSI file APIs to use that scheme.
#include "winbase.h" #include "winerror.h" #include "winternl.h" #include "thread.h"
/* * asciiz_to_unicode (internal) * Does not check for NULL. This is a duty of a higher level API. */ UNICODE_STRING *asciiz_to_unicode(LPCSTR src) { UNICODE_STRING *unicode = &NtCurrentTeb()->StaticUnicodeString; STRING ansi; NTSTATUS status;
RtlInitAnsiString(&ansi, src); status = RtlAnsiStringToUnicodeString(unicode, &ansi, FALSE); if (!status) return unicode;
if (status == STATUS_BUFFER_OVERFLOW) SetLastError(ERROR_FILENAME_EXCED_RANGE); else SetLastError(RtlNtStatusToDosError(status)); return NULL; }
/*********************************************************************** * CreateDirectoryA (KERNEL32.@) */ BOOL WINAPI CreateDirectoryA( LPCSTR path, LPSECURITY_ATTRIBUTES lpsecattribs ) { UNICODE_STRING *pathW;
if (!path || !*path) { SetLastError(ERROR_PATH_NOT_FOUND); return FALSE; }
pathW = asciiz_to_unicode(path); if (pathW) return CreateDirectoryW(pathW->Buffer, lpsecattribs); return FALSE; }