[SHELL32] SHChangeNotify: Add drive, remove drive (#6782)
[reactos.git] / drivers / sac / driver / channel.c
1 /*
2 * PROJECT: ReactOS Drivers
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/sac/driver/channel.c
5 * PURPOSE: Driver for the Server Administration Console (SAC) for EMS
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "sacdrv.h"
12
13 /* FUNCTIONS ******************************************************************/
14
15 BOOLEAN
16 NTAPI
17 ChannelIsValidType(IN SAC_CHANNEL_TYPE ChannelType)
18 {
19 /* Check if the type is valid */
20 return ((ChannelType >= VtUtf8) && (ChannelType <= Raw));
21 }
22
23 BOOLEAN
24 NTAPI
25 ChannelIsEqual(IN PSAC_CHANNEL Channel,
26 IN PSAC_CHANNEL_ID ChannelId)
27 {
28 /* Check if the GUIDs match */
29 return IsEqualGUIDAligned(&Channel->ChannelId.ChannelGuid,
30 &ChannelId->ChannelGuid);
31 }
32
33 NTSTATUS
34 NTAPI
35 ChannelDereferenceHandles(IN PSAC_CHANNEL Channel)
36 {
37 CHECK_PARAMETER(Channel);
38
39 /* Clear the data event */
40 if (Channel->HasNewDataEvent)
41 {
42 ChannelUninitializeEvent(Channel,
43 HasNewDataEvent,
44 SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT);
45 }
46
47 /* Clear the close event */
48 if (Channel->CloseEvent)
49 {
50 ChannelUninitializeEvent(Channel,
51 CloseEvent,
52 SAC_CHANNEL_FLAG_CLOSE_EVENT);
53 }
54
55 /* Clear the lock event */
56 if (Channel->LockEvent)
57 {
58 ChannelUninitializeEvent(Channel,
59 LockEvent,
60 SAC_CHANNEL_FLAG_LOCK_EVENT);
61 }
62
63 /* Clear the redraw event */
64 if (Channel->RedrawEvent)
65 {
66 ChannelUninitializeEvent(Channel,
67 RedrawEvent,
68 SAC_CHANNEL_FLAG_REDRAW_EVENT);
69 }
70
71 /* All done */
72 return STATUS_SUCCESS;
73 }
74
75 NTSTATUS
76 NTAPI
77 ChannelDestroy(IN PSAC_CHANNEL Channel)
78 {
79 CHECK_PARAMETER(Channel);
80
81 /* Same thing as dereferencing all the handles */
82 return ChannelDereferenceHandles(Channel);
83 }
84
85 NTSTATUS
86 NTAPI
87 ChannelOWrite(IN PSAC_CHANNEL Channel,
88 IN PCHAR Buffer,
89 IN ULONG BufferSize)
90 {
91 NTSTATUS Status;
92 CHECK_PARAMETER3(BufferSize < SAC_OBUFFER_SIZE);
93
94 /* While holding the output lock, write to the output buffer */
95 ChannelLockOBuffer(Channel);
96 Status = Channel->ChannelOutputWrite(Channel, Buffer, BufferSize);
97 ChannelUnlockOBuffer(Channel);
98 return Status;
99 }
100
101 NTSTATUS
102 NTAPI
103 ChannelOFlush(IN PSAC_CHANNEL Channel)
104 {
105 NTSTATUS Status;
106
107 /* While holding the output lock, flush to the output buffer */
108 ChannelLockOBuffer(Channel);
109 Status = Channel->ChannelOutputFlush(Channel);
110 ChannelUnlockOBuffer(Channel);
111 return Status;
112 }
113
114 NTSTATUS
115 NTAPI
116 ChannelIWrite(IN PSAC_CHANNEL Channel,
117 IN PCHAR Buffer,
118 IN ULONG BufferSize)
119 {
120 NTSTATUS Status;
121
122 /* Write into the input buffer while holding the lock */
123 ChannelLockIBuffer(Channel);
124 Status = Channel->ChannelInputWrite(Channel, Buffer, BufferSize);
125 ChannelUnlockIBuffer(Channel);
126 return Status;
127 }
128
129 NTSTATUS
130 NTAPI
131 ChannelIRead(IN PSAC_CHANNEL Channel,
132 IN PCHAR Buffer,
133 IN ULONG BufferSize,
134 IN OUT PULONG ResultBufferSize)
135 {
136 NTSTATUS Status;
137
138 /* Read the input buffer while holding the lock */
139 ChannelLockIBuffer(Channel);
140 Status = Channel->ChannelInputRead(Channel,
141 Buffer,
142 BufferSize,
143 ResultBufferSize);
144 ChannelUnlockIBuffer(Channel);
145 return Status;
146 }
147
148 WCHAR
149 NTAPI
150 ChannelIReadLast(IN PSAC_CHANNEL Channel)
151 {
152 WCHAR LastChar;
153
154 /* Read the last character while holding the lock */
155 ChannelLockIBuffer(Channel);
156 LastChar = Channel->ChannelInputReadLast(Channel);
157 ChannelUnlockIBuffer(Channel);
158 return LastChar;
159 }
160
161 ULONG
162 NTAPI
163 ChannelIBufferLength(IN PSAC_CHANNEL Channel)
164 {
165 ULONG Length;
166
167 /* Get the input buffer length while holding the lock */
168 ChannelLockOBuffer(Channel);
169 Length = Channel->ChannelInputBufferLength(Channel);
170 ChannelUnlockOBuffer(Channel);
171 return Length;
172 }
173
174 NTSTATUS
175 NTAPI
176 ChannelSetRedrawEvent(IN PSAC_CHANNEL Channel)
177 {
178 NTSTATUS Status;
179
180 /* Set the event */
181 ChannelSetEvent(Channel, RedrawEvent);
182 return Status;
183 }
184
185 NTSTATUS
186 NTAPI
187 ChannelSetLockEvent(IN PSAC_CHANNEL Channel)
188 {
189 NTSTATUS Status;
190
191 /* Set the event */
192 ChannelSetEvent(Channel, LockEvent);
193 return Status;
194 }
195
196 NTSTATUS
197 NTAPI
198 ChannelClearRedrawEvent(IN PSAC_CHANNEL Channel)
199 {
200 NTSTATUS Status;
201
202 /* Clear the event */
203 ChannelClearEvent(Channel, RedrawEvent);
204 return Status;
205 }
206
207 NTSTATUS
208 NTAPI
209 ChannelHasRedrawEvent(IN PSAC_CHANNEL Channel,
210 OUT PBOOLEAN Present)
211 {
212 CHECK_PARAMETER1(Channel);
213 CHECK_PARAMETER2(Present);
214
215 /* Return if the flag is set */
216 *Present = Channel->Flags & SAC_CHANNEL_FLAG_REDRAW_EVENT;
217 return STATUS_SUCCESS;
218 }
219
220 NTSTATUS
221 NTAPI
222 ChannelGetStatus(IN PSAC_CHANNEL Channel,
223 OUT PSAC_CHANNEL_STATUS ChannelStatus)
224 {
225 CHECK_PARAMETER1(Channel);
226
227 /* Read the status while holding the attribute lock */
228 ChannelLockAttributes(Channel);
229 *ChannelStatus = Channel->ChannelStatus;
230 ChannelUnlockAttributes(Channel);
231 return STATUS_SUCCESS;
232 }
233
234 NTSTATUS
235 NTAPI
236 ChannelSetStatus(IN PSAC_CHANNEL Channel,
237 IN SAC_CHANNEL_STATUS ChannelStatus)
238 {
239 CHECK_PARAMETER1(Channel);
240
241 /* Read the status while holding the attribute lock */
242 ChannelLockAttributes(Channel);
243 Channel->ChannelStatus = ChannelStatus;
244 ChannelUnlockAttributes(Channel);
245 return STATUS_SUCCESS;
246 }
247
248 BOOLEAN
249 NTAPI
250 ChannelIsActive(IN PSAC_CHANNEL Channel)
251 {
252 SAC_CHANNEL_STATUS ChannelStatus;
253 BOOLEAN IsActive;
254
255 /* Get the status */
256 if (!NT_SUCCESS(ChannelGetStatus(Channel, &ChannelStatus)))
257 {
258 /* We couldn't even do that, assume it's inactive */
259 IsActive = FALSE;
260 }
261 else
262 {
263 /* Check if the status shows activity */
264 IsActive = (ChannelStatus == Active);
265 }
266
267 /* Return the state */
268 return IsActive;
269 }
270
271 BOOLEAN
272 NTAPI
273 ChannelIsClosed(IN PSAC_CHANNEL Channel)
274 {
275 SAC_CHANNEL_STATUS ChannelStatus;
276 BOOLEAN IsClosed;
277
278 /* Get the status */
279 if (!NT_SUCCESS(ChannelGetStatus(Channel, &ChannelStatus)))
280 {
281 /* We couldn't even do that, assume it's inactive */
282 IsClosed = FALSE;
283 }
284 else
285 {
286 /* Check if the status shows activity */
287 IsClosed = ((ChannelStatus == Inactive) &&
288 (Channel->ChannelHasNewOBufferData));
289 }
290
291 /* Return the state */
292 return IsClosed;
293 }
294
295 NTSTATUS
296 NTAPI
297 ChannelGetName(IN PSAC_CHANNEL Channel,
298 OUT PWCHAR *Name)
299 {
300 CHECK_PARAMETER1(Channel);
301 CHECK_PARAMETER2(Name);
302
303 /* Allocate space to hold the name */
304 *Name = SacAllocatePool(sizeof(Channel->NameBuffer), GLOBAL_BLOCK_TAG);
305 CHECK_ALLOCATION(*Name);
306
307 /* Lock the attributes while we copy the name */
308 ChannelLockAttributes(Channel);
309
310 /* Copy the name and null-terminate it */
311 ASSERT(((wcslen(Channel->NameBuffer) + 1) * sizeof(WCHAR)) <= ((SAC_CHANNEL_NAME_SIZE + 1) * sizeof(WCHAR)));
312 wcsncpy(*Name, Channel->NameBuffer, RTL_NUMBER_OF(Channel->NameBuffer)); // bug
313 (*Name)[SAC_CHANNEL_NAME_SIZE] = UNICODE_NULL;
314
315 /* Release the lock and return */
316 ChannelUnlockAttributes(Channel);
317 return STATUS_SUCCESS;
318 }
319
320 NTSTATUS
321 NTAPI
322 ChannelSetName(IN PSAC_CHANNEL Channel,
323 IN PWCHAR Name)
324 {
325 CHECK_PARAMETER1(Channel);
326 CHECK_PARAMETER2(Name);
327
328 /* Lock the attributes while we copy the name */
329 ChannelLockAttributes(Channel);
330
331 /* Copy the name and null-terminate it */
332 ASSERT(((wcslen(Name) + 1) * sizeof(WCHAR)) <= ((SAC_CHANNEL_NAME_SIZE + 1) * sizeof(WCHAR)));
333 wcsncpy(Channel->NameBuffer, Name, RTL_NUMBER_OF(Channel->NameBuffer)); // bug
334 Channel->NameBuffer[SAC_CHANNEL_NAME_SIZE] = UNICODE_NULL;
335
336 /* Release the lock and return */
337 ChannelUnlockAttributes(Channel);
338 return STATUS_SUCCESS;
339 }
340
341 NTSTATUS
342 NTAPI
343 ChannelGetDescription(IN PSAC_CHANNEL Channel,
344 IN PWCHAR* Description)
345 {
346 CHECK_PARAMETER1(Channel);
347 CHECK_PARAMETER2(Description);
348
349 /* Allocate space to hold the description */
350 *Description = SacAllocatePool(sizeof(Channel->DescriptionBuffer), GLOBAL_BLOCK_TAG);
351 CHECK_ALLOCATION(*Description);
352
353 /* Lock the attributes while we copy the name */
354 ChannelLockAttributes(Channel);
355
356 /* Copy the name and null-terminate it */
357 ASSERT(((wcslen(Channel->DescriptionBuffer) + 1) * sizeof(WCHAR)) <= ((SAC_CHANNEL_DESCRIPTION_SIZE + 1) * sizeof(WCHAR)));
358 wcsncpy(*Description, Channel->DescriptionBuffer, RTL_NUMBER_OF(Channel->DescriptionBuffer)); // bug
359 (*Description)[SAC_CHANNEL_DESCRIPTION_SIZE] = UNICODE_NULL;
360
361 /* Release the lock and return */
362 ChannelUnlockAttributes(Channel);
363 return STATUS_SUCCESS;
364 }
365
366 NTSTATUS
367 NTAPI
368 ChannelSetDescription(IN PSAC_CHANNEL Channel,
369 IN PWCHAR Description)
370 {
371 CHECK_PARAMETER1(Channel);
372 CHECK_PARAMETER2(Description);
373
374 /* Lock the attributes while we copy the name */
375 ChannelLockAttributes(Channel);
376
377 /* Copy the name and null-terminate it */
378 ASSERT(((wcslen(Description) + 1) * sizeof(WCHAR)) <= ((SAC_CHANNEL_NAME_SIZE + 1) * sizeof(WCHAR)));
379 wcsncpy(Channel->DescriptionBuffer, Description, RTL_NUMBER_OF(Channel->DescriptionBuffer)); // bug
380 Channel->DescriptionBuffer[SAC_CHANNEL_DESCRIPTION_SIZE] = UNICODE_NULL;
381
382 /* Release the lock and return */
383 ChannelUnlockAttributes(Channel);
384 return STATUS_SUCCESS;
385 }
386
387 NTSTATUS
388 NTAPI
389 ChannelGetApplicationType(IN PSAC_CHANNEL Channel,
390 OUT PGUID ApplicationType)
391 {
392 CHECK_PARAMETER1(Channel);
393
394 /* Read the application type GUID */
395 ChannelLockAttributes(Channel);
396 *ApplicationType = Channel->ApplicationType;
397 ChannelUnlockAttributes(Channel);
398
399 /* Always return success */
400 return STATUS_SUCCESS;
401 }
402
403 NTSTATUS
404 NTAPI
405 ChannelInitializeVTable(IN PSAC_CHANNEL Channel)
406 {
407 /* What kind of channel is this? */
408 switch (Channel->ChannelType)
409 {
410 case VtUtf8:
411 /* Setup the calls for a VT-UTF8 channel */
412 Channel->ChannelCreate = VTUTF8ChannelCreate;
413 Channel->ChannelDestroy = VTUTF8ChannelDestroy;
414 Channel->ChannelOutputFlush = VTUTF8ChannelOFlush;
415 Channel->ChannelOutputEcho = VTUTF8ChannelOEcho;
416 Channel->ChannelOutputWrite = VTUTF8ChannelOWrite;
417 Channel->ChannelOutputRead = VTUTF8ChannelORead;
418 Channel->ChannelInputWrite = VTUTF8ChannelIWrite;
419 Channel->ChannelInputRead = VTUTF8ChannelIRead;
420 Channel->ChannelInputReadLast = VTUTF8ChannelIReadLast;
421 Channel->ChannelInputBufferIsFull = VTUTF8ChannelIBufferIsFull;
422 Channel->ChannelInputBufferLength = VTUTF8ChannelIBufferLength;
423 break;
424
425 case Cmd:
426 /* FIXME: TODO */
427 ASSERT(FALSE);
428 return STATUS_NOT_IMPLEMENTED;
429
430 case Raw:
431
432 /* Setup the calls for a raw channel */
433 Channel->ChannelCreate = RawChannelCreate;
434 Channel->ChannelDestroy = RawChannelDestroy;
435 Channel->ChannelOutputFlush = RawChannelOFlush;
436 Channel->ChannelOutputEcho = RawChannelOEcho;
437 Channel->ChannelOutputWrite = RawChannelOWrite;
438 Channel->ChannelOutputRead = RawChannelORead;
439 Channel->ChannelInputWrite = RawChannelIWrite;
440 Channel->ChannelInputRead = RawChannelIRead;
441 Channel->ChannelInputReadLast = RawChannelIReadLast;
442 Channel->ChannelInputBufferIsFull = RawChannelIBufferIsFull;
443 Channel->ChannelInputBufferLength = RawChannelIBufferLength;
444 break;
445
446 default:
447 /* Unsupported channel type */
448 return STATUS_INVALID_PARAMETER;
449 }
450
451 /* If we got here, the channel was supported */
452 return STATUS_SUCCESS;
453 }
454
455 NTSTATUS
456 NTAPI
457 ChannelCreate(IN PSAC_CHANNEL Channel,
458 IN PSAC_CHANNEL_ATTRIBUTES Attributes,
459 IN SAC_CHANNEL_ID ChannelId)
460 {
461 NTSTATUS Status;
462 CHECK_PARAMETER1(Channel);
463 CHECK_PARAMETER2(Attributes);
464
465 /* If a close event is being passed in, it must exist, and vice-versa */
466 if (Attributes->Flag & SAC_CHANNEL_FLAG_CLOSE_EVENT)
467 {
468 CHECK_PARAMETER(Attributes->CloseEvent != NULL);
469 }
470 else
471 {
472 CHECK_PARAMETER(Attributes->CloseEvent == NULL);
473 }
474
475 /* If a new data event is being passed in, it must exist, and vice-versa */
476 if (Attributes->Flag & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT)
477 {
478 CHECK_PARAMETER(Attributes->HasNewDataEvent != NULL);
479 }
480 else
481 {
482 CHECK_PARAMETER(Attributes->HasNewDataEvent == NULL);
483 }
484
485 /* If a lock event is being passed in, it must exist, and vice-versa */
486 if (Attributes->Flag & SAC_CHANNEL_FLAG_LOCK_EVENT)
487 {
488 CHECK_PARAMETER(Attributes->LockEvent != NULL);
489 }
490 else
491 {
492 CHECK_PARAMETER(Attributes->LockEvent == NULL);
493 }
494
495 /* If a redraw event is being passed in, it must exist, and vice-versa */
496 if (Attributes->Flag & SAC_CHANNEL_FLAG_REDRAW_EVENT)
497 {
498 CHECK_PARAMETER(Attributes->RedrawEvent != NULL);
499 }
500 else
501 {
502 CHECK_PARAMETER(Attributes->RedrawEvent == NULL);
503 }
504
505 /* Initialize the channel structure */
506 RtlZeroMemory(Channel, sizeof(SAC_CHANNEL));
507 Channel->ChannelId = ChannelId;
508 Channel->ChannelType = Attributes->ChannelType;
509 Channel->Flags = Attributes->Flag;
510 if (Attributes->Flag & SAC_CHANNEL_FLAG_APPLICATION)
511 {
512 Channel->ApplicationType = Attributes->ChannelId;
513 }
514
515 /* Initialize all the locks and events */
516 SacInitializeLock(&Channel->ChannelAttributeLock);
517 SacInitializeLock(&Channel->ChannelOBufferLock);
518 SacInitializeLock(&Channel->ChannelIBufferLock);
519 ChannelInitializeEvent(Channel, Attributes, CloseEvent);
520 ChannelInitializeEvent(Channel, Attributes, HasNewDataEvent);
521 ChannelInitializeEvent(Channel, Attributes, LockEvent);
522 ChannelInitializeEvent(Channel, Attributes, RedrawEvent);
523
524 /* Set the name and description */
525 ChannelSetName(Channel, Attributes->NameBuffer);
526 ChannelSetDescription(Channel, Attributes->DescriptionBuffer);
527
528 /* Initialize the function table for the type of channel this is */
529 Status = ChannelInitializeVTable(Channel);
530 if (!NT_SUCCESS(Status))
531 {
532 /* This is critical */
533 SAC_DBG(SAC_DBG_INIT, "SAC Create Channel :: Failed to initialize vtable\n");
534 goto FailChannel;
535 }
536
537 /* Now call the channel specific type constructor */
538 Status = Channel->ChannelCreate(Channel);
539 if (!NT_SUCCESS(Status))
540 {
541 /* This is critical */
542 SAC_DBG(SAC_DBG_INIT, "SAC Create Channel :: Failed channel specific initialization\n");
543 goto FailChannel;
544 }
545
546 /* Finally, mark the channel as active */
547 ChannelSetStatus(Channel, Active);
548 return STATUS_SUCCESS;
549
550 FailChannel:
551 /* Destroy the channel and return the failure code */
552 Channel->ChannelDestroy(Channel);
553 return Status;
554 }
555
556 NTSTATUS
557 NTAPI
558 ChannelClose(IN PSAC_CHANNEL Channel)
559 {
560 NTSTATUS Status;
561 CHECK_PARAMETER(Channel);
562
563 /* Set the channel inactive */
564 ChannelSetStatus(Channel, Inactive);
565
566 /* Set the close event */
567 if (Channel->Flags & SAC_CHANNEL_FLAG_CLOSE_EVENT)
568 {
569 ChannelSetEvent(Channel, CloseEvent);
570 }
571
572 /* Close all the handles */
573 Status = ChannelDereferenceHandles(Channel);
574 return Status;
575 }