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