Revert "[SHELL32] SHChangeNotify: Use tree for CDirectoryList (#6784)" (#6800)
[reactos.git] / sdk / tools / pipetools / piperead.cpp
1 //
2 // piperead.cpp
3 //
4 // Martin Fuchs, 30.11.2003
5 //
6 // Jan Roeloffzen, 26.1.2010
7 // Pipe client, based on msdn example
8
9
10 #define WIN32_LEAN_AND_MEAN
11 #include <errno.h>
12 #include <windows.h>
13 #include <stdio.h>
14
15 #define PIPEREAD_VERSION "0.3"
16 #define PIPEREAD_NOPIPE (-101)
17
18 // This definition currently missing in MinGW.
19 #ifndef FILE_FLAG_FIRST_PIPE_INSTANCE
20 #define FILE_FLAG_FIRST_PIPE_INSTANCE 0x00080000
21 #endif
22
23
24 #define BUFSIZE 1024
25
26 static void print_error(DWORD win32_error)
27 {
28 fprintf(stderr, "WIN32 error %lu\n", win32_error);
29 }
30
31 static int pipeServer(char *path)
32 {
33 HANDLE hPipe = CreateNamedPipe(path, PIPE_ACCESS_DUPLEX|FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_WAIT|PIPE_TYPE_BYTE, 1, 4096, 4096, 30000, NULL);
34
35 if (hPipe == INVALID_HANDLE_VALUE) {
36 print_error(GetLastError());
37 return 1;
38 }
39
40 for(;;) {
41 DWORD read;
42 BYTE buffer[BUFSIZE];
43
44 if (!ReadFile(hPipe, buffer, sizeof(buffer), &read, NULL)) {
45 DWORD error = GetLastError();
46
47 if (error == ERROR_PIPE_LISTENING) {
48 Sleep(1000);
49 } else if (error == ERROR_BROKEN_PIPE) {
50 CloseHandle(hPipe);
51
52 hPipe = CreateNamedPipe(path, PIPE_ACCESS_DUPLEX|FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_WAIT|PIPE_TYPE_BYTE, 1, 4096, 4096, 30000, NULL);
53
54 if (hPipe == INVALID_HANDLE_VALUE) {
55 fprintf(stderr,"INVALID_HANDLE_VALUE\n");
56 print_error(GetLastError());
57 return 1;
58 }
59 } else {
60 fprintf(stderr,"error %lu\n",error);
61 print_error(error);
62 break;
63 }
64 }
65
66 if (read)
67 fwrite(buffer, read, 1, stdout);
68 }
69
70 if (!CloseHandle(hPipe))
71 print_error(GetLastError());
72
73 return 0;
74 }
75
76
77 static int pipeClient(char *path)
78 {
79 HANDLE hPipe=INVALID_HANDLE_VALUE;
80 TCHAR chBuf[BUFSIZE];
81 BOOL fSuccess = FALSE;
82 DWORD cbRead;
83 DWORD Err;
84 int res = 0;
85
86 setvbuf(stdout, NULL, _IONBF, 0);
87 while (1) {
88 hPipe = CreateFile(path, // pipe name
89 GENERIC_READ,
90 0, // no sharing
91 NULL, // default security attributes
92 OPEN_EXISTING, // opens existing pipe
93 0, // default attributes
94 NULL); // no template file
95
96 // Break if the pipe handle is valid.
97 if (hPipe != INVALID_HANDLE_VALUE)
98 break;
99
100 // Exit if an error other than ERROR_PIPE_BUSY occurs.
101 Err = GetLastError();
102 if (Err != ERROR_PIPE_BUSY) {
103 if (ERROR_FILE_NOT_FOUND == Err)
104 {
105 res = PIPEREAD_NOPIPE;
106 return res;
107 }
108 else
109 {
110 fprintf(stderr,"Could not open pipe %s. Error=%lu\n", path, Err );
111 res = -1;
112 }
113 break;
114 }
115
116 // All pipe instances are busy, so wait for 20 seconds.
117 if ( ! WaitNamedPipe(path, 20000)) {
118 fprintf(stderr,"Could not open pipe: 20 second wait timed out.");
119 res = -2;
120 break;
121 }
122 }
123
124 if (!res) do {
125 fSuccess = ReadFile(hPipe, // pipe handle
126 chBuf, // buffer to receive reply
127 BUFSIZE, // size of buffer
128 &cbRead, // number of bytes read
129 NULL); // not overlapped
130
131 if ( ! fSuccess ) {
132 Err = GetLastError();
133 if ( Err == ERROR_MORE_DATA ) {
134 fSuccess = TRUE;
135 } else {
136 fprintf(stderr, "ReadFile: Error %lu \n", Err );
137 res = -9;
138 break;
139 }
140 }
141
142 fwrite(chBuf,1,cbRead,stdout);
143 } while ( fSuccess);
144
145 if ( ! fSuccess) {
146 fprintf(stderr, "ReadFile from pipe failed. Error=%lu\n", GetLastError() );
147 }
148
149 if (hPipe != INVALID_HANDLE_VALUE)
150 CloseHandle(hPipe);
151
152 return res;
153
154 }
155
156 static int fileClient(const char *path)
157 {
158 int res = 0;
159 FILE *fin;
160 int c;
161
162 setvbuf(stdout, NULL, _IONBF, 0);
163 if (!(fin = fopen(path, "r"))) {
164 fprintf(stderr,"Could not fopen %s (%s)\n", path, strerror(errno) );
165 return -1;
166 }
167
168 while ((c = fgetc(fin)) != EOF) {
169 fputc(c, stdout);
170 }
171
172 fclose(fin);
173 return res;
174 }
175
176 void usage(void)
177 {
178 fprintf(stderr, "piperead " PIPEREAD_VERSION "\n\n");
179 fprintf(stderr, "Usage: piperead [-c] <named pipe>\n");
180 fprintf(stderr, "-c means Client mode\n");
181 fprintf(stderr, "Example: piperead -c \\\\.\\pipe\\kdbg | log2lines -c\n\n");
182 }
183
184 int main(int argc, char** argv)
185 {
186 char path[MAX_PATH];
187 const char* pipe_name;
188 const char* clientMode;
189 int res = 0;
190
191 pipe_name = "com_1";
192 clientMode = NULL;
193 switch (argc) {
194 case 3:
195 clientMode = *++argv;
196 if (strcmp(clientMode,"-c") != 0) {
197 fprintf(stderr,"Invalid option: %s\n", clientMode);
198 clientMode = NULL;
199 res = -6;
200 }
201 //fall through
202 case 2:
203 pipe_name = *++argv;
204 if (strcmp(pipe_name,"-h") == 0) {
205 res = -7;
206 }
207 break;
208 default:
209 res = -8;
210 break;
211 }
212 if (res) {
213 usage();
214 return res;
215 }
216
217 if ( pipe_name[0] == '\\' ) {
218 //assume caller specified full path
219 sprintf(path, "%s", pipe_name);
220 } else {
221 sprintf(path, "\\\\.\\pipe\\%s", pipe_name);
222 }
223
224 if ( clientMode ) {
225 res = pipeClient(path);
226 if (res == PIPEREAD_NOPIPE) {
227 res = fileClient(pipe_name);
228 }
229 } else {
230 res = pipeServer(path);
231 }
232
233 return res;
234 }