xref: /reactos/dll/win32/kernel32/include/base_x.h (revision 18a9993d)
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