Authors: Stewart Caie<kyz@uklinux.net>, Jed Wing <jedwin@ugcs.caltech.edu>, Mike McCormack <mike@codeweavers.com>

Added an implemenation of ITSS.DLL.
oldstable
Alexandre Julliard 2004-08-24 21:00:15 +00:00
parent 47c94c0e4d
commit 5f6e3c88bd
15 changed files with 4779 additions and 1 deletions

3
configure vendored

File diff suppressed because one or more lines are too long

View File

@ -1576,6 +1576,7 @@ dlls/imagehlp/Makefile
dlls/imm32/Makefile
dlls/iphlpapi/Makefile
dlls/iphlpapi/tests/Makefile
dlls/itss/Makefile
dlls/kernel/Makefile
dlls/kernel/tests/Makefile
dlls/lzexpand/Makefile

View File

@ -63,6 +63,7 @@ BASEDIRS = \
imagehlp \
imm32 \
iphlpapi \
itss \
kernel \
lzexpand \
mapi32 \
@ -287,6 +288,7 @@ SYMLINKS_SO = \
imagehlp.dll.so \
imm32.dll.so \
iphlpapi.dll.so \
itss.dll.so \
joystick.drv.so \
kernel32.dll.so \
libdxerr8.a \
@ -578,6 +580,9 @@ imm.dll.so : imm32.dll.so
iphlpapi.dll.so: iphlpapi/iphlpapi.dll.so
$(RM) $@ && $(LN_S) iphlpapi/iphlpapi.dll.so $@
itss.dll.so: itss/itss.dll.so
$(RM) $@ && $(LN_S) itss/itss.dll.so $@
joystick.drv.so: winmm/joystick/joystick.drv.so
$(RM) $@ && $(LN_S) winmm/joystick/joystick.drv.so $@
@ -1013,6 +1018,7 @@ IMPORT_LIBS = \
libimagehlp.$(IMPLIBEXT) \
libimm32.$(IMPLIBEXT) \
libiphlpapi.$(IMPLIBEXT) \
libitss.$(IMPLIBEXT) \
libkernel32.$(IMPLIBEXT) \
liblz32.$(IMPLIBEXT) \
libmapi32.$(IMPLIBEXT) \
@ -1348,6 +1354,11 @@ libiphlpapi.def: iphlpapi/iphlpapi.spec.def
libiphlpapi.a: iphlpapi/iphlpapi.spec.def
$(DLLTOOL) -k -l $@ -d iphlpapi/iphlpapi.spec.def
libitss.def: itss/itss.spec.def
$(RM) $@ && $(LN_S) itss/itss.spec.def $@
libitss.a: itss/itss.spec.def
$(DLLTOOL) -k -l $@ -d itss/itss.spec.def
libkernel32.def: kernel/kernel32.spec.def
$(RM) $@ && $(LN_S) kernel/kernel32.spec.def $@
libkernel32.a: kernel/kernel32.spec.def
@ -1759,6 +1770,7 @@ icmp/icmp.spec.def: $(WINEBUILD)
imagehlp/imagehlp.spec.def: $(WINEBUILD)
imm32/imm32.spec.def: $(WINEBUILD)
iphlpapi/iphlpapi.spec.def: $(WINEBUILD)
itss/itss.spec.def: $(WINEBUILD)
kernel/kernel32.spec.def: $(WINEBUILD)
lzexpand/lz32.spec.def: $(WINEBUILD)
mapi32/mapi32.spec.def: $(WINEBUILD)
@ -1891,6 +1903,7 @@ msacm/imaadp32/imaadp32.acm.so: msacm/imaadp32
imagehlp/imagehlp.dll.so: imagehlp
imm32/imm32.dll.so: imm32
iphlpapi/iphlpapi.dll.so: iphlpapi
itss/itss.dll.so: itss
winmm/joystick/joystick.drv.so: winmm/joystick
kernel/kernel32.dll.so: kernel
lzexpand/lz32.dll.so: lzexpand

View File

@ -0,0 +1,3 @@
Makefile
itss.dll.dbg.c
itss.spec.def

View File

@ -0,0 +1,29 @@
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = itss.dll
IMPORTS = ole32 user32 advapi32 kernel32 ntdll
EXTRALIBS = $(LIBUNICODE) -luuid
EXTRADEFS = -DCOM_NO_WINDOWS_H
C_SRCS = \
chm_lib.c \
lzx.c \
itss.c \
moniker.c \
storage.c
IDL_SRCS = \
itss.idl
@MAKE_DLL_RULES@
.SUFFIXES: .idl .h
.idl.h:
$(WIDL) $(IDLFLAGS) -b -h -H $@ $<
idl: $(IDL_SRCS:.idl=.h)
### Dependencies:

1670
dlls/itss/chm_lib.c 100644

File diff suppressed because it is too large Load Diff

116
dlls/itss/chm_lib.h 100644
View File

@ -0,0 +1,116 @@
/* $Id$ */
/***************************************************************************
* chm_lib.h - CHM archive manipulation routines *
* ------------------- *
* *
* author: Jed Wing <jedwin@ugcs.caltech.edu> *
* 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. *
* *
***************************************************************************/
#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);
/* methods for ssetting tuning parameters for particular file */
#define CHM_PARAM_MAX_BLOCKS_CACHED 0
void chm_set_param(struct chmFile *h,
int paramType,
int paramVal);
/* 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);
#endif /* INCLUDED_CHMLIB_H */

409
dlls/itss/itss.c 100644
View File

