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
;
96 if (BufferSize
>= MAXLONG
) return NULL
;
98 /* Add the size of the header and for each offset to the pointers */
99 BufferSize
+= FIELD_OFFSET(CSR_CAPTURE_BUFFER
, PointerOffsetsArray
) +
100 (ArgumentCount
* sizeof(ULONG_PTR
));
102 /* Align it to a 4-byte boundary */
103 BufferSize
= (BufferSize
+ 3) & ~3;
105 /* Add the size of the alignment padding for each argument */
106 BufferSize
+= ArgumentCount
* 3;
108 /* Allocate memory from the port heap */
109 CaptureBuffer
= RtlAllocateHeap(CsrPortHeap
, HEAP_ZERO_MEMORY
, BufferSize
);
110 if (CaptureBuffer
== NULL
) return NULL
;
112 /* Initialize the header */
113 CaptureBuffer
->Size
= BufferSize
;
114 CaptureBuffer
->PointerCount
= 0;
116 /* Initialize all the offsets */
117 RtlZeroMemory(CaptureBuffer
->PointerOffsetsArray
,
118 ArgumentCount
* sizeof(ULONG_PTR
));
120 /* Point to the start of the free buffer */
121 CaptureBuffer
->BufferEnd
= (PVOID
)((ULONG_PTR
)CaptureBuffer
->PointerOffsetsArray
+
122 ArgumentCount
* sizeof(ULONG_PTR
));
124 /* Return the address of the buffer */
125 return CaptureBuffer
;
133 CsrAllocateMessagePointer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer
,
134 IN ULONG MessageLength
,
135 OUT PVOID
* CapturedData
)
137 if (MessageLength
== 0)
139 *CapturedData
= NULL
;
144 /* Set the capture data at our current available buffer */
145 *CapturedData
= CaptureBuffer
->BufferEnd
;
147 /* Validate the size */
148 if (MessageLength
>= MAXLONG
) return 0;
150 /* Align it to a 4-byte boundary */
151 MessageLength
= (MessageLength
+ 3) & ~3;
153 /* Move our available buffer beyond this space */
154 CaptureBuffer
->BufferEnd
= (PVOID
)((ULONG_PTR
)CaptureBuffer
->BufferEnd
+ MessageLength
);
157 /* Write down this pointer in the array and increase the count */
158 CaptureBuffer
->PointerOffsetsArray
[CaptureBuffer
->PointerCount
++] = (ULONG_PTR
)CapturedData
;
160 /* Return the aligned length */
161 return MessageLength
;
169 CsrCaptureMessageBuffer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer
,
170 IN PVOID MessageBuffer OPTIONAL
,
171 IN ULONG MessageLength
,
172 OUT PVOID
* CapturedData
)
174 /* Simply allocate a message pointer in the buffer */
175 CsrAllocateMessagePointer(CaptureBuffer
, MessageLength
, CapturedData
);
177 /* Check if there was any data */
178 if (!MessageBuffer
|| !MessageLength
) return;
180 /* Copy the data into the buffer */
181 RtlMoveMemory(*CapturedData
, MessageBuffer
, MessageLength
);
189 CsrFreeCaptureBuffer(IN PCSR_CAPTURE_BUFFER CaptureBuffer
)
191 /* Free it from the heap */
192 RtlFreeHeap(CsrPortHeap
, 0, CaptureBuffer
);
200 CsrCaptureMessageString(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer
,
201 IN PCSTR String OPTIONAL
,
202 IN ULONG StringLength
,
203 IN ULONG MaximumLength
,
204 OUT PSTRING CapturedString
)
206 ASSERT(CapturedString
!= NULL
);
209 * If we don't have a string, initialize an empty one,
210 * otherwise capture the given string.
214 CapturedString
->Length
= 0;
215 CapturedString
->MaximumLength
= (USHORT
)MaximumLength
;
217 /* Allocate a pointer for it */
218 CsrAllocateMessagePointer(CaptureBuffer
,
220 (PVOID
*)&CapturedString
->Buffer
);
224 /* Cut-off the string length if needed */
225 if (StringLength
> MaximumLength
)
226 StringLength
= MaximumLength
;
228 CapturedString
->Length
= (USHORT
)StringLength
;
230 /* Allocate a buffer and get its size */
231 CapturedString
->MaximumLength
=
232 (USHORT
)CsrAllocateMessagePointer(CaptureBuffer
,
234 (PVOID
*)&CapturedString
->Buffer
);
236 /* If the string has data, copy it into the buffer */
238 RtlMoveMemory(CapturedString
->Buffer
, String
, StringLength
);
241 /* Null-terminate the string if we don't take up the whole space */
242 if (CapturedString
->Length
< CapturedString
->MaximumLength
)
243 CapturedString
->Buffer
[CapturedString
->Length
] = '\0';
247 CsrCaptureMessageUnicodeStringInPlace(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer
,
248 IN PUNICODE_STRING String
)
250 ASSERT(String
!= NULL
);
252 /* This is a way to capture the UNICODE string, since (Maximum)Length are also in bytes */
253 CsrCaptureMessageString(CaptureBuffer
,
254 (PCSTR
)String
->Buffer
,
256 String
->MaximumLength
,
259 /* Null-terminate the string */
260 if (String
->MaximumLength
>= String
->Length
+ sizeof(WCHAR
))
262 String
->Buffer
[String
->Length
/ sizeof(WCHAR
)] = L
'\0';
271 CsrCaptureMessageMultiUnicodeStringsInPlace(OUT PCSR_CAPTURE_BUFFER
* CaptureBuffer
,
272 IN ULONG StringsCount
,
273 IN PUNICODE_STRING
* MessageStrings
)
277 if (!CaptureBuffer
) return STATUS_INVALID_PARAMETER
;
279 /* Allocate a new capture buffer if we don't have one already */
282 /* Compute the required size for the capture buffer */
286 while (Count
< StringsCount
)
288 if (MessageStrings
[Count
])
289 Size
+= MessageStrings
[Count
]->MaximumLength
;
294 /* Allocate the capture buffer */
295 *CaptureBuffer
= CsrAllocateCaptureBuffer(StringsCount
, Size
);
296 if (!*CaptureBuffer
) return STATUS_NO_MEMORY
;
299 /* Now capture each UNICODE string */
301 while (Count
< StringsCount
)
303 if (MessageStrings
[Count
])
304 CsrCaptureMessageUnicodeStringInPlace(*CaptureBuffer
, MessageStrings
[Count
]);
309 return STATUS_SUCCESS
;
317 CsrCaptureTimeout(IN ULONG Milliseconds
,
318 OUT PLARGE_INTEGER Timeout
)
320 /* Validate the time */
321 if (Milliseconds
== -1) return NULL
;
323 /* Convert to relative ticks */
324 Timeout
->QuadPart
= Milliseconds
* -10000LL;