-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathCArchive.cpp
More file actions
221 lines (186 loc) · 5.07 KB
/
Copy pathCArchive.cpp
File metadata and controls
221 lines (186 loc) · 5.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#pragma comment (lib, "Urlmon.lib")
#include <windows.h>
#include "tp_stub.h"
#define PROTOCOL TJS_W("krkr")
/**
* Asynchronous Pluggable Protocols による IE/URL Moniker からの
* アーカイブへのアクセス処理
*/
class CArchive : public IInternetProtocol, public IClassFactory {
protected:
int refCount;
IStream *stream;
public:
CArchive() {
refCount = 0;
stream = NULL;
AddRef();
}
~CArchive() {
if (stream) {
stream->Release();
}
}
//----------------------------------------------------------------------------
// IUnknown 実装
public:
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) {
if (riid == IID_IUnknown ||
riid == IID_IInternetProtocol ||
riid == IID_IInternetProtocolRoot) {
if (ppvObject == NULL)
return E_POINTER;
*ppvObject = this;
AddRef();
return S_OK;
} else {
*ppvObject = 0;
return E_NOINTERFACE;
}
}
ULONG STDMETHODCALLTYPE AddRef() {
return ++refCount;
}
ULONG STDMETHODCALLTYPE Release() {
int ret = --refCount;
if (ret <= 0) {
delete this;
ret = 0;
}
return ret;
}
//----------------------------------------------------------------------------
// IInternetProtocolRoot 実装
public:
HRESULT STDMETHODCALLTYPE Start(
/* [in] */ LPCWSTR szUrl,
/* [in] */ IInternetProtocolSink *pOIProtSink,
/* [in] */ IInternetBindInfo *pOIBindInfo,
/* [in] */ DWORD grfPI,
/* [in] */ HANDLE_PTR dwReserved) {
LPCWSTR p = wcsstr(szUrl, PROTOCOL TJS_W(":"));
//TVPAddLog(ttstr(p));
if (p) {
p += TJS_strlen(PROTOCOL TJS_W(":"));
//TVPAddLog(ttstr(p));
// パス名の切り出し
int i=0;
while (p[i] && p[i] != '#' && p[i] != '?') i++;
ttstr name(p, i);
//TVPAddLog(name);
stream = TVPCreateIStream(name, TJS_BS_READ);
if (stream) {
//TVPAddLog(TJS_W("get stream!"));
STATSTG stat;
memset(&stat, 0, sizeof(stat));
stream->Stat(&stat, STATFLAG_NONAME);
ULONG size = stat.cbSize.LowPart; // XXX 32bitの壁こえるとはまるコード
pOIProtSink->ReportData(BSCF_DATAFULLYAVAILABLE,size,size);
pOIProtSink->ReportResult(S_OK,0,NULL);
} else {
return INET_E_OBJECT_NOT_FOUND;
}
return S_OK;
}
return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
}
HRESULT STDMETHODCALLTYPE Continue(
/* [in] */ PROTOCOLDATA *pProtocolData) {
return S_OK;
}
HRESULT STDMETHODCALLTYPE Abort(
/* [in] */ HRESULT hrReason,
/* [in] */ DWORD dwOptions) {
if (stream) {
stream->Release();
stream = NULL;
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE Terminate(
/* [in] */ DWORD dwOptions) {
return S_OK;
}
HRESULT STDMETHODCALLTYPE Suspend( void) {
return E_NOTIMPL;
} // Not implemented
HRESULT STDMETHODCALLTYPE Resume( void) {
return E_NOTIMPL;
} // Not implemented
//----------------------------------------------------------------------------
// IInternetProtocol 実装
public:
HRESULT STDMETHODCALLTYPE Read(
/* [length_is][size_is][out][in] */ void *pv,
/* [in] */ ULONG cb,
/* [out] */ ULONG *pcbRead) {
if (stream) {
stream->Read(pv, cb, pcbRead);
if (*pcbRead == cb) {
return S_OK;
}
return S_FALSE;
} else {
return INET_E_DOWNLOAD_FAILURE;
}
}
HRESULT STDMETHODCALLTYPE Seek(
/* [in] */ LARGE_INTEGER dlibMove,
/* [in] */ DWORD dwOrigin,
/* [out] */ ULARGE_INTEGER *plibNewPosition) {
return S_OK;
}
HRESULT STDMETHODCALLTYPE LockRequest(/* [in] */ DWORD dwOptions) {
return S_OK;
}
HRESULT STDMETHODCALLTYPE UnlockRequest( void) {
if (stream) {
stream->Release();
stream = NULL;
}
return S_OK;
}
//----------------------------------------------------------------------------
// IClassFactory 実装
HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown * pUnkOuter, REFIID riid,void ** ppvObject) {
*ppvObject = NULL;
if (pUnkOuter) {
return CLASS_E_NOAGGREGATION;
}
CArchive *p = new CArchive();
if (p == NULL) {
return E_OUTOFMEMORY;
}
HRESULT hr = p->QueryInterface(riid, ppvObject);
p->Release();
return hr;
}
HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock) {
return S_OK;
}
};
static IInternetSession *pIInternetSession = NULL;
static IClassFactory *pcf = NULL;
/**
* アーカイブ処理をプロセスのインターネットセッションに登録する
*/
void registerArchive()
{
if (pIInternetSession == NULL && CoInternetGetSession(0, &pIInternetSession, 0) == S_OK) {
pcf = new CArchive();
GUID dummy;
pIInternetSession->RegisterNameSpace(pcf, (REFCLSID)dummy, PROTOCOL, 0, NULL, 0);
}
}
/**
* アーカイブ処理をプロセスのインターネットセッションから解除する
*/
void unregisterArchive()
{
if (pIInternetSession) {
pIInternetSession->UnregisterNameSpace(pcf, PROTOCOL);
pcf->Release();
pIInternetSession->Release();
pIInternetSession = NULL;
}
}