@ -0,0 +1,409 @@
/*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdarg.h>
#include <stdio.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "winnls.h"
#include "winreg.h"
#include "ole2.h"
#include "itss.h"
#include "uuids.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(itss);
#include "initguid.h"
DEFINE_GUID(CLSID_ITStorage,0x5d02926a,0x212e,0x11d0,0x9d,0xf9,0x00,0xa0,0xc9,0x22,0xe6,0xec );
DEFINE_GUID(CLSID_ITSProtocol,0x9d148290,0xb9c8,0x11d0,0xa4,0xcc,0x00,0x00,0xf8,0x01,0x49,0xf6);
DEFINE_GUID(IID_IITStorage, 0x88cc31de, 0x27ab, 0x11d0, 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
static HRESULT ITSS_create(IUnknown *pUnkOuter, LPVOID *ppObj);
extern HRESULT ITS_IParseDisplayName_create(IUnknown *pUnkOuter, LPVOID *ppObj);
extern HRESULT ITSS_StgOpenStorage( const WCHAR*, IStorage*, DWORD, SNB, DWORD, IStorage** );
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
{
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hInstDLL);
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
/******************************************************************************
* ITSS ClassFactory
*/
typedef struct {
IClassFactory ITF_IClassFactory;
DWORD ref;
HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
} IClassFactoryImpl;
struct object_creation_info
{
const CLSID *clsid;
LPCSTR szClassName;
HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
};
static const struct object_creation_info object_creation[] =
{
{ &CLSID_ITStorage, "ITStorage", ITSS_create },
{ &CLSID_ITSProtocol, "ITSProtocol", ITS_IParseDisplayName_create },
};
static HRESULT WINAPI
ITSSCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
{
ICOM_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) {
ICOM_THIS(IClassFactoryImpl,iface);
return ++(This->ref);
}
static ULONG WINAPI ITSSCF_Release(LPCLASSFACTORY iface) {
ICOM_THIS(IClassFactoryImpl,iface);
ULONG ref = --This->ref;
if (ref == 0)
HeapFree(GetProcessHeap(), 0, This);
return ref;
}
static HRESULT WINAPI ITSSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter,
REFIID riid, LPVOID *ppobj) {
ICOM_THIS(IClassFactoryImpl,iface);
HRESULT hres;
LPUNKNOWN punk;
TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
if (FAILED(hres)) {
*ppobj = NULL;
return hres;
}
hres = IUnknown_QueryInterface(punk, riid, ppobj);
if (FAILED(hres)) {
*ppobj = NULL;
return hres;
}
IUnknown_Release(punk);
return hres;
}
static HRESULT WINAPI ITSSCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
ICOM_THIS(IClassFactoryImpl,iface);
FIXME("(%p)->(%d),stub!\n",This,dolock);
return S_OK;
}
static IClassFactoryVtbl ITSSCF_Vtbl =
{
ITSSCF_QueryInterface,
ITSSCF_AddRef,
ITSSCF_Release,
ITSSCF_CreateInstance,
ITSSCF_LockServer
};
HRESULT WINAPI ITSS_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
{
int i;
IClassFactoryImpl *factory;
TRACE("%s %s %p\n",debugstr_guid(rclsid), debugstr_guid(iid), ppv);
if ( !IsEqualGUID( &IID_IClassFactory, iid )
&& ! IsEqualGUID( &IID_IUnknown, iid) )
return E_NOINTERFACE;
for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
{
if (IsEqualGUID(object_creation[i].clsid, rclsid))
break;
}
if (i == sizeof(object_creation)/sizeof(object_creation[0]))
{
FIXME("%s: no class found.\n", debugstr_guid(rclsid));
return CLASS_E_CLASSNOTAVAILABLE;
}
TRACE("Creating a class factory for %s\n",object_creation[i].szClassName);
factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
if (factory == NULL) return E_OUTOFMEMORY;
factory->ITF_IClassFactory.lpVtbl = &ITSSCF_Vtbl;
factory->ref = 1;
factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
*ppv = &(factory->ITF_IClassFactory);
TRACE("(%p) <- %p\n", ppv, &(factory->ITF_IClassFactory) );
return S_OK;
}
/*****************************************************************************/
typedef struct {
IITStorageVtbl *vtbl_IITStorage;
DWORD ref;
} ITStorageImpl;
HRESULT WINAPI ITStorageImpl_QueryInterface(
IITStorage* iface,
REFIID riid,
void** ppvObject)
{
ICOM_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;
}
ULONG WINAPI ITStorageImpl_AddRef(
IITStorage* iface)
{
ICOM_THIS(ITStorageImpl,iface);
TRACE("%p\n", This);
return ++(This->ref);
}
ULONG WINAPI ITStorageImpl_Release(
IITStorage* iface)
{
ICOM_THIS(ITStorageImpl,iface);
ULONG ref = --This->ref;
if (ref == 0)
HeapFree(GetProcessHeap(), 0, This);
return ref;
}
HRESULT WINAPI ITStorageImpl_StgCreateDocfile(
IITStorage* iface,
const WCHAR* pwcsName,
DWORD grfMode,
DWORD reserved,
IStorage** ppstgOpen)
{
ICOM_THIS(ITStorageImpl,iface);
TRACE("%p %s %lu %lu %p\n", This,
debugstr_w(pwcsName), grfMode, reserved, ppstgOpen );
return ITSS_StgOpenStorage( pwcsName, NULL, grfMode,
0, reserved, ppstgOpen);
}
HRESULT WINAPI ITStorageImpl_StgCreateDocfileOnILockBytes(
IITStorage* iface,
ILockBytes* plkbyt,
DWORD grfMode,
DWORD reserved,
IStorage** ppstgOpen)
{
ICOM_THIS(ITStorageImpl,iface);
FIXME("%p\n", This);
return E_NOTIMPL;
}
HRESULT WINAPI ITStorageImpl_StgIsStorageFile(
IITStorage* iface,
const WCHAR* pwcsName)
{
ICOM_THIS(ITStorageImpl,iface);
FIXME("%p\n", This);
return E_NOTIMPL;
}
HRESULT WINAPI ITStorageImpl_StgIsStorageILockBytes(
IITStorage* iface,
ILockBytes* plkbyt)
{
ICOM_THIS(ITStorageImpl,iface);
FIXME("%p\n", This);
return E_NOTIMPL;
}
HRESULT WINAPI ITStorageImpl_StgOpenStorage(
IITStorage* iface,
const WCHAR* pwcsName,
IStorage* pstgPriority,
DWORD grfMode,
SNB snbExclude,
DWORD reserved,
IStorage** ppstgOpen)
{
ICOM_THIS(ITStorageImpl,iface);
TRACE("%p %s %p %ld %p\n", This, debugstr_w( pwcsName ),
pstgPriority, grfMode, snbExclude );
return ITSS_StgOpenStorage( pwcsName, pstgPriority, grfMode,
snbExclude, reserved, ppstgOpen);
}
HRESULT WINAPI ITStorageImpl_StgOpenStorageOnILockBytes(
IITStorage* iface,
ILockBytes* plkbyt,
IStorage* pStgPriority,
DWORD grfMode,
SNB snbExclude,
DWORD reserved,
IStorage** ppstgOpen)
{
ICOM_THIS(ITStorageImpl,iface);
FIXME("%p\n", This);
return E_NOTIMPL;
}
HRESULT WINAPI ITStorageImpl_StgSetTimes(
IITStorage* iface,
WCHAR* lpszName,
FILETIME* pctime,
FILETIME* patime,
FILETIME* pmtime)
{
ICOM_THIS(ITStorageImpl,iface);
FIXME("%p\n", This);
return E_NOTIMPL;
}
HRESULT WINAPI ITStorageImpl_SetControlData(
IITStorage* iface,
PITS_Control_Data pControlData)
{
ICOM_THIS(ITStorageImpl,iface);
FIXME("%p\n", This);
return E_NOTIMPL;
}
HRESULT WINAPI ITStorageImpl_DefaultControlData(
IITStorage* iface,
PITS_Control_Data* ppControlData)
{
ICOM_THIS(ITStorageImpl,iface);
FIXME("%p\n", This);
return E_NOTIMPL;
}
HRESULT WINAPI ITStorageImpl_Compact(
IITStorage* iface,
const WCHAR* pwcsName,
ECompactionLev iLev)
{
ICOM_THIS(ITStorageImpl,iface);
FIXME("%p\n", This);
return E_NOTIMPL;
}
static 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;
its = HeapAlloc( GetProcessHeap(), 0, sizeof(ITStorageImpl) );
its->vtbl_IITStorage = &ITStorageImpl_Vtbl;
its->ref = 1;
TRACE("-> %p\n", its);
*ppObj = (LPVOID) its;
return S_OK;
}
/*****************************************************************************/
HRESULT WINAPI ITSS_DllRegisterServer(void)
{
FIXME("\n");
return S_OK;
}
BOOL WINAPI ITSS_DllCanUnloadNow(void)
{
FIXME("\n");
return FALSE;
}

