1c2c66affSColin Finck /*
2c2c66affSColin Finck * FileMonikers implementation
3c2c66affSColin Finck *
4c2c66affSColin Finck * Copyright 1999 Noomen Hamza
5c2c66affSColin Finck * Copyright 2007 Robert Shearman
6c2c66affSColin Finck *
7c2c66affSColin Finck * This library is free software; you can redistribute it and/or
8c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
9c2c66affSColin Finck * License as published by the Free Software Foundation; either
10c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
11c2c66affSColin Finck *
12c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
13c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
14c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15c2c66affSColin Finck * Lesser General Public License for more details.
16c2c66affSColin Finck *
17c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
18c2c66affSColin Finck * License along with this library; if not, write to the Free Software
19c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20c2c66affSColin Finck */
21c2c66affSColin Finck
22c0f90872SAmine Khaldi #include <assert.h>
23c0f90872SAmine Khaldi #include <stdarg.h>
24c0f90872SAmine Khaldi #include <string.h>
25c0f90872SAmine Khaldi
26c0f90872SAmine Khaldi #define COBJMACROS
27c0f90872SAmine Khaldi #define NONAMELESSUNION
28c0f90872SAmine Khaldi
29c0f90872SAmine Khaldi #include "windef.h"
30c0f90872SAmine Khaldi #include "winbase.h"
31c0f90872SAmine Khaldi #include "winerror.h"
32c0f90872SAmine Khaldi #include "winnls.h"
33c0f90872SAmine Khaldi #include "wine/debug.h"
34c0f90872SAmine Khaldi #include "objbase.h"
35c0f90872SAmine Khaldi #include "moniker.h"
36c0f90872SAmine Khaldi
37c0f90872SAmine Khaldi #include "compobj_private.h"
38c2c66affSColin Finck
39c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(ole);
40c2c66affSColin Finck
41c2c66affSColin Finck /* filemoniker data structure */
42c2c66affSColin Finck typedef struct FileMonikerImpl{
43c2c66affSColin Finck IMoniker IMoniker_iface;
44c2c66affSColin Finck IROTData IROTData_iface;
45c2c66affSColin Finck LONG ref;
46c2c66affSColin Finck LPOLESTR filePathName; /* path string identified by this filemoniker */
47c2c66affSColin Finck IUnknown *pMarshal; /* custom marshaler */
48c2c66affSColin Finck } FileMonikerImpl;
49c2c66affSColin Finck
impl_from_IMoniker(IMoniker * iface)50c2c66affSColin Finck static inline FileMonikerImpl *impl_from_IMoniker(IMoniker *iface)
51c2c66affSColin Finck {
52c2c66affSColin Finck return CONTAINING_RECORD(iface, FileMonikerImpl, IMoniker_iface);
53c2c66affSColin Finck }
54c2c66affSColin Finck
impl_from_IROTData(IROTData * iface)55c2c66affSColin Finck static inline FileMonikerImpl *impl_from_IROTData(IROTData *iface)
56c2c66affSColin Finck {
57c2c66affSColin Finck return CONTAINING_RECORD(iface, FileMonikerImpl, IROTData_iface);
58c2c66affSColin Finck }
59c2c66affSColin Finck
60c2c66affSColin Finck /* Local function used by filemoniker implementation */
61c2c66affSColin Finck static HRESULT FileMonikerImpl_Construct(FileMonikerImpl* iface, LPCOLESTR lpszPathName);
62c2c66affSColin Finck static HRESULT FileMonikerImpl_Destroy(FileMonikerImpl* iface);
63c2c66affSColin Finck
64c2c66affSColin Finck /*******************************************************************************
65c2c66affSColin Finck * FileMoniker_QueryInterface
66c2c66affSColin Finck */
67c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_QueryInterface(IMoniker * iface,REFIID riid,void ** ppvObject)68c2c66affSColin Finck FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
69c2c66affSColin Finck {
70c2c66affSColin Finck FileMonikerImpl *This = impl_from_IMoniker(iface);
71c2c66affSColin Finck
72c2c66affSColin Finck TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
73c2c66affSColin Finck
74c2c66affSColin Finck /* Perform a sanity check on the parameters.*/
75c2c66affSColin Finck if ( ppvObject==0 )
76c2c66affSColin Finck return E_INVALIDARG;
77c2c66affSColin Finck
78c2c66affSColin Finck /* Initialize the return parameter */
79c2c66affSColin Finck *ppvObject = 0;
80c2c66affSColin Finck
81c2c66affSColin Finck /* Compare the riid with the interface IDs implemented by this object.*/
82c2c66affSColin Finck if (IsEqualIID(&IID_IUnknown, riid) ||
83c2c66affSColin Finck IsEqualIID(&IID_IPersist, riid) ||
84c2c66affSColin Finck IsEqualIID(&IID_IPersistStream,riid) ||
85c2c66affSColin Finck IsEqualIID(&IID_IMoniker, riid)
86c2c66affSColin Finck )
87c2c66affSColin Finck *ppvObject = iface;
88c2c66affSColin Finck
89c2c66affSColin Finck else if (IsEqualIID(&IID_IROTData, riid))
90c2c66affSColin Finck *ppvObject = &This->IROTData_iface;
91c2c66affSColin Finck else if (IsEqualIID(&IID_IMarshal, riid))
92c2c66affSColin Finck {
93c2c66affSColin Finck HRESULT hr = S_OK;
94c2c66affSColin Finck if (!This->pMarshal)
95c2c66affSColin Finck hr = MonikerMarshal_Create(iface, &This->pMarshal);
96c2c66affSColin Finck if (hr != S_OK)
97c2c66affSColin Finck return hr;
98c2c66affSColin Finck return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);
99c2c66affSColin Finck }
100c2c66affSColin Finck
101c2c66affSColin Finck /* Check that we obtained an interface.*/
102c2c66affSColin Finck if ((*ppvObject)==0)
103c2c66affSColin Finck return E_NOINTERFACE;
104c2c66affSColin Finck
105c2c66affSColin Finck /* Query Interface always increases the reference count by one when it is successful */
106c2c66affSColin Finck IMoniker_AddRef(iface);
107c2c66affSColin Finck
108c2c66affSColin Finck return S_OK;
109c2c66affSColin Finck }
110c2c66affSColin Finck
111c2c66affSColin Finck /******************************************************************************
112c2c66affSColin Finck * FileMoniker_AddRef
113c2c66affSColin Finck */
114c2c66affSColin Finck static ULONG WINAPI
FileMonikerImpl_AddRef(IMoniker * iface)115c2c66affSColin Finck FileMonikerImpl_AddRef(IMoniker* iface)
116c2c66affSColin Finck {
117c2c66affSColin Finck FileMonikerImpl *This = impl_from_IMoniker(iface);
118c2c66affSColin Finck
119c2c66affSColin Finck TRACE("(%p)\n",iface);
120c2c66affSColin Finck
121c2c66affSColin Finck return InterlockedIncrement(&This->ref);
122c2c66affSColin Finck }
123c2c66affSColin Finck
124c2c66affSColin Finck /******************************************************************************
125c2c66affSColin Finck * FileMoniker_Release
126c2c66affSColin Finck */
127c2c66affSColin Finck static ULONG WINAPI
FileMonikerImpl_Release(IMoniker * iface)128c2c66affSColin Finck FileMonikerImpl_Release(IMoniker* iface)
129c2c66affSColin Finck {
130c2c66affSColin Finck FileMonikerImpl *This = impl_from_IMoniker(iface);
131c2c66affSColin Finck ULONG ref;
132c2c66affSColin Finck
133c2c66affSColin Finck TRACE("(%p)\n",iface);
134c2c66affSColin Finck
135c2c66affSColin Finck ref = InterlockedDecrement(&This->ref);
136c2c66affSColin Finck
137c2c66affSColin Finck /* destroy the object if there are no more references to it */
138c2c66affSColin Finck if (ref == 0) FileMonikerImpl_Destroy(This);
139c2c66affSColin Finck
140c2c66affSColin Finck return ref;
141c2c66affSColin Finck }
142c2c66affSColin Finck
143c2c66affSColin Finck /******************************************************************************
144c2c66affSColin Finck * FileMoniker_GetClassID
145c2c66affSColin Finck */
146c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_GetClassID(IMoniker * iface,CLSID * pClassID)147c2c66affSColin Finck FileMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID)
148c2c66affSColin Finck {
149c2c66affSColin Finck TRACE("(%p,%p)\n",iface,pClassID);
150c2c66affSColin Finck
151c2c66affSColin Finck if (pClassID==NULL)
152c2c66affSColin Finck return E_POINTER;
153c2c66affSColin Finck
154c2c66affSColin Finck *pClassID = CLSID_FileMoniker;
155c2c66affSColin Finck
156c2c66affSColin Finck return S_OK;
157c2c66affSColin Finck }
158c2c66affSColin Finck
159c2c66affSColin Finck /******************************************************************************
160c2c66affSColin Finck * FileMoniker_IsDirty
161c2c66affSColin Finck *
162c2c66affSColin Finck * Note that the OLE-provided implementations of the IPersistStream::IsDirty
163c2c66affSColin Finck * method in the OLE-provided moniker interfaces always return S_FALSE because
164c2c66affSColin Finck * their internal state never changes.
165c2c66affSColin Finck */
166c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_IsDirty(IMoniker * iface)167c2c66affSColin Finck FileMonikerImpl_IsDirty(IMoniker* iface)
168c2c66affSColin Finck {
169c2c66affSColin Finck
170c2c66affSColin Finck TRACE("(%p)\n",iface);
171c2c66affSColin Finck
172c2c66affSColin Finck return S_FALSE;
173c2c66affSColin Finck }
174c2c66affSColin Finck
175c2c66affSColin Finck /******************************************************************************
176c2c66affSColin Finck * FileMoniker_Load
177c2c66affSColin Finck *
178c2c66affSColin Finck * this function locates and reads from the stream the filePath string
179c2c66affSColin Finck * written by FileMonikerImpl_Save
180c2c66affSColin Finck */
181c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_Load(IMoniker * iface,IStream * pStm)182c2c66affSColin Finck FileMonikerImpl_Load(IMoniker* iface, IStream* pStm)
183c2c66affSColin Finck {
184c2c66affSColin Finck FileMonikerImpl *This = impl_from_IMoniker(iface);
185c2c66affSColin Finck HRESULT res;
186c2c66affSColin Finck CHAR* filePathA = NULL;
187c2c66affSColin Finck WCHAR* filePathW = NULL;
188c2c66affSColin Finck ULONG bread;
189c2c66affSColin Finck WORD wbuffer;
190c2c66affSColin Finck DWORD dwbuffer, bytesA, bytesW, len;
191c2c66affSColin Finck int i;
192c2c66affSColin Finck
193c2c66affSColin Finck
194c2c66affSColin Finck TRACE("(%p,%p)\n",iface,pStm);
195c2c66affSColin Finck
196c2c66affSColin Finck /* first WORD */
197c2c66affSColin Finck res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
198c2c66affSColin Finck if (bread!=sizeof(WORD))
199c2c66affSColin Finck {
200c2c66affSColin Finck WARN("Couldn't read 0 word\n");
201c2c66affSColin Finck goto fail;
202c2c66affSColin Finck }
203c2c66affSColin Finck
204c2c66affSColin Finck /* read filePath string length (plus one) */
205c2c66affSColin Finck res=IStream_Read(pStm,&bytesA,sizeof(DWORD),&bread);
206c2c66affSColin Finck if (bread != sizeof(DWORD))
207c2c66affSColin Finck {
208c2c66affSColin Finck WARN("Couldn't read file string length\n");
209c2c66affSColin Finck goto fail;
210c2c66affSColin Finck }
211c2c66affSColin Finck
212c2c66affSColin Finck /* read filePath string */
213c2c66affSColin Finck filePathA=HeapAlloc(GetProcessHeap(),0,bytesA);
214c2c66affSColin Finck if (!filePathA)
215c2c66affSColin Finck {
216c2c66affSColin Finck res = E_OUTOFMEMORY;
217c2c66affSColin Finck goto fail;
218c2c66affSColin Finck }
219c2c66affSColin Finck
220c2c66affSColin Finck res=IStream_Read(pStm,filePathA,bytesA,&bread);
221c2c66affSColin Finck if (bread != bytesA)
222c2c66affSColin Finck {
223c2c66affSColin Finck WARN("Couldn't read file path string\n");
224c2c66affSColin Finck goto fail;
225c2c66affSColin Finck }
226c2c66affSColin Finck
227c2c66affSColin Finck /* read the unknown value */
228c2c66affSColin Finck IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
229c2c66affSColin Finck if (bread != sizeof(WORD))
230c2c66affSColin Finck {
231c2c66affSColin Finck WARN("Couldn't read unknown value\n");
232c2c66affSColin Finck goto fail;
233c2c66affSColin Finck }
234c2c66affSColin Finck
235c2c66affSColin Finck /* read the DEAD constant */
236c2c66affSColin Finck IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
237c2c66affSColin Finck if (bread != sizeof(WORD))
238c2c66affSColin Finck {
239c2c66affSColin Finck WARN("Couldn't read DEAD constant\n");
240c2c66affSColin Finck goto fail;
241c2c66affSColin Finck }
242c2c66affSColin Finck
243c2c66affSColin Finck for(i=0;i<5;i++)
244c2c66affSColin Finck {
245c2c66affSColin Finck res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
246c2c66affSColin Finck if (bread!=sizeof(DWORD))
247c2c66affSColin Finck {
248c2c66affSColin Finck WARN("Couldn't read 0 padding\n");
249c2c66affSColin Finck goto fail;
250c2c66affSColin Finck }
251c2c66affSColin Finck }
252c2c66affSColin Finck
253c2c66affSColin Finck res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
254c2c66affSColin Finck if (bread!=sizeof(DWORD))
255c2c66affSColin Finck goto fail;
256c2c66affSColin Finck
257c2c66affSColin Finck if (!dwbuffer) /* No W-string */
258c2c66affSColin Finck {
259c2c66affSColin Finck bytesA--;
260c2c66affSColin Finck len=MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, filePathA, bytesA, NULL, 0);
261c2c66affSColin Finck if (!len)
262c2c66affSColin Finck goto fail;
263c2c66affSColin Finck
264c2c66affSColin Finck filePathW=HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
265c2c66affSColin Finck if (!filePathW)
266c2c66affSColin Finck {
267c2c66affSColin Finck res = E_OUTOFMEMORY;
268c2c66affSColin Finck goto fail;
269c2c66affSColin Finck }
270c2c66affSColin Finck MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, filePathA, -1, filePathW, len+1);
271c2c66affSColin Finck goto succeed;
272c2c66affSColin Finck }
273c2c66affSColin Finck
274c2c66affSColin Finck if (dwbuffer < 6)
275c2c66affSColin Finck goto fail;
276c2c66affSColin Finck
277c2c66affSColin Finck bytesW=dwbuffer - 6;
278c2c66affSColin Finck
279c2c66affSColin Finck res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
280c2c66affSColin Finck if (bread!=sizeof(DWORD) || dwbuffer!=bytesW)
281c2c66affSColin Finck goto fail;
282c2c66affSColin Finck
283c2c66affSColin Finck res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
284c2c66affSColin Finck if (bread!=sizeof(WORD) || wbuffer!=0x3)
285c2c66affSColin Finck goto fail;
286c2c66affSColin Finck
287c2c66affSColin Finck len=bytesW/sizeof(WCHAR);
288c2c66affSColin Finck filePathW=HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
289c2c66affSColin Finck if(!filePathW)
290c2c66affSColin Finck {
291c2c66affSColin Finck res = E_OUTOFMEMORY;
292c2c66affSColin Finck goto fail;
293c2c66affSColin Finck }
294c2c66affSColin Finck res=IStream_Read(pStm,filePathW,bytesW,&bread);
295c2c66affSColin Finck if (bread!=bytesW)
296c2c66affSColin Finck goto fail;
297c2c66affSColin Finck
298c2c66affSColin Finck filePathW[len]=0;
299c2c66affSColin Finck
300c2c66affSColin Finck succeed:
301c2c66affSColin Finck HeapFree(GetProcessHeap(),0,filePathA);
302c2c66affSColin Finck HeapFree(GetProcessHeap(),0,This->filePathName);
303c2c66affSColin Finck This->filePathName=filePathW;
304c2c66affSColin Finck
305c2c66affSColin Finck return S_OK;
306c2c66affSColin Finck
307c2c66affSColin Finck fail:
308c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, filePathA);
309c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, filePathW);
310c2c66affSColin Finck
311c2c66affSColin Finck if (SUCCEEDED(res))
312c2c66affSColin Finck res = E_FAIL;
313c2c66affSColin Finck return res;
314c2c66affSColin Finck }
315c2c66affSColin Finck
316c2c66affSColin Finck /******************************************************************************
317c2c66affSColin Finck * FileMoniker_Save
318c2c66affSColin Finck *
319c2c66affSColin Finck * This function saves data of this object. In the beginning I thought
320c2c66affSColin Finck * that I have just to write the filePath string on Stream. But, when I
321c2c66affSColin Finck * tested this function with windows program samples, I noticed that it
322c2c66affSColin Finck * was not the case. This implementation is based on XP SP2. Other versions
323c2c66affSColin Finck * of Windows have minor variations.
324c2c66affSColin Finck *
325c2c66affSColin Finck * Data which must be written on stream is:
326c2c66affSColin Finck * 1) WORD constant: zero (not validated by Windows)
327c2c66affSColin Finck * 2) length of the path string ("\0" included)
328c2c66affSColin Finck * 3) path string type A
329c2c66affSColin Finck * 4) Unknown WORD value: Frequently 0xFFFF, but not always. If set very large,
330c2c66affSColin Finck * Windows returns E_OUTOFMEMORY
331c2c66affSColin Finck * 5) WORD Constant: 0xDEAD (not validated by Windows)
332c2c66affSColin Finck * 6) five DWORD constant: zero (not validated by Windows)
333c2c66affSColin Finck * 7) If we're only writing the multibyte version,
334c2c66affSColin Finck * write a zero DWORD and finish.
335c2c66affSColin Finck *
336c2c66affSColin Finck * 8) DWORD: double-length of the path string type W ("\0" not
337c2c66affSColin Finck * included)
338c2c66affSColin Finck * 9) WORD constant: 0x3
339c2c66affSColin Finck * 10) filePath unicode string.
340c2c66affSColin Finck *
341c2c66affSColin Finck */
342c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_Save(IMoniker * iface,IStream * pStm,BOOL fClearDirty)343c2c66affSColin Finck FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
344c2c66affSColin Finck {
345c2c66affSColin Finck FileMonikerImpl *This = impl_from_IMoniker(iface);
346c2c66affSColin Finck HRESULT res;
347c2c66affSColin Finck LPOLESTR filePathW=This->filePathName;
348c2c66affSColin Finck CHAR* filePathA;
349c2c66affSColin Finck DWORD bytesA, bytesW, len;
350c2c66affSColin Finck
351c2c66affSColin Finck static const WORD FFFF = 0xFFFF; /* Constants */
352c2c66affSColin Finck static const WORD DEAD = 0xDEAD;
353c2c66affSColin Finck static const DWORD ZERO = 0;
354c2c66affSColin Finck static const WORD THREE = 0x3;
355c2c66affSColin Finck
356c2c66affSColin Finck int i;
357c2c66affSColin Finck BOOL bUsedDefault, bWriteWide;
358c2c66affSColin Finck
359c2c66affSColin Finck TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
360c2c66affSColin Finck
361c2c66affSColin Finck if (pStm==NULL)
362c2c66affSColin Finck return E_POINTER;
363c2c66affSColin Finck
364c2c66affSColin Finck /* write a 0 WORD */
365c2c66affSColin Finck res=IStream_Write(pStm,&ZERO,sizeof(WORD),NULL);
366c2c66affSColin Finck if (FAILED(res)) return res;
367c2c66affSColin Finck
368c2c66affSColin Finck /* write length of filePath string ( 0 included )*/
369c2c66affSColin Finck bytesA = WideCharToMultiByte( CP_ACP, 0, filePathW, -1, NULL, 0, NULL, NULL );
370c2c66affSColin Finck res=IStream_Write(pStm,&bytesA,sizeof(DWORD),NULL);
371c2c66affSColin Finck if (FAILED(res)) return res;
372c2c66affSColin Finck
373c2c66affSColin Finck /* write A string (with '\0') */
374c2c66affSColin Finck filePathA=HeapAlloc(GetProcessHeap(),0,bytesA);
375c2c66affSColin Finck if (!filePathA)
376c2c66affSColin Finck return E_OUTOFMEMORY;
377c2c66affSColin Finck WideCharToMultiByte( CP_ACP, 0, filePathW, -1, filePathA, bytesA, NULL, &bUsedDefault);
378c2c66affSColin Finck res=IStream_Write(pStm,filePathA,bytesA,NULL);
379c2c66affSColin Finck HeapFree(GetProcessHeap(),0,filePathA);
380c2c66affSColin Finck if (FAILED(res)) return res;
381c2c66affSColin Finck
382c2c66affSColin Finck /* write a WORD 0xFFFF */
383c2c66affSColin Finck res=IStream_Write(pStm,&FFFF,sizeof(WORD),NULL);
384c2c66affSColin Finck if (FAILED(res)) return res;
385c2c66affSColin Finck
386c2c66affSColin Finck /* write a WORD 0xDEAD */
387c2c66affSColin Finck res=IStream_Write(pStm,&DEAD,sizeof(WORD),NULL);
388c2c66affSColin Finck if (FAILED(res)) return res;
389c2c66affSColin Finck
390c2c66affSColin Finck /* write 5 zero DWORDs */
391c2c66affSColin Finck for(i=0;i<5;i++)
392c2c66affSColin Finck {
393c2c66affSColin Finck res=IStream_Write(pStm,&ZERO,sizeof(DWORD),NULL);
394c2c66affSColin Finck if (FAILED(res)) return res;
395c2c66affSColin Finck }
396c2c66affSColin Finck
397c2c66affSColin Finck /* Write the wide version if:
398c2c66affSColin Finck * + couldn't convert to CP_ACP,
399c2c66affSColin Finck * or + it's a directory,
400c2c66affSColin Finck * or + there's a character > 0xFF
401c2c66affSColin Finck */
402c2c66affSColin Finck len = lstrlenW(filePathW);
403c2c66affSColin Finck bWriteWide = (bUsedDefault || (len > 0 && filePathW[len-1]=='\\' ));
404c2c66affSColin Finck if (!bWriteWide)
405c2c66affSColin Finck {
406c2c66affSColin Finck WCHAR* pch;
407c2c66affSColin Finck for(pch=filePathW;*pch;++pch)
408c2c66affSColin Finck {
409c2c66affSColin Finck if (*pch > 0xFF)
410c2c66affSColin Finck {
411c2c66affSColin Finck bWriteWide = TRUE;
412c2c66affSColin Finck break;
413c2c66affSColin Finck }
414c2c66affSColin Finck }
415c2c66affSColin Finck }
416c2c66affSColin Finck
417c2c66affSColin Finck if (!bWriteWide)
418c2c66affSColin Finck return IStream_Write(pStm,&ZERO,sizeof(DWORD),NULL);
419c2c66affSColin Finck
420c2c66affSColin Finck /* write bytes needed for the filepathW (without 0) + 6 */
421c2c66affSColin Finck bytesW = len*sizeof(WCHAR) + 6;
422c2c66affSColin Finck res=IStream_Write(pStm,&bytesW,sizeof(DWORD),NULL);
423c2c66affSColin Finck if (FAILED(res)) return res;
424c2c66affSColin Finck
425c2c66affSColin Finck /* try again, without the extra 6 */
426c2c66affSColin Finck bytesW -= 6;
427c2c66affSColin Finck res=IStream_Write(pStm,&bytesW,sizeof(DWORD),NULL);
428c2c66affSColin Finck if (FAILED(res)) return res;
429c2c66affSColin Finck
430c2c66affSColin Finck /* write a WORD 3 */
431c2c66affSColin Finck res=IStream_Write(pStm,&THREE,sizeof(WORD),NULL);
432c2c66affSColin Finck if (FAILED(res)) return res;
433c2c66affSColin Finck
434c2c66affSColin Finck /* write W string (no 0) */
435c2c66affSColin Finck return IStream_Write(pStm,filePathW,bytesW,NULL);
436c2c66affSColin Finck }
437c2c66affSColin Finck
438c2c66affSColin Finck /******************************************************************************
439c2c66affSColin Finck * FileMoniker_GetSizeMax
440c2c66affSColin Finck */
441c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_GetSizeMax(IMoniker * iface,ULARGE_INTEGER * pcbSize)442c2c66affSColin Finck FileMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
443c2c66affSColin Finck {
444c2c66affSColin Finck FileMonikerImpl *This = impl_from_IMoniker(iface);
445c2c66affSColin Finck
446c2c66affSColin Finck TRACE("(%p,%p)\n",iface,pcbSize);
447c2c66affSColin Finck
448c2c66affSColin Finck if (!pcbSize)
449c2c66affSColin Finck return E_POINTER;
450c2c66affSColin Finck
451c2c66affSColin Finck /* We could calculate exactly (see ...::Save()) but instead
452c2c66affSColin Finck * we'll make a quick over-estimate, like Windows (NT4, XP) does.
453c2c66affSColin Finck */
454c2c66affSColin Finck pcbSize->u.LowPart = 0x38 + 4 * lstrlenW(This->filePathName);
455c2c66affSColin Finck pcbSize->u.HighPart = 0;
456c2c66affSColin Finck
457c2c66affSColin Finck return S_OK;
458c2c66affSColin Finck }
459c2c66affSColin Finck
460c2c66affSColin Finck /******************************************************************************
461c2c66affSColin Finck * FileMoniker_Destroy (local function)
462c2c66affSColin Finck *******************************************************************************/
FileMonikerImpl_Destroy(FileMonikerImpl * This)463c2c66affSColin Finck HRESULT FileMonikerImpl_Destroy(FileMonikerImpl* This)
464c2c66affSColin Finck {
465c2c66affSColin Finck TRACE("(%p)\n",This);
466c2c66affSColin Finck
467c2c66affSColin Finck if (This->pMarshal) IUnknown_Release(This->pMarshal);
468c2c66affSColin Finck HeapFree(GetProcessHeap(),0,This->filePathName);
469c2c66affSColin Finck HeapFree(GetProcessHeap(),0,This);
470c2c66affSColin Finck
471c2c66affSColin Finck return S_OK;
472c2c66affSColin Finck }
473c2c66affSColin Finck
474c2c66affSColin Finck /******************************************************************************
475c2c66affSColin Finck * FileMoniker_BindToObject
476c2c66affSColin Finck */
477c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_BindToObject(IMoniker * iface,IBindCtx * pbc,IMoniker * pmkToLeft,REFIID riid,VOID ** ppvResult)478c2c66affSColin Finck FileMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
479c2c66affSColin Finck REFIID riid, VOID** ppvResult)
480c2c66affSColin Finck {
481c2c66affSColin Finck FileMonikerImpl *This = impl_from_IMoniker(iface);
482c2c66affSColin Finck HRESULT res=E_FAIL;
483c2c66affSColin Finck CLSID clsID;
484c2c66affSColin Finck IUnknown* pObj=0;
485c2c66affSColin Finck IRunningObjectTable *prot=0;
486c2c66affSColin Finck IPersistFile *ppf=0;
487c2c66affSColin Finck IClassFactory *pcf=0;
488c2c66affSColin Finck IClassActivator *pca=0;
489c2c66affSColin Finck
490c2c66affSColin Finck *ppvResult=0;
491c2c66affSColin Finck
492c2c66affSColin Finck TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
493c2c66affSColin Finck
494c2c66affSColin Finck if(pmkToLeft==NULL){
495c2c66affSColin Finck
496c2c66affSColin Finck res=IBindCtx_GetRunningObjectTable(pbc,&prot);
497c2c66affSColin Finck
498c2c66affSColin Finck if (SUCCEEDED(res)){
499c2c66affSColin Finck /* if the requested class was loaded before ! we don't need to reload it */
500c2c66affSColin Finck res = IRunningObjectTable_GetObject(prot,iface,&pObj);
501c2c66affSColin Finck
502c2c66affSColin Finck if (res != S_OK){
503c2c66affSColin Finck /* first activation of this class */
504c2c66affSColin Finck res=GetClassFile(This->filePathName,&clsID);
505c2c66affSColin Finck if (SUCCEEDED(res)){
506c2c66affSColin Finck
507c2c66affSColin Finck res=CoCreateInstance(&clsID,NULL,CLSCTX_SERVER,&IID_IPersistFile,(void**)&ppf);
508c2c66affSColin Finck if (SUCCEEDED(res)){
509c2c66affSColin Finck
510c2c66affSColin Finck res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
511c2c66affSColin Finck if (SUCCEEDED(res)){
512c2c66affSColin Finck
513c2c66affSColin Finck pObj=(IUnknown*)ppf;
514c2c66affSColin Finck IUnknown_AddRef(pObj);
515c2c66affSColin Finck }
516c2c66affSColin Finck }
517c2c66affSColin Finck }
518c2c66affSColin Finck }
519c2c66affSColin Finck }
520c2c66affSColin Finck }
521c2c66affSColin Finck else{
522c2c66affSColin Finck res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassFactory,(void**)&pcf);
523c2c66affSColin Finck
524c2c66affSColin Finck if (res==E_NOINTERFACE){
525c2c66affSColin Finck
526c2c66affSColin Finck res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassActivator,(void**)&pca);
527c2c66affSColin Finck
528c2c66affSColin Finck if (res==E_NOINTERFACE)
529c2c66affSColin Finck return MK_E_INTERMEDIATEINTERFACENOTSUPPORTED;
530c2c66affSColin Finck }
531c2c66affSColin Finck if (pcf!=NULL){
532c2c66affSColin Finck
533c2c66affSColin Finck IClassFactory_CreateInstance(pcf,NULL,&IID_IPersistFile,(void**)&ppf);
534c2c66affSColin Finck
535c2c66affSColin Finck res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
536c2c66affSColin Finck
537c2c66affSColin Finck if (SUCCEEDED(res)){
538c2c66affSColin Finck
539c2c66affSColin Finck pObj=(IUnknown*)ppf;
540c2c66affSColin Finck IUnknown_AddRef(pObj);
541c2c66affSColin Finck }
542c2c66affSColin Finck }
543c2c66affSColin Finck if (pca!=NULL){
544c2c66affSColin Finck
545c2c66affSColin Finck FIXME("()\n");
546c2c66affSColin Finck
547c2c66affSColin Finck /*res=GetClassFile(This->filePathName,&clsID);
548c2c66affSColin Finck
549c2c66affSColin Finck if (SUCCEEDED(res)){
550c2c66affSColin Finck
551c2c66affSColin Finck res=IClassActivator_GetClassObject(pca,&clsID,CLSCTX_ALL,0,&IID_IPersistFile,(void**)&ppf);
552c2c66affSColin Finck
553c2c66affSColin Finck if (SUCCEEDED(res)){
554c2c66affSColin Finck
555c2c66affSColin Finck pObj=(IUnknown*)ppf;
556c2c66affSColin Finck IUnknown_AddRef(pObj);
557c2c66affSColin Finck }
558c2c66affSColin Finck }*/
559c2c66affSColin Finck }
560c2c66affSColin Finck }
561c2c66affSColin Finck
562c2c66affSColin Finck if (pObj!=NULL){
563c2c66affSColin Finck /* get the requested interface from the loaded class */
564c2c66affSColin Finck res= IUnknown_QueryInterface(pObj,riid,ppvResult);
565c2c66affSColin Finck
566c2c66affSColin Finck IBindCtx_RegisterObjectBound(pbc,*ppvResult);
567c2c66affSColin Finck
568c2c66affSColin Finck IUnknown_Release(pObj);
569c2c66affSColin Finck }
570c2c66affSColin Finck
571c2c66affSColin Finck if (prot!=NULL)
572c2c66affSColin Finck IRunningObjectTable_Release(prot);
573c2c66affSColin Finck
574c2c66affSColin Finck if (ppf!=NULL)
575c2c66affSColin Finck IPersistFile_Release(ppf);
576c2c66affSColin Finck
577c2c66affSColin Finck if (pca!=NULL)
578c2c66affSColin Finck IClassActivator_Release(pca);
579c2c66affSColin Finck
580c2c66affSColin Finck if (pcf!=NULL)
581c2c66affSColin Finck IClassFactory_Release(pcf);
582c2c66affSColin Finck
583c2c66affSColin Finck return res;
584c2c66affSColin Finck }
585c2c66affSColin Finck
586c2c66affSColin Finck /******************************************************************************
587c2c66affSColin Finck * FileMoniker_BindToStorage
588c2c66affSColin Finck */
589c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_BindToStorage(IMoniker * iface,IBindCtx * pbc,IMoniker * pmkToLeft,REFIID riid,VOID ** ppvObject)590c2c66affSColin Finck FileMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
591c2c66affSColin Finck REFIID riid, VOID** ppvObject)
592c2c66affSColin Finck {
593c2c66affSColin Finck LPOLESTR filePath=0;
594c2c66affSColin Finck IStorage *pstg=0;
595c2c66affSColin Finck HRESULT res;
596c2c66affSColin Finck
597c2c66affSColin Finck TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvObject);
598c2c66affSColin Finck
599c2c66affSColin Finck if (pmkToLeft==NULL){
600c2c66affSColin Finck
601c2c66affSColin Finck if (IsEqualIID(&IID_IStorage, riid)){
602c2c66affSColin Finck
603c2c66affSColin Finck /* get the file name */
604c2c66affSColin Finck IMoniker_GetDisplayName(iface,pbc,pmkToLeft,&filePath);
605c2c66affSColin Finck
606c2c66affSColin Finck res=StgOpenStorage(filePath,NULL,STGM_READWRITE|STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
607c2c66affSColin Finck
608c2c66affSColin Finck if (SUCCEEDED(res))
609c2c66affSColin Finck *ppvObject=pstg;
610c2c66affSColin Finck
611c2c66affSColin Finck CoTaskMemFree(filePath);
612c2c66affSColin Finck }
613c2c66affSColin Finck else
614c2c66affSColin Finck if ( (IsEqualIID(&IID_IStream, riid)) || (IsEqualIID(&IID_ILockBytes, riid)) )
615c2c66affSColin Finck return E_FAIL;
616c2c66affSColin Finck else
617c2c66affSColin Finck return E_NOINTERFACE;
618c2c66affSColin Finck }
619c2c66affSColin Finck else {
620c2c66affSColin Finck
621c2c66affSColin Finck FIXME("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvObject);
622c2c66affSColin Finck
623c2c66affSColin Finck return E_NOTIMPL;
624c2c66affSColin Finck }
625c2c66affSColin Finck return res;
626c2c66affSColin Finck }
627c2c66affSColin Finck
628c2c66affSColin Finck /******************************************************************************
629c2c66affSColin Finck * FileMoniker_Reduce
630c2c66affSColin Finck ******************************************************************************/
631c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_Reduce(IMoniker * iface,IBindCtx * pbc,DWORD dwReduceHowFar,IMoniker ** ppmkToLeft,IMoniker ** ppmkReduced)632c2c66affSColin Finck FileMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
633c2c66affSColin Finck IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
634c2c66affSColin Finck {
635c2c66affSColin Finck TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
636c2c66affSColin Finck
637c2c66affSColin Finck if (ppmkReduced==NULL)
638c2c66affSColin Finck return E_POINTER;
639c2c66affSColin Finck
640c2c66affSColin Finck IMoniker_AddRef(iface);
641c2c66affSColin Finck
642c2c66affSColin Finck *ppmkReduced=iface;
643c2c66affSColin Finck
644c2c66affSColin Finck return MK_S_REDUCED_TO_SELF;
645c2c66affSColin Finck }
646c2c66affSColin Finck
free_stringtable(LPOLESTR * stringTable)647c2c66affSColin Finck static void free_stringtable(LPOLESTR *stringTable)
648c2c66affSColin Finck {
649c2c66affSColin Finck int i;
650c2c66affSColin Finck
651c2c66affSColin Finck for (i=0; stringTable[i]!=NULL; i++)
652c2c66affSColin Finck CoTaskMemFree(stringTable[i]);
653c2c66affSColin Finck CoTaskMemFree(stringTable);
654c2c66affSColin Finck }
655c2c66affSColin Finck
656c2c66affSColin Finck /******************************************************************************
657c2c66affSColin Finck * FileMoniker_ComposeWith
658c2c66affSColin Finck */
659c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_ComposeWith(IMoniker * iface,IMoniker * pmkRight,BOOL fOnlyIfNotGeneric,IMoniker ** ppmkComposite)660c2c66affSColin Finck FileMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
661c2c66affSColin Finck BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
662c2c66affSColin Finck {
663c2c66affSColin Finck HRESULT res;
664c2c66affSColin Finck LPOLESTR str1=0,str2=0,*strDec1=0,*strDec2=0,newStr=0;
665c2c66affSColin Finck static const WCHAR twoPoint[]={'.','.',0};
666c2c66affSColin Finck static const WCHAR bkSlash[]={'\\',0};
667c2c66affSColin Finck IBindCtx *bind=0;
668c2c66affSColin Finck int i=0,j=0,lastIdx1=0,lastIdx2=0;
669c2c66affSColin Finck DWORD mkSys;
670c2c66affSColin Finck
671c2c66affSColin Finck TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
672c2c66affSColin Finck
673c2c66affSColin Finck if (ppmkComposite==NULL)
674c2c66affSColin Finck return E_POINTER;
675c2c66affSColin Finck
676c2c66affSColin Finck if (pmkRight==NULL)
677c2c66affSColin Finck return E_INVALIDARG;
678c2c66affSColin Finck
679c2c66affSColin Finck *ppmkComposite=0;
680c2c66affSColin Finck
681c2c66affSColin Finck IMoniker_IsSystemMoniker(pmkRight,&mkSys);
682c2c66affSColin Finck
683c2c66affSColin Finck /* check if we have two FileMonikers to compose or not */
684c2c66affSColin Finck if(mkSys==MKSYS_FILEMONIKER){
685c2c66affSColin Finck
686c2c66affSColin Finck CreateBindCtx(0,&bind);
687c2c66affSColin Finck
688c2c66affSColin Finck IMoniker_GetDisplayName(iface,bind,NULL,&str1);
689c2c66affSColin Finck IMoniker_GetDisplayName(pmkRight,bind,NULL,&str2);
690c2c66affSColin Finck
691c2c66affSColin Finck /* decompose pathnames of the two monikers : (to prepare the path merge operation ) */
692c2c66affSColin Finck lastIdx1=FileMonikerImpl_DecomposePath(str1,&strDec1)-1;
693c2c66affSColin Finck lastIdx2=FileMonikerImpl_DecomposePath(str2,&strDec2)-1;
694c2c66affSColin Finck
695*0f5d91b7SAmine Khaldi if ((lastIdx1==-1 && lastIdx2>-1)||(lastIdx1==1 && wcscmp(strDec1[0],twoPoint)==0))
696c2c66affSColin Finck res = MK_E_SYNTAX;
697c2c66affSColin Finck else{
698*0f5d91b7SAmine Khaldi if(wcscmp(strDec1[lastIdx1],bkSlash)==0)
699c2c66affSColin Finck lastIdx1--;
700c2c66affSColin Finck
701c2c66affSColin Finck /* for each "..\" in the left of str2 remove the right element from str1 */
702*0f5d91b7SAmine Khaldi for(i=0; ( (lastIdx1>=0) && (strDec2[i]!=NULL) && (wcscmp(strDec2[i],twoPoint)==0) ); i+=2){
703c2c66affSColin Finck
704c2c66affSColin Finck lastIdx1-=2;
705c2c66affSColin Finck }
706c2c66affSColin Finck
707c2c66affSColin Finck /* the length of the composed path string is increased by the sum of the two paths' lengths */
708c2c66affSColin Finck newStr=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(lstrlenW(str1)+lstrlenW(str2)+1));
709c2c66affSColin Finck
710c2c66affSColin Finck if (newStr){
711c2c66affSColin Finck /* new path is the concatenation of the rest of str1 and str2 */
712c2c66affSColin Finck for(*newStr=0,j=0;j<=lastIdx1;j++)
713*0f5d91b7SAmine Khaldi lstrcatW(newStr,strDec1[j]);
714c2c66affSColin Finck
715*0f5d91b7SAmine Khaldi if ((strDec2[i]==NULL && lastIdx1>-1 && lastIdx2>-1) || wcscmp(strDec2[i],bkSlash)!=0)
716*0f5d91b7SAmine Khaldi lstrcatW(newStr,bkSlash);
717c2c66affSColin Finck
718c2c66affSColin Finck for(j=i;j<=lastIdx2;j++)
719*0f5d91b7SAmine Khaldi lstrcatW(newStr,strDec2[j]);
720c2c66affSColin Finck
721c2c66affSColin Finck /* create a new moniker with the new string */
722c2c66affSColin Finck res=CreateFileMoniker(newStr,ppmkComposite);
723c2c66affSColin Finck
724c2c66affSColin Finck /* free string memory used by this function */
725c2c66affSColin Finck HeapFree(GetProcessHeap(),0,newStr);
726c2c66affSColin Finck }
727c2c66affSColin Finck else res = E_OUTOFMEMORY;
728c2c66affSColin Finck }
729c2c66affSColin Finck
730c2c66affSColin Finck free_stringtable(strDec1);
731c2c66affSColin Finck free_stringtable(strDec2);
732c2c66affSColin Finck
733c2c66affSColin Finck CoTaskMemFree(str1);
734c2c66affSColin Finck CoTaskMemFree(str2);
735c2c66affSColin Finck
736c2c66affSColin Finck return res;
737c2c66affSColin Finck }
738c2c66affSColin Finck else if(mkSys==MKSYS_ANTIMONIKER){
739c2c66affSColin Finck
740c2c66affSColin Finck *ppmkComposite=NULL;
741c2c66affSColin Finck return S_OK;
742c2c66affSColin Finck }
743c2c66affSColin Finck else if (fOnlyIfNotGeneric){
744c2c66affSColin Finck
745c2c66affSColin Finck *ppmkComposite=NULL;
746c2c66affSColin Finck return MK_E_NEEDGENERIC;
747c2c66affSColin Finck }
748c2c66affSColin Finck else
749c2c66affSColin Finck
750c2c66affSColin Finck return CreateGenericComposite(iface,pmkRight,ppmkComposite);
751c2c66affSColin Finck }
752c2c66affSColin Finck
753c2c66affSColin Finck /******************************************************************************
754c2c66affSColin Finck * FileMoniker_Enum
755c2c66affSColin Finck */
756c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_Enum(IMoniker * iface,BOOL fForward,IEnumMoniker ** ppenumMoniker)757c2c66affSColin Finck FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
758c2c66affSColin Finck {
759c2c66affSColin Finck TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
760c2c66affSColin Finck
761c2c66affSColin Finck if (ppenumMoniker == NULL)
762c2c66affSColin Finck return E_POINTER;
763c2c66affSColin Finck
764c2c66affSColin Finck *ppenumMoniker = NULL;
765c2c66affSColin Finck
766c2c66affSColin Finck return S_OK;
767c2c66affSColin Finck }
768c2c66affSColin Finck
769c2c66affSColin Finck /******************************************************************************
770c2c66affSColin Finck * FileMoniker_IsEqual
771c2c66affSColin Finck */
772c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_IsEqual(IMoniker * iface,IMoniker * pmkOtherMoniker)773c2c66affSColin Finck FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
774c2c66affSColin Finck {
775c2c66affSColin Finck FileMonikerImpl *This = impl_from_IMoniker(iface);
776c2c66affSColin Finck CLSID clsid;
777c2c66affSColin Finck LPOLESTR filePath;
778c2c66affSColin Finck IBindCtx* bind;
779c2c66affSColin Finck HRESULT res;
780c2c66affSColin Finck
781c2c66affSColin Finck TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
782c2c66affSColin Finck
783c2c66affSColin Finck if (pmkOtherMoniker==NULL)
784c2c66affSColin Finck return S_FALSE;
785c2c66affSColin Finck
786c2c66affSColin Finck IMoniker_GetClassID(pmkOtherMoniker,&clsid);
787c2c66affSColin Finck
788c2c66affSColin Finck if (!IsEqualCLSID(&clsid,&CLSID_FileMoniker))
789c2c66affSColin Finck return S_FALSE;
790c2c66affSColin Finck
791c2c66affSColin Finck res = CreateBindCtx(0,&bind);
792c2c66affSColin Finck if (FAILED(res)) return res;
793c2c66affSColin Finck
794c2c66affSColin Finck res = S_FALSE;
795c2c66affSColin Finck if (SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&filePath))) {
796c2c66affSColin Finck if (!lstrcmpiW(filePath, This->filePathName))
797c2c66affSColin Finck res = S_OK;
798c2c66affSColin Finck CoTaskMemFree(filePath);
799c2c66affSColin Finck }
800c2c66affSColin Finck
801c2c66affSColin Finck IBindCtx_Release(bind);
802c2c66affSColin Finck return res;
803c2c66affSColin Finck }
804c2c66affSColin Finck
805c2c66affSColin Finck /******************************************************************************
806c2c66affSColin Finck * FileMoniker_Hash
807c2c66affSColin Finck */
808c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_Hash(IMoniker * iface,DWORD * pdwHash)809c2c66affSColin Finck FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
810c2c66affSColin Finck {
811c2c66affSColin Finck FileMonikerImpl *This = impl_from_IMoniker(iface);
812c2c66affSColin Finck int h = 0,i,skip,len;
813c2c66affSColin Finck int off = 0;
814c2c66affSColin Finck LPOLESTR val;
815c2c66affSColin Finck
816c2c66affSColin Finck if (pdwHash==NULL)
817c2c66affSColin Finck return E_POINTER;
818c2c66affSColin Finck
819c2c66affSColin Finck val = This->filePathName;
820c2c66affSColin Finck len = lstrlenW(val);
821c2c66affSColin Finck
822c2c66affSColin Finck if (len < 16) {
823c2c66affSColin Finck for (i = len ; i > 0; i--) {
824c2c66affSColin Finck h = (h * 37) + val[off++];
825c2c66affSColin Finck }
826c2c66affSColin Finck } else {
827c2c66affSColin Finck /* only sample some characters */
828c2c66affSColin Finck skip = len / 8;
829c2c66affSColin Finck for (i = len ; i > 0; i -= skip, off += skip) {
830c2c66affSColin Finck h = (h * 39) + val[off];
831c2c66affSColin Finck }
832c2c66affSColin Finck }
833c2c66affSColin Finck
834c2c66affSColin Finck *pdwHash=h;
835c2c66affSColin Finck
836c2c66affSColin Finck return S_OK;
837c2c66affSColin Finck }
838c2c66affSColin Finck
839c2c66affSColin Finck /******************************************************************************
840c2c66affSColin Finck * FileMoniker_IsRunning
841c2c66affSColin Finck */
842c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_IsRunning(IMoniker * iface,IBindCtx * pbc,IMoniker * pmkToLeft,IMoniker * pmkNewlyRunning)843c2c66affSColin Finck FileMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
844c2c66affSColin Finck IMoniker* pmkNewlyRunning)
845c2c66affSColin Finck {
846c2c66affSColin Finck IRunningObjectTable* rot;
847c2c66affSColin Finck HRESULT res;
848c2c66affSColin Finck
849c2c66affSColin Finck TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
850c2c66affSColin Finck
851c2c66affSColin Finck if ( (pmkNewlyRunning!=NULL) && (IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK) )
852c2c66affSColin Finck return S_OK;
853c2c66affSColin Finck
854c2c66affSColin Finck if (pbc==NULL)
855c2c66affSColin Finck return E_POINTER;
856c2c66affSColin Finck
857c2c66affSColin Finck res=IBindCtx_GetRunningObjectTable(pbc,&rot);
858c2c66affSColin Finck
859c2c66affSColin Finck if (FAILED(res))
860c2c66affSColin Finck return res;
861c2c66affSColin Finck
862c2c66affSColin Finck res = IRunningObjectTable_IsRunning(rot,iface);
863c2c66affSColin Finck
864c2c66affSColin Finck IRunningObjectTable_Release(rot);
865c2c66affSColin Finck
866c2c66affSColin Finck return res;
867c2c66affSColin Finck }
868c2c66affSColin Finck
869c2c66affSColin Finck /******************************************************************************
870c2c66affSColin Finck * FileMoniker_GetTimeOfLastChange
871c2c66affSColin Finck ******************************************************************************/
872c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_GetTimeOfLastChange(IMoniker * iface,IBindCtx * pbc,IMoniker * pmkToLeft,FILETIME * pFileTime)873c2c66affSColin Finck FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
874c2c66affSColin Finck IMoniker* pmkToLeft, FILETIME* pFileTime)
875c2c66affSColin Finck {
876c2c66affSColin Finck FileMonikerImpl *This = impl_from_IMoniker(iface);
877c2c66affSColin Finck IRunningObjectTable* rot;
878c2c66affSColin Finck HRESULT res;
879c2c66affSColin Finck WIN32_FILE_ATTRIBUTE_DATA info;
880c2c66affSColin Finck
881c2c66affSColin Finck TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pFileTime);
882c2c66affSColin Finck
883c2c66affSColin Finck if (pFileTime==NULL)
884c2c66affSColin Finck return E_POINTER;
885c2c66affSColin Finck
886c2c66affSColin Finck if (pmkToLeft!=NULL)
887c2c66affSColin Finck return E_INVALIDARG;
888c2c66affSColin Finck
889c2c66affSColin Finck res=IBindCtx_GetRunningObjectTable(pbc,&rot);
890c2c66affSColin Finck
891c2c66affSColin Finck if (FAILED(res))
892c2c66affSColin Finck return res;
893c2c66affSColin Finck
894c2c66affSColin Finck res= IRunningObjectTable_GetTimeOfLastChange(rot,iface,pFileTime);
895c2c66affSColin Finck
896c2c66affSColin Finck if (FAILED(res)){ /* the moniker is not registered */
897c2c66affSColin Finck
898c2c66affSColin Finck if (!GetFileAttributesExW(This->filePathName,GetFileExInfoStandard,&info))
899c2c66affSColin Finck return MK_E_NOOBJECT;
900c2c66affSColin Finck
901c2c66affSColin Finck *pFileTime=info.ftLastWriteTime;
902c2c66affSColin Finck }
903c2c66affSColin Finck
904c2c66affSColin Finck return S_OK;
905c2c66affSColin Finck }
906c2c66affSColin Finck
907c2c66affSColin Finck /******************************************************************************
908c2c66affSColin Finck * FileMoniker_Inverse
909c2c66affSColin Finck */
910c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_Inverse(IMoniker * iface,IMoniker ** ppmk)911c2c66affSColin Finck FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
912c2c66affSColin Finck {
913c2c66affSColin Finck TRACE("(%p,%p)\n",iface,ppmk);
914c2c66affSColin Finck
915c2c66affSColin Finck return CreateAntiMoniker(ppmk);
916c2c66affSColin Finck }
917c2c66affSColin Finck
918c2c66affSColin Finck /******************************************************************************
919c2c66affSColin Finck * FileMoniker_CommonPrefixWith
920c2c66affSColin Finck */
921c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_CommonPrefixWith(IMoniker * iface,IMoniker * pmkOther,IMoniker ** ppmkPrefix)922c2c66affSColin Finck FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
923c2c66affSColin Finck {
924c2c66affSColin Finck
925c2c66affSColin Finck LPOLESTR pathThis = NULL, pathOther = NULL, *stringTable1 = NULL;
926c2c66affSColin Finck LPOLESTR *stringTable2 = NULL, commonPath = NULL;
927c2c66affSColin Finck IBindCtx *bindctx;
928c2c66affSColin Finck DWORD mkSys;
929c2c66affSColin Finck ULONG nb1,nb2,i,sameIdx;
930c2c66affSColin Finck BOOL machineNameCase = FALSE;
931c2c66affSColin Finck HRESULT ret;
932c2c66affSColin Finck
933c2c66affSColin Finck if (ppmkPrefix==NULL)
934c2c66affSColin Finck return E_POINTER;
935c2c66affSColin Finck
936c2c66affSColin Finck if (pmkOther==NULL)
937c2c66affSColin Finck return E_INVALIDARG;
938c2c66affSColin Finck
939c2c66affSColin Finck *ppmkPrefix=0;
940c2c66affSColin Finck
941c2c66affSColin Finck /* check if we have the same type of moniker */
942c2c66affSColin Finck IMoniker_IsSystemMoniker(pmkOther,&mkSys);
943c2c66affSColin Finck if (mkSys != MKSYS_FILEMONIKER)
944c2c66affSColin Finck return MonikerCommonPrefixWith(iface, pmkOther, ppmkPrefix);
945c2c66affSColin Finck
946c2c66affSColin Finck ret = CreateBindCtx(0, &bindctx);
947c2c66affSColin Finck if (FAILED(ret))
948c2c66affSColin Finck return ret;
949c2c66affSColin Finck
950c2c66affSColin Finck /* create a string based on common part of the two paths */
951c2c66affSColin Finck ret = IMoniker_GetDisplayName(iface, bindctx, NULL, &pathThis);
952c2c66affSColin Finck if (FAILED(ret))
953c2c66affSColin Finck goto failed;
954c2c66affSColin Finck
955c2c66affSColin Finck ret = IMoniker_GetDisplayName(pmkOther, bindctx, NULL, &pathOther);
956c2c66affSColin Finck if (FAILED(ret))
957c2c66affSColin Finck goto failed;
958c2c66affSColin Finck
959c2c66affSColin Finck nb1 = FileMonikerImpl_DecomposePath(pathThis, &stringTable1);
960c2c66affSColin Finck if (FAILED(nb1)) {
961c2c66affSColin Finck ret = nb1;
962c2c66affSColin Finck goto failed;
963c2c66affSColin Finck }
964c2c66affSColin Finck
965c2c66affSColin Finck nb2 = FileMonikerImpl_DecomposePath(pathOther, &stringTable2);
966c2c66affSColin Finck if (FAILED(nb2)) {
967c2c66affSColin Finck ret = nb2;
968c2c66affSColin Finck goto failed;
969c2c66affSColin Finck }
970c2c66affSColin Finck
971c2c66affSColin Finck if (nb1 == 0 || nb2 == 0) {
972c2c66affSColin Finck ret = MK_E_NOPREFIX;
973c2c66affSColin Finck goto failed;
974c2c66affSColin Finck }
975c2c66affSColin Finck
976c2c66affSColin Finck commonPath = CoTaskMemAlloc(sizeof(WCHAR)*(min(lstrlenW(pathThis),lstrlenW(pathOther))+1));
977c2c66affSColin Finck if (!commonPath) {
978c2c66affSColin Finck ret = E_OUTOFMEMORY;
979c2c66affSColin Finck goto failed;
980c2c66affSColin Finck }
981c2c66affSColin Finck
982c2c66affSColin Finck *commonPath = 0;
983c2c66affSColin Finck for(sameIdx=0; ( (stringTable1[sameIdx]!=NULL) &&
984c2c66affSColin Finck (stringTable2[sameIdx]!=NULL) &&
985c2c66affSColin Finck (lstrcmpiW(stringTable1[sameIdx],stringTable2[sameIdx])==0)); sameIdx++);
986c2c66affSColin Finck
987c2c66affSColin Finck if (sameIdx > 1 && *stringTable1[0]=='\\' && *stringTable2[1]=='\\'){
988c2c66affSColin Finck machineNameCase = TRUE;
989c2c66affSColin Finck
990c2c66affSColin Finck for(i=2;i<sameIdx;i++)
991c2c66affSColin Finck if( (*stringTable1[i]=='\\') && (i+1 < sameIdx) && (*stringTable1[i+1]=='\\') ){
992c2c66affSColin Finck machineNameCase = FALSE;
993c2c66affSColin Finck break;
994c2c66affSColin Finck }
995c2c66affSColin Finck }
996c2c66affSColin Finck
997c2c66affSColin Finck if (machineNameCase && *stringTable1[sameIdx-1]=='\\')
998c2c66affSColin Finck sameIdx--;
999c2c66affSColin Finck
1000c2c66affSColin Finck if (machineNameCase && (sameIdx<=3) && (nb1 > 3 || nb2 > 3) )
1001c2c66affSColin Finck ret = MK_E_NOPREFIX;
1002c2c66affSColin Finck else
1003c2c66affSColin Finck {
1004c2c66affSColin Finck for (i = 0; i < sameIdx; i++)
1005*0f5d91b7SAmine Khaldi lstrcatW(commonPath,stringTable1[i]);
1006c2c66affSColin Finck ret = CreateFileMoniker(commonPath, ppmkPrefix);
1007c2c66affSColin Finck }
1008c2c66affSColin Finck
1009c2c66affSColin Finck failed:
1010c2c66affSColin Finck IBindCtx_Release(bindctx);
1011c2c66affSColin Finck CoTaskMemFree(pathThis);
1012c2c66affSColin Finck CoTaskMemFree(pathOther);
1013c2c66affSColin Finck CoTaskMemFree(commonPath);
1014c2c66affSColin Finck if (stringTable1) free_stringtable(stringTable1);
1015c2c66affSColin Finck if (stringTable2) free_stringtable(stringTable2);
1016c2c66affSColin Finck
1017c2c66affSColin Finck return ret;
1018c2c66affSColin Finck }
1019c2c66affSColin Finck
1020c2c66affSColin Finck /******************************************************************************
1021c2c66affSColin Finck * DecomposePath (local function)
1022c2c66affSColin Finck */
FileMonikerImpl_DecomposePath(LPCOLESTR str,LPOLESTR ** stringTable)1023c2c66affSColin Finck int FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable)
1024c2c66affSColin Finck {
1025c2c66affSColin Finck static const WCHAR bSlash[] = {'\\',0};
1026c2c66affSColin Finck LPOLESTR word;
1027c2c66affSColin Finck int i=0,j,tabIndex=0, ret=0;
1028c2c66affSColin Finck LPOLESTR *strgtable ;
1029c2c66affSColin Finck
1030c2c66affSColin Finck int len=lstrlenW(str);
1031c2c66affSColin Finck
1032c2c66affSColin Finck TRACE("%s, %p\n", debugstr_w(str), *stringTable);
1033c2c66affSColin Finck
1034c2c66affSColin Finck strgtable = CoTaskMemAlloc((len + 1)*sizeof(*strgtable));
1035c2c66affSColin Finck
1036c2c66affSColin Finck if (strgtable==NULL)
1037c2c66affSColin Finck return E_OUTOFMEMORY;
1038c2c66affSColin Finck
1039c2c66affSColin Finck word = CoTaskMemAlloc((len + 1)*sizeof(WCHAR));
1040c2c66affSColin Finck
1041c2c66affSColin Finck if (word==NULL)
1042c2c66affSColin Finck {
1043c2c66affSColin Finck ret = E_OUTOFMEMORY;
1044c2c66affSColin Finck goto lend;
1045c2c66affSColin Finck }
1046c2c66affSColin Finck
1047c2c66affSColin Finck while(str[i]!=0){
1048c2c66affSColin Finck
1049c2c66affSColin Finck if(str[i]==bSlash[0]){
1050c2c66affSColin Finck
1051c2c66affSColin Finck strgtable[tabIndex]=CoTaskMemAlloc(2*sizeof(WCHAR));
1052c2c66affSColin Finck
1053c2c66affSColin Finck if (strgtable[tabIndex]==NULL)
1054c2c66affSColin Finck {
1055c2c66affSColin Finck ret = E_OUTOFMEMORY;
1056c2c66affSColin Finck goto lend;
1057c2c66affSColin Finck }
1058c2c66affSColin Finck
1059*0f5d91b7SAmine Khaldi lstrcpyW(strgtable[tabIndex++],bSlash);
1060c2c66affSColin Finck
1061c2c66affSColin Finck i++;
1062c2c66affSColin Finck
1063c2c66affSColin Finck }
1064c2c66affSColin Finck else {
1065c2c66affSColin Finck
1066c2c66affSColin Finck for(j=0; str[i]!=0 && str[i]!=bSlash[0] ; i++,j++)
1067c2c66affSColin Finck word[j]=str[i];
1068c2c66affSColin Finck
1069c2c66affSColin Finck word[j]=0;
1070c2c66affSColin Finck
1071c2c66affSColin Finck strgtable[tabIndex]=CoTaskMemAlloc(sizeof(WCHAR)*(j+1));
1072c2c66affSColin Finck
1073c2c66affSColin Finck if (strgtable[tabIndex]==NULL)
1074c2c66affSColin Finck {
1075c2c66affSColin Finck ret = E_OUTOFMEMORY;
1076c2c66affSColin Finck goto lend;
1077c2c66affSColin Finck }
1078c2c66affSColin Finck
1079*0f5d91b7SAmine Khaldi lstrcpyW(strgtable[tabIndex++],word);
1080c2c66affSColin Finck }
1081c2c66affSColin Finck }
1082c2c66affSColin Finck strgtable[tabIndex]=NULL;
1083c2c66affSColin Finck
1084c2c66affSColin Finck *stringTable=strgtable;
1085c2c66affSColin Finck
1086c2c66affSColin Finck ret = tabIndex;
1087c2c66affSColin Finck
1088c2c66affSColin Finck lend:
1089c2c66affSColin Finck if (ret < 0)
1090c2c66affSColin Finck {
1091c2c66affSColin Finck for (i = 0; i < tabIndex; i++)
1092c2c66affSColin Finck CoTaskMemFree(strgtable[i]);
1093c2c66affSColin Finck
1094c2c66affSColin Finck CoTaskMemFree(strgtable);
1095c2c66affSColin Finck }
1096c2c66affSColin Finck
1097c2c66affSColin Finck CoTaskMemFree(word);
1098c2c66affSColin Finck
1099c2c66affSColin Finck return ret;
1100c2c66affSColin Finck }
1101c2c66affSColin Finck
1102c2c66affSColin Finck /******************************************************************************
1103c2c66affSColin Finck * FileMoniker_RelativePathTo
1104c2c66affSColin Finck */
1105c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_RelativePathTo(IMoniker * iface,IMoniker * pmOther,IMoniker ** ppmkRelPath)1106c2c66affSColin Finck FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
1107c2c66affSColin Finck {
1108c2c66affSColin Finck IBindCtx *bind;
1109c2c66affSColin Finck HRESULT res;
1110c2c66affSColin Finck LPOLESTR str1=0,str2=0,*tabStr1=0,*tabStr2=0,relPath=0;
1111c2c66affSColin Finck DWORD len1=0,len2=0,sameIdx=0,j=0;
1112c2c66affSColin Finck static const WCHAR back[] ={'.','.','\\',0};
1113c2c66affSColin Finck
1114c2c66affSColin Finck TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
1115c2c66affSColin Finck
1116c2c66affSColin Finck if (ppmkRelPath==NULL)
1117c2c66affSColin Finck return E_POINTER;
1118c2c66affSColin Finck
1119c2c66affSColin Finck if (pmOther==NULL)
1120c2c66affSColin Finck return E_INVALIDARG;
1121c2c66affSColin Finck
1122c2c66affSColin Finck res=CreateBindCtx(0,&bind);
1123c2c66affSColin Finck if (FAILED(res))
1124c2c66affSColin Finck return res;
1125c2c66affSColin Finck
1126c2c66affSColin Finck res=IMoniker_GetDisplayName(iface,bind,NULL,&str1);
1127c2c66affSColin Finck if (FAILED(res))
1128c2c66affSColin Finck return res;
1129c2c66affSColin Finck res=IMoniker_GetDisplayName(pmOther,bind,NULL,&str2);
1130c2c66affSColin Finck if (FAILED(res))
1131c2c66affSColin Finck return res;
1132c2c66affSColin Finck
1133c2c66affSColin Finck len1=FileMonikerImpl_DecomposePath(str1,&tabStr1);
1134c2c66affSColin Finck if (FAILED(len1))
1135c2c66affSColin Finck return E_OUTOFMEMORY;
1136c2c66affSColin Finck len2=FileMonikerImpl_DecomposePath(str2,&tabStr2);
1137c2c66affSColin Finck
1138c2c66affSColin Finck if (FAILED(len2))
1139c2c66affSColin Finck {
1140c2c66affSColin Finck free_stringtable(tabStr1);
1141c2c66affSColin Finck return E_OUTOFMEMORY;
1142c2c66affSColin Finck }
1143c2c66affSColin Finck
1144c2c66affSColin Finck /* count the number of similar items from the begin of the two paths */
1145c2c66affSColin Finck for(sameIdx=0; ( (tabStr1[sameIdx]!=NULL) &&
1146c2c66affSColin Finck (tabStr2[sameIdx]!=NULL) &&
1147c2c66affSColin Finck (lstrcmpiW(tabStr1[sameIdx],tabStr2[sameIdx])==0)); sameIdx++);
1148c2c66affSColin Finck
1149c2c66affSColin Finck /* begin the construction of relativePath */
1150c2c66affSColin Finck /* if the two paths have a consecutive similar item from the begin ! the relativePath will be composed */
1151c2c66affSColin Finck /* by "..\\" in the begin */
1152c2c66affSColin Finck relPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(1+lstrlenW(str1)+lstrlenW(str2)));
1153c2c66affSColin Finck
1154c2c66affSColin Finck *relPath=0;
1155c2c66affSColin Finck
1156c2c66affSColin Finck if (len2>0 && !(len1==1 && len2==1 && sameIdx==0))
1157c2c66affSColin Finck for(j=sameIdx;(tabStr1[j] != NULL); j++)
1158c2c66affSColin Finck if (*tabStr1[j]!='\\')
1159*0f5d91b7SAmine Khaldi lstrcatW(relPath,back);
1160c2c66affSColin Finck
1161c2c66affSColin Finck /* add items of the second path (similar items with the first path are not included) to the relativePath */
1162c2c66affSColin Finck for(j=sameIdx;tabStr2[j]!=NULL;j++)
1163*0f5d91b7SAmine Khaldi lstrcatW(relPath,tabStr2[j]);
1164c2c66affSColin Finck
1165c2c66affSColin Finck res=CreateFileMoniker(relPath,ppmkRelPath);
1166c2c66affSColin Finck
1167c2c66affSColin Finck free_stringtable(tabStr1);
1168c2c66affSColin Finck free_stringtable(tabStr2);
1169c2c66affSColin Finck CoTaskMemFree(str1);
1170c2c66affSColin Finck CoTaskMemFree(str2);
1171c2c66affSColin Finck HeapFree(GetProcessHeap(),0,relPath);
1172c2c66affSColin Finck
1173c2c66affSColin Finck if (len1==0 || len2==0 || (len1==1 && len2==1 && sameIdx==0))
1174c2c66affSColin Finck return MK_S_HIM;
1175c2c66affSColin Finck
1176c2c66affSColin Finck return res;
1177c2c66affSColin Finck }
1178c2c66affSColin Finck
1179c2c66affSColin Finck /******************************************************************************
1180c2c66affSColin Finck * FileMoniker_GetDisplayName
1181c2c66affSColin Finck */
1182c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_GetDisplayName(IMoniker * iface,IBindCtx * pbc,IMoniker * pmkToLeft,LPOLESTR * ppszDisplayName)1183c2c66affSColin Finck FileMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
1184c2c66affSColin Finck IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
1185c2c66affSColin Finck {
1186c2c66affSColin Finck FileMonikerImpl *This = impl_from_IMoniker(iface);
1187c2c66affSColin Finck int len=lstrlenW(This->filePathName);
1188c2c66affSColin Finck
1189c2c66affSColin Finck TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1190c2c66affSColin Finck
1191c2c66affSColin Finck if (ppszDisplayName==NULL)
1192c2c66affSColin Finck return E_POINTER;
1193c2c66affSColin Finck
1194c2c66affSColin Finck if (pmkToLeft!=NULL)
1195c2c66affSColin Finck return E_INVALIDARG;
1196c2c66affSColin Finck
1197c2c66affSColin Finck *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
1198c2c66affSColin Finck if (*ppszDisplayName==NULL)
1199c2c66affSColin Finck return E_OUTOFMEMORY;
1200c2c66affSColin Finck
1201*0f5d91b7SAmine Khaldi lstrcpyW(*ppszDisplayName,This->filePathName);
1202c2c66affSColin Finck
1203c2c66affSColin Finck TRACE("-- %s\n", debugstr_w(*ppszDisplayName));
1204c2c66affSColin Finck
1205c2c66affSColin Finck return S_OK;
1206c2c66affSColin Finck }
1207c2c66affSColin Finck
1208c2c66affSColin Finck /******************************************************************************
1209c2c66affSColin Finck * FileMoniker_ParseDisplayName
1210c2c66affSColin Finck */
1211c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_ParseDisplayName(IMoniker * iface,IBindCtx * pbc,IMoniker * pmkToLeft,LPOLESTR pszDisplayName,ULONG * pchEaten,IMoniker ** ppmkOut)1212c2c66affSColin Finck FileMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
1213c2c66affSColin Finck LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
1214c2c66affSColin Finck {
1215c2c66affSColin Finck FIXME("(%p,%p,%p,%p,%p,%p),stub!\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
1216c2c66affSColin Finck return E_NOTIMPL;
1217c2c66affSColin Finck }
1218c2c66affSColin Finck
1219c2c66affSColin Finck /******************************************************************************
1220c2c66affSColin Finck * FileMoniker_IsSystemMoniker
1221c2c66affSColin Finck */
1222c2c66affSColin Finck static HRESULT WINAPI
FileMonikerImpl_IsSystemMoniker(IMoniker * iface,DWORD * pwdMksys)1223c2c66affSColin Finck FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1224c2c66affSColin Finck {
1225c2c66affSColin Finck TRACE("(%p,%p)\n",iface,pwdMksys);
1226c2c66affSColin Finck
1227c2c66affSColin Finck if (!pwdMksys)
1228c2c66affSColin Finck return E_POINTER;
1229c2c66affSColin Finck
1230c2c66affSColin Finck (*pwdMksys)=MKSYS_FILEMONIKER;
1231c2c66affSColin Finck
1232c2c66affSColin Finck return S_OK;
1233c2c66affSColin Finck }
1234c2c66affSColin Finck
1235c2c66affSColin Finck /*******************************************************************************
1236c2c66affSColin Finck * FileMonikerIROTData_QueryInterface
1237c2c66affSColin Finck */
1238c2c66affSColin Finck static HRESULT WINAPI
FileMonikerROTDataImpl_QueryInterface(IROTData * iface,REFIID riid,VOID ** ppvObject)1239c2c66affSColin Finck FileMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1240c2c66affSColin Finck {
1241c2c66affSColin Finck
1242c2c66affSColin Finck FileMonikerImpl *This = impl_from_IROTData(iface);
1243c2c66affSColin Finck
1244c2c66affSColin Finck TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
1245c2c66affSColin Finck
1246c2c66affSColin Finck return FileMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject);
1247c2c66affSColin Finck }
1248c2c66affSColin Finck
1249c2c66affSColin Finck /***********************************************************************
1250c2c66affSColin Finck * FileMonikerIROTData_AddRef
1251c2c66affSColin Finck */
1252c2c66affSColin Finck static ULONG WINAPI
FileMonikerROTDataImpl_AddRef(IROTData * iface)1253c2c66affSColin Finck FileMonikerROTDataImpl_AddRef(IROTData *iface)
1254c2c66affSColin Finck {
1255c2c66affSColin Finck FileMonikerImpl *This = impl_from_IROTData(iface);
1256c2c66affSColin Finck
1257c2c66affSColin Finck TRACE("(%p)\n",This);
1258c2c66affSColin Finck
1259c2c66affSColin Finck return IMoniker_AddRef(&This->IMoniker_iface);
1260c2c66affSColin Finck }
1261c2c66affSColin Finck
1262c2c66affSColin Finck /***********************************************************************
1263c2c66affSColin Finck * FileMonikerIROTData_Release
1264c2c66affSColin Finck */
1265c2c66affSColin Finck static ULONG WINAPI
FileMonikerROTDataImpl_Release(IROTData * iface)1266c2c66affSColin Finck FileMonikerROTDataImpl_Release(IROTData* iface)
1267c2c66affSColin Finck {
1268c2c66affSColin Finck FileMonikerImpl *This = impl_from_IROTData(iface);
1269c2c66affSColin Finck
1270c2c66affSColin Finck TRACE("(%p)\n",This);
1271c2c66affSColin Finck
1272c2c66affSColin Finck return FileMonikerImpl_Release(&This->IMoniker_iface);
1273c2c66affSColin Finck }
1274c2c66affSColin Finck
1275c2c66affSColin Finck /******************************************************************************
1276c2c66affSColin Finck * FileMonikerIROTData_GetComparisonData
1277c2c66affSColin Finck */
1278c2c66affSColin Finck static HRESULT WINAPI
FileMonikerROTDataImpl_GetComparisonData(IROTData * iface,BYTE * pbData,ULONG cbMax,ULONG * pcbData)1279c2c66affSColin Finck FileMonikerROTDataImpl_GetComparisonData(IROTData* iface, BYTE* pbData,
1280c2c66affSColin Finck ULONG cbMax, ULONG* pcbData)
1281c2c66affSColin Finck {
1282c2c66affSColin Finck FileMonikerImpl *This = impl_from_IROTData(iface);
1283*0f5d91b7SAmine Khaldi int len = lstrlenW(This->filePathName)+1;
1284c2c66affSColin Finck int i;
1285c2c66affSColin Finck LPWSTR pszFileName;
1286c2c66affSColin Finck
1287c2c66affSColin Finck TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData);
1288c2c66affSColin Finck
1289c2c66affSColin Finck *pcbData = sizeof(CLSID) + len * sizeof(WCHAR);
1290c2c66affSColin Finck if (cbMax < *pcbData)
1291c2c66affSColin Finck return E_OUTOFMEMORY;
1292c2c66affSColin Finck
1293c2c66affSColin Finck memcpy(pbData, &CLSID_FileMoniker, sizeof(CLSID));
1294c2c66affSColin Finck pszFileName = (LPWSTR)(pbData+sizeof(CLSID));
1295c2c66affSColin Finck for (i = 0; i < len; i++)
1296*0f5d91b7SAmine Khaldi pszFileName[i] = towupper(This->filePathName[i]);
1297c2c66affSColin Finck
1298c2c66affSColin Finck return S_OK;
1299c2c66affSColin Finck }
1300c2c66affSColin Finck
1301c2c66affSColin Finck /*
1302c2c66affSColin Finck * Virtual function table for the FileMonikerImpl class which include IPersist,
1303c2c66affSColin Finck * IPersistStream and IMoniker functions.
1304c2c66affSColin Finck */
1305c2c66affSColin Finck static const IMonikerVtbl VT_FileMonikerImpl =
1306c2c66affSColin Finck {
1307c2c66affSColin Finck FileMonikerImpl_QueryInterface,
1308c2c66affSColin Finck FileMonikerImpl_AddRef,
1309c2c66affSColin Finck FileMonikerImpl_Release,
1310c2c66affSColin Finck FileMonikerImpl_GetClassID,
1311c2c66affSColin Finck FileMonikerImpl_IsDirty,
1312c2c66affSColin Finck FileMonikerImpl_Load,
1313c2c66affSColin Finck FileMonikerImpl_Save,
1314c2c66affSColin Finck FileMonikerImpl_GetSizeMax,
1315c2c66affSColin Finck FileMonikerImpl_BindToObject,
1316c2c66affSColin Finck FileMonikerImpl_BindToStorage,
1317c2c66affSColin Finck FileMonikerImpl_Reduce,
1318c2c66affSColin Finck FileMonikerImpl_ComposeWith,
1319c2c66affSColin Finck FileMonikerImpl_Enum,
1320c2c66affSColin Finck FileMonikerImpl_IsEqual,
1321c2c66affSColin Finck FileMonikerImpl_Hash,
1322c2c66affSColin Finck FileMonikerImpl_IsRunning,
1323c2c66affSColin Finck FileMonikerImpl_GetTimeOfLastChange,
1324c2c66affSColin Finck FileMonikerImpl_Inverse,
1325c2c66affSColin Finck FileMonikerImpl_CommonPrefixWith,
1326c2c66affSColin Finck FileMonikerImpl_RelativePathTo,
1327c2c66affSColin Finck FileMonikerImpl_GetDisplayName,
1328c2c66affSColin Finck FileMonikerImpl_ParseDisplayName,
1329c2c66affSColin Finck FileMonikerImpl_IsSystemMoniker
1330c2c66affSColin Finck };
1331c2c66affSColin Finck
1332c2c66affSColin Finck /* Virtual function table for the IROTData class. */
1333c2c66affSColin Finck static const IROTDataVtbl VT_ROTDataImpl =
1334c2c66affSColin Finck {
1335c2c66affSColin Finck FileMonikerROTDataImpl_QueryInterface,
1336c2c66affSColin Finck FileMonikerROTDataImpl_AddRef,
1337c2c66affSColin Finck FileMonikerROTDataImpl_Release,
1338c2c66affSColin Finck FileMonikerROTDataImpl_GetComparisonData
1339c2c66affSColin Finck };
1340c2c66affSColin Finck
1341c2c66affSColin Finck /******************************************************************************
1342c2c66affSColin Finck * FileMoniker_Construct (local function)
1343c2c66affSColin Finck */
FileMonikerImpl_Construct(FileMonikerImpl * This,LPCOLESTR lpszPathName)1344c2c66affSColin Finck static HRESULT FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPathName)
1345c2c66affSColin Finck {
1346c2c66affSColin Finck int nb=0,i;
1347c2c66affSColin Finck int sizeStr=lstrlenW(lpszPathName);
1348c2c66affSColin Finck LPOLESTR *tabStr=0;
1349c2c66affSColin Finck static const WCHAR twoPoint[]={'.','.',0};
1350c2c66affSColin Finck static const WCHAR bkSlash[]={'\\',0};
1351c2c66affSColin Finck BOOL addBkSlash;
1352c2c66affSColin Finck
1353c2c66affSColin Finck TRACE("(%p,%s)\n",This,debugstr_w(lpszPathName));
1354c2c66affSColin Finck
1355c2c66affSColin Finck /* Initialize the virtual function table. */
1356c2c66affSColin Finck This->IMoniker_iface.lpVtbl = &VT_FileMonikerImpl;
1357c2c66affSColin Finck This->IROTData_iface.lpVtbl = &VT_ROTDataImpl;
1358c2c66affSColin Finck This->ref = 0;
1359c2c66affSColin Finck This->pMarshal = NULL;
1360c2c66affSColin Finck
1361c2c66affSColin Finck This->filePathName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr+1));
1362c2c66affSColin Finck
1363c2c66affSColin Finck if (This->filePathName==NULL)
1364c2c66affSColin Finck return E_OUTOFMEMORY;
1365c2c66affSColin Finck
1366*0f5d91b7SAmine Khaldi lstrcpyW(This->filePathName,lpszPathName);
1367c2c66affSColin Finck
1368c2c66affSColin Finck nb=FileMonikerImpl_DecomposePath(This->filePathName,&tabStr);
1369c2c66affSColin Finck
1370c2c66affSColin Finck if (nb > 0 ){
1371c2c66affSColin Finck
1372c2c66affSColin Finck addBkSlash = TRUE;
1373*0f5d91b7SAmine Khaldi if (wcscmp(tabStr[0],twoPoint)!=0)
1374c2c66affSColin Finck addBkSlash = FALSE;
1375c2c66affSColin Finck else
1376c2c66affSColin Finck for(i=0;i<nb;i++){
1377c2c66affSColin Finck
1378*0f5d91b7SAmine Khaldi if ( (wcscmp(tabStr[i],twoPoint)!=0) && (wcscmp(tabStr[i],bkSlash)!=0) ){
1379c2c66affSColin Finck addBkSlash = FALSE;
1380c2c66affSColin Finck break;
1381c2c66affSColin Finck }
1382c2c66affSColin Finck else
1383c2c66affSColin Finck
1384*0f5d91b7SAmine Khaldi if (wcscmp(tabStr[i],bkSlash)==0 && i<nb-1 && wcscmp(tabStr[i+1],bkSlash)==0){
1385c2c66affSColin Finck *tabStr[i]=0;
1386c2c66affSColin Finck sizeStr--;
1387c2c66affSColin Finck addBkSlash = FALSE;
1388c2c66affSColin Finck break;
1389c2c66affSColin Finck }
1390c2c66affSColin Finck }
1391c2c66affSColin Finck
1392*0f5d91b7SAmine Khaldi if (wcscmp(tabStr[nb-1],bkSlash)==0)
1393c2c66affSColin Finck addBkSlash = FALSE;
1394c2c66affSColin Finck
1395c2c66affSColin Finck This->filePathName=HeapReAlloc(GetProcessHeap(),0,This->filePathName,(sizeStr+1)*sizeof(WCHAR));
1396c2c66affSColin Finck
1397c2c66affSColin Finck *This->filePathName=0;
1398c2c66affSColin Finck
1399c2c66affSColin Finck for(i=0;tabStr[i]!=NULL;i++)
1400*0f5d91b7SAmine Khaldi lstrcatW(This->filePathName,tabStr[i]);
1401c2c66affSColin Finck
1402c2c66affSColin Finck if (addBkSlash)
1403*0f5d91b7SAmine Khaldi lstrcatW(This->filePathName,bkSlash);
1404c2c66affSColin Finck }
1405c2c66affSColin Finck
1406c2c66affSColin Finck free_stringtable(tabStr);
1407c2c66affSColin Finck
1408c2c66affSColin Finck return S_OK;
1409c2c66affSColin Finck }
1410c2c66affSColin Finck
1411c2c66affSColin Finck /******************************************************************************
1412c2c66affSColin Finck * CreateFileMoniker (OLE32.@)
1413c2c66affSColin Finck ******************************************************************************/
CreateFileMoniker(LPCOLESTR lpszPathName,IMoniker ** ppmk)1414c2c66affSColin Finck HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, IMoniker **ppmk)
1415c2c66affSColin Finck {
1416c2c66affSColin Finck FileMonikerImpl* newFileMoniker;
1417c2c66affSColin Finck HRESULT hr;
1418c2c66affSColin Finck
1419c2c66affSColin Finck TRACE("(%s,%p)\n",debugstr_w(lpszPathName),ppmk);
1420c2c66affSColin Finck
1421c2c66affSColin Finck if (!ppmk)
1422c2c66affSColin Finck return E_POINTER;
1423c2c66affSColin Finck
1424c2c66affSColin Finck if(!lpszPathName)
1425c2c66affSColin Finck return MK_E_SYNTAX;
1426c2c66affSColin Finck
1427c2c66affSColin Finck *ppmk=NULL;
1428c2c66affSColin Finck
1429c2c66affSColin Finck newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl));
1430c2c66affSColin Finck
1431c2c66affSColin Finck if (!newFileMoniker)
1432c2c66affSColin Finck return E_OUTOFMEMORY;
1433c2c66affSColin Finck
1434c2c66affSColin Finck hr = FileMonikerImpl_Construct(newFileMoniker,lpszPathName);
1435c2c66affSColin Finck
1436c2c66affSColin Finck if (SUCCEEDED(hr))
1437c2c66affSColin Finck hr = IMoniker_QueryInterface(&newFileMoniker->IMoniker_iface,&IID_IMoniker,(void**)ppmk);
1438c2c66affSColin Finck else
1439c2c66affSColin Finck HeapFree(GetProcessHeap(),0,newFileMoniker);
1440c2c66affSColin Finck
1441c2c66affSColin Finck return hr;
1442c2c66affSColin Finck }
1443c2c66affSColin Finck
1444c2c66affSColin Finck /* find a character from a set in reverse without the string having to be null-terminated */
memrpbrkW(const WCHAR * ptr,size_t n,const WCHAR * accept)1445c2c66affSColin Finck static inline WCHAR *memrpbrkW(const WCHAR *ptr, size_t n, const WCHAR *accept)
1446c2c66affSColin Finck {
1447c2c66affSColin Finck const WCHAR *end, *ret = NULL;
1448*0f5d91b7SAmine Khaldi for (end = ptr + n; ptr < end; ptr++) if (wcschr(accept, *ptr)) ret = ptr;
1449c2c66affSColin Finck return (WCHAR *)ret;
1450c2c66affSColin Finck }
1451c2c66affSColin Finck
FileMoniker_CreateFromDisplayName(LPBC pbc,LPCOLESTR szDisplayName,LPDWORD pchEaten,IMoniker ** ppmk)1452c2c66affSColin Finck HRESULT FileMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
1453c2c66affSColin Finck LPDWORD pchEaten, IMoniker **ppmk)
1454c2c66affSColin Finck {
1455c2c66affSColin Finck LPCWSTR end;
1456c2c66affSColin Finck static const WCHAR wszSeparators[] = {':','\\','/','!',0};
1457c2c66affSColin Finck
1458*0f5d91b7SAmine Khaldi for (end = szDisplayName + lstrlenW(szDisplayName);
1459c2c66affSColin Finck end && (end != szDisplayName);
1460c2c66affSColin Finck end = memrpbrkW(szDisplayName, end - szDisplayName, wszSeparators))
1461c2c66affSColin Finck {
1462c2c66affSColin Finck HRESULT hr;
1463c2c66affSColin Finck IRunningObjectTable *rot;
1464c2c66affSColin Finck IMoniker *file_moniker;
1465c2c66affSColin Finck LPWSTR file_display_name;
1466c2c66affSColin Finck LPWSTR full_path_name;
1467c2c66affSColin Finck DWORD full_path_name_len;
1468c2c66affSColin Finck int len = end - szDisplayName;
1469c2c66affSColin Finck
1470c2c66affSColin Finck file_display_name = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
1471c2c66affSColin Finck if (!file_display_name) return E_OUTOFMEMORY;
1472c2c66affSColin Finck memcpy(file_display_name, szDisplayName, len * sizeof(WCHAR));
1473c2c66affSColin Finck file_display_name[len] = '\0';
1474c2c66affSColin Finck
1475c2c66affSColin Finck hr = CreateFileMoniker(file_display_name, &file_moniker);
1476c2c66affSColin Finck if (FAILED(hr))
1477c2c66affSColin Finck {
1478c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, file_display_name);
1479c2c66affSColin Finck return hr;
1480c2c66affSColin Finck }
1481c2c66affSColin Finck
1482c2c66affSColin Finck hr = IBindCtx_GetRunningObjectTable(pbc, &rot);
1483c2c66affSColin Finck if (FAILED(hr))
1484c2c66affSColin Finck {
1485c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, file_display_name);
1486c2c66affSColin Finck IMoniker_Release(file_moniker);
1487c2c66affSColin Finck return hr;
1488c2c66affSColin Finck }
1489c2c66affSColin Finck
1490c2c66affSColin Finck hr = IRunningObjectTable_IsRunning(rot, file_moniker);
1491c2c66affSColin Finck IRunningObjectTable_Release(rot);
1492c2c66affSColin Finck if (FAILED(hr))
1493c2c66affSColin Finck {
1494c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, file_display_name);
1495c2c66affSColin Finck IMoniker_Release(file_moniker);
1496c2c66affSColin Finck return hr;
1497c2c66affSColin Finck }
1498c2c66affSColin Finck if (hr == S_OK)
1499c2c66affSColin Finck {
1500c2c66affSColin Finck TRACE("found running file moniker for %s\n", debugstr_w(file_display_name));
1501c2c66affSColin Finck *pchEaten = len;
1502c2c66affSColin Finck *ppmk = file_moniker;
1503c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, file_display_name);
1504c2c66affSColin Finck return S_OK;
1505c2c66affSColin Finck }
1506c2c66affSColin Finck
1507c2c66affSColin Finck full_path_name_len = GetFullPathNameW(file_display_name, 0, NULL, NULL);
1508c2c66affSColin Finck if (!full_path_name_len)
1509c2c66affSColin Finck {
1510c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, file_display_name);
1511c2c66affSColin Finck IMoniker_Release(file_moniker);
1512c2c66affSColin Finck return MK_E_SYNTAX;
1513c2c66affSColin Finck }
1514c2c66affSColin Finck full_path_name = HeapAlloc(GetProcessHeap(), 0, full_path_name_len * sizeof(WCHAR));
1515c2c66affSColin Finck if (!full_path_name)
1516c2c66affSColin Finck {
1517c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, file_display_name);
1518c2c66affSColin Finck IMoniker_Release(file_moniker);
1519c2c66affSColin Finck return E_OUTOFMEMORY;
1520c2c66affSColin Finck }
1521c2c66affSColin Finck GetFullPathNameW(file_display_name, full_path_name_len, full_path_name, NULL);
1522c2c66affSColin Finck
1523c2c66affSColin Finck if (GetFileAttributesW(full_path_name) == INVALID_FILE_ATTRIBUTES)
1524c2c66affSColin Finck TRACE("couldn't open file %s\n", debugstr_w(full_path_name));
1525c2c66affSColin Finck else
1526c2c66affSColin Finck {
1527c2c66affSColin Finck TRACE("got file moniker for %s\n", debugstr_w(szDisplayName));
1528c2c66affSColin Finck *pchEaten = len;
1529c2c66affSColin Finck *ppmk = file_moniker;
1530c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, file_display_name);
1531c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, full_path_name);
1532c2c66affSColin Finck return S_OK;
1533c2c66affSColin Finck }
1534c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, file_display_name);
1535c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, full_path_name);
1536c2c66affSColin Finck IMoniker_Release(file_moniker);
1537c2c66affSColin Finck }
1538c2c66affSColin Finck
1539c2c66affSColin Finck return MK_E_CANTOPENFILE;
1540c2c66affSColin Finck }
1541c2c66affSColin Finck
1542c2c66affSColin Finck
FileMoniker_CreateInstance(IClassFactory * iface,IUnknown * pUnk,REFIID riid,void ** ppv)1543c2c66affSColin Finck HRESULT WINAPI FileMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv)
1544c2c66affSColin Finck {
1545c2c66affSColin Finck FileMonikerImpl* newFileMoniker;
1546c2c66affSColin Finck HRESULT hr;
1547c2c66affSColin Finck static const WCHAR wszEmpty[] = { 0 };
1548c2c66affSColin Finck
1549c2c66affSColin Finck TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
1550c2c66affSColin Finck
1551c2c66affSColin Finck *ppv = NULL;
1552c2c66affSColin Finck
1553c2c66affSColin Finck if (pUnk)
1554c2c66affSColin Finck return CLASS_E_NOAGGREGATION;
1555c2c66affSColin Finck
1556c2c66affSColin Finck newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl));
1557c2c66affSColin Finck if (!newFileMoniker)
1558c2c66affSColin Finck return E_OUTOFMEMORY;
1559c2c66affSColin Finck
1560c2c66affSColin Finck hr = FileMonikerImpl_Construct(newFileMoniker, wszEmpty);
1561c2c66affSColin Finck
1562c2c66affSColin Finck if (SUCCEEDED(hr))
1563c2c66affSColin Finck hr = IMoniker_QueryInterface(&newFileMoniker->IMoniker_iface, riid, ppv);
1564c2c66affSColin Finck if (FAILED(hr))
1565c2c66affSColin Finck HeapFree(GetProcessHeap(),0,newFileMoniker);
1566c2c66affSColin Finck
1567c2c66affSColin Finck return hr;
1568c2c66affSColin Finck }
1569