Initial support for typelib generation.
authorHuw Davies <huw@codeweavers.com>
Thu, 6 Jan 2005 20:45:21 +0000 (20:45 +0000)
committerAlexandre Julliard <julliard@winehq.org>
Thu, 6 Jan 2005 20:45:21 +0000 (20:45 +0000)
tools/widl/Makefile.in
tools/widl/hash.c [new file with mode: 0644]
tools/widl/hash.h [new file with mode: 0644]
tools/widl/header.c
tools/widl/parser.y
tools/widl/typelib.c
tools/widl/typelib.h
tools/widl/typelib_struct.h [new file with mode: 0644]
tools/widl/widltypes.h
tools/widl/write_msft.c [new file with mode: 0644]

index 73c1bcd5a1c393bcdbe7aaa2d7a8062d92ee5f87..df682580cd7fe7773a71459dec8ad0b78f4a61e7 100644 (file)
@@ -10,11 +10,13 @@ PROGRAMS = widl$(EXEEXT)
 MODULE   = none
 
 C_SRCS = \
+       hash.c \
        header.c \
        proxy.c \
        typelib.c \
        utils.c \
-       widl.c
+       widl.c \
+       write_msft.c
 
 EXTRA_SRCS = parser.y parser.l
 EXTRA_OBJS = y.tab.o @LEX_OUTPUT_ROOT@.o
diff --git a/tools/widl/hash.c b/tools/widl/hash.c
new file mode 100644 (file)
index 0000000..aeaff06
--- /dev/null
@@ -0,0 +1,621 @@
+/*
+ * Oleaut32 hash functions
+ *
+ * Copyright 1999 Corel Corporation
+ * Copyright 2001-2003 Jon Griffiths
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+
+#include "hash.h"
+
+static const unsigned char Lookup_16[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+
+ /* Windows */
+ 0x7F, 0x7F, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x7F, 0x89, 0x53, 0x8B, 0x8C,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x98, 0x99,
+ 0x53, 0x9B, 0x8C, 0x7F, 0x7F, 0x55, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x96, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49,
+ 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0xD7, 0x4F, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0xDE, 0xDF, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43,
+ 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x4F, 0x4F, 0xF7, 0x4F, 0x55, 0x55, 0x55, 0x55, 0x55, 0xDE, 0x55,
+
+ /* Mac */
+ 0x41, 0x41, 0x43, 0x45, 0x4E, 0x4F, 0x55, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
+ 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x4F, 0x4F, 0x55, 0x55, 0x55, 0x55, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0x41, 0x4F, 0xB0, 0xB1, 0xB2, 0xB3,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0x41, 0x4F, 0xBD, 0x41, 0x4F, 0xC0,
+ 0xC1, 0xC2, 0xC3, 0x46, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0x41, 0x41, 0x4F,
+ 0xCE, 0xCE, 0xD0, 0xD0, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0x55, 0x55, 0xDA,
+ 0xDB, 0xDC, 0xDD, 0x3F, 0x3F, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0x41, 0x45, 0x41,
+ 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4F, 0x4F, 0x3F, 0x4F, 0x55, 0x55, 0x55,
+ 0x49, 0x7F, 0xF7, 0x7F, 0xF9, 0xFA, 0xFB, 0x3F, 0xFD, 0xFE, 0x7F
+};
+
+static const unsigned char Lookup_32[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+
+ /* Windows */
+ 0x7F, 0x7F, 0x82, 0x7F, 0x84, 0x85, 0x86, 0x87, 0x7F, 0x89, 0x53, 0x8B, 0x53,
+ 0x54, 0x5A, 0x5A, 0x7F, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x7F, 0x99,
+ 0x53, 0x9B, 0x53, 0x54, 0x5A, 0x5A, 0xA0, 0x7F, 0xA2, 0x4C, 0xA4, 0x41, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x53, 0xAB, 0xAC, 0x96, 0xAE, 0x5A, 0xB0, 0xB1, 0xB2, 0x4C,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x41, 0x53, 0xBB, 0x4C, 0xBD, 0x4C, 0x5A, 0x52,
+ 0x41, 0x41, 0x41, 0x41, 0x4C, 0x43, 0x43, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49,
+ 0x49, 0x44, 0xD0, 0x4E, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0xD7, 0x52, 0x55, 0x55,
+ 0x55, 0x55, 0x59, 0x54, 0xDF, 0x52, 0x41, 0x41, 0x41, 0x41, 0x4C, 0x43, 0x43,
+ 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x44, 0xD0, 0x4E, 0x4E, 0x4F, 0x4F,
+ 0x4F, 0x4F, 0xF7, 0x52, 0x55, 0x55, 0x55, 0x55, 0x59, 0x54, 0xFF,
+
+ /* Mac */
+ 0x41, 0x41, 0x41, 0x45, 0x41, 0x4F, 0x55, 0x41, 0x41, 0x43, 0x41, 0x43, 0x43,
+ 0x43, 0x45, 0x5A, 0x5A, 0x44, 0x49, 0x44, 0x45, 0x45, 0x45, 0x4F, 0x45, 0x4F,
+ 0x4F, 0x4F, 0x55, 0x45, 0x45, 0x55, 0xA0, 0xA1, 0x45, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0x45, 0xAC, 0xAD, 0x47, 0x49, 0x49, 0x49, 0xB2, 0xB3,
+ 0x49, 0x4B, 0xB6, 0xB7, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4E, 0x4E,
+ 0x4E, 0xC2, 0xC3, 0x4E, 0x4E, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0x4E, 0x4F, 0x4F,
+ 0x4F, 0x4F, 0xD0, 0xD0, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0x4F, 0x52, 0x52,
+ 0x52, 0xDC, 0xDD, 0x52, 0x52, 0x52, 0x53, 0xE2, 0xE3, 0x53, 0x53, 0x53, 0x41,
+ 0x54, 0x54, 0x49, 0x5A, 0x5A, 0x55, 0x4F, 0x4F, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x59, 0x59, 0x4B, 0x5A, 0x4C, 0x4C, 0x47, 0xFF
+};
+
+static const unsigned char Lookup_48[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+
+ /* Windows */
+ 0x7F, 0x7F, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x7F, 0x89, 0x53, 0x8B, 0x8C,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x98, 0x99,
+ 0x53, 0x9B, 0x8C, 0x7F, 0x7F, 0x59, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x96, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49,
+ 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0xD7, 0x4F, 0x55, 0x55,
+ 0x55, 0x55, 0x59, 0xDE, 0xDF, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43,
+ 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x4F, 0x4F, 0xF7, 0x4F, 0x55, 0x55, 0x55, 0x55, 0x59, 0xDE, 0x59,
+
+ /* Mac */
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C,
+ 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+ 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAB, 0xAD, 0xAE, 0xAE, 0xB0, 0xB1, 0xB2, 0xB3,
+ 0xA7, 0xB5, 0xB6, 0xB7, 0xB8, 0xB8, 0xBA, 0xBA, 0xBC, 0xBC, 0xBE, 0xBE, 0xB7,
+ 0xC1, 0xC2, 0xC3, 0x46, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCB, 0xCD,
+ 0xCD, 0xC1, 0xD0, 0xD0, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD8, 0xDA,
+ 0xDA, 0xDC, 0xDD, 0xDD, 0x9F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94,
+ 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F
+};
+
+static const unsigned char Lookup_64[128 * 3] = {
+ /* Common */
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+
+/* Windows */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x96, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49,
+ 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0xD7, 0x4F, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0xDE, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* Mac */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x96, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49,
+ 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0xD7, 0x4F, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0xDE, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const unsigned char Lookup_80[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+
+/* Windows */
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+
+ /* Mac */
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+};
+
+static const unsigned char Lookup_112[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+
+/* Windows */
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+
+ /* Mac */
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+};
+
+static const unsigned char Lookup_128[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x00,
+
+/* Windows */
+ 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x00, 0x8B, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x00, 0x99,
+ 0x00, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x00, 0xAB, 0xAC, 0x2D, 0xAE, 0x2D, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xBA,
+ 0xA2, 0xC2, 0xC3, 0xC4, 0xB8, 0xC6, 0xB9, 0xC8, 0xBA, 0xCA, 0xCB, 0xCC, 0xCD,
+ 0xCE, 0xBC, 0xD0, 0xD1, 0x00, 0xD3, 0xD4, 0xBE, 0xD6, 0xD7, 0xD8, 0xBF, 0xBA,
+ 0xBE, 0xA2, 0xB8, 0xB9, 0xBA, 0xBE, 0xA2, 0xC2, 0xC3, 0xC4, 0xB8, 0xC6, 0xB9,
+ 0xC8, 0xBA, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xBC, 0xD0, 0xD1, 0xD3, 0xD3, 0xD4,
+ 0xBE, 0xD6, 0xD7, 0xD8, 0xBF, 0xBA, 0xBE, 0xBC, 0xBE, 0xBF, 0x00,
+
+ /* Mac */
+ 0x41, 0x31, 0x32, 0x45, 0x33, 0x4F, 0x55, 0x87, 0x41, 0x41, 0x41, 0x00, 0x8C,
+ 0x43, 0x45, 0x45, 0x45, 0x45, 0x92, 0x93, 0x49, 0x49, 0x96, 0x97, 0x98, 0x4F,
+ 0x4F, 0x9B, 0x3F, 0x55, 0x55, 0x55, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xAB, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xB0,
+ 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0x09, 0xBD, 0xCC, 0xB0,
+ 0xB6, 0xCF, 0x2D, 0x2D, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xB8, 0xAB, 0xC3, 0xBD,
+ 0xB6, 0xB8, 0xAB, 0xC3, 0xBF, 0xBD, 0xB0, 0xB5, 0xBE, 0xA2, 0xB6, 0xBC, 0xA1,
+ 0xB8, 0xAB, 0xA5, 0xBA, 0xA4, 0xBB, 0xC1, 0xC3, 0xA6, 0xBF, 0xC4, 0xAA, 0xC6,
+ 0xA3, 0xBF, 0xAA, 0xCC, 0xBD, 0xB7, 0xAB, 0xBD, 0xAB, 0xBD, 0x3F,
+};
+
+static const unsigned char Lookup_144[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x00,
+
+/* Windows */
+ 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x53, 0x8B, 0x8C,
+ 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x98, 0x99,
+ 0x53, 0x9B, 0x8C, 0x00, 0x00, 0x59, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x2D, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0xC1, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43, 0x45, 0xC9, 0x45, 0x45, 0x49, 0xCD,
+ 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0xD3, 0x4F, 0x4F, 0xD6, 0xD7, 0xD6, 0x55, 0xDA,
+ 0x55, 0x55, 0xDD, 0xDE, 0xDF, 0x41, 0xC1, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43,
+ 0x45, 0xC9, 0x45, 0x45, 0x49, 0xCD, 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0xD3, 0x4F,
+ 0x4F, 0xD6, 0xF7, 0xD6, 0x55, 0xDA, 0x55, 0x55, 0xDD, 0xDE, 0x59,
+
+ /* Mac */
+ 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x53, 0x8B, 0x8C,
+ 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x98, 0x99,
+ 0x53, 0x9B, 0x8C, 0x00, 0x00, 0x59, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x2D, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0xC1, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43, 0x45, 0xC9, 0x45, 0x45, 0x49, 0xCD,
+ 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0xD3, 0x4F, 0x4F, 0xD6, 0xD7, 0xD6, 0x55, 0xDA,
+ 0x55, 0x55, 0xDD, 0xDE, 0xDF, 0x41, 0xC1, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43,
+ 0x45, 0xC9, 0x45, 0x45, 0x49, 0xCD, 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0xD3, 0x4F,
+ 0x4F, 0xD6, 0xF7, 0xD6, 0x55, 0xDA, 0x55, 0x55, 0xDD, 0xDE, 0x59,
+};
+
+static const unsigned char Lookup_160[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x00,
+
+/* Windows */
+ 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x53, 0x8B, 0x8C,
+ 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x98, 0x99,
+ 0x53, 0x9B, 0x8C, 0x00, 0x00, 0x59, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x2D, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0xC7, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49,
+ 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0xD6, 0xD7, 0x4F, 0x55, 0x55,
+ 0x55, 0xDC, 0xDD, 0xDE, 0xDF, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0xC7,
+ 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x4F, 0xD6, 0xF7, 0x4F, 0x55, 0x55, 0x55, 0xDC, 0xDD, 0xDE, 0x59,
+
+ /* Mac */
+ 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x53, 0x8B, 0x8C,
+ 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x98, 0x99,
+ 0x53, 0x9B, 0x8C, 0x00, 0x00, 0x59, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x2D, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0xC7, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49,
+ 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0xD6, 0xD7, 0x4F, 0x55, 0x55,
+ 0x55, 0xDC, 0xDD, 0xDE, 0xDF, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0xC7,
+ 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x4F, 0xD6, 0xF7, 0x4F, 0x55, 0x55, 0x55, 0xDC, 0xDD, 0xDE, 0x59,
+};
+
+static const unsigned char Lookup_176[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x00,
+
+ /* Windows */
+ 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x53, 0x8B, 0x8C,
+ 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x98, 0x99,
+ 0x53, 0x9B, 0x8C, 0x00, 0x00, 0x59, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x2D, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0x41, 0x41, 0x41, 0xC4, 0xC5, 0xC4, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49,
+ 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0xD6, 0xD7, 0xD6, 0x55, 0x55,
+ 0x55, 0x59, 0x59, 0xDE, 0xDF, 0x41, 0x41, 0x41, 0x41, 0xC4, 0xC5, 0xC4, 0x43,
+ 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x4F, 0xD6, 0xF7, 0xD6, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0x59,
+
+ /* Mac */
+ 0x80, 0x81, 0x43, 0x45, 0x4E, 0x85, 0x59, 0x41, 0x41, 0x41, 0x80, 0x41, 0x81,
+ 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x85, 0x4F, 0x55, 0x55, 0x55, 0x59, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0x80, 0x85, 0xB0, 0xB1, 0xB2, 0xB3,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0x41, 0x4F, 0xBD, 0x80, 0x85, 0xC0,
+ 0xC1, 0xC2, 0xC3, 0x46, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0x09, 0x41, 0x41, 0x4F,
+ 0xCE, 0xCE, 0x2D, 0x2D, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0x59, 0x59, 0xDA,
+ 0xDB, 0xDC, 0xDD, 0x3F, 0x3F, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0x41, 0x45, 0x41,
+ 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4F, 0x4F, 0x3F, 0x4F, 0x55, 0x55, 0x55,
+ 0x49, 0x00, 0xF7, 0x00, 0xF9, 0xFA, 0xFB, 0x3F, 0xFD, 0xFE, 0x00
+};
+
+static const unsigned char Lookup_208[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+
+/* Windows */
+ 0x80, 0x81, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x5E, 0x89, 0x8A, 0x8B, 0x8C,
+ 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+ 0x9A, 0x9B, 0x8C, 0x9D, 0x00, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0,
+ 0xC1, 0xC2, 0xC1, 0xC1, 0xC1, 0xC1, 0xC7, 0xC8, 0xC9, 0xC9, 0xCB, 0xCC, 0xCD,
+ 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
+ 0xDB, 0x00, 0xDD, 0xDE, 0xDF, 0x41, 0xE1, 0x41, 0xE3, 0xE4, 0xE5, 0xE6, 0x43,
+ 0x45, 0x45, 0x45, 0x45, 0xEC, 0xEC, 0x49, 0x49, 0xF0, 0xF1, 0xF2, 0xF3, 0x4F,
+ 0xF5, 0xF6, 0xF7, 0xF8, 0x55, 0xFA, 0x55, 0x55, 0x00, 0x00, 0xFF,
+
+ /* Mac */
+ 0x41, 0x81, 0x43, 0x45, 0x4E, 0x4F, 0x55, 0x41, 0x41, 0x41, 0x41, 0x8B, 0x8C,
+ 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x93, 0x49, 0x49, 0x4E, 0x4F, 0x98, 0x4F,
+ 0x4F, 0x9B, 0x55, 0x55, 0x55, 0x55, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0,
+ 0xC1, 0xC2, 0xC1, 0xC1, 0xC1, 0xC1, 0xC7, 0xC8, 0xC9, 0xC9, 0xCB, 0xCC, 0xCD,
+ 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
+ 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0x00, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xE9, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4,
+ 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+};
+
+static const unsigned char Lookup_224[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+
+/* Windows */
+ 0x80, 0x81, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x5E, 0x89, 0x8A, 0x8B, 0x8C,
+ 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+ 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0,
+ 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD,
+ 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
+ 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xEA, 0xEA, 0xEC, 0xED, 0xED, 0xEF, 0xEF, 0xF1, 0xF2, 0xF3, 0xF3,
+ 0xF5, 0xF5, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0x00, 0x00, 0xFF,
+
+ /* Mac */
+ 0x41, 0x41, 0x43, 0x45, 0x4E, 0x4F, 0x55, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
+ 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x4F, 0x4F, 0x55, 0x55, 0x55, 0x55, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0,
+ 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD,
+ 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
+ 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xEA, 0xEA, 0xEC, 0xED, 0xED, 0xEF, 0xEF, 0xF1, 0xF2, 0xF3, 0xF3,
+ 0xF5, 0xF5, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+};
+
+/***********************************************************************
+ *             lhash_val_of_name_sys
+ *
+ * Copy of oleaut32.LHashValOfNameSysA
+ * Produce a string hash value.
+ *
+ * PARAMS
+ *  skind [I] Type of the system.
+ *  lcid  [I] Locale id for the hash.
+ *  lpStr [I] String to hash.
+ *
+ * RETURNS
+ *  Success: The hash value of the string.
+ *  Failure: 0, if lpStr is NULL.
+ *
+ * NOTES
+ *  This function produces a two part hash: The high word is based on
+ *  skind and lcid, while the low word is based on a repeated string
+ *  hash of skind/str.
+ */
+unsigned long lhash_val_of_name_sys( syskind_t skind, LCID lcid, LPCSTR lpStr)
+{
+  ULONG nOffset, nMask = skind == SYS_MAC ? 1 : 0;
+  ULONG nHiWord, nLoWord = 0x0deadbee;
+  const unsigned char *str = (const unsigned char *)lpStr, *pnLookup = NULL;
+
+  if (!str)
+    return 0;
+
+  switch (PRIMARYLANGID(LANGIDFROMLCID(lcid)))
+  {
+  default:
+    fprintf(stderr, "Unknown lcid %lx, treating as latin-based, please report\n", lcid);
+    /* .. Fall Through .. */
+  case LANG_AFRIKAANS:  case LANG_ALBANIAN:   case LANG_ARMENIAN:
+  case LANG_ASSAMESE:   case LANG_AZERI:      case LANG_BASQUE:
+  case LANG_BELARUSIAN: case LANG_BENGALI:    case LANG_BULGARIAN:
+  case LANG_CATALAN:    case LANG_DANISH:     case LANG_DIVEHI:
+  case LANG_DUTCH:      case LANG_ENGLISH:    case LANG_ESTONIAN:
+  case LANG_FAEROESE:   case LANG_FINNISH:    case LANG_FRENCH:
+  case LANG_GALICIAN:   case LANG_GEORGIAN:   case LANG_GERMAN:
+  case LANG_GUJARATI:   case LANG_HINDI:      case LANG_INDONESIAN:
+  case LANG_ITALIAN:    case LANG_KANNADA:    case LANG_KASHMIRI:
+  case LANG_KAZAK:      case LANG_KONKANI:    case LANG_KYRGYZ:
+  case LANG_LATVIAN:    case LANG_LITHUANIAN: case LANG_MACEDONIAN:
+  case LANG_MALAY:      case LANG_MALAYALAM:  case LANG_MANIPURI:
+  case LANG_MARATHI:    case LANG_MONGOLIAN:  case LANG_NEPALI:
+  case LANG_ORIYA:      case LANG_PORTUGUESE: case LANG_PUNJABI:
+  case LANG_ROMANIAN:   case LANG_SANSKRIT:   case LANG_SERBIAN:
+  case LANG_SINDHI:     case LANG_SLOVENIAN:  case LANG_SWAHILI:
+  case LANG_SWEDISH:    case LANG_SYRIAC:     case LANG_TAMIL:
+  case LANG_TATAR:      case LANG_TELUGU:     case LANG_THAI:
+  case LANG_UKRAINIAN:  case LANG_URDU:       case LANG_UZBEK:
+  case LANG_VIETNAMESE: case LANG_GAELIC:     case LANG_MALTESE:
+  case LANG_MAORI:      case LANG_RHAETO_ROMANCE:
+  case LANG_SAAMI:      case LANG_SORBIAN:    case LANG_SUTU:
+  case LANG_TSONGA:     case LANG_TSWANA:     case LANG_VENDA:
+  case LANG_XHOSA:      case LANG_ZULU:       case LANG_ESPERANTO:
+  case LANG_WALON:      case LANG_CORNISH:    case LANG_WELSH:
+  case LANG_BRETON:
+    nOffset = 16;
+    pnLookup = Lookup_16;
+    break;
+  case LANG_CZECH:  case LANG_HUNGARIAN:  case LANG_POLISH:
+  case LANG_SLOVAK: case LANG_SPANISH:
+    nOffset = 32;
+    pnLookup = Lookup_32;
+    break;
+  case LANG_HEBREW:
+    nOffset = 48;
+    pnLookup = Lookup_48;
+    break;
+  case LANG_JAPANESE:
+    nOffset = 64;
+    pnLookup = Lookup_64;
+    break;
+  case LANG_KOREAN:
+    nOffset = 80;
+    pnLookup = Lookup_80;
+    break;
+  case LANG_CHINESE:
+    nOffset = 112;
+    pnLookup = Lookup_112;
+    break;
+  case LANG_GREEK:
+    nOffset = 128;
+    pnLookup = Lookup_128;
+    break;
+  case LANG_ICELANDIC:
+    nOffset = 144;
+    pnLookup = Lookup_144;
+    break;
+  case LANG_TURKISH:
+    nOffset = 160;
+    pnLookup = Lookup_160;
+    break;
+  case LANG_NORWEGIAN:
+    if (SUBLANGID(LANGIDFROMLCID(lcid)) == SUBLANG_NORWEGIAN_NYNORSK)
+    {
+      nOffset = 176;
+      pnLookup = Lookup_176;
+    }
+    else
+    {
+      nOffset = 16;
+      pnLookup = Lookup_16;
+    }
+    break;
+  case LANG_ARABIC:
+  case LANG_FARSI:
+    nOffset = 208;
+    pnLookup = Lookup_208;
+    break;
+  case LANG_RUSSIAN:
+    nOffset = 224;
+    pnLookup = Lookup_224;
+    break;
+  }
+
+  nHiWord = (nOffset | nMask) << 16;
+
+  while (*str)
+  {
+    ULONG newLoWord = 0, i;
+
+    /* Cumulative prime multiplication (*37) with modulo 2^32 wrap-around */
+    for (i = 0; i < 37; i++)
+      newLoWord += nLoWord;
+
+    nLoWord = newLoWord + pnLookup[*str > 0x7f && nMask ? *str + 0x80 : *str];
+    str++;
+  }
+  /* Constrain to a prime modulo and sizeof(WORD) */
+  nLoWord = (nLoWord % 65599) & 0xffff;
+
+  return nHiWord | nLoWord;
+}
diff --git a/tools/widl/hash.h b/tools/widl/hash.h
new file mode 100644 (file)
index 0000000..de91849
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Hash definitions
+ *
+ * Copyright 2005 Huw Davies
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __WIDL_HASH_H
+#define __WIDL_HASH_H
+
+typedef enum tag_syskind_t {
+    SYS_WIN16 = 0,
+    SYS_WIN32,
+    SYS_MAC
+} syskind_t;
+
+extern unsigned long lhash_val_of_name_sys( syskind_t skind, LCID lcid, LPCSTR lpStr);
+
+#endif
index 75becddf828eb5ced15b8c2882160dbc18ab37e7..67ea841dbdbd5c7b3b55aa6598ecf97f1e978124 100644 (file)
@@ -30,6 +30,7 @@
 #include <ctype.h>
 #include <signal.h>
 
+#include "windef.h"
 #include "widl.h"
 #include "utils.h"
 #include "parser.h"
index 86b22e1bfd04c877716ed01d429aec5c3ff734ba..dfcf1b04d05e03e866848edd921e144c5c82d7f4 100644 (file)
@@ -31,6 +31,8 @@
 #include <alloca.h>
 #endif
 
+#include "windef.h"
+
 #include "widl.h"
 #include "utils.h"
 #include "parser.h"
@@ -969,6 +971,7 @@ static type_t *make_type(unsigned char type, type_t *ref)
   t->sign = 0;
   t->defined = FALSE;
   t->written = FALSE;
+  t->typelib_idx = -1;
   INIT_LINK(t);
   return t;
 }
