changeset 557:1a210e2f214b

Added a bunch of support routines I now own due to the settlement agreement with F/X. Shared memory and named event semaphores in particular.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Sat, 17 Apr 2004 05:38:09 +0000
parents f4093dce8155
children 05060ce4d6ae
files compat.c compat.h dw.def dw.h dwcompat.def dwcompatw.def dww.def gtk/dw.c os2/dw.c win/dw.c
diffstat 10 files changed, 931 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/compat.c	Mon Apr 12 03:52:15 2004 +0000
+++ b/compat.c	Sat Apr 17 05:38:09 2004 +0000
@@ -713,6 +713,85 @@
 	return fseek(stream, offset, whence);
 }
 
+void API nice_strformat(char *dest, long double val, int dec)
+{
+	char formatbuf[10];
+	char format = 0;
+	double printval;
+
+	/* 1024 ^ 3 = Gigabytes */
+	if(val >= 1073741824L)
+	{
+		printval = val/(1073741824L);
+		format = 'G';
+	}
+	/* 1024 ^ 2 = Megabytes */
+	else if(val >= 1048576)
+	{
+		printval = val/(1048576);
+		format = 'M';
+	}
+	/* 1024 = Kilobytes */
+	else if(val > 1024)
+	{
+		printval = val/1024;
+		format = 'K';
+	}
+	else
+		printval = val;
+
+	/* Generate the format string */
+	sprintf(formatbuf, "%%.%df%c", dec, format);
+	/* Create the pretty value */
+	sprintf(dest, formatbuf, printval);
+}
+
+/* Update the current working directory based on the
+ * path of the executable being executed.
+ */
+void API initdir(int argc, char *argv[])
+{
+	if(argc > 0)
+	{
+		char *tmpdir = strdup(argv[0]);
+		int z, len = strlen(argv[0]);
+
+		for(z=len;z > -1;z--)
+		{
+			if(tmpdir[z] == '/')
+			{
+				tmpdir[z+1] = 0;
+				setpath(tmpdir);
+				free(tmpdir);
+				return;
+			}
+		}
+		free(tmpdir);
+	}
+}
+
+/*
+ * Sets	the current directory (and drive) information.
+ * Parameters:
+ *	 path: A buffer	containing the new path.
+ * Returns:
+ *	 -1 on error.
+ */
+int API setpath(char *path)
+{
+#if defined(__OS2__) || defined(__WIN32__)
+	if(strlen(path)	> 2)
+	{
+		if(path[1] == ':')
+		{
+			char drive = toupper(path[0]);
+			_chdrive((drive - 'A')+1);
+		}
+	}
+#endif
+	return chdir(path);
+}
+
 static int locale_number = -1, locale_count = 0;
 static char **locale_text = NULL;
 
--- a/compat.h	Mon Apr 12 03:52:15 2004 +0000
+++ b/compat.h	Sat Apr 17 05:38:09 2004 +0000
@@ -232,4 +232,7 @@
 int API fsseek(FILE *stream, long offset, int whence);
 int API locale_init(char *filename, int my_locale);
 char * API locale_string(char *default_text, int message);
+void API nice_strformat(char *dest, long double val, int dec);
+void API initdir(int argc, char *argv[]);
+int API setpath(char *path);
 #endif
--- a/dw.def	Mon Apr 12 03:52:15 2004 +0000
+++ b/dw.def	Sat Apr 17 05:38:09 2004 +0000
@@ -250,3 +250,13 @@
   dw_taskbar_insert                      @440
   dw_taskbar_delete                      @441
   
+  dw_named_memory_new                    @450
+  dw_named_memory_get                    @451
+  dw_named_memory_free                   @452
+
+  dw_named_event_new                     @460
+  dw_named_event_get                     @461
+  dw_named_event_reset                   @462
+  dw_named_event_post                    @463
+  dw_named_event_wait                    @464
+  dw_named_event_close                   @465
--- a/dw.h	Mon Apr 12 03:52:15 2004 +0000
+++ b/dw.h	Sat Apr 17 05:38:09 2004 +0000
@@ -223,6 +223,7 @@
 typedef HWND HMENUI;
 typedef HMODULE HMOD;
 typedef unsigned short UWORD;
