1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS System Libraries 4 * FILE: dll/win32/kernel32/include/base_x.h 5 * PURPOSE: Base API Client Macros 6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net) 7 */ 8 9 #pragma once 10 11 /* INCLUDES *******************************************************************/ 12 13 // 14 // This macro (split it up in 3 pieces to allow for intermediary code in between) 15 // converts a NULL-terminated ASCII string, usually associated with an object 16 // name, into its NT-native UNICODE_STRING structure, by using the TEB's Static 17 // Unicode String. 18 // 19 // It should only be used when the name is supposed to be less than MAX_PATH 20 // (260 characters). 21 // 22 // It returns the correct ERROR_FILENAME_EXCED_RANGE Win32 error when the path 23 // is too long. 24 // 25 // Note that Basep8BitStringToStaticUnicodeString looks deceptively similar. 26 // However, that function was designed for File APIs, which can be switched into 27 // a special "OEM" mode, that uses different NLS files/encoding, and thus calls 28 // RtlOemStringToAnsiString (see SetFileApisToOEM). Therefore, this macro and 29 // that function are not interchangeable. As a separate note, that function uses 30 // the *Ex version of the Rtl conversion APIs, which does stricter checking that 31 // is not done when this macro is used. 32 // 33 #define ConvertAnsiToUnicodePrologue \ 34 { \ 35 NTSTATUS Status; \ 36 PUNICODE_STRING UnicodeCache; \ 37 ANSI_STRING AnsiName; 38 #define ConvertAnsiToUnicodeBody(name) \ 39 UnicodeCache = &NtCurrentTeb()->StaticUnicodeString; \ 40 RtlInitAnsiString(&AnsiName, name); \ 41 Status = RtlAnsiStringToUnicodeString(UnicodeCache, &AnsiName, FALSE); 42 #define ConvertAnsiToUnicodeEpilogue \ 43 if (Status == STATUS_BUFFER_OVERFLOW) \ 44 SetLastError(ERROR_FILENAME_EXCED_RANGE); \ 45 else \ 46 BaseSetLastNTError(Status); \ 47 return FALSE; \ 48 } 49 50 // 51 // This macro uses the ConvertAnsiToUnicode macros above to convert a CreateXxxA 52 // Win32 API into its equivalent CreateXxxW API. 53 // 54 #define ConvertWin32AnsiObjectApiToUnicodeApi(obj, name, ...) \ 55 ConvertAnsiToUnicodePrologue \ 56 if (!name) return Create##obj##W(__VA_ARGS__, NULL); \ 57 ConvertAnsiToUnicodeBody(name) \ 58 if (NT_SUCCESS(Status)) return Create##obj##W(__VA_ARGS__, UnicodeCache->Buffer); \ 59 ConvertAnsiToUnicodeEpilogue 60 61 // 62 // This macro uses the ConvertAnsiToUnicode macros above to convert a CreateXxxA 63 // Win32 API into its equivalent CreateXxxW API. 64 // 65 #define ConvertWin32AnsiObjectApiToUnicodeApi2(obj, name, ...) \ 66 ConvertAnsiToUnicodePrologue \ 67 if (!name) return Create##obj##W(NULL, __VA_ARGS__); \ 68 ConvertAnsiToUnicodeBody(name) \ 69 if (NT_SUCCESS(Status)) return Create##obj##W(UnicodeCache->Buffer, __VA_ARGS__); \ 70 ConvertAnsiToUnicodeEpilogue 71 72 // 73 // This macro uses the ConvertAnsiToUnicode macros above to convert a FindFirst*A 74 // Win32 API into its equivalent FindFirst*W API. 75 // 76 #define ConvertWin32AnsiChangeApiToUnicodeApi(obj, name, ...) \ 77 ConvertAnsiToUnicodePrologue \ 78 ConvertAnsiToUnicodeBody(name) \ 79 if (NT_SUCCESS(Status)) return obj##W(UnicodeCache->Buffer, ##__VA_ARGS__); \ 80 ConvertAnsiToUnicodeEpilogue 81 82 // 83 // This macro uses the ConvertAnsiToUnicode macros above to convert a OpenXxxA 84 // Win32 API into its equivalent OpenXxxW API. 85 // 86 #define ConvertOpenWin32AnsiObjectApiToUnicodeApi(obj, acc, inh, name) \ 87 ConvertAnsiToUnicodePrologue \ 88 if (!name) \ 89 { \ 90 SetLastError(ERROR_INVALID_PARAMETER); \ 91 return NULL; \ 92 } \ 93 ConvertAnsiToUnicodeBody(name) \ 94 if (NT_SUCCESS(Status)) return Open##obj##W(acc, inh, UnicodeCache->Buffer);\ 95 ConvertAnsiToUnicodeEpilogue 96 97 // 98 // This macro (split it up in 3 pieces to allow for intermediary code in between) 99 // wraps the usual code path required to create an NT object based on a Unicode 100 // (Wide) Win32 object creation API. 101 // 102 // It makes use of BaseFormatObjectAttributes and allows for a custom access 103 // mode to be used, and also sets the correct error codes in case of a collision 104 // 105 #define CreateNtObjectFromWin32ApiPrologue \ 106 { \ 107 NTSTATUS Status; \ 108 HANDLE Handle; \ 109 UNICODE_STRING ObjectName; \ 110 OBJECT_ATTRIBUTES LocalAttributes; \ 111 POBJECT_ATTRIBUTES ObjectAttributes = &LocalAttributes; 112 #define CreateNtObjectFromWin32ApiBody(ntobj, sec, name, access, ...) \ 113 if (name) RtlInitUnicodeString(&ObjectName, name); \ 114 ObjectAttributes = BaseFormatObjectAttributes(&LocalAttributes, \ 115 sec, \ 116 name ? &ObjectName : NULL); \ 117 Status = NtCreate##ntobj(&Handle, access, ObjectAttributes, ##__VA_ARGS__); 118 #define CreateNtObjectFromWin32ApiEpilogue \ 119 if (NT_SUCCESS(Status)) \ 120 { \ 121 if (Status == STATUS_OBJECT_NAME_EXISTS) \ 122 SetLastError(ERROR_ALREADY_EXISTS); \ 123 else \ 124 SetLastError(ERROR_SUCCESS); \ 125 return Handle; \ 126 } \ 127 BaseSetLastNTError(Status); \ 128 return NULL; \ 129 } 130 131 // 132 // This macro uses the CreateNtObjectFromWin32Api macros from above to create an 133 // NT object based on the Win32 API settings. 134 // 135 #define CreateNtObjectFromWin32Api(obj, ntobj, access, sec, name, ...) \ 136 CreateNtObjectFromWin32ApiPrologue \ 137 CreateNtObjectFromWin32ApiBody(ntobj, sec, name, access, ##__VA_ARGS__); \ 138 CreateNtObjectFromWin32ApiEpilogue 139 140 // 141 // This macro opens an NT object based on the Win32 API settings. 142 // 143 #define OpenNtObjectFromWin32Api(ntobj, acc, inh, name) \ 144 CreateNtObjectFromWin32ApiPrologue \ 145 if (!name) \ 146 { \ 147 BaseSetLastNTError(STATUS_INVALID_PARAMETER); \ 148 return NULL; \ 149 } \ 150 RtlInitUnicodeString(&ObjectName, name); \ 151 InitializeObjectAttributes(ObjectAttributes, \ 152 &ObjectName, \ 153 inh ? OBJ_INHERIT : 0, \ 154 BaseGetNamedObjectDirectory(), \ 155 NULL); \ 156 Status = NtOpen##ntobj(&Handle, acc, ObjectAttributes); \ 157 if (!NT_SUCCESS(Status)) \ 158 { \ 159 BaseSetLastNTError(Status); \ 160 return NULL; \ 161 } \ 162 return Handle; \ 163 } 164 165