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)
9 /* INCLUDES *******************************************************************/
16 /* GLOBALS ********************************************************************/
18 extern HANDLE CsrPortHeap
;
20 /* FUNCTIONS ******************************************************************/
27 CsrProbeForRead(IN PVOID Address
,
31 volatile UCHAR
*Pointer
;
35 if (Length
== 0) return;
37 /* Validate alignment */
38 if ((ULONG_PTR
)Address
& (Alignment
- 1))
40 /* Raise exception if it doesn't match */
41 RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT
);
44 /* Probe first byte */
49 Pointer
= (PUCHAR
)Address
+ Length
- 1;
59 CsrProbeForWrite(IN PVOID Address
,
63 volatile UCHAR
*Pointer
;
66 if (Length
== 0) return;
68 /* Validate alignment */
69 if ((ULONG_PTR
)Address
& (Alignment
- 1))
71 /* Raise exception if it doesn't match */
72 RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT
);
75 /* Probe first byte */
80 Pointer
= (PUCHAR
)Address
+ Length
- 1;
89 CsrAllocateCaptureBuffer(IN ULONG ArgumentCount
,
92 PCSR_CAPTURE_BUFFER CaptureBuffer
;
95 if (BufferSize
>= MAXLONG
) return NULL
;
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
));
101 /* Align it to a 4-byte boundary */
102 BufferSize
= (BufferSize
+ 3) & ~3;
104 /* Allocate memory from the port heap */
105 CaptureBuffer
= RtlAllocateHeap(CsrPortHeap
, HEAP_ZERO_MEMORY
, BufferSize
);
106 if (CaptureBuffer
== NULL
) return NULL
;
108 /* Initialize the header */
109 CaptureBuffer
->Size
= BufferSize
;
110 CaptureBuffer
->PointerCount
= 0;
112 /* Initialize all the offsets */
113 RtlZeroMemory(CaptureBuffer
->PointerOffsetsArray
,
114 ArgumentCount
* sizeof(ULONG_PTR
));
116 /* Point to the start of the free buffer */
117 CaptureBuffer
->BufferEnd
= (PVOID
)((ULONG_PTR
)CaptureBuffer
->PointerOffsetsArray
+
118 ArgumentCount
* sizeof(ULONG_PTR
));
120 /* Return the address of the buffer */
121 return CaptureBuffer
;
129 CsrAllocateMessagePointer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer
,
130 IN ULONG MessageLength
,
131 OUT PVOID
* CapturedData
)
133 if (MessageLength
== 0)
135 *CapturedData
= NULL
;
140 /* Set the capture data at our current available buffer */
141 *CapturedData
= CaptureBuffer
->BufferEnd
;
143 /* Validate the size */
144 if (MessageLength
>= MAXLONG
) return 0;
146 /* Align it to a 4-byte boundary */
147 MessageLength
= (MessageLength
+ 3) & ~3;
149 /* Move our available buffer beyond this space */
150 CaptureBuffer
->BufferEnd
= (PVOID
)((ULONG_PTR
)CaptureBuffer
->BufferEnd
+ MessageLength
);
153 /* Write down this pointer in the array and increase the count */
154 CaptureBuffer
->PointerOffsetsArray
[CaptureBuffer
->PointerCount
++] = (ULONG_PTR
)CapturedData
;
156 /* Return the aligned length */
157 return MessageLength
;
165 CsrCaptureMessageBuffer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer
,
166 IN PVOID MessageBuffer OPTIONAL
,
167 IN ULONG MessageLength
,
168 OUT PVOID
* CapturedData
)
170 /* Simply allocate a message pointer in the buffer */
171 CsrAllocateMessagePointer(CaptureBuffer
, MessageLength
, CapturedData
);
173 /* Check if there was any data */
174 if (!MessageBuffer
|| !MessageLength
) return;
176 /* Copy the data into the buffer */
177 RtlMoveMemory(*CapturedData
, MessageBuffer
, MessageLength
);
185 CsrFreeCaptureBuffer(IN PCSR_CAPTURE_BUFFER CaptureBuffer
)
187 /* Free it from the heap */
188 RtlFreeHeap(CsrPortHeap
, 0, CaptureBuffer
);
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
)
202 ASSERT(CapturedString
!= NULL
);
205 * If we don't have a string, initialize an empty one,
206 * otherwise capture the given string.
210 CapturedString
->Length
= 0;
211 CapturedString
->MaximumLength
= (USHORT
)MaximumLength
;
213 /* Allocate a pointer for it */
214 CsrAllocateMessagePointer(CaptureBuffer
,
216 (PVOID
*)&CapturedString
->Buffer
);
220 /* Cut-off the string length if needed */
221 if (StringLength
> MaximumLength
)
222 StringLength
= MaximumLength
;
224 CapturedString
->Length
= (USHORT
)StringLength
;
226 /* Allocate a buffer and get its size */
227 CapturedString
->MaximumLength
=
228 (USHORT
)CsrAllocateMessagePointer(CaptureBuffer
,
230 (PVOID
*)&CapturedString
->Buffer
);
232 /* If the string has data, copy it into the buffer */
234 RtlMoveMemory(CapturedString
->Buffer
, String
, StringLength
);
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';
243 CsrCaptureMessageUnicodeStringInPlace(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer
,
244 IN PUNICODE_STRING String
)
246 ASSERT(String
!= NULL
);
248 /* This is a way to capture the UNICODE string, since (Maximum)Length are also in bytes */
249 CsrCaptureMessageString(CaptureBuffer
,
250 (PCSTR
)String
->Buffer
,
252 String
->MaximumLength
,
255 /* Null-terminate the string */
256 if (String
->MaximumLength
>= String
->Length
+ sizeof(WCHAR
))
258 String
->Buffer
[String
->Length
/ sizeof(WCHAR
)] = L
'\0';
267 CsrCaptureMessageMultiUnicodeStringsInPlace(OUT PCSR_CAPTURE_BUFFER
* CaptureBuffer
,
268 IN ULONG StringsCount
,
269 IN PUNICODE_STRING
* MessageStrings
)
273 if (!CaptureBuffer
) return STATUS_INVALID_PARAMETER
;
275 /* Allocate a new capture buffer if we don't have one already */
278 /* Compute the required size for the capture buffer */
282 while (Count
< StringsCount
)
284 if (MessageStrings
[Count
])
285 Size
+= MessageStrings
[Count
]->MaximumLength
;
290 /* Allocate the capture buffer */
291 *CaptureBuffer
= CsrAllocateCaptureBuffer(StringsCount
, Size
);
292 if (!*CaptureBuffer
) return STATUS_NO_MEMORY
;
295 /* Now capture each UNICODE string */
297 while (Count
< StringsCount
)
299 if (MessageStrings
[Count
])
300 CsrCaptureMessageUnicodeStringInPlace(*CaptureBuffer
, MessageStrings
[Count
]);
305 return STATUS_SUCCESS
;
313 CsrCaptureTimeout(IN ULONG Milliseconds
,
314 OUT PLARGE_INTEGER Timeout
)
316 /* Validate the time */
317 if (Milliseconds
== -1) return NULL
;
319 /* Convert to relative ticks */
320 Timeout
->QuadPart
= Int32x32To64(Milliseconds
, -10000);