+typedef unsigned long HSHM;
 
 extern HAB dwhab;
 extern HMQ dwhmq;
@@ -463,6 +464,7 @@
 typedef HANDLE HMTX;
 typedef HANDLE HEV;
 typedef HANDLE HMOD;
+typedef HANDLE HSHM;
 
 typedef struct _container {
 	ColorInfo cinfo;
@@ -737,6 +739,12 @@
 } *HEV;
 typedef pthread_t DWTID;
 typedef void * HMOD;
+typedef struct _dw_unix_shm {
+	int fd;
+	char *path;
+	int sid;
+	int size;
+} HSHM;
 
 typedef struct _hpixmap {
 	unsigned long width, height;
@@ -856,6 +864,14 @@
 #define DW_MENU_SEPARATOR ""
 #define DW_NOMENU 0
 
+/* Return value error codes */
+#define DW_ERROR_NONE      0
+#define DW_ERROR_GENERAL   1
+#define DW_ERROR_TIMEOUT   2
+#define DW_ERROR_NON_INIT  3
+#define DW_ERROR_NO_MEM    4
+#define DW_ERROR_INTERRUPT 5
+
 #if defined(__OS2__) || defined(__EMX__)
 #define DW_OS2_RGB(a) ((DW_RED_VALUE(a) << 16) | (DW_GREEN_VALUE(a) << 8) | DW_BLUE_VALUE(a))
 #endif
@@ -1089,5 +1105,14 @@
 void API dw_signal_disconnect_by_window(HWND window);
 void API dw_signal_disconnect_by_data(HWND window, void *data);
 void API dw_signal_disconnect_by_name(HWND window, char *signame);
+HEV API dw_named_event_new(char *name);
+HEV API dw_named_event_get(char *name);
+int API dw_named_event_reset(HEV eve);
+int API dw_named_event_post(HEV eve);
+int API dw_named_event_wait(HEV eve, unsigned long timeout);
+int API dw_named_event_close(HEV eve);
+HSHM API dw_named_memory_new(void **dest, int size, char *name);
+HSHM API dw_named_memory_get(void **dest, int size, char *name);
+int API dw_named_memory_free(HSHM handle, void *ptr);
 
 #endif
--- a/dwcompat.def	Mon Apr 12 03:52:15 2004 +0000
+++ b/dwcompat.def	Sat Apr 17 05:38:09 2004 +0000
@@ -39,3 +39,6 @@
 
   locale_init        @50
   locale_string      @51
+  
+  nice_strformat     @60
+  initdir            @61
--- a/dwcompatw.def	Mon Apr 12 03:52:15 2004 +0000
+++ b/dwcompatw.def	Sat Apr 17 05:38:09 2004 +0000
@@ -35,3 +35,6 @@
   locale_init        @50
   locale_string      @51
 
+  nice_strformat     @60
+  initdir            @61
+  setpath            @62
--- a/dww.def	Mon Apr 12 03:52:15 2004 +0000
+++ b/dww.def	Sat Apr 17 05:38:09 2004 +0000
@@ -247,3 +247,13 @@
   dw_taskbar_insert                      @440
   dw_taskbar_delete                      @441
   
+  dw_named_memory_new                    @450
+  dw_named_memory_get                    @451
+  dw_named_memory_free                   @452
+
+  dw_named_event_new                     @460
+  dw_named_event_get                     @461
+  dw_named_event_reset                   @462
+  dw_named_event_post                    @463
+  dw_named_event_wait                    @464
+  dw_named_event_close                   @465
--- a/gtk/dw.c	Mon Apr 12 03:52:15 2004 +0000
+++ b/gtk/dw.c	Sat Apr 17 05:38:09 2004 +0000
@@ -7368,6 +7368,339 @@
 	return TRUE;
 }
 
