* Sync to trunk HEAD (r53298).
[reactos.git] / dll / win32 / kernel32 / include / base_x.h
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). Thererefore, 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 FindFirst*A
63 // Win32 API into its equivalent FindFirst*W API.
64 //
65 #define ConvertWin32AnsiChangeApiToUnicodeApi(obj, name, ...) \
66 ConvertAnsiToUnicodePrologue \
67 ConvertAnsiToUnicodeBody(name) \
68 if (NT_SUCCESS(Status)) return obj##W(UnicodeCache->Buffer, ##__VA_ARGS__); \
69 ConvertAnsiToUnicodeEpilogue
70
71 //
72 // This macro uses the ConvertAnsiToUnicode macros above to convert a OpenXxxA
73 // Win32 API into its equivalent OpenXxxW API.
74 //
75 #define ConvertOpenWin32AnsiObjectApiToUnicodeApi(obj, acc, inh, name) \
76 ConvertAnsiToUnicodePrologue \
77 if (!name) \
78 { \
79 SetLastError(ERROR_INVALID_PARAMETER); \
80 return NULL; \
81 } \
82 ConvertAnsiToUnicodeBody(name) \
83 if (NT_SUCCESS(Status)) return Open##obj##W(acc, inh, UnicodeCache->Buffer);\
84 ConvertAnsiToUnicodeEpilogue
85
86 //
87 // This macro (split it up in 3 pieces to allow for intermediary code in between)
88 // wraps the usual code path required to create an NT object based on a Unicode
89 // (Wide) Win32 object creation API.
90 //
91 // It makes use of BasepConvertObjectAttributes and allows for a custom access
92 // mode to be used, and also sets the correct error codes in case of a collision
93 //
94 #define CreateNtObjectFromWin32ApiPrologue \
95 { \
96 NTSTATUS Status; \
97 HANDLE Handle; \
98 UNICODE_STRING ObjectName; \
99 OBJECT_ATTRIBUTES LocalAttributes; \
100 POBJECT_ATTRIBUTES ObjectAttributes = &LocalAttributes;
101 #define CreateNtObjectFromWin32ApiBody(ntobj, sec, name, access, ...) \
102 if (name) RtlInitUnicodeString(&ObjectName, name); \
103 ObjectAttributes = BasepConvertObjectAttributes(&LocalAttributes, \
104 sec, \
105 name ? &ObjectName : NULL); \
106 Status = NtCreate##ntobj(&Handle, access, ObjectAttributes, ##__VA_ARGS__);
107 #define CreateNtObjectFromWin32ApiEpilogue \
108 if (NT_SUCCESS(Status)) \
109 { \
110 if (Status == STATUS_OBJECT_NAME_EXISTS) \
111 SetLastError(ERROR_ALREADY_EXISTS); \
112 else \
113 SetLastError(ERROR_SUCCESS); \
114 return Handle; \
115 } \
116 BaseSetLastNTError(Status); \
117 return NULL; \
118 }
119
120 //
121 // This macro uses the CreateNtObjectFromWin32Api macros from above to create an
122 // NT object based on the Win32 API settings.
123 //
124 // Note that it is hardcoded to always use XXX_ALL_ACCESS permissions, which is
125 // the behavior up until Vista. When/if the target moves to Vista, the macro can
126 // be improved to support caller-specified access masks, as the underlying macro
127 // above does support this.
128 //
129 #define CreateNtObjectFromWin32Api(obj, ntobj, capsobj, sec, name, ...) \
130 CreateNtObjectFromWin32ApiPrologue \
131 CreateNtObjectFromWin32ApiBody(ntobj, sec, name, capsobj##_ALL_ACCESS, ##__VA_ARGS__); \
132 CreateNtObjectFromWin32ApiEpilogue
133
134 //
135 // This macro opens an NT object based on the Win32 API settings.
136 //
137 #define OpenNtObjectFromWin32Api(ntobj, acc, inh, name) \
138 CreateNtObjectFromWin32ApiPrologue \
139 if (!name) \
140 { \
141 BaseSetLastNTError(STATUS_INVALID_PARAMETER); \
142 return NULL; \
143 } \
144 RtlInitUnicodeString(&ObjectName, name); \
145 InitializeObjectAttributes(ObjectAttributes, \
146 &ObjectName, \
147 inh ? OBJ_INHERIT : 0, \
148 hBaseDir, \
149 NULL); \
150 Status = NtOpen##ntobj(&Handle, acc, ObjectAttributes); \
151 if (!NT_SUCCESS(Status)) \
152 { \
153 BaseSetLastNTError(Status); \
154 return NULL; \
155 } \
156 return Handle; \
157 }
158