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