index e9a28cefb5641ae69934af274b8460ea3263e990..c03002501a6f61b6f807e7a16e349025043ba196 100644 (file)
 
 int in_typelib = 0;
 
-/* Copied from wtypes.h. Not included directly because that would create a
- * circular dependency (after all, wtypes.h is generated by widl...) */
-
-enum VARENUM {
-    VT_EMPTY = 0,
-    VT_NULL = 1,
-    VT_I2 = 2,
-    VT_I4 = 3,
-    VT_R4 = 4,
-    VT_R8 = 5,
-    VT_CY = 6,
-    VT_DATE = 7,
-    VT_BSTR = 8,
-    VT_DISPATCH = 9,
-    VT_ERROR = 10,
-    VT_BOOL = 11,
-    VT_VARIANT = 12,
-    VT_UNKNOWN = 13,
-    VT_DECIMAL = 14,
-    VT_I1 = 16,
-    VT_UI1 = 17,
-    VT_UI2 = 18,
-    VT_UI4 = 19,
-    VT_I8 = 20,
-    VT_UI8 = 21,
-    VT_INT = 22,
-    VT_UINT = 23,
-    VT_VOID = 24,
-    VT_HRESULT = 25,
-    VT_PTR = 26,
-    VT_SAFEARRAY = 27,
-    VT_CARRAY = 28,
-    VT_USERDEFINED = 29,
-    VT_LPSTR = 30,
-    VT_LPWSTR = 31,
-    VT_RECORD = 36,
-    VT_FILETIME = 64,
-    VT_BLOB = 65,
-    VT_STREAM = 66,
-    VT_STORAGE = 67,
-    VT_STREAMED_OBJECT = 68,
-    VT_STORED_OBJECT = 69,
-    VT_BLOB_OBJECT = 70,
-    VT_CF = 71,
-    VT_CLSID = 72,
-    VT_BSTR_BLOB = 0xfff,
-    VT_VECTOR = 0x1000,
-    VT_ARRAY = 0x2000,
-    VT_BYREF = 0x4000,
-    VT_RESERVED = 0x8000,
-    VT_ILLEGAL = 0xffff,
-    VT_ILLEGALMASKED = 0xfff,
-    VT_TYPEMASK = 0xfff
-};
 static typelib_t *typelib;
 
 /* List of oleauto types that should be recognized by name.
@@ -195,8 +141,11 @@ unsigned short get_type_vt(type_t *t)
     }
     /* FIXME: should we recurse and add a VT_BYREF? */
     /* Or just return VT_PTR? */
