ReactOS  0.4.13-dev-464-g6b95727
filelockbytes.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * File-based ILockBytes implementation
4  *
5  * Copyright 1999 Thuy Nguyen
6  * Copyright 2010 Vincent Povirk for CodeWeavers
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 
23 #include <assert.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <limits.h>
29 
30 #define COBJMACROS
31 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
33 
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winuser.h"
37 #include "winerror.h"
38 #include "objbase.h"
39 #include "ole2.h"
40 
41 #include "storage32.h"
42 
43 #include "wine/debug.h"
44 #include "wine/unicode.h"
45 
47 
48 typedef struct FileLockBytesImpl
49 {
56 
57 static const ILockBytesVtbl FileLockBytesImpl_Vtbl;
58 
60 {
61  return CONTAINING_RECORD(iface, FileLockBytesImpl, ILockBytes_iface);
62 }
63 
64 /***********************************************************
65  * Prototypes for private methods
66  */
67 
68 /****************************************************************************
69  * GetProtectMode
70  *
71  * This function will return a protection mode flag for a file-mapping object
72  * from the open flags of a file.
73  */
74 static DWORD GetProtectMode(DWORD openFlags)
75 {
76  switch(STGM_ACCESS_MODE(openFlags))
77  {
78  case STGM_WRITE:
79  case STGM_READWRITE:
80  return PAGE_READWRITE;
81  }
82  return PAGE_READONLY;
83 }
84 
85 /******************************************************************************
86  * FileLockBytesImpl_Construct
87  *
88  * Initialize a big block object supported by a file.
89  */
91 {
93  WCHAR fullpath[MAX_PATH];
94 
96  return E_FAIL;
97 
99 
100  if (!This)
101  return E_OUTOFMEMORY;
102 
103  This->ILockBytes_iface.lpVtbl = &FileLockBytesImpl_Vtbl;
104  This->ref = 1;
105  This->hfile = hFile;
106  This->flProtect = GetProtectMode(openFlags);
107 
108  if(pwcsName) {
109  if (!GetFullPathNameW(pwcsName, MAX_PATH, fullpath, NULL))
110  {
111  lstrcpynW(fullpath, pwcsName, MAX_PATH);
112  }
113  This->pwcsName = HeapAlloc(GetProcessHeap(), 0,
114  (lstrlenW(fullpath)+1)*sizeof(WCHAR));
115  if (!This->pwcsName)
116  {
118  return E_OUTOFMEMORY;
119  }
120  strcpyW(This->pwcsName, fullpath);
121  }
122  else
123  This->pwcsName = NULL;
124 
125  *pLockBytes = &This->ILockBytes_iface;
126 
127  return S_OK;
128 }
129 
130 /* ILockByte Interfaces */
131 
133  void **ppvObject)
134 {
135  if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ILockBytes))
136  *ppvObject = iface;
137  else
138  {
139  *ppvObject = NULL;
140  return E_NOINTERFACE;
141  }
142 
143  IUnknown_AddRef((IUnknown*)*ppvObject);
144 
145  return S_OK;
146 }
147 
149 {
151  return InterlockedIncrement(&This->ref);
152 }
153 
155 {
157  ULONG ref;
158 
159  ref = InterlockedDecrement(&This->ref);
160 
161  if (ref == 0)
162  {
163  CloseHandle(This->hfile);
164  HeapFree(GetProcessHeap(), 0, This->pwcsName);
166  }
167 
168  return ref;
169 }
170 
171 /******************************************************************************
172  * This method is part of the ILockBytes interface.
173  *
174  * It reads a block of information from the byte array at the specified
175  * offset.
176  *
177  * See the documentation of ILockBytes for more info.
178  */
180  ILockBytes* iface,
181  ULARGE_INTEGER ulOffset, /* [in] */
182  void* pv, /* [length_is][size_is][out] */
183  ULONG cb, /* [in] */
184  ULONG* pcbRead) /* [out] */
185 {
187  ULONG bytes_left = cb;
188  LPBYTE readPtr = pv;
189  BOOL ret;
191  ULONG cbRead;
192 
193  TRACE("(%p)-> %i %p %i %p\n",This, ulOffset.u.LowPart, pv, cb, pcbRead);
194 
195  /* verify a sane environment */
196  if (!This) return E_FAIL;
197 
198  if (pcbRead)
199  *pcbRead = 0;
200 
201  offset.QuadPart = ulOffset.QuadPart;
202 
204 
205  if (!ret)
206  return STG_E_READFAULT;
207 
208  while (bytes_left)
209  {
210  ret = ReadFile(This->hfile, readPtr, bytes_left, &cbRead, NULL);
211 
212  if (!ret || cbRead == 0)
213  return STG_E_READFAULT;
214 
215  if (pcbRead)
216  *pcbRead += cbRead;
217 
218  bytes_left -= cbRead;
219  readPtr += cbRead;
220  }
221 
222  TRACE("finished\n");
223  return S_OK;
224 }
225 
226 /******************************************************************************
227  * This method is part of the ILockBytes interface.
228  *
229  * It writes the specified bytes at the specified offset.
230  * position. If the file is too small, it will be resized.
231  *
232  * See the documentation of ILockBytes for more info.
233  */
235  ILockBytes* iface,
236  ULARGE_INTEGER ulOffset, /* [in] */
237  const void* pv, /* [size_is][in] */
238  ULONG cb, /* [in] */
239  ULONG* pcbWritten) /* [out] */
240 {
242  ULONG bytes_left = cb;
243  const BYTE *writePtr = pv;
244  BOOL ret;
246  ULONG cbWritten;
247 
248  TRACE("(%p)-> %i %p %i %p\n",This, ulOffset.u.LowPart, pv, cb, pcbWritten);
249 
250  /* verify a sane environment */
251  if (!This) return E_FAIL;
252 
253  if (This->flProtect != PAGE_READWRITE)
254  return STG_E_ACCESSDENIED;
255 
256  if (pcbWritten)
257  *pcbWritten = 0;
258 
259  offset.QuadPart = ulOffset.QuadPart;
260 
262 
263  if (!ret)
264  return STG_E_WRITEFAULT;
265 
266  while (bytes_left)
267  {
268  ret = WriteFile(This->hfile, writePtr, bytes_left, &cbWritten, NULL);
269 
270  if (!ret)
271  return STG_E_WRITEFAULT;
272 
273  if (pcbWritten)
274  *pcbWritten += cbWritten;
275 
276  bytes_left -= cbWritten;
277  writePtr += cbWritten;
278  }
279 
280  TRACE("finished\n");
281  return S_OK;
282 }
283 
285 {
286  return S_OK;
287 }
288 
289 /******************************************************************************
290  * ILockBytes_SetSize
291  *
292  * Sets the size of the file.
293  *
294  */
296 {
298  HRESULT hr = S_OK;
299  LARGE_INTEGER newpos;
300 
301  TRACE("new size %u\n", newSize.u.LowPart);
302 
303  newpos.QuadPart = newSize.QuadPart;
304  if (SetFilePointerEx(This->hfile, newpos, NULL, FILE_BEGIN))
305  {
306  SetEndOfFile(This->hfile);
307  }
308 
309  return hr;
310 }
311 
313 {
314  switch (GetLastError())
315  {
316  case ERROR_LOCK_VIOLATION: return STG_E_LOCKVIOLATION; break;
317  case ERROR_ACCESS_DENIED: return STG_E_ACCESSDENIED; break;
318  case ERROR_NOT_SUPPORTED: return STG_E_INVALIDFUNCTION; break;
319  default:
320  FIXME("no mapping for error %d\n", GetLastError());
321  return STG_E_INVALIDFUNCTION;
322  }
323 }
324 
326  ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
327 {
329  OVERLAPPED ol;
330  DWORD lock_flags = LOCKFILE_FAIL_IMMEDIATELY;
331 
332  TRACE("ofs %u count %u flags %x\n", libOffset.u.LowPart, cb.u.LowPart, dwLockType);
333 
334  if (dwLockType & LOCK_WRITE)
335  return STG_E_INVALIDFUNCTION;
336 
337  if (dwLockType & (LOCK_EXCLUSIVE|LOCK_ONLYONCE))
338  lock_flags |= LOCKFILE_EXCLUSIVE_LOCK;
339 
340  ol.hEvent = 0;
341  ol.u.s.Offset = libOffset.u.LowPart;
342  ol.u.s.OffsetHigh = libOffset.u.HighPart;
343 
344  if (LockFileEx(This->hfile, lock_flags, 0, cb.u.LowPart, cb.u.HighPart, &ol))
345  return S_OK;
346  return get_lock_error();
347 }
348 
350  ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
351 {
353  OVERLAPPED ol;
354 
355  TRACE("ofs %u count %u flags %x\n", libOffset.u.LowPart, cb.u.LowPart, dwLockType);
356 
357  if (dwLockType & LOCK_WRITE)
358  return STG_E_INVALIDFUNCTION;
359 
360  ol.hEvent = 0;
361  ol.u.s.Offset = libOffset.u.LowPart;
362  ol.u.s.OffsetHigh = libOffset.u.HighPart;
363 
364  if (UnlockFileEx(This->hfile, 0, cb.u.LowPart, cb.u.HighPart, &ol))
365  return S_OK;
366  return get_lock_error();
367 }
368 
370  STATSTG *pstatstg, DWORD grfStatFlag)
371 {
373 
374  if (!(STATFLAG_NONAME & grfStatFlag) && This->pwcsName)
375  {
376  pstatstg->pwcsName =
377  CoTaskMemAlloc((lstrlenW(This->pwcsName)+1)*sizeof(WCHAR));
378 
379  strcpyW(pstatstg->pwcsName, This->pwcsName);
380  }
381  else
382  pstatstg->pwcsName = NULL;
383 
384  pstatstg->type = STGTY_LOCKBYTES;
385 
386  pstatstg->cbSize.u.LowPart = GetFileSize(This->hfile, &pstatstg->cbSize.u.HighPart);
387  /* FIXME: If the implementation is exported, we'll need to set other fields. */
388 
389  pstatstg->grfLocksSupported = LOCK_EXCLUSIVE|LOCK_ONLYONCE|WINE_LOCK_READ;
390 
391  return S_OK;
392 }
393 
394 static const ILockBytesVtbl FileLockBytesImpl_Vtbl = {
405 };
static FileLockBytesImpl * impl_from_ILockBytes(ILockBytes *iface)
Definition: filelockbytes.c:59
BOOL WINAPI SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod)
Definition: fileinfo.c:327
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
struct _ULARGE_INTEGER::@3741 u
#define REFIID
Definition: guiddef.h:113
#define STG_E_WRITEFAULT
Definition: winerror.h:2575
#define CloseHandle
Definition: compat.h:398
#define E_NOINTERFACE
Definition: winerror.h:2364
#define WINE_LOCK_READ
Definition: storage32.h:523
HRESULT hr
Definition: shlfolder.c:183
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
REFIID riid
Definition: precomp.h:44
static DWORD GetProtectMode(DWORD openFlags)
Definition: filelockbytes.c:74
BOOL WINAPI SetEndOfFile(HANDLE hFile)
Definition: fileinfo.c:1154
GLintptr offset
Definition: glext.h:5920
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1105
DWORD Offset
Definition: winbase.h:787
#define lstrlenW
Definition: compat.h:407
#define E_FAIL
Definition: ddrawi.h:102
Definition: send.c:47
#define lstrcpynW
Definition: compat.h:397
unsigned char * LPBYTE
Definition: typedefs.h:52
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
WINE_DEFAULT_DEBUG_CHANNEL(storage)
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
#define ERROR_ACCESS_DENIED
Definition: compat.h:87
#define STG_E_ACCESSDENIED
Definition: winerror.h:2568
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
struct FileLockBytesImpl FileLockBytesImpl
GLenum GLint ref
Definition: glext.h:6028
#define FIXME(fmt,...)
Definition: debug.h:110
static HRESULT WINAPI FileLockBytesImpl_Stat(ILockBytes *iface, STATSTG *pstatstg, DWORD grfStatFlag)
static HRESULT WINAPI FileLockBytesImpl_WriteAt(ILockBytes *iface, ULARGE_INTEGER ulOffset, const void *pv, ULONG cb, ULONG *pcbWritten)
HANDLE hEvent
Definition: winbase.h:792
static HRESULT WINAPI FileLockBytesImpl_Flush(ILockBytes *iface)
#define LOCKFILE_FAIL_IMMEDIATELY
Definition: winbase.h:366
smooth NULL
Definition: ftsmooth.c:416
#define STGM_WRITE
Definition: objbase.h:917
#define STG_E_INVALIDFUNCTION
Definition: winerror.h:2564
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
static HRESULT WINAPI FileLockBytesImpl_ReadAt(ILockBytes *iface, ULARGE_INTEGER ulOffset, void *pv, ULONG cb, ULONG *pcbRead)
#define TRACE(s)
Definition: solgame.cpp:4
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
__wchar_t WCHAR
Definition: xmlstorage.h:180
static HRESULT WINAPI FileLockBytesImpl_SetSize(ILockBytes *iface, ULARGE_INTEGER newSize)
LONG HRESULT
Definition: typedefs.h:77
const GUID IID_IUnknown
#define MAX_PATH
Definition: compat.h:26
#define WINAPI
Definition: msvc.h:8
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:481
static DWORD cb
Definition: integrity.c:41
static ULONG WINAPI FileLockBytesImpl_AddRef(ILockBytes *iface)
static ULONG WINAPI FileLockBytesImpl_Release(ILockBytes *iface)
int ret
#define InterlockedDecrement
Definition: armddk.h:52
BOOL WINAPI UnlockFileEx(IN HANDLE hFile, IN DWORD dwReserved, IN DWORD nNumberOfBytesToUnLockLow, IN DWORD nNumberOfBytesToUnLockHigh, IN LPOVERLAPPED lpOverlapped)
Definition: lock.c:183
unsigned char BYTE
Definition: mem.h:68
REFIID LPVOID * ppvObject
Definition: precomp.h:44
_In_ HANDLE hFile
Definition: mswsock.h:90
#define STGM_READWRITE
Definition: objbase.h:918
#define STGM_ACCESS_MODE(stgm)
Definition: storage32.h:115
static HRESULT WINAPI FileLockBytesImpl_LockRegion(ILockBytes *iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
ILockBytes ILockBytes_iface
Definition: filelockbytes.c:50
#define S_OK
Definition: intsafe.h:59
#define FILE_BEGIN
Definition: winbase.h:112
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
BOOL WINAPI LockFileEx(IN HANDLE hFile, IN DWORD dwFlags, IN DWORD dwReserved, IN DWORD nNumberOfBytesToLockLow, IN DWORD nNumberOfBytesToLockHigh, IN LPOVERLAPPED lpOverlapped)
Definition: lock.c:82
#define STG_E_LOCKVIOLATION
Definition: winerror.h:2578
#define InterlockedIncrement
Definition: armddk.h:53
DWORD OffsetHigh
Definition: winbase.h:788
static HRESULT get_lock_error(void)
static const ILockBytesVtbl FileLockBytesImpl_Vtbl
Definition: filelockbytes.c:57
HRESULT FileLockBytesImpl_Construct(HANDLE hFile, DWORD openFlags, LPCWSTR pwcsName, ILockBytes **pLockBytes)
Definition: filelockbytes.c:90
static HRESULT WINAPI FileLockBytesImpl_QueryInterface(ILockBytes *iface, REFIID riid, void **ppvObject)
#define LOCKFILE_EXCLUSIVE_LOCK
Definition: winbase.h:367
#define STG_E_READFAULT
Definition: winerror.h:2576
#define PAGE_READONLY
Definition: compat.h:127
#define ERROR_NOT_SUPPORTED
Definition: compat.h:90
#define ERROR_LOCK_VIOLATION
Definition: winerror.h:136
unsigned int ULONG
Definition: retypes.h:1
WCHAR * LPWSTR
Definition: xmlstorage.h:184
BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:123
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:406
#define HeapFree(x, y, z)
Definition: compat.h:394
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:90
static HRESULT WINAPI FileLockBytesImpl_UnlockRegion(ILockBytes *iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
LONGLONG QuadPart
Definition: typedefs.h:112
#define PAGE_READWRITE
Definition: nt_native.h:1304