ReactOS  0.4.15-dev-1389-g828d5fa
capture.c
Go to the documentation of this file.
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
29  IN ULONG Length,
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 */
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
61  IN ULONG Length,
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 */
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  */
89 NTAPI
92 {
93  PCSR_CAPTURE_BUFFER CaptureBuffer;
94  ULONG OffsetsArraySize;
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;
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 */
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
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
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
211 {
212  /* Free it from the heap */
213  RtlFreeHeap(CsrPortHeap, 0, CaptureBuffer);
214 }
215 
216 /*
217  * @implemented
218  */
219 VOID
220 NTAPI
223  IN ULONG StringLength,
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,
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,
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
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
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  */
337 NTAPI
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 */
VOID NTAPI CsrFreeCaptureBuffer(IN PCSR_CAPTURE_BUFFER CaptureBuffer)
Definition: capture.c:210
#define IN
Definition: typedefs.h:39
DECLSPEC_NORETURN NTSYSAPI VOID NTAPI RtlRaiseStatus(_In_ NTSTATUS Status)
#define LL
Definition: tui.h:84
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define MAXLONG
Definition: umtypes.h:116
ULONG NTAPI CsrAllocateMessagePointer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, IN ULONG MessageLength, OUT PVOID *CapturedData)
Definition: capture.c:154
PCSR_CAPTURE_BUFFER NTAPI CsrAllocateCaptureBuffer(IN ULONG ArgumentCount, IN ULONG BufferSize)
Definition: capture.c:90
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
unsigned char * PUCHAR
Definition: retypes.h:3
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG _In_opt_ PVOID Data
Definition: wdfdevice.h:4527
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
HANDLE CsrPortHeap
Definition: connect.c:23
PLARGE_INTEGER NTAPI CsrCaptureTimeout(IN ULONG Milliseconds, OUT PLARGE_INTEGER Timeout)
Definition: capture.c:338
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
uint32_t ULONG_PTR
Definition: typedefs.h:65
VOID NTAPI CsrCaptureMessageBuffer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, IN PVOID MessageBuffer OPTIONAL, IN ULONG MessageLength, OUT PVOID *CapturedData)
Definition: capture.c:190
VOID NTAPI CsrProbeForWrite(IN PVOID Address, IN ULONG Length, IN ULONG Alignment)
Definition: capture.c:60
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2430
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
static WCHAR Address[46]
Definition: ping.c:68
void * PVOID
Definition: retypes.h:9
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
int Count
Definition: noreturn.cpp:7
_In_ WDFDMATRANSACTION _In_ size_t MaximumLength
#define ASSERT(a)
Definition: mode.c:45
__wchar_t WCHAR
Definition: xmlstorage.h:180
VOID NTAPI CsrCaptureMessageString(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, IN PCSTR String OPTIONAL, IN ULONG StringLength, IN ULONG MaximumLength, OUT PSTRING CapturedString)
Definition: capture.c:221
unsigned char UCHAR
Definition: xmlstorage.h:181
static const WCHAR L[]
Definition: oid.c:1250
ULONG PointerCount
Definition: csrmsg.h:96
static ULONG Timeout
Definition: ping.c:61
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
static VOID CsrCaptureMessageUnicodeStringInPlace(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, IN PUNICODE_STRING String)
Definition: capture.c:268
#define NULL
Definition: types.h:112
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER MaximumSize
Definition: mmfuncs.h:360
#define OUT
Definition: typedefs.h:40
#define STATUS_DATATYPE_MISALIGNMENT
Definition: ntstatus.h:183
NTSTATUS NTAPI CsrCaptureMessageMultiUnicodeStringsInPlace(OUT PCSR_CAPTURE_BUFFER *CaptureBuffer, IN ULONG StringsCount, IN PUNICODE_STRING *MessageStrings)
Definition: capture.c:292
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
VOID NTAPI CsrProbeForRead(IN PVOID Address, IN ULONG Length, IN ULONG Alignment)
Definition: capture.c:28
const char * PCSTR
Definition: typedefs.h:52
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG_PTR PointerOffsetsArray[ANYSIZE_ARRAY]
Definition: csrmsg.h:98
#define BufferSize
Definition: mmc.h:75
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:251
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68