source: trunk/src/kernel32/hmmailslot.cpp@ 7312

Last change on this file since 7312 was 6646, checked in by bird, 24 years ago

Added $Id:$ keyword.

File size: 19.3 KB
Line 
1/* $Id: hmmailslot.cpp,v 1.2 2001-09-05 12:57:58 bird Exp $
2 *
3 * Win32 mailslot APIs
4 *
5 * Copyright 2001 Sander van Leeuwen (sandervl@xs4all.nl)
6 *
7 * This is not a complete implementation. Just a partial implementation
8 * using named pipes.
9 *
10 * TODO: Doesn't work for remote mailslots (on other machines)
11 * TODO: Writing to multiple mailslot servers doesn't work (\\*\mailslot\xxx)
12 *
13 * Project Odin Software License can be found in LICENSE.TXT
14 *
15 */
16
17#include <os2win.h>
18#include <string.h>
19#include "HandleManager.h"
20#include "HMMailslot.h"
21
22#define DBG_LOCALLOG DBG_hmmailslot
23#include "dbglocal.h"
24
25HMMailSlotInfo::HMMailSlotInfo(LPCSTR lpszName, HANDLE hPipe, DWORD nMaxMessageSize,
26 DWORD lReadTimeout, BOOL fServer,
27 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
28{
29 this->lpszName = (LPSTR)malloc(strlen(lpszName)+1);
30 if(!this->lpszName) {
31 DebugInt3();
32 }
33 strcpy(this->lpszName, lpszName);
34 this->lpSecurityAttributes = lpSecurityAttributes;
35 lpMessage = NULL;
36 dwMessageCount = 0;
37
38 this->nMaxMessageSize = nMaxMessageSize;
39 this->lReadTimeout = lReadTimeout;
40 this->fServer = fServer;
41 this->hPipe = hPipe;
42}
43
44HMMailSlotInfo::~HMMailSlotInfo()
45{
46 if(lpszName) free(lpszName);
47 if(hPipe) CloseHandle(hPipe);
48}
49
50
51HMMailslotClass::HMMailslotClass(LPCSTR lpDeviceName) : HMDeviceHandler(lpDeviceName)
52{
53 HMDeviceRegisterEx("\\\\.\\MAILSLOT", this, NULL);
54}
55
56/*****************************************************************************
57 * Name : HMMailslotClass::FindDevice
58 * Purpose : Checks if lpDeviceName belongs to this device class
59 * Parameters: LPCSTR lpClassDevName
60 * LPCSTR lpDeviceName
61 * int namelength
62 * Variables :
63 * Result : checks if name is for a drive of physical disk
64 * Remark :
65 * Status :
66 *
67 * Author : SvL
68 *****************************************************************************/
69BOOL HMMailslotClass::FindDevice(LPCSTR lpClassDevName, LPCSTR lpDeviceName, int namelength)
70{
71 //\\*\mailslot\ length 13
72 if((lstrncmpiA(lpDeviceName, "\\\\*\\mailslot\\", 13) == 0))
73 {
74 return TRUE;
75 }
76 if((lstrncmpiA(lpDeviceName, "\\\\.\\mailslot\\", 13) == 0))
77 {
78 return TRUE;
79 }
80 return FALSE;
81}
82
83/*****************************************************************************
84 * Name : HANDLE WIN32API CreateMailslotA
85 * Purpose : The CreateMailslot function creates a mailslot with the specified
86 * name and returns a handle that a mailslot server can use to
87 * perform operations on the mailslot. The mailslot is local to the
88 * computer that creates it. An error occurs if a mailslot with
89 * the specified name already exists.
90 * Parameters: LPCSTR lpName pointer to string for mailslot name
91 * DWORD nMaxMessageSize maximum message size
92 * DWORD lReadTimeout milliseconds before read time-out
93 * LPSECURITY_ATTRIBUTES lpSecurityAttributes pointer to security structure
94 * Variables :
95 * Result : If the function succeeds, the return value is a handle to
96 * the mailslot, for use in server mailslot operations.
97 * If the function fails, the return value is INVALID_HANDLE_VALUE.
98 * Remark :
99 * Status : UNTESTED STUB
100 *
101 * Author : SvL
102 *****************************************************************************/
103
104BOOL HMMailslotClass::CreateMailslotA(PHMHANDLEDATA pHMHandleData,
105 LPCSTR lpName, DWORD nMaxMessageSize,
106 DWORD lReadTimeout,
107 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
108{
109 HMMailSlotInfo *mailslot;
110 HANDLE hPipe;
111
112 dprintf(("KERNEL32: CreateMailslotA(%s,%08x,%08x,%08x) partially implemented",
113 lpName, nMaxMessageSize, lReadTimeout, lpSecurityAttributes));
114
115
116 pHMHandleData->dwUserData = 0;
117
118 if(lpName == NULL) {
119 SetLastError(ERROR_PATH_NOT_FOUND);
120 return FALSE;
121 }
122
123 char *pipename = (char *)alloca(strlen(lpName)+16);
124 if(pipename == NULL) {
125 DebugInt3();
126 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
127 return FALSE;
128 }
129 strcpy(pipename, "\\\\.\\pipe\\");
130 strcat(pipename, lpName);
131 //TODO: lookup name and fail if exists
132 hPipe = CreateNamedPipeA(pipename, PIPE_ACCESS_INBOUND,
133 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT,
134 PIPE_UNLIMITED_INSTANCES, MAILSLOT_SIZE,
135 (nMaxMessageSize) ? nMaxMessageSize : MAILSLOT_SIZE,
136 lReadTimeout, lpSecurityAttributes);
137
138 if(hPipe == INVALID_HANDLE_VALUE) {
139 dprintf(("CreateMailslotA: unable to create pipe %s", pipename));
140 return FALSE;
141 }
142 ::ConnectNamedPipe(hPipe, NULL);
143 SetLastError(0);
144 if(lReadTimeout == MAILSLOT_WAIT_FOREVER) {
145 DWORD mode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
146 ::SetNamedPipeHandleState(hPipe, &mode, NULL, NULL);
147 }
148 else
149 if(lReadTimeout != 0) {
150 dprintf(("WARNING: timeout %x not supported", lReadTimeout));
151 }
152 mailslot = new HMMailSlotInfo(lpName, hPipe, nMaxMessageSize, lReadTimeout, TRUE, lpSecurityAttributes);
153 if(mailslot == NULL) {
154 DebugInt3();
155 return FALSE;
156 }
157 pHMHandleData->dwUserData = (DWORD)mailslot;
158 return TRUE;
159}
160
161/*****************************************************************************
162 * Name : DWORD HMMailslotClass::CreateFile
163 * Purpose : this is called from the handle manager if a CreateFile() is
164 * performed on a handle
165 * Parameters: LPCSTR lpFileName name of the file / device
166 * PHMHANDLEDATA pHMHandleData data of the NEW handle
167 * PVOID lpSecurityAttributes ignored
168 * PHMHANDLEDATA pHMHandleDataTemplate data of the template handle
169 * Variables :
170 * Result :
171 * Remark :
172 * Status : NO_ERROR - API succeeded
173 * other - what is to be set in SetLastError
174 *
175 * Author : SvL
176 *****************************************************************************/
177
178DWORD HMMailslotClass::CreateFile (LPCSTR lpFileName,
179 PHMHANDLEDATA pHMHandleData,
180 PVOID lpSecurityAttributes,
181 PHMHANDLEDATA pHMHandleDataTemplate)
182{
183 HMMailSlotInfo *mailslot;
184 HANDLE hPipe;
185
186 dprintf(("HMMailslotClass::CreateFile: %s", lpFileName));
187
188 pHMHandleData->dwUserData = 0;
189
190 char *pipename = (char *)alloca(strlen(lpFileName)+16);
191 if(pipename == NULL) {
192 DebugInt3();
193 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
194 return FALSE;
195 }
196 strcpy(pipename, "\\\\.\\pipe\\");
197 strcat(pipename, lpFileName);
198
199tryagain:
200 hPipe = ::CreateFileA(pipename, pHMHandleData->dwAccess,
201 pHMHandleData->dwShare, (LPSECURITY_ATTRIBUTES)lpSecurityAttributes,
202 pHMHandleData->dwCreation,
203 pHMHandleData->dwFlags, 0);
204
205 if(hPipe == INVALID_HANDLE_VALUE) {
206 if(pipename[11] == '*') {
207 dprintf(("pipename with asterix not supported; connect only to one mailslot"));
208 pipename[11] = '.';
209 goto tryagain;
210 }
211 dprintf(("CreateMailslotA: unable to create pipe %s", pipename));
212 return GetLastError();
213 }
214 //todo: lookup name and fail if exists
215 mailslot = new HMMailSlotInfo(lpFileName, hPipe, -1, 0, FALSE, (LPSECURITY_ATTRIBUTES)lpSecurityAttributes);
216 if(mailslot == NULL) {
217 DebugInt3();
218 return ERROR_NOT_ENOUGH_MEMORY;
219 }
220 pHMHandleData->dwUserData = (DWORD)mailslot;
221 return NO_ERROR;
222}
223/*****************************************************************************
224 * Name : DWORD HMMailslotClass::CloseHandle
225 * Purpose : close the handle
226 * Parameters: PHMHANDLEDATA pHMHandleData
227 * Variables :
228 * Result : API returncode
229 * Remark :
230 * Status :
231 *
232 * Author : SvL
233 *****************************************************************************/
234
235BOOL HMMailslotClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
236{
237 HMMailSlotInfo *mailslot = (HMMailSlotInfo *)pHMHandleData->dwUserData;
238
239 dprintf(("KERNEL32: HMMailslotClass::CloseHandle(%08x)", pHMHandleData->hHMHandle));
240
241 if(mailslot) {
242 delete mailslot;
243 }
244 return TRUE;
245}
246
247/*****************************************************************************
248 * Name : BOOL GetMailslotInfo
249 * Purpose : The GetMailslotInfo function retrieves information about the
250 * specified mailslot.
251 * Parameters: HANDLE hMailslot mailslot handle
252 * LPDWORD lpMaxMessageSize address of maximum message size
253 * LPDWORD lpNextSize address of size of next message
254 * LPDWORD lpMessageCount address of number of messages
255 * LPDWORD lpReadTimeout address of read time-out
256 * Variables :
257 * Result : TRUE / FALSE
258 * Remark :
259 * Status : UNTESTED STUB
260 *
261 * Author : SvL
262 *****************************************************************************/
263
264BOOL HMMailslotClass::GetMailslotInfo(PHMHANDLEDATA pHMHandleData,
265 LPDWORD lpMaxMessageSize,
266 LPDWORD lpNextSize,
267 LPDWORD lpMessageCount,
268 LPDWORD lpReadTimeout)
269{
270 DWORD bytesread, bytesavail, msgsize;
271 HMMailSlotInfo *mailslot = (HMMailSlotInfo *)pHMHandleData->dwUserData;
272
273 dprintf(("KERNEL32: GetMailslotInfo(%08xh,%08xh,%08xh,%08xh,%08xh) partially implemented",
274 pHMHandleData->hHMHandle,
275 lpMaxMessageSize,
276 lpNextSize,
277 lpMessageCount,
278 lpReadTimeout));
279
280 if(mailslot == NULL) {
281 DebugInt3();
282 return FALSE;
283 }
284 if(mailslot->fServer == FALSE) {
285 dprintf(("GetMailslotInfo not allowed with client handle"));
286 SetLastError(ERROR_INVALID_FUNCTION);
287 return FALSE;
288 }
289 if(::PeekNamedPipe(mailslot->hPipe, NULL, 0, &bytesread, &bytesavail, &msgsize) == FALSE) {
290 dprintf(("ERROR: GetMailslotInfo: PeekNamedPipe failed!"));
291 return FALSE;
292 }
293 if(lpMaxMessageSize) *lpMaxMessageSize = mailslot->nMaxMessageSize;
294 if(lpReadTimeout) *lpReadTimeout = mailslot->lReadTimeout;
295
296 //TODO: get correct number of messages!
297 if(bytesavail) {
298 if(lpNextSize) *lpNextSize = msgsize;
299 if(lpMessageCount) *lpMessageCount = 1;
300 }
301 else {
302 if(lpNextSize) *lpNextSize = 0;
303 if(lpMessageCount) *lpMessageCount = 0;
304 }
305 return TRUE;
306}
307
308/*****************************************************************************
309 * Name : BOOL SetMailslotInfo
310 * Purpose : The SetMailslotInfo function sets the time-out value used by the
311 * specified mailslot for a read operation.
312 * Parameters: HANDLE hObject handle to a mailslot object
313 * DWORD dwReadTimeout read time-out
314 * Variables :
315 * Result : TRUE / FALSE
316 * Remark :
317 * Status : UNTESTED STUB
318 *
319 * Author : SvL
320 *****************************************************************************/
321BOOL HMMailslotClass::SetMailslotInfo(PHMHANDLEDATA pHMHandleData,
322 DWORD dwReadTimeout)
323{
324 HMMailSlotInfo *mailslot = (HMMailSlotInfo *)pHMHandleData->dwUserData;
325
326 dprintf(("KERNEL32: SetMailslotInfo(%08xh,%08xh) partially implemented",
327 pHMHandleData->hHMHandle, dwReadTimeout));
328
329 if(mailslot == NULL) {
330 DebugInt3();
331 return FALSE;
332 }
333 if(mailslot->fServer == FALSE) {
334 dprintf(("SetMailslotInfo not allowed with client handle"));
335 SetLastError(ERROR_INVALID_FUNCTION);
336 return FALSE;
337 }
338 mailslot->lReadTimeout = dwReadTimeout;
339 return(FALSE);
340}
341
342/*****************************************************************************
343 * Name : BOOL HMMailslotClass::ReadFile
344 * Purpose : read data from handle / device
345 * Parameters: PHMHANDLEDATA pHMHandleData,
346 * LPCVOID lpBuffer,
347 * DWORD nNumberOfBytesToRead,
348 * LPDWORD lpNumberOfBytesRead,
349 * LPOVERLAPPED lpOverlapped
350 * Variables :
351 * Result : Boolean
352 * Remark :
353 * Status :
354 *
355 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
356 *****************************************************************************/
357
358BOOL HMMailslotClass::ReadFile(PHMHANDLEDATA pHMHandleData,
359 LPCVOID lpBuffer,
360 DWORD nNumberOfBytesToRead,
361 LPDWORD lpNumberOfBytesRead,
362 LPOVERLAPPED lpOverlapped)
363{
364 HMMailSlotInfo *mailslot = (HMMailSlotInfo *)pHMHandleData->dwUserData;
365 dprintf(("KERNEL32: HMMailslotClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)",
366 lpHMDeviceName, pHMHandleData, lpBuffer, nNumberOfBytesToRead,
367 lpNumberOfBytesRead, lpOverlapped));
368
369 if(lpNumberOfBytesRead)
370 *lpNumberOfBytesRead = 0;
371
372 if(mailslot == NULL) {
373 DebugInt3();
374 return FALSE;
375 }
376 if(mailslot->fServer == FALSE) {
377 dprintf(("ReadFile not allowed with client handle"));
378 SetLastError(ERROR_INVALID_FUNCTION); //TODO: right error?
379 return FALSE;
380 }
381 return ::ReadFile(mailslot->hPipe, (LPVOID)lpBuffer, nNumberOfBytesToRead,
382 lpNumberOfBytesRead, lpOverlapped);
383}
384
385/*****************************************************************************
386 * Name : BOOL ReadFileEx
387 * Purpose : The ReadFileEx function reads data from a file asynchronously.
388 * It is designed solely for asynchronous operation, unlike the
389 * ReadFile function, which is designed for both synchronous and
390 * asynchronous operation. ReadFileEx lets an application perform
391 * other processing during a file read operation.
392 * The ReadFileEx function reports its completion status asynchronously,
393 * calling a specified completion routine when reading is completed
394 * and the calling thread is in an alertable wait state.
395 * Parameters: HANDLE hFile handle of file to read
396 * LPVOID lpBuffer address of buffer
397 * DWORD nNumberOfBytesToRead number of bytes to read
398 * LPOVERLAPPED lpOverlapped address of offset
399 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine
400 * Variables :
401 * Result : TRUE / FALSE
402 * Remark :
403 * Status : UNTESTED STUB
404 *
405 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
406 *****************************************************************************/
407BOOL HMMailslotClass::ReadFileEx(PHMHANDLEDATA pHMHandleData,
408 LPVOID lpBuffer,
409 DWORD nNumberOfBytesToRead,
410 LPOVERLAPPED lpOverlapped,
411 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
412{
413 HMMailSlotInfo *mailslot = (HMMailSlotInfo *)pHMHandleData->dwUserData;
414
415 dprintf(("HMMailslotClass::ReadFileEx(%08xh,%08xh,%08xh,%08xh,%08xh)", pHMHandleData->hHMHandle,
416 lpBuffer, nNumberOfBytesToRead, lpOverlapped, lpCompletionRoutine));
417
418 if(mailslot == NULL) {
419 DebugInt3();
420 return FALSE;
421 }
422 if(mailslot->fServer == FALSE) {
423 dprintf(("ReadFile not allowed with client handle"));
424 SetLastError(ERROR_INVALID_FUNCTION); //TODO: right error?
425 return FALSE;
426 }
427 return ::ReadFileEx(mailslot->hPipe, lpBuffer, nNumberOfBytesToRead, lpOverlapped, lpCompletionRoutine);
428}
429
430
431/*****************************************************************************
432 * Name : BOOL HMMailslotClass::WriteFile
433 * Purpose : write data to handle / device
434 * Parameters: PHMHANDLEDATA pHMHandleData,
435 * LPCVOID lpBuffer,
436 * DWORD nNumberOfBytesToWrite,
437 * LPDWORD lpNumberOfBytesWritten,
438 * LPOVERLAPPED lpOverlapped
439 * Variables :
440 * Result : Boolean
441 * Remark :
442 * Status :
443 *
444 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
445 *****************************************************************************/
446
447BOOL HMMailslotClass::WriteFile(PHMHANDLEDATA pHMHandleData,
448 LPCVOID lpBuffer,
449 DWORD nNumberOfBytesToWrite,
450 LPDWORD lpNumberOfBytesWritten,
451 LPOVERLAPPED lpOverlapped)
452{
453 HMMailSlotInfo *mailslot = (HMMailSlotInfo *)pHMHandleData->dwUserData;
454
455 dprintf(("KERNEL32: HMMailslotClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x)",
456 lpHMDeviceName, pHMHandleData, lpBuffer, nNumberOfBytesToWrite,
457 lpNumberOfBytesWritten, lpOverlapped));
458
459 if(lpNumberOfBytesWritten)
460 *lpNumberOfBytesWritten = 0;
461
462 if(mailslot == NULL) {
463 DebugInt3();
464 return FALSE;
465 }
466 if(mailslot->fServer == TRUE) {
467 dprintf(("ReadFile not allowed with server handle"));
468 SetLastError(ERROR_INVALID_FUNCTION); //TODO: right error?
469 return FALSE;
470 }
471
472 return ::WriteFile(mailslot->hPipe, lpBuffer, nNumberOfBytesToWrite,
473 lpNumberOfBytesWritten, lpOverlapped);
474}
475
476/*****************************************************************************
477 * Name : BOOL WriteFileEx
478 * Purpose : The WriteFileEx function writes data to a file. It is designed
479 * solely for asynchronous operation, unlike WriteFile, which is
480 * designed for both synchronous and asynchronous operation.
481 * WriteFileEx reports its completion status asynchronously,
482 * calling a specified completion routine when writing is completed
483 * and the calling thread is in an alertable wait state.
484 * Parameters: HANDLE hFile handle of file to write
485 * LPVOID lpBuffer address of buffer
486 * DWORD nNumberOfBytesToRead number of bytes to write
487 * LPOVERLAPPED lpOverlapped address of offset
488 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine
489 * Variables :
490 * Result : TRUE / FALSE
491 * Remark :
492 * Status : UNTESTED STUB
493 *
494 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
495 *****************************************************************************/
496
497BOOL HMMailslotClass::WriteFileEx(PHMHANDLEDATA pHMHandleData,
498 LPVOID lpBuffer,
499 DWORD nNumberOfBytesToWrite,
500 LPOVERLAPPED lpOverlapped,
501 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
502{
503 HMMailSlotInfo *mailslot = (HMMailSlotInfo *)pHMHandleData->dwUserData;
504
505 dprintf(("HMMailslotClass::WriteFileEx(%08xh,%08xh,%08xh,%08xh,%08xh)",
506 pHMHandleData->hHMHandle, lpBuffer, nNumberOfBytesToWrite,
507 lpOverlapped,lpCompletionRoutine));
508
509 if(mailslot == NULL) {
510 DebugInt3();
511 return FALSE;
512 }
513 if(mailslot->fServer == TRUE) {
514 dprintf(("ReadFile not allowed with server handle"));
515 SetLastError(ERROR_INVALID_FUNCTION); //TODO: right error?
516 return FALSE;
517 }
518 return ::WriteFileEx(mailslot->hPipe, lpBuffer, nNumberOfBytesToWrite,lpOverlapped,lpCompletionRoutine);
519}
Note: See TracBrowser for help on using the repository browser.