1 /*
2  *  Mailslot regression test
3  *
4  *  Copyright 2003 Mike McCormack
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 
25 #include <windef.h>
26 #include <winbase.h>
27 
28 #include "wine/test.h"
29 
30 static const char szmspath[] = "\\\\.\\mailslot\\wine_mailslot_test";
31 
32 static int mailslot_test(void)
33 {
34     HANDLE hSlot, hSlot2, hWriter, hWriter2;
35     unsigned char buffer[16];
36     DWORD count, dwMax, dwNext, dwMsgCount, dwTimeout;
37     BOOL ret;
38 
39     /* sanity check on GetMailslotInfo */
40     dwMax = dwNext = dwMsgCount = dwTimeout = 0;
41     ok( !GetMailslotInfo( INVALID_HANDLE_VALUE, &dwMax, &dwNext,
42             &dwMsgCount, &dwTimeout ), "getmailslotinfo succeeded\n");
43 
44     /* open a mailslot that doesn't exist */
45     hWriter = CreateFileA(szmspath, GENERIC_READ|GENERIC_WRITE,
46                              FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
47     ok( hWriter == INVALID_HANDLE_VALUE, "nonexistent mailslot\n");
48 
49     /* open a mailslot without the right name */
50     hSlot = CreateMailslotA( "blah", 0, 0, NULL );
51     ok( hSlot == INVALID_HANDLE_VALUE,
52             "Created mailslot with invalid name\n");
53     ok( GetLastError() == ERROR_INVALID_NAME,
54             "error should be ERROR_INVALID_NAME\n");
55 
56     /* open a mailslot with a null name */
57     hSlot = CreateMailslotA( NULL, 0, 0, NULL );
58     ok( hSlot == INVALID_HANDLE_VALUE, "Created mailslot with invalid name\n");
59     ok( GetLastError() == ERROR_PATH_NOT_FOUND, "error should be ERROR_PATH_NOT_FOUND\n");
60 
61     /* valid open, but with wacky parameters ... then check them */
62     hSlot = CreateMailslotA( szmspath, -1, -1, NULL );
63     ok( hSlot != INVALID_HANDLE_VALUE , "mailslot with valid name failed\n");
64     dwMax = dwNext = dwMsgCount = dwTimeout = 0;
65     ok( GetMailslotInfo( hSlot, &dwMax, &dwNext, &dwMsgCount, &dwTimeout ),
66            "getmailslotinfo failed\n");
67     ok( dwMax == ~0U, "dwMax incorrect\n");
68     ok( dwNext == MAILSLOT_NO_MESSAGE, "dwNext incorrect\n");
69     ok( dwMsgCount == 0, "dwMsgCount incorrect\n");
70     ok( dwTimeout == ~0U, "dwTimeout incorrect\n");
71     ok( GetMailslotInfo( hSlot, NULL, NULL, NULL, NULL ),
72             "getmailslotinfo failed\n");
73     ok( CloseHandle(hSlot), "failed to close mailslot\n");
74 
75     /* now open it for real */
76     hSlot = CreateMailslotA( szmspath, 0, 0, NULL );
77     ok( hSlot != INVALID_HANDLE_VALUE , "valid mailslot failed\n");
78 
79     /* try and read/write to it */
80     count = 0xdeadbeef;
81     SetLastError(0xdeadbeef);
82     ret = ReadFile(INVALID_HANDLE_VALUE, buffer, 0, &count, NULL);
83     ok(!ret, "ReadFile should fail\n");
84     ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError());
85     ok(count == 0, "expected 0, got %u\n", count);
86 
87     count = 0xdeadbeef;
88     SetLastError(0xdeadbeef);
89     ret = ReadFile(hSlot, buffer, 0, &count, NULL);
90     ok(!ret, "ReadFile should fail\n");
91 todo_wine
92     ok(GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError());
93     ok(count == 0, "expected 0, got %u\n", count);
94 
95     count = 0;
96     memset(buffer, 0, sizeof buffer);
97     ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
98     ok( !ret, "slot read\n");
99     if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
100     else ok( count == 0, "wrong count %u\n", count );
101     ok( !WriteFile( hSlot, buffer, sizeof buffer, &count, NULL),
102             "slot write\n");
103     ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
104 
105     /* now try and open the client, but with the wrong sharing mode */
106     hWriter = CreateFileA(szmspath, GENERIC_WRITE,
107                              0, NULL, OPEN_EXISTING, 0, NULL);
108     ok( hWriter != INVALID_HANDLE_VALUE /* vista */ || GetLastError() == ERROR_SHARING_VIOLATION,
109         "error should be ERROR_SHARING_VIOLATION got %p / %u\n", hWriter, GetLastError());
110     if (hWriter != INVALID_HANDLE_VALUE) CloseHandle( hWriter );
111 
112     /* now open the client with the correct sharing mode */
113     hWriter = CreateFileA(szmspath, GENERIC_READ|GENERIC_WRITE,
114                              FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
115     ok( hWriter != INVALID_HANDLE_VALUE, "existing mailslot err %u\n", GetLastError());
116 
117     /*
118      * opening a client should make no difference to
119      * whether we can read or write the mailslot
120      */
121     ret = ReadFile( hSlot, buffer, sizeof buffer/2, &count, NULL);
122     ok( !ret, "slot read\n");
123     if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
124     else ok( count == 0, "wrong count %u\n", count );
125     ok( !WriteFile( hSlot, buffer, sizeof buffer/2, &count, NULL),
126             "slot write\n");
127     ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
128 
129     /*
130      * we can't read from this client,
131      * but we should be able to write to it
132      */
133     ok( !ReadFile( hWriter, buffer, sizeof buffer/2, &count, NULL),
134             "can read client\n");
135     ok( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_ACCESS_DENIED,
136             "wrong error %u\n", GetLastError() );
137     ok( WriteFile( hWriter, buffer, sizeof buffer/2, &count, NULL),
138             "can't write client\n");
139     ok( !ReadFile( hWriter, buffer, sizeof buffer/2, &count, NULL),
140             "can read client\n");
141     ok( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_ACCESS_DENIED,
142             "wrong error %u\n", GetLastError() );
143 
144     /*
145      * seeing as there's something in the slot,
146      * we should be able to read it once
147      */
148     ok( ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
149             "slot read\n");
150     ok( count == (sizeof buffer/2), "short read\n" );
151 
152     /* but not again */
153     ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
154     ok( !ret, "slot read\n");
155     if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
156     else ok( count == 0, "wrong count %u\n", count );
157 
158     /* now try open another writer... should fail */
159     hWriter2 = CreateFileA(szmspath, GENERIC_READ|GENERIC_WRITE,
160                      FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
161     /* succeeds on vista, don't test */
162     if (hWriter2 != INVALID_HANDLE_VALUE) CloseHandle( hWriter2 );
163 
164     /* now try open another as a reader ... also fails */
165     hWriter2 = CreateFileA(szmspath, GENERIC_READ,
166                      FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
167     /* succeeds on vista, don't test */
168     if (hWriter2 != INVALID_HANDLE_VALUE) CloseHandle( hWriter2 );
169 
170     /* now try open another as a writer ... still fails */
171     hWriter2 = CreateFileA(szmspath, GENERIC_WRITE,
172                      FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
173     /* succeeds on vista, don't test */
174     if (hWriter2 != INVALID_HANDLE_VALUE) CloseHandle( hWriter2 );
175 
176     /* now open another one */
177     hSlot2 = CreateMailslotA( szmspath, 0, 0, NULL );
178     ok( hSlot2 == INVALID_HANDLE_VALUE , "opened two mailslots\n");
179 
180     /* close the client again */
181     ok( CloseHandle( hWriter ), "closing the client\n");
182 
183     /*
184      * now try reopen it with slightly different permissions ...
185      * shared writing
186      */
187     hWriter = CreateFileA(szmspath, GENERIC_WRITE,
188               FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
189     ok( hWriter != INVALID_HANDLE_VALUE, "sharing writer\n");
190 
191     /*
192      * now try open another as a writer ...
193      * but don't share with the first ... fail
194      */
195     hWriter2 = CreateFileA(szmspath, GENERIC_WRITE,
196                      FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
197     /* succeeds on vista, don't test */
198     if (hWriter2 != INVALID_HANDLE_VALUE) CloseHandle( hWriter2 );
199 
200     /* now try open another as a writer ... and share with the first */
201     hWriter2 = CreateFileA(szmspath, GENERIC_WRITE,
202               FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
203     ok( hWriter2 != INVALID_HANDLE_VALUE, "2nd sharing writer\n");
204 
205     /* check the mailslot info */
206     dwMax = dwNext = dwMsgCount = dwTimeout = 0;
207     ok( GetMailslotInfo( hSlot, &dwMax, &dwNext, &dwMsgCount, &dwTimeout ),
208         "getmailslotinfo failed\n");
209     ok( dwNext == MAILSLOT_NO_MESSAGE, "dwNext incorrect\n");
210     ok( dwMax == 0, "dwMax incorrect\n");
211     ok( dwMsgCount == 0, "dwMsgCount incorrect\n");
212     ok( dwTimeout == 0, "dwTimeout incorrect\n");
213 
214     /* check there's still no data */
215     ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
216     ok( !ret, "slot read\n");
217     if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
218     else ok( count == 0, "wrong count %u\n", count );
219 
220     /* write two messages */
221     buffer[0] = 'a';
222     ok( WriteFile( hWriter, buffer, 1, &count, NULL), "1st write failed\n");
223 
224     /* check the mailslot info */
225     dwNext = dwMsgCount = 0;
226     ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
227         "getmailslotinfo failed\n");
228     ok( dwNext == 1, "dwNext incorrect\n");
229     ok( dwMsgCount == 1, "dwMsgCount incorrect\n");
230 
231     buffer[0] = 'b';
232     buffer[1] = 'c';
233     ok( WriteFile( hWriter2, buffer, 2, &count, NULL), "2nd write failed\n");
234 
235     /* check the mailslot info */
236     dwNext = dwMsgCount = 0;
237     ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
238         "getmailslotinfo failed\n");
239     ok( dwNext == 1, "dwNext incorrect\n");
240     todo_wine {
241     ok( dwMsgCount == 2, "dwMsgCount incorrect\n");
242     }
243 
244     /* write a 3rd message with zero size */
245     ok( WriteFile( hWriter2, buffer, 0, &count, NULL), "3rd write failed\n");
246 
247     /* check the mailslot info */
248     dwNext = dwMsgCount = 0;
249     ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
250         "getmailslotinfo failed\n");
251     ok( dwNext == 1, "dwNext incorrect\n");
252     todo_wine
253         ok( dwMsgCount == 3, "dwMsgCount incorrect %u\n", dwMsgCount);
254 
255     buffer[0]=buffer[1]=0;
256 
257     /*
258      * then check that they come out with the correct order and size,
259      * then the slot is empty
260      */
261     ok( ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
262         "1st slot read failed\n");
263     ok( count == 1, "failed to get 1st message\n");
264     ok( buffer[0] == 'a', "1st message wrong\n");
265 
266     /* check the mailslot info */
267     dwNext = dwMsgCount = 0;
268     ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
269         "getmailslotinfo failed\n");
270     ok( dwNext == 2, "dwNext incorrect\n");
271     todo_wine {
272         ok( dwMsgCount == 2, "dwMsgCount incorrect %u\n", dwMsgCount);
273     }
274 
275     /* read the second message */
276     ok( ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
277         "2nd slot read failed\n");
278     ok( count == 2, "failed to get 2nd message\n");
279     ok( ( buffer[0] == 'b' ) && ( buffer[1] == 'c' ), "2nd message wrong\n");
280 
281     /* check the mailslot info */
282     dwNext = dwMsgCount = 0;
283     ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
284         "getmailslotinfo failed\n");
285     ok( dwNext == 0, "dwNext incorrect %u\n", dwNext);
286     todo_wine {
287         ok( dwMsgCount == 1, "dwMsgCount incorrect %u\n", dwMsgCount);
288     }
289 
290     /* read the 3rd (zero length) message */
291     todo_wine {
292     ok( ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
293         "3rd slot read failed\n");
294     }
295     ok( count == 0, "failed to get 3rd message\n");
296 
297     /*
298      * now there should be no more messages
299      * check the mailslot info
300      */
301     dwNext = dwMsgCount = 0;
302     ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
303         "getmailslotinfo failed\n");
304     ok( dwNext == MAILSLOT_NO_MESSAGE, "dwNext incorrect\n");
305     ok( dwMsgCount == 0, "dwMsgCount incorrect\n");
306 
307     /* check that reads fail */
308     ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
309     ok( !ret, "3rd slot read succeeded\n");
310     if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
311     else ok( count == 0, "wrong count %u\n", count );
312 
313     /* finally close the mailslot and its client */
314     ok( CloseHandle( hWriter2 ), "closing 2nd client\n");
315     ok( CloseHandle( hWriter ), "closing the client\n");
316     ok( CloseHandle( hSlot ), "closing the mailslot\n");
317 
318     /* test timeouts */
319     hSlot = CreateMailslotA( szmspath, 0, 1000, NULL );
320     ok( hSlot != INVALID_HANDLE_VALUE , "valid mailslot failed\n");
321     count = 0;
322     memset(buffer, 0, sizeof buffer);
323     dwTimeout = GetTickCount();
324     ok( !ReadFile( hSlot, buffer, sizeof buffer, &count, NULL), "slot read\n");
325     ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
326     dwTimeout = GetTickCount() - dwTimeout;
327     ros_skip_flaky
328     ok( dwTimeout >= 990, "timeout too short %u\n", dwTimeout );
329     ok( CloseHandle( hSlot ), "closing the mailslot\n");
330 
331     return 0;
332 }
333 
334 START_TEST(mailslot)
335 {
336     mailslot_test();
337 }
338