315
dlls/itss/itss.h 100644
View File

@ -0,0 +1,315 @@
/*** Autogenerated by WIDL 0.1 from itss.idl - Do not edit ***/
#include <rpc.h>
#include <rpcndr.h>
#ifndef __WIDL_ITSS_H
#define __WIDL_ITSS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <oaidl.h>
typedef struct _ITS_Control_Data {
UINT cdwControlData;
UINT adwControlData[1];
} ITS_Control_Data, *PITS_Control_Data;
typedef enum ECompactionLev {
COMPACT_DATA = 0,
COMPACT_DATA_AND_PATH
} ECompactionLev;
#ifndef __IITStorage_FWD_DEFINED__
#define __IITStorage_FWD_DEFINED__
typedef struct IITStorage IITStorage;
#endif
/*****************************************************************************
* IITStorage interface
*/
#ifndef __IITStorage_INTERFACE_DEFINED__
#define __IITStorage_INTERFACE_DEFINED__
#if defined(__cplusplus) && !defined(CINTERFACE)
struct IITStorage : public IUnknown
{
virtual HRESULT STDMETHODCALLTYPE StgCreateDocfile(
const WCHAR* pwcsName,
DWORD grfMode,
DWORD reserved,
IStorage** ppstgOpen) = 0;
virtual HRESULT STDMETHODCALLTYPE StgCreateDocfileOnILockBytes(
ILockBytes* plkbyt,
DWORD grfMode,
DWORD reserved,
IStorage** ppstgOpen) = 0;
virtual HRESULT STDMETHODCALLTYPE StgIsStorageFile(
const WCHAR* pwcsName) = 0;
virtual HRESULT STDMETHODCALLTYPE StgIsStorageILockBytes(
ILockBytes* plkbyt) = 0;
virtual HRESULT STDMETHODCALLTYPE StgOpenStorage(
const WCHAR* pwcsName,
IStorage* pstgPriority,
DWORD grfMode,
SNB snbExclude,
DWORD reserved,
IStorage** ppstgOpen) = 0;
virtual HRESULT STDMETHODCALLTYPE StgOpenStorageOnILockBytes(
ILockBytes* plkbyt,
IStorage* pStgPriority,
DWORD grfMode,
SNB snbExclude,
DWORD reserved,
IStorage** ppstgOpen) = 0;
virtual HRESULT STDMETHODCALLTYPE StgSetTimes(
WCHAR* lpszName,
FILETIME* pctime,
FILETIME* patime,
FILETIME* pmtime) = 0;
virtual HRESULT STDMETHODCALLTYPE SetControlData(
PITS_Control_Data pControlData) = 0;
virtual HRESULT STDMETHODCALLTYPE DefaultControlData(
PITS_Control_Data* ppControlData) = 0;
virtual HRESULT STDMETHODCALLTYPE Compact(
const WCHAR* pwcsName,
ECompactionLev iLev) = 0;
};
#else
typedef struct IITStorageVtbl IITStorageVtbl;
struct IITStorage {
const IITStorageVtbl* lpVtbl;
};
struct IITStorageVtbl {
BEGIN_INTERFACE
/*** IUnknown methods ***/
HRESULT (STDMETHODCALLTYPE *QueryInterface)(
IITStorage* This,
REFIID riid,
void** ppvObject);
ULONG (STDMETHODCALLTYPE *AddRef)(
IITStorage* This);
ULONG (STDMETHODCALLTYPE *Release)(
IITStorage* This);
/*** IITStorage methods ***/
HRESULT (STDMETHODCALLTYPE *StgCreateDocfile)(
IITStorage* This,
const WCHAR* pwcsName,
DWORD grfMode,
DWORD reserved,
IStorage** ppstgOpen);
HRESULT (STDMETHODCALLTYPE *StgCreateDocfileOnILockBytes)(
IITStorage* This,
ILockBytes* plkbyt,
DWORD grfMode,
DWORD reserved,
IStorage** ppstgOpen);
HRESULT (STDMETHODCALLTYPE *StgIsStorageFile)(
IITStorage* This,
const WCHAR* pwcsName);
HRESULT (STDMETHODCALLTYPE *StgIsStorageILockBytes)(
IITStorage* This,
ILockBytes* plkbyt);
HRESULT (STDMETHODCALLTYPE *StgOpenStorage)(
IITStorage* This,
const WCHAR* pwcsName,
IStorage* pstgPriority,
DWORD grfMode,
SNB snbExclude,
DWORD reserved,
IStorage** ppstgOpen);
HRESULT (STDMETHODCALLTYPE *StgOpenStorageOnILockBytes)(
IITStorage* This,
ILockBytes* plkbyt,
IStorage* pStgPriority,
DWORD grfMode,
SNB snbExclude,
DWORD reserved,
IStorage** ppstgOpen);
HRESULT (STDMETHODCALLTYPE *StgSetTimes)(
IITStorage* This,
WCHAR* lpszName,
FILETIME* pctime,
FILETIME* patime,
FILETIME* pmtime);
HRESULT (STDMETHODCALLTYPE *SetControlData)(
IITStorage* This,
PITS_Control_Data pControlData);
HRESULT (STDMETHODCALLTYPE *DefaultControlData)(
IITStorage* This,
PITS_Control_Data* ppControlData);
HRESULT (STDMETHODCALLTYPE *Compact)(
IITStorage* This,
const WCHAR* pwcsName,
ECompactionLev iLev);
END_INTERFACE
};
#ifdef COBJMACROS
/*** IUnknown methods ***/
#define IITStorage_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
#define IITStorage_AddRef(p) (p)->lpVtbl->AddRef(p)
#define IITStorage_Release(p) (p)->lpVtbl->Release(p)
/*** IITStorage methods ***/
#define IITStorage_StgCreateDocfile(p,a,b,c,d) (p)->lpVtbl->StgCreateDocfile(p,a,b,c,d)
#define IITStorage_StgCreateDocfileOnILockBytes(p,a,b,c,d) (p)->lpVtbl->StgCreateDocfileOnILockBytes(p,a,b,c,d)
#define IITStorage_StgIsStorageFile(p,a) (p)->lpVtbl->StgIsStorageFile(p,a)
#define IITStorage_StgIsStorageILockBytes(p,a) (p)->lpVtbl->StgIsStorageILockBytes(p,a)
#define IITStorage_StgOpenStorage(p,a,b,c,d,e,f) (p)->lpVtbl->StgOpenStorage(p,a,b,c,d,e,f)
#define IITStorage_StgOpenStorageOnILockBytes(p,a,b,c,d,e,f) (p)->lpVtbl->StgOpenStorageOnILockBytes(p,a,b,c,d,e,f)
#define IITStorage_StgSetTimes(p,a,b,c,d) (p)->lpVtbl->StgSetTimes(p,a,b,c,d)
#define IITStorage_SetControlData(p,a) (p)->lpVtbl->SetControlData(p,a)
#define IITStorage_DefaultControlData(p,a) (p)->lpVtbl->DefaultControlData(p,a)
#define IITStorage_Compact(p,a,b) (p)->lpVtbl->Compact(p,a,b)
#endif
#endif
#define IITStorage_METHODS \
/*** IUnknown methods ***/ \
STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; \
STDMETHOD_(ULONG,AddRef)(THIS) PURE; \
STDMETHOD_(ULONG,Release)(THIS) PURE; \
/*** IITStorage methods ***/ \
STDMETHOD_(HRESULT,StgCreateDocfile)(THIS_ const WCHAR* pwcsName, DWORD grfMode, DWORD reserved, IStorage** ppstgOpen) PURE; \
STDMETHOD_(HRESULT,StgCreateDocfileOnILockBytes)(THIS_ ILockBytes* plkbyt, DWORD grfMode, DWORD reserved, IStorage** ppstgOpen) PURE; \
STDMETHOD_(HRESULT,StgIsStorageFile)(THIS_ const WCHAR* pwcsName) PURE; \
STDMETHOD_(HRESULT,StgIsStorageILockBytes)(THIS_ ILockBytes* plkbyt) PURE; \
STDMETHOD_(HRESULT,StgOpenStorage)(THIS_ const WCHAR* pwcsName, IStorage* pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage** ppstgOpen) PURE; \
STDMETHOD_(HRESULT,StgOpenStorageOnILockBytes)(THIS_ ILockBytes* plkbyt, IStorage* pStgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage** ppstgOpen) PURE; \
STDMETHOD_(HRESULT,StgSetTimes)(THIS_ WCHAR* lpszName, FILETIME* pctime, FILETIME* patime, FILETIME* pmtime) PURE; \
STDMETHOD_(HRESULT,SetControlData)(THIS_ PITS_Control_Data pControlData) PURE; \
STDMETHOD_(HRESULT,DefaultControlData)(THIS_ PITS_Control_Data* ppControlData) PURE; \
STDMETHOD_(HRESULT,Compact)(THIS_ const WCHAR* pwcsName, ECompactionLev iLev) PURE;
HRESULT CALLBACK IITStorage_StgCreateDocfile_Proxy(
IITStorage* This,
const WCHAR* pwcsName,
DWORD grfMode,
DWORD reserved,
IStorage** ppstgOpen);
void __RPC_STUB IITStorage_StgCreateDocfile_Stub(
struct IRpcStubBuffer* This,
struct IRpcChannelBuffer* pRpcChannelBuffer,
PRPC_MESSAGE pRpcMessage,
DWORD* pdwStubPhase);
HRESULT CALLBACK IITStorage_StgCreateDocfileOnILockBytes_Proxy(
IITStorage* This,
ILockBytes* plkbyt,
DWORD grfMode,
DWORD reserved,
IStorage** ppstgOpen);
void __RPC_STUB IITStorage_StgCreateDocfileOnILockBytes_Stub(
struct IRpcStubBuffer* This,
struct IRpcChannelBuffer* pRpcChannelBuffer,
PRPC_MESSAGE pRpcMessage,
DWORD* pdwStubPhase);
HRESULT CALLBACK IITStorage_StgIsStorageFile_Proxy(
IITStorage* This,
const WCHAR* pwcsName);
void __RPC_STUB IITStorage_StgIsStorageFile_Stub(
struct IRpcStubBuffer* This,
struct IRpcChannelBuffer* pRpcChannelBuffer,
PRPC_MESSAGE pRpcMessage,
DWORD* pdwStubPhase);
HRESULT CALLBACK IITStorage_StgIsStorageILockBytes_Proxy(
IITStorage* This,
ILockBytes* plkbyt);
void __RPC_STUB IITStorage_StgIsStorageILockBytes_Stub(
struct IRpcStubBuffer* This,
struct IRpcChannelBuffer* pRpcChannelBuffer,
PRPC_MESSAGE pRpcMessage,
DWORD* pdwStubPhase);
HRESULT CALLBACK IITStorage_StgOpenStorage_Proxy(
IITStorage* This,
const WCHAR* pwcsName,
IStorage* pstgPriority,
DWORD grfMode,
SNB snbExclude,
DWORD reserved,
IStorage** ppstgOpen);
void __RPC_STUB IITStorage_StgOpenStorage_Stub(
struct IRpcStubBuffer* This,
struct IRpcChannelBuffer* pRpcChannelBuffer,
PRPC_MESSAGE pRpcMessage,
DWORD* pdwStubPhase);
HRESULT CALLBACK IITStorage_StgOpenStorageOnILockBytes_Proxy(
IITStorage* This,
ILockBytes* plkbyt,
IStorage* pStgPriority,
DWORD grfMode,
SNB snbExclude,
DWORD reserved,
IStorage** ppstgOpen);
void __RPC_STUB IITStorage_StgOpenStorageOnILockBytes_Stub(
struct IRpcStubBuffer* This,
struct IRpcChannelBuffer* pRpcChannelBuffer,
PRPC_MESSAGE pRpcMessage,
DWORD* pdwStubPhase);
HRESULT CALLBACK IITStorage_StgSetTimes_Proxy(
IITStorage* This,
WCHAR* lpszName,
FILETIME* pctime,
FILETIME* patime,
FILETIME* pmtime);
void __RPC_STUB IITStorage_StgSetTimes_Stub(
struct IRpcStubBuffer* This,
struct IRpcChannelBuffer* pRpcChannelBuffer,
PRPC_MESSAGE pRpcMessage,
DWORD* pdwStubPhase);
HRESULT CALLBACK IITStorage_SetControlData_Proxy(
IITStorage* This,
PITS_Control_Data pControlData);
void __RPC_STUB IITStorage_SetControlData_Stub(
struct IRpcStubBuffer* This,
struct IRpcChannelBuffer* pRpcChannelBuffer,
PRPC_MESSAGE pRpcMessage,
DWORD* pdwStubPhase);
HRESULT CALLBACK IITStorage_DefaultControlData_Proxy(
IITStorage* This,
PITS_Control_Data* ppControlData);
void __RPC_STUB IITStorage_DefaultControlData_Stub(
struct IRpcStubBuffer* This,
struct IRpcChannelBuffer* pRpcChannelBuffer,
PRPC_MESSAGE pRpcMessage,
DWORD* pdwStubPhase);
HRESULT CALLBACK IITStorage_Compact_Proxy(
IITStorage* This,
const WCHAR* pwcsName,
ECompactionLev iLev);
void __RPC_STUB IITStorage_Compact_Stub(
struct IRpcStubBuffer* This,
struct IRpcChannelBuffer* pRpcChannelBuffer,
PRPC_MESSAGE pRpcMessage,
DWORD* pdwStubPhase);
#endif /* __IITStorage_INTERFACE_DEFINED__ */
DEFINE_GUID(CLSID_ITStorage,0x5d02926a,0x212e,0x11d0,0x9d,0xf9,0x00,0xa0,0xc9,0x22,0xe6,0xec );
DEFINE_GUID(IID_IITStorage, 0x88cc31de, 0x27ab, 0x11d0, 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
#ifdef __cplusplus
}
#endif
#endif /* __WIDL_ITSS_H */