+struct _seminfo {
+	int fd;
+	int waiting;
+};
+
+static void _handle_sem(int *tmpsock)
+{
+	fd_set rd;
+	struct _seminfo *array = (struct _seminfo *)malloc(sizeof(struct _seminfo));
+	int listenfd = tmpsock[0];
+	int bytesread, connectcount = 1, maxfd, z, posted = 0;
+	char command;
+	sigset_t mask;
+
+	sigfillset(&mask); /* Mask all allowed signals */
+	pthread_sigmask(SIG_BLOCK, &mask, NULL);
+
+	/* problems */
+	if(tmpsock[1] == -1)
+	{
+		free(array);
+		return;
+	}
+
+	array[0].fd = tmpsock[1];
+	array[0].waiting = 0;
+
+	/* Free the memory allocated in dw_named_event_new. */
+	free(tmpsock);
+
+	while(1)
+	{
+		FD_ZERO(&rd);
+		FD_SET(listenfd, &rd);
+
+		maxfd = listenfd;
+
+		/* Added any connections to the named event semaphore */
+		for(z=0;z<connectcount;z++)
+		{
+			if(array[z].fd > maxfd)
+				maxfd = array[z].fd;
+
+			FD_SET(array[z].fd, &rd);
+		}
+
+		if(select(maxfd+1, &rd, NULL, NULL, NULL) == -1)
+			return;
+
+		if(FD_ISSET(listenfd, &rd))
+		{
+			struct _seminfo *newarray;
+            int newfd = accept(listenfd, 0, 0);
+
+			if(newfd > -1)
+			{
+				/* Add new connections to the set */
+				newarray = (struct _seminfo *)malloc(sizeof(struct _seminfo)*(connectcount+1));
+				memcpy(newarray, array, sizeof(struct _seminfo)*(connectcount));
+
+				newarray[connectcount].fd = newfd;
+				newarray[connectcount].waiting = 0;
+
+				connectcount++;
+
+				/* Replace old array with new one */
+				free(array);
+				array = newarray;
+			}
+		}
+
+		/* Handle any events posted to the semaphore */
+		for(z=0;z<connectcount;z++)
+		{
+			if(FD_ISSET(array[z].fd, &rd))
+			{
+				if((bytesread = read(array[z].fd, &command, 1)) < 1)
+				{
+					struct _seminfo *newarray;
+
+					/* Remove this connection from the set */
+					newarray = (struct _seminfo *)malloc(sizeof(struct _seminfo)*(connectcount-1));
+					if(!z)
+						memcpy(newarray, &array[1], sizeof(struct _seminfo)*(connectcount-1));
+					else
+					{
+						memcpy(newarray, array, sizeof(struct _seminfo)*z);
+						if(z!=(connectcount-1))
+							memcpy(&newarray[z], &array[z+1], sizeof(struct _seminfo)*(z-connectcount-1));
+					}
+					connectcount--;
+
+					/* Replace old array with new one */
+					free(array);
+					array = newarray;
+				}
+				else if(bytesread == 1)
+				{
+					switch(command)
+					{
+					case 0:
+						{
+						/* Reset */
+						posted = 0;
+						}
+						break;
+					case 1:
+						/* Post */
+						{
+							int s;
+							char tmp = (char)0;
+
+							posted = 1;
+
+							for(s=0;s<connectcount;s++)
+							{
+								/* The semaphore has been posted so
+								 * we tell all the waiting threads to
+								 * continue.
+								 */
+								if(array[s].waiting)
+									write(array[s].fd, &tmp, 1);
+							}
+						}
+						break;
+					case 2:
+						/* Wait */
+						{
+							char tmp = (char)0;
+
+							array[z].waiting = 1;
+
+							/* If we are posted exit immeditately */
+							if(posted)
+								write(array[z].fd, &tmp, 1);
+						}
+						break;
+					case 3:
+						{
+							/* Done Waiting */
+							array[z].waiting = 0;
+						}
+						break;
+					}
+				}
+			}
+		}
+
+	}
+
+}
+
+/* Using domain sockets on unix for IPC */
+/* Create a named event semaphore which can be
+ * opened from other processes.
+ * Parameters:
+ *         eve: Pointer to an event handle to receive handle.
+ *         name: Name given to semaphore which can be opened
+ *               by other processes.
+ */
+HEV dw_named_event_new(char *name)
+{
+	struct sockaddr_un un;
+	int ev, *tmpsock = (int *)malloc(sizeof(int)*2);
+	DWTID dwthread;
+
+	if(!tmpsock)
+		return DB_EVENT_NO_MEM;
+
+	tmpsock[0] = socket(AF_UNIX, SOCK_STREAM, 0);
+	ev = socket(AF_UNIX, SOCK_STREAM, 0);
+	memset(&un, 0, sizeof(un));
+	un.sun_family=AF_UNIX;
+	mkdir("/tmp/.dw", S_IWGRP|S_IWOTH);
+	strcpy(un.sun_path, "/tmp/.dw/");
+	strcat(un.sun_path, name);
+
+	/* just to be safe, this should be changed
+	 * to support multiple instances.
+	 */
+	remove(un.sun_path);
+
+	bind(tmpsock[0], (struct sockaddr *)&un, sizeof(un));
+	listen(tmpsock[0], 0);
+	connect(ev, (struct sockaddr *)&un, sizeof(un));
+	tmpsock[1] = accept(tmpsock[0], 0, 0);
+
+	if(tmpsock[0] < 0 || tmpsock[1] < 0 || ev < 0)
+	{
+		if(tmpsock[0] > -1)
+			close(tmpsock[0]);
+		if(tmpsock[1] > -1)
+			close(tmpsock[1]);
+		if(ev > -1)
+			close(ev);
+		free(tmpsock);
+		return 0;
+	}
+
+	/* Create a thread to handle this event semaphore */
+	pthread_create(&dwthread, NULL, (void *)_handle_sem, (void *)tmpsock);
+	return ev;
+}
+
+/* Open an already existing named event semaphore.
+ * Parameters:
+ *         eve: Pointer to an event handle to receive handle.
+ *         name: Name given to semaphore which can be opened
+ *               by other processes.
+ */
+HEV dw_named_event_get(char *name)
+{
+	struct sockaddr_un un;
+	int ev = socket(AF_UNIX, SOCK_STREAM, 0);
+	if(ev < 0)
+		return 0;
+
+	un.sun_family=AF_UNIX;
+	mkdir("/tmp/.dw", S_IWGRP|S_IWOTH);
+	strcpy(un.sun_path, "/tmp/.dw/");
+	strcat(un.sun_path, name);
+	connect(ev, (struct sockaddr *)&un, sizeof(un));
+	return ev;
+}
+
+/* Resets the event semaphore so threads who call wait
+ * on this semaphore will block.
+ * Parameters:
+ *         eve: Handle to the semaphore obtained by
+ *              an open or create call.
+ */
+int dw_named_event_reset(HEV eve)
+{
+	/* signal reset */
+	char tmp = (char)0;
+
+	if(eve < 0)
+		return 0;
+
+	if(write(eve, &tmp, 1) == 1)
+		return 0;
+	return 1;
+}
+
+/* Sets the posted state of an event semaphore, any threads
+ * waiting on the semaphore will no longer block.
+ * Parameters:
+ *         eve: Handle to the semaphore obtained by
+ *              an open or create call.
+ */
+int dw_named_event_post(HEV eve)
+{
+
+	/* signal post */
+	char tmp = (char)1;
+
+	if(eve < 0)
+		return 0;
+
+	if(write(eve, &tmp, 1) == 1)
+		return 0;
+	return 1;
+}
+
+/* Waits on the specified semaphore until it becomes
+ * posted, or returns immediately if it already is posted.
+ * Parameters:
+ *         eve: Handle to the semaphore obtained by
+ *              an open or create call.
+ *         timeout: Number of milliseconds before timing out
+ *                  or -1 if indefinite.
+ */
+int dw_named_event_wait(HEV eve, unsigned long timeout)
+{
+	fd_set rd;
+	struct timeval tv, *useme;
+	int retval = 0;
+	char tmp;
+
+	if(eve < 0)
+		return DB_EVENT_NON_INIT;
+
+	/* Set the timout or infinite */
+	if(timeout == -1)
+		useme = NULL;
+	else
+	{
+		tv.tv_sec = timeout / 1000;
+		tv.tv_usec = timeout % 1000;
+
+		useme = &tv;
+	}
+
+	FD_ZERO(&rd);
+	FD_SET(eve, &rd);
+
+	/* Signal wait */
+	tmp = (char)2;
+	write(eve, &tmp, 1);
+
+	retval = select(eve+1, &rd, NULL, NULL, useme);
+
+	/* Signal done waiting. */
+	tmp = (char)3;
+	write(eve, &tmp, 1);
+
+	if(retval == 0)
+		return DW_EVENT_TIMEOUT;
+	else if(retval == -1)
+		return DW_EVENT_INTERRUPT;
+
+	/* Clear the entry from the pipe so
+	 * we don't loop endlessly. :)
+	 */
+	read(eve, &tmp, 1);
+	return 0;
+}
+
+/* Release this semaphore, if there are no more open
+ * handles on this semaphore the semaphore will be destroyed.
+ * Parameters:
+ *         eve: Handle to the semaphore obtained by
+ *              an open or create call.
+ */
+int dw_named_event_close(HEV eve)
+{
+	/* Finally close the domain socket,
+	 * cleanup will continue in _handle_sem.
+	 */
+	close(eve);
+	return 0;
+}
+
 /*
  * Setup thread independent color sets.
  */
