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

Last change on this file since 7474 was 7474, checked in by phaller, 24 years ago

Fixes in HandleManager and Device Handlers

File size: 19.4 KB
Line 
1/* $Id: hmmailslot.cpp,v 1.4 2001-11-28 23:33:36 phaller 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 (HANDLE hHandle,
179 LPCSTR lpFileName,
180 PHMHANDLEDATA pHMHandleData,
181 PVOID lpSecurityAttributes,
182 PHMHANDLEDATA pHMHandleDataTemplate)
183{
184 HMMailSlotInfo *mailslot;
185 HANDLE hPipe;
186
187 dprintf(("HMMailslotClass::CreateFile: %s", lpFileName));
188
189 pHMHandleData->dwUserData = 0;
190
191 char *pipename = (char *)alloca(strlen(lpFileName)+16);
192 if(pipename == NULL)
193 {
194 DebugInt3();
195 return ERROR_NOT_ENOUGH_MEMORY;
196 }
197 strcpy(pipename, "\\\\.\\pipe\\");
198 strcat(pipename, lpFileName);
199
200tryagain:
201 hPipe = ::CreateFileA(pipename, pHMHandleData->dwAccess,
202 pHMHandleData->dwShare, (LPSECURITY_ATTRIBUTES)lpSecurityAttributes,
203 pHMHandleData->dwCreation,
204 pHMHandleData->dwFlags, 0);
205
206 if(hPipe == INVALID_HANDLE_VALUE) {
207 if(pipename[11] == '*') {
208 dprintf(("pipename with asterix not supported; connect only to one mailslot"));
209 pipename[11] = '.';
210 goto tryagain;
211 }
212 dprintf(("CreateMailslotA: unable to create pipe %s", pipename));
213 return GetLastError();
214 }
215 //todo: lookup name and fail if exists
216 mailslot = new HMMailSlotInfo(lpFileName, hPipe, -1, 0, FALSE, (LPSECURITY_ATTRIBUTES)lpSecurityAttributes);
217 if(mailslot == NULL)
218 {
219 DebugInt3();
220 return ERROR_NOT_ENOUGH_MEMORY;
221 }
222 pHMHandleData->dwUserData = (DWORD)mailslot;
223 return NO_ERROR;
224}
225/*****************************************************************************
226 * Name : DWORD HMMailslotClass::CloseHandle
227 * Purpose : close the handle
228 * Parameters: PHMHANDLEDATA pHMHandleData
229 * Variables :
230 * Result : API returncode
231 * Remark :
232 * Status :
233 *
234 * Author : SvL
235 *****************************************************************************/
236
237BOOL HMMailslotClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
238{
239 HMMailSlotInfo *mailslot = (HMMailSlotInfo *)pHMHandleData->dwUserData;
240
241 dprintf(("KERNEL32: HMMailslotClass::CloseHandle(%08x)", pHMHandleData->hHMHandle));
242
243 if(mailslot) {
244 delete mailslot;
245 }
246 return TRUE;
247}
248
249/*****************************************************************************
250 * Name : BOOL GetMailslotInfo
251 * Purpose : The GetMailslotInfo function retrieves information about the
252 * specified mailslot.
253 * Parameters: HANDLE hMailslot mailslot handle
254 * LPDWORD lpMaxMessageSize address of maximum message size
255 * LPDWORD lpNextSize address of size of next message
256 * LPDWORD lpMessageCount address of number of messages
257 * LPDWORD lpReadTimeout address of read time-out
258 * Variables :
259 * Result : TRUE / FALSE
260 * Remark :
261 * Status : UNTESTED STUB
262 *
263 * Author : SvL
264 *****************************************************************************/
265
266BOOL HMMailslotClass::GetMailslotInfo(PHMHANDLEDATA pHMHandleData,
267 LPDWORD lpMaxMessageSize,
268 LPDWORD lpNextSize,
269 LPDWORD lpMessageCount,
270 LPDWORD lpReadTimeout)
271{
272 DWORD bytesread, bytesavail, msgsize;
273 HMMailSlotInfo *mailslot = (HMMailSlotInfo *)pHMHandleData->dwUserData;
274
275 dprintf(("KERNEL32: GetMailslotInfo(%08xh,%08xh,%08xh,%08xh,%08xh) partially implemented",
276 pHMHandleData->hHMHandle,
277 lpMaxMessageSize,
278 lpNextSize,
279 lpMessageCount,
280 lpReadTimeout));
281
282 if(mailslot == NULL) {
283 DebugInt3();
284 return FALSE;
285 }
286 if(mailslot->fServer == FALSE) {
287 dprintf(("GetMailslotInfo not allowed with client handle"));
288 SetLastError(ERROR_INVALID_FUNCTION);
289 return FALSE;
290 }
291 if(::PeekNamedPipe(mailslot->hPipe, NULL, 0, &bytesread, &bytesavail, &msgsize) == FALSE) {
292 dprintf(("ERROR: GetMailslotInfo: PeekNamedPipe failed!"));
293 return FALSE;
294 }
295 if(lpMaxMessageSize) *lpMaxMessageSize = mailslot->nMaxMessageSize;
296 if(lpReadTimeout) *lpReadTimeout = mailslot->lReadTimeout;
297
298 //TODO: get correct number of messages!
299 if(bytesavail) {
300 if(lpNextSize) *lpNextSize = msgsize;
301 if(lpMessageCount) *lpMessageCount = 1;
302 }
303 else {
304 if(lpNextSize) *lpNextSize = 0;
305 if(lpMessageCount) *lpMessageCount = 0;
306 }
307 return TRUE;
308}
309
310/*****************************************************************************
311 * Name : BOOL SetMailslotInfo
312 * Purpose : The SetMailslotInfo function sets the time-out value used by the
313 * specified mailslot for a read operation.
314 * Parameters: HANDLE hObject handle to a mailslot object
315 * DWORD dwReadTimeout read time-out
316 * Variables :
317 * Result : TRUE / FALSE
318 * Remark :
319 * Status : UNTESTED STUB
320 *
321 * Author : SvL
322 *****************************************************************************/
323BOOL HMMailslotClass::SetMailslotInfo(PHMHANDLEDATA pHMHandleData,
324 DWORD dwReadTimeout)
325{
326 HMMailSlotInfo *mailslot = (HMMailSlotInfo *)pHMHandleData->dwUserData;
327
328 dprintf(("KERNEL32: SetMailslotInfo(%08xh,%08xh) partially implemented",
329 pHMHandleData->hHMHandle, dwReadTimeout));
330
331 if(mailslot == NULL) {
332 DebugInt3();
333 return FALSE;
334 }
335 if(mailslot->fServer == FALSE) {
336 dprintf(("SetMailslotInfo not allowed with client handle"));
337 SetLastError(ERROR_INVALID_FUNCTION);
338 return FALSE;
339 }
340 mailslot->lReadTimeout = dwReadTimeout;
341 return(FALSE);
342}
343
344/*****************************************************************************
345 * Name : BOOL HMMailslotClass::ReadFile
346 * Purpose : read data from handle / device
347 * Parameters: PHMHANDLEDATA pHMHandleData,
348 * LPCVOID lpBuffer,
349 * DWORD nNumberOfBytesToRead,
350 * LPDWORD lpNumberOfBytesRead,
351 * LPOVERLAPPED lpOverlapped
352 * Variables :
353 * Result : Boolean
354 * Remark :
355 * Status :
356 *
357 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
358 *****************************************************************************/
359
360BOOL HMMailslotClass::ReadFile(PHMHANDLEDATA pHMHandleData,
361 LPCVOID lpBuffer,
362 DWORD nNumberOfBytesToRead,
363 LPDWORD lpNumberOfBytesRead,
364 LPOVERLAPPED lpOverlapped)
365{
366 HMMailSlotInfo *mailslot = (HMMailSlotInfo *)pHMHandleData->dwUserData;
367 dprintf(("KERNEL32: HMMailslotClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)",
368 lpHMDeviceName, pHMHandleData, lpBuffer, nNumberOfBytesToRead,
369 lpNumberOfBytesRead, lpOverlapped));
370
371 if(lpNumberOfBytesRead)
372 *lpNumberOfBytesRead = 0;
373
374 if(mailslot == NULL) {
375 DebugInt3();
376 return FALSE;
377 }
378 if(mailslot->fServer == FALSE) {
379 dprintf(("ReadFile not allowed with client handle"));
380 SetLastError(ERROR_INVALID_FUNCTION); //TODO: right error?
381 return FALSE;
382 }
383 return ::ReadFile(mailslot->hPipe, (LPVOID)lpBuffer, nNumberOfBytesToRead,
384 lpNumberOfBytesRead, lpOverlapped);
385}
386
387/*****************************************************************************
388 * Name : BOOL ReadFileEx
389 * Purpose : The ReadFileEx function reads data from a file asynchronously.
390 * It is designed solely for asynchronous operation, unlike the
391 * ReadFile function, which is designed for both synchronous and
392 * asynchronous operation. ReadFileEx lets an application perform
393 * other processing during a file read operation.
394 * The ReadFileEx function reports its completion status asynchronously,
395 * calling a specified completion routine when reading is completed
396 * and the calling thread is in an alertable wait state.
397 * Parameters: HANDLE hFile handle of file to read
398 * LPVOID lpBuffer address of buffer
399 * DWORD nNumberOfBytesToRead number of bytes to read
400 * LPOVERLAPPED lpOverlapped address of offset
401 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine
402 * Variables :
403 * Result : TRUE / FALSE
404 * Remark :
405 * Status : UNTESTED STUB
406 *
407 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
408 *****************************************************************************/
409BOOL HMMailslotClass::ReadFileEx(PHMHANDLEDATA pHMHandleData,
410 LPVOID lpBuffer,
411 DWORD nNumberOfBytesToRead,
412 LPOVERLAPPED lpOverlapped,
413 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
414{
415 HMMailSlotInfo *mailslot = (HMMailSlotInfo *)pHMHandleData->dwUserData;
416
417 dprintf(("HMMailslotClass::ReadFileEx(%08xh,%08xh,%08xh,%08xh,%08xh)", pHMHandleData->hHMHandle,
418 lpBuffer, nNumberOfBytesToRead, lpOverlapped, lpCompletionRoutine));
419
420 if(mailslot == NULL) {
421 DebugInt3();
422 return FALSE;
423 }
424 if(mailslot->fServer == FALSE) {
425 dprintf(("ReadFile not allowed with client handle"));
426 SetLastError(ERROR_INVALID_FUNCTION); //TODO: right error?
427 return FALSE;
428 }
429 return ::ReadFileEx(mailslot->hPipe, lpBuffer, nNumberOfBytesToRead, lpOverlapped, lpCompletionRoutine);
430}
431
432
433/*****************************************************************************
434 * Name : BOOL HMMailslotClass::WriteFile
435 * Purpose : write data to handle / device
436 * Parameters: PHMHANDLEDATA pHMHandleData,
437 * LPCVOID lpBuffer,
438 * DWORD nNumberOfBytesToWrite,
439 * LPDWORD lpNumberOfBytesWritten,
440 * LPOVERLAPPED lpOverlapped
441 * Variables :
442 * Result : Boolean
443 * Remark :
444 * Status :
445 *
446 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
447 *****************************************************************************/
448
449BOOL HMMailslotClass::WriteFile(PHMHANDLEDATA pHMHandleData,
450 LPCVOID lpBuffer,
451 DWORD nNumberOfBytesToWrite,
452 LPDWORD lpNumberOfBytesWritten,
453 LPOVERLAPPED lpOverlapped)
454{
455 HMMailSlotInfo *mailslot = (HMMailSlotInfo *)pHMHandleData->dwUserData;
456
457 dprintf(("KERNEL32: HMMailslotClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x)",
458 lpHMDeviceName, pHMHandleData, lpBuffer, nNumberOfBytesToWrite,
459 lpNumberOfBytesWritten, lpOverlapped));
460
461 if(lpNumberOfBytesWritten)
462 *lpNumberOfBytesWritten = 0;
463
464 if(mailslot == NULL) {
465 DebugInt3();
466 return FALSE;
467 }
468 if(mailslot->fServer == TRUE) {
469 dprintf(("ReadFile not allowed with server handle"));
470 SetLastError(ERROR_INVALID_FUNCTION); //TODO: right error?
471 return FALSE;
472 }
473
474 return ::WriteFile(mailslot->hPipe, lpBuffer, nNumberOfBytesToWrite,
475 lpNumberOfBytesWritten, lpOverlapped);
476}
477
478/*****************************************************************************
479 * Name : BOOL WriteFileEx
480 * Purpose : The WriteFileEx function writes data to a file. It is designed
481 * solely for asynchronous operation, unlike WriteFile, which is
482 * designed for both synchronous and asynchronous operation.
483 * WriteFileEx reports its completion status asynchronously,
484 * calling a specified completion routine when writing is completed
485 * and the calling thread is in an alertable wait state.
486 * Parameters: HANDLE hFile handle of file to write
487 * LPVOID lpBuffer address of buffer
488 * DWORD nNumberOfBytesToRead number of bytes to write
489 * LPOVERLAPPED lpOverlapped address of offset
490 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine
491 * Variables :
492 * Result : TRUE / FALSE
493 * Remark :
494 * Status : UNTESTED STUB
495 *
496 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
497 *****************************************************************************/
498
499BOOL HMMailslotClass::WriteFileEx(PHMHANDLEDATA pHMHandleData,
500 LPVOID lpBuffer,
501 DWORD nNumberOfBytesToWrite,
502 LPOVERLAPPED lpOverlapped,
503 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
504{
505 HMMailSlotInfo *mailslot = (HMMailSlotInfo *)pHMHandleData->dwUserData;
506
507 dprintf(("HMMailslotClass::WriteFileEx(%08xh,%08xh,%08xh,%08xh,%08xh)",
508 pHMHandleData->hHMHandle, lpBuffer, nNumberOfBytesToWrite,
509 lpOverlapped,lpCompletionRoutine));
510
511 if(mailslot == NULL) {
512 DebugInt3();
513 return FALSE;
514 }
515 if(mailslot->fServer == TRUE) {
516 dprintf(("ReadFile not allowed with server handle"));
517 SetLastError(ERROR_INVALID_FUNCTION); //TODO: right error?
518 return FALSE;
519 }
520 return ::WriteFileEx(mailslot->hPipe, lpBuffer, nNumberOfBytesToWrite,lpOverlapped,lpCompletionRoutine);
521}
Note: See TracBrowser for help on using the repository browser.