+    if(t->ref) return get_type_vt(t->ref);
     error("get_type_vt: unknown-deref-type: %d\n", t->ref->type);
     break;
+  case RPC_FC_STRUCT:
+    return VT_USERDEFINED;
   default:
     error("get_type_vt: unknown-type: %d\n", t->type);
   }
@@ -231,7 +180,7 @@ void end_typelib(void)
     in_typelib--;
     if (!typelib) return;
 
-/*    create_msft_typelib(typelib);*/
+    create_msft_typelib(typelib);
     return;
 }
 
index fe173b4ac685dfa7125a4d603111cac7da64f9d8..ba5260b2d68e5cdfe24100d5077da11e91bfcaff 100644 (file)
@@ -29,4 +29,61 @@ extern void add_coclass(class_t *cls);
 extern void add_module(type_t *module);
 extern void add_struct(type_t *structure);
 
+/* Copied from wtypes.h. Not included directly because that would create a
+ * circular dependency (after all, wtypes.h is generated by widl...) */
+
+enum VARENUM {
+    VT_EMPTY = 0,
+    VT_NULL = 1,
+    VT_I2 = 2,
+    VT_I4 = 3,
+    VT_R4 = 4,
+    VT_R8 = 5,
+    VT_CY = 6,
+    VT_DATE = 7,
+    VT_BSTR = 8,
+    VT_DISPATCH = 9,
+    VT_ERROR = 10,
+    VT_BOOL = 11,
+    VT_VARIANT = 12,
+    VT_UNKNOWN = 13,
+    VT_DECIMAL = 14,
+    VT_I1 = 16,
+    VT_UI1 = 17,
+    VT_UI2 = 18,
+    VT_UI4 = 19,
+    VT_I8 = 20,
+    VT_UI8 = 21,
+    VT_INT = 22,
+    VT_UINT = 23,
+    VT_VOID = 24,
+    VT_HRESULT = 25,
+    VT_PTR = 26,
+    VT_SAFEARRAY = 27,
+    VT_CARRAY = 28,
+    VT_USERDEFINED = 29,
+    VT_LPSTR = 30,
+    VT_LPWSTR = 31,
+    VT_RECORD = 36,
+    VT_FILETIME = 64,
+    VT_BLOB = 65,
+    VT_STREAM = 66,
+    VT_STORAGE = 67,
+    VT_STREAMED_OBJECT = 68,
+    VT_STORED_OBJECT = 69,
+    VT_BLOB_OBJECT = 70,
+    VT_CF = 71,
+    VT_CLSID = 72,
+    VT_BSTR_BLOB = 0xfff,
+    VT_VECTOR = 0x1000,
+    VT_ARRAY = 0x2000,
+    VT_BYREF = 0x4000,
+    VT_RESERVED = 0x8000,
+    VT_ILLEGAL = 0xffff,
+    VT_ILLEGALMASKED = 0xfff,
+    VT_TYPEMASK = 0xfff
+};
+extern unsigned short get_type_vt(type_t *t);
+
+extern int create_msft_typelib(typelib_t *typelib);
 #endif
