Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS System Libraries * FILE: dll/win32/kernel32/include/base_x.h * PURPOSE: Base API Client Macros * PROGRAMMER: Alex Ionescu (alex@relsoft.net) */
#pragma once
/* INCLUDES *******************************************************************/
//// This macro (split it up in 3 pieces to allow for intermediary code in between)// converts a NULL-terminated ASCII string, usually associated with an object// name, into its NT-native UNICODE_STRING structure, by using the TEB's Static// Unicode String.//// It should only be used when the name is supposed to be less than MAX_PATH// (260 characters).//// It returns the correct ERROR_FILENAME_EXCED_RANGE Win32 error when the path// is too long.//// Note that Basep8BitStringToStaticUnicodeString looks deceptively similar.// However, that function was designed for File APIs, which can be switched into// a special "OEM" mode, that uses different NLS files/encoding, and thus calls// RtlOemStringToAnsiString (see SetFileApisToOEM). Therefore, this macro and// that function are not interchangeable. As a separate note, that function uses// the *Ex version of the Rtl conversion APIs, which does stricter checking that// is not done when this macro is used.//#define ConvertAnsiToUnicodePrologue \{ \ NTSTATUS Status; \ PUNICODE_STRING UnicodeCache; \ ANSI_STRING AnsiName;#define ConvertAnsiToUnicodeBody(name) \ UnicodeCache = &NtCurrentTeb()->StaticUnicodeString; \ RtlInitAnsiString(&AnsiName, name); \ Status = RtlAnsiStringToUnicodeString(UnicodeCache, &AnsiName, FALSE);#define ConvertAnsiToUnicodeEpilogue \ if (Status == STATUS_BUFFER_OVERFLOW) \ SetLastError(ERROR_FILENAME_EXCED_RANGE); \ else \ BaseSetLastNTError(Status); \ return FALSE; \}
//// This macro uses the ConvertAnsiToUnicode macros above to convert a CreateXxxA// Win32 API into its equivalent CreateXxxW API.//#define ConvertWin32AnsiObjectApiToUnicodeApi(obj, name, ...) \ ConvertAnsiToUnicodePrologue \ if (!name) return Create##obj##W(__VA_ARGS__, NULL); \ ConvertAnsiToUnicodeBody(name) \ if (NT_SUCCESS(Status)) return Create##obj##W(__VA_ARGS__, UnicodeCache->Buffer); \ ConvertAnsiToUnicodeEpilogue
//// This macro uses the ConvertAnsiToUnicode macros above to convert a CreateXxxA// Win32 API into its equivalent CreateXxxW API.//#define ConvertWin32AnsiObjectApiToUnicodeApi2(obj, name, ...) \ ConvertAnsiToUnicodePrologue \ if (!name) return Create##obj##W(NULL, __VA_ARGS__); \ ConvertAnsiToUnicodeBody(name) \ if (NT_SUCCESS(Status)) return Create##obj##W(UnicodeCache->Buffer, __VA_ARGS__); \ ConvertAnsiToUnicodeEpilogue
//// This macro uses the ConvertAnsiToUnicode macros above to convert a FindFirst*A// Win32 API into its equivalent FindFirst*W API.//#define ConvertWin32AnsiChangeApiToUnicodeApi(obj, name, ...) \ ConvertAnsiToUnicodePrologue \ ConvertAnsiToUnicodeBody(name) \ if (NT_SUCCESS(Status)) return obj##W(UnicodeCache->Buffer, ##__VA_ARGS__); \ ConvertAnsiToUnicodeEpilogue
//// This macro uses the ConvertAnsiToUnicode macros above to convert a OpenXxxA// Win32 API into its equivalent OpenXxxW API.//#define ConvertOpenWin32AnsiObjectApiToUnicodeApi(obj, acc, inh, name) \ ConvertAnsiToUnicodePrologue \ if (!name) \ { \ SetLastError(ERROR_INVALID_PARAMETER); \ return NULL; \ } \ ConvertAnsiToUnicodeBody(name) \ if (NT_SUCCESS(Status)) return Open##obj##W(acc, inh, UnicodeCache->Buffer);\ ConvertAnsiToUnicodeEpilogue
//// This macro (split it up in 3 pieces to allow for intermediary code in between)// wraps the usual code path required to create an NT object based on a Unicode// (Wide) Win32 object creation API.//// It makes use of BaseFormatObjectAttributes and allows for a custom access// mode to be used, and also sets the correct error codes in case of a collision//#define CreateNtObjectFromWin32ApiPrologue \{ \ NTSTATUS Status; \ HANDLE Handle; \ UNICODE_STRING ObjectName; \ OBJECT_ATTRIBUTES LocalAttributes; \ POBJECT_ATTRIBUTES ObjectAttributes = &LocalAttributes;#define CreateNtObjectFromWin32ApiBody(ntobj, sec, name, access, ...) \ if (name) RtlInitUnicodeString(&ObjectName, name); \ ObjectAttributes = BaseFormatObjectAttributes(&LocalAttributes, \ sec, \ name ? &ObjectName : NULL); \ Status = NtCreate##ntobj(&Handle, access, ObjectAttributes, ##__VA_ARGS__);#define CreateNtObjectFromWin32ApiEpilogue \ if (NT_SUCCESS(Status)) \ { \ if (Status == STATUS_OBJECT_NAME_EXISTS) \ SetLastError(ERROR_ALREADY_EXISTS); \ else \ SetLastError(ERROR_SUCCESS); \ return Handle; \ } \ BaseSetLastNTError(Status); \ return NULL; \}
//// This macro uses the CreateNtObjectFromWin32Api macros from above to create an// NT object based on the Win32 API settings.//#define CreateNtObjectFromWin32Api(obj, ntobj, access, sec, name, ...) \ CreateNtObjectFromWin32ApiPrologue \ CreateNtObjectFromWin32ApiBody(ntobj, sec, name, access, ##__VA_ARGS__); \ CreateNtObjectFromWin32ApiEpilogue
//// This macro opens an NT object based on the Win32 API settings.//#define OpenNtObjectFromWin32Api(ntobj, acc, inh, name) \ CreateNtObjectFromWin32ApiPrologue \ if (!name) \ { \ BaseSetLastNTError(STATUS_INVALID_PARAMETER); \ return NULL; \ } \ RtlInitUnicodeString(&ObjectName, name); \ InitializeObjectAttributes(ObjectAttributes, \ &ObjectName, \ inh ? OBJ_INHERIT : 0, \ BaseGetNamedObjectDirectory(), \ NULL); \ Status = NtOpen##ntobj(&Handle, acc, ObjectAttributes); \ if (!NT_SUCCESS(Status)) \ { \ BaseSetLastNTError(Status); \ return NULL; \ } \ return Handle; \}