imagehlp: Use the IMAGE_FIRST_SECTION helper macro.
[wine.git] / dlls / ole32 / filelockbytes.c
blobd806916f1d5879a6321a14097d004c9d5762cc7f
1 /******************************************************************************
3 * File-based ILockBytes implementation
5 * Copyright 1999 Thuy Nguyen
6 * Copyright 2010 Vincent Povirk for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include <assert.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <limits.h>
30 #define COBJMACROS
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winuser.h"
34 #include "winerror.h"
35 #include "objbase.h"
36 #include "ole2.h"
38 #include "storage32.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(storage);
44 typedef struct FileLockBytesImpl
46 ILockBytes ILockBytes_iface;
47 LONG ref;
48 HANDLE hfile;
49 DWORD flProtect;
50 LPWSTR pwcsName;
51 } FileLockBytesImpl;
53 static const ILockBytesVtbl FileLockBytesImpl_Vtbl;
55 static inline FileLockBytesImpl *impl_from_ILockBytes(ILockBytes *iface)
57 return CONTAINING_RECORD(iface, FileLockBytesImpl, ILockBytes_iface);
60 /***********************************************************
61 * Prototypes for private methods
64 /****************************************************************************
65 * GetProtectMode
67 * This function will return a protection mode flag for a file-mapping object
68 * from the open flags of a file.
70 static DWORD GetProtectMode(DWORD openFlags)
72 switch(STGM_ACCESS_MODE(openFlags))
74 case STGM_WRITE:
75 case STGM_READWRITE:
76 return PAGE_READWRITE;
78 return PAGE_READONLY;
81 /******************************************************************************
82 * FileLockBytesImpl_Construct
84 * Initialize a big block object supported by a file.
86 HRESULT FileLockBytesImpl_Construct(HANDLE hFile, DWORD openFlags, LPCWSTR pwcsName, ILockBytes **pLockBytes)
88 FileLockBytesImpl *This;
89 WCHAR fullpath[MAX_PATH];
91 if (hFile == INVALID_HANDLE_VALUE)
92 return E_FAIL;
94 This = HeapAlloc(GetProcessHeap(), 0, sizeof(FileLockBytesImpl));
96 if (!This)
97 return E_OUTOFMEMORY;
99 This->ILockBytes_iface.lpVtbl = &FileLockBytesImpl_Vtbl;
100 This->ref = 1;
101 This->hfile = hFile;
102 This->flProtect = GetProtectMode(openFlags);
104 if(pwcsName) {
105 if (!GetFullPathNameW(pwcsName, MAX_PATH, fullpath, NULL))
107 lstrcpynW(fullpath, pwcsName, MAX_PATH);
109 This->pwcsName = HeapAlloc(GetProcessHeap(), 0,
110 (lstrlenW(fullpath)+1)*sizeof(WCHAR));
111 if (!This->pwcsName)
113 HeapFree(GetProcessHeap(), 0, This);
114 return E_OUTOFMEMORY;
116 lstrcpyW(This->pwcsName, fullpath);
118 else
119 This->pwcsName = NULL;
121 *pLockBytes = &This->ILockBytes_iface;
123 return S_OK;
126 /* ILockByte Interfaces */
128 static HRESULT WINAPI FileLockBytesImpl_QueryInterface(ILockBytes *iface, REFIID riid,
129 void **ppvObject)
131 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ILockBytes))
132 *ppvObject = iface;
133 else
135 *ppvObject = NULL;
136 return E_NOINTERFACE;
139 IUnknown_AddRef((IUnknown*)*ppvObject);
141 return S_OK;
144 static ULONG WINAPI FileLockBytesImpl_AddRef(ILockBytes *iface)
146 FileLockBytesImpl* This = impl_from_ILockBytes(iface);
147 return InterlockedIncrement(&This->ref);
150 static ULONG WINAPI FileLockBytesImpl_Release(ILockBytes *iface)
152 FileLockBytesImpl* This = impl_from_ILockBytes(iface);
153 ULONG ref;
155 ref = InterlockedDecrement(&This->ref);
157 if (ref == 0)
159 CloseHandle(This->hfile);
160 HeapFree(GetProcessHeap(), 0, This->pwcsName);
161 HeapFree(GetProcessHeap(), 0, This);
164 return ref;
167 /******************************************************************************
168 * This method is part of the ILockBytes interface.
170 * It reads a block of information from the byte array at the specified
171 * offset.
173 * See the documentation of ILockBytes for more info.
175 static HRESULT WINAPI FileLockBytesImpl_ReadAt(
176 ILockBytes* iface,
177 ULARGE_INTEGER ulOffset, /* [in] */
178 void* pv, /* [length_is][size_is][out] */
179 ULONG cb, /* [in] */
180 ULONG* pcbRead) /* [out] */
182 FileLockBytesImpl* This = impl_from_ILockBytes(iface);
183 ULONG bytes_left = cb;
184 LPBYTE readPtr = pv;
185 BOOL ret;
186 LARGE_INTEGER offset;
187 ULONG cbRead;
189 TRACE("%p, %ld, %p, %lu, %p.\n", iface, ulOffset.LowPart, pv, cb, pcbRead);
191 /* verify a sane environment */
192 if (!This) return E_FAIL;
194 if (pcbRead)
195 *pcbRead = 0;
197 offset.QuadPart = ulOffset.QuadPart;
199 ret = SetFilePointerEx(This->hfile, offset, NULL, FILE_BEGIN);
201 if (!ret)
202 return STG_E_READFAULT;
204 while (bytes_left)
206 ret = ReadFile(This->hfile, readPtr, bytes_left, &cbRead, NULL);
208 if (!ret || cbRead == 0)
209 return STG_E_READFAULT;
211 if (pcbRead)
212 *pcbRead += cbRead;
214 bytes_left -= cbRead;
215 readPtr += cbRead;
218 TRACE("finished\n");
219 return S_OK;
222 /******************************************************************************
223 * This method is part of the ILockBytes interface.
225 * It writes the specified bytes at the specified offset.
226 * position. If the file is too small, it will be resized.
228 * See the documentation of ILockBytes for more info.
230 static HRESULT WINAPI FileLockBytesImpl_WriteAt(
231 ILockBytes* iface,
232 ULARGE_INTEGER ulOffset, /* [in] */
233 const void* pv, /* [size_is][in] */
234 ULONG cb, /* [in] */
235 ULONG* pcbWritten) /* [out] */
237 FileLockBytesImpl* This = impl_from_ILockBytes(iface);
238 ULONG bytes_left = cb;
239 const BYTE *writePtr = pv;
240 BOOL ret;
241 LARGE_INTEGER offset;
242 ULONG cbWritten;
244 TRACE("%p, %ld, %p, %lu, %p.\n", iface, ulOffset.LowPart, pv, cb, pcbWritten);
246 /* verify a sane environment */
247 if (!This) return E_FAIL;
249 if (This->flProtect != PAGE_READWRITE)
250 return STG_E_ACCESSDENIED;
252 if (pcbWritten)
253 *pcbWritten = 0;
255 offset.QuadPart = ulOffset.QuadPart;
257 ret = SetFilePointerEx(This->hfile, offset, NULL, FILE_BEGIN);
259 if (!ret)
260 return STG_E_WRITEFAULT;
262 while (bytes_left)
264 ret = WriteFile(This->hfile, writePtr, bytes_left, &cbWritten, NULL);
266 if (!ret)
267 return STG_E_WRITEFAULT;
269 if (pcbWritten)
270 *pcbWritten += cbWritten;
272 bytes_left -= cbWritten;
273 writePtr += cbWritten;
276 TRACE("finished\n");
277 return S_OK;
280 static HRESULT WINAPI FileLockBytesImpl_Flush(ILockBytes* iface)
282 return S_OK;
285 /******************************************************************************
286 * ILockBytes_SetSize
288 * Sets the size of the file.
291 static HRESULT WINAPI FileLockBytesImpl_SetSize(ILockBytes* iface, ULARGE_INTEGER newSize)
293 FileLockBytesImpl* This = impl_from_ILockBytes(iface);
294 HRESULT hr = S_OK;
295 LARGE_INTEGER newpos;
297 TRACE("new size %lu\n", newSize.LowPart);
299 newpos.QuadPart = newSize.QuadPart;
300 if (SetFilePointerEx(This->hfile, newpos, NULL, FILE_BEGIN))
302 SetEndOfFile(This->hfile);
305 return hr;
308 static HRESULT get_lock_error(void)
310 switch (GetLastError())
312 case ERROR_LOCK_VIOLATION: return STG_E_LOCKVIOLATION; break;
313 case ERROR_ACCESS_DENIED: return STG_E_ACCESSDENIED; break;
314 case ERROR_NOT_SUPPORTED: return STG_E_INVALIDFUNCTION; break;
315 default:
316 FIXME("no mapping for error %ld\n", GetLastError());
317 return STG_E_INVALIDFUNCTION;
321 static HRESULT WINAPI FileLockBytesImpl_LockRegion(ILockBytes* iface,
322 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
324 FileLockBytesImpl* This = impl_from_ILockBytes(iface);
325 OVERLAPPED ol;
326 DWORD lock_flags = LOCKFILE_FAIL_IMMEDIATELY;
328 TRACE("ofs %lu count %lu flags %lx\n", libOffset.LowPart, cb.LowPart, dwLockType);
330 if (dwLockType & LOCK_WRITE)
331 return STG_E_INVALIDFUNCTION;
333 if (dwLockType & (LOCK_EXCLUSIVE|LOCK_ONLYONCE))
334 lock_flags |= LOCKFILE_EXCLUSIVE_LOCK;
336 ol.hEvent = 0;
337 ol.Offset = libOffset.LowPart;
338 ol.OffsetHigh = libOffset.HighPart;
340 if (LockFileEx(This->hfile, lock_flags, 0, cb.LowPart, cb.HighPart, &ol))
341 return S_OK;
342 return get_lock_error();
345 static HRESULT WINAPI FileLockBytesImpl_UnlockRegion(ILockBytes* iface,
346 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
348 FileLockBytesImpl* This = impl_from_ILockBytes(iface);
349 OVERLAPPED ol;
351 TRACE("ofs %lu count %lu flags %lx\n", libOffset.LowPart, cb.LowPart, dwLockType);
353 if (dwLockType & LOCK_WRITE)
354 return STG_E_INVALIDFUNCTION;
356 ol.hEvent = 0;
357 ol.Offset = libOffset.LowPart;
358 ol.OffsetHigh = libOffset.HighPart;
360 if (UnlockFileEx(This->hfile, 0, cb.LowPart, cb.HighPart, &ol))
361 return S_OK;
362 return get_lock_error();
365 static HRESULT WINAPI FileLockBytesImpl_Stat(ILockBytes* iface,
366 STATSTG *pstatstg, DWORD grfStatFlag)
368 FileLockBytesImpl* This = impl_from_ILockBytes(iface);
370 if (!(STATFLAG_NONAME & grfStatFlag) && This->pwcsName)
372 pstatstg->pwcsName =
373 CoTaskMemAlloc((lstrlenW(This->pwcsName)+1)*sizeof(WCHAR));
375 lstrcpyW(pstatstg->pwcsName, This->pwcsName);
377 else
378 pstatstg->pwcsName = NULL;
380 pstatstg->type = STGTY_LOCKBYTES;
382 pstatstg->cbSize.LowPart = GetFileSize(This->hfile, &pstatstg->cbSize.HighPart);
383 /* FIXME: If the implementation is exported, we'll need to set other fields. */
385 pstatstg->grfLocksSupported = LOCK_EXCLUSIVE|LOCK_ONLYONCE|WINE_LOCK_READ;
387 return S_OK;
390 static const ILockBytesVtbl FileLockBytesImpl_Vtbl = {
391 FileLockBytesImpl_QueryInterface,
392 FileLockBytesImpl_AddRef,
393 FileLockBytesImpl_Release,
394 FileLockBytesImpl_ReadAt,
395 FileLockBytesImpl_WriteAt,
396 FileLockBytesImpl_Flush,
397 FileLockBytesImpl_SetSize,
398 FileLockBytesImpl_LockRegion,
399 FileLockBytesImpl_UnlockRegion,
400 FileLockBytesImpl_Stat