Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenistream.c
Go to the documentation of this file.
00001 /* 00002 * SHLWAPI IStream functions 00003 * 00004 * Copyright 2002 Jon Griffiths 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 #include <stdarg.h> 00021 #include <string.h> 00022 00023 #define COBJMACROS 00024 #define NONAMELESSUNION 00025 #define NONAMELESSSTRUCT 00026 00027 #include "windef.h" 00028 #include "winbase.h" 00029 #include "winerror.h" 00030 #include "winnls.h" 00031 #define NO_SHLWAPI_REG 00032 #define NO_SHLWAPI_PATH 00033 #include "shlwapi.h" 00034 #include "wine/debug.h" 00035 00036 WINE_DEFAULT_DEBUG_CHANNEL(shell); 00037 00038 #define STGM_ACCESS_MODE(stgm) ((stgm)&0x0000f) 00039 #define STGM_SHARE_MODE(stgm) ((stgm)&0x000f0) 00040 #define STGM_CREATE_MODE(stgm) ((stgm)&0x0f000) 00041 00042 /* Layout of ISHFileStream object */ 00043 typedef struct 00044 { 00045 const IStreamVtbl *lpVtbl; 00046 LONG ref; 00047 HANDLE hFile; 00048 DWORD dwMode; 00049 LPOLESTR lpszPath; 00050 DWORD type; 00051 DWORD grfStateBits; 00052 } ISHFileStream; 00053 00054 static HRESULT WINAPI IStream_fnCommit(IStream*,DWORD); 00055 00056 00057 /************************************************************************** 00058 * IStream_fnQueryInterface 00059 */ 00060 static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface, REFIID riid, LPVOID *ppvObj) 00061 { 00062 ISHFileStream *This = (ISHFileStream *)iface; 00063 00064 TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppvObj); 00065 00066 *ppvObj = NULL; 00067 00068 if(IsEqualIID(riid, &IID_IUnknown) || 00069 IsEqualIID(riid, &IID_IStream)) 00070 { 00071 *ppvObj = This; 00072 IStream_AddRef(iface); 00073 return S_OK; 00074 } 00075 return E_NOINTERFACE; 00076 } 00077 00078 /************************************************************************** 00079 * IStream_fnAddRef 00080 */ 00081 static ULONG WINAPI IStream_fnAddRef(IStream *iface) 00082 { 00083 ISHFileStream *This = (ISHFileStream *)iface; 00084 ULONG refCount = InterlockedIncrement(&This->ref); 00085 00086 TRACE("(%p)->(ref before=%u)\n",This, refCount - 1); 00087 00088 return refCount; 00089 } 00090 00091 /************************************************************************** 00092 * IStream_fnRelease 00093 */ 00094 static ULONG WINAPI IStream_fnRelease(IStream *iface) 00095 { 00096 ISHFileStream *This = (ISHFileStream *)iface; 00097 ULONG refCount = InterlockedDecrement(&This->ref); 00098 00099 TRACE("(%p)->(ref before=%u)\n",This, refCount + 1); 00100 00101 if (!refCount) 00102 { 00103 IStream_fnCommit(iface, 0); /* If ever buffered, this will be needed */ 00104 LocalFree(This->lpszPath); 00105 CloseHandle(This->hFile); 00106 HeapFree(GetProcessHeap(), 0, This); 00107 } 00108 00109 return refCount; 00110 } 00111 00112 /************************************************************************** 00113 * IStream_fnRead 00114 */ 00115 static HRESULT WINAPI IStream_fnRead(IStream *iface, void* pv, ULONG cb, ULONG* pcbRead) 00116 { 00117 ISHFileStream *This = (ISHFileStream *)iface; 00118 DWORD dwRead = 0; 00119 00120 TRACE("(%p,%p,0x%08x,%p)\n", This, pv, cb, pcbRead); 00121 00122 if (!ReadFile(This->hFile, pv, cb, &dwRead, NULL)) 00123 { 00124 WARN("error %d reading file\n", GetLastError()); 00125 return S_FALSE; 00126 } 00127 if (pcbRead) 00128 *pcbRead = dwRead; 00129 return S_OK; 00130 } 00131 00132 /************************************************************************** 00133 * IStream_fnWrite 00134 */ 00135 static HRESULT WINAPI IStream_fnWrite(IStream *iface, const void* pv, ULONG cb, ULONG* pcbWritten) 00136 { 00137 ISHFileStream *This = (ISHFileStream *)iface; 00138 DWORD dwWritten = 0; 00139 00140 TRACE("(%p,%p,0x%08x,%p)\n", This, pv, cb, pcbWritten); 00141 00142 switch (STGM_ACCESS_MODE(This->dwMode)) 00143 { 00144 case STGM_WRITE: 00145 case STGM_READWRITE: 00146 break; 00147 default: 00148 return STG_E_ACCESSDENIED; 00149 } 00150 00151 if (!WriteFile(This->hFile, pv, cb, &dwWritten, NULL)) 00152 return HRESULT_FROM_WIN32(GetLastError()); 00153 00154 if (pcbWritten) 00155 *pcbWritten = dwWritten; 00156 return S_OK; 00157 } 00158 00159 /************************************************************************** 00160 * IStream_fnSeek 00161 */ 00162 static HRESULT WINAPI IStream_fnSeek(IStream *iface, LARGE_INTEGER dlibMove, 00163 DWORD dwOrigin, ULARGE_INTEGER* pNewPos) 00164 { 00165 ISHFileStream *This = (ISHFileStream *)iface; 00166 DWORD dwPos; 00167 00168 TRACE("(%p,%d,%d,%p)\n", This, dlibMove.u.LowPart, dwOrigin, pNewPos); 00169 00170 IStream_fnCommit(iface, 0); /* If ever buffered, this will be needed */ 00171 dwPos = SetFilePointer(This->hFile, dlibMove.u.LowPart, NULL, dwOrigin); 00172 if( dwPos == INVALID_SET_FILE_POINTER ) 00173 return HRESULT_FROM_WIN32(GetLastError()); 00174 00175 if (pNewPos) 00176 { 00177 pNewPos->u.HighPart = 0; 00178 pNewPos->u.LowPart = dwPos; 00179 } 00180 return S_OK; 00181 } 00182 00183 /************************************************************************** 00184 * IStream_fnSetSize 00185 */ 00186 static HRESULT WINAPI IStream_fnSetSize(IStream *iface, ULARGE_INTEGER libNewSize) 00187 { 00188 ISHFileStream *This = (ISHFileStream *)iface; 00189 00190 TRACE("(%p,%d)\n", This, libNewSize.u.LowPart); 00191 00192 IStream_fnCommit(iface, 0); /* If ever buffered, this will be needed */ 00193 if( ! SetFilePointer( This->hFile, libNewSize.QuadPart, NULL, FILE_BEGIN ) ) 00194 return E_FAIL; 00195 00196 if( ! SetEndOfFile( This->hFile ) ) 00197 return E_FAIL; 00198 00199 return S_OK; 00200 } 00201 00202 /************************************************************************** 00203 * IStream_fnCopyTo 00204 */ 00205 static HRESULT WINAPI IStream_fnCopyTo(IStream *iface, IStream* pstm, ULARGE_INTEGER cb, 00206 ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) 00207 { 00208 ISHFileStream *This = (ISHFileStream *)iface; 00209 char copyBuff[1024]; 00210 ULONGLONG ulSize; 00211 HRESULT hRet = S_OK; 00212 00213 TRACE("(%p,%p,%d,%p,%p)\n", This, pstm, cb.u.LowPart, pcbRead, pcbWritten); 00214 00215 if (pcbRead) 00216 pcbRead->QuadPart = 0; 00217 if (pcbWritten) 00218 pcbWritten->QuadPart = 0; 00219 00220 if (!pstm) 00221 return S_OK; 00222 00223 IStream_fnCommit(iface, 0); /* If ever buffered, this will be needed */ 00224 00225 /* Copy data */ 00226 ulSize = cb.QuadPart; 00227 while (ulSize) 00228 { 00229 ULONG ulLeft, ulAmt; 00230 00231 ulLeft = ulSize > sizeof(copyBuff) ? sizeof(copyBuff) : ulSize; 00232 00233 /* Read */ 00234 hRet = IStream_fnRead(iface, copyBuff, ulLeft, &ulAmt); 00235 if (pcbRead) 00236 pcbRead->QuadPart += ulAmt; 00237 if (FAILED(hRet) || ulAmt != ulLeft) 00238 break; 00239 00240 /* Write */ 00241 hRet = IStream_fnWrite(pstm, copyBuff, ulLeft, &ulAmt); 00242 if (pcbWritten) 00243 pcbWritten->QuadPart += ulAmt; 00244 if (FAILED(hRet) || ulAmt != ulLeft) 00245 break; 00246 00247 ulSize -= ulLeft; 00248 } 00249 return hRet; 00250 } 00251 00252 /************************************************************************** 00253 * IStream_fnCommit 00254 */ 00255 static HRESULT WINAPI IStream_fnCommit(IStream *iface, DWORD grfCommitFlags) 00256 { 00257 ISHFileStream *This = (ISHFileStream *)iface; 00258 00259 TRACE("(%p,%d)\n", This, grfCommitFlags); 00260 /* Currently unbuffered: This function is not needed */ 00261 return S_OK; 00262 } 00263 00264 /************************************************************************** 00265 * IStream_fnRevert 00266 */ 00267 static HRESULT WINAPI IStream_fnRevert(IStream *iface) 00268 { 00269 ISHFileStream *This = (ISHFileStream *)iface; 00270 00271 TRACE("(%p)\n", This); 00272 return E_NOTIMPL; 00273 } 00274 00275 /************************************************************************** 00276 * IStream_fnLockUnlockRegion 00277 */ 00278 static HRESULT WINAPI IStream_fnLockUnlockRegion(IStream *iface, ULARGE_INTEGER libOffset, 00279 ULARGE_INTEGER cb, DWORD dwLockType) 00280 { 00281 ISHFileStream *This = (ISHFileStream *)iface; 00282 TRACE("(%p,%d,%d,%d)\n", This, libOffset.u.LowPart, cb.u.LowPart, dwLockType); 00283 return E_NOTIMPL; 00284 } 00285 00286 /************************************************************************* 00287 * IStream_fnStat 00288 */ 00289 static HRESULT WINAPI IStream_fnStat(IStream *iface, STATSTG* lpStat, 00290 DWORD grfStatFlag) 00291 { 00292 ISHFileStream *This = (ISHFileStream *)iface; 00293 BY_HANDLE_FILE_INFORMATION fi; 00294 HRESULT hRet = S_OK; 00295 00296 TRACE("(%p,%p,%d)\n", This, lpStat, grfStatFlag); 00297 00298 if (!grfStatFlag) 00299 hRet = STG_E_INVALIDPOINTER; 00300 else 00301 { 00302 memset(&fi, 0, sizeof(fi)); 00303 GetFileInformationByHandle(This->hFile, &fi); 00304 00305 if (grfStatFlag & STATFLAG_NONAME) 00306 lpStat->pwcsName = NULL; 00307 else 00308 lpStat->pwcsName = StrDupW(This->lpszPath); 00309 lpStat->type = This->type; 00310 lpStat->cbSize.u.LowPart = fi.nFileSizeLow; 00311 lpStat->cbSize.u.HighPart = fi.nFileSizeHigh; 00312 lpStat->mtime = fi.ftLastWriteTime; 00313 lpStat->ctime = fi.ftCreationTime; 00314 lpStat->atime = fi.ftLastAccessTime; 00315 lpStat->grfMode = This->dwMode; 00316 lpStat->grfLocksSupported = 0; 00317 memcpy(&lpStat->clsid, &IID_IStream, sizeof(CLSID)); 00318 lpStat->grfStateBits = This->grfStateBits; 00319 lpStat->reserved = 0; 00320 } 00321 return hRet; 00322 } 00323 00324 /************************************************************************* 00325 * IStream_fnClone 00326 */ 00327 static HRESULT WINAPI IStream_fnClone(IStream *iface, IStream** ppstm) 00328 { 00329 ISHFileStream *This = (ISHFileStream *)iface; 00330 00331 TRACE("(%p)\n",This); 00332 if (ppstm) 00333 *ppstm = NULL; 00334 return E_NOTIMPL; 00335 } 00336 00337 static const IStreamVtbl SHLWAPI_fsVTable = 00338 { 00339 IStream_fnQueryInterface, 00340 IStream_fnAddRef, 00341 IStream_fnRelease, 00342 IStream_fnRead, 00343 IStream_fnWrite, 00344 IStream_fnSeek, 00345 IStream_fnSetSize, 00346 IStream_fnCopyTo, 00347 IStream_fnCommit, 00348 IStream_fnRevert, 00349 IStream_fnLockUnlockRegion, 00350 IStream_fnLockUnlockRegion, 00351 IStream_fnStat, 00352 IStream_fnClone 00353 }; 00354 00355 /************************************************************************** 00356 * IStream_Create 00357 * 00358 * Internal helper: Create and initialise a new file stream object. 00359 */ 00360 static IStream *IStream_Create(LPCWSTR lpszPath, HANDLE hFile, DWORD dwMode) 00361 { 00362 ISHFileStream* fileStream; 00363 00364 fileStream = HeapAlloc(GetProcessHeap(), 0, sizeof(ISHFileStream)); 00365 00366 if (fileStream) 00367 { 00368 fileStream->lpVtbl = &SHLWAPI_fsVTable; 00369 fileStream->ref = 1; 00370 fileStream->hFile = hFile; 00371 fileStream->dwMode = dwMode; 00372 fileStream->lpszPath = StrDupW(lpszPath); 00373 fileStream->type = 0; /* FIXME */ 00374 fileStream->grfStateBits = 0; /* FIXME */ 00375 } 00376 TRACE ("Returning %p\n", fileStream); 00377 return (IStream *)fileStream; 00378 } 00379 00380 /************************************************************************* 00381 * SHCreateStreamOnFileEx [SHLWAPI.@] 00382 * 00383 * Create a stream on a file. 00384 * 00385 * PARAMS 00386 * lpszPath [I] Path of file to create stream on 00387 * dwMode [I] Mode to create stream in 00388 * dwAttributes [I] Attributes of the file 00389 * bCreate [I] Whether to create the file if it doesn't exist 00390 * lpTemplate [I] Reserved, must be NULL 00391 * lppStream [O] Destination for created stream 00392 * 00393 * RETURNS 00394 * Success: S_OK. lppStream contains the new stream object 00395 * Failure: E_INVALIDARG if any parameter is invalid, or an HRESULT error code 00396 * 00397 * NOTES 00398 * This function is available in Unicode only. 00399 */ 00400 HRESULT WINAPI SHCreateStreamOnFileEx(LPCWSTR lpszPath, DWORD dwMode, 00401 DWORD dwAttributes, BOOL bCreate, 00402 IStream *lpTemplate, IStream **lppStream) 00403 { 00404 DWORD dwAccess, dwShare, dwCreate; 00405 HANDLE hFile; 00406 00407 TRACE("(%s,%d,0x%08X,%d,%p,%p)\n", debugstr_w(lpszPath), dwMode, 00408 dwAttributes, bCreate, lpTemplate, lppStream); 00409 00410 if (!lpszPath || !lppStream || lpTemplate) 00411 return E_INVALIDARG; 00412 00413 *lppStream = NULL; 00414 00415 /* Access */ 00416 switch (STGM_ACCESS_MODE(dwMode)) 00417 { 00418 case STGM_READWRITE: 00419 dwAccess = GENERIC_READ|GENERIC_WRITE; 00420 break; 00421 case STGM_WRITE: 00422 dwAccess = GENERIC_WRITE; 00423 break; 00424 case STGM_READ: 00425 dwAccess = GENERIC_READ; 00426 break; 00427 default: 00428 return E_INVALIDARG; 00429 } 00430 00431 /* Sharing */ 00432 switch (STGM_SHARE_MODE(dwMode)) 00433 { 00434 case 0: 00435 dwShare = FILE_SHARE_READ|FILE_SHARE_WRITE; 00436 break; 00437 case STGM_SHARE_DENY_READ: 00438 dwShare = FILE_SHARE_WRITE; 00439 break; 00440 case STGM_SHARE_DENY_WRITE: 00441 dwShare = FILE_SHARE_READ; 00442 break; 00443 case STGM_SHARE_EXCLUSIVE: 00444 dwShare = 0; 00445 break; 00446 case STGM_SHARE_DENY_NONE: 00447 dwShare = FILE_SHARE_READ|FILE_SHARE_WRITE; 00448 break; 00449 default: 00450 return E_INVALIDARG; 00451 } 00452 00453 switch(STGM_CREATE_MODE(dwMode)) 00454 { 00455 case STGM_FAILIFTHERE: 00456 dwCreate = bCreate ? CREATE_NEW : OPEN_EXISTING; 00457 break; 00458 case STGM_CREATE: 00459 dwCreate = CREATE_ALWAYS; 00460 break; 00461 default: 00462 return E_INVALIDARG; 00463 } 00464 00465 /* Open HANDLE to file */ 00466 hFile = CreateFileW(lpszPath, dwAccess, dwShare, NULL, dwCreate, 00467 dwAttributes, 0); 00468 00469 if(hFile == INVALID_HANDLE_VALUE) 00470 return HRESULT_FROM_WIN32(GetLastError()); 00471 00472 *lppStream = IStream_Create(lpszPath, hFile, dwMode); 00473 00474 if(!*lppStream) 00475 { 00476 CloseHandle(hFile); 00477 return E_OUTOFMEMORY; 00478 } 00479 return S_OK; 00480 } 00481 00482 /************************************************************************* 00483 * SHCreateStreamOnFileW [SHLWAPI.@] 00484 * 00485 * See SHCreateStreamOnFileA. 00486 */ 00487 HRESULT WINAPI SHCreateStreamOnFileW(LPCWSTR lpszPath, DWORD dwMode, 00488 IStream **lppStream) 00489 { 00490 TRACE("(%s,%d,%p)\n", debugstr_w(lpszPath), dwMode, lppStream); 00491 00492 if (!lpszPath || !lppStream) 00493 return E_INVALIDARG; 00494 00495 if ((dwMode & (STGM_CONVERT|STGM_DELETEONRELEASE|STGM_TRANSACTED)) != 0) 00496 return E_INVALIDARG; 00497 00498 return SHCreateStreamOnFileEx(lpszPath, dwMode, 0, FALSE, NULL, lppStream); 00499 } 00500 00501 /************************************************************************* 00502 * SHCreateStreamOnFileA [SHLWAPI.@] 00503 * 00504 * Create a stream on a file. 00505 * 00506 * PARAMS 00507 * lpszPath [I] Path of file to create stream on 00508 * dwMode [I] Mode to create stream in 00509 * lppStream [O] Destination for created IStream object 00510 * 00511 * RETURNS 00512 * Success: S_OK. lppStream contains the new IStream object 00513 * Failure: E_INVALIDARG if any parameter is invalid, or an HRESULT error code 00514 */ 00515 HRESULT WINAPI SHCreateStreamOnFileA(LPCSTR lpszPath, DWORD dwMode, 00516 IStream **lppStream) 00517 { 00518 WCHAR szPath[MAX_PATH]; 00519 00520 TRACE("(%s,%d,%p)\n", debugstr_a(lpszPath), dwMode, lppStream); 00521 00522 if (!lpszPath) 00523 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); 00524 00525 MultiByteToWideChar(0, 0, lpszPath, -1, szPath, MAX_PATH); 00526 return SHCreateStreamOnFileW(szPath, dwMode, lppStream); 00527 } 00528 00529 /************************************************************************* 00530 * @ [SHLWAPI.184] 00531 * 00532 * Call IStream_Read() on a stream. 00533 * 00534 * PARAMS 00535 * lpStream [I] IStream object 00536 * lpvDest [O] Destination for data read 00537 * ulSize [I] Size of data to read 00538 * 00539 * RETURNS 00540 * Success: S_OK. ulSize bytes have been read from the stream into lpvDest. 00541 * Failure: An HRESULT error code, or E_FAIL if the read succeeded but the 00542 * number of bytes read does not match. 00543 */ 00544 HRESULT WINAPI SHIStream_Read(IStream *lpStream, LPVOID lpvDest, ULONG ulSize) 00545 { 00546 ULONG ulRead; 00547 HRESULT hRet; 00548 00549 TRACE("(%p,%p,%d)\n", lpStream, lpvDest, ulSize); 00550 00551 hRet = IStream_Read(lpStream, lpvDest, ulSize, &ulRead); 00552 00553 if (SUCCEEDED(hRet) && ulRead != ulSize) 00554 hRet = E_FAIL; 00555 return hRet; 00556 } 00557 00558 /************************************************************************* 00559 * @ [SHLWAPI.166] 00560 * 00561 * Determine if a stream has 0 length. 00562 * 00563 * PARAMS 00564 * lpStream [I] IStream object 00565 * 00566 * RETURNS 00567 * TRUE: If the stream has 0 length 00568 * FALSE: Otherwise. 00569 */ 00570 BOOL WINAPI SHIsEmptyStream(IStream *lpStream) 00571 { 00572 STATSTG statstg; 00573 BOOL bRet = TRUE; 00574 00575 TRACE("(%p)\n", lpStream); 00576 00577 memset(&statstg, 0, sizeof(statstg)); 00578 00579 if(SUCCEEDED(IStream_Stat(lpStream, &statstg, 1))) 00580 { 00581 if(statstg.cbSize.QuadPart) 00582 bRet = FALSE; /* Non-Zero */ 00583 } 00584 else 00585 { 00586 DWORD dwDummy; 00587 00588 /* Try to read from the stream */ 00589 if(SUCCEEDED(SHIStream_Read(lpStream, &dwDummy, sizeof(dwDummy)))) 00590 { 00591 LARGE_INTEGER zero; 00592 zero.QuadPart = 0; 00593 00594 IStream_Seek(lpStream, zero, 0, NULL); 00595 bRet = FALSE; /* Non-Zero */ 00596 } 00597 } 00598 return bRet; 00599 } 00600 00601 /************************************************************************* 00602 * @ [SHLWAPI.212] 00603 * 00604 * Call IStream_Write() on a stream. 00605 * 00606 * PARAMS 00607 * lpStream [I] IStream object 00608 * lpvSrc [I] Source for data to write 00609 * ulSize [I] Size of data 00610 * 00611 * RETURNS 00612 * Success: S_OK. ulSize bytes have been written to the stream from lpvSrc. 00613 * Failure: An HRESULT error code, or E_FAIL if the write succeeded but the 00614 * number of bytes written does not match. 00615 */ 00616 HRESULT WINAPI SHIStream_Write(IStream *lpStream, LPCVOID lpvSrc, ULONG ulSize) 00617 { 00618 ULONG ulWritten; 00619 HRESULT hRet; 00620 00621 TRACE("(%p,%p,%d)\n", lpStream, lpvSrc, ulSize); 00622 00623 hRet = IStream_Write(lpStream, lpvSrc, ulSize, &ulWritten); 00624 00625 if (SUCCEEDED(hRet) && ulWritten != ulSize) 00626 hRet = E_FAIL; 00627 00628 return hRet; 00629 } 00630 00631 /************************************************************************* 00632 * @ [SHLWAPI.213] 00633 * 00634 * Seek to the start of a stream. 00635 * 00636 * PARAMS 00637 * lpStream [I] IStream object 00638 * 00639 * RETURNS 00640 * Success: S_OK. The current position within the stream is updated 00641 * Failure: An HRESULT error code. 00642 */ 00643 HRESULT WINAPI IStream_Reset(IStream *lpStream) 00644 { 00645 LARGE_INTEGER zero; 00646 TRACE("(%p)\n", lpStream); 00647 zero.QuadPart = 0; 00648 return IStream_Seek(lpStream, zero, 0, NULL); 00649 } 00650 00651 /************************************************************************* 00652 * @ [SHLWAPI.214] 00653 * 00654 * Get the size of a stream. 00655 * 00656 * PARAMS 00657 * lpStream [I] IStream object 00658 * lpulSize [O] Destination for size 00659 * 00660 * RETURNS 00661 * Success: S_OK. lpulSize contains the size of the stream. 00662 * Failure: An HRESULT error code. 00663 */ 00664 HRESULT WINAPI IStream_Size(IStream *lpStream, ULARGE_INTEGER* lpulSize) 00665 { 00666 STATSTG statstg; 00667 HRESULT hRet; 00668 00669 TRACE("(%p,%p)\n", lpStream, lpulSize); 00670 00671 memset(&statstg, 0, sizeof(statstg)); 00672 00673 hRet = IStream_Stat(lpStream, &statstg, 1); 00674 00675 if (SUCCEEDED(hRet) && lpulSize) 00676 *lpulSize = statstg.cbSize; 00677 return hRet; 00678 } Generated on Fri May 25 2012 04:24:38 for ReactOS by
1.7.6.1
|