92
dlls/itss/itss.idl 100644
View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2004 Mike McCormack
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import "oaidl.idl";
typedef struct _ITS_Control_Data
{
UINT cdwControlData;
UINT adwControlData[1];
} ITS_Control_Data, *PITS_Control_Data;
typedef enum ECompactionLev {
COMPACT_DATA = 0,
COMPACT_DATA_AND_PATH
} ECompactionLev;
[
object,
pointer_default(unique)
]
interface IITStorage : IUnknown
{
HRESULT StgCreateDocfile(
[in] const WCHAR * pwcsName,
[in] DWORD grfMode,
[in] DWORD reserved,
[out] IStorage ** ppstgOpen);
HRESULT StgCreateDocfileOnILockBytes(
[in] ILockBytes * plkbyt,
[in] DWORD grfMode,
[in] DWORD reserved,
[out] IStorage ** ppstgOpen);
HRESULT StgIsStorageFile(
[in] const WCHAR * pwcsName);
HRESULT StgIsStorageILockBytes(
[in] ILockBytes * plkbyt);
HRESULT StgOpenStorage(
[in] const WCHAR * pwcsName,
[in] IStorage * pstgPriority,
[in] DWORD grfMode,
[in] SNB snbExclude,
[in] DWORD reserved,
[out] IStorage ** ppstgOpen);
HRESULT StgOpenStorageOnILockBytes(
[in] ILockBytes * plkbyt,
[in] IStorage * pStgPriority,
[in] DWORD grfMode,
[in] SNB snbExclude,
[in] DWORD reserved,
[out] IStorage ** ppstgOpen);
HRESULT StgSetTimes(
[in] WCHAR const * lpszName,
[in] FILETIME const * pctime,
[in] FILETIME const * patime,
[in] FILETIME const * pmtime);
HRESULT SetControlData(
[in] PITS_Control_Data pControlData);
HRESULT DefaultControlData(
[out] PITS_Control_Data * ppControlData);
HRESULT Compact(
[in] const WCHAR * pwcsName,
[in] ECompactionLev iLev);
}
cpp_quote("DEFINE_GUID(CLSID_ITStorage,0x5d02926a,0x212e,0x11d0,0x9d,0xf9,0x00,0xa0,0xc9,0x22,0xe6,0xec );");
cpp_quote("DEFINE_GUID(IID_IITStorage, 0x88cc31de, 0x27ab, 0x11d0, 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);");

