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

Last change on this file since 22015 was 7550, checked in by sandervl, 24 years ago

overlapped io updates

File size: 15.8 KB
Line 
1/* $Id: hmmailslot.cpp,v 1.7 2001-12-05 18:06:01 sandervl 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 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
364{
365 HMMailSlotInfo *mailslot = (HMMailSlotInfo *)pHMHandleData->dwUserData;
366 dprintf(("KERNEL32: HMMailslotClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)",
367 lpHMDeviceName, pHMHandleData, lpBuffer, nNumberOfBytesToRead,
368 lpNumberOfBytesRead, lpOverlapped));
369
370 if(lpCompletionRoutine) {
371 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
372 }
373
374 if(lpNumberOfBytesRead)
375 *lpNumberOfBytesRead = 0;
376
377 if(mailslot == NULL) {
378 DebugInt3();
379 return FALSE;
380 }
381 if(mailslot->fServer == FALSE) {
382 dprintf(("ReadFile not allowed with client handle"));
383 SetLastError(ERROR_INVALID_FUNCTION); //TODO: right error?
384 return FALSE;
385 }
386 if(lpCompletionRoutine) {
387 return ::ReadFileEx(mailslot->hPipe, (LPVOID)lpBuffer, nNumberOfBytesToRead,
388 lpOverlapped, lpCompletionRoutine);
389 }
390 else return ::ReadFile(mailslot->hPipe, (LPVOID)lpBuffer, nNumberOfBytesToRead,
391 lpNumberOfBytesRead, lpOverlapped);
392}
393
394/*****************************************************************************
395 * Name : BOOL HMMailslotClass::WriteFile
396 * Purpose : write data to handle / device
397 * Parameters: PHMHANDLEDATA pHMHandleData,
398 * LPCVOID lpBuffer,
399 * DWORD nNumberOfBytesToWrite,
400 * LPDWORD lpNumberOfBytesWritten,
401 * LPOVERLAPPED lpOverlapped
402 * Variables :
403 * Result : Boolean
404 * Remark :
405 * Status :
406 *
407 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
408 *****************************************************************************/
409
410BOOL HMMailslotClass::WriteFile(PHMHANDLEDATA pHMHandleData,
411 LPCVOID lpBuffer,
412 DWORD nNumberOfBytesToWrite,
413 LPDWORD lpNumberOfBytesWritten,
414 LPOVERLAPPED lpOverlapped,
415 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
416{
417 HMMailSlotInfo *mailslot = (HMMailSlotInfo *)pHMHandleData->dwUserData;
418
419 dprintf(("KERNEL32: HMMailslotClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x)",
420 lpHMDeviceName, pHMHandleData, lpBuffer, nNumberOfBytesToWrite,
421 lpNumberOfBytesWritten, lpOverlapped));
422
423 if(lpCompletionRoutine) {
424 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
425 }
426
427 if(lpNumberOfBytesWritten)
428 *lpNumberOfBytesWritten = 0;
429
430 if(mailslot == NULL) {
431 DebugInt3();
432 return FALSE;
433 }
434 if(mailslot->fServer == TRUE) {
435 dprintf(("ReadFile not allowed with server handle"));
436 SetLastError(ERROR_INVALID_FUNCTION); //TODO: right error?
437 return FALSE;
438 }
439
440 if(lpCompletionRoutine) {
441 return ::WriteFileEx(mailslot->hPipe, lpBuffer, nNumberOfBytesToWrite,
442 lpOverlapped, lpCompletionRoutine);
443 }
444 else return ::WriteFile(mailslot->hPipe, lpBuffer, nNumberOfBytesToWrite,
445 lpNumberOfBytesWritten, lpOverlapped);
446}
447
Note: See TracBrowser for help on using the repository browser.