@@ -7383,6 +7716,102 @@
 	_dw_thread_remove(dw_thread_id());
 	free(tmp);
 }
+
+/*
+ * Allocates a shared memory region with a name.
+ * Parameters:
+ *         handle: A pointer to receive a SHM identifier.
+ *         dest: A pointer to a pointer to receive the memory address.
+ *         size: Size in bytes of the shared memory region to allocate.
+ *         name: A string pointer to a unique memory name.
+ */
+HSHM dw_named_memory_new(void **dest, int size, char *name)
+{
+	char namebuf[1024];
+	HSHM handle;
+
+	mkdir("/tmp/.dw", S_IWGRP|S_IWOTH);
+	sprintf(namebuf, "/tmp/.dw/%s", name);
+
+	if((handle->fd = open(namebuf, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0)
+		return 0;
+
+	ftruncate(handle->fd, size);
+
+	/* attach the shared memory segment to our process's address space. */
+	*dest = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd, 0);
+
+	if(*dest == MAP_FAILED)
+	{
+		close(handle->fd);
+		*dest = NULL;
+		return 0;
+	}
+
+	handle->size = size;
+	handle->sid = getsid(0);
+	handle->path = strdup(namebuf);
+
+	return handle;
+}
+
+/*
+ * Aquires shared memory region with a name.
+ * Parameters:
+ *         dest: A pointer to a pointer to receive the memory address.
+ *         size: Size in bytes of the shared memory region to requested.
+ *         name: A string pointer to a unique memory name.
+ */
+HSHM dw_named_memory_get(void **dest, int size, char *name)
+{
+	char namebuf[1024];
+	HSHM handle;
+
+	mkdir("/tmp/.dw", S_IWGRP|S_IWOTH);
+	sprintf(namebuf, "/tmp/.dw/%s", name);
+
+	if((handle->fd = open(namebuf, O_RDWR)) < 0)
+		return -1;
+
+	/* attach the shared memory segment to our process's address space. */
+	*dest = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd, 0);
+
+	if(*dest == MAP_FAILED)
+	{
+		close(handle->fd);
+		*dest = NULL;
+		return 0;
+	}
+
+	handle->size = size;
+	handle->sid = -1;
+	handle->path = NULL;
+
+	return handle;
+}
+
+/*
+ * Frees a shared memory region previously allocated.
+ * Parameters:
+ *         handle: Handle obtained from DB_named_memory_allocate.
+ *         ptr: The memory address aquired with DB_named_memory_allocate.
+ */
+int dw_named_memory_free(HSHM handle, void *ptr)
+{
+	int rc = munmap(ptr, handle.size);
+
+	close(handle.fd);
+	if(handle.path)
+	{
+		/* Only remove the actual file if we are the
+		 * creator of the file.
+		 */
+		if(handle.sid != -1 && handle.sid == getsid(0))
+			remove(handle.path);
+		free(handle.path);
+	}
+	return rc;
+}
 /*
  * Creates a new thread with a starting point of func.
  * Parameters:
--- a/os2/dw.c	Mon Apr 12 03:52:15 2004 +0000
+++ b/os2/dw.c	Sat Apr 17 05:38:09 2004 +0000
@@ -7932,6 +7932,188 @@
 	return TRUE;
 }
 
+/* Create a named event semaphore which can be
+ * opened from other processes.
+ * Parameters:
+ *         eve: Pointer to an event handle to receive handle.
+ *         name: Name given to semaphore which can be opened
+ *               by other processes.
+ */
+HEV API dw_named_event_new(char *name)
+{
+	int rc;
+	char *semname = malloc(strlen(name)+8);
+	HEV ev = 0;
+
+	if(!semname)
+		return 0;
+
+	strcpy(semname, "\\sem32\\");
+	strcat(semname, name);
+
+	DosCreateEventSem(semname, &ev, 0L, FALSE);
+
+	free(semname);
+	return ev;
+}
+
+/* Open an already existing named event semaphore.
+ * Parameters:
+ *         eve: Pointer to an event handle to receive handle.
+ *         name: Name given to semaphore which can be opened
+ *               by other processes.
+ */
+HEV API dw_named_event_get(char *name)
+{
+	char *semname = malloc(strlen(name)+8);
+	HEV ev;
+
+	if(!semname)
+		return 0;
+
+	strcpy(semname, "\\sem32\\");
+	strcat(semname, name);
+
+	DosOpenEventSem(semname, &ev);
+
+	free(semname);
+	return ev;
+}
+
+/* Resets the event semaphore so threads who call wait
+ * on this semaphore will block.
+ * Parameters:
+ *         eve: Handle to the semaphore obtained by
+ *              an open or create call.
+ */
+int API dw_named_event_reset(HEV eve)
+{
+	ULONG count;
+
+	return DosResetEventSem(eve, &count);
+}
+
+/* Sets the posted state of an event semaphore, any threads
+ * waiting on the semaphore will no longer block.
+ * Parameters:
+ *         eve: Handle to the semaphore obtained by
+ *              an open or create call.
+ */
+int API dw_named_event_post(HEV eve)
+{
+	return DosPostEventSem(eve);
+}
+
+
+/* Waits on the specified semaphore until it becomes
+ * posted, or returns immediately if it already is posted.
+ * Parameters:
+ *         eve: Handle to the semaphore obtained by
+ *              an open or create call.
+ *         timeout: Number of milliseconds before timing out
+ *                  or -1 if indefinite.
+ */
+int API dw_named_event_wait(HEV eve, unsigned long timeout)
+{
+	int rc;
+
+	rc = DosWaitEventSem(eve, timeout);
+	switch (rc)
+	{
+	case ERROR_INVALID_HANDLE:
+		rc = DW_ERROR_NON_INIT;
+		break;
+	case ERROR_NOT_ENOUGH_MEMORY:
+		rc = DW_ERROR_NO_MEM;
+		break;
+	case ERROR_INTERRUPT:
+		rc = DW_ERROR_INTERRUPT;
+		break;
+	case ERROR_TIMEOUT:
+		rc = DW_ERROR_TIMEOUT;
+		break;
+	}
+
+	return rc;
+}
+
+/* Release this semaphore, if there are no more open
+ * handles on this semaphore the semaphore will be destroyed.
+ * Parameters:
+ *         eve: Handle to the semaphore obtained by
+ *              an open or create call.
+ */
+int API dw_named_event_close(HEV eve)
+{
+	int rc;
+
+	rc = DosCloseEventSem(eve);
+	switch (rc)
+	{
+	case ERROR_INVALID_HANDLE:
+		rc = DW_ERROR_NON_INIT;
+		break;
+
+	case ERROR_SEM_BUSY:
+		rc = DW_ERROR_BUSY;
+		break;
+	}
+
+	return rc;
+}
+
+/*
+ * Allocates a shared memory region with a name.
+ * Parameters:
+ *         handle: A pointer to receive a SHM identifier.
+ *         dest: A pointer to a pointer to receive the memory address.
+ *         size: Size in bytes of the shared memory region to allocate.
+ *         name: A string pointer to a unique memory name.
+ */
+int API dw_named_memory_alloc(HSHM *handle, void **dest, int size, char *name)
+{
+	char namebuf[1024];
+
+	sprintf(namebuf, "\\sharemem\\%s", name);
+
+	if(DosAllocSharedMem((void *)dest, namebuf, size, PAG_COMMIT | PAG_WRITE | PAG_READ) != NO_ERROR)
+		return -1;
+
+	return 0;
+}
+
+/*
+ * Aquires shared memory region with a name.
+ * Parameters:
+ *         dest: A pointer to a pointer to receive the memory address.
+ *         size: Size in bytes of the shared memory region to requested.
+ *         name: A string pointer to a unique memory name.
+ */
+int API dw_named_memory_get(HSHM *handle, void **dest, int size, char *name)
+{
+	char namebuf[1024];
+
+	sprintf(namebuf, "\\sharemem\\%s", name);
+
+	if(DosGetNamedSharedMem((void *)dest, namebuf, PAG_READ | PAG_WRITE) != NO_ERROR)
+		return -1;
+
+	return 0;
+}
+
+/*
+ * Frees a shared memory region previously allocated.
+ * Parameters:
+ *         handle: Handle obtained from DB_named_memory_allocate.
+ *         ptr: The memory address aquired with DB_named_memory_allocate.
+ */
+int API dw_named_memory_free(HSHM handle, void *ptr)
+{
+	if(DosFreeMem(ptr) != NO_ERROR)
+		return -1;
+	return 0;
+}
+
 /*
  * Encapsulate the message queues on OS/2.
  */
