[BASESRV-CONSRV-WINSRV]
[reactos.git] / dll / ntdll / csr / capture.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: lib/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 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS ********************************************************************/
16
17 extern HANDLE CsrPortHeap;
18
19 /* FUNCTIONS ******************************************************************/
20
21 /*
22 * @implemented
23 */
24 VOID
25 NTAPI
26 CsrProbeForRead(IN PVOID Address,
27 IN ULONG Length,
28 IN ULONG Alignment)
29 {
30 volatile UCHAR *Pointer;
31 UCHAR Data;
32
33 /* Validate length */
34 if (Length == 0) return;
35
36 /* Validate alignment */
37 if ((ULONG_PTR)Address & (Alignment - 1))
38 {
39 /* Raise exception if it doesn't match */
40 RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
41 }
42
43 /* Probe first byte */
44 Pointer = Address;
45 Data = *Pointer;
46
47 /* Probe last byte */
48 Pointer = (PUCHAR)Address + Length - 1;
49 Data = *Pointer;
50 (void)Data;
51 }
52
53 /*
54 * @implemented
55 */
56 VOID
57 NTAPI
58 CsrProbeForWrite(IN PVOID Address,
59 IN ULONG Length,
60 IN ULONG Alignment)
61 {
62 volatile UCHAR *Pointer;
63
64 /* Validate length */
65 if (Length == 0) return;
66
67 /* Validate alignment */
68 if ((ULONG_PTR)Address & (Alignment - 1))
69 {
70 /* Raise exception if it doesn't match */
71 RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
72 }
73
74 /* Probe first byte */
75 Pointer = Address;
76 *Pointer = *Pointer;
77
78 /* Probe last byte */
79 Pointer = (PUCHAR)Address + Length - 1;
80 *Pointer = *Pointer;
81 }
82
83 /*
84 * @implemented
85 */
86 PCSR_CAPTURE_BUFFER
87 NTAPI
88 CsrAllocateCaptureBuffer(IN ULONG ArgumentCount,
89 IN ULONG BufferSize)
90 {
91 PCSR_CAPTURE_BUFFER CaptureBuffer;
92
93 /* Validate size */
94 if (BufferSize >= MAXLONG) return NULL;
95
96 /* Add the size of the header and for each offset to the pointers */
97 BufferSize += FIELD_OFFSET(CSR_CAPTURE_BUFFER, PointerOffsetsArray) + (ArgumentCount * sizeof(ULONG_PTR));
98
99 /* Align it to a 4-byte boundary */
100 BufferSize = (BufferSize + 3) & ~3;
101
102 /* Allocate memory from the port heap */
103 CaptureBuffer = RtlAllocateHeap(CsrPortHeap, HEAP_ZERO_MEMORY, BufferSize);
104 if (CaptureBuffer == NULL) return NULL;
105
106 /* Initialize the header */
107 CaptureBuffer->Size = BufferSize;
108 CaptureBuffer->PointerCount = 0;
109
110 /* Initialize all the offsets */
111 RtlZeroMemory(CaptureBuffer->PointerOffsetsArray,
112 ArgumentCount * sizeof(ULONG_PTR));
113
114 /* Point to the start of the free buffer */
115 CaptureBuffer->BufferEnd = (PVOID)((ULONG_PTR)CaptureBuffer->PointerOffsetsArray +
116 ArgumentCount * sizeof(ULONG_PTR));
117
118 /* Return the address of the buffer */
119 return CaptureBuffer;
120 }
121
122 /*
123 * @implemented
124 */
125 ULONG
126 NTAPI
127 CsrAllocateMessagePointer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer,
128 IN ULONG MessageLength,
129 OUT PVOID *CapturedData)
130 {
131 if (MessageLength == 0)
132 {
133 *CapturedData = NULL;
134 CapturedData = NULL;
135 }
136 else
137 {
138 /* Set the capture data at our current available buffer */
139 *CapturedData = CaptureBuffer->BufferEnd;
140
141 /* Validate the size */
142 if (MessageLength >= MAXLONG) return 0;
143
144 /* Align it to a 4-byte boundary */
145 MessageLength = (MessageLength + 3) & ~3;
146
147 /* Move our available buffer beyond this space */
148 CaptureBuffer->BufferEnd = (PVOID)((ULONG_PTR)CaptureBuffer->BufferEnd + MessageLength);
149 }
150
151 /* Write down this pointer in the array and increase the count */
152 CaptureBuffer->PointerOffsetsArray[CaptureBuffer->PointerCount++] = (ULONG_PTR)CapturedData;
153
154 /* Return the aligned length */
155 return MessageLength;
156 }
157
158 /*
159 * @implemented
160 */
161 VOID
162 NTAPI
163 CsrCaptureMessageBuffer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer,
164 IN PVOID MessageBuffer OPTIONAL,
165 IN ULONG MessageLength,
166 OUT PVOID *CapturedData)
167 {
168 /* Simply allocate a message pointer in the buffer */
169 CsrAllocateMessagePointer(CaptureBuffer, MessageLength, CapturedData);
170
171 /* Check if there was any data */
172 if (!MessageBuffer || !MessageLength) return;
173
174 /* Copy the data into the buffer */
175 RtlMoveMemory(*CapturedData, MessageBuffer, MessageLength);
176 }
177
178 /*
179 * @implemented
180 */
181 VOID
182 NTAPI
183 CsrFreeCaptureBuffer(IN PCSR_CAPTURE_BUFFER CaptureBuffer)
184 {
185 /* Free it from the heap */
186 RtlFreeHeap(CsrPortHeap, 0, CaptureBuffer);
187 }
188
189 /*
190 * @unimplemented
191 */
192 NTSTATUS
193 NTAPI
194 CsrCaptureMessageMultiUnicodeStringsInPlace(IN PCSR_CAPTURE_BUFFER *CaptureBuffer,
195 IN ULONG MessageCount,
196 IN PVOID MessageStrings)
197 {
198 /* FIXME: allocate a buffer if we don't have one, and return it */
199 /* FIXME: call CsrCaptureMessageUnicodeStringInPlace for each string */
200 UNIMPLEMENTED;
201 return STATUS_NOT_IMPLEMENTED;
202 }
203
204 /*
205 * @implemented
206 */
207 VOID
208 NTAPI
209 CsrCaptureMessageString(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer,
210 IN LPSTR String OPTIONAL,
211 IN ULONG StringLength,
212 IN ULONG MaximumLength,
213 OUT PANSI_STRING CapturedString)
214 {
215 ULONG ReturnedLength;
216
217 /* If we don't have a string, initialize an empty one */
218 if (!String)
219 {
220 CapturedString->Length = 0;
221 CapturedString->MaximumLength = (USHORT)MaximumLength;
222
223 /* Allocate a pointer for it */
224 CsrAllocateMessagePointer(CaptureBuffer,
225 MaximumLength,
226 (PVOID*)&CapturedString->Buffer);
227 return;
228 }
229
230 /* Initialize this string */
231 CapturedString->Length = (USHORT)StringLength;
232
233 /* Allocate a buffer and get its size */
234 ReturnedLength = CsrAllocateMessagePointer(CaptureBuffer,
235 MaximumLength,
236 (PVOID*)&CapturedString->Buffer);
237 CapturedString->MaximumLength = (USHORT)ReturnedLength;
238
239 /* If the string had data */
240 if (StringLength)
241 {
242 /* Copy it into the capture buffer */
243 RtlMoveMemory(CapturedString->Buffer, String, MaximumLength);
244
245 /* If we don't take up the whole space */
246 if (CapturedString->Length < CapturedString->MaximumLength)
247 {
248 /* Null-terminate it */
249 CapturedString->Buffer[CapturedString->Length] = '\0';
250 }
251 }
252 }
253
254 /*
255 * @implemented
256 */
257 PLARGE_INTEGER
258 NTAPI
259 CsrCaptureTimeout(IN ULONG Milliseconds,
260 OUT PLARGE_INTEGER Timeout)
261 {
262 /* Validate the time */
263 if (Milliseconds == -1) return NULL;
264
265 /* Convert to relative ticks */
266 Timeout->QuadPart = Int32x32To64(Milliseconds, -10000);
267 return Timeout;
268 }
269
270 /* EOF */