40#define NONAMELESSUNION
220 return This->numBlocks;
295 ERR(
"unknown flags %08x\n", stgm);
386 ERR(
"Invalid share mode!\n");
407 ERR(
"Invalid access mode!\n");
425 FIXME(
"STGM_CONVERT not implemented!\n");
430 ERR(
"Invalid create mode!\n");
448 return IStorage_QueryInterface(&
This->IStorage_iface,
riid,
obj);
454 return IStorage_AddRef(&
This->IStorage_iface);
460 return IStorage_Release(&
This->IStorage_iface);
516 while (diff == 0 && *
name1 != 0)
541 currentEntry =
data->dirRootEntry;
556 currentEntry =
data->leftChild;
559 currentEntry =
data->rightChild;
584 *parentEntry = storageEntry;
603 *parentData = childData;
604 *parentEntry = childEntry;
612 *parentData = childData;
613 *parentEntry = childEntry;
631 entry->leftChild = new_target;
634 entry->rightChild = new_target;
637 entry->dirRootEntry = new_target;
652 DirRef parentStorageIndex,
773 DirRef parentStorageIndex,
779 ULONG typeOfRelation;
791 &parentEntry, &parentEntryRef, &typeOfRelation);
827 &newRightChildParentEntry);
834 newRightChildParent = newRightChildParentEntry.
rightChild;
842 &newRightChildParentEntry);
899 IStorage_Release(&
This->parentStorage->IStorage_iface);
921 IEnumSTATSTG_AddRef(&
This->IEnumSTATSTG_iface);
926 TRACE(
"<-- E_NOINTERFACE\n");
967 This->parentStorage->storageDirEntry, &
entry);
968 searchNode =
entry.dirRootEntry;
980 searchNode =
entry.rightChild;
985 memcpy(result_name,
entry.name,
sizeof(result_name));
986 searchNode =
entry.leftChild;
995 memcpy(
This->name, result_name,
sizeof(result_name));
1006 ULONG* pceltFetched)
1011 STATSTG* currentReturnStruct = rgelt;
1012 ULONG objectFetched = 0;
1013 DirRef currentSearchNode;
1016 TRACE(
"%p,%u,%p,%p\n", iface, celt, rgelt, pceltFetched);
1018 if ( (rgelt==0) || ( (celt!=1) && (pceltFetched==0) ) )
1021 if (
This->parentStorage->reverted)
1023 TRACE(
"<-- STG_E_REVERTED\n");
1031 if (pceltFetched==0)
1032 pceltFetched = &objectFetched;
1040 while ( *pceltFetched < celt )
1046 memset(currentReturnStruct, 0,
sizeof(*currentReturnStruct));
1062 currentReturnStruct,
1070 currentReturnStruct++;
1076 TRACE(
"<-- %08x (asked %u, got %u)\n",
hr, celt, *pceltFetched);
1087 ULONG objectFetched = 0;
1088 DirRef currentSearchNode;
1091 TRACE(
"%p,%u\n", iface, celt);
1093 if (
This->parentStorage->reverted)
1095 TRACE(
"<-- STG_E_REVERTED\n");
1099 while ( (objectFetched < celt) )
1121 TRACE(
"%p\n", iface);
1123 if (
This->parentStorage->reverted)
1125 TRACE(
"<-- STG_E_REVERTED\n");
1143 TRACE(
"%p,%p\n", iface, ppenum);
1145 if (
This->parentStorage->reverted)
1147 TRACE(
"<-- STG_E_REVERTED\n");
1155 This->storageDirEntry);
1198 newEnumeration->
ref = 1;
1199 newEnumeration->
name[0] = 0;
1211 return newEnumeration;
1262 TRACE(
"<-- E_NOINTERFACE\n");
1266 IStorage_AddRef(iface);
1322 SNB snbExclude,
IStorage *pstgDest);
1326 SNB snbExclude,
IStorage *pstgDest)
1345 WCHAR **snb = snbExclude;
1357 if (
data.stgType == STGTY_STORAGE && !skip_storage)
1362 hr = IStorage_CreateStorage( pstgDest,
data.name,
1372 hr = IStorage_OpenStorage( pstgDest,
data.name,
NULL,
1374 NULL, 0, &pstgTmp );
1380 skip_stream,
NULL, pstgTmp );
1382 IStorage_Release(pstgTmp);
1385 else if (
data.stgType == STGTY_STREAM && !skip_stream)
1391 hr = IStorage_CreateStream( pstgDest,
data.name,
1407 IStream_AddRef(pstrChild);
1421 IStream_Stat( pstrChild, &strStat, STATFLAG_NONAME );
1426 IStream_SetSize(pstrTmp, strStat.cbSize);
1431 hr = IStream_CopyTo( pstrChild, pstrTmp, strStat.cbSize,
1434 IStream_Release( pstrChild );
1437 IStream_Release( pstrTmp );
1444 skip_stream, snbExclude, pstgDest );
1448 skip_stream, snbExclude, pstgDest );
1458 TRACE(
"%p,%d\n", stg, streamEntry);
1475 TRACE(
"%p,%d\n", stg, storageEntry);
1479 if (childstg->
base.storageDirEntry == storageEntry)
1509 TRACE(
"(%p, %s, %p, %x, %d, %p)\n",
1512 if ( (pwcsName==
NULL) || (ppstm==0) )
1559 This->storageDirEntry,
1567 (currentEntry.
stgType==STGTY_STREAM) )
1583 IStream_AddRef(*ppstm);
1597 TRACE(
"<-- IStream %p\n", *ppstm);
1625 TRACE(
"(%p, %s, %p, %x, %p, %d, %p)\n",
1627 grfMode, snbExclude,
reserved, ppstg);
1629 if ((pwcsName==
NULL) || (ppstg==0) )
1642 if (snbExclude !=
NULL)
1684 This->storageDirEntry,
1689 (currentEntry.
stgType==STGTY_STORAGE) )
1703 if (newStorage != 0)
1719 *ppstg = &newStorage->
base.IStorage_iface;
1757 TRACE(
"(%p, %d, %p, %d, %p)\n",
1768 This->storageDirEntry);
1795 TRACE(
"(%p, %p, %x)\n",
1796 iface, pstatstg, grfStatFlag);
1812 This->storageDirEntry,
1823 pstatstg->grfMode =
This->openFlags;
1824 pstatstg->grfStateBits =
This->stateBits;
1830 TRACE(
"<-- STATSTG: pwcsName: %s, type: %d, cbSize.Low/High: %d/%d, grfMode: %08x, grfLocksSupported: %d, grfStateBits: %08x\n",
debugstr_w(pstatstg->pwcsName), pstatstg->type, pstatstg->cbSize.u.LowPart, pstatstg->cbSize.u.HighPart, pstatstg->grfMode, pstatstg->grfLocksSupported, pstatstg->grfStateBits);
1852 TRACE(
"(%p, %s, %s)\n",
1859 This->storageDirEntry,
1875 This->storageDirEntry,
1884 WARN(
"Element is already open; cannot rename.\n");
1934 DirEntry currentEntry, newStreamEntry;
1935 DirRef currentEntryRef, newStreamEntryRef;
1938 TRACE(
"(%p, %s, %x, %d, %d, %p)\n",
1987 This->storageDirEntry,
1998 IStorage_DestroyElement(iface, pwcsName);
2017 newStreamEntry.
stgType = STGTY_STREAM;
2019 newStreamEntry.
size.
u.LowPart = 0;
2020 newStreamEntry.
size.
u.HighPart = 0;
2045 This->storageDirEntry,
2061 IStream_AddRef(*ppstm);
2093 This->storageDirEntry,
2100 This->storageDirEntry,
2133 TRACE(
"(%p, %s, %x, %d, %d, %p)\n",
2153 WARN(
"bad grfMode: 0x%x\n", grfMode);
2166 WARN(
"access denied\n");
2171 This->storageDirEntry,
2184 hr = IStorage_DestroyElement(iface, pwcsName);
2190 WARN(
"file already exists\n");
2197 WARN(
"read-only storage\n");
2207 FIXME(
"name too long\n");
2213 newEntry.
stgType = STGTY_STORAGE;
2215 newEntry.
size.
u.LowPart = 0;
2216 newEntry.
size.
u.HighPart = 0;
2241 This->storageDirEntry,
2252 hr = IStorage_OpenStorage(iface, pwcsName, 0, grfMode, 0, 0, ppstg);
2267 SNB snbExclude,
IStorage *pstgDest)
2275 hr = IStorage_SetClass( pstgDest, &
data.clsid );
2279 skip_stream, snbExclude, pstgDest );
2291 const IID* rgiidExclude,
2300 TRACE(
"(%p, %d, %p, %p, %p)\n",
2301 iface, ciidExclude, rgiidExclude,
2302 snbExclude, pstgDest);
2304 if ( pstgDest == 0 )
2307 for(
i = 0;
i < ciidExclude; ++
i)
2310 skip_storage =
TRUE;
2322 IStorage *pstgDestAncestor = pstgDest;
2326 while (pstgDestAncestor != iface) {
2327 pstgDestAncestorChild = pstgDest;
2333 pstgDestAncestor = &
snapshot->transactedParent->IStorage_iface;
2339 pstgDestAncestor = &
internal->parentStorage->IStorage_iface;
2345 if (pstgDestAncestor == iface)
2349 if (pstgDestAncestorChild && snbExclude)
2353 WCHAR **snb = snbExclude;
2357 while ( *snb !=
NULL && fail )
2371 skip_storage, skip_stream, snbExclude, pstgDest );
2384 FIXME(
"(%p %s %p %s %u): stub\n", iface,
2400 DWORD grfCommitFlags)
2403 TRACE(
"(%p %d)\n", iface, grfCommitFlags);
2415 TRACE(
"(%p)\n", iface);
2433 STATSTG currentElement;
2438 TRACE(
"%p,%d\n", parentStorage, indexToDelete);
2443 if (stg->
base.storageDirEntry == indexToDelete)
2452 hr = IStorage_OpenStorage(
2454 entryDataToDelete.
name,
2470 hr = IStorage_EnumElements(childStorage, 0, 0, 0, &elements);
2473 IStorage_Release(childStorage);
2483 hr = IEnumSTATSTG_Next(elements, 1, ¤tElement,
NULL);
2486 destroyHr = IStorage_DestroyElement(childStorage, currentElement.pwcsName);
2495 IEnumSTATSTG_Reset(elements);
2497 }
while ((
hr ==
S_OK) && (destroyHr ==
S_OK));
2499 IStorage_Release(childStorage);
2500 IEnumSTATSTG_Release(elements);
2526 if (strm->
dirEntry == indexToDelete)
2528 TRACE(
"Stream deleted %p\n", strm);
2534 size.u.HighPart = 0;
2549 hr = IStream_SetSize(pis,
size);
2560 IStream_Release(pis);
2601 This->storageDirEntry,
2607 TRACE(
"<-- STG_E_FILENOTFOUND\n");
2611 if ( entryToDelete.
stgType == STGTY_STORAGE )
2618 else if ( entryToDelete.
stgType == STGTY_STREAM )
2637 This->storageDirEntry,
2661 TRACE(
"Streams invalidated (stg=%p strm=%p next=%p prev=%p)\n", stg,strm,
cur->next,
cur->prev);
2706 This->stateBits = (
This->stateBits & ~grfMask) | (grfStateBits & grfMask);
2716 TRACE(
"Stream added (stg=%p strm=%p)\n", stg, strm);
2722 TRACE(
"Stream removed (stg=%p strm=%p)\n", stg,strm);
2734 ULONG bytestocopy, bytesread, byteswritten;
2753 data, &byteswritten);
2757 bytes_copied.
QuadPart += byteswritten;
2782 has_stream = (
data.stgType == STGTY_STREAM &&
data.size.QuadPart != 0);
2784 data.size.QuadPart = 0;
2934 &
This->bigBlockSizeBits);
2939 &
This->smallBlockSizeBits);
2944 &
This->bigBlockDepotCount);
2949 &
This->rootStartBlock);
2954 &
This->transactionSig);
2959 &
This->smallBlockLimit);
2964 &
This->smallBlockDepotStart);
2969 &
This->extBigBlockDepotStart);
2974 &
This->extBigBlockDepotCount);
2987 This->bigBlockSize = 0x000000001 << (
DWORD)
This->bigBlockSizeBits;
2988 This->smallBlockSize = 0x000000001 << (
DWORD)
This->smallBlockSizeBits;
2998 FIXME(
"Broken OLE storage file? bigblock=0x%x, smallblock=0x%x, sblimit=0x%x\n",
2999 This->bigBlockSize,
This->smallBlockSize,
This->smallBlockLimit);
3021 DWORD bytes_read, bytes_written;
3022 DWORD major_version, dirsectorcount;
3033 if (
This->bigBlockSizeBits == 0x9)
3035 else if (
This->bigBlockSizeBits == 0xc)
3039 ERR(
"invalid big block shift 0x%x\n",
This->bigBlockSizeBits);
3080 This->bigBlockSizeBits);
3085 This->smallBlockSizeBits);
3087 if (major_version >= 4)
3089 if (
This->rootBlockChain)
3107 This->bigBlockDepotCount);
3112 This->rootStartBlock);
3117 This->transactionSig);
3122 This->smallBlockLimit);
3127 This->smallBlockDepotStart);
3132 This->smallBlockDepotChain ?
3138 This->extBigBlockDepotStart);
3143 This->extBigBlockDepotCount);
3180 This->rootBlockChain,
3207 This->rootBlockChain,
3303 newData->
size.
u.LowPart);
3308 newData->
size.
u.HighPart);
3323 ULONG currentEntryIndex = 0;
3327 WORD sizeOfNameString;
3342 if (sizeOfNameString == 0)
3347 newEntryIndex = currentEntryIndex;
3355 newEntryIndex = currentEntryIndex;
3357 currentEntryIndex++;
3369 ULONG lastEntry = 0;
3370 ULONG blockCount = 0;
3400 entryIndex = newEntryIndex + 1;
3401 entryIndex < lastEntry;
3418 *
index = newEntryIndex;
3452 &
buffer->sizeOfNameString);
3477 &
buffer->ctime.dwLowDateTime);
3482 &
buffer->ctime.dwHighDateTime);
3487 &
buffer->mtime.dwLowDateTime);
3492 &
buffer->mtime.dwHighDateTime);
3502 &
buffer->size.u.LowPart);
3504 if (
This->bigBlockSize < 4096)
3507 buffer->size.u.HighPart = 0;
3514 &
buffer->size.u.HighPart);
3566 if (out_read) *out_read =
read;
3600 return (wrote ==
This->bigBlockSize);
3617 return (wrote ==
sizeof(
DWORD));
3632 ULONG cbRead, cbWritten;
3650 if(!bbTempChain)
return NULL;
3689 offset.u.LowPart += cbRead;
3699 size.u.HighPart = 0;
3704 ERR(
"conversion failed: resRead = 0x%08x, resWrite = 0x%08x\n", resRead, resWrite);
3713 streamEntryRef = (*ppsbChain)->ownerDirEntry;
3737 return bigBlockChain;
3789 cbRead,
buffer, &cbWritten);
3794 offset.u.LowPart += cbRead;
3804 size.u.HighPart = 0;
3809 ERR(
"conversion failed: resRead = 0x%08x, resWrite = 0x%08x\n", resRead, resWrite);
3816 streamEntryRef = (*ppbbChain)->ownerDirEntry;
3840 ULONG rangeLockDepot = rangeLockIndex / blocksPerDepot;
3848 if (depotIndex == rangeLockDepot)
3865 ULONG depotBlocksPerExtBlock = (
This->bigBlockSize /
sizeof(
ULONG)) - 1;
3867 ULONG extBlockCount = numExtBlocks / depotBlocksPerExtBlock;
3868 ULONG extBlockOffset = numExtBlocks % depotBlocksPerExtBlock;
3870 ULONG extBlockIndex;
3876 if (extBlockCount >=
This->extBigBlockDepotCount)
3879 if (
This->indexExtBlockDepotCached != extBlockCount)
3881 extBlockIndex =
This->extBigBlockDepotLocations[extBlockCount];
3890 This->extBlockDepotCached[
index] = blockIndex;
3893 This->indexExtBlockDepotCached = extBlockCount;
3896 blockIndex =
This->extBlockDepotCached[extBlockOffset];
3910 ULONG depotBlocksPerExtBlock = (
This->bigBlockSize /
sizeof(
ULONG)) - 1;
3912 ULONG extBlockCount = numExtBlocks / depotBlocksPerExtBlock;
3913 ULONG extBlockOffset = numExtBlocks % depotBlocksPerExtBlock;
3914 ULONG extBlockIndex;
3918 assert(extBlockCount < This->extBigBlockDepotCount);
3920 extBlockIndex =
This->extBigBlockDepotLocations[extBlockCount];
3925 extBlockOffset *
sizeof(
ULONG),
3929 if (
This->indexExtBlockDepotCached == extBlockCount)
3931 This->extBlockDepotCached[extBlockOffset] = blockIndex;
3942 ULONG numExtBlocks =
This->extBigBlockDepotCount;
3943 ULONG nextExtBlock =
This->extBigBlockDepotStart;
3948 ULONG depotBlocksPerExtBlock = blocksPerDepotBlock - 1;
3951 blocksPerDepotBlock;
3965 nextExtBlock =
This->extBigBlockDepotLocations[
This->extBigBlockDepotCount-1];
3981 if (
This->extBigBlockDepotLocationsSize == numExtBlocks)
3983 ULONG new_cache_size = (
This->extBigBlockDepotLocationsSize+1)*2;
3986 memcpy(new_cache,
This->extBigBlockDepotLocations,
sizeof(
ULONG) *
This->extBigBlockDepotLocationsSize);
3989 This->extBigBlockDepotLocations = new_cache;
3990 This->extBigBlockDepotLocationsSize = new_cache_size;
3992 This->extBigBlockDepotLocations[numExtBlocks] =
index;
4024 ULONG* nextBlockIndex)
4026 ULONG offsetInDepot = blockIndex *
sizeof (
ULONG);
4027 ULONG depotBlockCount = offsetInDepot /
This->bigBlockSize;
4028 ULONG depotBlockOffset = offsetInDepot %
This->bigBlockSize;
4031 ULONG depotBlockIndexPos;
4036 if(depotBlockCount >=
This->bigBlockDepotCount)
4038 WARN(
"depotBlockCount %d, bigBlockDepotCount %d\n", depotBlockCount,
4039 This->bigBlockDepotCount);
4046 if (depotBlockCount !=
This->indexBlockDepotCached)
4048 This->indexBlockDepotCached = depotBlockCount;
4052 depotBlockIndexPos =
This->bigBlockDepotStart[depotBlockCount];
4072 This->blockDepotCached[
index] = *nextBlockIndex;
4076 *nextBlockIndex =
This->blockDepotCached[depotBlockOffset/
sizeof(
ULONG)];
4104 return nextBlockIndex;
4126 ULONG offsetInDepot = blockIndex *
sizeof (
ULONG);
4127 ULONG depotBlockCount = offsetInDepot /
This->bigBlockSize;
4128 ULONG depotBlockOffset = offsetInDepot %
This->bigBlockSize;
4129 ULONG depotBlockIndexPos;
4131 assert(depotBlockCount < This->bigBlockDepotCount);
4132 assert(blockIndex != nextBlock);
4139 ERR(
"Using range lock page\n");
4143 depotBlockIndexPos =
This->bigBlockDepotStart[depotBlockCount];
4158 if (depotBlockCount ==
This->indexBlockDepotCached)
4160 This->blockDepotCached[depotBlockOffset/
sizeof(
ULONG)] = nextBlock;
4174 ULONG depotBlockIndexPos;
4176 ULONG depotBlockOffset;
4185 depotIndex =
This->prevFreeBlock / blocksPerDepot;
4186 depotBlockOffset = (
This->prevFreeBlock % blocksPerDepot) *
sizeof(
ULONG);
4195 depotBlockIndexPos =
This->bigBlockDepotStart[depotIndex];
4202 depotBlockIndexPos = depotIndex*blocksPerDepot;
4208 This->bigBlockDepotCount++;
4209 This->bigBlockDepotStart[depotIndex] = depotBlockIndexPos;
4234 ULONG extBlockOffset = numExtBlocks % (blocksPerDepot - 1);
4236 if (extBlockOffset == 0)
4241 This->extBigBlockDepotCount++;
4242 depotBlockIndexPos = extIndex + 1;
4245 depotBlockIndexPos = depotIndex * blocksPerDepot;
4251 This->bigBlockDepotCount++;
4275 while ( ( (depotBlockOffset/
sizeof(
ULONG) ) < blocksPerDepot) &&
4282 freeBlock = (depotIndex * blocksPerDepot) +
4283 (depotBlockOffset/
sizeof(
ULONG));
4286 depotBlockOffset +=
sizeof(
ULONG);
4291 depotBlockOffset = 0;
4299 ILockBytes_Stat(
This->lockBytes, &statstg, STATFLAG_NONAME);
4301 if (neededSize.
QuadPart > statstg.cbSize.QuadPart)
4302 ILockBytes_SetSize(
This->lockBytes, neededSize);
4304 This->prevFreeBlock = freeBlock;
4320 if (blockIndex < This->prevFreeBlock)
4321 This->prevFreeBlock = blockIndex;
4345 if (!
This->blockChainCache[
i])
4347 return &
This->blockChainCache[
i];
4351 i =
This->blockChainToEvict;
4356 This->blockChainToEvict++;
4358 This->blockChainToEvict = 0;
4360 return &
This->blockChainCache[
i];
4366 int i, free_index=-1;
4370 if (!
This->blockChainCache[
i])
4372 if (free_index == -1) free_index =
i;
4374 else if (
This->blockChainCache[
i]->ownerDirEntry ==
index)
4376 return &
This->blockChainCache[
i];
4380 if (free_index == -1)
4382 free_index =
This->blockChainToEvict;
4385 This->blockChainCache[free_index] =
NULL;
4387 This->blockChainToEvict++;
4389 This->blockChainToEvict = 0;
4393 return &
This->blockChainCache[free_index];
4402 if (
This->blockChainCache[
i] &&
This->blockChainCache[
i]->ownerDirEntry ==
index)
4422 if (
data.size.QuadPart == 0)
4430 bytesToRead =
data.size.QuadPart -
offset.QuadPart;
4483 if (
data.size.QuadPart == 0)
4493 bigblock = *pbigblock;
4505 bigblock = *pbigblock;
4520 *pbigblock = bigblock;
4544 data.size = newsize;
4637 ILockBytes_SetSize(
This->lockBytes,
size);
4647 sizeof(
This->bigBlockDepotStart));
4649 This->bigBlockDepotCount = 1;
4650 This->bigBlockDepotStart[0] = 0;
4651 This->rootStartBlock = 1;
4654 if (
This->bigBlockSize == 4096)
4660 This->extBigBlockDepotCount = 0;
4667 size.u.HighPart = 0;
4668 size.u.LowPart =
This->bigBlockSize * 3;
4669 ILockBytes_SetSize(
This->lockBytes,
size);
4695 This->indexBlockDepotCached = 0xFFFFFFFF;
4696 This->indexExtBlockDepotCached = 0xFFFFFFFF;
4701 This->prevFreeBlock = 0;
4703 This->firstFreeSmallBlock = 0;
4706 if (
This->extBigBlockDepotCount != 0)
4708 ULONG current_block =
This->extBigBlockDepotStart;
4709 ULONG cache_size =
This->extBigBlockDepotCount * 2;
4713 if (!
This->extBigBlockDepotLocations)
4718 This->extBigBlockDepotLocationsSize = cache_size;
4720 for (
i=0;
i<
This->extBigBlockDepotCount;
i++)
4724 WARN(
"File has too few extended big block depot blocks.\n");
4727 This->extBigBlockDepotLocations[
i] = current_block;
4733 This->extBigBlockDepotLocations =
NULL;
4734 This->extBigBlockDepotLocationsSize = 0;
4740 if(!(blockChainStream =
4747 This->rootBlockChain = blockChainStream;
4749 if(!(blockChainStream =
4757 This->smallBlockDepotChain = blockChainStream;
4764 static const WCHAR rootentryW[] = {
'R',
'o',
'o',
't',
' ',
'E',
'n',
't',
'r',
'y',0};
4769 memset(&rootEntry, 0,
sizeof(rootEntry));
4777 rootEntry.
size.
u.HighPart = 0;
4778 rootEntry.
size.
u.LowPart = 0;
4786 currentEntryRef = 0;
4800 This->base.storageDirEntry = currentEntryRef;
4816 if(!(blockChainStream =
4823 This->smallBlockRootChain = blockChainStream;
4843 DWORD oldTransactionSig =
This->transactionSig;
4859 if (oldTransactionSig !=
This->transactionSig)
4862 TRACE(
"signature changed\n");
4868 This->transactionSig = oldTransactionSig;
4891 if ((dwLockType &
This->locks_supported) == 0)
4893 if (supported) *supported =
FALSE;
4897 if (supported) *supported =
TRUE;
4898 return ILockBytes_LockRegion(
This->lockBytes,
offset,
cb, dwLockType);
4904 if ((dwLockType &
This->locks_supported) == 0)
4907 return ILockBytes_UnlockRegion(
This->lockBytes,
offset,
cb, dwLockType);
4917 DWORD last_sanity_check = start_time;