Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfilelockbytes.c
Go to the documentation of this file.
00001 /****************************************************************************** 00002 * 00003 * File-based ILockBytes implementation 00004 * 00005 * Copyright 1999 Thuy Nguyen 00006 * Copyright 2010 Vincent Povirk for CodeWeavers 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00021 */ 00022 00023 #include <assert.h> 00024 #include <stdlib.h> 00025 #include <stdarg.h> 00026 #include <stdio.h> 00027 #include <string.h> 00028 #include <limits.h> 00029 00030 #define COBJMACROS 00031 #define NONAMELESSUNION 00032 #define NONAMELESSSTRUCT 00033 00034 #include "windef.h" 00035 #include "winbase.h" 00036 #include "winuser.h" 00037 #include "winerror.h" 00038 #include "objbase.h" 00039 #include "ole2.h" 00040 00041 #include "storage32.h" 00042 00043 #include "wine/debug.h" 00044 #include "wine/unicode.h" 00045 00046 WINE_DEFAULT_DEBUG_CHANNEL(storage); 00047 00048 typedef struct FileLockBytesImpl 00049 { 00050 ILockBytes ILockBytes_iface; 00051 LONG ref; 00052 ULARGE_INTEGER filesize; 00053 HANDLE hfile; 00054 DWORD flProtect; 00055 LPWSTR pwcsName; 00056 } FileLockBytesImpl; 00057 00058 static const ILockBytesVtbl FileLockBytesImpl_Vtbl; 00059 00060 static inline FileLockBytesImpl *impl_from_ILockBytes(ILockBytes *iface) 00061 { 00062 return CONTAINING_RECORD(iface, FileLockBytesImpl, ILockBytes_iface); 00063 } 00064 00065 /*********************************************************** 00066 * Prototypes for private methods 00067 */ 00068 00069 /* Note that this evaluates a and b multiple times, so don't 00070 * pass expressions with side effects. */ 00071 #define ROUND_UP(a, b) ((((a) + (b) - 1)/(b))*(b)) 00072 00073 /**************************************************************************** 00074 * GetProtectMode 00075 * 00076 * This function will return a protection mode flag for a file-mapping object 00077 * from the open flags of a file. 00078 */ 00079 static DWORD GetProtectMode(DWORD openFlags) 00080 { 00081 switch(STGM_ACCESS_MODE(openFlags)) 00082 { 00083 case STGM_WRITE: 00084 case STGM_READWRITE: 00085 return PAGE_READWRITE; 00086 } 00087 return PAGE_READONLY; 00088 } 00089 00090 /****************************************************************************** 00091 * FileLockBytesImpl_Construct 00092 * 00093 * Initialize a big block object supported by a file. 00094 */ 00095 HRESULT FileLockBytesImpl_Construct(HANDLE hFile, DWORD openFlags, LPCWSTR pwcsName, ILockBytes **pLockBytes) 00096 { 00097 FileLockBytesImpl *This; 00098 WCHAR fullpath[MAX_PATH]; 00099 00100 if (hFile == INVALID_HANDLE_VALUE) 00101 return E_FAIL; 00102 00103 This = HeapAlloc(GetProcessHeap(), 0, sizeof(FileLockBytesImpl)); 00104 00105 if (!This) 00106 return E_OUTOFMEMORY; 00107 00108 This->ILockBytes_iface.lpVtbl = &FileLockBytesImpl_Vtbl; 00109 This->ref = 1; 00110 This->hfile = hFile; 00111 This->filesize.u.LowPart = GetFileSize(This->hfile, 00112 &This->filesize.u.HighPart); 00113 This->flProtect = GetProtectMode(openFlags); 00114 00115 if(pwcsName) { 00116 if (!GetFullPathNameW(pwcsName, MAX_PATH, fullpath, NULL)) 00117 { 00118 lstrcpynW(fullpath, pwcsName, MAX_PATH); 00119 } 00120 This->pwcsName = HeapAlloc(GetProcessHeap(), 0, 00121 (lstrlenW(fullpath)+1)*sizeof(WCHAR)); 00122 if (!This->pwcsName) 00123 { 00124 HeapFree(GetProcessHeap(), 0, This); 00125 return E_OUTOFMEMORY; 00126 } 00127 strcpyW(This->pwcsName, fullpath); 00128 } 00129 else 00130 This->pwcsName = NULL; 00131 00132 TRACE("file len %u\n", This->filesize.u.LowPart); 00133 00134 *pLockBytes = &This->ILockBytes_iface; 00135 00136 return S_OK; 00137 } 00138 00139 /* ILockByte Interfaces */ 00140 00141 static HRESULT WINAPI FileLockBytesImpl_QueryInterface(ILockBytes *iface, REFIID riid, 00142 void **ppvObject) 00143 { 00144 if (IsEqualIID(riid, &IID_ILockBytes) || IsEqualIID(riid, &IID_ILockBytes)) 00145 *ppvObject = iface; 00146 else 00147 { 00148 *ppvObject = NULL; 00149 return E_NOINTERFACE; 00150 } 00151 00152 IUnknown_AddRef((IUnknown*)*ppvObject); 00153 00154 return S_OK; 00155 } 00156 00157 static ULONG WINAPI FileLockBytesImpl_AddRef(ILockBytes *iface) 00158 { 00159 FileLockBytesImpl* This = impl_from_ILockBytes(iface); 00160 return InterlockedIncrement(&This->ref); 00161 } 00162 00163 static ULONG WINAPI FileLockBytesImpl_Release(ILockBytes *iface) 00164 { 00165 FileLockBytesImpl* This = impl_from_ILockBytes(iface); 00166 ULONG ref; 00167 00168 ref = InterlockedDecrement(&This->ref); 00169 00170 if (ref == 0) 00171 { 00172 CloseHandle(This->hfile); 00173 HeapFree(GetProcessHeap(), 0, This->pwcsName); 00174 HeapFree(GetProcessHeap(), 0, This); 00175 } 00176 00177 return ref; 00178 } 00179 00180 /****************************************************************************** 00181 * This method is part of the ILockBytes interface. 00182 * 00183 * It reads a block of information from the byte array at the specified 00184 * offset. 00185 * 00186 * See the documentation of ILockBytes for more info. 00187 */ 00188 static HRESULT WINAPI FileLockBytesImpl_ReadAt( 00189 ILockBytes* iface, 00190 ULARGE_INTEGER ulOffset, /* [in] */ 00191 void* pv, /* [length_is][size_is][out] */ 00192 ULONG cb, /* [in] */ 00193 ULONG* pcbRead) /* [out] */ 00194 { 00195 FileLockBytesImpl* This = impl_from_ILockBytes(iface); 00196 ULONG bytes_left = cb; 00197 LPBYTE readPtr = pv; 00198 BOOL ret; 00199 LARGE_INTEGER offset; 00200 ULONG cbRead; 00201 00202 TRACE("(%p)-> %i %p %i %p\n",This, ulOffset.u.LowPart, pv, cb, pcbRead); 00203 00204 /* verify a sane environment */ 00205 if (!This) return E_FAIL; 00206 00207 if (pcbRead) 00208 *pcbRead = 0; 00209 00210 offset.QuadPart = ulOffset.QuadPart; 00211 00212 ret = SetFilePointerEx(This->hfile, offset, NULL, FILE_BEGIN); 00213 00214 if (!ret) 00215 return STG_E_READFAULT; 00216 00217 while (bytes_left) 00218 { 00219 ret = ReadFile(This->hfile, readPtr, bytes_left, &cbRead, NULL); 00220 00221 if (!ret || cbRead == 0) 00222 return STG_E_READFAULT; 00223 00224 if (pcbRead) 00225 *pcbRead += cbRead; 00226 00227 bytes_left -= cbRead; 00228 readPtr += cbRead; 00229 } 00230 00231 TRACE("finished\n"); 00232 return S_OK; 00233 } 00234 00235 /****************************************************************************** 00236 * This method is part of the ILockBytes interface. 00237 * 00238 * It writes the specified bytes at the specified offset. 00239 * position. If the file is too small, it will be resized. 00240 * 00241 * See the documentation of ILockBytes for more info. 00242 */ 00243 static HRESULT WINAPI FileLockBytesImpl_WriteAt( 00244 ILockBytes* iface, 00245 ULARGE_INTEGER ulOffset, /* [in] */ 00246 const void* pv, /* [size_is][in] */ 00247 ULONG cb, /* [in] */ 00248 ULONG* pcbWritten) /* [out] */ 00249 { 00250 FileLockBytesImpl* This = impl_from_ILockBytes(iface); 00251 ULONG size_needed = ulOffset.u.LowPart + cb; 00252 ULONG bytes_left = cb; 00253 const BYTE *writePtr = pv; 00254 BOOL ret; 00255 LARGE_INTEGER offset; 00256 ULONG cbWritten; 00257 00258 TRACE("(%p)-> %i %p %i %p\n",This, ulOffset.u.LowPart, pv, cb, pcbWritten); 00259 00260 /* verify a sane environment */ 00261 if (!This) return E_FAIL; 00262 00263 if (This->flProtect != PAGE_READWRITE) 00264 return STG_E_ACCESSDENIED; 00265 00266 if (pcbWritten) 00267 *pcbWritten = 0; 00268 00269 if (size_needed > This->filesize.u.LowPart) 00270 { 00271 ULARGE_INTEGER newSize; 00272 newSize.u.HighPart = 0; 00273 newSize.u.LowPart = size_needed; 00274 ILockBytes_SetSize(iface, newSize); 00275 } 00276 00277 offset.QuadPart = ulOffset.QuadPart; 00278 00279 ret = SetFilePointerEx(This->hfile, offset, NULL, FILE_BEGIN); 00280 00281 if (!ret) 00282 return STG_E_READFAULT; 00283 00284 while (bytes_left) 00285 { 00286 ret = WriteFile(This->hfile, writePtr, bytes_left, &cbWritten, NULL); 00287 00288 if (!ret) 00289 return STG_E_READFAULT; 00290 00291 if (pcbWritten) 00292 *pcbWritten += cbWritten; 00293 00294 bytes_left -= cbWritten; 00295 writePtr += cbWritten; 00296 } 00297 00298 TRACE("finished\n"); 00299 return S_OK; 00300 } 00301 00302 static HRESULT WINAPI FileLockBytesImpl_Flush(ILockBytes* iface) 00303 { 00304 return S_OK; 00305 } 00306 00307 /****************************************************************************** 00308 * ILockBytes_SetSize 00309 * 00310 * Sets the size of the file. 00311 * 00312 */ 00313 static HRESULT WINAPI FileLockBytesImpl_SetSize(ILockBytes* iface, ULARGE_INTEGER newSize) 00314 { 00315 FileLockBytesImpl* This = impl_from_ILockBytes(iface); 00316 HRESULT hr = S_OK; 00317 LARGE_INTEGER newpos; 00318 00319 if (This->filesize.u.LowPart == newSize.u.LowPart) 00320 return hr; 00321 00322 TRACE("from %u to %u\n", This->filesize.u.LowPart, newSize.u.LowPart); 00323 00324 newpos.QuadPart = newSize.QuadPart; 00325 if (SetFilePointerEx(This->hfile, newpos, NULL, FILE_BEGIN)) 00326 { 00327 SetEndOfFile(This->hfile); 00328 } 00329 00330 This->filesize = newSize; 00331 return hr; 00332 } 00333 00334 static HRESULT WINAPI FileLockBytesImpl_LockRegion(ILockBytes* iface, 00335 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) 00336 { 00337 FIXME("stub\n"); 00338 return E_NOTIMPL; 00339 } 00340 00341 static HRESULT WINAPI FileLockBytesImpl_UnlockRegion(ILockBytes* iface, 00342 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) 00343 { 00344 FIXME("stub\n"); 00345 return E_NOTIMPL; 00346 } 00347 00348 static HRESULT WINAPI FileLockBytesImpl_Stat(ILockBytes* iface, 00349 STATSTG *pstatstg, DWORD grfStatFlag) 00350 { 00351 FileLockBytesImpl* This = impl_from_ILockBytes(iface); 00352 00353 if (!(STATFLAG_NONAME & grfStatFlag) && This->pwcsName) 00354 { 00355 pstatstg->pwcsName = 00356 CoTaskMemAlloc((lstrlenW(This->pwcsName)+1)*sizeof(WCHAR)); 00357 00358 strcpyW(pstatstg->pwcsName, This->pwcsName); 00359 } 00360 else 00361 pstatstg->pwcsName = NULL; 00362 00363 pstatstg->type = STGTY_LOCKBYTES; 00364 pstatstg->cbSize = This->filesize; 00365 /* FIXME: If the implementation is exported, we'll need to set other fields. */ 00366 00367 return S_OK; 00368 } 00369 00370 static const ILockBytesVtbl FileLockBytesImpl_Vtbl = { 00371 FileLockBytesImpl_QueryInterface, 00372 FileLockBytesImpl_AddRef, 00373 FileLockBytesImpl_Release, 00374 FileLockBytesImpl_ReadAt, 00375 FileLockBytesImpl_WriteAt, 00376 FileLockBytesImpl_Flush, 00377 FileLockBytesImpl_SetSize, 00378 FileLockBytesImpl_LockRegion, 00379 FileLockBytesImpl_UnlockRegion, 00380 FileLockBytesImpl_Stat 00381 }; Generated on Sat May 26 2012 04:24:08 for ReactOS by
1.7.6.1
|