ReactOS  0.4.15-dev-1171-gab82533
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 
46 
47 typedef struct FileLockBytesImpl
48 {
55 
56 static const ILockBytesVtbl FileLockBytesImpl_Vtbl;
57 
59 {
60  return CONTAINING_RECORD(iface, FileLockBytesImpl, ILockBytes_iface);
61 }
62 
63 /***********************************************************
64  * Prototypes for private methods
65  */
66 
67 /****************************************************************************
68  * GetProtectMode
69  *
70  * This function will return a protection mode flag for a file-mapping object
71  * from the open flags of a file.
72  */
73 static DWORD GetProtectMode(DWORD openFlags)
74 {
75  switch(STGM_ACCESS_MODE(openFlags))
76  {
77  case STGM_WRITE:
78  case STGM_READWRITE:
79  return PAGE_READWRITE;
80  }
81  return PAGE_READONLY;
82 }
83 
84 /******************************************************************************
85  * FileLockBytesImpl_Construct
86  *
87  * Initialize a big block object supported by a file.
88  */
90 {
92  WCHAR fullpath[MAX_PATH];
93 
95  return E_FAIL;
96 
98 
99  if (!This)
100  return E_OUTOFMEMORY;
101 
102  This->ILockBytes_iface.lpVtbl = &FileLockBytesImpl_Vtbl;
103  This->ref = 1;
104  This->hfile = hFile;
105  This->flProtect = GetProtectMode(openFlags);
106 
107  if(pwcsName) {
108  if (!GetFullPathNameW(pwcsName, MAX_PATH, fullpath, NULL))
109  {
110  lstrcpynW(fullpath, pwcsName, MAX_PATH);
111  }
112  This->pwcsName = HeapAlloc(GetProcessHeap(), 0,
113  (lstrlenW(fullpath)+1)*sizeof(WCHAR));
114  if (!This->pwcsName)
115  {
117  return E_OUTOFMEMORY;
118  }
119  lstrcpyW(This->pwcsName, fullpath);
120  }
121  else
122  This->pwcsName = NULL;
123 
124  *pLockBytes = &This->ILockBytes_iface;
125 
126  return S_OK;
127 }
128 
129 /* ILockByte Interfaces */
130 
132  void **ppvObject)
133 {
134  if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ILockBytes))
135  *ppvObject = iface;
136  else
137  {
138  *ppvObject = NULL;
139  return E_NOINTERFACE;
140  }
141 
142  IUnknown_AddRef((IUnknown*)*ppvObject);
143 
144  return S_OK;
145 }
146 
148 {
150  return InterlockedIncrement(&This->ref);
151 }
152 
154 {
156  ULONG ref;
157 
158  ref = InterlockedDecrement(&This->ref);
159 
160  if (ref == 0)
161  {
162  CloseHandle(This->hfile);
163  HeapFree(GetProcessHeap(), 0, This->pwcsName);
165  }
166 
167  return ref;
168 }
169 
170 /******************************************************************************
171  * This method is part of the ILockBytes interface.
172  *
173  * It reads a block of information from the byte array at the specified
174  * offset.
175  *
176  * See the documentation of ILockBytes for more info.
177  */
179  ILockBytes* iface,
180  ULARGE_INTEGER ulOffset, /* [in] */
181  void* pv, /* [length_is][size_is][out] */
182  ULONG cb, /* [in] */
183  ULONG* pcbRead) /* [out] */
184 {
186  ULONG bytes_left = cb;
187  LPBYTE readPtr = pv;
188  BOOL ret;
190  ULONG cbRead;
191 
192  TRACE("(%p)-> %i %p %i %p\n",This, ulOffset.u.LowPart, pv, cb, pcbRead);
193 
194  /* verify a sane environment */
195  if (!This) return E_FAIL;
196 
197  if (pcbRead)
198  *pcbRead = 0;
199 
200  offset.QuadPart = ulOffset.QuadPart;
201 
203 
204  if (!ret)
205  return STG_E_READFAULT;
206 
207  while (bytes_left)
208  {
209  ret = ReadFile(This->hfile, readPtr, bytes_left, &cbRead, NULL);
210 
211  if (!ret || cbRead == 0)
212  return STG_E_READFAULT;
213 
214  if (pcbRead)
215  *pcbRead += cbRead;
216 
217  bytes_left -= cbRead;
218  readPtr += cbRead;
219  }
220 
221  TRACE("finished\n");
222  return S_OK;
223 }
224 
225 /******************************************************************************
226  * This method is part of the ILockBytes interface.
227  *
228  * It writes the specified bytes at the specified offset.
229  * position. If the file is too small, it will be resized.
230  *
231  * See the documentation of ILockBytes for more info.
232  */
234  ILockBytes* iface,
235  ULARGE_INTEGER ulOffset, /* [in] */
236  const void* pv, /* [size_is][in] */
237  ULONG cb, /* [in] */
238  ULONG* pcbWritten) /* [out] */
239 {
241  ULONG bytes_left = cb;
242  const BYTE *writePtr = pv;
243  BOOL ret;
245  ULONG cbWritten;
246 
247  TRACE("(%p)-> %i %p %i %p\n",This, ulOffset.u.LowPart, pv, cb, pcbWritten);
248 
249  /* verify a sane environment */
250  if (!This) return E_FAIL;
251 
252  if (This->flProtect != PAGE_READWRITE)
253  return STG_E_ACCESSDENIED;
254 
255  if (pcbWritten)
256  *pcbWritten = 0;
257 
258  offset.QuadPart = ulOffset.QuadPart;
259 
261 
262  if (!ret)
263  return STG_E_WRITEFAULT;
264 
265  while (bytes_left)
266  {
267  ret = WriteFile(This->hfile, writePtr, bytes_left, &cbWritten, NULL);
268 
269  if (!ret)
270  return STG_E_WRITEFAULT;
271 
272  if (pcbWritten)
273  *pcbWritten += cbWritten;
274 
275  bytes_left -= cbWritten;
276  writePtr += cbWritten;
277  }
278 
279  TRACE("finished\n");
280  return S_OK;
281 }
282 
284 {
285  return S_OK;
286 }
287 
288 /******************************************************************************
289  * ILockBytes_SetSize
290  *
291  * Sets the size of the file.
292  *
293  */
295 {
297  HRESULT hr = S_OK;
298  LARGE_INTEGER newpos;
299 
300  TRACE("new size %u\n", newSize.u.LowPart);
301 
302  newpos.QuadPart = newSize.QuadPart;
303  if (SetFilePointerEx(This->hfile, newpos, NULL, FILE_BEGIN))
304  {
305  SetEndOfFile(This->hfile);
306  }
307 
308  return hr;
309 }
310 
312 {
313  switch (GetLastError())
314  {
315  case ERROR_LOCK_VIOLATION: return STG_E_LOCKVIOLATION; break;
316  case ERROR_ACCESS_DENIED: return STG_E_ACCESSDENIED; break;
317  case ERROR_NOT_SUPPORTED: return STG_E_INVALIDFUNCTION; break;
318  default:
319  FIXME("no mapping for error %d\n", GetLastError());
320  return STG_E_INVALIDFUNCTION;
321  }
322 }
323 
325  ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
326 {
328  OVERLAPPED ol;
329  DWORD lock_flags = LOCKFILE_FAIL_IMMEDIATELY;
330 
331  TRACE("ofs %u count %u flags %x\n", libOffset.u.LowPart, cb.u.LowPart, dwLockType);
332 
333  if (dwLockType & LOCK_WRITE)
334  return STG_E_INVALIDFUNCTION;
335 
336  if (dwLockType & (LOCK_EXCLUSIVE|LOCK_ONLYONCE))
337  lock_flags |= LOCKFILE_EXCLUSIVE_LOCK;
338 
339  ol.hEvent = 0;
340  ol.u.s.Offset = libOffset.u.LowPart;
341  ol.u.s.OffsetHigh = libOffset.u.HighPart;
342 
343  if (LockFileEx(This->hfile, lock_flags, 0, cb.u.LowPart, cb.u.HighPart, &ol))
344  return S_OK;
345  return get_lock_error();
346 }
347 
349  ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
350 {
352  OVERLAPPED ol;
353 
354  TRACE("ofs %u count %u flags %x\n", libOffset.u.LowPart, cb.u.LowPart, dwLockType);
355 
356  if (dwLockType & LOCK_WRITE)
357  return STG_E_INVALIDFUNCTION;
358 
359  ol.hEvent = 0;
360  ol.u.s.Offset = libOffset.u.LowPart;
361  ol.u.s.OffsetHigh = libOffset.u.HighPart;
362 
363  if (UnlockFileEx(This->hfile, 0, cb.u.LowPart, cb.u.HighPart, &ol))
364  return S_OK;
365  return get_lock_error();
366 }
367 
369  STATSTG *pstatstg, DWORD grfStatFlag)
370 {
372 
373  if (!(STATFLAG_NONAME & grfStatFlag) && This->pwcsName)
374  {
375  pstatstg->pwcsName =
376  CoTaskMemAlloc((lstrlenW(This->pwcsName)+1)*sizeof(WCHAR));
377 
378  lstrcpyW(pstatstg->pwcsName, This->pwcsName);
379  }
380  else
381  pstatstg->pwcsName = NULL;
382 
383  pstatstg->type = STGTY_LOCKBYTES;
384 
385  pstatstg->cbSize.u.LowPart = GetFileSize(This->hfile, &pstatstg->cbSize.u.HighPart);
386  /* FIXME: If the implementation is exported, we'll need to set other fields. */
387 
388  pstatstg->grfLocksSupported = LOCK_EXCLUSIVE|LOCK_ONLYONCE|WINE_LOCK_READ;
389 
390  return S_OK;
391 }
392 
393 static const ILockBytesVtbl FileLockBytesImpl_Vtbl = {
404 };
static FileLockBytesImpl * impl_from_ILockBytes(ILockBytes *iface)
Definition: filelockbytes.c:58
BOOL WINAPI SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod)
Definition: fileinfo.c:177
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
#define REFIID
Definition: guiddef.h:118
#define STG_E_WRITEFAULT
Definition: winerror.h:2575
#define CloseHandle
Definition: compat.h:487
#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:73
BOOL WINAPI SetEndOfFile(HANDLE hFile)
Definition: fileinfo.c:1004
GLintptr offset
Definition: glext.h:5920
#define INVALID_HANDLE_VALUE
Definition: compat.h:479
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1044
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1105
#define FILE_BEGIN
Definition: compat.h:509
DWORD Offset
Definition: winbase.h:793
#define lstrlenW
Definition: compat.h:498
#define E_FAIL
Definition: ddrawi.h:102
Definition: send.c:48
struct _ULARGE_INTEGER::@3873 u
#define lstrcpynW
Definition: compat.h:486
unsigned char * LPBYTE
Definition: typedefs.h:53
#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:97
#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:111
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:798
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:484
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:79
const GUID IID_IUnknown
#define MAX_PATH
Definition: compat.h:34
#define WINAPI
Definition: msvc.h:6
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
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
REFIID LPVOID * ppvObject
Definition: precomp.h:44
_In_ HANDLE hFile
Definition: mswsock.h:90
#define STGM_READWRITE
Definition: objbase.h:918
unsigned char BYTE
Definition: xxhash.c:193
#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:49
#define S_OK
Definition: intsafe.h:51
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
#define lstrcpyW
Definition: compat.h:497
DWORD OffsetHigh
Definition: winbase.h:794
static HRESULT get_lock_error(void)
static const ILockBytesVtbl FileLockBytesImpl_Vtbl
Definition: filelockbytes.c:56
HRESULT FileLockBytesImpl_Construct(HANDLE hFile, DWORD openFlags, LPCWSTR pwcsName, ILockBytes **pLockBytes)
Definition: filelockbytes.c:89
static HRESULT WINAPI FileLockBytesImpl_QueryInterface(ILockBytes *iface, REFIID riid, void **ppvObject)
#define LOCKFILE_EXCLUSIVE_LOCK
Definition: winbase.h:367
#define ReadFile(a, b, c, d, e)
Definition: compat.h:490
#define STG_E_READFAULT
Definition: winerror.h:2576
#define PAGE_READONLY
Definition: compat.h:138
static HMODULE MODULEINFO DWORD cb
Definition: module.c:32
#define ERROR_NOT_SUPPORTED
Definition: compat.h:100
#define ERROR_LOCK_VIOLATION
Definition: winerror.h:136
unsigned int ULONG
Definition: retypes.h:1
WCHAR * LPWSTR
Definition: xmlstorage.h:184
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
#define HeapFree(x, y, z)
Definition: compat.h:483
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
static HRESULT WINAPI FileLockBytesImpl_UnlockRegion(ILockBytes *iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
LONGLONG QuadPart
Definition: typedefs.h:114
#define PAGE_READWRITE
Definition: nt_native.h:1304