--- a/win/dw.c	Mon Apr 12 03:52:15 2004 +0000
+++ b/win/dw.c	Sat Apr 17 05:38:09 2004 +0000
@@ -27,6 +27,7 @@
 
 DWORD dwVersion = 0, dwComctlVer = 0;
 DWTID _dwtid = -1;
+SECURITY_DESCRIPTOR _dwsd;
 
 #define PACKVERSION(major,minor) MAKELONG(minor,major)
 
@@ -3266,6 +3267,10 @@
 		FreeLibrary(huser);
 	}
 
+	/* Initialize Security for named events and memory */
+	InitializeSecurityDescriptor(&_dwsd, SECURITY_DESCRIPTOR_REVISION);
+	SetSecurityDescriptorDacl(&_dwsd, TRUE, (PACL) NULL, FALSE);
+
 	return 0;
 }
 
@@ -7870,7 +7875,188 @@
 {
 	if(eve)
 		return CloseHandle(*eve);
-	return FALSE;
+	return 0;
+}
+
+/* Create a named event semaphore which can be
+ * opened from other processes.
+ * Parameters:
+ *         eve: Pointer to an event handle to receive handle.
+ *         name: Name given to semaphore which can be opened
+ *               by other processes.
+ */
+HEV API dw_named_event_new(char *name)
+{
+	SECURITY_ATTRIBUTES sa;
+
+	sa.nLength = sizeof( SECURITY_ATTRIBUTES);
+	sa.lpSecurityDescriptor = &_dwsd;
+	sa.bInheritHandle = FALSE;
+
+	return CreateEvent(&sa, TRUE, FALSE, name);
+}
+
+/* Destroy this semaphore.
+ * Parameters:
+ *         eve: Handle to the semaphore obtained by
+ *              a create call.
+ */
+HEV API dw_named_event_get(char *name)
+{
+	return OpenEvent(EVENT_ALL_ACCESS, FALSE, name);
+}
+
+/* Resets the event semaphore so threads who call wait
+ * on this semaphore will block.
+ * Parameters:
+ *         eve: Handle to the semaphore obtained by
+ *              an open or create call.
+ */
+int API dw_named_event_reset(HEV eve)
+{
+	int rc;
+
+	rc = ResetEvent(eve);
+	if(!rc)
+		return 1;
+
+	return 0;
+}
+
+/* Sets the posted state of an event semaphore, any threads
+ * waiting on the semaphore will no longer block.
+ * Parameters:
+ *         eve: Handle to the semaphore obtained by
+ *              an open or create call.
+ */
+int API dw_named_event_post(HEV eve)
+{
+	int rc;
+
+	rc = SetEvent(eve);
+	if(!rc)
+	   return 1;
+
+	return 0;
+}
+
+/* Waits on the specified semaphore until it becomes
+ * posted, or returns immediately if it already is posted.
+ * Parameters:
+ *         eve: Handle to the semaphore obtained by
+ *              an open or create call.
+ *         timeout: Number of milliseconds before timing out
+ *                  or -1 if indefinite.
+ */
+int API dw_named_event_wait(HEV eve, unsigned long timeout)
+{
+	int rc;
+
+	rc = WaitForSingleObject(eve, timeout);
+	switch (rc)
+	{
+	case WAIT_FAILED:
+		rc = DW_ERROR_TIMEOUT;
+		break;
+
+	case WAIT_ABANDONED:
+		rc = DW_ERROR_INTERRUPT;
+		break;
+
+	case WAIT_OBJECT_0:
+		rc = 0;
+		break;
+	}
+
+	return rc;
+}
+
+/* Release this semaphore, if there are no more open
+ * handles on this semaphore the semaphore will be destroyed.
+ * Parameters:
+ *         eve: Handle to the semaphore obtained by
+ *              an open or create call.
+ */
+int API dw_named_event_close(HEV eve)
+{
+	int rc;
+
+	rc = CloseHandle(eve);
+	if(!rc)
+		return 1;
+
+	return 0;
+}
+
+/*
+ * Allocates a shared memory region with a name.
+ * Parameters:
+ *         handle: A pointer to receive a SHM identifier.
+ *         dest: A pointer to a pointer to receive the memory address.
+ *         size: Size in bytes of the shared memory region to allocate.
+ *         name: A string pointer to a unique memory name.
+ */
+HSHM API dw_named_memory_new(void **dest, int size, char *name)
+{
+	SECURITY_ATTRIBUTES sa;
+	HSHM handle;
+
+	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+	sa.lpSecurityDescriptor = &_dwsd;
+	sa.bInheritHandle = FALSE;
+
+	handle = CreateFileMapping((HANDLE)0xFFFFFFFF, &sa, PAGE_READWRITE, 0, size, name);
+
+	if(!handle)
+		return 0;
+
+	*dest = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+
+	if(!*dest)
+	{
+		CloseHandle(handle);
+		return 0;
+	}
+
+	return handle;
+}
+
+/*
+ * Aquires shared memory region with a name.
+ * Parameters:
+ *         dest: A pointer to a pointer to receive the memory address.
+ *         size: Size in bytes of the shared memory region to requested.
+ *         name: A string pointer to a unique memory name.
+ */
+HSHM API dw_named_memory_get(void **dest, int size, char *name)
+{
+	HSHM handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name);
+
+	if(!handle)
+		return 0;
+
+	*dest = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+
+	if(!*dest)
+	{
+		CloseHandle(handle);
+		return 0;
+	}
+
+	return handle;
+}
+
+/*
+ * Frees a shared memory region previously allocated.
+ * Parameters:
+ *         handle: Handle obtained from DB_named_memory_allocate.
+ *         ptr: The memory address aquired with DB_named_memory_allocate.
+ */
+int API dw_named_memory_free(HSHM handle, void *ptr)
+{
+	UnmapViewOfFile(ptr);
+	CloseHandle(handle);
+	return 0;
 }
 
 /*