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)
10 /* INCLUDES *******************************************************************/
17 /* GLOBALS ********************************************************************/
19 extern HANDLE CsrPortHeap
;
21 /* FUNCTIONS ******************************************************************/
28 CsrProbeForRead(IN PVOID Address
,
32 volatile UCHAR
*Pointer
;
36 if (Length
== 0) return;
38 /* Validate alignment */
39 if ((ULONG_PTR
)Address
& (Alignment
- 1))
41 /* Raise exception if it doesn't match */
42 RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT
);
45 /* Probe first byte */
50 Pointer
= (PUCHAR
)Address
+ Length
- 1;
60 CsrProbeForWrite(IN PVOID Address
,
64 volatile UCHAR
*Pointer
;
67 if (Length
== 0) return;
69 /* Validate alignment */
70 if ((ULONG_PTR
)Address
& (Alignment
- 1))
72 /* Raise exception if it doesn't match */
73 RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT
);
76 /* Probe first byte */
81 Pointer
= (PUCHAR
)Address
+ Length
- 1;
90 CsrAllocateCaptureBuffer(IN ULONG ArgumentCount
,
93 PCSR_CAPTURE_BUFFER CaptureBuffer
;
94 ULONG OffsetsArraySize
;
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
)))
102 OffsetsArraySize
= ArgumentCount
* sizeof(ULONG_PTR
);
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.
110 MaximumSize
= (MAXLONG
& ~3) - FIELD_OFFSET(CSR_CAPTURE_BUFFER
, PointerOffsetsArray
);
111 if (OffsetsArraySize
>= MaximumSize
)
113 MaximumSize
-= OffsetsArraySize
;
114 if (BufferSize
>= MaximumSize
)
116 MaximumSize
-= BufferSize
;
117 if ((ArgumentCount
* 3) + 3 >= MaximumSize
)
120 /* Add the size of the header and of the pointer-offset array */
121 BufferSize
+= FIELD_OFFSET(CSR_CAPTURE_BUFFER
, PointerOffsetsArray
) +
124 /* Add the size of the alignment padding for each argument */
125 BufferSize
+= ArgumentCount
* 3;
127 /* Align it to a 4-byte boundary */
128 BufferSize
= (BufferSize
+ 3) & ~3;
130 /* Allocate memory from the port heap */
131 CaptureBuffer
= RtlAllocateHeap(CsrPortHeap
, HEAP_ZERO_MEMORY
, BufferSize
);
132 if (CaptureBuffer
== NULL
) return NULL
;
134 /* Initialize the header */
135 CaptureBuffer
->Size
= BufferSize
;
136 CaptureBuffer
->PointerCount
= 0;
138 /* Initialize the pointer-offset array */
139 RtlZeroMemory(CaptureBuffer
->PointerOffsetsArray
, OffsetsArraySize
);
141 /* Point to the start of the free buffer */
142 CaptureBuffer
->BufferEnd
= (PVOID
)((ULONG_PTR
)CaptureBuffer
->PointerOffsetsArray
+
145 /* Return the address of the buffer */
146 return CaptureBuffer
;
154 CsrAllocateMessagePointer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer
,
155 IN ULONG MessageLength
,
156 OUT PVOID
* CapturedData
)
158 if (MessageLength
== 0)
160 *CapturedData
= NULL
;
165 /* Set the capture data at our current available buffer */
166 *CapturedData
= CaptureBuffer
->BufferEnd
;
168 /* Validate the size */
169 if (MessageLength
>= MAXLONG
) return 0;
171 /* Align it to a 4-byte boundary */
172 MessageLength
= (MessageLength
+ 3) & ~3;
174 /* Move our available buffer beyond this space */
175 CaptureBuffer
->BufferEnd
= (PVOID
)((ULONG_PTR
)CaptureBuffer
->BufferEnd
+ MessageLength
);
178 /* Write down this pointer in the array and increase the count */
179 CaptureBuffer
->PointerOffsetsArray
[CaptureBuffer
->PointerCount
++] = (ULONG_PTR
)CapturedData
;
181 /* Return the aligned length */
182 return MessageLength
;
190 CsrCaptureMessageBuffer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer
,
191 IN PVOID MessageBuffer OPTIONAL
,
192 IN ULONG MessageLength
,
193 OUT PVOID
* CapturedData
)
195 /* Simply allocate a message pointer in the buffer */
196 CsrAllocateMessagePointer(CaptureBuffer
, MessageLength
, CapturedData
);
198 /* Check if there was any data */
199 if (!MessageBuffer
|| !MessageLength
) return;
201 /* Copy the data into the buffer */
202 RtlMoveMemory(*CapturedData
, MessageBuffer
, MessageLength
);
210 CsrFreeCaptureBuffer(IN PCSR_CAPTURE_BUFFER CaptureBuffer
)
212 /* Free it from the heap */
213 RtlFreeHeap(CsrPortHeap
, 0, CaptureBuffer
);
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
)
227 ASSERT(CapturedString
!= NULL
);
230 * If we don't have a string, initialize an empty one,
231 * otherwise capture the given string.
235 CapturedString
->Length
= 0;
236 CapturedString
->MaximumLength
= (USHORT
)MaximumLength
;
238 /* Allocate a pointer for it */
239 CsrAllocateMessagePointer(CaptureBuffer
,
241 (PVOID
*)&CapturedString
->Buffer
);
245 /* Cut-off the string length if needed */
246 if (StringLength
> MaximumLength
)
247 StringLength
= MaximumLength
;
249 CapturedString
->Length
= (USHORT
)StringLength
;
251 /* Allocate a buffer and get its size */
252 CapturedString
->MaximumLength
=
253 (USHORT
)CsrAllocateMessagePointer(CaptureBuffer
,
255 (PVOID
*)&CapturedString
->Buffer
);
257 /* If the string has data, copy it into the buffer */
259 RtlMoveMemory(CapturedString
->Buffer
, String
, StringLength
);
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';
268 CsrCaptureMessageUnicodeStringInPlace(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer
,
269 IN PUNICODE_STRING String
)
271 ASSERT(String
!= NULL
);
273 /* This is a way to capture the UNICODE string, since (Maximum)Length are also in bytes */
274 CsrCaptureMessageString(CaptureBuffer
,
275 (PCSTR
)String
->Buffer
,
277 String
->MaximumLength
,
280 /* Null-terminate the string */
281 if (String
->MaximumLength
>= String
->Length
+ sizeof(WCHAR
))
283 String
->Buffer
[String
->Length
/ sizeof(WCHAR
)] = L
'\0';
292 CsrCaptureMessageMultiUnicodeStringsInPlace(OUT PCSR_CAPTURE_BUFFER
* CaptureBuffer
,
293 IN ULONG StringsCount
,
294 IN PUNICODE_STRING
* MessageStrings
)
298 if (!CaptureBuffer
) return STATUS_INVALID_PARAMETER
;
300 /* Allocate a new capture buffer if we don't have one already */
303 /* Compute the required size for the capture buffer */
307 while (Count
< StringsCount
)
309 if (MessageStrings
[Count
])
310 Size
+= MessageStrings
[Count
]->MaximumLength
;
315 /* Allocate the capture buffer */
316 *CaptureBuffer
= CsrAllocateCaptureBuffer(StringsCount
, Size
);
317 if (!*CaptureBuffer
) return STATUS_NO_MEMORY
;
320 /* Now capture each UNICODE string */
322 while (Count
< StringsCount
)
324 if (MessageStrings
[Count
])
325 CsrCaptureMessageUnicodeStringInPlace(*CaptureBuffer
, MessageStrings
[Count
]);
330 return STATUS_SUCCESS
;
338 CsrCaptureTimeout(IN ULONG Milliseconds
,
339 OUT PLARGE_INTEGER Timeout
)
341 /* Validate the time */
342 if (Milliseconds
== -1) return NULL
;
344 /* Convert to relative ticks */
345 Timeout
->QuadPart
= Milliseconds
* -10000LL;