From 928873cf853bd8697360ecb18d1a75d3234219ff Mon Sep 17 00:00:00 2001 From: Dmitry Chapyshev Date: Wed, 21 Jan 2009 14:10:09 +0000 Subject: [PATCH] - Add itss and msimtf from Wine - Update README.WINE svn path=/trunk/; revision=38995 --- reactos/boot/bootdata/packages/reactos.dff | 2 + reactos/dll/win32/itss/chm_lib.c | 1651 ++++++++++++++++++++ reactos/dll/win32/itss/chm_lib.h | 136 ++ reactos/dll/win32/itss/itss.c | 447 ++++++ reactos/dll/win32/itss/itss.inf | 79 + reactos/dll/win32/itss/itss.rbuild | 23 + reactos/dll/win32/itss/itss.spec | 6 + reactos/dll/win32/itss/itsstor.h | 46 + reactos/dll/win32/itss/lzx.c | 832 ++++++++++ reactos/dll/win32/itss/lzx.h | 60 + reactos/dll/win32/itss/moniker.c | 480 ++++++ reactos/dll/win32/itss/protocol.c | 488 ++++++ reactos/dll/win32/itss/rsrc.rc | 20 + reactos/dll/win32/itss/storage.c | 840 ++++++++++ reactos/dll/win32/msimtf/activeimmapp.c | 827 ++++++++++ reactos/dll/win32/msimtf/main.c | 219 +++ reactos/dll/win32/msimtf/msimtf.inf | 26 + reactos/dll/win32/msimtf/msimtf.rbuild | 17 + reactos/dll/win32/msimtf/msimtf.spec | 6 + reactos/dll/win32/msimtf/rsrc.rc | 20 + reactos/dll/win32/win32.rbuild | 6 + reactos/media/doc/README.WINE | 3 + 22 files changed, 6234 insertions(+) create mode 100644 reactos/dll/win32/itss/chm_lib.c create mode 100644 reactos/dll/win32/itss/chm_lib.h create mode 100644 reactos/dll/win32/itss/itss.c create mode 100644 reactos/dll/win32/itss/itss.inf create mode 100644 reactos/dll/win32/itss/itss.rbuild create mode 100644 reactos/dll/win32/itss/itss.spec create mode 100644 reactos/dll/win32/itss/itsstor.h create mode 100644 reactos/dll/win32/itss/lzx.c create mode 100644 reactos/dll/win32/itss/lzx.h create mode 100644 reactos/dll/win32/itss/moniker.c create mode 100644 reactos/dll/win32/itss/protocol.c create mode 100644 reactos/dll/win32/itss/rsrc.rc create mode 100644 reactos/dll/win32/itss/storage.c create mode 100644 reactos/dll/win32/msimtf/activeimmapp.c create mode 100644 reactos/dll/win32/msimtf/main.c create mode 100644 reactos/dll/win32/msimtf/msimtf.inf create mode 100644 reactos/dll/win32/msimtf/msimtf.rbuild create mode 100644 reactos/dll/win32/msimtf/msimtf.spec create mode 100644 reactos/dll/win32/msimtf/rsrc.rc diff --git a/reactos/boot/bootdata/packages/reactos.dff b/reactos/boot/bootdata/packages/reactos.dff index 008f8192cc7..89f17e641b1 100644 --- a/reactos/boot/bootdata/packages/reactos.dff +++ b/reactos/boot/bootdata/packages/reactos.dff @@ -271,6 +271,7 @@ dll\win32\imm32\imm32.dll 1 dll\win32\inetcomm\inetcomm.dll 1 dll\win32\inetmib1\inetmib1.dll 1 dll\win32\iphlpapi\iphlpapi.dll 1 +dll\win32\itss\itss.dll 1 dll\win32\jscript\jscript.dll 1 dll\win32\kernel32\kernel32.dll 1 dll\win32\localui\localui.dll 1 @@ -290,6 +291,7 @@ dll\win32\mshtml\mshtml.dll 1 dll\win32\mshtml.tlb\mshtml.tlb 1 dll\win32\msi\msi.dll 1 dll\win32\msimg32\msimg32.dll 1 +dll\win32\msimtf\msimtf.dll 1 dll\win32\mstask\mstask.dll 1 dll\win32\msvcrt\msvcrt.dll 1 dll\win32\msvcrt20\msvcrt20.dll 1 diff --git a/reactos/dll/win32/itss/chm_lib.c b/reactos/dll/win32/itss/chm_lib.c new file mode 100644 index 00000000000..6b80ef2b92a --- /dev/null +++ b/reactos/dll/win32/itss/chm_lib.c @@ -0,0 +1,1651 @@ +/*************************************************************************** + * chm_lib.c - CHM archive manipulation routines * + * ------------------- * + * * + * author: Jed Wing * + * version: 0.3 * + * notes: These routines are meant for the manipulation of microsoft * + * .chm (compiled html help) files, but may likely be used * + * for the manipulation of any ITSS archive, if ever ITSS * + * archives are used for any other purpose. * + * * + * Note also that the section names are statically handled. * + * To be entirely correct, the section names should be read * + * from the section names meta-file, and then the various * + * content sections and the "transforms" to apply to the data * + * they contain should be inferred from the section name and * + * the meta-files referenced using that name; however, all of * + * the files I've been able to get my hands on appear to have * + * only two sections: Uncompressed and MSCompressed. * + * Additionally, the ITSS.DLL file included with Windows does * + * not appear to handle any different transforms than the * + * simple LZX-transform. Furthermore, the list of transforms * + * to apply is broken, in that only half the required space * + * is allocated for the list. (It appears as though the * + * space is allocated for ASCII strings, but the strings are * + * written as unicode. As a result, only the first half of * + * the string appears.) So this is probably not too big of * + * a deal, at least until CHM v4 (MS .lit files), which also * + * incorporate encryption, of some description. * + * * + ***************************************************************************/ + +/*************************************************************************** + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + ***************************************************************************/ + +/*************************************************************************** + * * + * Adapted for Wine by Mike McCormack * + * * + ***************************************************************************/ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wine/unicode.h" + +#include "chm_lib.h" +#include "lzx.h" + +#define CHM_ACQUIRE_LOCK(a) do { \ + EnterCriticalSection(&(a)); \ + } while(0) +#define CHM_RELEASE_LOCK(a) do { \ + LeaveCriticalSection(&(a)); \ + } while(0) + +#define CHM_NULL_FD (INVALID_HANDLE_VALUE) +#define CHM_CLOSE_FILE(fd) CloseHandle((fd)) + +/* + * defines related to tuning + */ +#ifndef CHM_MAX_BLOCKS_CACHED +#define CHM_MAX_BLOCKS_CACHED 5 +#endif +#define CHM_PARAM_MAX_BLOCKS_CACHED 0 + +/* + * architecture specific defines + * + * Note: as soon as C99 is more widespread, the below defines should + * probably just use the C99 sized-int types. + * + * The following settings will probably work for many platforms. The sizes + * don't have to be exactly correct, but the types must accommodate at least as + * many bits as they specify. + */ + +/* i386, 32-bit, Windows */ +typedef BYTE UChar; +typedef SHORT Int16; +typedef USHORT UInt16; +typedef LONG Int32; +typedef DWORD UInt32; +typedef LONGLONG Int64; +typedef ULONGLONG UInt64; + +/* utilities for unmarshalling data */ +static int _unmarshal_char_array(unsigned char **pData, + unsigned int *pLenRemain, + char *dest, + int count) +{ + if (count <= 0 || (unsigned int)count > *pLenRemain) + return 0; + memcpy(dest, (*pData), count); + *pData += count; + *pLenRemain -= count; + return 1; +} + +static int _unmarshal_uchar_array(unsigned char **pData, + unsigned int *pLenRemain, + unsigned char *dest, + int count) +{ + if (count <= 0 || (unsigned int)count > *pLenRemain) + return 0; + memcpy(dest, (*pData), count); + *pData += count; + *pLenRemain -= count; + return 1; +} + +static int _unmarshal_int32(unsigned char **pData, + unsigned int *pLenRemain, + Int32 *dest) +{ + if (4 > *pLenRemain) + return 0; + *dest = (*pData)[0] | (*pData)[1]<<8 | (*pData)[2]<<16 | (*pData)[3]<<24; + *pData += 4; + *pLenRemain -= 4; + return 1; +} + +static int _unmarshal_uint32(unsigned char **pData, + unsigned int *pLenRemain, + UInt32 *dest) +{ + if (4 > *pLenRemain) + return 0; + *dest = (*pData)[0] | (*pData)[1]<<8 | (*pData)[2]<<16 | (*pData)[3]<<24; + *pData += 4; + *pLenRemain -= 4; + return 1; +} + +static int _unmarshal_int64(unsigned char **pData, + unsigned int *pLenRemain, + Int64 *dest) +{ + Int64 temp; + int i; + if (8 > *pLenRemain) + return 0; + temp=0; + for(i=8; i>0; i--) + { + temp <<= 8; + temp |= (*pData)[i-1]; + } + *dest = temp; + *pData += 8; + *pLenRemain -= 8; + return 1; +} + +static int _unmarshal_uint64(unsigned char **pData, + unsigned int *pLenRemain, + UInt64 *dest) +{ + UInt64 temp; + int i; + if (8 > *pLenRemain) + return 0; + temp=0; + for(i=8; i>0; i--) + { + temp <<= 8; + temp |= (*pData)[i-1]; + } + *dest = temp; + *pData += 8; + *pLenRemain -= 8; + return 1; +} + +static int _unmarshal_uuid(unsigned char **pData, + unsigned int *pDataLen, + unsigned char *dest) +{ + return _unmarshal_uchar_array(pData, pDataLen, dest, 16); +} + +/* names of sections essential to decompression */ +static const WCHAR _CHMU_RESET_TABLE[] = { +':',':','D','a','t','a','S','p','a','c','e','/', + 'S','t','o','r','a','g','e','/', + 'M','S','C','o','m','p','r','e','s','s','e','d','/', + 'T','r','a','n','s','f','o','r','m','/', + '{','7','F','C','2','8','9','4','0','-','9','D','3','1', + '-','1','1','D','0','-','9','B','2','7','-', + '0','0','A','0','C','9','1','E','9','C','7','C','}','/', + 'I','n','s','t','a','n','c','e','D','a','t','a','/', + 'R','e','s','e','t','T','a','b','l','e',0 +}; +static const WCHAR _CHMU_LZXC_CONTROLDATA[] = { +':',':','D','a','t','a','S','p','a','c','e','/', + 'S','t','o','r','a','g','e','/', + 'M','S','C','o','m','p','r','e','s','s','e','d','/', + 'C','o','n','t','r','o','l','D','a','t','a',0 +}; +static const WCHAR _CHMU_CONTENT[] = { +':',':','D','a','t','a','S','p','a','c','e','/', + 'S','t','o','r','a','g','e','/', + 'M','S','C','o','m','p','r','e','s','s','e','d','/', + 'C','o','n','t','e','n','t',0 +}; + +/* + * structures local to this module + */ + +/* structure of ITSF headers */ +#define _CHM_ITSF_V2_LEN (0x58) +#define _CHM_ITSF_V3_LEN (0x60) +struct chmItsfHeader +{ + char signature[4]; /* 0 (ITSF) */ + Int32 version; /* 4 */ + Int32 header_len; /* 8 */ + Int32 unknown_000c; /* c */ + UInt32 last_modified; /* 10 */ + UInt32 lang_id; /* 14 */ + UChar dir_uuid[16]; /* 18 */ + UChar stream_uuid[16]; /* 28 */ + UInt64 unknown_offset; /* 38 */ + UInt64 unknown_len; /* 40 */ + UInt64 dir_offset; /* 48 */ + UInt64 dir_len; /* 50 */ + UInt64 data_offset; /* 58 (Not present before V3) */ +}; /* __attribute__ ((aligned (1))); */ + +static int _unmarshal_itsf_header(unsigned char **pData, + unsigned int *pDataLen, + struct chmItsfHeader *dest) +{ + /* we only know how to deal with the 0x58 and 0x60 byte structures */ + if (*pDataLen != _CHM_ITSF_V2_LEN && *pDataLen != _CHM_ITSF_V3_LEN) + return 0; + + /* unmarshal common fields */ + _unmarshal_char_array(pData, pDataLen, dest->signature, 4); + _unmarshal_int32 (pData, pDataLen, &dest->version); + _unmarshal_int32 (pData, pDataLen, &dest->header_len); + _unmarshal_int32 (pData, pDataLen, &dest->unknown_000c); + _unmarshal_uint32 (pData, pDataLen, &dest->last_modified); + _unmarshal_uint32 (pData, pDataLen, &dest->lang_id); + _unmarshal_uuid (pData, pDataLen, dest->dir_uuid); + _unmarshal_uuid (pData, pDataLen, dest->stream_uuid); + _unmarshal_uint64 (pData, pDataLen, &dest->unknown_offset); + _unmarshal_uint64 (pData, pDataLen, &dest->unknown_len); + _unmarshal_uint64 (pData, pDataLen, &dest->dir_offset); + _unmarshal_uint64 (pData, pDataLen, &dest->dir_len); + + /* error check the data */ + /* XXX: should also check UUIDs, probably, though with a version 3 file, + * current MS tools do not seem to use them. + */ + if (memcmp(dest->signature, "ITSF", 4) != 0) + return 0; + if (dest->version == 2) + { + if (dest->header_len < _CHM_ITSF_V2_LEN) + return 0; + } + else if (dest->version == 3) + { + if (dest->header_len < _CHM_ITSF_V3_LEN) + return 0; + } + else + return 0; + + /* now, if we have a V3 structure, unmarshal the rest. + * otherwise, compute it + */ + if (dest->version == 3) + { + if (*pDataLen != 0) + _unmarshal_uint64(pData, pDataLen, &dest->data_offset); + else + return 0; + } + else + dest->data_offset = dest->dir_offset + dest->dir_len; + + return 1; +} + +/* structure of ITSP headers */ +#define _CHM_ITSP_V1_LEN (0x54) +struct chmItspHeader +{ + char signature[4]; /* 0 (ITSP) */ + Int32 version; /* 4 */ + Int32 header_len; /* 8 */ + Int32 unknown_000c; /* c */ + UInt32 block_len; /* 10 */ + Int32 blockidx_intvl; /* 14 */ + Int32 index_depth; /* 18 */ + Int32 index_root; /* 1c */ + Int32 index_head; /* 20 */ + Int32 unknown_0024; /* 24 */ + UInt32 num_blocks; /* 28 */ + Int32 unknown_002c; /* 2c */ + UInt32 lang_id; /* 30 */ + UChar system_uuid[16]; /* 34 */ + UChar unknown_0044[16]; /* 44 */ +}; /* __attribute__ ((aligned (1))); */ + +static int _unmarshal_itsp_header(unsigned char **pData, + unsigned int *pDataLen, + struct chmItspHeader *dest) +{ + /* we only know how to deal with a 0x54 byte structures */ + if (*pDataLen != _CHM_ITSP_V1_LEN) + return 0; + + /* unmarshal fields */ + _unmarshal_char_array(pData, pDataLen, dest->signature, 4); + _unmarshal_int32 (pData, pDataLen, &dest->version); + _unmarshal_int32 (pData, pDataLen, &dest->header_len); + _unmarshal_int32 (pData, pDataLen, &dest->unknown_000c); + _unmarshal_uint32 (pData, pDataLen, &dest->block_len); + _unmarshal_int32 (pData, pDataLen, &dest->blockidx_intvl); + _unmarshal_int32 (pData, pDataLen, &dest->index_depth); + _unmarshal_int32 (pData, pDataLen, &dest->index_root); + _unmarshal_int32 (pData, pDataLen, &dest->index_head); + _unmarshal_int32 (pData, pDataLen, &dest->unknown_0024); + _unmarshal_uint32 (pData, pDataLen, &dest->num_blocks); + _unmarshal_int32 (pData, pDataLen, &dest->unknown_002c); + _unmarshal_uint32 (pData, pDataLen, &dest->lang_id); + _unmarshal_uuid (pData, pDataLen, dest->system_uuid); + _unmarshal_uchar_array(pData, pDataLen, dest->unknown_0044, 16); + + /* error check the data */ + if (memcmp(dest->signature, "ITSP", 4) != 0) + return 0; + if (dest->version != 1) + return 0; + if (dest->header_len != _CHM_ITSP_V1_LEN) + return 0; + + return 1; +} + +/* structure of PMGL headers */ +static const char _chm_pmgl_marker[4] = "PMGL"; +#define _CHM_PMGL_LEN (0x14) +struct chmPmglHeader +{ + char signature[4]; /* 0 (PMGL) */ + UInt32 free_space; /* 4 */ + UInt32 unknown_0008; /* 8 */ + Int32 block_prev; /* c */ + Int32 block_next; /* 10 */ +}; /* __attribute__ ((aligned (1))); */ + +static int _unmarshal_pmgl_header(unsigned char **pData, + unsigned int *pDataLen, + struct chmPmglHeader *dest) +{ + /* we only know how to deal with a 0x14 byte structures */ + if (*pDataLen != _CHM_PMGL_LEN) + return 0; + + /* unmarshal fields */ + _unmarshal_char_array(pData, pDataLen, dest->signature, 4); + _unmarshal_uint32 (pData, pDataLen, &dest->free_space); + _unmarshal_uint32 (pData, pDataLen, &dest->unknown_0008); + _unmarshal_int32 (pData, pDataLen, &dest->block_prev); + _unmarshal_int32 (pData, pDataLen, &dest->block_next); + + /* check structure */ + if (memcmp(dest->signature, _chm_pmgl_marker, 4) != 0) + return 0; + + return 1; +} + +/* structure of PMGI headers */ +static const char _chm_pmgi_marker[4] = "PMGI"; +#define _CHM_PMGI_LEN (0x08) +struct chmPmgiHeader +{ + char signature[4]; /* 0 (PMGI) */ + UInt32 free_space; /* 4 */ +}; /* __attribute__ ((aligned (1))); */ + +static int _unmarshal_pmgi_header(unsigned char **pData, + unsigned int *pDataLen, + struct chmPmgiHeader *dest) +{ + /* we only know how to deal with a 0x8 byte structures */ + if (*pDataLen != _CHM_PMGI_LEN) + return 0; + + /* unmarshal fields */ + _unmarshal_char_array(pData, pDataLen, dest->signature, 4); + _unmarshal_uint32 (pData, pDataLen, &dest->free_space); + + /* check structure */ + if (memcmp(dest->signature, _chm_pmgi_marker, 4) != 0) + return 0; + + return 1; +} + +/* structure of LZXC reset table */ +#define _CHM_LZXC_RESETTABLE_V1_LEN (0x28) +struct chmLzxcResetTable +{ + UInt32 version; + UInt32 block_count; + UInt32 unknown; + UInt32 table_offset; + UInt64 uncompressed_len; + UInt64 compressed_len; + UInt64 block_len; +}; /* __attribute__ ((aligned (1))); */ + +static int _unmarshal_lzxc_reset_table(unsigned char **pData, + unsigned int *pDataLen, + struct chmLzxcResetTable *dest) +{ + /* we only know how to deal with a 0x28 byte structures */ + if (*pDataLen != _CHM_LZXC_RESETTABLE_V1_LEN) + return 0; + + /* unmarshal fields */ + _unmarshal_uint32 (pData, pDataLen, &dest->version); + _unmarshal_uint32 (pData, pDataLen, &dest->block_count); + _unmarshal_uint32 (pData, pDataLen, &dest->unknown); + _unmarshal_uint32 (pData, pDataLen, &dest->table_offset); + _unmarshal_uint64 (pData, pDataLen, &dest->uncompressed_len); + _unmarshal_uint64 (pData, pDataLen, &dest->compressed_len); + _unmarshal_uint64 (pData, pDataLen, &dest->block_len); + + /* check structure */ + if (dest->version != 2) + return 0; + + return 1; +} + +/* structure of LZXC control data block */ +#define _CHM_LZXC_MIN_LEN (0x18) +#define _CHM_LZXC_V2_LEN (0x1c) +struct chmLzxcControlData +{ + UInt32 size; /* 0 */ + char signature[4]; /* 4 (LZXC) */ + UInt32 version; /* 8 */ + UInt32 resetInterval; /* c */ + UInt32 windowSize; /* 10 */ + UInt32 windowsPerReset; /* 14 */ + UInt32 unknown_18; /* 18 */ +}; + +static int _unmarshal_lzxc_control_data(unsigned char **pData, + unsigned int *pDataLen, + struct chmLzxcControlData *dest) +{ + /* we want at least 0x18 bytes */ + if (*pDataLen < _CHM_LZXC_MIN_LEN) + return 0; + + /* unmarshal fields */ + _unmarshal_uint32 (pData, pDataLen, &dest->size); + _unmarshal_char_array(pData, pDataLen, dest->signature, 4); + _unmarshal_uint32 (pData, pDataLen, &dest->version); + _unmarshal_uint32 (pData, pDataLen, &dest->resetInterval); + _unmarshal_uint32 (pData, pDataLen, &dest->windowSize); + _unmarshal_uint32 (pData, pDataLen, &dest->windowsPerReset); + + if (*pDataLen >= _CHM_LZXC_V2_LEN) + _unmarshal_uint32 (pData, pDataLen, &dest->unknown_18); + else + dest->unknown_18 = 0; + + if (dest->version == 2) + { + dest->resetInterval *= 0x8000; + dest->windowSize *= 0x8000; + } + if (dest->windowSize == 0 || dest->resetInterval == 0) + return 0; + + /* for now, only support resetInterval a multiple of windowSize/2 */ + if (dest->windowSize == 1) + return 0; + if ((dest->resetInterval % (dest->windowSize/2)) != 0) + return 0; + + /* check structure */ + if (memcmp(dest->signature, "LZXC", 4) != 0) + return 0; + + return 1; +} + +/* the structure used for chm file handles */ +struct chmFile +{ + HANDLE fd; + + CRITICAL_SECTION mutex; + CRITICAL_SECTION lzx_mutex; + CRITICAL_SECTION cache_mutex; + + UInt64 dir_offset; + UInt64 dir_len; + UInt64 data_offset; + Int32 index_root; + Int32 index_head; + UInt32 block_len; + + UInt64 span; + struct chmUnitInfo rt_unit; + struct chmUnitInfo cn_unit; + struct chmLzxcResetTable reset_table; + + /* LZX control data */ + int compression_enabled; + UInt32 window_size; + UInt32 reset_interval; + UInt32 reset_blkcount; + + /* decompressor state */ + struct LZXstate *lzx_state; + int lzx_last_block; + + /* cache for decompressed blocks */ + UChar **cache_blocks; + Int64 *cache_block_indices; + Int32 cache_num_blocks; +}; + +/* + * utility functions local to this module + */ + +/* utility function to handle differences between {pread,read}(64)? */ +static Int64 _chm_fetch_bytes(struct chmFile *h, + UChar *buf, + UInt64 os, + Int64 len) +{ + Int64 readLen=0; + if (h->fd == CHM_NULL_FD) + return readLen; + + CHM_ACQUIRE_LOCK(h->mutex); + /* NOTE: this might be better done with CreateFileMapping, et cetera... */ + { + LARGE_INTEGER old_pos, new_pos; + DWORD actualLen=0; + + /* awkward Win32 Seek/Tell */ + new_pos.QuadPart = 0; + SetFilePointerEx( h->fd, new_pos, &old_pos, FILE_CURRENT ); + new_pos.QuadPart = os; + SetFilePointerEx( h->fd, new_pos, NULL, FILE_BEGIN ); + + /* read the data */ + if (ReadFile(h->fd, + buf, + (DWORD)len, + &actualLen, + NULL)) + readLen = actualLen; + else + readLen = 0; + + /* restore original position */ + SetFilePointerEx( h->fd, old_pos, NULL, FILE_BEGIN ); + } + CHM_RELEASE_LOCK(h->mutex); + return readLen; +} + +/* + * set a parameter on the file handle. + * valid parameter types: + * CHM_PARAM_MAX_BLOCKS_CACHED: + * how many decompressed blocks should be cached? A simple + * caching scheme is used, wherein the index of the block is + * used as a hash value, and hash collision results in the + * invalidation of the previously cached block. + */ +static void chm_set_param(struct chmFile *h, + int paramType, + int paramVal) +{ + switch (paramType) + { + case CHM_PARAM_MAX_BLOCKS_CACHED: + CHM_ACQUIRE_LOCK(h->cache_mutex); + if (paramVal != h->cache_num_blocks) + { + UChar **newBlocks; + Int64 *newIndices; + int i; + + /* allocate new cached blocks */ + newBlocks = HeapAlloc(GetProcessHeap(), 0, paramVal * sizeof (UChar *)); + newIndices = HeapAlloc(GetProcessHeap(), 0, paramVal * sizeof (UInt64)); + for (i=0; icache_blocks) + { + for (i=0; icache_num_blocks; i++) + { + int newSlot = (int)(h->cache_block_indices[i] % paramVal); + + if (h->cache_blocks[i]) + { + /* in case of collision, destroy newcomer */ + if (newBlocks[newSlot]) + { + HeapFree(GetProcessHeap(), 0, h->cache_blocks[i]); + h->cache_blocks[i] = NULL; + } + else + { + newBlocks[newSlot] = h->cache_blocks[i]; + newIndices[newSlot] = + h->cache_block_indices[i]; + } + } + } + + HeapFree(GetProcessHeap(), 0, h->cache_blocks); + HeapFree(GetProcessHeap(), 0, h->cache_block_indices); + } + + /* now, set new values */ + h->cache_blocks = newBlocks; + h->cache_block_indices = newIndices; + h->cache_num_blocks = paramVal; + } + CHM_RELEASE_LOCK(h->cache_mutex); + break; + + default: + break; + } +} + +/* open an ITS archive */ +struct chmFile *chm_openW(const WCHAR *filename) +{ + unsigned char sbuffer[256]; + unsigned int sremain; + unsigned char *sbufpos; + struct chmFile *newHandle=NULL; + struct chmItsfHeader itsfHeader; + struct chmItspHeader itspHeader; +#if 0 + struct chmUnitInfo uiSpan; +#endif + struct chmUnitInfo uiLzxc; + struct chmLzxcControlData ctlData; + + /* allocate handle */ + newHandle = HeapAlloc(GetProcessHeap(), 0, sizeof(struct chmFile)); + newHandle->fd = CHM_NULL_FD; + newHandle->lzx_state = NULL; + newHandle->cache_blocks = NULL; + newHandle->cache_block_indices = NULL; + newHandle->cache_num_blocks = 0; + + /* open file */ + if ((newHandle->fd=CreateFileW(filename, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL)) == CHM_NULL_FD) + { + HeapFree(GetProcessHeap(), 0, newHandle); + return NULL; + } + + /* initialize mutexes, if needed */ + InitializeCriticalSection(&newHandle->mutex); + newHandle->mutex.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": chmFile.mutex"); + InitializeCriticalSection(&newHandle->lzx_mutex); + newHandle->lzx_mutex.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": chmFile.lzx_mutex"); + InitializeCriticalSection(&newHandle->cache_mutex); + newHandle->cache_mutex.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": chmFile.cache_mutex"); + + /* read and verify header */ + sremain = _CHM_ITSF_V3_LEN; + sbufpos = sbuffer; + if (_chm_fetch_bytes(newHandle, sbuffer, 0, sremain) != sremain || + !_unmarshal_itsf_header(&sbufpos, &sremain, &itsfHeader)) + { + chm_close(newHandle); + return NULL; + } + + /* stash important values from header */ + newHandle->dir_offset = itsfHeader.dir_offset; + newHandle->dir_len = itsfHeader.dir_len; + newHandle->data_offset = itsfHeader.data_offset; + + /* now, read and verify the directory header chunk */ + sremain = _CHM_ITSP_V1_LEN; + sbufpos = sbuffer; + if (_chm_fetch_bytes(newHandle, sbuffer, + itsfHeader.dir_offset, sremain) != sremain || + !_unmarshal_itsp_header(&sbufpos, &sremain, &itspHeader)) + { + chm_close(newHandle); + return NULL; + } + + /* grab essential information from ITSP header */ + newHandle->dir_offset += itspHeader.header_len; + newHandle->dir_len -= itspHeader.header_len; + newHandle->index_root = itspHeader.index_root; + newHandle->index_head = itspHeader.index_head; + newHandle->block_len = itspHeader.block_len; + + /* if the index root is -1, this means we don't have any PMGI blocks. + * as a result, we must use the sole PMGL block as the index root + */ + if (newHandle->index_root == -1) + newHandle->index_root = newHandle->index_head; + + /* By default, compression is enabled. */ + newHandle->compression_enabled = 1; + + /* prefetch most commonly needed unit infos */ + if (CHM_RESOLVE_SUCCESS != chm_resolve_object(newHandle, + _CHMU_RESET_TABLE, + &newHandle->rt_unit) || + newHandle->rt_unit.space == CHM_COMPRESSED || + CHM_RESOLVE_SUCCESS != chm_resolve_object(newHandle, + _CHMU_CONTENT, + &newHandle->cn_unit) || + newHandle->cn_unit.space == CHM_COMPRESSED || + CHM_RESOLVE_SUCCESS != chm_resolve_object(newHandle, + _CHMU_LZXC_CONTROLDATA, + &uiLzxc) || + uiLzxc.space == CHM_COMPRESSED) + { + newHandle->compression_enabled = 0; + } + + /* read reset table info */ + if (newHandle->compression_enabled) + { + sremain = _CHM_LZXC_RESETTABLE_V1_LEN; + sbufpos = sbuffer; + if (chm_retrieve_object(newHandle, &newHandle->rt_unit, sbuffer, + 0, sremain) != sremain || + !_unmarshal_lzxc_reset_table(&sbufpos, &sremain, + &newHandle->reset_table)) + { + newHandle->compression_enabled = 0; + } + } + + /* read control data */ + if (newHandle->compression_enabled) + { + sremain = (unsigned long)uiLzxc.length; + sbufpos = sbuffer; + if (chm_retrieve_object(newHandle, &uiLzxc, sbuffer, + 0, sremain) != sremain || + !_unmarshal_lzxc_control_data(&sbufpos, &sremain, + &ctlData)) + { + newHandle->compression_enabled = 0; + } + + newHandle->window_size = ctlData.windowSize; + newHandle->reset_interval = ctlData.resetInterval; + +/* Jed, Mon Jun 28: Experimentally, it appears that the reset block count */ +/* must be multiplied by this formerly unknown ctrl data field in */ +/* order to decompress some files. */ +#if 0 + newHandle->reset_blkcount = newHandle->reset_interval / + (newHandle->window_size / 2); +#else + newHandle->reset_blkcount = newHandle->reset_interval / + (newHandle->window_size / 2) * + ctlData.windowsPerReset; +#endif + } + + /* initialize cache */ + chm_set_param(newHandle, CHM_PARAM_MAX_BLOCKS_CACHED, + CHM_MAX_BLOCKS_CACHED); + + return newHandle; +} + +/* close an ITS archive */ +void chm_close(struct chmFile *h) +{ + if (h != NULL) + { + if (h->fd != CHM_NULL_FD) + CHM_CLOSE_FILE(h->fd); + h->fd = CHM_NULL_FD; + + h->mutex.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&h->mutex); + h->lzx_mutex.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&h->lzx_mutex); + h->cache_mutex.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&h->cache_mutex); + + if (h->lzx_state) + LZXteardown(h->lzx_state); + h->lzx_state = NULL; + + if (h->cache_blocks) + { + int i; + for (i=0; icache_num_blocks; i++) + { + HeapFree(GetProcessHeap(), 0, h->cache_blocks[i]); + } + HeapFree(GetProcessHeap(), 0, h->cache_blocks); + h->cache_blocks = NULL; + } + + HeapFree(GetProcessHeap(), 0, h->cache_block_indices); + h->cache_block_indices = NULL; + + HeapFree(GetProcessHeap(), 0, h); + } +} + +/* + * helper methods for chm_resolve_object + */ + +/* skip a compressed dword */ +static void _chm_skip_cword(UChar **pEntry) +{ + while (*(*pEntry)++ >= 0x80) + ; +} + +/* skip the data from a PMGL entry */ +static void _chm_skip_PMGL_entry_data(UChar **pEntry) +{ + _chm_skip_cword(pEntry); + _chm_skip_cword(pEntry); + _chm_skip_cword(pEntry); +} + +/* parse a compressed dword */ +static UInt64 _chm_parse_cword(UChar **pEntry) +{ + UInt64 accum = 0; + UChar temp; + while ((temp=*(*pEntry)++) >= 0x80) + { + accum <<= 7; + accum += temp & 0x7f; + } + + return (accum << 7) + temp; +} + +/* parse a utf-8 string into an ASCII char buffer */ +static int _chm_parse_UTF8(UChar **pEntry, UInt64 count, WCHAR *path) +{ + /* MJM - Modified to return real Unicode strings */ + while (count != 0) + { + *path++ = (*(*pEntry)++); + --count; + } + + *path = '\0'; + return 1; +} + +/* parse a PMGL entry into a chmUnitInfo struct; return 1 on success. */ +static int _chm_parse_PMGL_entry(UChar **pEntry, struct chmUnitInfo *ui) +{ + UInt64 strLen; + + /* parse str len */ + strLen = _chm_parse_cword(pEntry); + if (strLen > CHM_MAX_PATHLEN) + return 0; + + /* parse path */ + if (! _chm_parse_UTF8(pEntry, strLen, ui->path)) + return 0; + + /* parse info */ + ui->space = (int)_chm_parse_cword(pEntry); + ui->start = _chm_parse_cword(pEntry); + ui->length = _chm_parse_cword(pEntry); + return 1; +} + +/* find an exact entry in PMGL; return NULL if we fail */ +static UChar *_chm_find_in_PMGL(UChar *page_buf, + UInt32 block_len, + const WCHAR *objPath) +{ + /* XXX: modify this to do a binary search using the nice index structure + * that is provided for us. + */ + struct chmPmglHeader header; + UInt32 hremain; + UChar *end; + UChar *cur; + UChar *temp; + UInt64 strLen; + WCHAR buffer[CHM_MAX_PATHLEN+1]; + + /* figure out where to start and end */ + cur = page_buf; + hremain = _CHM_PMGL_LEN; + if (! _unmarshal_pmgl_header(&cur, &hremain, &header)) + return NULL; + end = page_buf + block_len - (header.free_space); + + /* now, scan progressively */ + while (cur < end) + { + /* grab the name */ + temp = cur; + strLen = _chm_parse_cword(&cur); + if (! _chm_parse_UTF8(&cur, strLen, buffer)) + return NULL; + + /* check if it is the right name */ + if (! strcmpiW(buffer, objPath)) + return temp; + + _chm_skip_PMGL_entry_data(&cur); + } + + return NULL; +} + +/* find which block should be searched next for the entry; -1 if no block */ +static Int32 _chm_find_in_PMGI(UChar *page_buf, + UInt32 block_len, + const WCHAR *objPath) +{ + /* XXX: modify this to do a binary search using the nice index structure + * that is provided for us + */ + struct chmPmgiHeader header; + UInt32 hremain; + int page=-1; + UChar *end; + UChar *cur; + UInt64 strLen; + WCHAR buffer[CHM_MAX_PATHLEN+1]; + + /* figure out where to start and end */ + cur = page_buf; + hremain = _CHM_PMGI_LEN; + if (! _unmarshal_pmgi_header(&cur, &hremain, &header)) + return -1; + end = page_buf + block_len - (header.free_space); + + /* now, scan progressively */ + while (cur < end) + { + /* grab the name */ + strLen = _chm_parse_cword(&cur); + if (! _chm_parse_UTF8(&cur, strLen, buffer)) + return -1; + + /* check if it is the right name */ + if (strcmpiW(buffer, objPath) > 0) + return page; + + /* load next value for path */ + page = (int)_chm_parse_cword(&cur); + } + + return page; +} + +/* resolve a particular object from the archive */ +int chm_resolve_object(struct chmFile *h, + const WCHAR *objPath, + struct chmUnitInfo *ui) +{ + /* + * XXX: implement caching scheme for dir pages + */ + + Int32 curPage; + + /* buffer to hold whatever page we're looking at */ + UChar *page_buf = HeapAlloc(GetProcessHeap(), 0, h->block_len); + + /* starting page */ + curPage = h->index_root; + + /* until we have either returned or given up */ + while (curPage != -1) + { + + /* try to fetch the index page */ + if (_chm_fetch_bytes(h, page_buf, + h->dir_offset + (UInt64)curPage*h->block_len, + h->block_len) != h->block_len) + { + HeapFree(GetProcessHeap(), 0, page_buf); + return CHM_RESOLVE_FAILURE; + } + + /* now, if it is a leaf node: */ + if (memcmp(page_buf, _chm_pmgl_marker, 4) == 0) + { + /* scan block */ + UChar *pEntry = _chm_find_in_PMGL(page_buf, + h->block_len, + objPath); + if (pEntry == NULL) + { + HeapFree(GetProcessHeap(), 0, page_buf); + return CHM_RESOLVE_FAILURE; + } + + /* parse entry and return */ + _chm_parse_PMGL_entry(&pEntry, ui); + HeapFree(GetProcessHeap(), 0, page_buf); + return CHM_RESOLVE_SUCCESS; + } + + /* else, if it is a branch node: */ + else if (memcmp(page_buf, _chm_pmgi_marker, 4) == 0) + curPage = _chm_find_in_PMGI(page_buf, h->block_len, objPath); + + /* else, we are confused. give up. */ + else + { + HeapFree(GetProcessHeap(), 0, page_buf); + return CHM_RESOLVE_FAILURE; + } + } + + /* didn't find anything. fail. */ + HeapFree(GetProcessHeap(), 0, page_buf); + return CHM_RESOLVE_FAILURE; +} + +/* + * utility methods for dealing with compressed data + */ + +/* get the bounds of a compressed block. return 0 on failure */ +static int _chm_get_cmpblock_bounds(struct chmFile *h, + UInt64 block, + UInt64 *start, + Int64 *len) +{ + UChar buffer[8], *dummy; + UInt32 remain; + + /* for all but the last block, use the reset table */ + if (block < h->reset_table.block_count-1) + { + /* unpack the start address */ + dummy = buffer; + remain = 8; + if (_chm_fetch_bytes(h, buffer, + h->data_offset + + h->rt_unit.start + + h->reset_table.table_offset + + block*8, + remain) != remain || + !_unmarshal_uint64(&dummy, &remain, start)) + return 0; + + /* unpack the end address */ + dummy = buffer; + remain = 8; + if (_chm_fetch_bytes(h, buffer, + h->data_offset + + h->rt_unit.start + + h->reset_table.table_offset + + block*8 + 8, + remain) != remain || + !_unmarshal_int64(&dummy, &remain, len)) + return 0; + } + + /* for the last block, use the span in addition to the reset table */ + else + { + /* unpack the start address */ + dummy = buffer; + remain = 8; + if (_chm_fetch_bytes(h, buffer, + h->data_offset + + h->rt_unit.start + + h->reset_table.table_offset + + block*8, + remain) != remain || + !_unmarshal_uint64(&dummy, &remain, start)) + return 0; + + *len = h->reset_table.compressed_len; + } + + /* compute the length and absolute start address */ + *len -= *start; + *start += h->data_offset + h->cn_unit.start; + + return 1; +} + +/* decompress the block. must have lzx_mutex. */ +static Int64 _chm_decompress_block(struct chmFile *h, + UInt64 block, + UChar **ubuffer) +{ + UChar *cbuffer = HeapAlloc( GetProcessHeap(), 0, + ((unsigned int)h->reset_table.block_len + 6144)); + UInt64 cmpStart; /* compressed start */ + Int64 cmpLen; /* compressed len */ + int indexSlot; /* cache index slot */ + UChar *lbuffer; /* local buffer ptr */ + UInt32 blockAlign = (UInt32)(block % h->reset_blkcount); /* reset interval align */ + UInt32 i; /* local loop index */ + + /* let the caching system pull its weight! */ + if (block - blockAlign <= h->lzx_last_block && + block >= h->lzx_last_block) + blockAlign = (block - h->lzx_last_block); + + /* check if we need previous blocks */ + if (blockAlign != 0) + { + /* fetch all required previous blocks since last reset */ + for (i = blockAlign; i > 0; i--) + { + UInt32 curBlockIdx = block - i; + + /* check if we most recently decompressed the previous block */ + if (h->lzx_last_block != curBlockIdx) + { + if ((curBlockIdx % h->reset_blkcount) == 0) + { +#ifdef CHM_DEBUG + fprintf(stderr, "***RESET (1)***\n"); +#endif + LZXreset(h->lzx_state); + } + + indexSlot = (int)((curBlockIdx) % h->cache_num_blocks); + h->cache_block_indices[indexSlot] = curBlockIdx; + if (! h->cache_blocks[indexSlot]) + h->cache_blocks[indexSlot] = + HeapAlloc(GetProcessHeap(), 0, + (unsigned int)(h->reset_table.block_len)); + lbuffer = h->cache_blocks[indexSlot]; + + /* decompress the previous block */ +#ifdef CHM_DEBUG + fprintf(stderr, "Decompressing block #%4d (EXTRA)\n", curBlockIdx); +#endif + if (!_chm_get_cmpblock_bounds(h, curBlockIdx, &cmpStart, &cmpLen) || + _chm_fetch_bytes(h, cbuffer, cmpStart, cmpLen) != cmpLen || + LZXdecompress(h->lzx_state, cbuffer, lbuffer, (int)cmpLen, + (int)h->reset_table.block_len) != DECR_OK) + { +#ifdef CHM_DEBUG + fprintf(stderr, " (DECOMPRESS FAILED!)\n"); +#endif + HeapFree(GetProcessHeap(), 0, cbuffer); + return 0; + } + + h->lzx_last_block = (int)curBlockIdx; + } + } + } + else + { + if ((block % h->reset_blkcount) == 0) + { +#ifdef CHM_DEBUG + fprintf(stderr, "***RESET (2)***\n"); +#endif + LZXreset(h->lzx_state); + } + } + + /* allocate slot in cache */ + indexSlot = (int)(block % h->cache_num_blocks); + h->cache_block_indices[indexSlot] = block; + if (! h->cache_blocks[indexSlot]) + h->cache_blocks[indexSlot] = + HeapAlloc(GetProcessHeap(), 0, ((unsigned int)h->reset_table.block_len)); + lbuffer = h->cache_blocks[indexSlot]; + *ubuffer = lbuffer; + + /* decompress the block we actually want */ +#ifdef CHM_DEBUG + fprintf(stderr, "Decompressing block #%4d (REAL )\n", block); +#endif + if (! _chm_get_cmpblock_bounds(h, block, &cmpStart, &cmpLen) || + _chm_fetch_bytes(h, cbuffer, cmpStart, cmpLen) != cmpLen || + LZXdecompress(h->lzx_state, cbuffer, lbuffer, (int)cmpLen, + (int)h->reset_table.block_len) != DECR_OK) + { +#ifdef CHM_DEBUG + fprintf(stderr, " (DECOMPRESS FAILED!)\n"); +#endif + HeapFree(GetProcessHeap(), 0, cbuffer); + return 0; + } + h->lzx_last_block = (int)block; + + /* XXX: modify LZX routines to return the length of the data they + * decompressed and return that instead, for an extra sanity check. + */ + HeapFree(GetProcessHeap(), 0, cbuffer); + return h->reset_table.block_len; +} + +/* grab a region from a compressed block */ +static Int64 _chm_decompress_region(struct chmFile *h, + UChar *buf, + UInt64 start, + Int64 len) +{ + UInt64 nBlock, nOffset; + UInt64 nLen; + UInt64 gotLen; + UChar *ubuffer = NULL; + + if (len <= 0) + return 0; + + /* figure out what we need to read */ + nBlock = start / h->reset_table.block_len; + nOffset = start % h->reset_table.block_len; + nLen = len; + if (nLen > (h->reset_table.block_len - nOffset)) + nLen = h->reset_table.block_len - nOffset; + + /* if block is cached, return data from it. */ + CHM_ACQUIRE_LOCK(h->lzx_mutex); + CHM_ACQUIRE_LOCK(h->cache_mutex); + if (h->cache_block_indices[nBlock % h->cache_num_blocks] == nBlock && + h->cache_blocks[nBlock % h->cache_num_blocks] != NULL) + { + memcpy(buf, + h->cache_blocks[nBlock % h->cache_num_blocks] + nOffset, + (unsigned int)nLen); + CHM_RELEASE_LOCK(h->cache_mutex); + CHM_RELEASE_LOCK(h->lzx_mutex); + return nLen; + } + CHM_RELEASE_LOCK(h->cache_mutex); + + /* data request not satisfied, so... start up the decompressor machine */ + if (! h->lzx_state) + { + int window_size = ffs(h->window_size) - 1; + h->lzx_last_block = -1; + h->lzx_state = LZXinit(window_size); + } + + /* decompress some data */ + gotLen = _chm_decompress_block(h, nBlock, &ubuffer); + if (gotLen < nLen) + nLen = gotLen; + memcpy(buf, ubuffer+nOffset, (unsigned int)nLen); + CHM_RELEASE_LOCK(h->lzx_mutex); + return nLen; +} + +/* retrieve (part of) an object */ +LONGINT64 chm_retrieve_object(struct chmFile *h, + struct chmUnitInfo *ui, + unsigned char *buf, + LONGUINT64 addr, + LONGINT64 len) +{ + /* must be valid file handle */ + if (h == NULL) + return 0; + + /* starting address must be in correct range */ + if (addr >= ui->length) + return 0; + + /* clip length */ + if (addr + len > ui->length) + len = ui->length - addr; + + /* if the file is uncompressed, it's simple */ + if (ui->space == CHM_UNCOMPRESSED) + { + /* read data */ + return _chm_fetch_bytes(h, + buf, + h->data_offset + ui->start + addr, + len); + } + + /* else if the file is compressed, it's a little trickier */ + else /* ui->space == CHM_COMPRESSED */ + { + Int64 swath=0, total=0; + + /* if compression is not enabled for this file... */ + if (! h->compression_enabled) + return total; + + do { + + /* swill another mouthful */ + swath = _chm_decompress_region(h, buf, ui->start + addr, len); + + /* if we didn't get any... */ + if (swath == 0) + return total; + + /* update stats */ + total += swath; + len -= swath; + addr += swath; + buf += swath; + + } while (len != 0); + + return total; + } +} + +/* enumerate the objects in the .chm archive */ +int chm_enumerate(struct chmFile *h, + int what, + CHM_ENUMERATOR e, + void *context) +{ + Int32 curPage; + + /* buffer to hold whatever page we're looking at */ + UChar *page_buf = HeapAlloc(GetProcessHeap(), 0, h->block_len); + struct chmPmglHeader header; + UChar *end; + UChar *cur; + unsigned int lenRemain; + UInt64 ui_path_len; + + /* the current ui */ + struct chmUnitInfo ui; + int flag; + + /* starting page */ + curPage = h->index_head; + + /* until we have either returned or given up */ + while (curPage != -1) + { + + /* try to fetch the index page */ + if (_chm_fetch_bytes(h, + page_buf, + h->dir_offset + (UInt64)curPage*h->block_len, + h->block_len) != h->block_len) + { + HeapFree(GetProcessHeap(), 0, page_buf); + return 0; + } + + /* figure out start and end for this page */ + cur = page_buf; + lenRemain = _CHM_PMGL_LEN; + if (! _unmarshal_pmgl_header(&cur, &lenRemain, &header)) + { + HeapFree(GetProcessHeap(), 0, page_buf); + return 0; + } + end = page_buf + h->block_len - (header.free_space); + + /* loop over this page */ + while (cur < end) + { + if (! _chm_parse_PMGL_entry(&cur, &ui)) + { + HeapFree(GetProcessHeap(), 0, page_buf); + return 0; + } + + /* get the length of the path */ + ui_path_len = strlenW(ui.path)-1; + + /* check for DIRS */ + if (ui.path[ui_path_len] == '/' && !(what & CHM_ENUMERATE_DIRS)) + continue; + + /* check for FILES */ + if (ui.path[ui_path_len] != '/' && !(what & CHM_ENUMERATE_FILES)) + continue; + + /* check for NORMAL vs. META */ + if (ui.path[0] == '/') + { + + /* check for NORMAL vs. SPECIAL */ + if (ui.path[1] == '#' || ui.path[1] == '$') + flag = CHM_ENUMERATE_SPECIAL; + else + flag = CHM_ENUMERATE_NORMAL; + } + else + flag = CHM_ENUMERATE_META; + if (! (what & flag)) + continue; + + /* call the enumerator */ + { + int status = (*e)(h, &ui, context); + switch (status) + { + case CHM_ENUMERATOR_FAILURE: + HeapFree(GetProcessHeap(), 0, page_buf); + return 0; + case CHM_ENUMERATOR_CONTINUE: + break; + case CHM_ENUMERATOR_SUCCESS: + HeapFree(GetProcessHeap(), 0, page_buf); + return 1; + default: + break; + } + } + } + + /* advance to next page */ + curPage = header.block_next; + } + + HeapFree(GetProcessHeap(), 0, page_buf); + return 1; +} + +int chm_enumerate_dir(struct chmFile *h, + const WCHAR *prefix, + int what, + CHM_ENUMERATOR e, + void *context) +{ + /* + * XXX: do this efficiently (i.e. using the tree index) + */ + + Int32 curPage; + + /* buffer to hold whatever page we're looking at */ + UChar *page_buf = HeapAlloc(GetProcessHeap(), 0, h->block_len); + struct chmPmglHeader header; + UChar *end; + UChar *cur; + unsigned int lenRemain; + + /* set to 1 once we've started */ + int it_has_begun=0; + + /* the current ui */ + struct chmUnitInfo ui; + int flag; + UInt64 ui_path_len; + + /* the length of the prefix */ + WCHAR prefixRectified[CHM_MAX_PATHLEN+1]; + int prefixLen; + WCHAR lastPath[CHM_MAX_PATHLEN]; + int lastPathLen; + + /* starting page */ + curPage = h->index_head; + + /* initialize pathname state */ + lstrcpynW(prefixRectified, prefix, CHM_MAX_PATHLEN); + prefixLen = strlenW(prefixRectified); + if (prefixLen != 0) + { + if (prefixRectified[prefixLen-1] != '/') + { + prefixRectified[prefixLen] = '/'; + prefixRectified[prefixLen+1] = '\0'; + ++prefixLen; + } + } + lastPath[0] = '\0'; + lastPathLen = -1; + + /* until we have either returned or given up */ + while (curPage != -1) + { + + /* try to fetch the index page */ + if (_chm_fetch_bytes(h, + page_buf, + h->dir_offset + (UInt64)curPage*h->block_len, + h->block_len) != h->block_len) + { + HeapFree(GetProcessHeap(), 0, page_buf); + return 0; + } + + /* figure out start and end for this page */ + cur = page_buf; + lenRemain = _CHM_PMGL_LEN; + if (! _unmarshal_pmgl_header(&cur, &lenRemain, &header)) + { + HeapFree(GetProcessHeap(), 0, page_buf); + return 0; + } + end = page_buf + h->block_len - (header.free_space); + + /* loop over this page */ + while (cur < end) + { + if (! _chm_parse_PMGL_entry(&cur, &ui)) + { + HeapFree(GetProcessHeap(), 0, page_buf); + return 0; + } + + /* check if we should start */ + if (! it_has_begun) + { + if (ui.length == 0 && strncmpiW(ui.path, prefixRectified, prefixLen) == 0) + it_has_begun = 1; + else + continue; + + if (ui.path[prefixLen] == '\0') + continue; + } + + /* check if we should stop */ + else + { + if (strncmpiW(ui.path, prefixRectified, prefixLen) != 0) + { + HeapFree(GetProcessHeap(), 0, page_buf); + return 1; + } + } + + /* check if we should include this path */ + if (lastPathLen != -1) + { + if (strncmpiW(ui.path, lastPath, lastPathLen) == 0) + continue; + } + strcpyW(lastPath, ui.path); + lastPathLen = strlenW(lastPath); + + /* get the length of the path */ + ui_path_len = strlenW(ui.path)-1; + + /* check for DIRS */ + if (ui.path[ui_path_len] == '/' && !(what & CHM_ENUMERATE_DIRS)) + continue; + + /* check for FILES */ + if (ui.path[ui_path_len] != '/' && !(what & CHM_ENUMERATE_FILES)) + continue; + + /* check for NORMAL vs. META */ + if (ui.path[0] == '/') + { + + /* check for NORMAL vs. SPECIAL */ + if (ui.path[1] == '#' || ui.path[1] == '$') + flag = CHM_ENUMERATE_SPECIAL; + else + flag = CHM_ENUMERATE_NORMAL; + } + else + flag = CHM_ENUMERATE_META; + if (! (what & flag)) + continue; + + /* call the enumerator */ + { + int status = (*e)(h, &ui, context); + switch (status) + { + case CHM_ENUMERATOR_FAILURE: + HeapFree(GetProcessHeap(), 0, page_buf); + return 0; + case CHM_ENUMERATOR_CONTINUE: + break; + case CHM_ENUMERATOR_SUCCESS: + HeapFree(GetProcessHeap(), 0, page_buf); + return 1; + default: + break; + } + } + } + + /* advance to next page */ + curPage = header.block_next; + } + + HeapFree(GetProcessHeap(), 0, page_buf); + return 1; +} diff --git a/reactos/dll/win32/itss/chm_lib.h b/reactos/dll/win32/itss/chm_lib.h new file mode 100644 index 00000000000..516e57bf09d --- /dev/null +++ b/reactos/dll/win32/itss/chm_lib.h @@ -0,0 +1,136 @@ +/*************************************************************************** + * chm_lib.h - CHM archive manipulation routines * + * ------------------- * + * * + * author: Jed Wing * + * version: 0.3 * + * notes: These routines are meant for the manipulation of microsoft * + * .chm (compiled html help) files, but may likely be used * + * for the manipulation of any ITSS archive, if ever ITSS * + * archives are used for any other purpose. * + * * + * Note also that the section names are statically handled. * + * To be entirely correct, the section names should be read * + * from the section names meta-file, and then the various * + * content sections and the "transforms" to apply to the data * + * they contain should be inferred from the section name and * + * the meta-files referenced using that name; however, all of * + * the files I've been able to get my hands on appear to have * + * only two sections: Uncompressed and MSCompressed. * + * Additionally, the ITSS.DLL file included with Windows does * + * not appear to handle any different transforms than the * + * simple LZX-transform. Furthermore, the list of transforms * + * to apply is broken, in that only half the required space * + * is allocated for the list. (It appears as though the * + * space is allocated for ASCII strings, but the strings are * + * written as unicode. As a result, only the first half of * + * the string appears.) So this is probably not too big of * + * a deal, at least until CHM v4 (MS .lit files), which also * + * incorporate encryption, of some description. * + ***************************************************************************/ + +/*************************************************************************** + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + ***************************************************************************/ + +#ifndef INCLUDED_CHMLIB_H +#define INCLUDED_CHMLIB_H + +typedef ULONGLONG LONGUINT64; +typedef LONGLONG LONGINT64; + +/* the two available spaces in a CHM file */ +/* N.B.: The format supports arbitrarily many spaces, but only */ +/* two appear to be used at present. */ +#define CHM_UNCOMPRESSED (0) +#define CHM_COMPRESSED (1) + +/* structure representing an ITS (CHM) file stream */ +struct chmFile; + +/* structure representing an element from an ITS file stream */ +#define CHM_MAX_PATHLEN (256) +struct chmUnitInfo +{ + LONGUINT64 start; + LONGUINT64 length; + int space; + WCHAR path[CHM_MAX_PATHLEN+1]; +}; + +struct chmFile* chm_openW(const WCHAR *filename); + +/* close an ITS archive */ +void chm_close(struct chmFile *h); + +/* resolve a particular object from the archive */ +#define CHM_RESOLVE_SUCCESS (0) +#define CHM_RESOLVE_FAILURE (1) +int chm_resolve_object(struct chmFile *h, + const WCHAR *objPath, + struct chmUnitInfo *ui); + +/* retrieve part of an object from the archive */ +LONGINT64 chm_retrieve_object(struct chmFile *h, + struct chmUnitInfo *ui, + unsigned char *buf, + LONGUINT64 addr, + LONGINT64 len); + +/* enumerate the objects in the .chm archive */ +typedef int (*CHM_ENUMERATOR)(struct chmFile *h, + struct chmUnitInfo *ui, + void *context); +#define CHM_ENUMERATE_NORMAL (1) +#define CHM_ENUMERATE_META (2) +#define CHM_ENUMERATE_SPECIAL (4) +#define CHM_ENUMERATE_FILES (8) +#define CHM_ENUMERATE_DIRS (16) +#define CHM_ENUMERATE_ALL (31) +#define CHM_ENUMERATOR_FAILURE (0) +#define CHM_ENUMERATOR_CONTINUE (1) +#define CHM_ENUMERATOR_SUCCESS (2) +int chm_enumerate(struct chmFile *h, + int what, + CHM_ENUMERATOR e, + void *context); + +int chm_enumerate_dir(struct chmFile *h, + const WCHAR *prefix, + int what, + CHM_ENUMERATOR e, + void *context); + +/* + * This function is specific to Unix-systems. Do not remove it! + */ +static inline int +ffs(int field) +{ + static const int index[] = { 1, 2, 29, 3, 30, 15, 25, 4, 31, 23, 21, + 16, 26, 18, 5, 9, 32, 28, 14, 24, 22, 20, + 17, 8, 27, 13, 19, 7, 12, 6, 11, 10 }; + unsigned int w = field; + if (w == 0) + return (0); + w &= -w; + w *= 125613361U; + w >>= 27; + return index[w]; +} + +#endif /* INCLUDED_CHMLIB_H */ diff --git a/reactos/dll/win32/itss/itss.c b/reactos/dll/win32/itss/itss.c new file mode 100644 index 00000000000..0722efad9c2 --- /dev/null +++ b/reactos/dll/win32/itss/itss.c @@ -0,0 +1,447 @@ +/* + * ITSS Class Factory + * + * Copyright 2002 Lionel Ulmer + * Copyright 2004 Mike McCormack + * + * see http://bonedaddy.net/pabs3/hhm/#chmspec + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winreg.h" +#include "ole2.h" +#include "advpub.h" + +#include "wine/unicode.h" +#include "wine/debug.h" + +#include "itsstor.h" + +#include "initguid.h" +#include "wine/itss.h" + +WINE_DEFAULT_DEBUG_CHANNEL(itss); + +static HRESULT ITSS_create(IUnknown *pUnkOuter, LPVOID *ppObj); + +LONG dll_count = 0; +static HINSTANCE hInst; + +BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) +{ + switch(fdwReason) { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hInstDLL); + hInst = hInstDLL; + break; + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + +/****************************************************************************** + * ITSS ClassFactory + */ +typedef struct { + const IClassFactoryVtbl *lpVtbl; + HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj); +} IClassFactoryImpl; + +static HRESULT WINAPI +ITSSCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) +{ + IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + + if (IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IClassFactory)) + { + IClassFactory_AddRef(iface); + *ppobj = This; + return S_OK; + } + + WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj); + return E_NOINTERFACE; +} + +static ULONG WINAPI ITSSCF_AddRef(LPCLASSFACTORY iface) +{ + ITSS_LockModule(); + return 2; +} + +static ULONG WINAPI ITSSCF_Release(LPCLASSFACTORY iface) +{ + ITSS_UnlockModule(); + return 1; +} + + +static HRESULT WINAPI ITSSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, + REFIID riid, LPVOID *ppobj) +{ + IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + HRESULT hres; + LPUNKNOWN punk; + + TRACE("(%p)->(%p,%s,%p)\n", This, pOuter, debugstr_guid(riid), ppobj); + + *ppobj = NULL; + hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk); + if (SUCCEEDED(hres)) { + hres = IUnknown_QueryInterface(punk, riid, ppobj); + IUnknown_Release(punk); + } + return hres; +} + +static HRESULT WINAPI ITSSCF_LockServer(LPCLASSFACTORY iface, BOOL dolock) +{ + TRACE("(%p)->(%d)\n", iface, dolock); + + if (dolock) + ITSS_LockModule(); + else + ITSS_UnlockModule(); + + return S_OK; +} + +static const IClassFactoryVtbl ITSSCF_Vtbl = +{ + ITSSCF_QueryInterface, + ITSSCF_AddRef, + ITSSCF_Release, + ITSSCF_CreateInstance, + ITSSCF_LockServer +}; + +static const IClassFactoryImpl ITStorage_factory = { &ITSSCF_Vtbl, ITSS_create }; +static const IClassFactoryImpl MSITStore_factory = { &ITSSCF_Vtbl, ITS_IParseDisplayName_create }; +static const IClassFactoryImpl ITSProtocol_factory = { &ITSSCF_Vtbl, ITSProtocol_create }; + +/*********************************************************************** + * DllGetClassObject (ITSS.@) + */ +HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) +{ + const IClassFactoryImpl *factory; + + TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv); + + if (IsEqualGUID(&CLSID_ITStorage, rclsid)) + factory = &ITStorage_factory; + else if (IsEqualGUID(&CLSID_MSITStore, rclsid)) + factory = &MSITStore_factory; + else if (IsEqualGUID(&CLSID_ITSProtocol, rclsid)) + factory = &ITSProtocol_factory; + else + { + FIXME("%s: no class found.\n", debugstr_guid(rclsid)); + return CLASS_E_CLASSNOTAVAILABLE; + } + + return IUnknown_QueryInterface( (IUnknown*) factory, iid, ppv ); +} + +/*****************************************************************************/ + +typedef struct { + const IITStorageVtbl *vtbl_IITStorage; + LONG ref; +} ITStorageImpl; + + +static HRESULT WINAPI ITStorageImpl_QueryInterface( + IITStorage* iface, + REFIID riid, + void** ppvObject) +{ + ITStorageImpl *This = (ITStorageImpl *)iface; + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_IITStorage)) + { + IClassFactory_AddRef(iface); + *ppvObject = This; + return S_OK; + } + + WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject); + return E_NOINTERFACE; +} + +static ULONG WINAPI ITStorageImpl_AddRef( + IITStorage* iface) +{ + ITStorageImpl *This = (ITStorageImpl *)iface; + TRACE("%p\n", This); + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI ITStorageImpl_Release( + IITStorage* iface) +{ + ITStorageImpl *This = (ITStorageImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); + + if (ref == 0) { + HeapFree(GetProcessHeap(), 0, This); + ITSS_UnlockModule(); + } + + return ref; +} + +static HRESULT WINAPI ITStorageImpl_StgCreateDocfile( + IITStorage* iface, + const WCHAR* pwcsName, + DWORD grfMode, + DWORD reserved, + IStorage** ppstgOpen) +{ + ITStorageImpl *This = (ITStorageImpl *)iface; + + TRACE("%p %s %u %u %p\n", This, + debugstr_w(pwcsName), grfMode, reserved, ppstgOpen ); + + return ITSS_StgOpenStorage( pwcsName, NULL, grfMode, + 0, reserved, ppstgOpen); +} + +static HRESULT WINAPI ITStorageImpl_StgCreateDocfileOnILockBytes( + IITStorage* iface, + ILockBytes* plkbyt, + DWORD grfMode, + DWORD reserved, + IStorage** ppstgOpen) +{ + ITStorageImpl *This = (ITStorageImpl *)iface; + FIXME("%p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITStorageImpl_StgIsStorageFile( + IITStorage* iface, + const WCHAR* pwcsName) +{ + ITStorageImpl *This = (ITStorageImpl *)iface; + FIXME("%p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITStorageImpl_StgIsStorageILockBytes( + IITStorage* iface, + ILockBytes* plkbyt) +{ + ITStorageImpl *This = (ITStorageImpl *)iface; + FIXME("%p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITStorageImpl_StgOpenStorage( + IITStorage* iface, + const WCHAR* pwcsName, + IStorage* pstgPriority, + DWORD grfMode, + SNB snbExclude, + DWORD reserved, + IStorage** ppstgOpen) +{ + ITStorageImpl *This = (ITStorageImpl *)iface; + + TRACE("%p %s %p %d %p\n", This, debugstr_w( pwcsName ), + pstgPriority, grfMode, snbExclude ); + + return ITSS_StgOpenStorage( pwcsName, pstgPriority, grfMode, + snbExclude, reserved, ppstgOpen); +} + +static HRESULT WINAPI ITStorageImpl_StgOpenStorageOnILockBytes( + IITStorage* iface, + ILockBytes* plkbyt, + IStorage* pStgPriority, + DWORD grfMode, + SNB snbExclude, + DWORD reserved, + IStorage** ppstgOpen) +{ + ITStorageImpl *This = (ITStorageImpl *)iface; + FIXME("%p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITStorageImpl_StgSetTimes( + IITStorage* iface, + const WCHAR* lpszName, + const FILETIME* pctime, + const FILETIME* patime, + const FILETIME* pmtime) +{ + ITStorageImpl *This = (ITStorageImpl *)iface; + FIXME("%p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITStorageImpl_SetControlData( + IITStorage* iface, + PITS_Control_Data pControlData) +{ + ITStorageImpl *This = (ITStorageImpl *)iface; + FIXME("%p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITStorageImpl_DefaultControlData( + IITStorage* iface, + PITS_Control_Data* ppControlData) +{ + ITStorageImpl *This = (ITStorageImpl *)iface; + FIXME("%p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITStorageImpl_Compact( + IITStorage* iface, + const WCHAR* pwcsName, + ECompactionLev iLev) +{ + ITStorageImpl *This = (ITStorageImpl *)iface; + FIXME("%p\n", This); + return E_NOTIMPL; +} + +static const IITStorageVtbl ITStorageImpl_Vtbl = +{ + ITStorageImpl_QueryInterface, + ITStorageImpl_AddRef, + ITStorageImpl_Release, + ITStorageImpl_StgCreateDocfile, + ITStorageImpl_StgCreateDocfileOnILockBytes, + ITStorageImpl_StgIsStorageFile, + ITStorageImpl_StgIsStorageILockBytes, + ITStorageImpl_StgOpenStorage, + ITStorageImpl_StgOpenStorageOnILockBytes, + ITStorageImpl_StgSetTimes, + ITStorageImpl_SetControlData, + ITStorageImpl_DefaultControlData, + ITStorageImpl_Compact, +}; + +static HRESULT ITSS_create(IUnknown *pUnkOuter, LPVOID *ppObj) +{ + ITStorageImpl *its; + + if( pUnkOuter ) + return CLASS_E_NOAGGREGATION; + + its = HeapAlloc( GetProcessHeap(), 0, sizeof(ITStorageImpl) ); + its->vtbl_IITStorage = &ITStorageImpl_Vtbl; + its->ref = 1; + + TRACE("-> %p\n", its); + *ppObj = (LPVOID) its; + + ITSS_LockModule(); + return S_OK; +} + +/*****************************************************************************/ + +HRESULT WINAPI DllCanUnloadNow(void) +{ + TRACE("dll_count = %u\n", dll_count); + return dll_count ? S_FALSE : S_OK; +} + +#define INF_SET_ID(id) \ + do \ + { \ + static CHAR name[] = #id; \ + \ + pse[i].pszName = name; \ + clsids[i++] = &id; \ + } while (0) + +#define INF_SET_CLSID(clsid) INF_SET_ID(CLSID_ ## clsid) + +static HRESULT register_server(BOOL do_register) +{ + HRESULT hres; + HMODULE hAdvpack; + HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable); + STRTABLEA strtable; + STRENTRYA pse[4]; + static CLSID const *clsids[4]; + DWORD i = 0; + + static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0}; + + INF_SET_CLSID(ITStorage); + INF_SET_CLSID(MSFSStore); + INF_SET_CLSID(MSITStore); + INF_SET_CLSID(ITSProtocol); + + strtable.cEntries = sizeof(pse)/sizeof(pse[0]); + strtable.pse = pse; + + for(i=0; i < strtable.cEntries; i++) { + pse[i].pszValue = HeapAlloc(GetProcessHeap(), 0, 39); + sprintf(pse[i].pszValue, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + clsids[i]->Data1, clsids[i]->Data2, clsids[i]->Data3, clsids[i]->Data4[0], + clsids[i]->Data4[1], clsids[i]->Data4[2], clsids[i]->Data4[3], clsids[i]->Data4[4], + clsids[i]->Data4[5], clsids[i]->Data4[6], clsids[i]->Data4[7]); + } + + hAdvpack = LoadLibraryW(wszAdvpack); + pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall"); + + hres = pRegInstall(hInst, do_register ? "RegisterDll" : "UnregisterDll", &strtable); + + for(i=0; i < sizeof(pse)/sizeof(pse[0]); i++) + HeapFree(GetProcessHeap(), 0, pse[i].pszValue); + + return hres; +} + +#undef INF_SET_CLSID +#undef INF_SET_ID + +/*********************************************************************** + * DllRegisterServer (ITSS.@) + */ +HRESULT WINAPI DllRegisterServer(void) +{ + return register_server(TRUE); +} + +/*********************************************************************** + * DllUnregisterServer (ITSS.@) + */ +HRESULT WINAPI DllUnregisterServer(void) +{ + return register_server(FALSE); +} diff --git a/reactos/dll/win32/itss/itss.inf b/reactos/dll/win32/itss/itss.inf new file mode 100644 index 00000000000..eeefbbb93bc --- /dev/null +++ b/reactos/dll/win32/itss/itss.inf @@ -0,0 +1,79 @@ +[version] +Signature="$CHICAGO$" + + +[RegisterDll] +AddReg=Classes.Reg, Misc.Reg + + +[UnregisterDll] +DelReg=Classes.Reg, Misc.Reg + + +[Classes.Reg] + +;; ITStorage +HKCR,"CLSID\%CLSID_ITStorage%",,,"Microsoft InfoTech IStorage System" +HKCR,"CLSID\%CLSID_ITStorage%\InProcServer32",,,"itss.dll" +HKCR,"CLSID\%CLSID_ITStorage%\InProcServer32","ThreadingModel",,"Both" +HKCR,"CLSID\%CLSID_ITStorage%\NotInsertable",,,"" +HKCR,"CLSID\%CLSID_ITStorage%\ProgID",,,"MSITFS1.0" +HKCR,"CLSID\%CLSID_ITStorage%\VersionIndependentProgID",,,"MSITFS" + +HKCR,"MSITFS",,,"Microsoft InfoTech IStorage System" +HKCR,"MSITFS\CLSID",,,"%CLSID_ITStorage%" +HKCR,"MSITFS\CurVer",,,"MSITFS1.0" + +;; ITSProtocol for IE 3.0 +HKCR,"CLSID\%CLSID_MSITStore%",,,"Microsoft InfoTech Protocol for IE 3.0" +HKCR,"CLSID\%CLSID_MSITStore%\InProcServer32",,,"itss.dll" +HKCR,"CLSID\%CLSID_MSITStore%\InProcServer32","ThreadingModel",,"Both" +HKCR,"CLSID\%CLSID_MSITStore%\NotInsertable",,,"" +HKCR,"CLSID\%CLSID_MSITStore%\ProgID",,,"MSITFS1.0" +HKCR,"CLSID\%CLSID_MSITStore%\VersionIndependentProgID",,,"MSITFS" + +HKCR,"MSITStore",,,"Microsoft InfoTech Protocol for IE 3.0" +HKCR,"MSITStore\CLSID",,,"%CLSID_MSITStore%" +HKCR,"MSITStore\CurVer",,,"MSITStore1.0" + + +;; ITSProtocol for IE 4.0 +HKCR,"CLSID\%CLSID_ITSProtocol%",,,"Microsoft InfoTech Protocol for IE 4.0" +HKCR,"CLSID\%CLSID_ITSProtocol%\InProcServer32",,,"itss.dll" +HKCR,"CLSID\%CLSID_ITSProtocol%\InProcServer32","ThreadingModel",,"Both" +HKCR,"CLSID\%CLSID_ITSProtocol%\NotInsertable",,,"" +HKCR,"CLSID\%CLSID_ITSProtocol%\ProgID",,,"MSITFS1.0" +HKCR,"CLSID\%CLSID_ITSProtocol%%\VersionIndependentProgID",,,"MSITFS" + +HKCR,"ITSProtocol","Microsoft InfoTech Protocols for IE 4.0" +HKCR,"ITSProtocol\CLSID",,,"%CLSID_ITSProtocol%" +HKCR,"ITSProtocol\CurVer",,,"ITSProtocol1.0" + + +;; MSFSStore +HKCR,"CLSID\%CLSID_MSFSStore%",,,"Microsoft InfoTech IStorage for Win32 Files" +HKCR,"CLSID\%CLSID_MSFSStore%\InProcServer32",,,"itss.dll" +HKCR,"CLSID\%CLSID_MSFSStore%\InProcServer32","ThreadingModel",,"Both" +HKCR,"CLSID\%CLSID_MSFSStore%\NotInsertable",,,"" +HKCR,"CLSID\%CLSID_MSFSStore%\ProgID",,,"MSITFS1.0" +HKCR,"CLSID\%CLSID_MSFSStore%\VersionIndependentProgID",,,"MSITFS" + +HKCR,"MSFSStore",,,"Microsoft InfoTech IStorage for Win32 Files" +HKCR,"MSFSStore\CLSID",,,"%CLSID_MSFSStore%" +HKCR,"MSFSStore\CurVer",,,"MSFSStore1.0" + + +[Misc.Reg] + +HKCR,".its",,,"ITS File" +HKCR,"ITS FILE",,,"Internet Document Set" +HKCR,"ITS FILE\DefaultIcon",,,"itss.dll,0" +;; HKCR "ITS FILE\shell\open\command",,,"FIXME" + +HKCR,"PROTOCOLS\Handler\its",,,"its: Asychronous Pluggable Protocol Handler" +HKCR,"PROTOCOLS\Handler\its","CLSID",,"%CLSID_ITSProtocol%" +HKCR,"PROTOCOLS\Handler\ms-its",,,"ms-its: Asychronous Pluggable Protocol Handler" +HKCR,"PROTOCOLS\Handler\ms-its","CLSID",,"%CLSID_ITSProtocol%" + +HKCR,"PROTOCOLS\Name-Space Handler\mk",,,"NameSpace Filter for MK:@MSITStore:..." +HKCR,"PROTOCOLS\Name-Space Handler\mk\*","CLSID",,"%CLSID_ITSProtocol%" diff --git a/reactos/dll/win32/itss/itss.rbuild b/reactos/dll/win32/itss/itss.rbuild new file mode 100644 index 00000000000..edb61ad9ef5 --- /dev/null +++ b/reactos/dll/win32/itss/itss.rbuild @@ -0,0 +1,23 @@ + + + + + . + include/reactos/wine + + chm_lib.c + lzx.c + itss.c + moniker.c + protocol.c + storage.c + rsrc.rc + wine + uuid + urlmon + shlwapi + ole32 + kernel32 + ntdll + + diff --git a/reactos/dll/win32/itss/itss.spec b/reactos/dll/win32/itss/itss.spec new file mode 100644 index 00000000000..7437ca82333 --- /dev/null +++ b/reactos/dll/win32/itss/itss.spec @@ -0,0 +1,6 @@ +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetClassObject(ptr ptr ptr) +@ stub DllInstall +@ stdcall -private DllMain(long long ptr) +@ stdcall -private DllRegisterServer() +@ stdcall -private DllUnregisterServer() diff --git a/reactos/dll/win32/itss/itsstor.h b/reactos/dll/win32/itss/itsstor.h new file mode 100644 index 00000000000..d134725406b --- /dev/null +++ b/reactos/dll/win32/itss/itsstor.h @@ -0,0 +1,46 @@ +/* + * ITSS Storage implementation + * + * Copyright 2004 Mike McCormack + * + * see http://bonedaddy.net/pabs3/hhm/#chmspec + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_ITS_STORAGE_PRIVATE__ +#define __WINE_ITS_STORAGE_PRIVATE__ + +extern HRESULT ITSS_StgOpenStorage( + const WCHAR* pwcsName, + IStorage* pstgPriority, + DWORD grfMode, + SNB snbExclude, + DWORD reserved, + IStorage** ppstgOpen); + +extern HRESULT ITS_IParseDisplayName_create( + IUnknown *pUnkOuter, + LPVOID *ppObj); + +extern HRESULT ITSProtocol_create(IUnknown *pUnkOuter, LPVOID *ppobj); + +extern LONG dll_count; +static inline void ITSS_LockModule(void) { InterlockedIncrement(&dll_count); } +static inline void ITSS_UnlockModule(void) { InterlockedDecrement(&dll_count); } + +#define DEFINE_THIS(cls,ifc,iface) ((cls*)((BYTE*)(iface)-offsetof(cls,lp ## ifc ## Vtbl))) + +#endif /* __WINE_ITS_STORAGE_PRIVATE__ */ diff --git a/reactos/dll/win32/itss/lzx.c b/reactos/dll/win32/itss/lzx.c new file mode 100644 index 00000000000..b5fdfc7e275 --- /dev/null +++ b/reactos/dll/win32/itss/lzx.c @@ -0,0 +1,832 @@ +/*************************************************************************** + * lzx.c - LZX decompression routines * + * ------------------- * + * * + * maintainer: Jed Wing * + * source: modified lzx.c from cabextract v0.5 * + * notes: This file was taken from cabextract v0.5, which was, * + * itself, a modified version of the lzx decompression code * + * from unlzx. * + * * + * platforms: In its current incarnation, this file has been tested on * + * two different Linux platforms (one, redhat-based, with a * + * 2.1.2 glibc and gcc 2.95.x, and the other, Debian, with * + * 2.2.4 glibc and both gcc 2.95.4 and gcc 3.0.2). Both were * + * Intel x86 compatible machines. * + ***************************************************************************/ + +/*************************************************************************** + * + * Copyright(C) Stuart Caie + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + ***************************************************************************/ + +#include "lzx.h" +#include +#include +#include + +/* sized types */ +typedef unsigned char UBYTE; /* 8 bits exactly */ +typedef unsigned short UWORD; /* 16 bits (or more) */ +typedef unsigned int ULONG; /* 32 bits (or more) */ +typedef signed int LONG; /* 32 bits (or more) */ + +/* some constants defined by the LZX specification */ +#define LZX_MIN_MATCH (2) +#define LZX_MAX_MATCH (257) +#define LZX_NUM_CHARS (256) +#define LZX_BLOCKTYPE_INVALID (0) /* also blocktypes 4-7 invalid */ +#define LZX_BLOCKTYPE_VERBATIM (1) +#define LZX_BLOCKTYPE_ALIGNED (2) +#define LZX_BLOCKTYPE_UNCOMPRESSED (3) +#define LZX_PRETREE_NUM_ELEMENTS (20) +#define LZX_ALIGNED_NUM_ELEMENTS (8) /* aligned offset tree #elements */ +#define LZX_NUM_PRIMARY_LENGTHS (7) /* this one missing from spec! */ +#define LZX_NUM_SECONDARY_LENGTHS (249) /* length tree #elements */ + +/* LZX huffman defines: tweak tablebits as desired */ +#define LZX_PRETREE_MAXSYMBOLS (LZX_PRETREE_NUM_ELEMENTS) +#define LZX_PRETREE_TABLEBITS (6) +#define LZX_MAINTREE_MAXSYMBOLS (LZX_NUM_CHARS + 50*8) +#define LZX_MAINTREE_TABLEBITS (12) +#define LZX_LENGTH_MAXSYMBOLS (LZX_NUM_SECONDARY_LENGTHS+1) +#define LZX_LENGTH_TABLEBITS (12) +#define LZX_ALIGNED_MAXSYMBOLS (LZX_ALIGNED_NUM_ELEMENTS) +#define LZX_ALIGNED_TABLEBITS (7) + +#define LZX_LENTABLE_SAFETY (64) /* we allow length table decoding overruns */ + +#define LZX_DECLARE_TABLE(tbl) \ + UWORD tbl##_table[(1< 21) return NULL; + + /* allocate state and associated window */ + pState = malloc(sizeof(struct LZXstate)); + if (!(pState->window = malloc(wndsize))) + { + free(pState); + return NULL; + } + pState->actual_size = wndsize; + pState->window_size = wndsize; + + /* calculate required position slots */ + if (window == 20) posn_slots = 42; + else if (window == 21) posn_slots = 50; + else posn_slots = window << 1; + + /** alternatively **/ + /* posn_slots=i=0; while (i < wndsize) i += 1 << extra_bits[posn_slots++]; */ + + /* initialize other state */ + pState->R0 = pState->R1 = pState->R2 = 1; + pState->main_elements = LZX_NUM_CHARS + (posn_slots << 3); + pState->header_read = 0; + pState->frames_read = 0; + pState->block_remaining = 0; + pState->block_type = LZX_BLOCKTYPE_INVALID; + pState->intel_curpos = 0; + pState->intel_started = 0; + pState->window_posn = 0; + + /* initialise tables to 0 (because deltas will be applied to them) */ + for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++) pState->MAINTREE_len[i] = 0; + for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++) pState->LENGTH_len[i] = 0; + + return pState; +} + +void LZXteardown(struct LZXstate *pState) +{ + if (pState) + { + free(pState->window); + free(pState); + } +} + +int LZXreset(struct LZXstate *pState) +{ + int i; + + pState->R0 = pState->R1 = pState->R2 = 1; + pState->header_read = 0; + pState->frames_read = 0; + pState->block_remaining = 0; + pState->block_type = LZX_BLOCKTYPE_INVALID; + pState->intel_curpos = 0; + pState->intel_started = 0; + pState->window_posn = 0; + + for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS + LZX_LENTABLE_SAFETY; i++) pState->MAINTREE_len[i] = 0; + for (i = 0; i < LZX_LENGTH_MAXSYMBOLS + LZX_LENTABLE_SAFETY; i++) pState->LENGTH_len[i] = 0; + + return DECR_OK; +} + + +/* Bitstream reading macros: + * + * INIT_BITSTREAM should be used first to set up the system + * READ_BITS(var,n) takes N bits from the buffer and puts them in var + * + * ENSURE_BITS(n) ensures there are at least N bits in the bit buffer + * PEEK_BITS(n) extracts (without removing) N bits from the bit buffer + * REMOVE_BITS(n) removes N bits from the bit buffer + * + * These bit access routines work by using the area beyond the MSB and the + * LSB as a free source of zeroes. This avoids having to mask any bits. + * So we have to know the bit width of the bitbuffer variable. This is + * sizeof(ULONG) * 8, also defined as ULONG_BITS + */ + +/* number of bits in ULONG. Note: This must be at multiple of 16, and at + * least 32 for the bitbuffer code to work (ie, it must be able to ensure + * up to 17 bits - that's adding 16 bits when there's one bit left, or + * adding 32 bits when there are no bits left. The code should work fine + * for machines where ULONG >= 32 bits. + */ +#define ULONG_BITS (sizeof(ULONG)<<3) + +#define INIT_BITSTREAM do { bitsleft = 0; bitbuf = 0; } while (0) + +#define ENSURE_BITS(n) \ + while (bitsleft < (n)) { \ + bitbuf |= ((inpos[1]<<8)|inpos[0]) << (ULONG_BITS-16 - bitsleft); \ + bitsleft += 16; inpos+=2; \ + } + +#define PEEK_BITS(n) (bitbuf >> (ULONG_BITS - (n))) +#define REMOVE_BITS(n) ((bitbuf <<= (n)), (bitsleft -= (n))) + +#define READ_BITS(v,n) do { \ + ENSURE_BITS(n); \ + (v) = PEEK_BITS(n); \ + REMOVE_BITS(n); \ +} while (0) + + +/* Huffman macros */ + +#define TABLEBITS(tbl) (LZX_##tbl##_TABLEBITS) +#define MAXSYMBOLS(tbl) (LZX_##tbl##_MAXSYMBOLS) +#define SYMTABLE(tbl) (pState->tbl##_table) +#define LENTABLE(tbl) (pState->tbl##_len) + +/* BUILD_TABLE(tablename) builds a huffman lookup table from code lengths. + * In reality, it just calls make_decode_table() with the appropriate + * values - they're all fixed by some #defines anyway, so there's no point + * writing each call out in full by hand. + */ +#define BUILD_TABLE(tbl) \ + if (make_decode_table( \ + MAXSYMBOLS(tbl), TABLEBITS(tbl), LENTABLE(tbl), SYMTABLE(tbl) \ + )) { return DECR_ILLEGALDATA; } + + +/* READ_HUFFSYM(tablename, var) decodes one huffman symbol from the + * bitstream using the stated table and puts it in var. + */ +#define READ_HUFFSYM(tbl,var) do { \ + ENSURE_BITS(16); \ + hufftbl = SYMTABLE(tbl); \ + if ((i = hufftbl[PEEK_BITS(TABLEBITS(tbl))]) >= MAXSYMBOLS(tbl)) { \ + j = 1 << (ULONG_BITS - TABLEBITS(tbl)); \ + do { \ + j >>= 1; i <<= 1; i |= (bitbuf & j) ? 1 : 0; \ + if (!j) { return DECR_ILLEGALDATA; } \ + } while ((i = hufftbl[i]) >= MAXSYMBOLS(tbl)); \ + } \ + j = LENTABLE(tbl)[(var) = i]; \ + REMOVE_BITS(j); \ +} while (0) + + +/* READ_LENGTHS(tablename, first, last) reads in code lengths for symbols + * first to last in the given table. The code lengths are stored in their + * own special LZX way. + */ +#define READ_LENGTHS(tbl,first,last) do { \ + lb.bb = bitbuf; lb.bl = bitsleft; lb.ip = inpos; \ + if (lzx_read_lens(pState, LENTABLE(tbl),(first),(last),&lb)) { \ + return DECR_ILLEGALDATA; \ + } \ + bitbuf = lb.bb; bitsleft = lb.bl; inpos = lb.ip; \ +} while (0) + + +/* make_decode_table(nsyms, nbits, length[], table[]) + * + * This function was coded by David Tritscher. It builds a fast huffman + * decoding table out of just a canonical huffman code lengths table. + * + * nsyms = total number of symbols in this huffman tree. + * nbits = any symbols with a code length of nbits or less can be decoded + * in one lookup of the table. + * length = A table to get code lengths from [0 to syms-1] + * table = The table to fill up with decoded symbols and pointers. + * + * Returns 0 for OK or 1 for error + */ + +static int make_decode_table(ULONG nsyms, ULONG nbits, UBYTE *length, UWORD *table) { + register UWORD sym; + register ULONG leaf; + register UBYTE bit_num = 1; + ULONG fill; + ULONG pos = 0; /* the current position in the decode table */ + ULONG table_mask = 1 << nbits; + ULONG bit_mask = table_mask >> 1; /* don't do 0 length codes */ + ULONG next_symbol = bit_mask; /* base of allocation for long codes */ + + /* fill entries for codes short enough for a direct mapping */ + while (bit_num <= nbits) { + for (sym = 0; sym < nsyms; sym++) { + if (length[sym] == bit_num) { + leaf = pos; + + if((pos += bit_mask) > table_mask) return 1; /* table overrun */ + + /* fill all possible lookups of this symbol with the symbol itself */ + fill = bit_mask; + while (fill-- > 0) table[leaf++] = sym; + } + } + bit_mask >>= 1; + bit_num++; + } + + /* if there are any codes longer than nbits */ + if (pos != table_mask) { + /* clear the remainder of the table */ + for (sym = pos; sym < table_mask; sym++) table[sym] = 0; + + /* give ourselves room for codes to grow by up to 16 more bits */ + pos <<= 16; + table_mask <<= 16; + bit_mask = 1 << 15; + + while (bit_num <= 16) { + for (sym = 0; sym < nsyms; sym++) { + if (length[sym] == bit_num) { + leaf = pos >> 16; + for (fill = 0; fill < bit_num - nbits; fill++) { + /* if this path hasn't been taken yet, 'allocate' two entries */ + if (table[leaf] == 0) { + table[(next_symbol << 1)] = 0; + table[(next_symbol << 1) + 1] = 0; + table[leaf] = next_symbol++; + } + /* follow the path and select either left or right for next bit */ + leaf = table[leaf] << 1; + if ((pos >> (15-fill)) & 1) leaf++; + } + table[leaf] = sym; + + if ((pos += bit_mask) > table_mask) return 1; /* table overflow */ + } + } + bit_mask >>= 1; + bit_num++; + } + } + + /* full table? */ + if (pos == table_mask) return 0; + + /* either erroneous table, or all elements are 0 - let's find out. */ + for (sym = 0; sym < nsyms; sym++) if (length[sym]) return 1; + return 0; +} + +struct lzx_bits { + ULONG bb; + int bl; + UBYTE *ip; +}; + +static int lzx_read_lens(struct LZXstate *pState, UBYTE *lens, ULONG first, ULONG last, struct lzx_bits *lb) { + ULONG i,j, x,y; + int z; + + register ULONG bitbuf = lb->bb; + register int bitsleft = lb->bl; + UBYTE *inpos = lb->ip; + UWORD *hufftbl; + + for (x = 0; x < 20; x++) { + READ_BITS(y, 4); + LENTABLE(PRETREE)[x] = y; + } + BUILD_TABLE(PRETREE); + + for (x = first; x < last; ) { + READ_HUFFSYM(PRETREE, z); + if (z == 17) { + READ_BITS(y, 4); y += 4; + while (y--) lens[x++] = 0; + } + else if (z == 18) { + READ_BITS(y, 5); y += 20; + while (y--) lens[x++] = 0; + } + else if (z == 19) { + READ_BITS(y, 1); y += 4; + READ_HUFFSYM(PRETREE, z); + z = lens[x] - z; if (z < 0) z += 17; + while (y--) lens[x++] = z; + } + else { + z = lens[x] - z; if (z < 0) z += 17; + lens[x++] = z; + } + } + + lb->bb = bitbuf; + lb->bl = bitsleft; + lb->ip = inpos; + return 0; +} + +int LZXdecompress(struct LZXstate *pState, unsigned char *inpos, unsigned char *outpos, int inlen, int outlen) { + UBYTE *endinp = inpos + inlen; + UBYTE *window = pState->window; + UBYTE *runsrc, *rundest; + UWORD *hufftbl; /* used in READ_HUFFSYM macro as chosen decoding table */ + + ULONG window_posn = pState->window_posn; + ULONG window_size = pState->window_size; + ULONG R0 = pState->R0; + ULONG R1 = pState->R1; + ULONG R2 = pState->R2; + + register ULONG bitbuf; + register int bitsleft; + ULONG match_offset, i,j,k; /* ijk used in READ_HUFFSYM macro */ + struct lzx_bits lb; /* used in READ_LENGTHS macro */ + + int togo = outlen, this_run, main_element, aligned_bits; + int match_length, length_footer, extra, verbatim_bits; + int copy_length; + + INIT_BITSTREAM; + + /* read header if necessary */ + if (!pState->header_read) { + i = j = 0; + READ_BITS(k, 1); if (k) { READ_BITS(i,16); READ_BITS(j,16); } + pState->intel_filesize = (i << 16) | j; /* or 0 if not encoded */ + pState->header_read = 1; + } + + /* main decoding loop */ + while (togo > 0) { + /* last block finished, new block expected */ + if (pState->block_remaining == 0) { + if (pState->block_type == LZX_BLOCKTYPE_UNCOMPRESSED) { + if (pState->block_length & 1) inpos++; /* realign bitstream to word */ + INIT_BITSTREAM; + } + + READ_BITS(pState->block_type, 3); + READ_BITS(i, 16); + READ_BITS(j, 8); + pState->block_remaining = pState->block_length = (i << 8) | j; + + switch (pState->block_type) { + case LZX_BLOCKTYPE_ALIGNED: + for (i = 0; i < 8; i++) { READ_BITS(j, 3); LENTABLE(ALIGNED)[i] = j; } + BUILD_TABLE(ALIGNED); + /* rest of aligned header is same as verbatim */ + + case LZX_BLOCKTYPE_VERBATIM: + READ_LENGTHS(MAINTREE, 0, 256); + READ_LENGTHS(MAINTREE, 256, pState->main_elements); + BUILD_TABLE(MAINTREE); + if (LENTABLE(MAINTREE)[0xE8] != 0) pState->intel_started = 1; + + READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS); + BUILD_TABLE(LENGTH); + break; + + case LZX_BLOCKTYPE_UNCOMPRESSED: + pState->intel_started = 1; /* because we can't assume otherwise */ + ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */ + if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */ + R0 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4; + R1 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4; + R2 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4; + break; + + default: + return DECR_ILLEGALDATA; + } + } + + /* buffer exhaustion check */ + if (inpos > endinp) { + /* it's possible to have a file where the next run is less than + * 16 bits in size. In this case, the READ_HUFFSYM() macro used + * in building the tables will exhaust the buffer, so we should + * allow for this, but not allow those accidentally read bits to + * be used (so we check that there are at least 16 bits + * remaining - in this boundary case they aren't really part of + * the compressed data) + */ + if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA; + } + + while ((this_run = pState->block_remaining) > 0 && togo > 0) { + if (this_run > togo) this_run = togo; + togo -= this_run; + pState->block_remaining -= this_run; + + /* apply 2^x-1 mask */ + window_posn &= window_size - 1; + /* runs can't straddle the window wraparound */ + if ((window_posn + this_run) > window_size) + return DECR_DATAFORMAT; + + switch (pState->block_type) { + + case LZX_BLOCKTYPE_VERBATIM: + while (this_run > 0) { + READ_HUFFSYM(MAINTREE, main_element); + + if (main_element < LZX_NUM_CHARS) { + /* literal: 0 to LZX_NUM_CHARS-1 */ + window[window_posn++] = main_element; + this_run--; + } + else { + /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */ + main_element -= LZX_NUM_CHARS; + + match_length = main_element & LZX_NUM_PRIMARY_LENGTHS; + if (match_length == LZX_NUM_PRIMARY_LENGTHS) { + READ_HUFFSYM(LENGTH, length_footer); + match_length += length_footer; + } + match_length += LZX_MIN_MATCH; + + match_offset = main_element >> 3; + + if (match_offset > 2) { + /* not repeated offset */ + if (match_offset != 3) { + extra = extra_bits[match_offset]; + READ_BITS(verbatim_bits, extra); + match_offset = position_base[match_offset] - 2 + verbatim_bits; + } + else { + match_offset = 1; + } + + /* update repeated offset LRU queue */ + R2 = R1; R1 = R0; R0 = match_offset; + } + else if (match_offset == 0) { + match_offset = R0; + } + else if (match_offset == 1) { + match_offset = R1; + R1 = R0; R0 = match_offset; + } + else /* match_offset == 2 */ { + match_offset = R2; + R2 = R0; R0 = match_offset; + } + + rundest = window + window_posn; + this_run -= match_length; + + /* copy any wrapped around source data */ + if (window_posn >= match_offset) { + /* no wrap */ + runsrc = rundest - match_offset; + } else { + runsrc = rundest + (window_size - match_offset); + copy_length = match_offset - window_posn; + if (copy_length < match_length) { + match_length -= copy_length; + window_posn += copy_length; + while (copy_length-- > 0) *rundest++ = *runsrc++; + runsrc = window; + } + } + window_posn += match_length; + + /* copy match data - no worries about destination wraps */ + while (match_length-- > 0) *rundest++ = *runsrc++; + + } + } + break; + + case LZX_BLOCKTYPE_ALIGNED: + while (this_run > 0) { + READ_HUFFSYM(MAINTREE, main_element); + + if (main_element < LZX_NUM_CHARS) { + /* literal: 0 to LZX_NUM_CHARS-1 */ + window[window_posn++] = main_element; + this_run--; + } + else { + /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */ + main_element -= LZX_NUM_CHARS; + + match_length = main_element & LZX_NUM_PRIMARY_LENGTHS; + if (match_length == LZX_NUM_PRIMARY_LENGTHS) { + READ_HUFFSYM(LENGTH, length_footer); + match_length += length_footer; + } + match_length += LZX_MIN_MATCH; + + match_offset = main_element >> 3; + + if (match_offset > 2) { + /* not repeated offset */ + extra = extra_bits[match_offset]; + match_offset = position_base[match_offset] - 2; + if (extra > 3) { + /* verbatim and aligned bits */ + extra -= 3; + READ_BITS(verbatim_bits, extra); + match_offset += (verbatim_bits << 3); + READ_HUFFSYM(ALIGNED, aligned_bits); + match_offset += aligned_bits; + } + else if (extra == 3) { + /* aligned bits only */ + READ_HUFFSYM(ALIGNED, aligned_bits); + match_offset += aligned_bits; + } + else if (extra > 0) { /* extra==1, extra==2 */ + /* verbatim bits only */ + READ_BITS(verbatim_bits, extra); + match_offset += verbatim_bits; + } + else /* extra == 0 */ { + /* ??? */ + match_offset = 1; + } + + /* update repeated offset LRU queue */ + R2 = R1; R1 = R0; R0 = match_offset; + } + else if (match_offset == 0) { + match_offset = R0; + } + else if (match_offset == 1) { + match_offset = R1; + R1 = R0; R0 = match_offset; + } + else /* match_offset == 2 */ { + match_offset = R2; + R2 = R0; R0 = match_offset; + } + + rundest = window + window_posn; + this_run -= match_length; + + /* copy any wrapped around source data */ + if (window_posn >= match_offset) { + /* no wrap */ + runsrc = rundest - match_offset; + } else { + runsrc = rundest + (window_size - match_offset); + copy_length = match_offset - window_posn; + if (copy_length < match_length) { + match_length -= copy_length; + window_posn += copy_length; + while (copy_length-- > 0) *rundest++ = *runsrc++; + runsrc = window; + } + } + window_posn += match_length; + + /* copy match data - no worries about destination wraps */ + while (match_length-- > 0) *rundest++ = *runsrc++; + + } + } + break; + + case LZX_BLOCKTYPE_UNCOMPRESSED: + if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA; + memcpy(window + window_posn, inpos, (size_t) this_run); + inpos += this_run; window_posn += this_run; + break; + + default: + return DECR_ILLEGALDATA; /* might as well */ + } + + } + } + + if (togo != 0) return DECR_ILLEGALDATA; + memcpy(outpos, window + ((!window_posn) ? window_size : window_posn) - outlen, (size_t) outlen); + + pState->window_posn = window_posn; + pState->R0 = R0; + pState->R1 = R1; + pState->R2 = R2; + + /* intel E8 decoding */ + if ((pState->frames_read++ < 32768) && pState->intel_filesize != 0) { + if (outlen <= 6 || !pState->intel_started) { + pState->intel_curpos += outlen; + } + else { + UBYTE *data = outpos; + UBYTE *dataend = data + outlen - 10; + LONG curpos = pState->intel_curpos; + LONG filesize = pState->intel_filesize; + LONG abs_off, rel_off; + + pState->intel_curpos = curpos + outlen; + + while (data < dataend) { + if (*data++ != 0xE8) { curpos++; continue; } + abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24); + if ((abs_off >= -curpos) && (abs_off < filesize)) { + rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize; + data[0] = (UBYTE) rel_off; + data[1] = (UBYTE) (rel_off >> 8); + data[2] = (UBYTE) (rel_off >> 16); + data[3] = (UBYTE) (rel_off >> 24); + } + data += 4; + curpos += 5; + } + } + } + return DECR_OK; +} + +#ifdef LZX_CHM_TESTDRIVER +int main(int c, char **v) +{ + FILE *fin, *fout; + struct LZXstate state; + UBYTE ibuf[16384]; + UBYTE obuf[32768]; + int ilen, olen; + int status; + int i; + int count=0; + int w = atoi(v[1]); + LZXinit(&state, w); + fout = fopen(v[2], "wb"); + for (i=3; i * + * source: modified lzx.c from cabextract v0.5 * + * notes: This file was taken from cabextract v0.5, which was, * + * itself, a modified version of the lzx decompression code * + * from unlzx. * + ***************************************************************************/ + +/*************************************************************************** + * + * Copyright(C) Stuart Caie + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + ***************************************************************************/ + +#ifndef INCLUDED_LZX_H +#define INCLUDED_LZX_H + +/* return codes */ +#define DECR_OK (0) +#define DECR_DATAFORMAT (1) +#define DECR_ILLEGALDATA (2) +#define DECR_NOMEMORY (3) + +/* opaque state structure */ +struct LZXstate; + +/* create an lzx state object */ +struct LZXstate *LZXinit(int window); + +/* destroy an lzx state object */ +void LZXteardown(struct LZXstate *pState); + +/* reset an lzx stream */ +int LZXreset(struct LZXstate *pState); + +/* decompress an LZX compressed block */ +int LZXdecompress(struct LZXstate *pState, + unsigned char *inpos, + unsigned char *outpos, + int inlen, + int outlen); + +#endif /* INCLUDED_LZX_H */ diff --git a/reactos/dll/win32/itss/moniker.c b/reactos/dll/win32/itss/moniker.c new file mode 100644 index 00000000000..41e2bdaad86 --- /dev/null +++ b/reactos/dll/win32/itss/moniker.c @@ -0,0 +1,480 @@ +/* + * ITSS Moniker implementation + * + * Copyright 2004 Mike McCormack + * + * Implementation of the infamous mk:@MSITStore moniker + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "ole2.h" + +#include "wine/itss.h" +#include "wine/unicode.h" +#include "wine/debug.h" + +#include "itsstor.h" + +WINE_DEFAULT_DEBUG_CHANNEL(itss); + +/*****************************************************************************/ + +typedef struct { + const IMonikerVtbl *vtbl_ITS_IMoniker; + LONG ref; + LPWSTR szHtml; + WCHAR szFile[1]; +} ITS_IMonikerImpl; + +/*** IUnknown methods ***/ +static HRESULT WINAPI ITS_IMonikerImpl_QueryInterface( + IMoniker* iface, + REFIID riid, + void** ppvObject) +{ + ITS_IMonikerImpl *This = (ITS_IMonikerImpl *)iface; + + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_IParseDisplayName)) + { + IClassFactory_AddRef(iface); + *ppvObject = This; + return S_OK; + } + + WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject); + return E_NOINTERFACE; +} + +static ULONG WINAPI ITS_IMonikerImpl_AddRef( + IMoniker* iface) +{ + ITS_IMonikerImpl *This = (ITS_IMonikerImpl *)iface; + TRACE("%p\n", This); + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI ITS_IMonikerImpl_Release( + IMoniker* iface) +{ + ITS_IMonikerImpl *This = (ITS_IMonikerImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); + + if (ref == 0) { + HeapFree(GetProcessHeap(), 0, This); + ITSS_UnlockModule(); + } + + return ref; +} + +/*** IPersist methods ***/ +static HRESULT WINAPI ITS_IMonikerImpl_GetClassID( + IMoniker* iface, + CLSID* pClassID) +{ + ITS_IMonikerImpl *This = (ITS_IMonikerImpl *)iface; + + TRACE("%p %p\n", This, pClassID); + *pClassID = CLSID_ITStorage; + return S_OK; +} + +/*** IPersistStream methods ***/ +static HRESULT WINAPI ITS_IMonikerImpl_IsDirty( + IMoniker* iface) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITS_IMonikerImpl_Load( + IMoniker* iface, + IStream* pStm) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITS_IMonikerImpl_Save( + IMoniker* iface, + IStream* pStm, + BOOL fClearDirty) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITS_IMonikerImpl_GetSizeMax( + IMoniker* iface, + ULARGE_INTEGER* pcbSize) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +/*** IMoniker methods ***/ +static HRESULT WINAPI ITS_IMonikerImpl_BindToObject( + IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + REFIID riidResult, + void** ppvResult) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITS_IMonikerImpl_BindToStorage( + IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + REFIID riid, + void** ppvObj) +{ + ITS_IMonikerImpl *This = (ITS_IMonikerImpl *)iface; + DWORD grfMode = STGM_SIMPLE | STGM_READ | STGM_SHARE_EXCLUSIVE; + HRESULT r; + IStorage *stg = NULL; + + TRACE("%p %p %p %s %p\n", This, + pbc, pmkToLeft, debugstr_guid(riid), ppvObj); + + r = ITSS_StgOpenStorage( This->szFile, NULL, grfMode, 0, 0, &stg ); + if( r == S_OK ) + { + TRACE("Opened storage %s\n", debugstr_w( This->szFile ) ); + if (IsEqualGUID(riid, &IID_IStream)) + r = IStorage_OpenStream( stg, This->szHtml, + NULL, grfMode, 0, (IStream**)ppvObj ); + else if (IsEqualGUID(riid, &IID_IStorage)) + r = IStorage_OpenStorage( stg, This->szHtml, + NULL, grfMode, NULL, 0, (IStorage**)ppvObj ); + else + r = STG_E_ACCESSDENIED; + IStorage_Release( stg ); + } + + return r; +} + +static HRESULT WINAPI ITS_IMonikerImpl_Reduce( + IMoniker* iface, + IBindCtx* pbc, + DWORD dwReduceHowFar, + IMoniker** ppmkToLeft, + IMoniker** ppmkReduced) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITS_IMonikerImpl_ComposeWith( + IMoniker* iface, + IMoniker* pmkRight, + BOOL fOnlyIfNotGeneric, + IMoniker** ppmkComposite) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITS_IMonikerImpl_Enum( + IMoniker* iface, + BOOL fForward, + IEnumMoniker** ppenumMoniker) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITS_IMonikerImpl_IsEqual( + IMoniker* iface, + IMoniker* pmkOtherMoniker) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITS_IMonikerImpl_Hash( + IMoniker* iface, + DWORD* pdwHash) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITS_IMonikerImpl_IsRunning( + IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + IMoniker* pmkNewlyRunning) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITS_IMonikerImpl_GetTimeOfLastChange( + IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + FILETIME* pFileTime) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITS_IMonikerImpl_Inverse( + IMoniker* iface, + IMoniker** ppmk) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITS_IMonikerImpl_CommonPrefixWith( + IMoniker* iface, + IMoniker* pmkOther, + IMoniker** ppmkPrefix) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITS_IMonikerImpl_RelativePathTo( + IMoniker* iface, + IMoniker* pmkOther, + IMoniker** ppmkRelPath) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITS_IMonikerImpl_GetDisplayName( + IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + LPOLESTR* ppszDisplayName) +{ + ITS_IMonikerImpl *This = (ITS_IMonikerImpl *)iface; + static const WCHAR szFormat[] = { + 'm','s','-','i','t','s',':','%','s',':',':','%','s',0 }; + DWORD len = sizeof szFormat / sizeof(WCHAR); + LPWSTR str; + + TRACE("%p %p %p %p\n", iface, pbc, pmkToLeft, ppszDisplayName); + + len = strlenW( This->szFile ) + strlenW( This->szHtml ); + str = CoTaskMemAlloc( len*sizeof(WCHAR) ); + sprintfW( str, szFormat, This->szFile, This->szHtml ); + + *ppszDisplayName = str; + + return S_OK; +} + +static HRESULT WINAPI ITS_IMonikerImpl_ParseDisplayName( + IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + LPOLESTR pszDisplayName, + ULONG* pchEaten, + IMoniker** ppmkOut) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITS_IMonikerImpl_IsSystemMoniker( + IMoniker* iface, + DWORD* pdwMksys) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static const IMonikerVtbl ITS_IMonikerImpl_Vtbl = +{ + ITS_IMonikerImpl_QueryInterface, + ITS_IMonikerImpl_AddRef, + ITS_IMonikerImpl_Release, + ITS_IMonikerImpl_GetClassID, + ITS_IMonikerImpl_IsDirty, + ITS_IMonikerImpl_Load, + ITS_IMonikerImpl_Save, + ITS_IMonikerImpl_GetSizeMax, + ITS_IMonikerImpl_BindToObject, + ITS_IMonikerImpl_BindToStorage, + ITS_IMonikerImpl_Reduce, + ITS_IMonikerImpl_ComposeWith, + ITS_IMonikerImpl_Enum, + ITS_IMonikerImpl_IsEqual, + ITS_IMonikerImpl_Hash, + ITS_IMonikerImpl_IsRunning, + ITS_IMonikerImpl_GetTimeOfLastChange, + ITS_IMonikerImpl_Inverse, + ITS_IMonikerImpl_CommonPrefixWith, + ITS_IMonikerImpl_RelativePathTo, + ITS_IMonikerImpl_GetDisplayName, + ITS_IMonikerImpl_ParseDisplayName, + ITS_IMonikerImpl_IsSystemMoniker +}; + +static HRESULT ITS_IMoniker_create( IMoniker **ppObj, LPCWSTR name, DWORD n ) +{ + ITS_IMonikerImpl *itsmon; + DWORD sz; + + /* szFile[1] has space for one character already */ + sz = sizeof(ITS_IMonikerImpl) + strlenW( name )*sizeof(WCHAR); + + itsmon = HeapAlloc( GetProcessHeap(), 0, sz ); + itsmon->vtbl_ITS_IMoniker = &ITS_IMonikerImpl_Vtbl; + itsmon->ref = 1; + strcpyW( itsmon->szFile, name ); + itsmon->szHtml = &itsmon->szFile[n]; + + while( *itsmon->szHtml == ':' ) + *itsmon->szHtml++ = 0; + + TRACE("-> %p %s %s\n", itsmon, + debugstr_w(itsmon->szFile), debugstr_w(itsmon->szHtml) ); + *ppObj = (IMoniker*) itsmon; + + ITSS_LockModule(); + return S_OK; +} + +/*****************************************************************************/ + +typedef struct { + const IParseDisplayNameVtbl *vtbl_ITS_IParseDisplayName; + LONG ref; +} ITS_IParseDisplayNameImpl; + +static HRESULT WINAPI ITS_IParseDisplayNameImpl_QueryInterface( + IParseDisplayName* iface, + REFIID riid, + void** ppvObject) +{ + ITS_IParseDisplayNameImpl *This = (ITS_IParseDisplayNameImpl *)iface; + + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_IParseDisplayName)) + { + IClassFactory_AddRef(iface); + *ppvObject = This; + return S_OK; + } + + WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject); + return E_NOINTERFACE; +} + +static ULONG WINAPI ITS_IParseDisplayNameImpl_AddRef( + IParseDisplayName* iface) +{ + ITS_IParseDisplayNameImpl *This = (ITS_IParseDisplayNameImpl *)iface; + TRACE("%p\n", This); + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI ITS_IParseDisplayNameImpl_Release( + IParseDisplayName* iface) +{ + ITS_IParseDisplayNameImpl *This = (ITS_IParseDisplayNameImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); + + if (ref == 0) { + HeapFree(GetProcessHeap(), 0, This); + ITSS_UnlockModule(); + } + + return ref; +} + +static HRESULT WINAPI ITS_IParseDisplayNameImpl_ParseDisplayName( + IParseDisplayName *iface, + IBindCtx * pbc, + LPOLESTR pszDisplayName, + ULONG * pchEaten, + IMoniker ** ppmkOut) +{ + static const WCHAR szPrefix[] = { + '@','M','S','I','T','S','t','o','r','e',':',0 }; + const DWORD prefix_len = (sizeof szPrefix/sizeof szPrefix[0])-1; + DWORD n; + + ITS_IParseDisplayNameImpl *This = (ITS_IParseDisplayNameImpl *)iface; + + TRACE("%p %s %p %p\n", This, + debugstr_w( pszDisplayName ), pchEaten, ppmkOut ); + + if( strncmpW( pszDisplayName, szPrefix, prefix_len ) ) + return MK_E_SYNTAX; + + /* search backwards for a double colon */ + for( n = strlenW( pszDisplayName ) - 3; prefix_len <= n; n-- ) + if( ( pszDisplayName[n] == ':' ) && ( pszDisplayName[n+1] == ':' ) ) + break; + + if( n < prefix_len ) + return MK_E_SYNTAX; + + if( !pszDisplayName[n+2] ) + return MK_E_SYNTAX; + + *pchEaten = strlenW( pszDisplayName ) - n - 3; + + return ITS_IMoniker_create( ppmkOut, + &pszDisplayName[prefix_len], n-prefix_len ); +} + +static const IParseDisplayNameVtbl ITS_IParseDisplayNameImpl_Vtbl = +{ + ITS_IParseDisplayNameImpl_QueryInterface, + ITS_IParseDisplayNameImpl_AddRef, + ITS_IParseDisplayNameImpl_Release, + ITS_IParseDisplayNameImpl_ParseDisplayName +}; + +HRESULT ITS_IParseDisplayName_create(IUnknown *pUnkOuter, LPVOID *ppObj) +{ + ITS_IParseDisplayNameImpl *its; + + if( pUnkOuter ) + return CLASS_E_NOAGGREGATION; + + its = HeapAlloc( GetProcessHeap(), 0, sizeof(ITS_IParseDisplayNameImpl) ); + its->vtbl_ITS_IParseDisplayName = &ITS_IParseDisplayNameImpl_Vtbl; + its->ref = 1; + + TRACE("-> %p\n", its); + *ppObj = (LPVOID) its; + + ITSS_LockModule(); + return S_OK; +} diff --git a/reactos/dll/win32/itss/protocol.c b/reactos/dll/win32/itss/protocol.c new file mode 100644 index 00000000000..c2277e2c210 --- /dev/null +++ b/reactos/dll/win32/itss/protocol.c @@ -0,0 +1,488 @@ +/* + * Copyright 2006-2007 Jacek Caban for CodeWeavers + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winreg.h" +#include "ole2.h" +#include "urlmon.h" +#include "shlwapi.h" +#include "itsstor.h" +#include "chm_lib.h" + +#include "wine/debug.h" +#include "wine/unicode.h" + +WINE_DEFAULT_DEBUG_CHANNEL(itss); + +typedef struct { + const IInternetProtocolVtbl *lpInternetProtocolVtbl; + const IInternetProtocolInfoVtbl *lpInternetProtocolInfoVtbl; + + LONG ref; + + ULONG offset; + struct chmFile *chm_file; + struct chmUnitInfo chm_object; +} ITSProtocol; + +#define PROTOCOL(x) ((IInternetProtocol*) &(x)->lpInternetProtocolVtbl) +#define PROTINFO(x) ((IInternetProtocolInfo*) &(x)->lpInternetProtocolInfoVtbl) + +static void release_chm(ITSProtocol *This) +{ + if(This->chm_file) { + chm_close(This->chm_file); + This->chm_file = NULL; + } + This->offset = 0; +} + +#define PROTOCOL_THIS(iface) DEFINE_THIS(ITSProtocol, InternetProtocol, iface) + +static HRESULT WINAPI ITSProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv) +{ + ITSProtocol *This = PROTOCOL_THIS(iface); + + *ppv = NULL; + if(IsEqualGUID(&IID_IUnknown, riid)) { + TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); + *ppv = PROTOCOL(This); + }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) { + TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv); + *ppv = PROTOCOL(This); + }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) { + TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv); + *ppv = PROTOCOL(This); + }else if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) { + TRACE("(%p)->(IID_IInternetProtocolInfo %p)\n", This, ppv); + *ppv = PROTINFO(This); + } + + if(*ppv) { + IInternetProtocol_AddRef(iface); + return S_OK; + } + + WARN("not supported interface %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI ITSProtocol_AddRef(IInternetProtocol *iface) +{ + ITSProtocol *This = PROTOCOL_THIS(iface); + LONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p) ref=%d\n", This, ref); + return ref; +} + +static ULONG WINAPI ITSProtocol_Release(IInternetProtocol *iface) +{ + ITSProtocol *This = PROTOCOL_THIS(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if(!ref) { + release_chm(This); + HeapFree(GetProcessHeap(), 0, This); + + ITSS_UnlockModule(); + } + + return ref; +} + +static LPCWSTR skip_schema(LPCWSTR url) +{ + static const WCHAR its_schema[] = {'i','t','s',':'}; + static const WCHAR msits_schema[] = {'m','s','-','i','t','s',':'}; + static const WCHAR mk_schema[] = {'m','k',':','@','M','S','I','T','S','t','o','r','e',':'}; + + if(!strncmpiW(its_schema, url, sizeof(its_schema)/sizeof(WCHAR))) + return url+sizeof(its_schema)/sizeof(WCHAR); + if(!strncmpiW(msits_schema, url, sizeof(msits_schema)/sizeof(WCHAR))) + return url+sizeof(msits_schema)/sizeof(WCHAR); + if(!strncmpiW(mk_schema, url, sizeof(mk_schema)/sizeof(WCHAR))) + return url+sizeof(mk_schema)/sizeof(WCHAR); + + return NULL; +} + +static HRESULT report_result(IInternetProtocolSink *sink, HRESULT hres) +{ + IInternetProtocolSink_ReportResult(sink, hres, 0, NULL); + return hres; +} + +static HRESULT WINAPI ITSProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, + IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, + DWORD grfPI, DWORD dwReserved) +{ + ITSProtocol *This = PROTOCOL_THIS(iface); + BINDINFO bindinfo; + DWORD bindf = 0, len; + LPWSTR file_name, mime, object_name, p; + LPCWSTR ptr; + struct chmFile *chm_file; + struct chmUnitInfo chm_object; + int res; + HRESULT hres; + + static const WCHAR separator[] = {':',':',0}; + + TRACE("(%p)->(%s %p %p %08x %d)\n", This, debugstr_w(szUrl), pOIProtSink, + pOIBindInfo, grfPI, dwReserved); + + ptr = skip_schema(szUrl); + if(!ptr) + return INET_E_USE_DEFAULT_PROTOCOLHANDLER; + + memset(&bindinfo, 0, sizeof(bindinfo)); + bindinfo.cbSize = sizeof(BINDINFO); + hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &bindf, &bindinfo); + if(FAILED(hres)) { + WARN("GetBindInfo failed: %08x\n", hres); + return hres; + } + + ReleaseBindInfo(&bindinfo); + + len = strlenW(ptr)+3; + file_name = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); + memcpy(file_name, ptr, len*sizeof(WCHAR)); + hres = UrlUnescapeW(file_name, NULL, &len, URL_UNESCAPE_INPLACE); + if(FAILED(hres)) { + WARN("UrlUnescape failed: %08x\n", hres); + HeapFree(GetProcessHeap(), 0, file_name); + return hres; + } + + p = strstrW(file_name, separator); + if(!p) { + WARN("invalid url\n"); + HeapFree(GetProcessHeap(), 0, file_name); + return report_result(pOIProtSink, STG_E_FILENOTFOUND); + } + + *p = 0; + chm_file = chm_openW(file_name); + if(!chm_file) { + WARN("Could not open chm file\n"); + HeapFree(GetProcessHeap(), 0, file_name); + return report_result(pOIProtSink, STG_E_FILENOTFOUND); + } + + object_name = p+2; + len = strlenW(object_name); + + if(*object_name != '/' && *object_name != '\\') { + memmove(object_name+1, object_name, (len+1)*sizeof(WCHAR)); + *object_name = '/'; + len++; + } + + if(object_name[len-1] == '/') + object_name[--len] = 0; + + for(p=object_name; *p; p++) { + if(*p == '\\') + *p = '/'; + } + + TRACE("Resolving %s\n", debugstr_w(object_name)); + + memset(&chm_object, 0, sizeof(chm_object)); + res = chm_resolve_object(chm_file, object_name, &chm_object); + if(res != CHM_RESOLVE_SUCCESS) { + WARN("Could not resolve chm object\n"); + HeapFree(GetProcessHeap(), 0, file_name); + chm_close(chm_file); + return report_result(pOIProtSink, STG_E_FILENOTFOUND); + } + + IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, + strrchrW(object_name, '/')+1); + + /* FIXME: Native doesn't use FindMimeFromData */ + hres = FindMimeFromData(NULL, object_name, NULL, 0, NULL, 0, &mime, 0); + HeapFree(GetProcessHeap(), 0, file_name); + if(SUCCEEDED(hres)) { + IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, mime); + CoTaskMemFree(mime); + } + + release_chm(This); /* Native leaks handle here */ + This->chm_file = chm_file; + This->chm_object = chm_object; + + hres = IInternetProtocolSink_ReportData(pOIProtSink, + BSCF_FIRSTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE, + chm_object.length, chm_object.length); + if(FAILED(hres)) { + WARN("ReportData failed: %08x\n", hres); + release_chm(This); + return report_result(pOIProtSink, hres); + } + + hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_BEGINDOWNLOADDATA, NULL); + + return report_result(pOIProtSink, hres); +} + +static HRESULT WINAPI ITSProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData) +{ + ITSProtocol *This = PROTOCOL_THIS(iface); + FIXME("(%p)->(%p)\n", This, pProtocolData); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason, + DWORD dwOptions) +{ + ITSProtocol *This = PROTOCOL_THIS(iface); + FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions) +{ + ITSProtocol *This = PROTOCOL_THIS(iface); + + TRACE("(%p)->(%08x)\n", This, dwOptions); + + return S_OK; +} + +static HRESULT WINAPI ITSProtocol_Suspend(IInternetProtocol *iface) +{ + ITSProtocol *This = PROTOCOL_THIS(iface); + FIXME("(%p)\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSProtocol_Resume(IInternetProtocol *iface) +{ + ITSProtocol *This = PROTOCOL_THIS(iface); + FIXME("(%p)\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSProtocol_Read(IInternetProtocol *iface, void *pv, + ULONG cb, ULONG *pcbRead) +{ + ITSProtocol *This = PROTOCOL_THIS(iface); + + TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead); + + if(!This->chm_file) + return INET_E_DATA_NOT_AVAILABLE; + + *pcbRead = chm_retrieve_object(This->chm_file, &This->chm_object, pv, This->offset, cb); + This->offset += *pcbRead; + + return *pcbRead ? S_OK : S_FALSE; +} + +static HRESULT WINAPI ITSProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove, + DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) +{ + ITSProtocol *This = PROTOCOL_THIS(iface); + FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions) +{ + ITSProtocol *This = PROTOCOL_THIS(iface); + + TRACE("(%p)->(%08x)\n", This, dwOptions); + + return S_OK; +} + +static HRESULT WINAPI ITSProtocol_UnlockRequest(IInternetProtocol *iface) +{ + ITSProtocol *This = PROTOCOL_THIS(iface); + + TRACE("(%p)\n", This); + + return S_OK; +} + +#undef PROTOCOL_THIS + +static const IInternetProtocolVtbl ITSProtocolVtbl = { + ITSProtocol_QueryInterface, + ITSProtocol_AddRef, + ITSProtocol_Release, + ITSProtocol_Start, + ITSProtocol_Continue, + ITSProtocol_Abort, + ITSProtocol_Terminate, + ITSProtocol_Suspend, + ITSProtocol_Resume, + ITSProtocol_Read, + ITSProtocol_Seek, + ITSProtocol_LockRequest, + ITSProtocol_UnlockRequest +}; + +#define PROTINFO_THIS(iface) DEFINE_THIS(ITSProtocol, InternetProtocolInfo, iface) + +static HRESULT WINAPI ITSProtocolInfo_QueryInterface(IInternetProtocolInfo *iface, + REFIID riid, void **ppv) +{ + ITSProtocol *This = PROTINFO_THIS(iface); + return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv); +} + +static ULONG WINAPI ITSProtocolInfo_AddRef(IInternetProtocolInfo *iface) +{ + ITSProtocol *This = PROTINFO_THIS(iface); + return IInternetProtocol_AddRef(PROTOCOL(This)); +} + +static ULONG WINAPI ITSProtocolInfo_Release(IInternetProtocolInfo *iface) +{ + ITSProtocol *This = PROTINFO_THIS(iface); + return IInternetProtocol_Release(PROTOCOL(This)); +} + +static HRESULT WINAPI ITSProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl, + PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult, + DWORD *pcchResult, DWORD dwReserved) +{ + ITSProtocol *This = PROTINFO_THIS(iface); + + TRACE("(%p)->(%s %x %08x %p %d %p %d)\n", This, debugstr_w(pwzUrl), ParseAction, + dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved); + + switch(ParseAction) { + case PARSE_CANONICALIZE: + FIXME("PARSE_CANONICALIZE\n"); + return E_NOTIMPL; + case PARSE_SECURITY_URL: + FIXME("PARSE_SECURITY_URL\n"); + return E_NOTIMPL; + default: + return INET_E_DEFAULT_ACTION; + } + + return S_OK; +} + +static HRESULT WINAPI ITSProtocolInfo_CombineUrl(IInternetProtocolInfo *iface, + LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult, + DWORD cchResult, DWORD* pcchResult, DWORD dwReserved) +{ + ITSProtocol *This = PROTINFO_THIS(iface); + LPCWSTR base_end, ptr; + DWORD rel_len; + + static const WCHAR separator[] = {':',':',0}; + + TRACE("(%p)->(%s %s %08x %p %d %p %d)\n", This, debugstr_w(pwzBaseUrl), + debugstr_w(pwzRelativeUrl), dwCombineFlags, pwzResult, cchResult, + pcchResult, dwReserved); + + base_end = strstrW(pwzBaseUrl, separator); + if(!base_end) + return 0x80041001; + base_end += 2; + + if(!skip_schema(pwzBaseUrl)) + return INET_E_USE_DEFAULT_PROTOCOLHANDLER; + + if(strchrW(pwzRelativeUrl, ':')) + return STG_E_INVALIDNAME; + + if(pwzRelativeUrl[0] != '/') { + ptr = strrchrW(base_end, '/'); + if(ptr) + base_end = ptr+1; + else + base_end += strlenW(base_end); + } + + rel_len = strlenW(pwzRelativeUrl)+1; + + *pcchResult = rel_len + (base_end-pwzBaseUrl); + + if(*pcchResult > cchResult) + return E_OUTOFMEMORY; + + memcpy(pwzResult, pwzBaseUrl, (base_end-pwzBaseUrl)*sizeof(WCHAR)); + strcpyW(pwzResult + (base_end-pwzBaseUrl), pwzRelativeUrl); + + return S_OK; +} + +static HRESULT WINAPI ITSProtocolInfo_CompareUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl1, + LPCWSTR pwzUrl2, DWORD dwCompareFlags) +{ + ITSProtocol *This = PROTINFO_THIS(iface); + FIXME("%p)->(%s %s %08x)\n", This, debugstr_w(pwzUrl1), debugstr_w(pwzUrl2), dwCompareFlags); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl, + QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf, + DWORD dwReserved) +{ + ITSProtocol *This = PROTINFO_THIS(iface); + FIXME("(%p)->(%s %08x %08x %p %d %p %d)\n", This, debugstr_w(pwzUrl), QueryOption, + dwQueryFlags, pBuffer, cbBuffer, pcbBuf, dwReserved); + return E_NOTIMPL; +} + +#undef PROTINFO_THIS + +static const IInternetProtocolInfoVtbl ITSProtocolInfoVtbl = { + ITSProtocolInfo_QueryInterface, + ITSProtocolInfo_AddRef, + ITSProtocolInfo_Release, + ITSProtocolInfo_ParseUrl, + ITSProtocolInfo_CombineUrl, + ITSProtocolInfo_CompareUrl, + ITSProtocolInfo_QueryInfo +}; + +HRESULT ITSProtocol_create(IUnknown *pUnkOuter, LPVOID *ppobj) +{ + ITSProtocol *ret; + + TRACE("(%p %p)\n", pUnkOuter, ppobj); + + ITSS_LockModule(); + + ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ITSProtocol)); + + ret->lpInternetProtocolVtbl = &ITSProtocolVtbl; + ret->lpInternetProtocolInfoVtbl = &ITSProtocolInfoVtbl; + ret->ref = 1; + + *ppobj = PROTOCOL(ret); + + return S_OK; +} diff --git a/reactos/dll/win32/itss/rsrc.rc b/reactos/dll/win32/itss/rsrc.rc new file mode 100644 index 00000000000..2b0edd8c700 --- /dev/null +++ b/reactos/dll/win32/itss/rsrc.rc @@ -0,0 +1,20 @@ +/* + * Copyright 2006 Jacek Caban for CodeWeavers + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* @makedep: itss.inf */ +REGINST REGINST itss.inf diff --git a/reactos/dll/win32/itss/storage.c b/reactos/dll/win32/itss/storage.c new file mode 100644 index 00000000000..de0acfaee3e --- /dev/null +++ b/reactos/dll/win32/itss/storage.c @@ -0,0 +1,840 @@ +/* + * ITSS Storage implementation + * + * Copyright 2004 Mike McCormack + * + * see http://bonedaddy.net/pabs3/hhm/#chmspec + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "ole2.h" + +#include "chm_lib.h" +#include "itsstor.h" + +#include "wine/itss.h" +#include "wine/unicode.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(itss); + +/************************************************************************/ + +typedef struct _ITSS_IStorageImpl +{ + const IStorageVtbl *vtbl_IStorage; + LONG ref; + struct chmFile *chmfile; + WCHAR dir[1]; +} ITSS_IStorageImpl; + +struct enum_info +{ + struct enum_info *next, *prev; + struct chmUnitInfo ui; +}; + +typedef struct _IEnumSTATSTG_Impl +{ + const IEnumSTATSTGVtbl *vtbl_IEnumSTATSTG; + LONG ref; + struct enum_info *first, *last, *current; +} IEnumSTATSTG_Impl; + +typedef struct _IStream_Impl +{ + const IStreamVtbl *vtbl_IStream; + LONG ref; + ITSS_IStorageImpl *stg; + ULONGLONG addr; + struct chmUnitInfo ui; +} IStream_Impl; + +static HRESULT ITSS_create_chm_storage( + struct chmFile *chmfile, const WCHAR *dir, IStorage** ppstgOpen ); +static IStream_Impl* ITSS_create_stream( + ITSS_IStorageImpl *stg, struct chmUnitInfo *ui ); + +/************************************************************************/ + +static HRESULT WINAPI ITSS_IEnumSTATSTG_QueryInterface( + IEnumSTATSTG* iface, + REFIID riid, + void** ppvObject) +{ + IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface; + + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_IEnumSTATSTG)) + { + IEnumSTATSTG_AddRef(iface); + *ppvObject = This; + return S_OK; + } + + WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject); + return E_NOINTERFACE; +} + +static ULONG WINAPI ITSS_IEnumSTATSTG_AddRef( + IEnumSTATSTG* iface) +{ + IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface; + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI ITSS_IEnumSTATSTG_Release( + IEnumSTATSTG* iface) +{ + IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface; + + ULONG ref = InterlockedDecrement(&This->ref); + + if (ref == 0) + { + while( This->first ) + { + struct enum_info *t = This->first->next; + HeapFree( GetProcessHeap(), 0, This->first ); + This->first = t; + } + HeapFree(GetProcessHeap(), 0, This); + ITSS_UnlockModule(); + } + + return ref; +} + +static HRESULT WINAPI ITSS_IEnumSTATSTG_Next( + IEnumSTATSTG* iface, + ULONG celt, + STATSTG* rgelt, + ULONG* pceltFetched) +{ + IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface; + DWORD len, n; + struct enum_info *cur; + + TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched ); + + cur = This->current; + n = 0; + while( (nui.path; + if( *str == '/' ) + str++; + len = strlenW( str ) + 1; + rgelt->pwcsName = CoTaskMemAlloc( len*sizeof(WCHAR) ); + strcpyW( rgelt->pwcsName, str ); + + /* determine the type */ + if( rgelt->pwcsName[len-2] == '/' ) + { + rgelt->pwcsName[len-2] = 0; + rgelt->type = STGTY_STORAGE; + } + else + rgelt->type = STGTY_STREAM; + + /* copy the size */ + rgelt->cbSize.QuadPart = cur->ui.length; + + /* advance to the next item if it exists */ + n++; + cur = cur->next; + } + + This->current = cur; + *pceltFetched = n; + + if( n < celt ) + return S_FALSE; + + return S_OK; +} + +static HRESULT WINAPI ITSS_IEnumSTATSTG_Skip( + IEnumSTATSTG* iface, + ULONG celt) +{ + IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface; + DWORD n; + struct enum_info *cur; + + TRACE("%p %u\n", This, celt ); + + cur = This->current; + n = 0; + while( (nnext; + } + This->current = cur; + + if( n < celt ) + return S_FALSE; + + return S_OK; +} + +static HRESULT WINAPI ITSS_IEnumSTATSTG_Reset( + IEnumSTATSTG* iface) +{ + IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface; + + TRACE("%p\n", This ); + + This->current = This->first; + + return S_OK; +} + +static HRESULT WINAPI ITSS_IEnumSTATSTG_Clone( + IEnumSTATSTG* iface, + IEnumSTATSTG** ppenum) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static const IEnumSTATSTGVtbl IEnumSTATSTG_vtbl = +{ + ITSS_IEnumSTATSTG_QueryInterface, + ITSS_IEnumSTATSTG_AddRef, + ITSS_IEnumSTATSTG_Release, + ITSS_IEnumSTATSTG_Next, + ITSS_IEnumSTATSTG_Skip, + ITSS_IEnumSTATSTG_Reset, + ITSS_IEnumSTATSTG_Clone +}; + +static IEnumSTATSTG_Impl *ITSS_create_enum( void ) +{ + IEnumSTATSTG_Impl *stgenum; + + stgenum = HeapAlloc( GetProcessHeap(), 0, sizeof (IEnumSTATSTG_Impl) ); + stgenum->vtbl_IEnumSTATSTG = &IEnumSTATSTG_vtbl; + stgenum->ref = 1; + stgenum->first = NULL; + stgenum->last = NULL; + stgenum->current = NULL; + + ITSS_LockModule(); + TRACE(" -> %p\n", stgenum ); + + return stgenum; +} + +/************************************************************************/ + +static HRESULT WINAPI ITSS_IStorageImpl_QueryInterface( + IStorage* iface, + REFIID riid, + void** ppvObject) +{ + ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface; + + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_IStorage)) + { + IStorage_AddRef(iface); + *ppvObject = This; + return S_OK; + } + + WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject); + return E_NOINTERFACE; +} + +static ULONG WINAPI ITSS_IStorageImpl_AddRef( + IStorage* iface) +{ + ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface; + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI ITSS_IStorageImpl_Release( + IStorage* iface) +{ + ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface; + + ULONG ref = InterlockedDecrement(&This->ref); + + if (ref == 0) + { + chm_close(This->chmfile); + HeapFree(GetProcessHeap(), 0, This); + ITSS_UnlockModule(); + } + + return ref; +} + +static HRESULT WINAPI ITSS_IStorageImpl_CreateStream( + IStorage* iface, + LPCOLESTR pwcsName, + DWORD grfMode, + DWORD reserved1, + DWORD reserved2, + IStream** ppstm) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStorageImpl_OpenStream( + IStorage* iface, + LPCOLESTR pwcsName, + void* reserved1, + DWORD grfMode, + DWORD reserved2, + IStream** ppstm) +{ + ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface; + IStream_Impl *stm; + DWORD len; + struct chmUnitInfo ui; + int r; + WCHAR *path, *p; + + TRACE("%p %s %p %u %u %p\n", This, debugstr_w(pwcsName), + reserved1, grfMode, reserved2, ppstm ); + + len = strlenW( This->dir ) + strlenW( pwcsName ) + 1; + path = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + strcpyW( path, This->dir ); + + if( pwcsName[0] == '/' || pwcsName[0] == '\\' ) + { + p = &path[strlenW( path ) - 1]; + while( ( path <= p ) && ( *p == '/' ) ) + *p-- = 0; + } + strcatW( path, pwcsName ); + + for(p=path; *p; p++) { + if(*p == '\\') + *p = '/'; + } + + if(*--p == '/') + *p = 0; + + TRACE("Resolving %s\n", debugstr_w(path)); + + r = chm_resolve_object(This->chmfile, path, &ui); + HeapFree( GetProcessHeap(), 0, path ); + + if( r != CHM_RESOLVE_SUCCESS ) { + WARN("Could not resolve object\n"); + return STG_E_FILENOTFOUND; + } + + stm = ITSS_create_stream( This, &ui ); + if( !stm ) + return E_FAIL; + + *ppstm = (IStream*) stm; + + return S_OK; +} + +static HRESULT WINAPI ITSS_IStorageImpl_CreateStorage( + IStorage* iface, + LPCOLESTR pwcsName, + DWORD grfMode, + DWORD dwStgFmt, + DWORD reserved2, + IStorage** ppstg) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStorageImpl_OpenStorage( + IStorage* iface, + LPCOLESTR pwcsName, + IStorage* pstgPriority, + DWORD grfMode, + SNB snbExclude, + DWORD reserved, + IStorage** ppstg) +{ + ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface; + + FIXME("%p %s %p %u %p %u %p\n", This, debugstr_w(pwcsName), + pstgPriority, grfMode, snbExclude, reserved, ppstg); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStorageImpl_CopyTo( + IStorage* iface, + DWORD ciidExclude, + const IID* rgiidExclude, + SNB snbExclude, + IStorage* pstgDest) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStorageImpl_MoveElementTo( + IStorage* iface, + LPCOLESTR pwcsName, + IStorage* pstgDest, + LPCOLESTR pwcsNewName, + DWORD grfFlags) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStorageImpl_Commit( + IStorage* iface, + DWORD grfCommitFlags) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStorageImpl_Revert( + IStorage* iface) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static int ITSS_chm_enumerator( + struct chmFile *h, + struct chmUnitInfo *ui, + void *context) +{ + struct enum_info *info; + IEnumSTATSTG_Impl* stgenum = context; + + TRACE("adding %s to enumeration\n", debugstr_w(ui->path) ); + + info = HeapAlloc( GetProcessHeap(), 0, sizeof (struct enum_info) ); + info->ui = *ui; + + info->next = NULL; + info->prev = stgenum->last; + if( stgenum->last ) + stgenum->last->next = info; + else + stgenum->first = info; + stgenum->last = info; + + return CHM_ENUMERATOR_CONTINUE; +} + +static HRESULT WINAPI ITSS_IStorageImpl_EnumElements( + IStorage* iface, + DWORD reserved1, + void* reserved2, + DWORD reserved3, + IEnumSTATSTG** ppenum) +{ + ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface; + IEnumSTATSTG_Impl* stgenum; + + TRACE("%p %d %p %d %p\n", This, reserved1, reserved2, reserved3, ppenum ); + + stgenum = ITSS_create_enum(); + if( !stgenum ) + return E_FAIL; + + chm_enumerate_dir(This->chmfile, + This->dir, + CHM_ENUMERATE_ALL, + ITSS_chm_enumerator, + stgenum ); + + stgenum->current = stgenum->first; + + *ppenum = (IEnumSTATSTG*) stgenum; + + return S_OK; +} + +static HRESULT WINAPI ITSS_IStorageImpl_DestroyElement( + IStorage* iface, + LPCOLESTR pwcsName) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStorageImpl_RenameElement( + IStorage* iface, + LPCOLESTR pwcsOldName, + LPCOLESTR pwcsNewName) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStorageImpl_SetElementTimes( + IStorage* iface, + LPCOLESTR pwcsName, + const FILETIME* pctime, + const FILETIME* patime, + const FILETIME* pmtime) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStorageImpl_SetClass( + IStorage* iface, + REFCLSID clsid) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStorageImpl_SetStateBits( + IStorage* iface, + DWORD grfStateBits, + DWORD grfMask) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStorageImpl_Stat( + IStorage* iface, + STATSTG* pstatstg, + DWORD grfStatFlag) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static const IStorageVtbl ITSS_IStorageImpl_Vtbl = +{ + ITSS_IStorageImpl_QueryInterface, + ITSS_IStorageImpl_AddRef, + ITSS_IStorageImpl_Release, + ITSS_IStorageImpl_CreateStream, + ITSS_IStorageImpl_OpenStream, + ITSS_IStorageImpl_CreateStorage, + ITSS_IStorageImpl_OpenStorage, + ITSS_IStorageImpl_CopyTo, + ITSS_IStorageImpl_MoveElementTo, + ITSS_IStorageImpl_Commit, + ITSS_IStorageImpl_Revert, + ITSS_IStorageImpl_EnumElements, + ITSS_IStorageImpl_DestroyElement, + ITSS_IStorageImpl_RenameElement, + ITSS_IStorageImpl_SetElementTimes, + ITSS_IStorageImpl_SetClass, + ITSS_IStorageImpl_SetStateBits, + ITSS_IStorageImpl_Stat, +}; + +static HRESULT ITSS_create_chm_storage( + struct chmFile *chmfile, const WCHAR *dir, IStorage** ppstgOpen ) +{ + ITSS_IStorageImpl *stg; + DWORD len; + + TRACE("%p %s\n", chmfile, debugstr_w( dir ) ); + + len = strlenW( dir ) + 1; + stg = HeapAlloc( GetProcessHeap(), 0, + sizeof (ITSS_IStorageImpl) + len*sizeof(WCHAR) ); + stg->vtbl_IStorage = &ITSS_IStorageImpl_Vtbl; + stg->ref = 1; + stg->chmfile = chmfile; + strcpyW( stg->dir, dir ); + + *ppstgOpen = (IStorage*) stg; + + ITSS_LockModule(); + return S_OK; +} + +HRESULT ITSS_StgOpenStorage( + const WCHAR* pwcsName, + IStorage* pstgPriority, + DWORD grfMode, + SNB snbExclude, + DWORD reserved, + IStorage** ppstgOpen) +{ + struct chmFile *chmfile; + static const WCHAR szRoot[] = { '/', 0 }; + + TRACE("%s\n", debugstr_w(pwcsName) ); + + chmfile = chm_openW( pwcsName ); + if( !chmfile ) + return E_FAIL; + + return ITSS_create_chm_storage( chmfile, szRoot, ppstgOpen ); +} + +/************************************************************************/ + +static HRESULT WINAPI ITSS_IStream_QueryInterface( + IStream* iface, + REFIID riid, + void** ppvObject) +{ + IStream_Impl *This = (IStream_Impl *)iface; + + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_ISequentialStream) + || IsEqualGUID(riid, &IID_IStream)) + { + IStream_AddRef(iface); + *ppvObject = This; + return S_OK; + } + + WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject); + return E_NOINTERFACE; +} + +static ULONG WINAPI ITSS_IStream_AddRef( + IStream* iface) +{ + IStream_Impl *This = (IStream_Impl *)iface; + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI ITSS_IStream_Release( + IStream* iface) +{ + IStream_Impl *This = (IStream_Impl *)iface; + + ULONG ref = InterlockedDecrement(&This->ref); + + if (ref == 0) + { + IStorage_Release( (IStorage*) This->stg ); + HeapFree(GetProcessHeap(), 0, This); + ITSS_UnlockModule(); + } + + return ref; +} + +static HRESULT WINAPI ITSS_IStream_Read( + IStream* iface, + void* pv, + ULONG cb, + ULONG* pcbRead) +{ + IStream_Impl *This = (IStream_Impl *)iface; + ULONG count; + + TRACE("%p %p %u %p\n", This, pv, cb, pcbRead); + + count = chm_retrieve_object(This->stg->chmfile, + &This->ui, pv, This->addr, cb); + This->addr += count; + if( pcbRead ) + *pcbRead = count; + + return count ? S_OK : S_FALSE; +} + +static HRESULT WINAPI ITSS_IStream_Write( + IStream* iface, + const void* pv, + ULONG cb, + ULONG* pcbWritten) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStream_Seek( + IStream* iface, + LARGE_INTEGER dlibMove, + DWORD dwOrigin, + ULARGE_INTEGER* plibNewPosition) +{ + IStream_Impl *This = (IStream_Impl *)iface; + LONGLONG newpos; + + TRACE("%p %s %u %p\n", This, + wine_dbgstr_longlong( dlibMove.QuadPart ), dwOrigin, plibNewPosition ); + + newpos = This->addr; + switch( dwOrigin ) + { + case STREAM_SEEK_CUR: + newpos = This->addr + dlibMove.QuadPart; + break; + case STREAM_SEEK_SET: + newpos = dlibMove.QuadPart; + break; + case STREAM_SEEK_END: + newpos = This->ui.length + dlibMove.QuadPart; + break; + } + + if( ( newpos < 0 ) || ( newpos > This->ui.length ) ) + return STG_E_INVALIDPOINTER; + + This->addr = newpos; + if( plibNewPosition ) + plibNewPosition->QuadPart = This->addr; + + return S_OK; +} + +static HRESULT WINAPI ITSS_IStream_SetSize( + IStream* iface, + ULARGE_INTEGER libNewSize) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStream_CopyTo( + IStream* iface, + IStream* pstm, + ULARGE_INTEGER cb, + ULARGE_INTEGER* pcbRead, + ULARGE_INTEGER* pcbWritten) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStream_Commit( + IStream* iface, + DWORD grfCommitFlags) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStream_Revert( + IStream* iface) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStream_LockRegion( + IStream* iface, + ULARGE_INTEGER libOffset, + ULARGE_INTEGER cb, + DWORD dwLockType) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStream_UnlockRegion( + IStream* iface, + ULARGE_INTEGER libOffset, + ULARGE_INTEGER cb, + DWORD dwLockType) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITSS_IStream_Stat( + IStream* iface, + STATSTG* pstatstg, + DWORD grfStatFlag) +{ + IStream_Impl *This = (IStream_Impl *)iface; + + TRACE("%p %p %d\n", This, pstatstg, grfStatFlag); + + memset( pstatstg, 0, sizeof *pstatstg ); + if( !( grfStatFlag & STATFLAG_NONAME ) ) + { + FIXME("copy the name\n"); + } + pstatstg->type = STGTY_STREAM; + pstatstg->cbSize.QuadPart = This->ui.length; + pstatstg->grfMode = STGM_READ; + pstatstg->clsid = CLSID_ITStorage; + + return S_OK; +} + +static HRESULT WINAPI ITSS_IStream_Clone( + IStream* iface, + IStream** ppstm) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static const IStreamVtbl ITSS_IStream_vtbl = +{ + ITSS_IStream_QueryInterface, + ITSS_IStream_AddRef, + ITSS_IStream_Release, + ITSS_IStream_Read, + ITSS_IStream_Write, + ITSS_IStream_Seek, + ITSS_IStream_SetSize, + ITSS_IStream_CopyTo, + ITSS_IStream_Commit, + ITSS_IStream_Revert, + ITSS_IStream_LockRegion, + ITSS_IStream_UnlockRegion, + ITSS_IStream_Stat, + ITSS_IStream_Clone, +}; + +static IStream_Impl *ITSS_create_stream( + ITSS_IStorageImpl *stg, struct chmUnitInfo *ui ) +{ + IStream_Impl *stm; + + stm = HeapAlloc( GetProcessHeap(), 0, sizeof (IStream_Impl) ); + stm->vtbl_IStream = &ITSS_IStream_vtbl; + stm->ref = 1; + stm->addr = 0; + stm->ui = *ui; + stm->stg = stg; + IStorage_AddRef( (IStorage*) stg ); + + ITSS_LockModule(); + + TRACE(" -> %p\n", stm ); + + return stm; +} diff --git a/reactos/dll/win32/msimtf/activeimmapp.c b/reactos/dll/win32/msimtf/activeimmapp.c new file mode 100644 index 00000000000..73ce0758c70 --- /dev/null +++ b/reactos/dll/win32/msimtf/activeimmapp.c @@ -0,0 +1,827 @@ +/* + * ActiveIMMApp Interface + * + * Copyright 2008 CodeWeavers, Aric Stewart + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winreg.h" +#include "winuser.h" +#include "winerror.h" +#include "objbase.h" +#include "advpub.h" +#include "dimm.h" +#include "imm.h" + +#include "wine/unicode.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msimtf); + +typedef struct tagActiveIMMApp { + const IActiveIMMAppVtbl *vtbl; + LONG refCount; +} ActiveIMMApp; + +static void ActiveIMMApp_Destructor(ActiveIMMApp* This) +{ + TRACE("\n"); + HeapFree(GetProcessHeap(),0,This); +} + +static HRESULT WINAPI ActiveIMMApp_QueryInterface (IActiveIMMApp* iface, + REFIID iid, LPVOID *ppvOut) +{ + ActiveIMMApp *This = (ActiveIMMApp*)iface; + *ppvOut = NULL; + + if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IActiveIMMApp)) + { + *ppvOut = This; + } + + if (*ppvOut) + { + IUnknown_AddRef(iface); + return S_OK; + } + + WARN("unsupported interface: %s\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI ActiveIMMApp_AddRef(IActiveIMMApp* iface) +{ + ActiveIMMApp *This = (ActiveIMMApp*)iface; + return InterlockedIncrement(&This->refCount); +} + +static ULONG WINAPI ActiveIMMApp_Release(IActiveIMMApp* iface) +{ + ActiveIMMApp *This = (ActiveIMMApp*)iface; + ULONG ret; + + ret = InterlockedDecrement(&This->refCount); + if (ret == 0) + ActiveIMMApp_Destructor(This); + return ret; +} + +static HRESULT WINAPI ActiveIMMApp_AssociateContext(IActiveIMMApp* iface, + HWND hWnd, HIMC hIME, HIMC *phPrev) +{ + *phPrev = ImmAssociateContext(hWnd,hIME); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_ConfigureIMEA(IActiveIMMApp* This, + HKL hKL, HWND hwnd, DWORD dwMode, REGISTERWORDA *pData) +{ + BOOL rc; + + rc = ImmConfigureIMEA(hKL, hwnd, dwMode, pData); + if (rc) + return E_FAIL; + else + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_ConfigureIMEW(IActiveIMMApp* This, + HKL hKL, HWND hWnd, DWORD dwMode, REGISTERWORDW *pData) +{ + BOOL rc; + + rc = ImmConfigureIMEW(hKL, hWnd, dwMode, pData); + if (rc) + return E_FAIL; + else + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_CreateContext(IActiveIMMApp* This, + HIMC *phIMC) +{ + *phIMC = ImmCreateContext(); + if (*phIMC) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_DestroyContext(IActiveIMMApp* This, + HIMC hIME) +{ + BOOL rc; + + rc = ImmDestroyContext(hIME); + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_EnumRegisterWordA(IActiveIMMApp* This, + HKL hKL, LPSTR szReading, DWORD dwStyle, LPSTR szRegister, + LPVOID pData, IEnumRegisterWordA **pEnum) +{ + FIXME("Stub\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveIMMApp_EnumRegisterWordW(IActiveIMMApp* This, + HKL hKL, LPWSTR szReading, DWORD dwStyle, LPWSTR szRegister, + LPVOID pData, IEnumRegisterWordW **pEnum) +{ + FIXME("Stub\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveIMMApp_EscapeA(IActiveIMMApp* This, + HKL hKL, HIMC hIMC, UINT uEscape, LPVOID pData, LRESULT *plResult) +{ + *plResult = ImmEscapeA(hKL, hIMC, uEscape, pData); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_EscapeW(IActiveIMMApp* This, + HKL hKL, HIMC hIMC, UINT uEscape, LPVOID pData, LRESULT *plResult) +{ + *plResult = ImmEscapeW(hKL, hIMC, uEscape, pData); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetCandidateListA(IActiveIMMApp* This, + HIMC hIMC, DWORD dwIndex, UINT uBufLen, CANDIDATELIST *pCandList, + UINT *puCopied) +{ + *puCopied = ImmGetCandidateListA(hIMC, dwIndex, pCandList, uBufLen); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetCandidateListW(IActiveIMMApp* This, + HIMC hIMC, DWORD dwIndex, UINT uBufLen, CANDIDATELIST *pCandList, + UINT *puCopied) +{ + *puCopied = ImmGetCandidateListW(hIMC, dwIndex, pCandList, uBufLen); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetCandidateListCountA(IActiveIMMApp* This, + HIMC hIMC, DWORD *pdwListSize, DWORD *pdwBufLen) +{ + *pdwBufLen = ImmGetCandidateListCountA(hIMC, pdwListSize); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetCandidateListCountW(IActiveIMMApp* This, + HIMC hIMC, DWORD *pdwListSize, DWORD *pdwBufLen) +{ + *pdwBufLen = ImmGetCandidateListCountA(hIMC, pdwListSize); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetCandidateWindow(IActiveIMMApp* This, + HIMC hIMC, DWORD dwIndex, CANDIDATEFORM *pCandidate) +{ + BOOL rc; + rc = ImmGetCandidateWindow(hIMC,dwIndex,pCandidate); + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_GetCompositionFontA(IActiveIMMApp* This, + HIMC hIMC, LOGFONTA *plf) +{ + BOOL rc; + rc = ImmGetCompositionFontA(hIMC,plf); + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_GetCompositionFontW(IActiveIMMApp* This, + HIMC hIMC, LOGFONTW *plf) +{ + BOOL rc; + rc = ImmGetCompositionFontW(hIMC,plf); + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_GetCompositionStringA(IActiveIMMApp* This, + HIMC hIMC, DWORD dwIndex, DWORD dwBufLen, LONG *plCopied, LPVOID pBuf) +{ + *plCopied = ImmGetCompositionStringA(hIMC, dwIndex, pBuf, dwBufLen); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetCompositionStringW(IActiveIMMApp* This, + HIMC hIMC, DWORD dwIndex, DWORD dwBufLen, LONG *plCopied, LPVOID pBuf) +{ + *plCopied = ImmGetCompositionStringW(hIMC, dwIndex, pBuf, dwBufLen); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetCompositionWindow(IActiveIMMApp* This, + HIMC hIMC, COMPOSITIONFORM *pCompForm) +{ + BOOL rc; + + rc = ImmGetCompositionWindow(hIMC,pCompForm); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_GetContext(IActiveIMMApp* This, + HWND hwnd, HIMC *phIMC) +{ + *phIMC = ImmGetContext(hwnd); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetConversionListA(IActiveIMMApp* This, + HKL hKL, HIMC hIMC, LPSTR pSrc, UINT uBufLen, UINT uFlag, + CANDIDATELIST *pDst, UINT *puCopied) +{ + *puCopied = ImmGetConversionListA(hKL, hIMC, pSrc, pDst, uBufLen, uFlag); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetConversionListW(IActiveIMMApp* This, + HKL hKL, HIMC hIMC, LPWSTR pSrc, UINT uBufLen, UINT uFlag, + CANDIDATELIST *pDst, UINT *puCopied) +{ + *puCopied = ImmGetConversionListW(hKL, hIMC, pSrc, pDst, uBufLen, uFlag); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetConversionStatus(IActiveIMMApp* This, + HIMC hIMC, DWORD *pfdwConversion, DWORD *pfdwSentence) +{ + BOOL rc; + + rc = ImmGetConversionStatus(hIMC, pfdwConversion, pfdwSentence); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_GetDefaultIMEWnd(IActiveIMMApp* This, + HWND hWnd, HWND *phDefWnd) +{ + *phDefWnd = ImmGetDefaultIMEWnd(hWnd); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetDescriptionA(IActiveIMMApp* This, + HKL hKL, UINT uBufLen, LPSTR szDescription, UINT *puCopied) +{ + *puCopied = ImmGetDescriptionA(hKL, szDescription, uBufLen); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetDescriptionW(IActiveIMMApp* This, + HKL hKL, UINT uBufLen, LPWSTR szDescription, UINT *puCopied) +{ + *puCopied = ImmGetDescriptionW(hKL, szDescription, uBufLen); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetGuideLineA(IActiveIMMApp* This, + HIMC hIMC, DWORD dwIndex, DWORD dwBufLen, LPSTR pBuf, + DWORD *pdwResult) +{ + *pdwResult = ImmGetGuideLineA(hIMC, dwIndex, pBuf, dwBufLen); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetGuideLineW(IActiveIMMApp* This, + HIMC hIMC, DWORD dwIndex, DWORD dwBufLen, LPWSTR pBuf, + DWORD *pdwResult) +{ + *pdwResult = ImmGetGuideLineW(hIMC, dwIndex, pBuf, dwBufLen); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetIMEFileNameA(IActiveIMMApp* This, + HKL hKL, UINT uBufLen, LPSTR szFileName, UINT *puCopied) +{ + *puCopied = ImmGetIMEFileNameA(hKL, szFileName, uBufLen); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetIMEFileNameW(IActiveIMMApp* This, + HKL hKL, UINT uBufLen, LPWSTR szFileName, UINT *puCopied) +{ + *puCopied = ImmGetIMEFileNameW(hKL, szFileName, uBufLen); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetOpenStatus(IActiveIMMApp* This, + HIMC hIMC) +{ + return ImmGetOpenStatus(hIMC); +} + +static HRESULT WINAPI ActiveIMMApp_GetProperty(IActiveIMMApp* This, + HKL hKL, DWORD fdwIndex, DWORD *pdwProperty) +{ + *pdwProperty = ImmGetProperty(hKL, fdwIndex); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetRegisterWordStyleA(IActiveIMMApp* This, + HKL hKL, UINT nItem, STYLEBUFA *pStyleBuf, UINT *puCopied) +{ + *puCopied = ImmGetRegisterWordStyleA(hKL, nItem, pStyleBuf); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetRegisterWordStyleW(IActiveIMMApp* This, + HKL hKL, UINT nItem, STYLEBUFW *pStyleBuf, UINT *puCopied) +{ + *puCopied = ImmGetRegisterWordStyleW(hKL, nItem, pStyleBuf); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetStatusWindowPos(IActiveIMMApp* This, + HIMC hIMC, POINT *pptPos) +{ + BOOL rc; + rc = ImmGetStatusWindowPos(hIMC, pptPos); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_GetVirtualKey(IActiveIMMApp* This, + HWND hWnd, UINT *puVirtualKey) +{ + *puVirtualKey = ImmGetVirtualKey(hWnd); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_InstallIMEA(IActiveIMMApp* This, + LPSTR szIMEFileName, LPSTR szLayoutText, HKL *phKL) +{ + *phKL = ImmInstallIMEA(szIMEFileName,szLayoutText); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_InstallIMEW(IActiveIMMApp* This, + LPWSTR szIMEFileName, LPWSTR szLayoutText, HKL *phKL) +{ + *phKL = ImmInstallIMEW(szIMEFileName,szLayoutText); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_IsIME(IActiveIMMApp* This, + HKL hKL) +{ + return ImmIsIME(hKL); +} + +static HRESULT WINAPI ActiveIMMApp_IsUIMessageA(IActiveIMMApp* This, + HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam) +{ + return ImmIsUIMessageA(hWndIME,msg,wParam,lParam); +} + +static HRESULT WINAPI ActiveIMMApp_IsUIMessageW(IActiveIMMApp* This, + HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam) +{ + return ImmIsUIMessageW(hWndIME,msg,wParam,lParam); +} + +static HRESULT WINAPI ActiveIMMApp_NotifyIME(IActiveIMMApp* This, + HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue) +{ + BOOL rc; + + rc = ImmNotifyIME(hIMC,dwAction,dwIndex,dwValue); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_RegisterWordA(IActiveIMMApp* This, + HKL hKL, LPSTR szReading, DWORD dwStyle, LPSTR szRegister) +{ + BOOL rc; + + rc = ImmRegisterWordA(hKL,szReading,dwStyle,szRegister); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_RegisterWordW(IActiveIMMApp* This, + HKL hKL, LPWSTR szReading, DWORD dwStyle, LPWSTR szRegister) +{ + BOOL rc; + + rc = ImmRegisterWordW(hKL,szReading,dwStyle,szRegister); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_ReleaseContext(IActiveIMMApp* This, + HWND hWnd, HIMC hIMC) +{ + BOOL rc; + + rc = ImmReleaseContext(hWnd,hIMC); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_SetCandidateWindow(IActiveIMMApp* This, + HIMC hIMC, CANDIDATEFORM *pCandidate) +{ + BOOL rc; + + rc = ImmSetCandidateWindow(hIMC,pCandidate); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_SetCompositionFontA(IActiveIMMApp* This, + HIMC hIMC, LOGFONTA *plf) +{ + BOOL rc; + + rc = ImmSetCompositionFontA(hIMC,plf); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_SetCompositionFontW(IActiveIMMApp* This, + HIMC hIMC, LOGFONTW *plf) +{ + BOOL rc; + + rc = ImmSetCompositionFontW(hIMC,plf); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_SetCompositionStringA(IActiveIMMApp* This, + HIMC hIMC, DWORD dwIndex, LPVOID pComp, DWORD dwCompLen, + LPVOID pRead, DWORD dwReadLen) +{ + BOOL rc; + + rc = ImmSetCompositionStringA(hIMC,dwIndex,pComp,dwCompLen,pRead,dwReadLen); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_SetCompositionStringW(IActiveIMMApp* This, + HIMC hIMC, DWORD dwIndex, LPVOID pComp, DWORD dwCompLen, + LPVOID pRead, DWORD dwReadLen) +{ + BOOL rc; + + rc = ImmSetCompositionStringW(hIMC,dwIndex,pComp,dwCompLen,pRead,dwReadLen); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_SetCompositionWindow(IActiveIMMApp* This, + HIMC hIMC, COMPOSITIONFORM *pCompForm) +{ + BOOL rc; + + rc = ImmSetCompositionWindow(hIMC,pCompForm); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_SetConversionStatus(IActiveIMMApp* This, + HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence) +{ + BOOL rc; + + rc = ImmSetConversionStatus(hIMC,fdwConversion,fdwSentence); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_SetOpenStatus(IActiveIMMApp* This, + HIMC hIMC, BOOL fOpen) +{ + BOOL rc; + + rc = ImmSetOpenStatus(hIMC,fOpen); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_SetStatusWindowPos(IActiveIMMApp* This, + HIMC hIMC, POINT *pptPos) +{ + BOOL rc; + + rc = ImmSetStatusWindowPos(hIMC,pptPos); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_SimulateHotKey(IActiveIMMApp* This, + HWND hwnd, DWORD dwHotKeyID) +{ + BOOL rc; + + rc = ImmSimulateHotKey(hwnd,dwHotKeyID); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_UnregisterWordA(IActiveIMMApp* This, + HKL hKL, LPSTR szReading, DWORD dwStyle, LPSTR szUnregister) +{ + BOOL rc; + + rc = ImmUnregisterWordA(hKL,szReading,dwStyle,szUnregister); + + if (rc) + return S_OK; + else + return E_FAIL; + +} + +static HRESULT WINAPI ActiveIMMApp_UnregisterWordW(IActiveIMMApp* This, + HKL hKL, LPWSTR szReading, DWORD dwStyle, LPWSTR szUnregister) +{ + BOOL rc; + + rc = ImmUnregisterWordW(hKL,szReading,dwStyle,szUnregister); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_Activate(IActiveIMMApp* This, + BOOL fRestoreLayout) +{ + FIXME("Stub\n"); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_Deactivate(IActiveIMMApp* This) +{ + FIXME("Stub\n"); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_OnDefWindowProc(IActiveIMMApp* This, + HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *plResult) +{ + FIXME("Stub (%p %x %lx %lx)\n",hWnd,Msg,wParam,lParam); + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_FilterClientWindows(IActiveIMMApp* This, + ATOM *aaClassList, UINT uSize) +{ + FIXME("Stub\n"); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetCodePageA(IActiveIMMApp* This, + HKL hKL, UINT *uCodePage) +{ + FIXME("Stub\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveIMMApp_GetLangId(IActiveIMMApp* This, + HKL hKL, LANGID *plid) +{ + FIXME("Stub\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveIMMApp_AssociateContextEx(IActiveIMMApp* This, + HWND hWnd, HIMC hIMC, DWORD dwFlags) +{ + BOOL rc; + + rc = ImmAssociateContextEx(hWnd,hIMC,dwFlags); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_DisableIME(IActiveIMMApp* This, + DWORD idThread) +{ + BOOL rc; + + rc = ImmDisableIME(idThread); + + if (rc) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI ActiveIMMApp_GetImeMenuItemsA(IActiveIMMApp* This, + HIMC hIMC, DWORD dwFlags, DWORD dwType, + IMEMENUITEMINFOA *pImeParentMenu, IMEMENUITEMINFOA *pImeMenu, + DWORD dwSize, DWORD *pdwResult) +{ + *pdwResult = ImmGetImeMenuItemsA(hIMC,dwFlags,dwType,pImeParentMenu,pImeMenu,dwSize); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_GetImeMenuItemsW(IActiveIMMApp* This, + HIMC hIMC, DWORD dwFlags, DWORD dwType, + IMEMENUITEMINFOW *pImeParentMenu, IMEMENUITEMINFOW *pImeMenu, + DWORD dwSize, DWORD *pdwResult) +{ + *pdwResult = ImmGetImeMenuItemsW(hIMC,dwFlags,dwType,pImeParentMenu,pImeMenu,dwSize); + return S_OK; +} + +static HRESULT WINAPI ActiveIMMApp_EnumInputContext(IActiveIMMApp* This, + DWORD idThread, IEnumInputContext **ppEnum) +{ + FIXME("Stub\n"); + return E_NOTIMPL; +} + +static const IActiveIMMAppVtbl ActiveIMMAppVtbl = +{ + ActiveIMMApp_QueryInterface, + ActiveIMMApp_AddRef, + ActiveIMMApp_Release, + + ActiveIMMApp_AssociateContext, + ActiveIMMApp_ConfigureIMEA, + ActiveIMMApp_ConfigureIMEW, + ActiveIMMApp_CreateContext, + ActiveIMMApp_DestroyContext, + ActiveIMMApp_EnumRegisterWordA, + ActiveIMMApp_EnumRegisterWordW, + ActiveIMMApp_EscapeA, + ActiveIMMApp_EscapeW, + ActiveIMMApp_GetCandidateListA, + ActiveIMMApp_GetCandidateListW, + ActiveIMMApp_GetCandidateListCountA, + ActiveIMMApp_GetCandidateListCountW, + ActiveIMMApp_GetCandidateWindow, + ActiveIMMApp_GetCompositionFontA, + ActiveIMMApp_GetCompositionFontW, + ActiveIMMApp_GetCompositionStringA, + ActiveIMMApp_GetCompositionStringW, + ActiveIMMApp_GetCompositionWindow, + ActiveIMMApp_GetContext, + ActiveIMMApp_GetConversionListA, + ActiveIMMApp_GetConversionListW, + ActiveIMMApp_GetConversionStatus, + ActiveIMMApp_GetDefaultIMEWnd, + ActiveIMMApp_GetDescriptionA, + ActiveIMMApp_GetDescriptionW, + ActiveIMMApp_GetGuideLineA, + ActiveIMMApp_GetGuideLineW, + ActiveIMMApp_GetIMEFileNameA, + ActiveIMMApp_GetIMEFileNameW, + ActiveIMMApp_GetOpenStatus, + ActiveIMMApp_GetProperty, + ActiveIMMApp_GetRegisterWordStyleA, + ActiveIMMApp_GetRegisterWordStyleW, + ActiveIMMApp_GetStatusWindowPos, + ActiveIMMApp_GetVirtualKey, + ActiveIMMApp_InstallIMEA, + ActiveIMMApp_InstallIMEW, + ActiveIMMApp_IsIME, + ActiveIMMApp_IsUIMessageA, + ActiveIMMApp_IsUIMessageW, + ActiveIMMApp_NotifyIME, + ActiveIMMApp_RegisterWordA, + ActiveIMMApp_RegisterWordW, + ActiveIMMApp_ReleaseContext, + ActiveIMMApp_SetCandidateWindow, + ActiveIMMApp_SetCompositionFontA, + ActiveIMMApp_SetCompositionFontW, + ActiveIMMApp_SetCompositionStringA, + ActiveIMMApp_SetCompositionStringW, + ActiveIMMApp_SetCompositionWindow, + ActiveIMMApp_SetConversionStatus, + ActiveIMMApp_SetOpenStatus, + ActiveIMMApp_SetStatusWindowPos, + ActiveIMMApp_SimulateHotKey, + ActiveIMMApp_UnregisterWordA, + ActiveIMMApp_UnregisterWordW, + + ActiveIMMApp_Activate, + ActiveIMMApp_Deactivate, + ActiveIMMApp_OnDefWindowProc, + ActiveIMMApp_FilterClientWindows, + ActiveIMMApp_GetCodePageA, + ActiveIMMApp_GetLangId, + ActiveIMMApp_AssociateContextEx, + ActiveIMMApp_DisableIME, + ActiveIMMApp_GetImeMenuItemsA, + ActiveIMMApp_GetImeMenuItemsW, + ActiveIMMApp_EnumInputContext +}; + +HRESULT ActiveIMMApp_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) +{ + ActiveIMMApp *This; + if (pUnkOuter) + return CLASS_E_NOAGGREGATION; + + This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ActiveIMMApp)); + if (This == NULL) + return E_OUTOFMEMORY; + + This->vtbl = &ActiveIMMAppVtbl; + This->refCount = 1; + + TRACE("returning %p\n",This); + *ppOut = (IUnknown *)This; + return S_OK; +} diff --git a/reactos/dll/win32/msimtf/main.c b/reactos/dll/win32/msimtf/main.c new file mode 100644 index 00000000000..8e24a4c4837 --- /dev/null +++ b/reactos/dll/win32/msimtf/main.c @@ -0,0 +1,219 @@ +/* + * Copyright 2007 Jacek Caban for CodeWeavers + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winreg.h" +#include "advpub.h" +#include "ole2.h" +#include "dimm.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msimtf); + +extern HRESULT ActiveIMMApp_Constructor(IUnknown *punkOuter, IUnknown **ppOut); + +static HINSTANCE msimtf_instance; + +/****************************************************************** + * DllMain (msimtf.@) + */ +BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) +{ + switch(fdwReason) + { + case DLL_WINE_PREATTACH: + return FALSE; /* prefer native version */ + case DLL_PROCESS_ATTACH: + msimtf_instance = hInstDLL; + DisableThreadLibraryCalls(hInstDLL); + break; + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + +typedef struct { + const IClassFactoryVtbl *lpClassFactoryVtbl; + + HRESULT (*cf)(IUnknown*,IUnknown**); +} ClassFactory; + +static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, + REFIID riid, void **ppv) +{ + *ppv = NULL; + + if(IsEqualGUID(&IID_IUnknown, riid)) { + TRACE("(IID_IUnknown %p)\n", ppv); + *ppv = iface; + }else if(IsEqualGUID(&IID_IClassFactory, riid)) { + TRACE("IID_IClassFactory %p)\n", ppv); + *ppv = iface; + } + + if(*ppv) { + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; + } + + FIXME("(%s %p)\n", debugstr_guid(riid), ppv); + return E_NOINTERFACE; +} + +static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface) +{ + return 2; +} + +static ULONG WINAPI ClassFactory_Release(IClassFactory *iface) +{ + return 1; +} + +static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, + IUnknown *pOuter, REFIID riid, void **ppv) +{ + ClassFactory *This = (ClassFactory*)iface; + HRESULT ret; + IUnknown *obj; + TRACE("(%p, %p, %s, %p)\n", iface, pOuter, debugstr_guid(riid), ppv); + + ret = This->cf(pOuter, &obj); + if (FAILED(ret)) + return ret; + + ret = IUnknown_QueryInterface(obj,riid,ppv); + IUnknown_Release(obj); + return ret; +} + +static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock) +{ + FIXME("(%d)\n", dolock); + return S_OK; +} + +static const IClassFactoryVtbl ClassFactoryVtbl = { + ClassFactory_QueryInterface, + ClassFactory_AddRef, + ClassFactory_Release, + ClassFactory_CreateInstance, + ClassFactory_LockServer +}; + +/****************************************************************** + * DllGetClassObject (msimtf.@) + */ +HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) +{ + if(IsEqualGUID(&CLSID_CActiveIMM, rclsid)) { + static ClassFactory cf = { + &ClassFactoryVtbl, + ActiveIMMApp_Constructor, + }; + + return IClassFactory_QueryInterface((IClassFactory*)&cf, riid, ppv); + } + + FIXME("(%s %s %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); + return CLASS_E_CLASSNOTAVAILABLE; +} + +/****************************************************************** + * DllCanUnloadNow (msimtf.@) + */ +HRESULT WINAPI DllCanUnloadNow(void) +{ + FIXME("()\n"); + return S_FALSE; +} + +#define INF_SET_CLSID(clsid) \ + do \ + { \ + static CHAR name[] = "CLSID_" #clsid; \ + \ + pse[i].pszName = name; \ + clsids[i++] = &CLSID_ ## clsid; \ + } while (0) + +static HRESULT register_server(BOOL doregister) +{ + HRESULT hres; + HMODULE hAdvpack; + HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable); + STRTABLEA strtable; + STRENTRYA pse[1]; + static CLSID const *clsids[34]; + unsigned int i = 0; + + static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0}; + + INF_SET_CLSID(CActiveIMM); + + for(i = 0; i < sizeof(pse)/sizeof(pse[0]); i++) { + pse[i].pszValue = HeapAlloc(GetProcessHeap(), 0, 39); + sprintf(pse[i].pszValue, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + clsids[i]->Data1, clsids[i]->Data2, clsids[i]->Data3, clsids[i]->Data4[0], + clsids[i]->Data4[1], clsids[i]->Data4[2], clsids[i]->Data4[3], clsids[i]->Data4[4], + clsids[i]->Data4[5], clsids[i]->Data4[6], clsids[i]->Data4[7]); + } + + strtable.cEntries = sizeof(pse)/sizeof(pse[0]); + strtable.pse = pse; + + hAdvpack = LoadLibraryW(wszAdvpack); + pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall"); + + hres = pRegInstall(msimtf_instance, doregister ? "RegisterDll" : "UnregisterDll", &strtable); + + for(i=0; i < sizeof(pse)/sizeof(pse[0]); i++) + HeapFree(GetProcessHeap(), 0, pse[i].pszValue); + + return hres; +} + +#undef INF_SET_CLSID + +/*********************************************************************** + * DllRegisterServer (msimtf.@) + */ +HRESULT WINAPI DllRegisterServer(void) +{ + return register_server(TRUE); +} + +/*********************************************************************** + * DllUnregisterServer (msimtf.@) + */ +HRESULT WINAPI DllUnregisterServer(void) +{ + return register_server(FALSE); +} diff --git a/reactos/dll/win32/msimtf/msimtf.inf b/reactos/dll/win32/msimtf/msimtf.inf new file mode 100644 index 00000000000..2bc57852495 --- /dev/null +++ b/reactos/dll/win32/msimtf/msimtf.inf @@ -0,0 +1,26 @@ +[version] +Signature="$CHICAGO$" + + +[RegisterDll] +AddReg=Classes.Reg + + +[UnregisterDll] +DelReg=Classes.Reg + + +[Classes.Reg] +HKCR,"CLSID\%CLSID_CActiveIMM%",,,"CActiveIMMApp" +HKCR,"CLSID\%CLSID_CActiveIMM%\InProcServer32",,,"msimtf.dll" +HKCR,"CLSID\%CLSID_CActiveIMM%\InProcServer32","ThreadingModel",,"Apartment" +HKCR,"CLSID\%CLSID_CActiveIMMAppEx_Trident%",,,"CActiveIMMAppEx_Trident" +HKCR,"CLSID\%CLSID_CActiveIMMAppEx_Trident%\InProcServer32",,,"msimtf.dll" +HKCR,"CLSID\%CLSID_CActiveIMMAppEx_Trident%\InProcServer32","ThreadingModel",,"Apartment" +HKCR,"CLSID\%CLSID_CActiveIMMAppEx%",,,"CActiveIMMAppEx" +HKCR,"CLSID\%CLSID_CActiveIMMAppEx%\InProcServer32",,,"msimtf.dll" +HKCR,"CLSID\%CLSID_CActiveIMMAppEx%\InProcServer32","ThreadingModel",,"Apartment" + +[Strings] +CLSID_CActiveIMMAppEx_Trident={50D5107A-D278-4871-8989-F4CEAAF59CFC} +CLSID_CActiveIMMAppEx="{C1EE01F2-B3B6-4A6A-9DDD-E988C088EC82}" diff --git a/reactos/dll/win32/msimtf/msimtf.rbuild b/reactos/dll/win32/msimtf/msimtf.rbuild new file mode 100644 index 00000000000..6c8272a80cc --- /dev/null +++ b/reactos/dll/win32/msimtf/msimtf.rbuild @@ -0,0 +1,17 @@ + + + + + . + include/reactos/wine + + activeimmapp.c + main.c + rsrc.rc + wine + uuid + imm32 + kernel32 + ntdll + + \ No newline at end of file diff --git a/reactos/dll/win32/msimtf/msimtf.spec b/reactos/dll/win32/msimtf/msimtf.spec new file mode 100644 index 00000000000..ea3b7de6c89 --- /dev/null +++ b/reactos/dll/win32/msimtf/msimtf.spec @@ -0,0 +1,6 @@ +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetClassObject(ptr ptr ptr) +@ stdcall -private DllRegisterServer() +@ stdcall -private DllUnregisterServer() +@ stub MsimtfIsGuidMapEnable +@ stub MsimtfIsWindowFiltered diff --git a/reactos/dll/win32/msimtf/rsrc.rc b/reactos/dll/win32/msimtf/rsrc.rc new file mode 100644 index 00000000000..361feee27cc --- /dev/null +++ b/reactos/dll/win32/msimtf/rsrc.rc @@ -0,0 +1,20 @@ +/* + * Copyright 2007 Jacek Caban for CodeWeavers + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* @makedep: msimtf.inf */ +REGINST REGINST msimtf.inf diff --git a/reactos/dll/win32/win32.rbuild b/reactos/dll/win32/win32.rbuild index a46576f2135..493bea6b68d 100644 --- a/reactos/dll/win32/win32.rbuild +++ b/reactos/dll/win32/win32.rbuild @@ -133,6 +133,9 @@ + + + @@ -193,6 +196,9 @@ + + + diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 681ddf8986e..b40ae1b9181 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -56,6 +56,8 @@ reactos/dll/win32/imagehlp # Patches for BindImage need review and submis reactos/dll/win32/inetcomm # Autosync reactos/dll/win32/inetmib1 # Autosync reactos/dll/win32/iphlpapi # Out of sync +reactos/dll/win32/itss # Autosync +reactos/dll/win32/jscript # Autosync reactos/dll/win32/localui # Autosync reactos/dll/win32/lz32 # Autosync reactos/dll/win32/mapi32 # Autosync @@ -66,6 +68,7 @@ reactos/dll/win32/mscoree # Autosync reactos/dll/win32/mshtml # Autosync reactos/dll/win32/msimg32 # Autosync reactos/dll/win32/msi # Autosync +reactos/dll/win32/msimtf # Autosync reactos/dll/win32/mstask # Autosync reactos/dll/win32/msvcrt20 # Autosync reactos/dll/win32/msvfw32 # Autosync