diff --git a/tools/widl/typelib_struct.h b/tools/widl/typelib_struct.h
new file mode 100644 (file)
index 0000000..cafd424
--- /dev/null
@@ -0,0 +1,591 @@
+/*
+ * typelib_struct.h  internal wine data structures
+ * used to decode typelib's
+ *
+ * Copyright 1999 Rein KLazes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _WIDL_TYPELIB_STRUCT_H
+#define _WIDL_TYPELIB_STRUCT_H
+
+#define HELPDLLFLAG (0x0100)
+#define DO_NOT_SEEK (-1)
+
+#define MSFT_HREFTYPE_INTHISFILE(href) (!((href) & 3))
+#define MSFT_HREFTYPE_INDEX(href) ((href) /sizeof(MSFT_TypeInfoBase))
+
+/*-------------------------FILE STRUCTURES-----------------------------------*/
+
+/* There are two known file formats, those created with ICreateTypeLib
+ * have the signature "SLTG" as their first four bytes, while those created
+ * with ICreateTypeLib2 have "MSFT".
+ */
+
+/*****************************************************
+ *                MSFT typelibs
+ *
+ * These are TypeLibs created with ICreateTypeLib2
+ *
+ */
+
+/*
+ * structure of the typelib type2 header
+ * it is at the beginning of a type lib file
+ *
+ */
+typedef struct tagMSFT_Header {
+/*0x00*/INT magic1;       /* 0x5446534D "MSFT" */
+        INT   magic2;       /* 0x00010002 version nr? */
+        INT   posguid;      /* position of libid in guid table  */
+                            /* (should be,  else -1) */
+        INT   lcid;         /* locale id */
+/*0x10*/INT   lcid2;
+        INT   varflags;     /* (largely) unknown flags ,seems to be always 41 */
+                            /* becomes 0x51 with a helpfile defined */
+                            /* if help dll defined it's 0x151 */
+                            /* update : the lower nibble is syskind */
+        INT   version;      /* set with SetVersion() */
+        INT   flags;        /* set with SetFlags() */
+/*0x20*/INT   nrtypeinfos;  /* number of typeinfo's (till so far) */
+        INT   helpstring;   /* position of help string in stringtable */
+        INT   helpstringcontext;
+        INT   helpcontext;
+/*0x30*/INT   nametablecount;   /* number of names in name table */
+        INT   nametablechars;   /* nr of characters in name table */
+        INT   NameOffset;       /* offset of name in name table */
+        INT   helpfile;         /* position of helpfile in stringtable */
+/*0x40*/INT   CustomDataOffset; /* if -1 no custom data, else it is offset */
+                                /* in customer data/guid offset table */
+        INT   res44;            /* unknown always: 0x20 (guid hash size?) */
+        INT   res48;            /* unknown always: 0x80 (name hash size?) */
+        INT   dispatchpos;      /* HREFTYPE to IDispatch, or -1 if no IDispatch */
+/*0x50*/INT   res50;            /* is zero becomes one when an interface is derived */
+} MSFT_Header;
+
+/* segments in the type lib file have a structure like this: */
+typedef struct tagMSFT_pSeg {
+        INT   offset;       /* absolute offset in file */
+        INT   length;       /* length of segment */
+        INT   res08;        /* unknown always -1 */
+        INT   res0c;        /* unknown always 0x0f in the header */
+                            /* 0x03 in the typeinfo_data */
+} MSFT_pSeg;
+
+/* layout of the main segment directory */
+typedef struct tagMSFT_SegDir {
+/*1*/MSFT_pSeg pTypeInfoTab; /* each type info get an entry of 0x64 bytes */
+                             /* (25 ints) */
+/*2*/MSFT_pSeg pImpInfo;     /* table with info for imported types */
+/*3*/MSFT_pSeg pImpFiles;    /* import libaries */
+/*4*/MSFT_pSeg pRefTab;      /* References table */
+/*5*/MSFT_pSeg pLibtab;      /* always exists, alway same size (0x80) */
+                             /* hash table w offsets to guid????? */
+/*6*/MSFT_pSeg pGuidTab;     /* all guids are stored here together with  */
+                             /* offset in some table???? */
+/*7*/MSFT_pSeg res07;        /* always created, alway same size (0x200) */
+                             /* purpose largely unknown */
+/*8*/MSFT_pSeg pNametab;     /* name tables */
+/*9*/MSFT_pSeg pStringtab;   /* string table */
+/*A*/MSFT_pSeg pTypdescTab;  /* table with type descriptors */
+/*B*/MSFT_pSeg pArrayDescriptions;
+/*C*/MSFT_pSeg pCustData;    /* data table, used for custom data and default */
+                             /* parameter values */
+/*D*/MSFT_pSeg pCDGuids;     /* table with offsets for the guids and into */
+                             /* the customer data table */
+/*E*/MSFT_pSeg res0e;        /* unknown */
+/*F*/MSFT_pSeg res0f;        /* unknown  */
+} MSFT_SegDir;
+
+
+/* base type info data */
+typedef struct tagMSFT_TypeInfoBase {
+/*000*/ INT   typekind;             /*  it is the TKIND_xxx */
+                                    /* some byte alignment stuf */
+        INT     memoffset;          /* points past the file, if no elements */
+        INT     res2;               /* zero if no element, N*0x40 */
+        INT     res3;               /* -1 if no lement, (N-1)*0x38 */
+/*010*/ INT     res4;               /* always? 3 */
+        INT     res5;               /* always? zero */
+        INT     cElement;           /* counts elements, HI=cVars, LO=cFuncs */
+        INT     res7;               /* always? zero */
+/*020*/ INT     res8;               /* always? zero */
+        INT     res9;               /* always? zero */
+        INT     resA;               /* always? zero */
+        INT     posguid;            /* position in guid table */
+/*030*/ INT     flags;              /* Typeflags */
+        INT     NameOffset;         /* offset in name table */
+        INT     version;            /* element version */
+        INT     docstringoffs;      /* offset of docstring in string tab */
+/*040*/ INT     helpstringcontext;  /*  */
+        INT     helpcontext;    /* */
+        INT     oCustData;          /* offset in customer data table */
+#ifdef WORDS_BIGENDIAN
+        INT16   cbSizeVft;      /* virtual table size, not including inherits */
+        INT16   cImplTypes;     /* nr of implemented interfaces */
+#else
+        INT16   cImplTypes;     /* nr of implemented interfaces */
+        INT16   cbSizeVft;      /* virtual table size, not including inherits */
+#endif
+/*050*/ INT     size;           /* size in bytes, at least for structures */
+        /* FIXME: name of this field */
+        INT     datatype1;      /* position in type description table */
+                                /* or in base intefaces */
+                                /* if coclass: offset in reftable */
+                                /* if interface: reference to inherited if */
+        INT     datatype2;      /* if 0x8000, entry above is valid */
+                                /* actually dunno */
+                                /* else it is zero? */
+        INT     res18;          /* always? 0 */
+/*060*/ INT     res19;          /* always? -1 */
+    } MSFT_TypeInfoBase;
+
+/* layout of an entry with information on imported types */
+typedef struct tagMSFT_ImpInfo {
+    INT     res0;           /* unknown */
+    INT     oImpFile;       /* offset inthe Import File table */
+    INT     oGuid;          /* offset in Guid table */
+    } MSFT_ImpInfo;
+
+/* function description data */
+typedef struct {
+/*  INT   recsize;       record size including some xtra stuff */
+    INT   DataType;     /* data type of the memeber, eg return of function */
+    INT   Flags;        /* something to do with attribute flags (LOWORD) */
+#ifdef WORDS_BIGENDIAN
+    INT16 funcdescsize; /* size of reconstituted FUNCDESC and related structs */
+    INT16 VtableOffset; /* offset in vtable */
+#else
+    INT16 VtableOffset; /* offset in vtable */
+    INT16 funcdescsize; /* size of reconstituted FUNCDESC and related structs */
+#endif
+    INT   FKCCIC;       /* bit string with the following  */
+                        /* meaning (bit 0 is the msb): */
+                        /* bit 2 indicates that oEntry is numeric */
+                        /* bit 3 that parameter has default values */
+                        /* calling convention (bits 4-7 ) */
+                        /* bit 8 indicates that custom data is present */
+                        /* Invokation kind (bits 9-12 ) */
+                        /* function kind (eg virtual), bits 13-15  */
+#ifdef WORDS_BIGENDIAN
+    INT16 nroargs;      /* nr of optional arguments */
+    INT16 nrargs;       /* number of arguments (including optional ????) */
+#else
+    INT16 nrargs;       /* number of arguments (including optional ????) */
+    INT16 nroargs;      /* nr of optional arguments */
+#endif
+    /* optional attribute fields, the number of them is variable */
+    INT   OptAttr[1];
+/*
+0*  INT   helpcontext;
+1*  INT   oHelpString;
+2*  INT   oEntry;       // either offset in string table or numeric as it is //
+3*  INT   res9;         // unknown (-1) //
+4*  INT   resA;         // unknown (-1) //
+5*  INT   HelpStringContext;
+    // these are controlled by a bit set in the FKCCIC field  //
+6*  INT   oCustData;        // custom data for function //
+7*  INT   oArgCustData[1];  // custom data per argument //
+*/
+} MSFT_FuncRecord;
+
+/* after this may follow an array with default value pointers if the
+ * appropriate bit in the FKCCIC field has been set:
+ * INT   oDefautlValue[nrargs];
+ */
+
+    /* Parameter info one per argument*/
+typedef struct {
+        INT   DataType;
+        INT   oName;
+        INT   Flags;
+    } MSFT_ParameterInfo;
+
+/* Variable description data */
+typedef struct {
+/*  INT   recsize;      // record size including some xtra stuff */
+    INT   DataType;     /* data type of the variable */
+    INT   Flags;        /* VarFlags (LOWORD) */
+#ifdef WORDS_BIGENDIAN
+    INT16 vardescsize;  /* size of reconstituted VARDESC and related structs */
+    INT16 VarKind;      /* VarKind */
+#else
+    INT16 VarKind;      /* VarKind */
+    INT16 vardescsize;  /* size of reconstituted VARDESC and related structs */
+#endif
+    INT   OffsValue;    /* value of the variable or the offset  */
+                        /* in the data structure */
+    /* optional attribute fields, the number of them is variable */
+    /* controlled by record length */
+    INT   HelpContext;
+    INT   oHelpString;
+    INT   res9;         /* unknown (-1) */
+    INT   oCustData;        /* custom data for variable */
+    INT   HelpStringContext;
+
+} MSFT_VarRecord;
+
+/* Structure of the reference data  */
+typedef struct {
+    INT   reftype;  /* either offset in type info table, then it's */
+                    /* a multiple of 64 */
+                    /* or offset in the external reference table */
+                    /* with an offset of 1 */
+    INT   flags;
+    INT   oCustData;    /* custom data */
+    INT   onext;    /* next offset, -1 if last */
+} MSFT_RefRecord;
+
+/* this is how a guid is stored */
+typedef struct {
+    GUID guid;
+    INT   hreftype;     /* -2 for the typelib guid, typeinfo offset
+                          for typeinfo guid, low two bits are 01 if
+                          this is an imported typeinfo, low two bits
+                          are 10 if this is an imported typelib (used
+                          by imported typeinfos) */
+    INT   next_hash;    /* offset to next guid in the hash bucket */
+} MSFT_GuidEntry;
+/* some data preceding entries in the name table */
+typedef struct {
+    INT   hreftype;     /* is -1 if name is for neither a typeinfo,
+                          a variable, or a function (that is, name
+                          is for a typelib or a function parameter).
+                          otherwise is the offset of the first
+                          typeinfo that this name refers to (either
+                          to the typeinfo itself or to a member of
+                          the typeinfo */
+    INT   next_hash;    /* offset to next name in the hash bucket */
+    INT   namelen;      /* only lower 8 bits are valid,
+                          lower-middle 8 bits are unknown (flags?),
+                          upper 16 bits are hash code */
+} MSFT_NameIntro;
+/* the custom data table directory has enties like this */
+typedef struct {
+    INT   GuidOffset;
+    INT   DataOffset;
+    INT   next;     /* next offset in the table, -1 if it's the last */
+} MSFT_CDGuid;
+
+
+/***********************************************************
+ *
+ *                SLTG typelibs.
+ *
+ * These are created with ICreateTypeLib
+ *
+ */
+
+#include "pshpack1.h"
+
+typedef struct {
+/*00*/ DWORD SLTG_magic;       /* 0x47544c53  == "SLTG" */
+/*04*/ WORD nrOfFileBlks;      /* no of SLTG_BlkEntry's + 1 */
+/*06*/  WORD res06;            /* ?? always 9 */
+/*08*/  WORD res08;             /* some kind of len/offset ?? */
+/*0a*/ WORD first_blk;         /* 1 based index into blk entries that
+                                  corresponds to first block in file */
+/*0c*/ DWORD res0c;            /* always 0x000204ff */
+/*10*/  DWORD res10;           /* always 0x00000000 */
+/*14*/ DWORD res14;            /* always 0x000000c0 */
+/*18*/ DWORD res18;            /* always 0x46000000 */
+/*1c*/ DWORD res1c;            /* always 0x00000044 */
+/*20*/ DWORD res20;            /* always 0xffff0000 */
+} SLTG_Header;
+
+/* This gets followed by a list of block entries */
+typedef struct {
+/*00*/  DWORD len;
+/*04*/ WORD index_string; /* offs from start of SLTG_Magic to index string */
+/*06*/  WORD next;
+} SLTG_BlkEntry;
+
+/* The order of the blocks in the file is given by starting at Block
+   entry firt_blk and stepping through using the next pointer */
+
+/* These then get followed by this magic */
+typedef struct {
+/*00*/ BYTE res00;             /* always 0x01 */
+/*01*/ CHAR CompObj_magic[8];  /* always "CompObj" */
+/*09*/ CHAR dir_magic[4];      /* always "dir" */
+} SLTG_Magic;
+
+#define SLTG_COMPOBJ_MAGIC "CompObj"
+#define SLTG_DIR_MAGIC "dir"
+
+/* Next we have SLTG_Header.nrOfFileBlks - 2 of Index strings.  These
+are presumably unique to within the file and look something like
+"AAAAAAAAAA" with the first character incremented from 'A' to ensure
+uniqueness.  I guess successive chars increment when we need to wrap
+the first one. */
+
+typedef struct {
+/*00*/ CHAR string[11];
+} SLTG_Index;
+
+
+/* This is followed by SLTG_pad9 */
+typedef struct {
+/*00*/ CHAR pad[9];    /* 9 '\0's */
+} SLTG_Pad9;
+
+
+/* Now we have the noOfFileBlks - 1 worth of blocks. The length of
+each block is given by its entry in SLTG_BlkEntry. */
+
+/* type SLTG_NAME in rather like a BSTR except that the length in
+bytes is given by the first WORD and the string contains 8bit chars */
+
+typedef WORD SLTG_Name;
+
+/* The main library block looks like this.  This one seems to come last */
+
+typedef struct {
+/*00*/ WORD magic;             /* 0x51cc */
+/*02*/  WORD res02;            /* 0x0003, 0x0004 */
+/*04*/  WORD name;              /* offset to name in name table */
+/*06*/  SLTG_Name res06;       /* maybe this is just WORD == 0xffff */
+       SLTG_Name helpstring;
+       SLTG_Name helpfile;
+       DWORD helpcontext;
+       WORD syskind;           /* == 1 for win32, 0 for win16 */
+       WORD lcid;              /* == 0x409, 0x809 etc */
+       DWORD res12;            /* == 0 */
+       WORD libflags;          /* LIBFLAG_* */
+       WORD maj_vers;
+       WORD min_vers;
+       GUID uuid;
+} SLTG_LibBlk;
+
+#define SLTG_LIBBLK_MAGIC 0x51cc
+
+/* we then get 0x40 bytes worth of 0xffff or small numbers followed by
+   nrOfFileBlks - 2 of these */
+typedef struct {
+       WORD small_no;
+       SLTG_Name index_name; /* This refers to a name in the directory */
+       SLTG_Name other_name; /* Another one of these weird names */
+       WORD res1a;           /* 0xffff */
+       WORD name_offs;       /* offset to name in name table */
+       WORD more_bytes;      /* if this is non-zero we get this many
+                                bytes before the next element, which seem
+                                to reference the docstring of the type ? */
+       WORD res20;           /* 0xffff */
+       DWORD helpcontext;
+       WORD res26;           /* 0xffff */
+        GUID uuid;
+} SLTG_OtherTypeInfo;
+
+/* Next we get WORD 0x0003 followed by a DWORD which if we add to
+0x216 gives the offset to the name table from the start of the LibBlk
+struct */
+
+typedef struct {
+/*00*/ WORD magic;             /* 0x0501 */
+/*02*/ DWORD href_table;       /* if not 0xffffffff, then byte offset from
+                                  beginning of struct to href table */
+/*06*/ DWORD res06;            /* 0xffffffff */
+/*0a*/ DWORD elem_table;       /* offset to members */
+/*0e*/ DWORD res0e;            /* 0xffffffff */
+/*12*/ WORD major_version;     /* major version number */
+/*14*/  WORD minor_version;    /* minor version number */
+/*16*/ DWORD res16;    /* 0xfffe0000 */
+/*1a*/ BYTE typeflags1;/* 0x02 | top 5 bits hold l5sbs of TYPEFLAGS */
+/*1b*/ BYTE typeflags2;/* TYPEFLAGS >> 5 */
+/*1c*/ BYTE typeflags3;/* 0x02*/
+/*1d*/ BYTE typekind;  /* 0x03 == TKIND_INTERFACE etc. */
+/*1e*/  DWORD res1e;   /* 0x00000000 or 0xffffffff */
+} SLTG_TypeInfoHeader;
+
+#define SLTG_TIHEADER_MAGIC 0x0501
+
+typedef struct {
+/*00*/  WORD cFuncs;
+/*02*/  WORD cVars;
+/*04*/  WORD cImplTypes;
+/*06*/  WORD res06;
+/*08*/  WORD res08;
+/*0a*/  WORD res0a;
+/*0c*/  WORD res0c;
+/*0e*/  WORD res0e;
+/*10*/  WORD res10;
+/*12*/  WORD res12;
+/*14*/  WORD tdescalias_vt; /* for TKIND_ALIAS */
+/*16*/  WORD res16;
+/*18*/  WORD res18;
+/*1a*/  WORD res1a;
+/*1c*/  WORD res1c;
+/*1e*/  WORD res1e;
+/*20*/  WORD cbSizeInstance;
+/*22*/  WORD cbAlignment;
+/*24*/  WORD res24;
+/*26*/  WORD res26;
+/*28*/  WORD cbSizeVft;
+/*2a*/  WORD res2a;
+/*2c*/  WORD res2c;
+/*2e*/  WORD res2e;
+/*30*/  WORD res30;
+/*32*/  WORD res32;
+/*34*/  WORD res34;
+} SLTG_TypeInfoTail;
+
+typedef struct {
+/*00*/ WORD res00; /* 0x0001 sometimes 0x0003 ?? */
+/*02*/ WORD res02; /* 0xffff */
+/*04*/ BYTE res04; /* 0x01 */
+/*05*/ DWORD cbExtra; /* No of bytes that follow */
+} SLTG_MemberHeader;
+
+typedef struct {
+/*00*/ WORD magic;     /* 0x120a */
+/*02*/ WORD next;      /* offset in bytes to next block from start of block
+                           group, 0xffff if last item */
+/*04*/ WORD name;      /* offset to name within name table */
+/*06*/ WORD value;     /* offset to value from start of block group */
+/*08*/ WORD res08;     /* 0x56 */
+/*0a*/ DWORD memid;    /* memid */
+/*0e*/  WORD helpcontext;/* 0xfffe == no context, 0x0001 == stored in EnumInfo struct, else offset
+                           to value from start of block group */
+/*10*/ WORD helpstring;/* offset from start of block group to string offset */
+} SLTG_EnumItem;
+
+#define SLTG_ENUMITEM_MAGIC 0x120a
+
+typedef struct {
+/*00*/ WORD vt;        /* vartype, 0xffff marks end. */
+/*02*/ WORD res02;     /* ?, 0xffff marks end */
+} SLTG_AliasItem;
+
+#define SLTG_ALIASITEM_MAGIC 0x001d
+
+
+typedef struct {
+       BYTE magic;     /* 0x4c or 0x6c */
+       BYTE inv;       /* high nibble is INVOKE_KIND, low nibble = 2 */
+       WORD next;      /* byte offset from beginning of group to next fn */
+       WORD name;      /* Offset within name table to name */
+       DWORD dispid;   /* dispid */
+       WORD helpcontext; /* helpcontext (again 1 is special) */
+       WORD helpstring;/* helpstring offset to offset */
+       WORD arg_off;   /* offset to args from start of block */
+       BYTE nacc;      /* lowest 3bits are CALLCONV, rest are no of args */
+        BYTE retnextopt;/* if 0x80 bit set ret type follows else next WORD
+                          is offset to ret type. No of optional args is
+                          middle 6 bits */
+       WORD rettype;   /* return type VT_?? or offset to ret type */
+       WORD vtblpos;   /* position in vtbl? */
+       WORD funcflags; /* present if magic == 0x6c */
+/* Param list starts, repeat next two as required */
+#if 0
+       WORD  name;     /* offset to 2nd letter of name */
+       WORD+ type;     /* VT_ of param */
+#endif
+} SLTG_Function;
+
+#define SLTG_FUNCTION_MAGIC 0x4c
+#define SLTG_FUNCTION_WITH_FLAGS_MAGIC 0x6c
+
+typedef struct {
+/*00*/ BYTE magic;             /* 0xdf */
+/*01*/  BYTE res01;            /* 0x00 */
+/*02*/ DWORD res02;            /* 0xffffffff */
+/*06*/ DWORD res06;            /* 0xffffffff */
+/*0a*/ DWORD res0a;            /* 0xffffffff */
+/*0e*/ DWORD res0e;            /* 0xffffffff */
+/*12*/ DWORD res12;            /* 0xffffffff */
+/*16*/ DWORD res16;            /* 0xffffffff */
+/*1a*/ DWORD res1a;            /* 0xffffffff */
+/*1e*/ DWORD res1e;            /* 0xffffffff */
+/*22*/ DWORD res22;            /* 0xffffffff */
+/*26*/ DWORD res26;            /* 0xffffffff */
+/*2a*/ DWORD res2a;            /* 0xffffffff */
+/*2e*/ DWORD res2e;            /* 0xffffffff */
+/*32*/ DWORD res32;            /* 0xffffffff */
+/*36*/ DWORD res36;            /* 0xffffffff */
+/*3a*/ DWORD res3a;            /* 0xffffffff */
+/*3e*/ DWORD res3e;            /* 0xffffffff */
+/*42*/ WORD  res42;            /* 0xffff */
+/*44*/ DWORD number;           /* this is 8 times the number of refs */
+/*48*/ /* Now we have number bytes (8 for each ref) of SLTG_UnknownRefInfo */
+
+/*50*/ WORD res50;             /* 0xffff */
+/*52*/ BYTE res52;             /* 0x01 */
+/*53*/ DWORD res53;            /* 0x00000000 */
+/*57*/  SLTG_Name names[1];
+  /*    Now we have number/8 SLTG_Names (first WORD is no of bytes in the ascii
+   *    string).  Strings look like "*\Rxxxx*#n".  If xxxx == ffff then the
+   *    ref refers to the nth type listed in this library (0 based).  Else
+   *    the xxxx (which maybe fewer than 4 digits) is the offset into the name
+   *    table to a string "*\G{<guid>}#1.0#0#C:\WINNT\System32\stdole32.tlb#"
+   *    The guid is the typelib guid; the ref again refers to the nth type of
+   *    the imported typelib.
+   */
+
+/*xx*/ BYTE resxx;             /* 0xdf */
+
+} SLTG_RefInfo;
+
+#define SLTG_REF_MAGIC 0xdf
+
+typedef struct {
+       WORD res00;     /* 0x0001 */
+       BYTE res02;     /* 0x02 */
+       BYTE res03;     /* 0x40 if internal ref, 0x00 if external ? */
+       WORD res04;     /* 0xffff */
+       WORD res06;     /* 0x0000, 0x0013 or 0xffff ?? */
+} SLTG_UnknownRefInfo;
+
+typedef struct {
+  WORD res00; /* 0x004a */
+  WORD next;  /* byte offs to next interface */
+  WORD res04; /* 0xffff */
+  BYTE impltypeflags; /* IMPLTYPEFLAG_* */
+  BYTE res07; /* 0x80 */
+  WORD res08; /* 0x0012, 0x0028 ?? */
+  WORD ref;   /* number in ref table ? */
+  WORD res0c; /* 0x4000 */
+  WORD res0e; /* 0xfffe */
+  WORD res10; /* 0xffff */
+  WORD res12; /* 0x001d */
+  WORD pos_in_table; /* 0x0, 0x4, ? */
+} SLTG_ImplInfo;
+
+#define SLTG_IMPL_MAGIC 0x004a
+
+typedef struct {
+  BYTE magic; /* 0x0a */
+  BYTE typepos;
+  WORD next;
+  WORD name;
+  WORD byte_offs; /* pos in struct */
+  WORD type; /* if typepos == 0x02 this is the type, else offset to type */
+  DWORD memid;
+  WORD helpcontext; /* ?? */
+  WORD helpstring; /* ?? */
+} SLTG_RecordItem;
+
+#define SLTG_RECORD_MAGIC 0x0a
+
+
+/* CARRAYs look like this
+WORD type == VT_CARRAY
+WORD offset from start of block to SAFEARRAY
+WORD typeofarray
+*/
+
+#include "poppack.h"
+
+/*---------------------------END--------------------------------------------*/
+#endif
index 4918b4e6784f53d06e030ec0c2b87df440a59276..f04c984c4d478f241cab6ccb581691889e70c857 100644 (file)
@@ -33,10 +33,6 @@ typedef GUID UUID;
 #define TRUE 1
 #define FALSE 0
 