View File

@ -0,0 +1,5 @@
@ stdcall -private DllCanUnloadNow() ITSS_DllCanUnloadNow
@ stdcall -private DllGetClassObject(ptr ptr ptr) ITSS_DllGetClassObject
@ stub DllInstall
@ stdcall -private DllRegisterServer() ITSS_DllRegisterServer
@ stub DllUnregisterServer

825
dlls/itss/lzx.c 100644
View File

@ -0,0 +1,825 @@
/* $Id$ */
/***************************************************************************
* lzx.c - LZX decompression routines *
* ------------------- *
* *
* maintainer: Jed Wing <jedwin@ugcs.caltech.edu> *
* 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. *
* *
***************************************************************************/
#include "lzx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* 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<<LZX_##tbl##_TABLEBITS) + (LZX_##tbl##_MAXSYMBOLS<<1)];\
UBYTE tbl##_len [LZX_##tbl##_MAXSYMBOLS + LZX_LENTABLE_SAFETY]
struct LZXstate
{
UBYTE *window; /* the actual decoding window */
ULONG window_size; /* window size (32Kb through 2Mb) */
ULONG actual_size; /* window size when it was first allocated */
ULONG window_posn; /* current offset within the window */
ULONG R0, R1, R2; /* for the LRU offset system */
UWORD main_elements; /* number of main tree elements */
int header_read; /* have we started decoding at all yet? */
UWORD block_type; /* type of this block */
ULONG block_length; /* uncompressed length of this block */
ULONG block_remaining; /* uncompressed bytes still left to decode */
ULONG frames_read; /* the number of CFDATA blocks processed */
LONG intel_filesize; /* magic header value used for transform */
LONG intel_curpos; /* current offset in transform space */
int intel_started; /* have we seen any translatable data yet? */
LZX_DECLARE_TABLE(PRETREE);
LZX_DECLARE_TABLE(MAINTREE);
LZX_DECLARE_TABLE(LENGTH);
LZX_DECLARE_TABLE(ALIGNED);
};
/* LZX decruncher */
/* Microsoft's LZX document and their implementation of the
* com.ms.util.cab Java package do not concur.
*
* In the LZX document, there is a table showing the correlation between
* window size and the number of position slots. It states that the 1MB
* window = 40 slots and the 2MB window = 42 slots. In the implementation,
* 1MB = 42 slots, 2MB = 50 slots. The actual calculation is 'find the
* first slot whose position base is equal to or more than the required
* window size'. This would explain why other tables in the document refer
* to 50 slots rather than 42.
*
* The constant NUM_PRIMARY_LENGTHS used in the decompression pseudocode
* is not defined in the specification.
*
* The LZX document does not state the uncompressed block has an
* uncompressed length field. Where does this length field come from, so
* we can know how large the block is? The implementation has it as the 24
* bits following after the 3 blocktype bits, before the alignment
* padding.
*
* The LZX document states that aligned offset blocks have their aligned
* offset huffman tree AFTER the main and length trees. The implementation
* suggests that the aligned offset tree is BEFORE the main and length
* trees.
*
* The LZX document decoding algorithm states that, in an aligned offset
* block, if an extra_bits value is 1, 2 or 3, then that number of bits
* should be read and the result added to the match offset. This is
* correct for 1 and 2, but not 3, where just a huffman symbol (using the
* aligned tree) should be read.
*
* Regarding the E8 preprocessing, the LZX document states 'No translation
* may be performed on the last 6 bytes of the input block'. This is
* correct. However, the pseudocode provided checks for the *E8 leader*
* up to the last 6 bytes. If the leader appears between -10 and -7 bytes
* from the end, this would cause the next four bytes to be modified, at
* least one of which would be in the last 6 bytes, which is not allowed
* according to the spec.
*
* The specification states that the huffman trees must always contain at
* least one element. However, many CAB files contain blocks where the
* length tree is completely empty (because there are no matches), and
* this is expected to succeed.
*/
/* LZX uses what it calls 'position slots' to represent match offsets.
* What this means is that a small 'position slot' number and a small
* offset from that slot are encoded instead of one large offset for
* every match.
* - position_base is an index to the position slot bases
* - extra_bits states how many bits of offset-from-base data is needed.
*/
static const UBYTE extra_bits[51] = {
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14,
15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17
};
static const ULONG position_base[51] = {
0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192,
256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152,
65536, 98304, 131072, 196608, 262144, 393216, 524288, 655360, 786432, 917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936,
1835008, 1966080, 2097152
};
struct LZXstate *LZXinit(int window)
{
struct LZXstate *pState=NULL;
ULONG wndsize = 1 << window;
int i, posn_slots;
/* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
/* if a previously allocated window is big enough, keep it */
if (window < 15 || window > 21) return NULL;
/* allocate state and associated window */
pState = (struct LZXstate *)malloc(sizeof(struct LZXstate));
if (!(pState->window = (UBYTE *)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)
{
if (pState->window)
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<c; i++)
{
fin = fopen(v[i], "rb");
ilen = fread(ibuf, 1, 16384, fin);
status = LZXdecompress(&state, ibuf, obuf, ilen, 32768);
switch (status)
{
case DECR_OK:
printf("ok\n");
fwrite(obuf, 1, 32768, fout);
break;
case DECR_DATAFORMAT:
printf("bad format\n");
break;
case DECR_ILLEGALDATA:
printf("illegal data\n");
break;
case DECR_NOMEMORY:
printf("no memory\n");
break;
default:
break;
}
fclose(fin);
if (++count == 2)
{
count = 0;
LZXreset(&state);
}
}
fclose(fout);
}
#endif

52
dlls/itss/lzx.h 100644
View File

@ -0,0 +1,52 @@
/* $Id$ */
/***************************************************************************
* lzx.h - LZX decompression routines *
* ------------------- *
* *
* maintainer: Jed Wing <jedwin@ugcs.caltech.edu> *
* 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. *
* *
***************************************************************************/
#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 */

449
dlls/itss/moniker.c 100644
View File

@ -0,0 +1,449 @@
/*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdarg.h>
#include <stdio.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "winnls.h"
#include "winreg.h"
#include "ole2.h"
#include "itss.h"
#include "uuids.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(itss);
/*****************************************************************************/
typedef struct {
IMonikerVtbl *vtbl_ITS_IMoniker;
DWORD ref;
LPWSTR szHtml;
WCHAR szFile[1];
} ITS_IMonikerImpl;
/*** IUnknown methods ***/
static HRESULT WINAPI ITS_IMonikerImpl_QueryInterface(
IMoniker* iface,
REFIID riid,
void** ppvObject)
{
ICOM_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)
{
ICOM_THIS(ITS_IMonikerImpl,iface);
TRACE("%p\n", This);
return ++(This->ref);
}
static ULONG WINAPI ITS_IMonikerImpl_Release(
IMoniker* iface)
{
ICOM_THIS(ITS_IMonikerImpl,iface);
ULONG ref = --This->ref;
if (ref == 0)
HeapFree(GetProcessHeap(), 0, This);
return ref;
}
/*** IPersist methods ***/
static HRESULT WINAPI ITS_IMonikerImpl_GetClassID(
IMoniker* iface,
CLSID* pClassID)
{
ICOM_THIS(ITS_IMonikerImpl,iface);
TRACE("%p %p\n", This, pClassID);
memcpy( pClassID, &CLSID_ITStorage, sizeof (CLSID) );
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)
{
FIXME("\n");
return E_NOTIMPL;
}
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)
{
ICOM_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 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, LPWSTR 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;
return S_OK;
}
/*****************************************************************************/
typedef struct {
IParseDisplayNameVtbl *vtbl_ITS_IParseDisplayName;
DWORD ref;
} ITS_IParseDisplayNameImpl;
static HRESULT WINAPI ITS_IParseDisplayNameImpl_QueryInterface(
IParseDisplayName* iface,
REFIID riid,
void** ppvObject)
{
ICOM_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)
{
ICOM_THIS(ITS_IParseDisplayNameImpl,iface);
TRACE("%p\n", This);
return ++(This->ref);
}
static ULONG WINAPI ITS_IParseDisplayNameImpl_Release(
IParseDisplayName* iface)
{
ICOM_THIS(ITS_IParseDisplayNameImpl,iface);
ULONG ref = --This->ref;
if (ref == 0)
HeapFree(GetProcessHeap(), 0, This);
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;
ICOM_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 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;
its = HeapAlloc( GetProcessHeap(), 0, sizeof(ITS_IParseDisplayNameImpl) );
its->vtbl_ITS_IParseDisplayName = &ITS_IParseDisplayNameImpl_Vtbl;
its->ref = 1;
TRACE("-> %p\n", its);
*ppObj = (LPVOID) its;
return S_OK;
}

