--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}