-#define LOWORD(l) ((unsigned short)(l))
-#define HIWORD(l) ((unsigned short)((unsigned long)(l) >> 16))
-#define MAKELONG(low,high) ((unsigned long)(((unsigned short)(low)) | (((unsigned long)((unsigned short)(high))) << 16)))
-
 typedef struct _attr_t attr_t;
 typedef struct _expr_t expr_t;
 typedef struct _type_t type_t;
@@ -177,7 +173,7 @@ struct _type_t {
   var_t *fields;
   int ignore, is_const, sign;
   int defined, written;
-
+  int typelib_idx;
   /* parser-internal */
   DECL_LINK(type_t)
 };
diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c
new file mode 100644 (file)
index 0000000..5f557ee
--- /dev/null
@@ -0,0 +1,1603 @@
+/*
+ *      Typelib v2 (MSFT) generation
+ *
+ *     Copyright 2004  Alastair Bridgewater
+ *                2004, 2005 Huw Davies
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * --------------------------------------------------------------------------------------
+ *  Known problems:
+ *
+ *    Badly incomplete.
+ *
+ *    Only works on little-endian systems.
+ *
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+
+#include "winerror.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+
+#include "wine/unicode.h"
+
+#include "widltypes.h"
+#include "typelib.h"
+#include "typelib_struct.h"
+#include "utils.h"
+#include "hash.h"
+
+enum MSFT_segment_index {
+    MSFT_SEG_TYPEINFO = 0,  /* type information */
+    MSFT_SEG_IMPORTINFO,    /* import information */
+    MSFT_SEG_IMPORTFILES,   /* import filenames */
+    MSFT_SEG_REFERENCES,    /* references (?) */
+    MSFT_SEG_GUIDHASH,      /* hash table for guids? */
+    MSFT_SEG_GUID,          /* guid storage */
+    MSFT_SEG_NAMEHASH,      /* hash table for names */
+    MSFT_SEG_NAME,          /* name storage */
+    MSFT_SEG_STRING,        /* string storage */
+    MSFT_SEG_TYPEDESC,      /* type descriptions */
+    MSFT_SEG_ARRAYDESC,     /* array descriptions */
+    MSFT_SEG_CUSTDATA,      /* custom data */
+    MSFT_SEG_CUSTDATAGUID,  /* custom data guids */
+    MSFT_SEG_UNKNOWN,       /* ??? */
+    MSFT_SEG_UNKNOWN2,      /* ??? */
+    MSFT_SEG_MAX            /* total number of segments */
+};
+
+typedef struct tagMSFT_ImpFile {
+    int guid;
+    LCID lcid;
+    int version;
+    char filename[0]; /* preceeded by two bytes of encoded (length << 2) + flags in the low two bits. */
+} MSFT_ImpFile;
+
+typedef struct _msft_typelib_t
+{
+    typelib_t *typelib;
+    MSFT_Header typelib_header;
+    MSFT_pSeg typelib_segdir[MSFT_SEG_MAX];
+    char *typelib_segment_data[MSFT_SEG_MAX];
+    int typelib_segment_block_length[MSFT_SEG_MAX];
+
+    INT typelib_typeinfo_offsets[0x200]; /* Hope that's enough. */
+
+    INT *typelib_namehash_segment;
+    INT *typelib_guidhash_segment;
+
+    struct _msft_typeinfo_t *typeinfos;
+    struct _msft_typeinfo_t *last_typeinfo;
+} msft_typelib_t;
+
+typedef struct _msft_typeinfo_t
+{
+    msft_typelib_t *typelib;
+    MSFT_TypeInfoBase *typeinfo;
+
+    INT *typedata;
+    int typedata_allocated;
+    int typedata_length;
+
+    int indices[42];
+    int names[42];
+    int offsets[42];
+
+    int datawidth;
+
+    struct _msft_typeinfo_t *next_typeinfo;
+} msft_typeinfo_t;
+
+
+
+/*================== Internal functions ===================================*/
+
+/****************************************************************************
+ *     ctl2_init_header
+ *
+ *  Initializes the type library header of a new typelib.
+ */
+static void ctl2_init_header(
+       msft_typelib_t *typelib) /* [I] The typelib to initialize. */
+{
+    typelib->typelib_header.magic1 = 0x5446534d;
+    typelib->typelib_header.magic2 = 0x00010002;
+    typelib->typelib_header.posguid = -1;
+    typelib->typelib_header.lcid = 0x0409; /* or do we use the current one? */
+    typelib->typelib_header.lcid2 = 0x0;
+    typelib->typelib_header.varflags = 0x40;
+    typelib->typelib_header.version = 0;
+    typelib->typelib_header.flags = 0;
+    typelib->typelib_header.nrtypeinfos = 0;
+    typelib->typelib_header.helpstring = -1;
+    typelib->typelib_header.helpstringcontext = 0;
+    typelib->typelib_header.helpcontext = 0;
+    typelib->typelib_header.nametablecount = 0;
+    typelib->typelib_header.nametablechars = 0;
+    typelib->typelib_header.NameOffset = -1;
+    typelib->typelib_header.helpfile = -1;
+    typelib->typelib_header.CustomDataOffset = -1;
+    typelib->typelib_header.res44 = 0x20;
+    typelib->typelib_header.res48 = 0x80;
+    typelib->typelib_header.dispatchpos = -1;
+    typelib->typelib_header.res50 = 0;
+}
+
+/****************************************************************************
+ *     ctl2_init_segdir
+ *
+ *  Initializes the segment directory of a new typelib.
+ */
+static void ctl2_init_segdir(
+       msft_typelib_t *typelib) /* [I] The typelib to initialize. */
+{
+    int i;
+    MSFT_pSeg *segdir;
+
+    segdir = &typelib->typelib_segdir[MSFT_SEG_TYPEINFO];
+
+    for (i = 0; i < 15; i++) {
+       segdir[i].offset = -1;
+       segdir[i].length = 0;
+       segdir[i].res08 = -1;
+       segdir[i].res0c = 0x0f;
+    }
+}
+
+/****************************************************************************
+ *     ctl2_hash_guid
+ *
+ *  Generates a hash key from a GUID.
+ *
+ * RETURNS
+ *
+ *  The hash key for the GUID.
+ */
+static int ctl2_hash_guid(
+       REFGUID guid)                /* [I] The guid to find. */
+{
+    int hash;
+    int i;
+
+    hash = 0;
+    for (i = 0; i < 8; i ++) {
+       hash ^= ((const short *)guid)[i];
+    }
+
+    return (hash & 0xf) | ((hash & 0x10) & (0 - !!(hash & 0xe0)));
+}
+
+/****************************************************************************
+ *     ctl2_find_guid
+ *
+ *  Locates a guid in a type library.
+ *
+ * RETURNS
+ *
+ *  The offset into the GUID segment of the guid, or -1 if not found.
+ */
+static int ctl2_find_guid(
+       msft_typelib_t *typelib,   /* [I] The typelib to operate against. */
+       int hash_key,              /* [I] The hash key for the guid. */
+       REFGUID guid)              /* [I] The guid to find. */
+{
+    int offset;
+    MSFT_GuidEntry *guidentry;
+
+    offset = typelib->typelib_guidhash_segment[hash_key];
+    while (offset != -1) {
+       guidentry = (MSFT_GuidEntry *)&typelib->typelib_segment_data[MSFT_SEG_GUID][offset];
+
+       if (!memcmp(guidentry, guid, sizeof(GUID))) return offset;
+
+       offset = guidentry->next_hash;
+    }
+
+    return offset;
+}
+
+/****************************************************************************
+ *     ctl2_find_name
+ *
+ *  Locates a name in a type library.
+ *
+ * RETURNS
+ *
+ *  The offset into the NAME segment of the name, or -1 if not found.
+ *
+ * NOTES
+ *
+ *  The name must be encoded as with ctl2_encode_name().
+ */
+static int ctl2_find_name(
+       msft_typelib_t *typelib,   /* [I] The typelib to operate against. */
+       char *name)                /* [I] The encoded name to find. */
+{
+    int offset;
+    int *namestruct;
+
+    offset = typelib->typelib_namehash_segment[name[2] & 0x7f];
+    while (offset != -1) {
+       namestruct = (int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][offset];
+
+       if (!((namestruct[2] ^ *((int *)name)) & 0xffff00ff)) {
+           /* hash codes and lengths match, final test */
+           if (!strncasecmp(name+4, (void *)(namestruct+3), name[0])) break;
+       }
+
+       /* move to next item in hash bucket */
+       offset = namestruct[1];
+    }
+
+    return offset;
+}
+
+/****************************************************************************
+ *     ctl2_encode_name
+ *
+ *  Encodes a name string to a form suitable for storing into a type library
+ *  or comparing to a name stored in a type library.
+ *
+ * RETURNS
+ *
+ *  The length of the encoded name, including padding and length+hash fields.
+ *
+ * NOTES
+ *
+ *  Will throw an exception if name or result are NULL. Is not multithread
+ *  safe in the slightest.
+ */
+static int ctl2_encode_name(
+       msft_typelib_t *typelib,   /* [I] The typelib to operate against (used for LCID only). */
+       const char *name,          /* [I] The name string to encode. */
+       char **result)             /* [O] A pointer to a pointer to receive the encoded name. */
+{
+    int length;
+    static char converted_name[0x104];
+    int offset;
+    int value;
+
+    length = strlen(name);
+    memcpy(converted_name + 4, name, length);
+    converted_name[0] = length & 0xff;
+
+    converted_name[length + 4] = 0;
+
+    converted_name[1] = 0x00;
+
+    value = lhash_val_of_name_sys(typelib->typelib_header.varflags & 0x0f, typelib->typelib_header.lcid, converted_name + 4);
+
+    converted_name[2] = value;
+    converted_name[3] = value >> 8;
+
+    for (offset = (4 - length) & 3; offset; offset--) converted_name[length + offset + 3] = 0x57;
+
+    *result = converted_name;
+
+    return (length + 7) & ~3;
+}
+
+/****************************************************************************
+ *     ctl2_encode_string
+ *
+ *  Encodes a string to a form suitable for storing into a type library or
+ *  comparing to a string stored in a type library.
+ *
+ * RETURNS
+ *
+ *  The length of the encoded string, including padding and length fields.
+ *
+ * NOTES
+ *
+ *  Will throw an exception if string or result are NULL. Is not multithread
+ *  safe in the slightest.
+ */
+static int ctl2_encode_string(
+       msft_typelib_t *typelib,   /* [I] The typelib to operate against (not used?). */
+       const char *string,        /* [I] The string to encode. */
+       char **result)             /* [O] A pointer to a pointer to receive the encoded string. */
+{
+    int length;
+    static char converted_string[0x104];
+    int offset;
+
+    length = strlen(string);
+    memcpy(converted_string + 2, string, length);
+    converted_string[0] = length & 0xff;
+    converted_string[1] = (length >> 8) & 0xff;
+
+    for (offset = (4 - (length + 2)) & 3; offset; offset--) converted_string[length + offset + 1] = 0x57;
+
+    *result = converted_string;
+
+    return (length + 5) & ~3;
+}
+
+/****************************************************************************
+ *     ctl2_alloc_segment
+ *
+ *  Allocates memory from a segment in a type library.
+ *
+ * RETURNS
+ *
+ *  Success: The offset within the segment of the new data area.
+ *  Failure: -1 (this is invariably an out of memory condition).
+ *
+ * BUGS
+ *
+ *  Does not (yet) handle the case where the allocated segment memory needs to grow.
+ */
+static int ctl2_alloc_segment(
+       msft_typelib_t *typelib,         /* [I] The type library in which to allocate. */
+       enum MSFT_segment_index segment, /* [I] The segment in which to allocate. */
+       int size,                        /* [I] The amount to allocate. */
+       int block_size)                  /* [I] Initial allocation block size, or 0 for default. */
+{
+    int offset;
+
+    if(!typelib->typelib_segment_data[segment]) {
+       if (!block_size) block_size = 0x2000;
+
+       typelib->typelib_segment_block_length[segment] = block_size;
+       typelib->typelib_segment_data[segment] = xmalloc(block_size);
+       if (!typelib->typelib_segment_data[segment]) return -1;
+       memset(typelib->typelib_segment_data[segment], 0x57, block_size);
+    }
+
+    while ((typelib->typelib_segdir[segment].length + size) > typelib->typelib_segment_block_length[segment]) {
+       char *block;
+
+       block_size = typelib->typelib_segment_block_length[segment];
+       block = realloc(typelib->typelib_segment_data[segment], block_size << 1);
+       if (!block) return -1;
+
+       if (segment == MSFT_SEG_TYPEINFO) {
+           /* TypeInfos have a direct pointer to their memory space, so we have to fix them up. */
+           msft_typeinfo_t *typeinfo;
+
+           for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
+               typeinfo->typeinfo = (void *)&block[((char *)typeinfo->typeinfo) - typelib->typelib_segment_data[segment]];
+           }
+       }
+
+       memset(block + block_size, 0x57, block_size);
+       typelib->typelib_segment_block_length[segment] = block_size << 1;
+       typelib->typelib_segment_data[segment] = block;
+    }
+
+    offset = typelib->typelib_segdir[segment].length;
+    typelib->typelib_segdir[segment].length += size;
+
+    return offset;
+}
+
+/****************************************************************************
+ *     ctl2_alloc_typeinfo
+ *
+ *  Allocates and initializes a typeinfo structure in a type library.
+ *
+ * RETURNS
+ *
+ *  Success: The offset of the new typeinfo.
+ *  Failure: -1 (this is invariably an out of memory condition).
+ */
+static int ctl2_alloc_typeinfo(
+       msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
+       int nameoffset)            /* [I] The offset of the name for this typeinfo. */
+{
+    int offset;
+    MSFT_TypeInfoBase *typeinfo;
+
+    offset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEINFO, sizeof(MSFT_TypeInfoBase), 0);
+    if (offset == -1) return -1;
+
+    typelib->typelib_typeinfo_offsets[typelib->typelib_header.nrtypeinfos++] = offset;
+
+    typeinfo = (void *)(typelib->typelib_segment_data[MSFT_SEG_TYPEINFO] + offset);
+
+    typeinfo->typekind = (typelib->typelib_header.nrtypeinfos - 1) << 16;
+    typeinfo->memoffset = -1; /* should be EOF if no elements */
+    typeinfo->res2 = 0;
+    typeinfo->res3 = -1;
+    typeinfo->res4 = 3;
+    typeinfo->res5 = 0;
+    typeinfo->cElement = 0;
+    typeinfo->res7 = 0;
+    typeinfo->res8 = 0;
+    typeinfo->res9 = 0;
+    typeinfo->resA = 0;
+    typeinfo->posguid = -1;
+    typeinfo->flags = 0;
+    typeinfo->NameOffset = nameoffset;
+    typeinfo->version = 0;
+    typeinfo->docstringoffs = -1;
+    typeinfo->helpstringcontext = 0;
+    typeinfo->helpcontext = 0;
+    typeinfo->oCustData = -1;
+    typeinfo->cbSizeVft = 0;
+    typeinfo->cImplTypes = 0;
+    typeinfo->size = 0;
+    typeinfo->datatype1 = -1;
+    typeinfo->datatype2 = 0;
+    typeinfo->res18 = 0;
+    typeinfo->res19 = -1;
+
+    return offset;
+}
+
+/****************************************************************************
+ *     ctl2_alloc_guid
+ *
+ *  Allocates and initializes a GUID structure in a type library. Also updates
+ *  the GUID hash table as needed.
+ *
+ * RETURNS
+ *
+ *  Success: The offset of the new GUID.
+ *  Failure: -1 (this is invariably an out of memory condition).
+ */
+static int ctl2_alloc_guid(
+       msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
+       MSFT_GuidEntry *guid)      /* [I] The GUID to store. */
+{
+    int offset;
+    MSFT_GuidEntry *guid_space;
+    int hash_key;
+
+    hash_key = ctl2_hash_guid(&guid->guid);
+
+    offset = ctl2_find_guid(typelib, hash_key, &guid->guid);
+    if (offset != -1) return offset;
+
+    offset = ctl2_alloc_segment(typelib, MSFT_SEG_GUID, sizeof(MSFT_GuidEntry), 0);
+    if (offset == -1) return -1;
+
+    guid_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_GUID] + offset);
+    *guid_space = *guid;
+
+    guid_space->next_hash = typelib->typelib_guidhash_segment[hash_key];
+    typelib->typelib_guidhash_segment[hash_key] = offset;
+
+    return offset;
+}
+
+/****************************************************************************
+ *     ctl2_alloc_name
+ *
+ *  Allocates and initializes a name within a type library. Also updates the
+ *  name hash table as needed.
+ *
+ * RETURNS
+ *
+ *  Success: The offset within the segment of the new name.
+ *  Failure: -1 (this is invariably an out of memory condition).
+ */
+static int ctl2_alloc_name(
+       msft_typelib_t *typelib,  /* [I] The type library to allocate in. */
+       const char *name)         /* [I] The name to store. */
+{
+    int length;
+    int offset;
+    MSFT_NameIntro *name_space;
+    char *encoded_name;
+
+    length = ctl2_encode_name(typelib, name, &encoded_name);
+
+    offset = ctl2_find_name(typelib, encoded_name);
+    if (offset != -1) return offset;
+
+    offset = ctl2_alloc_segment(typelib, MSFT_SEG_NAME, length + 8, 0);
+    if (offset == -1) return -1;
+
+    name_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_NAME] + offset);
+    name_space->hreftype = -1;
+    name_space->next_hash = -1;
+    memcpy(&name_space->namelen, encoded_name, length);
+
+    if (typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] != -1)
+       name_space->next_hash = typelib->typelib_namehash_segment[encoded_name[2] & 0x7f];
+
+    typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] = offset;
+
+    typelib->typelib_header.nametablecount += 1;
+    typelib->typelib_header.nametablechars += *encoded_name;
+
+    return offset;
+}
+
+/****************************************************************************
+ *     ctl2_alloc_string
+ *
+ *  Allocates and initializes a string in a type library.
+ *
+ * RETURNS
+ *
+ *  Success: The offset within the segment of the new string.
+ *  Failure: -1 (this is invariably an out of memory condition).
+ */
+static int ctl2_alloc_string(
+       msft_typelib_t *typelib,  /* [I] The type library to allocate in. */
+       const char *string)       /* [I] The string to store. */
+{
+    int length;
+    int offset;
+    char *string_space;
+    char *encoded_string;
+
+    length = ctl2_encode_string(typelib, string, &encoded_string);
+
+    for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_STRING].length;
+        offset += ((((typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 1] << 8) & 0xff)
+            | (typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 0] & 0xff)) + 5) & ~3) {
+       if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_STRING] + offset, length)) return offset;
+    }
+
+    offset = ctl2_alloc_segment(typelib, MSFT_SEG_STRING, length, 0);
+    if (offset == -1) return -1;
+
+    string_space = typelib->typelib_segment_data[MSFT_SEG_STRING] + offset;
+    memcpy(string_space, encoded_string, length);
+
+    return offset;
+}
+
+/****************************************************************************
+ *     ctl2_alloc_importinfo
+ *
+ *  Allocates and initializes an import information structure in a type library.
+ *
+ * RETURNS
+ *
+ *  Success: The offset of the new importinfo.
+ *  Failure: -1 (this is invariably an out of memory condition).
+ */
+static int ctl2_alloc_importinfo(
+        msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
+       MSFT_ImpInfo *impinfo)     /* [I] The import information to store. */
+{
+    int offset;
+    MSFT_ImpInfo *impinfo_space;
+
+    for (offset = 0;
+        offset < typelib->typelib_segdir[MSFT_SEG_IMPORTINFO].length;
+        offset += sizeof(MSFT_ImpInfo)) {
+       if (!memcmp(&(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO][offset]),
+                   impinfo, sizeof(MSFT_ImpInfo))) {
+           return offset;
+       }
+    }
+
+    offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTINFO, sizeof(MSFT_ImpInfo), 0);
+    if (offset == -1) return -1;
+
+    impinfo_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO] + offset);
+    *impinfo_space = *impinfo;
+
+    return offset;
+}
+
+/****************************************************************************
+ *     ctl2_alloc_importfile
+ *
+ *  Allocates and initializes an import file definition in a type library.
+ *
+ * RETURNS
+ *
+ *  Success: The offset of the new importinfo.
+ *  Failure: -1 (this is invariably an out of memory condition).
+ */
+static int ctl2_alloc_importfile(
+       msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
+       int guidoffset,            /* [I] The offset to the GUID for the imported library. */
+       int major_version,         /* [I] The major version number of the imported library. */
+       int minor_version,         /* [I] The minor version number of the imported library. */
+       const char *filename)      /* [I] The filename of the imported library. */
+{
+    int length;
+    int offset;
+    MSFT_ImpFile *importfile;
+    char *encoded_string;
+
+    length = ctl2_encode_string(typelib, filename, &encoded_string);
+
+    encoded_string[0] <<= 2;
+    encoded_string[0] |= 1;
+
+    for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_IMPORTFILES].length;
+        offset += ((((typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xd] << 8) & 0xff)
+            | (typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xc] & 0xff)) >> 2) + 0xc) {
+       if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES] + offset + 0xc, length)) return offset;
+    }
+
+    offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTFILES, length + 0xc, 0);
+    if (offset == -1) return -1;
+
+    importfile = (MSFT_ImpFile *)&typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset];
+    importfile->guid = guidoffset;
+    importfile->lcid = typelib->typelib_header.lcid2;
+    importfile->version = major_version | (minor_version << 16);
+    memcpy(&importfile->filename, encoded_string, length);
+
+    return offset;
+}
+
+
+/****************************************************************************
+ *     ctl2_encode_typedesc
+ *
+ *  Encodes a type description, storing information in the TYPEDESC and ARRAYDESC
+ *  segments as needed.
+ *
+ * RETURNS
+ *
+ *  Success: 0.
+ *  Failure: -1.
+ */
+static int ctl2_encode_type(
+       msft_typelib_t *typelib,   /* [I] The type library in which to encode the TYPEDESC. */
+       type_t *type,              /* [I] The type description to encode. */
+        int ptr_level,             /* [I] ptr level */
+        expr_t *array,             /* [I] arrary description */
+       int *encoded_type,         /* [O] The encoded type description. */
+       int *width,                /* [O] The width of the type, or NULL. */
+       int *alignment,            /* [O] The alignment of the type, or NULL. */
+       int *decoded_size)         /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */
+{
+    int default_type;
+    int scratch;
+    int typeoffset;
+    int arrayoffset;
+    int *typedata;
+    int *arraydata;
+    int target_type;
+    int child_size;
+    unsigned short vt = get_type_vt(type);
+
+    chat("encode_type vt %d ptr_level %d\n", vt, ptr_level);
+
+    default_type = 0x80000000 | (vt << 16) | vt;
+    if (!width) width = &scratch;
+    if (!alignment) alignment = &scratch;
+    if (!decoded_size) decoded_size = &scratch;
+
+    *decoded_size = 0;
+
+    if(ptr_level--) {
+
+       ctl2_encode_type(typelib, type, ptr_level, array, &target_type, NULL, NULL, &child_size);
+
+       for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
+           typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+           if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
+       }
+
+       if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
+           int mix_field;
+           
+           if (target_type & 0x80000000) {
+               mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
+           } else {
+               typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
+               mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
+           }
+
+           typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
+           typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+
+           typedata[0] = (mix_field << 16) | VT_PTR;
+           typedata[1] = target_type;
+       }
+
+       *encoded_type = typeoffset;
+
+       *width = 4;
+       *alignment = 4;
+       *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
+        return 0;
+    }
+
+    if(array) {
+        expr_t *dim = array;
+        int num_dims = 1, elements = 1;
+
+        while(NEXT_LINK(dim)) {
+            dim = NEXT_LINK(dim);
+            num_dims++;
+        }
+        chat("array with %d dimensions\n", num_dims);
+       ctl2_encode_type(typelib, type, 0, NULL, &target_type, width, alignment, NULL);
+       arrayoffset = ctl2_alloc_segment(typelib, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(long), 0);
+       arraydata = (void *)&typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
+
+       arraydata[0] = target_type;
+        arraydata[1] = num_dims;
+        arraydata[1] |= ((num_dims * 2 * sizeof(long)) << 16);
+
+        arraydata += 2;
+        while(dim) {
+            arraydata[0] = dim->cval;
+            arraydata[1] = 0;
+            arraydata += 2;
+            elements *= dim->cval;
+            dim = PREV_LINK(dim);
+        }
+
+       typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
+       typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+
+       typedata[0] = (0x7ffe << 16) | VT_CARRAY;
+       typedata[1] = arrayoffset;
+
+       *encoded_type = typeoffset;
+       *width = *width * elements;
+       *decoded_size = 20 /*sizeof(ARRAYDESC)*/ + (num_dims - 1) * 8 /*sizeof(SAFEARRAYBOUND)*/;
+        return 0;
+    }
+
+    switch (vt) {
+    case VT_I1:
+    case VT_UI1:
+       *encoded_type = default_type;
+       *width = 1;
+       *alignment = 1;
+       break;
+
+    case VT_INT:
+       *encoded_type = 0x80000000 | (VT_I4 << 16) | VT_INT;
+       if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) {
+           *width = 2;
+           *alignment = 2;
+       } else {
+           *width = 4;
+           *alignment = 4;
+       }
+       break;
+
+    case VT_UINT:
+       *encoded_type = 0x80000000 | (VT_UI4 << 16) | VT_UINT;
+       if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) {
+           *width = 2;
+           *alignment = 2;
+       } else {
+           *width = 4;
+           *alignment = 4;
+       }
+       break;
+
+    case VT_UI2:
+    case VT_I2:
+    case VT_BOOL:
+       *encoded_type = default_type;
+       *width = 2;
+       *alignment = 2;
+       break;
+
+    case VT_I4:
+    case VT_UI4:
+    case VT_R4:
+    case VT_ERROR:
+    case VT_BSTR:
+    case VT_HRESULT:
+       *encoded_type = default_type;
+       *width = 4;
+       *alignment = 4;
+       break;
+
+    case VT_CY:
+       *encoded_type = default_type;
+       *width = 8;
+       *alignment = 4; /* guess? */
+       break;
+
+    case VT_VOID:
+       *encoded_type = 0x80000000 | (VT_EMPTY << 16) | vt;
+       *width = 0;
+       *alignment = 1;
+       break;
+
+#if 0
+
+
+    case VT_SAFEARRAY:
+       /* FIXME: Make with the error checking. */
+       FIXME("SAFEARRAY vartype, may not work correctly.\n");
+
+       ctl2_encode_typedesc(typelib, tdesc->u.lptdesc, &target_type, NULL, NULL, &child_size);
+
+       for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
+           typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+           if (((typedata[0] & 0xffff) == VT_SAFEARRAY) && (typedata[1] == target_type)) break;
+       }
+
+       if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
+           int mix_field;
+           
+           if (target_type & 0x80000000) {
+               mix_field = ((target_type >> 16) & VT_TYPEMASK) | VT_ARRAY;
+           } else {
+               typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
+               mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
+           }
+
+           typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
+           typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+
+           typedata[0] = (mix_field << 16) | VT_SAFEARRAY;
+           typedata[1] = target_type;
+       }
+
+       *encoded_tdesc = typeoffset;
+
+       *width = 4;
+       *alignment = 4;
+       *decoded_size = sizeof(TYPEDESC) + child_size;
+       break;
+
+
+#endif
+
+    case VT_USERDEFINED:
+      {
+        int typeinfo_offset;
+       chat("USERDEFINED.\n");
+        chat("type %p name = %s idx %d\n", type, type->name, type->typelib_idx);
+
+        if(type->typelib_idx == -1)
+            error("trying to ref not added type\n");
+
+        typeinfo_offset = typelib->typelib_typeinfo_offsets[type->typelib_idx];
+       for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
+           typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+           if ((typedata[0] == ((0x7fff << 16) | VT_USERDEFINED)) && (typedata[1] == typeinfo_offset)) break;
+       }
+
+       if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
+           typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
+           typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+
+           typedata[0] = (0x7fff << 16) | VT_USERDEFINED;
+           typedata[1] = typeinfo_offset;
+       }
+
+       *encoded_type = typeoffset;
+       *width = 0;
+       *alignment = 1;
+       break;
+      }
+
+    default:
+       error("Unrecognized type %d.\n", vt);
+       *encoded_type = default_type;
+       *width = 0;
+       *alignment = 1;
+       break;
+    }
+
+    return 0;
+}
+
+/****************************************************************************
+ *     ctl2_find_nth_reference
+ *
+ *  Finds a reference by index into the linked list of reference records.
+ *
+ * RETURNS
+ *
+ *  Success: Offset of the desired reference record.
+ *  Failure: -1.
+ */
+static int ctl2_find_nth_reference(
+       msft_typelib_t *typelib,   /* [I] The type library in which to search. */
+       int offset,                /* [I] The starting offset of the reference list. */
+       int index)                 /* [I] The index of the reference to find. */
+{
+    MSFT_RefRecord *ref;
+
+    for (; index && (offset != -1); index--) {
+       ref = (MSFT_RefRecord *)&typelib->typelib_segment_data[MSFT_SEG_REFERENCES][offset];
+       offset = ref->onext;
+    }
+
+    return offset;
+}
+
+
+static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func)
+{
+    int offset;
+    int *typedata;
+    int i, index = func->idx, id;
+    int decoded_size;
+    int num_params = 0;
+    var_t *arg, *last_arg = NULL;
+    char *namedata;
+    attr_t *attr;
+    unsigned int funcflags = 0, callconv = 4;
+
+    id = ((0x6000 | typeinfo->typeinfo->cImplTypes) << 16) | index;
+
+    chat("(%p,%d)\n", typeinfo, index);
+    
+    if (!typeinfo->typedata) {
+       typeinfo->typedata = xmalloc(0x2000);
+       typeinfo->typedata[0] = 0;
+    }
+
+    for(arg = func->args; arg; arg = NEXT_LINK(arg)) {
+        last_arg = arg;
+        num_params++;
+    }
+
+    chat("num of params %d\n", num_params);
+
+    for(attr = func->def->attrs; attr; attr = NEXT_LINK(attr)) {
+        switch(attr->type) {
+        case ATTR_ID:
+          {
+            expr_t *expr = attr->u.pval; 
+            id = expr->u.lval;
+            break;
+          }
+        case ATTR_OUT:
+            break;
+
+        default:
+            warning("ignoring attr %d\n", attr->type);
+            break;
+        }
+    }
+    /* allocate type data space for us */
+    offset = typeinfo->typedata[0];
+    typeinfo->typedata[0] += 0x18 + (num_params * 12);
+    typedata = typeinfo->typedata + (offset >> 2) + 1;
+
+    /* fill out the basic type information */
+    typedata[0] = (0x18 + (num_params * 12)) | (index << 16);
+    ctl2_encode_type(typeinfo->typelib, func->def->type, func->def->ptr_level, func->def->array, &typedata[1], NULL, NULL, &decoded_size);
+    typedata[2] = funcflags;
+    typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft;
+    typedata[4] = (index << 16) | (callconv << 8) | 9;
+    typedata[5] = num_params;
+
+    /* NOTE: High word of typedata[3] is total size of FUNCDESC + size of all ELEMDESCs for params + TYPEDESCs for pointer params and return types. */
+    /* That is, total memory allocation required to reconstitute the FUNCDESC in its entirety. */
+    typedata[3] += (16 /*sizeof(ELEMDESC)*/ * num_params) << 16;
+
+    for (arg = last_arg, i = 0; arg; arg = PREV_LINK(arg), i++) {
+        attr_t *attr;
+        int paramflags = 0;
+
+        for(attr = arg->attrs; attr; attr = NEXT_LINK(attr)) {
+            switch(attr->type) {
+            case ATTR_IN:
+                paramflags |= 0x01; /* PARAMFLAG_FIN */
+                break;
+            case ATTR_OUT:
+                paramflags |= 0x02; /* PARAMFLAG_FOUT */
+                break;
+            case ATTR_RETVAL:
+                paramflags |= 0x08; /* PARAMFLAG_FRETVAL */
+                break;
+            default:
+                chat("unhandled param attr %d\n", attr->type);
+                break;
+            }
+        }
+       ctl2_encode_type(typeinfo->typelib, arg->type, arg->ptr_level, arg->array, &typedata[6+(i*3)], NULL, NULL, &decoded_size);
+       typedata[7+(i*3)] = -1;
+       typedata[8+(i*3)] = paramflags;
+       typedata[3] += decoded_size << 16;
+
+#if 0
+       /* FIXME: Doesn't work. Doesn't even come up with usable VTs for varDefaultValue. */
+       if (pFuncDesc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) {
+           ctl2_alloc_custdata(This->typelib, &pFuncDesc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
+       }
+#endif
+    }
+
+    /* update the index data */
+    typeinfo->indices[index] = id; 
+    typeinfo->names[index] = -1;
+    typeinfo->offsets[index] = offset;
+
+    /* ??? */
+    if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x20;
+    typeinfo->typeinfo->res2 <<= 1;
+
+    /* ??? */
+    if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0;
+    typeinfo->typeinfo->res3 += 0x38;
+
+    /* ??? */
+    if (index < 2) typeinfo->typeinfo->res2 += num_params << 4;
+    typeinfo->typeinfo->res3 += num_params << 4;
+
+    /* adjust size of VTBL */
+    typeinfo->typeinfo->cbSizeVft += 4;
+
+    /* Increment the number of function elements */
+    typeinfo->typeinfo->cElement += 1;
+
+
+    offset = ctl2_alloc_name(typeinfo->typelib, func->def->name);
+    chat("name offset = %d index %d\n", offset, index);
+    typeinfo->names[index] = offset;
+
+    namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset;
+    namedata[9] &= ~0x10;
+    if (*((INT *)namedata) == -1) {
+       *((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16];
+    }
+
+    for (arg = last_arg, i = 0; arg; arg = PREV_LINK(arg), i++) {
+       /* FIXME: Almost certainly easy to break */
+       int *paramdata = &typeinfo->typedata[typeinfo->offsets[index] >> 2];
+        
+       offset = ctl2_alloc_name(typeinfo->typelib, arg->name);
+       paramdata[(i * 3) + 8] = offset;
+        chat("param %d name %s offset %d\n", i, arg->name, offset);
+    }
+    return S_OK;
+}
+
+
+static void set_alignment(
+        msft_typeinfo_t* typeinfo,
+        WORD cbAlignment)
+{
+
+    if (!cbAlignment) return;
+    if (cbAlignment > 16) return;
+
+    typeinfo->typeinfo->typekind &= ~0xffc0;
+    typeinfo->typeinfo->typekind |= cbAlignment << 6;
+
+    /* FIXME: There's probably some way to simplify this. */
+    switch (typeinfo->typeinfo->typekind & 15) {
+    case TKIND_ALIAS:
+    default:
+       break;
+
+    case TKIND_ENUM:
+    case TKIND_INTERFACE:
+    case TKIND_DISPATCH:
+    case TKIND_COCLASS:
+       if (cbAlignment > 4) cbAlignment = 4;
+       break;
+
+    case TKIND_RECORD:
+    case TKIND_MODULE:
+    case TKIND_UNION:
+       cbAlignment = 1;
+       break;
+    }
+
+    typeinfo->typeinfo->typekind |= cbAlignment << 11;
+
+    return;
+}
+
+static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var)
+{
+    int offset;
+    INT *typedata;
+    int var_datawidth;
+    int var_alignment;
+    int var_type_size;
+    int alignment;
+    int varflags = 0;
+    attr_t *attr;
+    char *namedata;
+
+    chat("add_var_desc(%d,%s) array %p\n", index, var->name, var->array);
+
+    if ((typeinfo->typeinfo->cElement >> 16) != index) {
+       error("Out-of-order element.\n");
+       return TYPE_E_ELEMENTNOTFOUND;
+    }
+
+
+    for(attr = var->attrs; attr; attr = NEXT_LINK(attr)) {
+        switch(attr->type) {
+        default:
+            warning("AddVarDesc: unhandled attr type %d\n", attr->type);
+            break;
+        }
+    }
+
+    if (!typeinfo->typedata) {
+       typeinfo->typedata = xmalloc(0x2000);
+       typeinfo->typedata[0] = 0;
+    }
+
+    /* allocate type data space for us */
+    offset = typeinfo->typedata[0];
+    typeinfo->typedata[0] += 0x14;
+    typedata = typeinfo->typedata + (offset >> 2) + 1;
+
+    /* fill out the basic type information */
+    typedata[0] = 0x14 | (index << 16);
+    typedata[2] = varflags;
+    typedata[3] = (36 /*sizeof(VARDESC)*/ << 16) | 0;
+
+    /* update the index data */
+    typeinfo->indices[index] = 0x40000000 + index;
+    typeinfo->names[index] = -1;
+    typeinfo->offsets[index] = offset;
+
+    /* figure out type widths and whatnot */
+    ctl2_encode_type(typeinfo->typelib, var->type, var->ptr_level, var->array,
+                     &typedata[1], &var_datawidth, &var_alignment,
+                     &var_type_size);
+
+    /* pad out starting position to data width */
+    typeinfo->datawidth += var_alignment - 1;
+    typeinfo->datawidth &= ~(var_alignment - 1);
+    typedata[4] = typeinfo->datawidth;
+    
+    /* add the new variable to the total data width */
+    typeinfo->datawidth += var_datawidth;
+
+    /* add type description size to total required allocation */
+    typedata[3] += var_type_size << 16;
+
+    /* fix type alignment */
+    alignment = (typeinfo->typeinfo->typekind >> 11) & 0x1f;
+    if (alignment < var_alignment) {
+       alignment = var_alignment;
+       typeinfo->typeinfo->typekind &= ~0xf800;
+       typeinfo->typeinfo->typekind |= alignment << 11;
+    }
+
+    /* ??? */
+    if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x1a;
+    if ((index == 0) || (index == 1) || (index == 2) || (index == 4) || (index == 9)) {
+       typeinfo->typeinfo->res2 <<= 1;
+    }
+
+    /* ??? */
+    if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0;
+    typeinfo->typeinfo->res3 += 0x2c;
+
+    /* increment the number of variable elements */
+    typeinfo->typeinfo->cElement += 0x10000;
+
+    /* pad data width to alignment */
+    typeinfo->typeinfo->size = (typeinfo->datawidth + (alignment - 1)) & ~(alignment - 1);
+
+    offset = ctl2_alloc_name(typeinfo->typelib, var->name);
+    if (offset == -1) return E_OUTOFMEMORY;
+
+    namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset;
+    if (*((INT *)namedata) == -1) {
+       *((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16];
+       namedata[9] |= 0x10;
+    }
+    if ((typeinfo->typeinfo->typekind & 15) == TKIND_ENUM) {
+       namedata[9] |= 0x20;
+    }
+    typeinfo->names[index] = offset;
+
+    return S_OK;
+}
+
+
+static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, typelib_entry_t *entry, int idx)
+{
+    msft_typeinfo_t *msft_typeinfo;
+    int nameoffset;
+    int typeinfo_offset;
+    MSFT_TypeInfoBase *typeinfo;
+    char *name;
+    MSFT_GuidEntry guidentry;
+    attr_t *attr;
+
+    switch(entry->kind) {
+    case TKIND_INTERFACE:
+        name = entry->u.interface->name;
+        attr = entry->u.interface->attrs;
+        entry->u.interface->typelib_idx = idx;
+        break;
+    case TKIND_MODULE:
+        name = entry->u.module->name;
+        attr = entry->u.module->attrs;
+        break;
+    case TKIND_COCLASS:
+        name = entry->u.class->name;
+        attr = entry->u.class->attrs;
+        break;
+    case TKIND_RECORD:
+        name = entry->u.structure->name;
+        attr = entry->u.structure->attrs;
+        entry->u.structure->typelib_idx = idx;
+        chat("type = %p\n", entry->u.structure);
+        break;
+    default:
+        error("create_msft_typeinfo: unhandled type %d\n", entry->kind);
+        return NULL;
+    }
+
+
+    chat("Constructing msft_typeinfo for name %s kind %d\n", name, entry->kind);
+
+    msft_typeinfo = xmalloc(sizeof(*msft_typeinfo));
+
+    msft_typeinfo->typelib = typelib;
+
+    nameoffset = ctl2_alloc_name(typelib, name);
+    typeinfo_offset = ctl2_alloc_typeinfo(typelib, nameoffset);
+    typeinfo = (MSFT_TypeInfoBase *)&typelib->typelib_segment_data[MSFT_SEG_TYPEINFO][typeinfo_offset];
+
+    typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset + 9] = 0x38;
+    *((int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset]) = typeinfo_offset;
+
+    msft_typeinfo->typeinfo = typeinfo;
+
+    typeinfo->typekind |= entry->kind | 0x20;
+    set_alignment(msft_typeinfo, 4);
+
+    switch (entry->kind) {
+    case TKIND_ENUM:
+    case TKIND_INTERFACE:
+    case TKIND_DISPATCH:
+    case TKIND_COCLASS:
+       typeinfo->size = 4;
+       break;
+
+    case TKIND_RECORD:
+    case TKIND_UNION:
+       typeinfo->size = 0;
+       break;
+
+    case TKIND_MODULE:
+       typeinfo->size = 2;
+       break;
+
+    case TKIND_ALIAS:
+       typeinfo->size = -0x75;
+       break;
+
+    default:
+       error("%s unrecognized typekind %d\n", name, entry->kind);
+       typeinfo->size = 0xdeadbeef;
+       break;
+    }
+
+
+    for( ; attr; attr = NEXT_LINK(attr)) {
+        if(attr->type == ATTR_UUID) {
+            guidentry.guid = *(GUID*)attr->u.pval;
+            guidentry.hreftype = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16];
+            guidentry.next_hash = -1;
+            typeinfo->posguid = ctl2_alloc_guid(typelib, &guidentry);
+#if 0
+            if (IsEqualIID(guid, &IID_IDispatch)) {
+                typelib->typelib_header.dispatchpos = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16];
+            }
+#endif
+        }
+    }
+
+    if (typelib->last_typeinfo) typelib->last_typeinfo->next_typeinfo = msft_typeinfo;
+    typelib->last_typeinfo = msft_typeinfo;
+    if (!typelib->typeinfos) typelib->typeinfos = msft_typeinfo;
+
+
+    return msft_typeinfo;
+}
+
+
+static void set_name(msft_typelib_t *typelib)
+{
+    int offset;
+
+    offset = ctl2_alloc_name(typelib, typelib->typelib->name);
+    if (offset == -1) return;
+    typelib->typelib_header.NameOffset = offset;
+    return;
+}
+
+static void set_version(msft_typelib_t *typelib)
+{
+    long version = MAKELONG(0,0);
+    attr_t *attr;
+
+    for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
+        if(attr->type == ATTR_VERSION) {
+            version = attr->u.ival;
+        }
+    }
+    typelib->typelib_header.version = version;
+    return;
+}
+
+static void set_guid(msft_typelib_t *typelib)
+{
+    MSFT_GuidEntry guidentry;
+    int offset;
+    attr_t *attr;
+    GUID guid = {0,0,0,{0,0,0,0,0,0}};
+
+    guidentry.guid = guid;
+    guidentry.hreftype = -2;
+    guidentry.next_hash = -1;
+
+    for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
+        if(attr->type == ATTR_UUID) {
+            guidentry.guid = *(GUID*)(attr->u.pval);
+        }
+    }
+
+    offset = ctl2_alloc_guid(typelib, &guidentry);
+    
+    if (offset == -1) return;
+
+    typelib->typelib_header.posguid = offset;
+
+    return;
+}
+
+static void set_doc_string(msft_typelib_t *typelib)
+{
+    attr_t *attr;
+    int offset;
+
+    for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
+        if(attr->type == ATTR_HELPSTRING) {
+            offset = ctl2_alloc_string(typelib, attr->u.pval);
+            if (offset == -1) return;
+            typelib->typelib_header.helpstring = offset;
+        }
+    }
+    return;
+}
+
+static void set_help_file_name(msft_typelib_t *typelib)
+{
+    int offset;
+    offset = ctl2_alloc_string(typelib, "help file name");
+    if (offset == -1) return;
+    typelib->typelib_header.helpfile = offset;
+    typelib->typelib_header.varflags |= 0x10;
+    return;
+}
+
+static void set_lcid(msft_typelib_t *typelib)
+{
+    typelib->typelib_header.lcid2 = 0x0;
+    return;
+}
+
+static void set_lib_flags(msft_typelib_t *typelib)
+{
+    typelib->typelib_header.flags = 0;
+    return;
+}
+
+static int ctl2_write_chunk(int fd, void *segment, int length)
+{
+    if (write(fd, segment, length) != length) {
+        close(fd);
+        return 0;
+    }
+    return -1;
+}
+
+static int ctl2_write_segment(msft_typelib_t *typelib, int fd, int segment)
+{
+    if (write(fd, typelib->typelib_segment_data[segment], typelib->typelib_segdir[segment].length)
+        != typelib->typelib_segdir[segment].length) {
+       close(fd);
+       return 0;
+    }
+
+    return -1;
+}
+
+static void ctl2_finalize_typeinfos(msft_typelib_t *typelib, int filesize)
+{
+    msft_typeinfo_t *typeinfo;
+
+    for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
+       typeinfo->typeinfo->memoffset = filesize;
+       if (typeinfo->typedata) {
+           /*LayOut(typeinfo);*/
+           filesize += typeinfo->typedata[0] + ((typeinfo->typeinfo->cElement >> 16) * 12) + ((typeinfo->typeinfo->cElement & 0xffff) * 12) + 4;
+       }
+    }
+}
+
+static int ctl2_finalize_segment(msft_typelib_t *typelib, int filepos, int segment)
+{
+    if (typelib->typelib_segdir[segment].length) {
+       typelib->typelib_segdir[segment].offset = filepos;
+    } else {
+       typelib->typelib_segdir[segment].offset = -1;
+    }
+
+    return typelib->typelib_segdir[segment].length;
+}
+
+
+static void ctl2_write_typeinfos(msft_typelib_t *typelib, int fd)
+{
+    msft_typeinfo_t *typeinfo;
+
+    for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
+       if (!typeinfo->typedata) continue;
+
+       ctl2_write_chunk(fd, typeinfo->typedata, typeinfo->typedata[0] + 4);
+       ctl2_write_chunk(fd, typeinfo->indices, ((typeinfo->typeinfo->cElement & 0xffff) + (typeinfo->typeinfo->cElement >> 16)) * 4);
+        chat("writing name chunk len %d %08lx\n", ((typeinfo->typeinfo->cElement & 0xffff) + (typeinfo->typeinfo->cElement >> 16)) * 4, *(DWORD*)typeinfo->names);
+       ctl2_write_chunk(fd, typeinfo->names, ((typeinfo->typeinfo->cElement & 0xffff) + (typeinfo->typeinfo->cElement >> 16)) * 4);
+       ctl2_write_chunk(fd, typeinfo->offsets, ((typeinfo->typeinfo->cElement & 0xffff) + (typeinfo->typeinfo->cElement >> 16)) * 4);
+    }
+}
+
+static int save_all_changes(msft_typelib_t *typelib)
+{
+    int retval;
+    int filepos;
+    int fd;
+
+    chat("save_all_changes(%p)\n", typelib);
+
+    retval = TYPE_E_IOERROR;
+
+    fd = creat(typelib->typelib->filename, 0666);
+    if (fd == -1) return retval;
+
+    filepos = sizeof(MSFT_Header) + sizeof(MSFT_SegDir);
+    filepos += typelib->typelib_header.nrtypeinfos * 4;
+
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_TYPEINFO);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_GUIDHASH);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_GUID);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_IMPORTINFO);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_IMPORTFILES);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_REFERENCES);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_NAMEHASH);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_NAME);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_STRING);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_TYPEDESC);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_ARRAYDESC);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_CUSTDATA);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_CUSTDATAGUID);
+
+    ctl2_finalize_typeinfos(typelib, filepos);
+
+    if (!ctl2_write_chunk(fd, &typelib->typelib_header, sizeof(typelib->typelib_header))) return retval;
+    if (!ctl2_write_chunk(fd, typelib->typelib_typeinfo_offsets, typelib->typelib_header.nrtypeinfos * 4)) return retval;
+    if (!ctl2_write_chunk(fd, &typelib->typelib_segdir, sizeof(typelib->typelib_segdir))) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_TYPEINFO    )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_GUIDHASH    )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_GUID        )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_IMPORTINFO  )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_IMPORTFILES )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_REFERENCES  )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_NAMEHASH    )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_NAME        )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_STRING      )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_TYPEDESC    )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_ARRAYDESC   )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_CUSTDATA    )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_CUSTDATAGUID)) return retval;
+
+    ctl2_write_typeinfos(typelib, fd);
+
+    if (close(fd) == -1) return retval;
+
+    retval = S_OK;
+    return retval;
+}
+
+
+
+
+int create_msft_typelib(typelib_t *typelib)
+{
+    msft_typelib_t *msft;
+    int failed = 0, typelib_idx;
+    typelib_entry_t *entry;
+
+    msft = malloc(sizeof(*msft));
+    if (!msft) return 0;
+    memset(msft, 0, sizeof(*msft));
+    msft->typelib = typelib;
+
+    ctl2_init_header(msft);
+    ctl2_init_segdir(msft);
+
+    msft->typelib_header.varflags |= SYS_WIN32;
+
+    /*
+     * The following two calls return an offset or -1 if out of memory. We
+     * specifically need an offset of 0, however, so...
+     */
+    if (ctl2_alloc_segment(msft, MSFT_SEG_GUIDHASH, 0x80, 0x80)) { failed = 1; }
+    if (ctl2_alloc_segment(msft, MSFT_SEG_NAMEHASH, 0x200, 0x200)) { failed = 1; }
+
+    if(failed) return 0;
+
+    msft->typelib_guidhash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_GUIDHASH];
+    msft->typelib_namehash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_NAMEHASH];
+
+    memset(msft->typelib_guidhash_segment, 0xff, 0x80);
+    memset(msft->typelib_namehash_segment, 0xff, 0x200);
+
+    set_lib_flags(msft);
+    set_lcid(msft);
+/*    set_help_file_name(msft);*/
+    set_doc_string(msft);
+    set_guid(msft);
+    set_version(msft);
+    set_name(msft);
+
+    typelib_idx = 0;
+    for(entry = typelib->entry; NEXT_LINK(entry); entry = NEXT_LINK(entry))
+        ;
+    for( ; entry; entry = PREV_LINK(entry)) {
+        msft_typeinfo_t *msft_typeinfo = create_msft_typeinfo(msft, entry, typelib_idx);
+        switch(entry->kind) {
+        case TKIND_INTERFACE:
+          {
+            int idx = 0;
+            func_t *cur = entry->u.interface->funcs;
+            while(NEXT_LINK(cur)) cur = NEXT_LINK(cur);
+            while(cur) {
+                if(cur->idx == -1) cur->idx = idx;
+                else if(cur->idx != idx) error("method index mismatch\n");
+                add_func_desc(msft_typeinfo, cur);
+                idx++;
+                cur = PREV_LINK(cur);
+            }
+            break;
+          }
+        case TKIND_RECORD:
+          {
+            int idx = 0;
+            var_t *cur = entry->u.structure->fields;
+            while(NEXT_LINK(cur)) cur = NEXT_LINK(cur);
+            while(cur) {
+                add_var_desc(msft_typeinfo, idx, cur);
+                idx++;
+                cur = PREV_LINK(cur);
+            }
+            break;
+          }
+                
+        default:
+            error("create_msft_typelib: unhandled type %d\n", entry->kind);
+            break;
+        }
+        typelib_idx++;
+    }
+    save_all_changes(msft);
+    return 1;
+}