Release 0.1.0
WHAT'S NEW with version 0.1.0:
- Integrated patches from Alexandre.
- Minor bug fix in if1632.S
WHAT'S NEW with version 0.0.5:
- Patches from Alexandre Julliard. Some integration with Tcl.
- Generic interface for callback procedures. This will allow
callbacks into DLLs.
- MakeProcInstance() has been implemented but untested.
WHAT'S NEW with version 0.0.4:
- Eric Youngdale modified wine.c and selector.c to allow loading
of Windows DLLs.
- Added global memory allocation routines (GlobalAlloc, GlobalFree,
and GlobalLock)
- Bitmap resource loading into global memory.
diff --git a/global.c b/global.c
new file mode 100644
index 0000000..3ef21ee
--- /dev/null
+++ b/global.c
@@ -0,0 +1,316 @@
+static char RCSId[] = "$Id: global.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
+static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "prototypes.h"
+#include "heap.h"
+#include "segmem.h"
+
+/*
+ * Global memory pool descriptor.
+ *
+ * handle = 0, this descriptor contains the address of a free pool.
+ * != 0, this describes an allocated block.
+ *
+ * sequence = 0, this is not a huge block
+ * > 0, this is a portion of a huge block
+ * =-1, this is a free segment
+ *
+ * addr - address of this memory block.
+ *
+ * length - used to maintain huge blocks.
+ *
+ */
+typedef struct global_mem_desc_s
+{
+ struct global_mem_desc_s *next;
+ struct global_mem_desc_s *prev;
+ unsigned short handle;
+ short sequence;
+ void *addr;
+ int length;
+} GDESC;
+
+GDESC *GlobalList = NULL;
+
+/**********************************************************************
+ * GLOBAL_GetFreeSegments
+ */
+GDESC *
+GLOBAL_GetFreeSegments(unsigned int flags, int n_segments)
+{
+ struct segment_descriptor_s *s;
+ GDESC *g;
+ GDESC *g_start;
+ GDESC *g_prev;
+ int count, i;
+
+ /*
+ * Try to find some empty segments in our list.
+ */
+ count = 0;
+ for (g = GlobalList; g != NULL && count != n_segments; g = g->next)
+ {
+ if ((int) g->sequence == -1)
+ {
+ if (count > 0)
+ {
+ if (g->prev->handle + 8 != g->handle)
+ count = 0;
+ else
+ count++;
+ }
+ else
+ {
+ g_start = g;
+ count = 1;
+ }
+ }
+ else if (count)
+ count = 0;
+ }
+
+ /*
+ * If we couldn't find enough segments, then we need to create some.
+ */
+ if (count != n_segments)
+ {
+ /*
+ * Find list tail.
+ */
+ g_prev = NULL;
+ for (g = GlobalList; g != NULL; g = g->next)
+ g_prev = g;
+
+ /*
+ * Allocate segments.
+ */
+ for (count = 0; count < n_segments; count++)
+ {
+ s = GetNextSegment(flags, 0x10000);
+ if (s == NULL)
+ return NULL;
+
+ g = (GDESC *) malloc(sizeof(*g));
+
+ g->prev = g_prev;
+ g->next = NULL;
+ g->handle = s->selector;
+ g->sequence = -1;
+ g->addr = s->base_addr;
+ g->length = s->length;
+
+ free(s);
+
+ if (count == 0)
+ g_start = g;
+
+ if (g_prev != NULL)
+ {
+ g_prev->next = g;
+ g->prev = g_prev;
+ }
+ else
+ GlobalList = g;
+ }
+ }
+
+ /*
+ * We have all of the segments we need. Let's adjust their contents.
+ */
+ g = g_start;
+ for (i = 0; i < n_segments; i++, g = g->next)
+ {
+ g->sequence = i + 1;
+ g->length = n_segments;
+ }
+
+ return g_start;
+}
+
+/**********************************************************************
+ * GLOBAL_Alloc
+ */
+unsigned int
+GLOBAL_Alloc(unsigned int flags, unsigned long size)
+{
+ GDESC *g;
+ GDESC *g_prev;
+ void *m;
+ int i;
+
+ /*
+ * If this block is fixed or very big we need to allocate entire
+ * segments.
+ */
+ if (size > 0x8000 || !(flags & GLOBAL_FLAGS_MOVEABLE))
+ {
+ int segments = (size >> 16) + 1;
+
+ g = GLOBAL_GetFreeSegments(flags, segments);
+ if (g == NULL)
+ return 0;
+ else
+ return g->handle;
+ }
+ /*
+ * Otherwise we just need a little piece of a segment.
+ */
+ else
+ {
+ /*
+ * Try to allocate from active free lists.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ {
+ if (g->handle == 0 && g->sequence == 0)
+ {
+ m = HEAP_Alloc((MDESC **) g->addr, 0, size);
+ if (m != NULL)
+ break;
+ }
+ }
+
+ /*
+ * If we couldn't get the memory there, then we need to create
+ * a new free list.
+ */
+ if (m == NULL)
+ {
+ g = GLOBAL_GetFreeSegments(0, 1);
+ if (g == NULL)
+ return 0;
+
+ g->handle = 0;
+ g->sequence = 0;
+ HEAP_Init((MDESC **) g->addr, (MDESC **) g->addr + 1,
+ 0x10000 - sizeof(MDESC **));
+ m = HEAP_Alloc((MDESC **) g->addr, 0, size);
+ if (m == NULL)
+ return 0;
+ }
+
+ /*
+ * We have a new block. Let's create a GDESC entry for it.
+ */
+ g_prev = NULL;
+ i = 0;
+ for (g = GlobalList; g != NULL; g = g->next, i++)
+ g_prev = g;
+
+ g = malloc(sizeof(*g));
+ if (g == NULL)
+ return 0;
+
+ g->handle = i << 3;
+ g->sequence = 0;
+ g->addr = m;
+ g->length = size;
+ g->next = NULL;
+
+ if (g_prev != NULL)
+ {
+ g_prev->next = g;
+ g->prev = g_prev;
+ }
+ else
+ {
+ GlobalList = g;
+ g->prev = NULL;
+ }
+
+ return g->handle;
+ }
+}
+
+/**********************************************************************
+ * GLOBAL_Free
+ *
+ * Windows programs will pass a handle in the "block" parameter, but
+ * this function will also accept a 32-bit address.
+ */
+unsigned int
+GLOBAL_Free(unsigned int block)
+{
+ GDESC *g;
+
+ if (block == 0)
+ return 0;
+
+ /*
+ * Find GDESC for this block.
+ */
+ if (block & 0xffff0000)
+ {
+ for (g = GlobalList; g != NULL; g = g->next)
+ if (g->handle > 0 && (unsigned int) g->addr == block)
+ break;
+ }
+ else
+ {
+ for (g = GlobalList; g != NULL; g = g->next)
+ if (g->handle == block)
+ break;
+ }
+ if (g == NULL)
+ return block;
+
+ /*
+ * If the sequence number is zero then use HEAP_Free to deallocate
+ * memory, and throw away this descriptor.
+ */
+ if (g->sequence == 0)
+ {
+ HEAP_Free((MDESC **) (block & 0xffff0000), (void *) block);
+
+ if (g->prev != NULL)
+ g->prev->next = g->next;
+ else
+ GlobalList = g->next;
+
+ if (g->next != NULL)
+ g->next->prev = g->prev;
+
+ free(g);
+ }
+
+ /*
+ * Otherwise just mark these descriptors as free.
+ */
+ else
+ {
+ int i, limit;
+
+ g->length;
+ for (i = 0; i < limit; i++)
+ {
+ g->sequence = -1;
+ g->length = 0x10000;
+ }
+ }
+
+ return 0;
+}
+
+/**********************************************************************
+ * GLOBAL_Lock
+ *
+ */
+void *
+GLOBAL_Lock(unsigned int block)
+{
+ GDESC *g;
+
+ if (block == 0)
+ return 0;
+
+ /*
+ * Find GDESC for this block.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ if (g->handle == block)
+ return g->addr;
+
+ return NULL;
+}