4 * Copyright 2005 James Hawkins
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
36 static LPWSTR
CHM_ANSIToUnicode(LPCSTR ansi
)
41 count
= MultiByteToWideChar(CP_ACP
, 0, ansi
, -1, NULL
, 0);
42 unicode
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WCHAR
));
43 MultiByteToWideChar(CP_ACP
, 0, ansi
, -1, unicode
, count
);
48 /* Reads a string from the #STRINGS section in the CHM file */
49 LPWSTR
CHM_ReadString(CHMInfo
*pChmInfo
, DWORD dwOffset
)
51 LARGE_INTEGER liOffset
;
52 IStorage
*pStorage
= pChmInfo
->pStorage
;
60 const int CB_READ_BLOCK
= 64;
61 static const WCHAR stringsW
[] = {'#','S','T','R','I','N','G','S',0};
63 dwSize
= CB_READ_BLOCK
;
64 szString
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
66 if (FAILED(IStorage_OpenStream(pStorage
, stringsW
, NULL
, STGM_READ
, 0, &pStream
)))
69 liOffset
.QuadPart
= dwOffset
;
71 if (FAILED(IStream_Seek(pStream
, liOffset
, STREAM_SEEK_SET
, NULL
)))
73 IStream_Release(pStream
);
77 while (SUCCEEDED(IStream_Read(pStream
, szString
, CB_READ_BLOCK
, &cbRead
)))
82 for (iPos
= 0; iPos
< cbRead
; iPos
++)
86 stringW
= CHM_ANSIToUnicode(szString
);
87 HeapFree(GetProcessHeap(), 0, szString
);
93 szString
= HeapReAlloc(GetProcessHeap(), 0, szString
, dwSize
);
97 /* didn't find a string */
101 /* Loads the HH_WINTYPE data from the CHM file
103 * FIXME: There may be more than one window type in the file, so
104 * add the ability to choose a certain window type
106 BOOL
CHM_LoadWinTypeFromCHM(CHMInfo
*pChmInfo
, HH_WINTYPEW
*pHHWinType
)
108 LARGE_INTEGER liOffset
;
109 IStorage
*pStorage
= pChmInfo
->pStorage
;
114 static const WCHAR windowsW
[] = {'#','W','I','N','D','O','W','S',0};
116 hr
= IStorage_OpenStream(pStorage
, windowsW
, NULL
, STGM_READ
, 0, &pStream
);
120 /* jump past the #WINDOWS header */
121 liOffset
.QuadPart
= sizeof(DWORD
) * 2;
123 hr
= IStream_Seek(pStream
, liOffset
, STREAM_SEEK_SET
, NULL
);
124 if (FAILED(hr
)) goto done
;
126 /* read the HH_WINTYPE struct data */
127 hr
= IStream_Read(pStream
, pHHWinType
, sizeof(*pHHWinType
), &cbRead
);
128 if (FAILED(hr
)) goto done
;
130 /* convert the #STRINGS offsets to actual strings */
131 pHHWinType
->pszType
= CHM_ReadString(pChmInfo
, (DWORD
)pHHWinType
->pszType
);
132 pHHWinType
->pszCaption
= CHM_ReadString(pChmInfo
, (DWORD
)pHHWinType
->pszCaption
);
133 pHHWinType
->pszToc
= CHM_ReadString(pChmInfo
, (DWORD
)pHHWinType
->pszToc
);
134 pHHWinType
->pszIndex
= CHM_ReadString(pChmInfo
, (DWORD
)pHHWinType
->pszIndex
);
135 pHHWinType
->pszFile
= CHM_ReadString(pChmInfo
, (DWORD
)pHHWinType
->pszFile
);
136 pHHWinType
->pszHome
= CHM_ReadString(pChmInfo
, (DWORD
)pHHWinType
->pszHome
);
137 pHHWinType
->pszJump1
= CHM_ReadString(pChmInfo
, (DWORD
)pHHWinType
->pszJump1
);
138 pHHWinType
->pszJump2
= CHM_ReadString(pChmInfo
, (DWORD
)pHHWinType
->pszJump2
);
139 pHHWinType
->pszUrlJump1
= CHM_ReadString(pChmInfo
, (DWORD
)pHHWinType
->pszUrlJump1
);
140 pHHWinType
->pszUrlJump2
= CHM_ReadString(pChmInfo
, (DWORD
)pHHWinType
->pszUrlJump2
);
142 /* FIXME: pszCustomTabs is a list of multiple zero-terminated strings so ReadString won't
146 pHHWinType
->pszCustomTabs
= CHM_ReadString(pChmInfo
, (DWORD
)pHHWinType
->pszCustomTabs
);
150 IStream_Release(pStream
);
152 return SUCCEEDED(hr
);
155 /* Opens the CHM file for reading */
156 BOOL
CHM_OpenCHM(CHMInfo
*pChmInfo
, LPCWSTR szFile
)
158 pChmInfo
->szFile
= szFile
;
160 if (FAILED(CoCreateInstance(&CLSID_ITStorage
, NULL
, CLSCTX_INPROC_SERVER
,
161 &IID_IITStorage
, (void **) &pChmInfo
->pITStorage
)))
164 if (FAILED(IITStorage_StgOpenStorage(pChmInfo
->pITStorage
, szFile
, NULL
,
165 STGM_READ
| STGM_SHARE_DENY_WRITE
,
166 NULL
, 0, &pChmInfo
->pStorage
)))
172 void CHM_CloseCHM(CHMInfo
*pCHMInfo
)
174 IITStorage_Release(pCHMInfo
->pITStorage
);
175 IStorage_Release(pCHMInfo
->pStorage
);
178 /* Creates a Url of a CHM file that can be used with WB_Navigate */
179 void CHM_CreateITSUrl(CHMInfo
*pChmInfo
, LPCWSTR szIndex
, LPWSTR szUrl
)
181 static const WCHAR formatW
[] = {
182 'i','t','s',':','%','s',':',':','%','s',0
185 wsprintfW(szUrl
, formatW
, pChmInfo
->szFile
, szIndex
);