798
dlls/itss/storage.c 100644
View File

@ -0,0 +1,798 @@
/*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdarg.h>
#include <stdio.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "winnls.h"
#include "winreg.h"
#include "ole2.h"
#include "uuids.h"
#include "itss.h"
#include "chm_lib.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(itss);
/************************************************************************/
typedef struct _ITSS_IStorageImpl
{
IStorageVtbl *vtbl_IStorage;
DWORD ref;
struct chmFile *chmfile;
WCHAR dir[1];
} ITSS_IStorageImpl;
struct enum_info
{
struct enum_info *next, *prev;
struct chmUnitInfo ui;
};
typedef struct _IEnumSTATSTG_Impl
{
IEnumSTATSTGVtbl *vtbl_IEnumSTATSTG;
DWORD ref;
struct enum_info *first, *last, *current;
} IEnumSTATSTG_Impl;
typedef struct _IStream_Impl
{
IStreamVtbl *vtbl_IStream;
DWORD 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)
{
ICOM_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)
{
ICOM_THIS(IEnumSTATSTG_Impl,iface);
return ++(This->ref);
}
static ULONG WINAPI ITSS_IEnumSTATSTG_Release(
IEnumSTATSTG* iface)
{
ICOM_THIS(IEnumSTATSTG_Impl,iface);
ULONG ref = --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);
}
return ref;
}
static HRESULT WINAPI ITSS_IEnumSTATSTG_Next(
IEnumSTATSTG* iface,
ULONG celt,
STATSTG* rgelt,
ULONG* pceltFetched)
{
ICOM_THIS(IEnumSTATSTG_Impl,iface);
DWORD len, n;
struct enum_info *cur;
TRACE("%p %lu %p %p\n", This, celt, rgelt, pceltFetched );
cur = This->current;
n = 0;
while( (n<celt) && cur)
{
WCHAR *str;
memset( rgelt, 0, sizeof *rgelt );
/* copy the name */
str = cur->ui.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)
{
ICOM_THIS(IEnumSTATSTG_Impl,iface);
DWORD n;
struct enum_info *cur;
TRACE("%p %lu\n", This, celt );
cur = This->current;
n = 0;
while( (n<celt) && cur)
{
n++;
cur = cur->next;
}
This->current = cur;
if( n < celt )
return S_FALSE;
return S_OK;
}
static HRESULT WINAPI ITSS_IEnumSTATSTG_Reset(
IEnumSTATSTG* iface)
{
ICOM_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;
}
struct 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;
TRACE(" -> %p\n", stgenum );
return stgenum;
}
/************************************************************************/
HRESULT WINAPI ITSS_IStorageImpl_QueryInterface(
IStorage* iface,
REFIID riid,
void** ppvObject)
{
ICOM_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;
}
ULONG WINAPI ITSS_IStorageImpl_AddRef(
IStorage* iface)
{
ICOM_THIS(ITSS_IStorageImpl,iface);
return ++(This->ref);
}
ULONG WINAPI ITSS_IStorageImpl_Release(
IStorage* iface)
{
ICOM_THIS(ITSS_IStorageImpl,iface);
ULONG ref = --This->ref;
if (ref == 0)
{
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
}
HRESULT WINAPI ITSS_IStorageImpl_CreateStream(
IStorage* iface,
LPCOLESTR pwcsName,
DWORD grfMode,
DWORD reserved1,
DWORD reserved2,
IStream** ppstm)
{
FIXME("\n");
return E_NOTIMPL;
}
HRESULT WINAPI ITSS_IStorageImpl_OpenStream(
IStorage* iface,
LPCOLESTR pwcsName,
void* reserved1,
DWORD grfMode,
DWORD reserved2,
IStream** ppstm)
{
ICOM_THIS(ITSS_IStorageImpl,iface);
IStream_Impl *stm;
DWORD len;
struct chmUnitInfo ui;
int r;
WCHAR *path;
TRACE("%p %s %p %lu %lu %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 );
strcatW( path, pwcsName );
r = chm_resolve_object(This->chmfile, path, &ui);
HeapFree( GetProcessHeap(), 0, path );
if( r != CHM_RESOLVE_SUCCESS )
return STG_E_FILENOTFOUND;
stm = ITSS_create_stream( This, &ui );
if( !stm )
return E_FAIL;
*ppstm = (IStream*) stm;
return S_OK;
}
HRESULT WINAPI ITSS_IStorageImpl_CreateStorage(
IStorage* iface,
LPCOLESTR pwcsName,
DWORD grfMode,
DWORD dwStgFmt,
DWORD reserved2,
IStorage** ppstg)
{
FIXME("\n");
return E_NOTIMPL;
}
HRESULT WINAPI ITSS_IStorageImpl_OpenStorage(
IStorage* iface,
LPCOLESTR pwcsName,
IStorage* pstgPriority,
DWORD grfMode,
SNB snbExclude,
DWORD reserved,
IStorage** ppstg)
{
FIXME("\n");
return E_NOTIMPL;
}
HRESULT WINAPI ITSS_IStorageImpl_CopyTo(
IStorage* iface,
DWORD ciidExclude,
const IID* rgiidExclude,
SNB snbExclude,
IStorage* pstgDest)
{
FIXME("\n");
return E_NOTIMPL;
}
HRESULT WINAPI ITSS_IStorageImpl_MoveElementTo(
IStorage* iface,
LPCOLESTR pwcsName,
IStorage* pstgDest,
LPCOLESTR pwcsNewName,
DWORD grfFlags)
{
FIXME("\n");
return E_NOTIMPL;
}
HRESULT WINAPI ITSS_IStorageImpl_Commit(
IStorage* iface,
DWORD grfCommitFlags)
{
FIXME("\n");
return E_NOTIMPL;
}
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) );
memcpy( &info->ui, ui, sizeof info->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;
}
HRESULT WINAPI ITSS_IStorageImpl_EnumElements(
IStorage* iface,
DWORD reserved1,
void* reserved2,
DWORD reserved3,
IEnumSTATSTG** ppenum)
{
ICOM_THIS(ITSS_IStorageImpl,iface);
IEnumSTATSTG_Impl* stgenum;
TRACE("%p %ld %p %ld %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;
}
HRESULT WINAPI ITSS_IStorageImpl_DestroyElement(
IStorage* iface,
LPCOLESTR pwcsName)
{
FIXME("\n");
return E_NOTIMPL;
}
HRESULT WINAPI ITSS_IStorageImpl_RenameElement(
IStorage* iface,
LPCOLESTR pwcsOldName,
LPCOLESTR pwcsNewName)
{
FIXME("\n");
return E_NOTIMPL;
}
HRESULT WINAPI ITSS_IStorageImpl_SetElementTimes(
IStorage* iface,
LPCOLESTR pwcsName,
const FILETIME* pctime,
const FILETIME* patime,
const FILETIME* pmtime)
{
FIXME("\n");
return E_NOTIMPL;
}
HRESULT WINAPI ITSS_IStorageImpl_SetClass(
IStorage* iface,
REFCLSID clsid)
{
FIXME("\n");
return E_NOTIMPL;
}
HRESULT WINAPI ITSS_IStorageImpl_SetStateBits(
IStorage* iface,
DWORD grfStateBits,
DWORD grfMask)
{
FIXME("\n");
return E_NOTIMPL;
}
HRESULT WINAPI ITSS_IStorageImpl_Stat(
IStorage* iface,
STATSTG* pstatstg,
DWORD grfStatFlag)
{
FIXME("\n");
return E_NOTIMPL;
}
static 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;
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)
{
ICOM_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)
{
ICOM_THIS(IStream_Impl,iface);
return ++(This->ref);
}
static ULONG WINAPI ITSS_IStream_Release(
IStream* iface)
{
ICOM_THIS(IStream_Impl,iface);
ULONG ref = --This->ref;
if (ref == 0)
{
IStorage_Release( (IStorage*) This->stg );
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
}
static HRESULT WINAPI ITSS_IStream_Read(
IStream* iface,
void* pv,
ULONG cb,
ULONG* pcbRead)
{
ICOM_THIS(IStream_Impl,iface);
ULONG count;
TRACE("%p %p %lu %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 S_OK;
}
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)
{
ICOM_THIS(IStream_Impl,iface);
LONGLONG newpos;
TRACE("%p %s %lu %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)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI ITSS_IStream_Clone(
IStream* iface,
IStream** ppstm)
{
FIXME("\n");
return E_NOTIMPL;
}
struct 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;
memcpy( &stm->ui, ui, sizeof stm->ui );
stm->stg = stg;
IStorage_AddRef( (IStorage*) stg );
TRACE(" -> %p\n", stm );
return stm;
}