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