ReactOS 0.4.15-dev-7953-g1f49173
base_x.h
Go to the documentation of this file.
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