Commit | Line | Data |
---|---|---|
5f6e3c88 AJ |
1 | /* |
2 | * ITSS Storage implementation | |
3 | * | |
4 | * Copyright 2004 Mike McCormack | |
5 | * | |
6 | * see http://bonedaddy.net/pabs3/hhm/#chmspec | |
7 | * | |
8 | * This library is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License as published by the Free Software Foundation; either | |
11 | * version 2.1 of the License, or (at your option) any later version. | |
12 | * | |
13 | * This library is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * Lesser General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU Lesser General Public | |
19 | * License along with this library; if not, write to the Free Software | |
360a3f91 | 20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
5f6e3c88 AJ |
21 | */ |
22 | ||
23 | #include "config.h" | |
24 | ||
25 | #include <stdarg.h> | |
26 | #include <stdio.h> | |
27 | ||
486d020c FG |
28 | #define COBJMACROS |
29 | ||
5f6e3c88 AJ |
30 | #include "windef.h" |
31 | #include "winbase.h" | |
32 | #include "winuser.h" | |
5f6e3c88 AJ |
33 | #include "ole2.h" |
34 | ||
5f6e3c88 | 35 | #include "chm_lib.h" |
332408b8 | 36 | #include "itsstor.h" |
5f6e3c88 | 37 | |
5a07e6ed | 38 | #include "wine/itss.h" |
5f6e3c88 AJ |
39 | #include "wine/unicode.h" |
40 | #include "wine/debug.h" | |
41 | ||
42 | WINE_DEFAULT_DEBUG_CHANNEL(itss); | |
43 | ||
44 | /************************************************************************/ | |
45 | ||
46 | typedef struct _ITSS_IStorageImpl | |
47 | { | |
b67da5b9 | 48 | const IStorageVtbl *vtbl_IStorage; |
bda7ace2 | 49 | LONG ref; |
5f6e3c88 AJ |
50 | struct chmFile *chmfile; |
51 | WCHAR dir[1]; | |
52 | } ITSS_IStorageImpl; | |
53 | ||
54 | struct enum_info | |
55 | { | |
56 | struct enum_info *next, *prev; | |
57 | struct chmUnitInfo ui; | |
58 | }; | |
59 | ||
60 | typedef struct _IEnumSTATSTG_Impl | |
61 | { | |
b67da5b9 | 62 | const IEnumSTATSTGVtbl *vtbl_IEnumSTATSTG; |
bda7ace2 | 63 | LONG ref; |
5f6e3c88 AJ |
64 | struct enum_info *first, *last, *current; |
65 | } IEnumSTATSTG_Impl; | |
66 | ||
67 | typedef struct _IStream_Impl | |
68 | { | |
b67da5b9 | 69 | const IStreamVtbl *vtbl_IStream; |
bda7ace2 | 70 | LONG ref; |
5f6e3c88 AJ |
71 | ITSS_IStorageImpl *stg; |
72 | ULONGLONG addr; | |
73 | struct chmUnitInfo ui; | |
74 | } IStream_Impl; | |
75 | ||
76 | static HRESULT ITSS_create_chm_storage( | |
77 | struct chmFile *chmfile, const WCHAR *dir, IStorage** ppstgOpen ); | |
78 | static IStream_Impl* ITSS_create_stream( | |
79 | ITSS_IStorageImpl *stg, struct chmUnitInfo *ui ); | |
80 | ||
81 | /************************************************************************/ | |
82 | ||
83 | static HRESULT WINAPI ITSS_IEnumSTATSTG_QueryInterface( | |
84 | IEnumSTATSTG* iface, | |
85 | REFIID riid, | |
86 | void** ppvObject) | |
87 | { | |
39a696a1 | 88 | IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface; |
5f6e3c88 AJ |
89 | |
90 | if (IsEqualGUID(riid, &IID_IUnknown) | |
91 | || IsEqualGUID(riid, &IID_IEnumSTATSTG)) | |
92 | { | |
93 | IEnumSTATSTG_AddRef(iface); | |
94 | *ppvObject = This; | |
95 | return S_OK; | |
96 | } | |
97 | ||
98 | WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject); | |
99 | return E_NOINTERFACE; | |
100 | } | |
101 | ||
102 | static ULONG WINAPI ITSS_IEnumSTATSTG_AddRef( | |
103 | IEnumSTATSTG* iface) | |
104 | { | |
39a696a1 | 105 | IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface; |
a8d9c87c | 106 | return InterlockedIncrement(&This->ref); |
5f6e3c88 AJ |
107 | } |
108 | ||
109 | static ULONG WINAPI ITSS_IEnumSTATSTG_Release( | |
110 | IEnumSTATSTG* iface) | |
111 | { | |
39a696a1 | 112 | IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface; |
5f6e3c88 | 113 | |
a8d9c87c | 114 | ULONG ref = InterlockedDecrement(&This->ref); |
5f6e3c88 AJ |
115 | |
116 | if (ref == 0) | |
117 | { | |
118 | while( This->first ) | |
119 | { | |
120 | struct enum_info *t = This->first->next; | |
121 | HeapFree( GetProcessHeap(), 0, This->first ); | |
122 | This->first = t; | |
123 | } | |
a8d9c87c | 124 | HeapFree(GetProcessHeap(), 0, This); |
162b3350 | 125 | ITSS_UnlockModule(); |
5f6e3c88 AJ |
126 | } |
127 | ||
128 | return ref; | |
129 | } | |
130 | ||
131 | static HRESULT WINAPI ITSS_IEnumSTATSTG_Next( | |
132 | IEnumSTATSTG* iface, | |
133 | ULONG celt, | |
134 | STATSTG* rgelt, | |
135 | ULONG* pceltFetched) | |
136 | { | |
39a696a1 | 137 | IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface; |
5f6e3c88 AJ |
138 | DWORD len, n; |
139 | struct enum_info *cur; | |
140 | ||
2492abbb | 141 | TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched ); |
5f6e3c88 AJ |
142 | |
143 | cur = This->current; | |
144 | n = 0; | |
145 | while( (n<celt) && cur) | |
146 | { | |
147 | WCHAR *str; | |
148 | ||
149 | memset( rgelt, 0, sizeof *rgelt ); | |
150 | ||
151 | /* copy the name */ | |
152 | str = cur->ui.path; | |
153 | if( *str == '/' ) | |
154 | str++; | |
155 | len = strlenW( str ) + 1; | |
156 | rgelt->pwcsName = CoTaskMemAlloc( len*sizeof(WCHAR) ); | |
157 | strcpyW( rgelt->pwcsName, str ); | |
158 | ||
159 | /* determine the type */ | |
160 | if( rgelt->pwcsName[len-2] == '/' ) | |
161 | { | |
162 | rgelt->pwcsName[len-2] = 0; | |
163 | rgelt->type = STGTY_STORAGE; | |
164 | } | |
165 | else | |
166 | rgelt->type = STGTY_STREAM; | |
167 | ||
168 | /* copy the size */ | |
169 | rgelt->cbSize.QuadPart = cur->ui.length; | |
170 | ||
171 | /* advance to the next item if it exists */ | |
172 | n++; | |
173 | cur = cur->next; | |
174 | } | |
175 | ||
176 | This->current = cur; | |
177 | *pceltFetched = n; | |
178 | ||
179 | if( n < celt ) | |
180 | return S_FALSE; | |
181 | ||
182 | return S_OK; | |
183 | } | |
184 | ||
185 | static HRESULT WINAPI ITSS_IEnumSTATSTG_Skip( | |
186 | IEnumSTATSTG* iface, | |
187 | ULONG celt) | |
188 | { | |
39a696a1 | 189 | IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface; |
5f6e3c88 AJ |
190 | DWORD n; |
191 | struct enum_info *cur; | |
192 | ||
2492abbb | 193 | TRACE("%p %u\n", This, celt ); |
5f6e3c88 AJ |
194 | |
195 | cur = This->current; | |
196 | n = 0; | |
197 | while( (n<celt) && cur) | |
198 | { | |
199 | n++; | |
200 | cur = cur->next; | |
201 | } | |
202 | This->current = cur; | |
203 | ||
204 | if( n < celt ) | |
205 | return S_FALSE; | |
206 | ||
207 | return S_OK; | |
208 | } | |
209 | ||
210 | static HRESULT WINAPI ITSS_IEnumSTATSTG_Reset( | |
211 | IEnumSTATSTG* iface) | |
212 | { | |
39a696a1 | 213 | IEnumSTATSTG_Impl *This = (IEnumSTATSTG_Impl *)iface; |
5f6e3c88 AJ |
214 | |
215 | TRACE("%p\n", This ); | |
216 | ||
217 | This->current = This->first; | |
218 | ||
219 | return S_OK; | |
220 | } | |
221 | ||
222 | static HRESULT WINAPI ITSS_IEnumSTATSTG_Clone( | |
223 | IEnumSTATSTG* iface, | |
224 | IEnumSTATSTG** ppenum) | |
225 | { | |
226 | FIXME("\n"); | |
227 | return E_NOTIMPL; | |
228 | } | |
229 | ||
b67da5b9 | 230 | static const IEnumSTATSTGVtbl IEnumSTATSTG_vtbl = |
5f6e3c88 AJ |
231 | { |
232 | ITSS_IEnumSTATSTG_QueryInterface, | |
233 | ITSS_IEnumSTATSTG_AddRef, | |
234 | ITSS_IEnumSTATSTG_Release, | |
235 | ITSS_IEnumSTATSTG_Next, | |
236 | ITSS_IEnumSTATSTG_Skip, | |
237 | ITSS_IEnumSTATSTG_Reset, | |
238 | ITSS_IEnumSTATSTG_Clone | |
239 | }; | |
240 | ||
241 | static IEnumSTATSTG_Impl *ITSS_create_enum( void ) | |
242 | { | |
243 | IEnumSTATSTG_Impl *stgenum; | |
244 | ||
245 | stgenum = HeapAlloc( GetProcessHeap(), 0, sizeof (IEnumSTATSTG_Impl) ); | |
246 | stgenum->vtbl_IEnumSTATSTG = &IEnumSTATSTG_vtbl; | |
247 | stgenum->ref = 1; | |
248 | stgenum->first = NULL; | |
249 | stgenum->last = NULL; | |
250 | stgenum->current = NULL; | |
251 | ||
162b3350 | 252 | ITSS_LockModule(); |
5f6e3c88 AJ |
253 | TRACE(" -> %p\n", stgenum ); |
254 | ||
255 | return stgenum; | |
256 | } | |
257 | ||
258 | /************************************************************************/ | |
259 | ||
383302c1 | 260 | static HRESULT WINAPI ITSS_IStorageImpl_QueryInterface( |
5f6e3c88 AJ |
261 | IStorage* iface, |
262 | REFIID riid, | |
263 | void** ppvObject) | |
264 | { | |
39a696a1 | 265 | ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface; |
5f6e3c88 AJ |
266 | |
267 | if (IsEqualGUID(riid, &IID_IUnknown) | |
268 | || IsEqualGUID(riid, &IID_IStorage)) | |
269 | { | |
270 | IStorage_AddRef(iface); | |
271 | *ppvObject = This; | |
272 | return S_OK; | |
273 | } | |
274 | ||
275 | WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject); | |
276 | return E_NOINTERFACE; | |
277 | } | |
278 | ||
383302c1 | 279 | static ULONG WINAPI ITSS_IStorageImpl_AddRef( |
5f6e3c88 AJ |
280 | IStorage* iface) |
281 | { | |
39a696a1 | 282 | ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface; |
a8d9c87c | 283 | return InterlockedIncrement(&This->ref); |
5f6e3c88 AJ |
284 | } |
285 | ||
383302c1 | 286 | static ULONG WINAPI ITSS_IStorageImpl_Release( |
5f6e3c88 AJ |
287 | IStorage* iface) |
288 | { | |
39a696a1 | 289 | ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface; |
5f6e3c88 | 290 | |
a8d9c87c | 291 | ULONG ref = InterlockedDecrement(&This->ref); |
5f6e3c88 AJ |
292 | |
293 | if (ref == 0) | |
294 | { | |
05d2aa45 | 295 | chm_close(This->chmfile); |
a8d9c87c | 296 | HeapFree(GetProcessHeap(), 0, This); |
162b3350 | 297 | ITSS_UnlockModule(); |
5f6e3c88 AJ |
298 | } |
299 | ||
300 | return ref; | |
301 | } | |
302 | ||
383302c1 | 303 | static HRESULT WINAPI ITSS_IStorageImpl_CreateStream( |
5f6e3c88 AJ |
304 | IStorage* iface, |
305 | LPCOLESTR pwcsName, | |
306 | DWORD grfMode, | |
307 | DWORD reserved1, | |
308 | DWORD reserved2, | |
309 | IStream** ppstm) | |
310 | { | |
311 | FIXME("\n"); | |
312 | return E_NOTIMPL; | |
313 | } | |
314 | ||
383302c1 | 315 | static HRESULT WINAPI ITSS_IStorageImpl_OpenStream( |
5f6e3c88 AJ |
316 | IStorage* iface, |
317 | LPCOLESTR pwcsName, | |
318 | void* reserved1, | |
319 | DWORD grfMode, | |
320 | DWORD reserved2, | |
321 | IStream** ppstm) | |
322 | { | |
39a696a1 | 323 | ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface; |
5f6e3c88 AJ |
324 | IStream_Impl *stm; |
325 | DWORD len; | |
326 | struct chmUnitInfo ui; | |
327 | int r; | |
18632c2b | 328 | WCHAR *path, *p; |
5f6e3c88 | 329 | |
2492abbb | 330 | TRACE("%p %s %p %u %u %p\n", This, debugstr_w(pwcsName), |
5f6e3c88 AJ |
331 | reserved1, grfMode, reserved2, ppstm ); |
332 | ||
333 | len = strlenW( This->dir ) + strlenW( pwcsName ) + 1; | |
334 | path = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); | |
335 | strcpyW( path, This->dir ); | |
18632c2b JC |
336 | |
337 | if( pwcsName[0] == '/' || pwcsName[0] == '\\' ) | |
332408b8 | 338 | { |
18632c2b | 339 | p = &path[strlenW( path ) - 1]; |
eefb72c8 | 340 | while( ( path <= p ) && ( *p == '/' ) ) |
332408b8 MM |
341 | *p-- = 0; |
342 | } | |
5f6e3c88 AJ |
343 | strcatW( path, pwcsName ); |
344 | ||
18632c2b JC |
345 | for(p=path; *p; p++) { |
346 | if(*p == '\\') | |
347 | *p = '/'; | |
348 | } | |
349 | ||
ff0a6136 JC |
350 | if(*--p == '/') |
351 | *p = 0; | |
352 | ||
332408b8 MM |
353 | TRACE("Resolving %s\n", debugstr_w(path)); |
354 | ||
5f6e3c88 AJ |
355 | r = chm_resolve_object(This->chmfile, path, &ui); |
356 | HeapFree( GetProcessHeap(), 0, path ); | |
357 | ||
18632c2b JC |
358 | if( r != CHM_RESOLVE_SUCCESS ) { |
359 | WARN("Could not resolve object\n"); | |
5f6e3c88 | 360 | return STG_E_FILENOTFOUND; |
18632c2b | 361 | } |
5f6e3c88 AJ |
362 | |
363 | stm = ITSS_create_stream( This, &ui ); | |
364 | if( !stm ) | |
365 | return E_FAIL; | |
366 | ||
367 | *ppstm = (IStream*) stm; | |
368 | ||
369 | return S_OK; | |
370 | } | |
371 | ||
383302c1 | 372 | static HRESULT WINAPI ITSS_IStorageImpl_CreateStorage( |
5f6e3c88 AJ |
373 | IStorage* iface, |
374 | LPCOLESTR pwcsName, | |
375 | DWORD grfMode, | |
376 | DWORD dwStgFmt, | |
377 | DWORD reserved2, | |
378 | IStorage** ppstg) | |
379 | { | |
380 | FIXME("\n"); | |
381 | return E_NOTIMPL; | |
382 | } | |
383 | ||
383302c1 | 384 | static HRESULT WINAPI ITSS_IStorageImpl_OpenStorage( |
5f6e3c88 AJ |
385 | IStorage* iface, |
386 | LPCOLESTR pwcsName, | |
387 | IStorage* pstgPriority, | |
388 | DWORD grfMode, | |
389 | SNB snbExclude, | |
390 | DWORD reserved, | |
391 | IStorage** ppstg) | |
392 | { | |
39a696a1 | 393 | ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface; |
332408b8 | 394 | |
2492abbb | 395 | FIXME("%p %s %p %u %p %u %p\n", This, debugstr_w(pwcsName), |
332408b8 | 396 | pstgPriority, grfMode, snbExclude, reserved, ppstg); |
5f6e3c88 AJ |
397 | return E_NOTIMPL; |
398 | } | |
399 | ||
383302c1 | 400 | static HRESULT WINAPI ITSS_IStorageImpl_CopyTo( |
5f6e3c88 AJ |
401 | IStorage* iface, |
402 | DWORD ciidExclude, | |
403 | const IID* rgiidExclude, | |
404 | SNB snbExclude, | |
405 | IStorage* pstgDest) | |
406 | { | |
407 | FIXME("\n"); | |
408 | return E_NOTIMPL; | |
409 | } | |
410 | ||
383302c1 | 411 | static HRESULT WINAPI ITSS_IStorageImpl_MoveElementTo( |
5f6e3c88 AJ |
412 | IStorage* iface, |
413 | LPCOLESTR pwcsName, | |
414 | IStorage* pstgDest, | |
415 | LPCOLESTR pwcsNewName, | |
416 | DWORD grfFlags) | |
417 | { | |
418 | FIXME("\n"); | |
419 | return E_NOTIMPL; | |
420 | } | |
421 | ||
383302c1 | 422 | static HRESULT WINAPI ITSS_IStorageImpl_Commit( |
5f6e3c88 AJ |
423 | IStorage* iface, |
424 | DWORD grfCommitFlags) | |
425 | { | |
426 | FIXME("\n"); | |
427 | return E_NOTIMPL; | |
428 | } | |
429 | ||
383302c1 | 430 | static HRESULT WINAPI ITSS_IStorageImpl_Revert( |
5f6e3c88 AJ |
431 | IStorage* iface) |
432 | { | |
433 | FIXME("\n"); | |
434 | return E_NOTIMPL; | |
435 | } | |
436 | ||
437 | static int ITSS_chm_enumerator( | |
438 | struct chmFile *h, | |
439 | struct chmUnitInfo *ui, | |
440 | void *context) | |
441 | { | |
442 | struct enum_info *info; | |
443 | IEnumSTATSTG_Impl* stgenum = context; | |
444 | ||
445 | TRACE("adding %s to enumeration\n", debugstr_w(ui->path) ); | |
446 | ||
447 | info = HeapAlloc( GetProcessHeap(), 0, sizeof (struct enum_info) ); | |
448 | memcpy( &info->ui, ui, sizeof info->ui ); | |
449 | ||
450 | info->next = NULL; | |
451 | info->prev = stgenum->last; | |
452 | if( stgenum->last ) | |
453 | stgenum->last->next = info; | |
454 | else | |
455 | stgenum->first = info; | |
456 | stgenum->last = info; | |
457 | ||
458 | return CHM_ENUMERATOR_CONTINUE; | |
459 | } | |
460 | ||
383302c1 | 461 | static HRESULT WINAPI ITSS_IStorageImpl_EnumElements( |
5f6e3c88 AJ |
462 | IStorage* iface, |
463 | DWORD reserved1, | |
464 | void* reserved2, | |
465 | DWORD reserved3, | |
466 | IEnumSTATSTG** ppenum) | |
467 | { | |
39a696a1 | 468 | ITSS_IStorageImpl *This = (ITSS_IStorageImpl *)iface; |
5f6e3c88 AJ |
469 | IEnumSTATSTG_Impl* stgenum; |
470 | ||
2492abbb | 471 | TRACE("%p %d %p %d %p\n", This, reserved1, reserved2, reserved3, ppenum ); |
5f6e3c88 AJ |
472 | |
473 | stgenum = ITSS_create_enum(); | |
474 | if( !stgenum ) | |
475 | return E_FAIL; | |
476 | ||
477 | chm_enumerate_dir(This->chmfile, | |
478 | This->dir, | |
479 | CHM_ENUMERATE_ALL, | |
480 | ITSS_chm_enumerator, | |
481 | stgenum ); | |
482 | ||
483 | stgenum->current = stgenum->first; | |
484 | ||
485 | *ppenum = (IEnumSTATSTG*) stgenum; | |
486 | ||
487 | return S_OK; | |
488 | } | |
489 | ||
383302c1 | 490 | static HRESULT WINAPI ITSS_IStorageImpl_DestroyElement( |
5f6e3c88 AJ |
491 | IStorage* iface, |
492 | LPCOLESTR pwcsName) | |
493 | { | |
494 | FIXME("\n"); | |
495 | return E_NOTIMPL; | |
496 | } | |
497 | ||
383302c1 | 498 | static HRESULT WINAPI ITSS_IStorageImpl_RenameElement( |
5f6e3c88 AJ |
499 | IStorage* iface, |
500 | LPCOLESTR pwcsOldName, | |
501 | LPCOLESTR pwcsNewName) | |
502 | { | |
503 | FIXME("\n"); | |
504 | return E_NOTIMPL; | |
505 | } | |
506 | ||
383302c1 | 507 | static HRESULT WINAPI ITSS_IStorageImpl_SetElementTimes( |
5f6e3c88 AJ |
508 | IStorage* iface, |
509 | LPCOLESTR pwcsName, | |
510 | const FILETIME* pctime, | |
511 | const FILETIME* patime, | |
512 | const FILETIME* pmtime) | |
513 | { | |
514 | FIXME("\n"); | |
515 | return E_NOTIMPL; | |
516 | } | |
517 | ||
383302c1 | 518 | static HRESULT WINAPI ITSS_IStorageImpl_SetClass( |
5f6e3c88 AJ |
519 | IStorage* iface, |
520 | REFCLSID clsid) | |
521 | { | |
522 | FIXME("\n"); | |
523 | return E_NOTIMPL; | |
524 | } | |
525 | ||
383302c1 | 526 | static HRESULT WINAPI ITSS_IStorageImpl_SetStateBits( |
5f6e3c88 AJ |
527 | IStorage* iface, |
528 | DWORD grfStateBits, | |
529 | DWORD grfMask) | |
530 | { | |
531 | FIXME("\n"); | |
532 | return E_NOTIMPL; | |
533 | } | |
534 | ||
383302c1 | 535 | static HRESULT WINAPI ITSS_IStorageImpl_Stat( |
5f6e3c88 AJ |
536 | IStorage* iface, |
537 | STATSTG* pstatstg, | |
538 | DWORD grfStatFlag) | |
539 | { | |
540 | FIXME("\n"); | |
541 | return E_NOTIMPL; | |
542 | } | |
543 | ||
b67da5b9 | 544 | static const IStorageVtbl ITSS_IStorageImpl_Vtbl = |
5f6e3c88 AJ |
545 | { |
546 | ITSS_IStorageImpl_QueryInterface, | |
547 | ITSS_IStorageImpl_AddRef, | |
548 | ITSS_IStorageImpl_Release, | |
549 | ITSS_IStorageImpl_CreateStream, | |
550 | ITSS_IStorageImpl_OpenStream, | |
551 | ITSS_IStorageImpl_CreateStorage, | |
552 | ITSS_IStorageImpl_OpenStorage, | |
553 | ITSS_IStorageImpl_CopyTo, | |
554 | ITSS_IStorageImpl_MoveElementTo, | |
555 | ITSS_IStorageImpl_Commit, | |
556 | ITSS_IStorageImpl_Revert, | |
557 | ITSS_IStorageImpl_EnumElements, | |
558 | ITSS_IStorageImpl_DestroyElement, | |
559 | ITSS_IStorageImpl_RenameElement, | |
560 | ITSS_IStorageImpl_SetElementTimes, | |
561 | ITSS_IStorageImpl_SetClass, | |
562 | ITSS_IStorageImpl_SetStateBits, | |
563 | ITSS_IStorageImpl_Stat, | |
564 | }; | |
565 | ||
566 | static HRESULT ITSS_create_chm_storage( | |
567 | struct chmFile *chmfile, const WCHAR *dir, IStorage** ppstgOpen ) | |
568 | { | |
569 | ITSS_IStorageImpl *stg; | |
570 | DWORD len; | |
571 | ||
572 | TRACE("%p %s\n", chmfile, debugstr_w( dir ) ); | |
573 | ||
574 | len = strlenW( dir ) + 1; | |
575 | stg = HeapAlloc( GetProcessHeap(), 0, | |
576 | sizeof (ITSS_IStorageImpl) + len*sizeof(WCHAR) ); | |
577 | stg->vtbl_IStorage = &ITSS_IStorageImpl_Vtbl; | |
578 | stg->ref = 1; | |
579 | stg->chmfile = chmfile; | |
580 | strcpyW( stg->dir, dir ); | |
581 | ||
582 | *ppstgOpen = (IStorage*) stg; | |
583 | ||
162b3350 | 584 | ITSS_LockModule(); |
5f6e3c88 AJ |
585 | return S_OK; |
586 | } | |
587 | ||
588 | HRESULT ITSS_StgOpenStorage( | |
589 | const WCHAR* pwcsName, | |
590 | IStorage* pstgPriority, | |
591 | DWORD grfMode, | |
592 | SNB snbExclude, | |
593 | DWORD reserved, | |
594 | IStorage** ppstgOpen) | |
595 | { | |
596 | struct chmFile *chmfile; | |
597 | static const WCHAR szRoot[] = { '/', 0 }; | |
598 | ||
599 | TRACE("%s\n", debugstr_w(pwcsName) ); | |
600 | ||
601 | chmfile = chm_openW( pwcsName ); | |
602 | if( !chmfile ) | |
603 | return E_FAIL; | |
604 | ||
605 | return ITSS_create_chm_storage( chmfile, szRoot, ppstgOpen ); | |
606 | } | |
607 | ||
608 | /************************************************************************/ | |
609 | ||
610 | static HRESULT WINAPI ITSS_IStream_QueryInterface( | |
611 | IStream* iface, | |
612 | REFIID riid, | |
613 | void** ppvObject) | |
614 | { | |
39a696a1 | 615 | IStream_Impl *This = (IStream_Impl *)iface; |
5f6e3c88 AJ |
616 | |
617 | if (IsEqualGUID(riid, &IID_IUnknown) | |
618 | || IsEqualGUID(riid, &IID_ISequentialStream) | |
619 | || IsEqualGUID(riid, &IID_IStream)) | |
620 | { | |
621 | IStream_AddRef(iface); | |
622 | *ppvObject = This; | |
623 | return S_OK; | |
624 | } | |
625 | ||
626 | WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject); | |
627 | return E_NOINTERFACE; | |
628 | } | |
629 | ||
630 | static ULONG WINAPI ITSS_IStream_AddRef( | |
631 | IStream* iface) | |
632 | { | |
39a696a1 | 633 | IStream_Impl *This = (IStream_Impl *)iface; |
a8d9c87c | 634 | return InterlockedIncrement(&This->ref); |
5f6e3c88 AJ |
635 | } |
636 | ||
637 | static ULONG WINAPI ITSS_IStream_Release( | |
638 | IStream* iface) | |
639 | { | |
39a696a1 | 640 | IStream_Impl *This = (IStream_Impl *)iface; |
5f6e3c88 | 641 | |
a8d9c87c | 642 | ULONG ref = InterlockedDecrement(&This->ref); |
5f6e3c88 AJ |
643 | |
644 | if (ref == 0) | |
645 | { | |
646 | IStorage_Release( (IStorage*) This->stg ); | |
162b3350 JC |
647 | HeapFree(GetProcessHeap(), 0, This); |
648 | ITSS_UnlockModule(); | |
5f6e3c88 AJ |
649 | } |
650 | ||
651 | return ref; | |
652 | } | |
653 | ||
654 | static HRESULT WINAPI ITSS_IStream_Read( | |
655 | IStream* iface, | |
656 | void* pv, | |
657 | ULONG cb, | |
658 | ULONG* pcbRead) | |
659 | { | |
39a696a1 | 660 | IStream_Impl *This = (IStream_Impl *)iface; |
5f6e3c88 AJ |
661 | ULONG count; |
662 | ||
2492abbb | 663 | TRACE("%p %p %u %p\n", This, pv, cb, pcbRead); |
5f6e3c88 AJ |
664 | |
665 | count = chm_retrieve_object(This->stg->chmfile, | |
666 | &This->ui, pv, This->addr, cb); | |
667 | This->addr += count; | |
668 | if( pcbRead ) | |
669 | *pcbRead = count; | |
18632c2b | 670 | |
f925e0c0 | 671 | return count ? S_OK : S_FALSE; |
5f6e3c88 AJ |
672 | } |
673 | ||
674 | static HRESULT WINAPI ITSS_IStream_Write( | |
675 | IStream* iface, | |
676 | const void* pv, | |
677 | ULONG cb, | |
678 | ULONG* pcbWritten) | |
679 | { | |
680 | FIXME("\n"); | |
681 | return E_NOTIMPL; | |
682 | } | |
683 | ||
684 | static HRESULT WINAPI ITSS_IStream_Seek( | |
685 | IStream* iface, | |
686 | LARGE_INTEGER dlibMove, | |
687 | DWORD dwOrigin, | |
688 | ULARGE_INTEGER* plibNewPosition) | |
689 | { | |
39a696a1 | 690 | IStream_Impl *This = (IStream_Impl *)iface; |
5f6e3c88 AJ |
691 | LONGLONG newpos; |
692 | ||
2492abbb | 693 | TRACE("%p %s %u %p\n", This, |
5f6e3c88 AJ |
694 | wine_dbgstr_longlong( dlibMove.QuadPart ), dwOrigin, plibNewPosition ); |
695 | ||
696 | newpos = This->addr; | |
697 | switch( dwOrigin ) | |
698 | { | |
699 | case STREAM_SEEK_CUR: | |
700 | newpos = This->addr + dlibMove.QuadPart; | |
701 | break; | |
702 | case STREAM_SEEK_SET: | |
703 | newpos = dlibMove.QuadPart; | |
704 | break; | |
705 | case STREAM_SEEK_END: | |
706 | newpos = This->ui.length + dlibMove.QuadPart; | |
707 | break; | |
708 | } | |
709 | ||
710 | if( ( newpos < 0 ) || ( newpos > This->ui.length ) ) | |
711 | return STG_E_INVALIDPOINTER; | |
712 | ||
713 | This->addr = newpos; | |
714 | if( plibNewPosition ) | |
715 | plibNewPosition->QuadPart = This->addr; | |
716 | ||
717 | return S_OK; | |
718 | } | |
719 | ||
720 | static HRESULT WINAPI ITSS_IStream_SetSize( | |
721 | IStream* iface, | |
722 | ULARGE_INTEGER libNewSize) | |
723 | { | |
724 | FIXME("\n"); | |
725 | return E_NOTIMPL; | |
726 | } | |
727 | ||
728 | static HRESULT WINAPI ITSS_IStream_CopyTo( | |
729 | IStream* iface, | |
730 | IStream* pstm, | |
731 | ULARGE_INTEGER cb, | |
732 | ULARGE_INTEGER* pcbRead, | |
733 | ULARGE_INTEGER* pcbWritten) | |
734 | { | |
735 | FIXME("\n"); | |
736 | return E_NOTIMPL; | |
737 | } | |
738 | ||
739 | static HRESULT WINAPI ITSS_IStream_Commit( | |
740 | IStream* iface, | |
741 | DWORD grfCommitFlags) | |
742 | { | |
743 | FIXME("\n"); | |
744 | return E_NOTIMPL; | |
745 | } | |
746 | ||
747 | static HRESULT WINAPI ITSS_IStream_Revert( | |
748 | IStream* iface) | |
749 | { | |
750 | FIXME("\n"); | |
751 | return E_NOTIMPL; | |
752 | } | |
753 | ||
754 | static HRESULT WINAPI ITSS_IStream_LockRegion( | |
755 | IStream* iface, | |
756 | ULARGE_INTEGER libOffset, | |
757 | ULARGE_INTEGER cb, | |
758 | DWORD dwLockType) | |
759 | { | |
760 | FIXME("\n"); | |
761 | return E_NOTIMPL; | |
762 | } | |
763 | ||
764 | static HRESULT WINAPI ITSS_IStream_UnlockRegion( | |
765 | IStream* iface, | |
766 | ULARGE_INTEGER libOffset, | |
767 | ULARGE_INTEGER cb, | |
768 | DWORD dwLockType) | |
769 | { | |
770 | FIXME("\n"); | |
771 | return E_NOTIMPL; | |
772 | } | |
773 | ||
774 | static HRESULT WINAPI ITSS_IStream_Stat( | |
775 | IStream* iface, | |
776 | STATSTG* pstatstg, | |
777 | DWORD grfStatFlag) | |
778 | { | |
39a696a1 | 779 | IStream_Impl *This = (IStream_Impl *)iface; |
332408b8 | 780 | |
2492abbb | 781 | TRACE("%p %p %d\n", This, pstatstg, grfStatFlag); |
332408b8 MM |
782 | |
783 | memset( pstatstg, 0, sizeof *pstatstg ); | |
784 | if( !( grfStatFlag & STATFLAG_NONAME ) ) | |
785 | { | |
786 | FIXME("copy the name\n"); | |
787 | } | |
788 | pstatstg->type = STGTY_STREAM; | |
789 | pstatstg->cbSize.QuadPart = This->ui.length; | |
790 | pstatstg->grfMode = STGM_READ; | |
791 | memcpy( &pstatstg->clsid, &CLSID_ITStorage, sizeof (CLSID) ); | |
792 | ||
793 | return S_OK; | |
5f6e3c88 AJ |
794 | } |
795 | ||
796 | static HRESULT WINAPI ITSS_IStream_Clone( | |
797 | IStream* iface, | |
798 | IStream** ppstm) | |
799 | { | |
800 | FIXME("\n"); | |
801 | return E_NOTIMPL; | |
802 | } | |
803 | ||
b67da5b9 | 804 | static const IStreamVtbl ITSS_IStream_vtbl = |
5f6e3c88 AJ |
805 | { |
806 | ITSS_IStream_QueryInterface, | |
807 | ITSS_IStream_AddRef, | |
808 | ITSS_IStream_Release, | |
809 | ITSS_IStream_Read, | |
810 | ITSS_IStream_Write, | |
811 | ITSS_IStream_Seek, | |
812 | ITSS_IStream_SetSize, | |
813 | ITSS_IStream_CopyTo, | |
814 | ITSS_IStream_Commit, | |
815 | ITSS_IStream_Revert, | |
816 | ITSS_IStream_LockRegion, | |
817 | ITSS_IStream_UnlockRegion, | |
818 | ITSS_IStream_Stat, | |
819 | ITSS_IStream_Clone, | |
820 | }; | |
821 | ||
822 | static IStream_Impl *ITSS_create_stream( | |
823 | ITSS_IStorageImpl *stg, struct chmUnitInfo *ui ) | |
824 | { | |
825 | IStream_Impl *stm; | |
826 | ||
827 | stm = HeapAlloc( GetProcessHeap(), 0, sizeof (IStream_Impl) ); | |
828 | stm->vtbl_IStream = &ITSS_IStream_vtbl; | |
829 | stm->ref = 1; | |
830 | stm->addr = 0; | |
831 | memcpy( &stm->ui, ui, sizeof stm->ui ); | |
832 | stm->stg = stg; | |
833 | IStorage_AddRef( (IStorage*) stg ); | |
162b3350 JC |
834 | |
835 | ITSS_LockModule(); | |
5f6e3c88 AJ |
836 | |
837 | TRACE(" -> %p\n", stm ); | |
838 | ||
839 | return stm; | |
840 | } |