eb2503b88f76d4f494305f683d0ecfd1c9961988
[reactos.git] / reactos / lib / kernel32 / file / npipe.c
1 /* $Id: npipe.c,v 1.9 2001/11/20 20:35:10 ekohl Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/file/npipe.c
6 * PURPOSE: Directory functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * UPDATE HISTORY:
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <ntdll/rtl.h>
15 #include <windows.h>
16 #include <kernel32/error.h>
17 //#include <wchar.h>
18 //#include <string.h>
19 #include <limits.h>
20 #include <napi/npipe.h>
21
22 //#define NDEBUG
23 #include <kernel32/kernel32.h>
24
25 /* FUNCTIONS ****************************************************************/
26
27 HANDLE STDCALL
28 CreateNamedPipeA(LPCSTR lpName,
29 DWORD dwOpenMode,
30 DWORD dwPipeMode,
31 DWORD nMaxInstances,
32 DWORD nOutBufferSize,
33 DWORD nInBufferSize,
34 DWORD nDefaultTimeOut,
35 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
36 {
37 HANDLE NamedPipeHandle;
38 UNICODE_STRING NameU;
39 ANSI_STRING NameA;
40
41 RtlInitAnsiString(&NameA, (LPSTR)lpName);
42 RtlAnsiStringToUnicodeString(&NameU, &NameA, TRUE);
43
44 NamedPipeHandle = CreateNamedPipeW(NameU.Buffer,
45 dwOpenMode,
46 dwPipeMode,
47 nMaxInstances,
48 nOutBufferSize,
49 nInBufferSize,
50 nDefaultTimeOut,
51 lpSecurityAttributes);
52
53 RtlFreeUnicodeString(&NameU);
54
55 return(NamedPipeHandle);
56 }
57
58
59 HANDLE STDCALL
60 CreateNamedPipeW(LPCWSTR lpName,
61 DWORD dwOpenMode,
62 DWORD dwPipeMode,
63 DWORD nMaxInstances,
64 DWORD nOutBufferSize,
65 DWORD nInBufferSize,
66 DWORD nDefaultTimeOut,
67 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
68 {
69 UNICODE_STRING NamedPipeName;
70 BOOL Result;
71 NTSTATUS Status;
72 OBJECT_ATTRIBUTES ObjectAttributes;
73 HANDLE PipeHandle;
74 ACCESS_MASK DesiredAccess;
75 ULONG CreateOptions;
76 ULONG CreateDisposition;
77 BOOLEAN WriteModeMessage;
78 BOOLEAN ReadModeMessage;
79 BOOLEAN NonBlocking;
80 IO_STATUS_BLOCK Iosb;
81 ULONG ShareAccess;
82 LARGE_INTEGER DefaultTimeOut;
83
84 Result = RtlDosPathNameToNtPathName_U((LPWSTR)lpName,
85 &NamedPipeName,
86 NULL,
87 NULL);
88 if (!Result)
89 {
90 SetLastError(ERROR_PATH_NOT_FOUND);
91 return(INVALID_HANDLE_VALUE);
92 }
93
94 DPRINT("Pipe name: %wZ\n", &NamedPipeName);
95 DPRINT("Pipe name: %S\n", NamedPipeName.Buffer);
96
97 InitializeObjectAttributes(&ObjectAttributes,
98 &NamedPipeName,
99 OBJ_CASE_INSENSITIVE,
100 NULL,
101 NULL);
102
103 DesiredAccess = 0;
104
105 ShareAccess = 0;
106
107 CreateDisposition = FILE_OPEN_IF;
108
109 CreateOptions = 0;
110 if (dwOpenMode & FILE_FLAG_WRITE_THROUGH)
111 {
112 CreateOptions = CreateOptions | FILE_WRITE_THROUGH;
113 }
114 if (dwOpenMode & FILE_FLAG_OVERLAPPED)
115 {
116 CreateOptions = CreateOptions | FILE_SYNCHRONOUS_IO_ALERT;
117 }
118 if (dwOpenMode & PIPE_ACCESS_DUPLEX)
119 {
120 CreateOptions = CreateOptions | FILE_PIPE_FULL_DUPLEX;
121 }
122 else if (dwOpenMode & PIPE_ACCESS_INBOUND)
123 {
124 CreateOptions = CreateOptions | FILE_PIPE_INBOUND;
125 }
126 else if (dwOpenMode & PIPE_ACCESS_OUTBOUND)
127 {
128 CreateOptions = CreateOptions | FILE_PIPE_OUTBOUND;
129 }
130
131 if (dwPipeMode & PIPE_TYPE_BYTE)
132 {
133 WriteModeMessage = FALSE;
134 }
135 else if (dwPipeMode & PIPE_TYPE_MESSAGE)
136 {
137 WriteModeMessage = TRUE;
138 }
139 else
140 {
141 WriteModeMessage = FALSE;
142 }
143
144 if (dwPipeMode & PIPE_READMODE_BYTE)
145 {
146 ReadModeMessage = FALSE;
147 }
148 else if (dwPipeMode & PIPE_READMODE_MESSAGE)
149 {
150 ReadModeMessage = TRUE;
151 }
152 else
153 {
154 ReadModeMessage = FALSE;
155 }
156
157 if (dwPipeMode & PIPE_WAIT)
158 {
159 NonBlocking = FALSE;
160 }
161 else if (dwPipeMode & PIPE_NOWAIT)
162 {
163 NonBlocking = TRUE;
164 }
165 else
166 {
167 NonBlocking = FALSE;
168 }
169
170 if (nMaxInstances >= PIPE_UNLIMITED_INSTANCES)
171 {
172 nMaxInstances = ULONG_MAX;
173 }
174
175 DefaultTimeOut.QuadPart = nDefaultTimeOut * -10000;
176
177 Status = NtCreateNamedPipeFile(&PipeHandle,
178 DesiredAccess,
179 &ObjectAttributes,
180 &Iosb,
181 ShareAccess,
182 CreateDisposition,
183 CreateOptions,
184 WriteModeMessage,
185 ReadModeMessage,
186 NonBlocking,
187 nMaxInstances,
188 nInBufferSize,
189 nOutBufferSize,
190 &DefaultTimeOut);
191
192 RtlFreeUnicodeString(&NamedPipeName);
193
194 if (!NT_SUCCESS(Status))
195 {
196 DPRINT("NtCreateNamedPipe failed (Status %x)!\n", Status);
197 SetLastErrorByStatus (Status);
198 return(INVALID_HANDLE_VALUE);
199 }
200
201 return(PipeHandle);
202 }
203
204
205 BOOL STDCALL
206 WaitNamedPipeA(LPCSTR lpNamedPipeName,
207 DWORD nTimeOut)
208 {
209 BOOL r;
210 UNICODE_STRING NameU;
211 ANSI_STRING NameA;
212
213 RtlInitAnsiString(&NameA, (LPSTR)lpNamedPipeName);
214 RtlAnsiStringToUnicodeString(&NameU, &NameA, TRUE);
215
216 r = WaitNamedPipeW(NameU.Buffer, nTimeOut);
217
218 RtlFreeUnicodeString(&NameU);
219
220 return(r);
221 }
222
223
224 BOOL STDCALL
225 WaitNamedPipeW(LPCWSTR lpNamedPipeName,
226 DWORD nTimeOut)
227 {
228 UNICODE_STRING NamedPipeName;
229 BOOL r;
230 NTSTATUS Status;
231 OBJECT_ATTRIBUTES ObjectAttributes;
232 NPFS_WAIT_PIPE WaitPipe;
233 HANDLE FileHandle;
234 IO_STATUS_BLOCK Iosb;
235
236 r = RtlDosPathNameToNtPathName_U((LPWSTR)lpNamedPipeName,
237 &NamedPipeName,
238 NULL,
239 NULL);
240
241 if (!r)
242 {
243 return(FALSE);
244 }
245
246 InitializeObjectAttributes(&ObjectAttributes,
247 &NamedPipeName,
248 OBJ_CASE_INSENSITIVE,
249 NULL,
250 NULL);
251 Status = NtOpenFile(&FileHandle,
252 FILE_GENERIC_READ,
253 &ObjectAttributes,
254 &Iosb,
255 0,
256 FILE_SYNCHRONOUS_IO_ALERT);
257 if (!NT_SUCCESS(Status))
258 {
259 SetLastErrorByStatus (Status);
260 return(FALSE);
261 }
262
263 WaitPipe.Timeout.QuadPart = nTimeOut * -10000;
264
265 Status = NtFsControlFile(FileHandle,
266 NULL,
267 NULL,
268 NULL,
269 &Iosb,
270 FSCTL_PIPE_WAIT,
271 &WaitPipe,
272 sizeof(WaitPipe),
273 NULL,
274 0);
275 NtClose(FileHandle);
276 if (!NT_SUCCESS(Status))
277 {
278 SetLastErrorByStatus (Status);
279 return(FALSE);
280 }
281
282 return(TRUE);
283 }
284
285
286 BOOL STDCALL
287 ConnectNamedPipe(HANDLE hNamedPipe,
288 LPOVERLAPPED lpOverlapped)
289 {
290 IO_STATUS_BLOCK Iosb;
291 HANDLE hEvent;
292 PIO_STATUS_BLOCK IoStatusBlock;
293 NTSTATUS Status;
294
295 if (lpOverlapped != NULL)
296 {
297 lpOverlapped->Internal = STATUS_PENDING;
298 hEvent = lpOverlapped->hEvent;
299 IoStatusBlock = (PIO_STATUS_BLOCK)lpOverlapped;
300 }
301 else
302 {
303 IoStatusBlock = &Iosb;
304 hEvent = NULL;
305 }
306
307 Status = NtFsControlFile(hNamedPipe,
308 hEvent,
309 NULL,
310 NULL,
311 IoStatusBlock,
312 FSCTL_PIPE_LISTEN,
313 NULL,
314 0,
315 NULL,
316 0);
317 if ((lpOverlapped == NULL) && (Status == STATUS_PENDING))
318 {
319 Status = NtWaitForSingleObject(hNamedPipe,
320 FALSE,
321 NULL);
322 if (!NT_SUCCESS(Status))
323 {
324 SetLastErrorByStatus(Status);
325 return(FALSE);
326 }
327 Status = Iosb.Status;
328 }
329 if (!NT_SUCCESS(Status) || (Status == STATUS_PENDING))
330 {
331 SetLastErrorByStatus (Status);
332 return(FALSE);
333 }
334 return(TRUE);
335 }
336
337
338 BOOL STDCALL
339 SetNamedPipeHandleState(HANDLE hNamedPipe,
340 LPDWORD lpMode,
341 LPDWORD lpMaxCollectionCount,
342 LPDWORD lpCollectDataTimeout)
343 {
344 NPFS_GET_STATE GetState;
345 NPFS_SET_STATE SetState;
346 IO_STATUS_BLOCK Iosb;
347 NTSTATUS Status;
348
349 Status = NtFsControlFile(hNamedPipe,
350 NULL,
351 NULL,
352 NULL,
353 &Iosb,
354 FSCTL_PIPE_GET_STATE,
355 NULL,
356 0,
357 &GetState,
358 sizeof(NPFS_GET_STATE));
359 if (Status == STATUS_PENDING)
360 {
361 Status = NtWaitForSingleObject(hNamedPipe,
362 FALSE,
363 NULL);
364 if (!NT_SUCCESS(Status))
365 {
366 SetLastErrorByStatus(Status);
367 return(FALSE);
368 }
369 }
370
371 if (lpMode != NULL)
372 {
373 if ((*lpMode) & PIPE_READMODE_MESSAGE)
374 {
375 SetState.ReadModeMessage = TRUE;
376 }
377 else
378 {
379 SetState.ReadModeMessage = FALSE;
380 }
381 if ((*lpMode) & PIPE_NOWAIT)
382 {
383 SetState.NonBlocking = TRUE;
384 }
385 else
386 {
387 SetState.NonBlocking = FALSE;
388 }
389 SetState.WriteModeMessage = GetState.WriteModeMessage;
390 }
391 else
392 {
393 SetState.ReadModeMessage = GetState.ReadModeMessage;
394 SetState.WriteModeMessage = GetState.WriteModeMessage;
395 SetState.NonBlocking = SetState.NonBlocking;
396 }
397
398 if (lpMaxCollectionCount != NULL)
399 {
400 SetState.InBufferSize = *lpMaxCollectionCount;
401 }
402 else
403 {
404 SetState.InBufferSize = GetState.InBufferSize;
405 }
406
407 SetState.OutBufferSize = GetState.OutBufferSize;
408
409 if (lpCollectDataTimeout != NULL)
410 {
411 SetState.Timeout.QuadPart = (*lpCollectDataTimeout) * -10000;
412 }
413 else
414 {
415 SetState.Timeout = GetState.Timeout;
416 }
417
418 Status = NtFsControlFile(hNamedPipe,
419 NULL,
420 NULL,
421 NULL,
422 &Iosb,
423 FSCTL_PIPE_SET_STATE,
424 &SetState,
425 sizeof(NPFS_SET_STATE),
426 NULL,
427 0);
428 if (Status == STATUS_PENDING)
429 {
430 Status = NtWaitForSingleObject(hNamedPipe,
431 FALSE,
432 NULL);
433 if (!NT_SUCCESS(Status))
434 {
435 SetLastErrorByStatus(Status);
436 return(FALSE);
437 }
438 }
439
440 return(TRUE);
441 }
442
443
444 BOOL STDCALL
445 CallNamedPipeA(LPCSTR lpNamedPipeName,
446 LPVOID lpInBuffer,
447 DWORD nInBufferSize,
448 LPVOID lpOutBuffer,
449 DWORD nOutBufferSize,
450 LPDWORD lpBytesRead,
451 DWORD nTimeOut)
452 {
453 UNICODE_STRING PipeName;
454 BOOL Result;
455
456 RtlCreateUnicodeStringFromAsciiz(&PipeName,
457 (LPSTR)lpNamedPipeName);
458
459 Result = CallNamedPipeW(PipeName.Buffer,
460 lpInBuffer,
461 nInBufferSize,
462 lpOutBuffer,
463 nOutBufferSize,
464 lpBytesRead,
465 nTimeOut);
466
467 RtlFreeUnicodeString(&PipeName);
468
469 return(Result);
470 }
471
472
473 BOOL STDCALL
474 CallNamedPipeW(LPCWSTR lpNamedPipeName,
475 LPVOID lpInBuffer,
476 DWORD nInBufferSize,
477 LPVOID lpOutBuffer,
478 DWORD nOutBufferSize,
479 LPDWORD lpBytesRead,
480 DWORD nTimeOut)
481 {
482 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
483 return FALSE;
484 }
485
486
487 BOOL STDCALL
488 DisconnectNamedPipe(HANDLE hNamedPipe)
489 {
490 IO_STATUS_BLOCK Iosb;
491 NTSTATUS Status;
492
493 Status = NtFsControlFile(hNamedPipe,
494 NULL,
495 NULL,
496 NULL,
497 &Iosb,
498 FSCTL_PIPE_DISCONNECT,
499 NULL,
500 0,
501 NULL,
502 0);
503 if (Status == STATUS_PENDING)
504 {
505 Status = NtWaitForSingleObject(hNamedPipe,
506 FALSE,
507 NULL);
508 if (!NT_SUCCESS(Status))
509 {
510 SetLastErrorByStatus(Status);
511 return(FALSE);
512 }
513 }
514
515 if (!NT_SUCCESS(Status))
516 {
517 SetLastErrorByStatus(Status);
518 return(FALSE);
519 }
520 return(TRUE);
521 }
522
523
524 WINBOOL STDCALL
525 GetNamedPipeHandleStateW(HANDLE hNamedPipe,
526 LPDWORD lpState,
527 LPDWORD lpCurInstances,
528 LPDWORD lpMaxCollectionCount,
529 LPDWORD lpCollectDataTimeout,
530 LPWSTR lpUserName,
531 DWORD nMaxUserNameSize)
532 {
533 FILE_PIPE_LOCAL_INFORMATION LocalInfo;
534 FILE_PIPE_INFORMATION PipeInfo;
535 IO_STATUS_BLOCK StatusBlock;
536 NTSTATUS Status;
537
538 if (lpState != NULL)
539 {
540 Status = NtQueryInformationFile(hNamedPipe,
541 &StatusBlock,
542 &PipeInfo,
543 sizeof(FILE_PIPE_INFORMATION),
544 FilePipeInformation);
545 if (!NT_SUCCESS(Status))
546 {
547 SetLastErrorByStatus(Status);
548 return(FALSE);
549 }
550 *lpState = 0; /* FIXME */
551 }
552
553 if (lpCurInstances != NULL)
554 {
555 Status = NtQueryInformationFile(hNamedPipe,
556 &StatusBlock,
557 &LocalInfo,
558 sizeof(FILE_PIPE_LOCAL_INFORMATION),
559 FilePipeLocalInformation);
560 if (!NT_SUCCESS(Status))
561 {
562 SetLastErrorByStatus(Status);
563 return(FALSE);
564 }
565 *lpCurInstances = min(LocalInfo.CurrentInstances, 255);
566 }
567
568
569 /* FIXME: retrieve remaining information */
570
571
572 return(TRUE);
573 }
574
575
576 WINBOOL STDCALL
577 GetNamedPipeHandleStateA(HANDLE hNamedPipe,
578 LPDWORD lpState,
579 LPDWORD lpCurInstances,
580 LPDWORD lpMaxCollectionCount,
581 LPDWORD lpCollectDataTimeout,
582 LPSTR lpUserName,
583 DWORD nMaxUserNameSize)
584 {
585 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
586 return FALSE;
587 }
588
589
590 WINBOOL STDCALL
591 GetNamedPipeInfo(HANDLE hNamedPipe,
592 LPDWORD lpFlags,
593 LPDWORD lpOutBufferSize,
594 LPDWORD lpInBufferSize,
595 LPDWORD lpMaxInstances)
596 {
597 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation;
598 IO_STATUS_BLOCK StatusBlock;
599 NTSTATUS Status;
600
601 Status = NtQueryInformationFile(hNamedPipe,
602 &StatusBlock,
603 &PipeLocalInformation,
604 sizeof(FILE_PIPE_LOCAL_INFORMATION),
605 FilePipeLocalInformation);
606 if (!NT_SUCCESS(Status))
607 {
608 SetLastErrorByStatus(Status);
609 return(FALSE);
610 }
611
612 if (lpFlags != NULL)
613 {
614 *lpFlags = (PipeLocalInformation.NamedPipeEnd == FILE_PIPE_SERVER_END) ? PIPE_SERVER_END : PIPE_CLIENT_END;
615 *lpFlags |= (PipeLocalInformation.NamedPipeType == 1) ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE;
616 }
617
618 if (lpOutBufferSize != NULL)
619 *lpOutBufferSize = PipeLocalInformation.OutboundQuota;
620
621 if (lpInBufferSize != NULL)
622 *lpInBufferSize = PipeLocalInformation.InboundQuota;
623
624 if (lpMaxInstances != NULL)
625 {
626 if (PipeLocalInformation.MaximumInstances >= 255)
627 *lpMaxInstances = PIPE_UNLIMITED_INSTANCES;
628 else
629 *lpMaxInstances = PipeLocalInformation.MaximumInstances;
630 }
631
632 return(TRUE);
633 }
634
635
636 BOOL STDCALL
637 PeekNamedPipe(HANDLE hNamedPipe,
638 LPVOID lpBuffer,
639 DWORD nBufferSize,
640 LPDWORD lpBytesRead,
641 LPDWORD lpTotalBytesAvail,
642 LPDWORD lpBytesLeftThisMessage)
643 {
644 PFILE_PIPE_PEEK_BUFFER Buffer;
645 IO_STATUS_BLOCK Iosb;
646 ULONG BufferSize;
647 NTSTATUS Status;
648
649 BufferSize = nBufferSize + sizeof(FILE_PIPE_PEEK_BUFFER);
650 Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
651 0,
652 BufferSize);
653
654 Status = NtFsControlFile(hNamedPipe,
655 NULL,
656 NULL,
657 NULL,
658 &Iosb,
659 FSCTL_PIPE_PEEK,
660 NULL,
661 0,
662 Buffer,
663 BufferSize);
664 if (Status == STATUS_PENDING)
665 {
666 Status = NtWaitForSingleObject(hNamedPipe,
667 FALSE,
668 NULL);
669 if (NT_SUCCESS(Status))
670 Status = Iosb.Status;
671 }
672
673 if (Status == STATUS_BUFFER_OVERFLOW)
674 {
675 Status = STATUS_SUCCESS;
676 }
677
678 if (!NT_SUCCESS(Status))
679 {
680 RtlFreeHeap(RtlGetProcessHeap(),
681 0,
682 Buffer);
683 SetLastErrorByStatus(Status);
684 return(FALSE);
685 }
686
687 if (lpTotalBytesAvail != NULL)
688 {
689 *lpTotalBytesAvail = Buffer->ReadDataAvailable;
690 }
691
692 if (lpBytesRead != NULL)
693 {
694 *lpBytesRead = Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER);
695 }
696
697 if (lpBytesLeftThisMessage != NULL)
698 {
699 *lpBytesLeftThisMessage = Buffer->MessageLength -
700 (Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER));
701 }
702
703 if (lpBuffer != NULL)
704 {
705 memcpy(lpBuffer, Buffer->Data,
706 min(nBufferSize, Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER)));
707 }
708
709 RtlFreeHeap(RtlGetProcessHeap(),
710 0,
711 Buffer);
712
713 return(TRUE);
714 }
715
716
717 BOOL STDCALL
718 TransactNamedPipe(HANDLE hNamedPipe,
719 LPVOID lpInBuffer,
720 DWORD nInBufferSize,
721 LPVOID lpOutBuffer,
722 DWORD nOutBufferSize,
723 LPDWORD lpBytesRead,
724 LPOVERLAPPED lpOverlapped)
725 {
726 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
727 return FALSE;
728 }
729
730 /* EOF */