[SHELL32] Remove 2 redundant initializations
[reactos.git] / dll / ntdll / csr / capture.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: dll/ntdll/csr/capture.c
5 * PURPOSE: Routines for probing and capturing CSR API Messages
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include <ntdll.h>
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* GLOBALS ********************************************************************/
18
19 extern HANDLE CsrPortHeap;
20
21 /* FUNCTIONS ******************************************************************/
22
23 /*
24 * @implemented
25 */
26 VOID
27 NTAPI
28 CsrProbeForRead(IN PVOID Address,
29 IN ULONG Length,
30 IN ULONG Alignment)
31 {
32 volatile UCHAR *Pointer;
33 UCHAR Data;
34
35 /* Validate length */
36 if (Length == 0) return;
37
38 /* Validate alignment */
39 if ((ULONG_PTR)Address & (Alignment - 1))
40 {
41 /* Raise exception if it doesn't match */
42 RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
43 }
44
45 /* Probe first byte */
46 Pointer = Address;
47 Data = *Pointer;
48
49 /* Probe last byte */
50 Pointer = (PUCHAR)Address + Length - 1;
51 Data = *Pointer;
52 (void)Data;
53 }
54
55 /*
56 * @implemented
57 */
58 VOID
59 NTAPI
60 CsrProbeForWrite(IN PVOID Address,
61 IN ULONG Length,
62 IN ULONG Alignment)
63 {
64 volatile UCHAR *Pointer;
65
66 /* Validate length */
67 if (Length == 0) return;
68
69 /* Validate alignment */
70 if ((ULONG_PTR)Address & (Alignment - 1))
71 {
72 /* Raise exception if it doesn't match */
73 RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
74 }
75
76 /* Probe first byte */
77 Pointer = Address;
78 *Pointer = *Pointer;
79
80 /* Probe last byte */
81 Pointer = (PUCHAR)Address + Length - 1;
82 *Pointer = *Pointer;
83 }
84
85 /*
86 * @implemented
87 */
88 PCSR_CAPTURE_BUFFER
89 NTAPI
90 CsrAllocateCaptureBuffer(IN ULONG ArgumentCount,
91 IN ULONG BufferSize)
92 {
93 PCSR_CAPTURE_BUFFER CaptureBuffer;
94 ULONG OffsetsArraySize;
95 ULONG MaximumSize;
96
97 /* Validate the argument count. Note that on server side, CSRSRV
98 * limits the count to MAXUSHORT; here we are a bit more lenient. */
99 if (ArgumentCount > (MAXLONG / sizeof(ULONG_PTR)))
100 return NULL;
101
102 OffsetsArraySize = ArgumentCount * sizeof(ULONG_PTR);
103
104 /*
105 * Validate the total buffer size.
106 * The total size of the header plus the pointer-offset array and the
107 * provided buffer, together with the alignment padding for each argument,
108 * must be less than MAXLONG aligned to 4-byte boundary.
109 */
110 MaximumSize = (MAXLONG & ~3) - FIELD_OFFSET(CSR_CAPTURE_BUFFER, PointerOffsetsArray);
111 if (OffsetsArraySize >= MaximumSize)
112 return NULL;
113 MaximumSize -= OffsetsArraySize;
114 if (BufferSize >= MaximumSize)
115 return NULL;
116 MaximumSize -= BufferSize;
117 if ((ArgumentCount * 3) + 3 >= MaximumSize)
118 return NULL;
119
120 /* Add the size of the header and of the pointer-offset array */
121 BufferSize += FIELD_OFFSET(CSR_CAPTURE_BUFFER, PointerOffsetsArray) +
122 OffsetsArraySize;
123
124 /* Add the size of the alignment padding for each argument */
125 BufferSize += ArgumentCount * 3;
126
127 /* Align it to a 4-byte boundary */
128 BufferSize = (BufferSize + 3) & ~3;
129
130 /* Allocate memory from the port heap */
131 CaptureBuffer = RtlAllocateHeap(CsrPortHeap, HEAP_ZERO_MEMORY, BufferSize);
132 if (CaptureBuffer == NULL) return NULL;
133
134 /* Initialize the header */
135 CaptureBuffer->Size = BufferSize;
136 CaptureBuffer->PointerCount = 0;
137
138 /* Initialize the pointer-offset array */
139 RtlZeroMemory(CaptureBuffer->PointerOffsetsArray, OffsetsArraySize);
140
141 /* Point to the start of the free buffer */
142 CaptureBuffer->BufferEnd = (PVOID)((ULONG_PTR)CaptureBuffer->PointerOffsetsArray +
143 OffsetsArraySize);
144
145 /* Return the address of the buffer */
146 return CaptureBuffer;
147 }
148
149 /*
150 * @implemented
151 */
152 ULONG
153 NTAPI
154 CsrAllocateMessagePointer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer,
155 IN ULONG MessageLength,
156 OUT PVOID* CapturedData)
157 {
158 if (MessageLength == 0)
159 {
160 *CapturedData = NULL;
161 CapturedData = NULL;
162 }
163 else
164 {
165 /* Set the capture data at our current available buffer */
166 *CapturedData = CaptureBuffer->BufferEnd;
167
168 /* Validate the size */
169 if (MessageLength >= MAXLONG) return 0;
170
171 /* Align it to a 4-byte boundary */
172 MessageLength = (MessageLength + 3) & ~3;
173
174 /* Move our available buffer beyond this space */
175 CaptureBuffer->BufferEnd = (PVOID)((ULONG_PTR)CaptureBuffer->BufferEnd + MessageLength);
176 }
177
178 /* Write down this pointer in the array and increase the count */
179 CaptureBuffer->PointerOffsetsArray[CaptureBuffer->PointerCount++] = (ULONG_PTR)CapturedData;
180
181 /* Return the aligned length */
182 return MessageLength;
183 }
184
185 /*
186 * @implemented
187 */
188 VOID
189 NTAPI
190 CsrCaptureMessageBuffer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer,
191 IN PVOID MessageBuffer OPTIONAL,
192 IN ULONG MessageLength,
193 OUT PVOID* CapturedData)
194 {
195 /* Simply allocate a message pointer in the buffer */
196 CsrAllocateMessagePointer(CaptureBuffer, MessageLength, CapturedData);
197
198 /* Check if there was any data */
199 if (!MessageBuffer || !MessageLength) return;
200
201 /* Copy the data into the buffer */
202 RtlMoveMemory(*CapturedData, MessageBuffer, MessageLength);
203 }
204
205 /*
206 * @implemented
207 */
208 VOID
209 NTAPI
210 CsrFreeCaptureBuffer(IN PCSR_CAPTURE_BUFFER CaptureBuffer)
211 {
212 /* Free it from the heap */
213 RtlFreeHeap(CsrPortHeap, 0, CaptureBuffer);
214 }
215
216 /*
217 * @implemented
218 */
219 VOID
220 NTAPI
221 CsrCaptureMessageString(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer,
222 IN PCSTR String OPTIONAL,
223 IN ULONG StringLength,
224 IN ULONG MaximumLength,
225 OUT PSTRING CapturedString)
226 {
227 ASSERT(CapturedString != NULL);
228
229 /*
230 * If we don't have a string, initialize an empty one,
231 * otherwise capture the given string.
232 */
233 if (!String)
234 {
235 CapturedString->Length = 0;
236 CapturedString->MaximumLength = (USHORT)MaximumLength;
237
238 /* Allocate a pointer for it */
239 CsrAllocateMessagePointer(CaptureBuffer,
240 MaximumLength,
241 (PVOID*)&CapturedString->Buffer);
242 }
243 else
244 {
245 /* Cut-off the string length if needed */
246 if (StringLength > MaximumLength)
247 StringLength = MaximumLength;
248
249 CapturedString->Length = (USHORT)StringLength;
250
251 /* Allocate a buffer and get its size */
252 CapturedString->MaximumLength =
253 (USHORT)CsrAllocateMessagePointer(CaptureBuffer,
254 MaximumLength,
255 (PVOID*)&CapturedString->Buffer);
256
257 /* If the string has data, copy it into the buffer */
258 if (StringLength)
259 RtlMoveMemory(CapturedString->Buffer, String, StringLength);
260 }
261
262 /* Null-terminate the string if we don't take up the whole space */
263 if (CapturedString->Length < CapturedString->MaximumLength)
264 CapturedString->Buffer[CapturedString->Length] = '\0';
265 }
266
267 static VOID
268 CsrCaptureMessageUnicodeStringInPlace(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer,
269 IN PUNICODE_STRING String)
270 {
271 ASSERT(String != NULL);
272
273 /* This is a way to capture the UNICODE string, since (Maximum)Length are also in bytes */
274 CsrCaptureMessageString(CaptureBuffer,
275 (PCSTR)String->Buffer,
276 String->Length,
277 String->MaximumLength,
278 (PSTRING)String);
279
280 /* Null-terminate the string */
281 if (String->MaximumLength >= String->Length + sizeof(WCHAR))
282 {
283 String->Buffer[String->Length / sizeof(WCHAR)] = L'\0';
284 }
285 }
286
287 /*
288 * @implemented
289 */
290 NTSTATUS
291 NTAPI
292 CsrCaptureMessageMultiUnicodeStringsInPlace(OUT PCSR_CAPTURE_BUFFER* CaptureBuffer,
293 IN ULONG StringsCount,
294 IN PUNICODE_STRING* MessageStrings)
295 {
296 ULONG Count;
297
298 if (!CaptureBuffer) return STATUS_INVALID_PARAMETER;
299
300 /* Allocate a new capture buffer if we don't have one already */
301 if (!*CaptureBuffer)
302 {
303 /* Compute the required size for the capture buffer */
304 ULONG Size = 0;
305
306 Count = 0;
307 while (Count < StringsCount)
308 {
309 if (MessageStrings[Count])
310 Size += MessageStrings[Count]->MaximumLength;
311
312 ++Count;
313 }
314
315 /* Allocate the capture buffer */
316 *CaptureBuffer = CsrAllocateCaptureBuffer(StringsCount, Size);
317 if (!*CaptureBuffer) return STATUS_NO_MEMORY;
318 }
319
320 /* Now capture each UNICODE string */
321 Count = 0;
322 while (Count < StringsCount)
323 {
324 if (MessageStrings[Count])
325 CsrCaptureMessageUnicodeStringInPlace(*CaptureBuffer, MessageStrings[Count]);
326
327 ++Count;
328 }
329
330 return STATUS_SUCCESS;
331 }
332
333 /*
334 * @implemented
335 */
336 PLARGE_INTEGER
337 NTAPI
338 CsrCaptureTimeout(IN ULONG Milliseconds,
339 OUT PLARGE_INTEGER Timeout)
340 {
341 /* Validate the time */
342 if (Milliseconds == -1) return NULL;
343
344 /* Convert to relative ticks */
345 Timeout->QuadPart = Milliseconds * -10000LL;
346 return Timeout;
347 }
348
349 /* EOF */