⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 storage.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
		while (cb) {
			unsigned int cc;

			if (!STORAGE_get_small_block(&This->str,blocknr,block)) {
			   WARN("small block read failed!!!\n");
				return E_FAIL;
			}
			cc = cb;
			if (cc>SMALLSIZE-(This->offset.u.LowPart&(SMALLSIZE-1)))
				cc=SMALLSIZE-(This->offset.u.LowPart&(SMALLSIZE-1));
			memcpy(pbv,block+(This->offset.u.LowPart&(SMALLSIZE-1)),cc);
			This->offset.u.LowPart+=cc;
			pbv+=cc;
			*bytesread+=cc;
			cb-=cc;
			blocknr = STORAGE_get_next_small_blocknr(&This->str,blocknr);
		}
	} else {
		/* use big block reader */
		blocknr = STORAGE_get_nth_next_big_blocknr(&This->str,This->stde.pps_sb,This->offset.u.LowPart/BIGSIZE);
		while (cb) {
			unsigned int cc;

			if (!STORAGE_get_big_block(&This->str,blocknr,block)) {
				WARN("big block read failed!!!\n");
				return E_FAIL;
			}
			cc = cb;
			if (cc>BIGSIZE-(This->offset.u.LowPart&(BIGSIZE-1)))
				cc=BIGSIZE-(This->offset.u.LowPart&(BIGSIZE-1));
			memcpy(pbv,block+(This->offset.u.LowPart&(BIGSIZE-1)),cc);
			This->offset.u.LowPart+=cc;
			pbv+=cc;
			*bytesread+=cc;
			cb-=cc;
			blocknr=STORAGE_get_next_big_blocknr(&This->str,blocknr);
		}
	}
	return S_OK;
}

/******************************************************************************
 *		IStream16_Write	[STORAGE.522]
 */
HRESULT CDECL IStream16_fnWrite(
        IStream16* iface,const void *pv,ULONG cb,ULONG *pcbWrite
) {
	IStream16Impl *This = (IStream16Impl *)iface;
	BYTE	block[BIGSIZE];
	ULONG	*byteswritten=pcbWrite,xxwritten;
	int	oldsize,newsize,i,curoffset=0,lastblocknr,blocknr,cc;
	const BYTE*     pbv = (const BYTE*)pv;

	if (!pcbWrite) byteswritten=&xxwritten;
	*byteswritten = 0;

	TRACE_(relay)("(%p)->(%p,%d,%p)\n",This,pv,cb,pcbWrite);
	/* do we need to junk some blocks? */
	newsize	= This->offset.u.LowPart+cb;
	oldsize	= This->stde.pps_size;
	if (newsize < oldsize) {
		if (oldsize < 0x1000) {
			/* only small blocks */
			blocknr=STORAGE_get_nth_next_small_blocknr(&This->str,This->stde.pps_sb,newsize/SMALLSIZE);

			assert(blocknr>=0);

			/* will set the rest of the chain to 'free' */
			if (!STORAGE_set_small_chain(&This->str,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
				return E_FAIL;
		} else {
			if (newsize >= 0x1000) {
				blocknr=STORAGE_get_nth_next_big_blocknr(&This->str,This->stde.pps_sb,newsize/BIGSIZE);
				assert(blocknr>=0);

				/* will set the rest of the chain to 'free' */
				if (!STORAGE_set_big_chain(&This->str,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
					return E_FAIL;
			} else {
				/* Migrate large blocks to small blocks
				 * (we just migrate newsize bytes)
				 */
				LPBYTE	curdata,data = HeapAlloc(GetProcessHeap(),0,newsize+BIGSIZE);
				HRESULT r = E_FAIL;

				cc	= newsize;
				blocknr = This->stde.pps_sb;
				curdata = data;
				while (cc>0) {
					if (!STORAGE_get_big_block(&This->str,blocknr,curdata)) {
						HeapFree(GetProcessHeap(),0,data);
						return E_FAIL;
					}
					curdata	+= BIGSIZE;
					cc	-= BIGSIZE;
					blocknr	 = STORAGE_get_next_big_blocknr(&This->str,blocknr);
				}
				/* frees complete chain for this stream */
				if (!STORAGE_set_big_chain(&This->str,This->stde.pps_sb,STORAGE_CHAINENTRY_FREE))
					goto err;
				curdata	= data;
				blocknr = This->stde.pps_sb = STORAGE_get_free_small_blocknr(&This->str);
				if (blocknr<0)
					goto err;
				cc	= newsize;
				while (cc>0) {
					if (!STORAGE_put_small_block(&This->str,blocknr,curdata))
						goto err;
					cc	-= SMALLSIZE;
					if (cc<=0) {
						if (!STORAGE_set_small_chain(&This->str,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
							goto err;
						break;
					} else {
						int newblocknr = STORAGE_get_free_small_blocknr(&This->str);
						if (newblocknr<0)
							goto err;
						if (!STORAGE_set_small_chain(&This->str,blocknr,newblocknr))
							goto err;
						blocknr = newblocknr;
					}
					curdata	+= SMALLSIZE;
				}
				r = S_OK;
			err:
				HeapFree(GetProcessHeap(),0,data);
				if(r != S_OK)
					return r;
			}
		}
		This->stde.pps_size = newsize;
	}

	if (newsize > oldsize) {
		if (oldsize >= 0x1000) {
			/* should return the block right before the 'endofchain' */
			blocknr = STORAGE_get_nth_next_big_blocknr(&This->str,This->stde.pps_sb,This->stde.pps_size/BIGSIZE);
			assert(blocknr>=0);
			lastblocknr	= blocknr;
			for (i=oldsize/BIGSIZE;i<newsize/BIGSIZE;i++) {
				blocknr = STORAGE_get_free_big_blocknr(&This->str);
				if (blocknr<0)
					return E_FAIL;
				if (!STORAGE_set_big_chain(&This->str,lastblocknr,blocknr))
					return E_FAIL;
				lastblocknr = blocknr;
			}
			if (!STORAGE_set_big_chain(&This->str,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
				return E_FAIL;
		} else {
			if (newsize < 0x1000) {
				/* find startblock */
				if (!oldsize)
					This->stde.pps_sb = blocknr = STORAGE_get_free_small_blocknr(&This->str);
				else
					blocknr = STORAGE_get_nth_next_small_blocknr(&This->str,This->stde.pps_sb,This->stde.pps_size/SMALLSIZE);
				if (blocknr<0)
					return E_FAIL;

				/* allocate required new small blocks */
				lastblocknr = blocknr;
				for (i=oldsize/SMALLSIZE;i<newsize/SMALLSIZE;i++) {
					blocknr = STORAGE_get_free_small_blocknr(&This->str);
					if (blocknr<0)
						return E_FAIL;
					if (!STORAGE_set_small_chain(&This->str,lastblocknr,blocknr))
						return E_FAIL;
					lastblocknr = blocknr;
				}
				/* and terminate the chain */
				if (!STORAGE_set_small_chain(&This->str,lastblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
					return E_FAIL;
			} else {
				if (!oldsize) {
					/* no single block allocated yet */
					blocknr=STORAGE_get_free_big_blocknr(&This->str);
					if (blocknr<0)
						return E_FAIL;
					This->stde.pps_sb = blocknr;
				} else {
					/* Migrate small blocks to big blocks */
					LPBYTE	curdata,data = HeapAlloc(GetProcessHeap(),0,oldsize+BIGSIZE);
					HRESULT r = E_FAIL;

					cc	= oldsize;
					blocknr = This->stde.pps_sb;
					curdata = data;
					/* slurp in */
					while (cc>0) {
						if (!STORAGE_get_small_block(&This->str,blocknr,curdata))
							goto err2;
						curdata	+= SMALLSIZE;
						cc	-= SMALLSIZE;
						blocknr	 = STORAGE_get_next_small_blocknr(&This->str,blocknr);
					}
					/* free small block chain */
					if (!STORAGE_set_small_chain(&This->str,This->stde.pps_sb,STORAGE_CHAINENTRY_FREE))
						goto err2;
					curdata	= data;
					blocknr = This->stde.pps_sb = STORAGE_get_free_big_blocknr(&This->str);
					if (blocknr<0)
						goto err2;
					/* put the data into the big blocks */
					cc	= This->stde.pps_size;
					while (cc>0) {
						if (!STORAGE_put_big_block(&This->str,blocknr,curdata))
							goto err2;
						cc	-= BIGSIZE;
						if (cc<=0) {
							if (!STORAGE_set_big_chain(&This->str,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
								goto err2;
							break;
						} else {
							int newblocknr = STORAGE_get_free_big_blocknr(&This->str);
							if (newblocknr<0)
								goto err2;
							if (!STORAGE_set_big_chain(&This->str,blocknr,newblocknr))
								goto err2;
							blocknr = newblocknr;
						}
						curdata	+= BIGSIZE;
					}
					r = S_OK;
				err2:
					HeapFree(GetProcessHeap(),0,data);
					if(r != S_OK)
						return r;
				}
				/* generate big blocks to fit the new data */
				lastblocknr	= blocknr;
				for (i=oldsize/BIGSIZE;i<newsize/BIGSIZE;i++) {
					blocknr = STORAGE_get_free_big_blocknr(&This->str);
					if (blocknr<0)
						return E_FAIL;
					if (!STORAGE_set_big_chain(&This->str,lastblocknr,blocknr))
						return E_FAIL;
					lastblocknr = blocknr;
				}
				/* terminate chain */
				if (!STORAGE_set_big_chain(&This->str,lastblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
					return E_FAIL;
			}
		}
		This->stde.pps_size = newsize;
	}

	/* There are just some cases where we didn't modify it, we write it out
	 * everytime
	 */
	if (!STORAGE_put_pps_entry(&This->str,This->ppsent,&(This->stde)))
		return E_FAIL;

	/* finally the write pass */
	if (This->stde.pps_size < 0x1000) {
		blocknr = STORAGE_get_nth_next_small_blocknr(&This->str,This->stde.pps_sb,This->offset.u.LowPart/SMALLSIZE);
		assert(blocknr>=0);
		while (cb>0) {
			/* we ensured that it is allocated above */
			assert(blocknr>=0);
			/* Read old block everytime, since we can have
			 * overlapping data at START and END of the write
			 */
			if (!STORAGE_get_small_block(&This->str,blocknr,block))
				return E_FAIL;

			cc = SMALLSIZE-(This->offset.u.LowPart&(SMALLSIZE-1));
			if (cc>cb)
				cc=cb;
			memcpy(	((LPBYTE)block)+(This->offset.u.LowPart&(SMALLSIZE-1)),
				pbv+curoffset,
				cc
			);
			if (!STORAGE_put_small_block(&This->str,blocknr,block))
				return E_FAIL;
			cb			-= cc;
			curoffset		+= cc;
			pbv			+= cc;
			This->offset.u.LowPart	+= cc;
			*byteswritten		+= cc;
			blocknr = STORAGE_get_next_small_blocknr(&This->str,blocknr);
		}
	} else {
		blocknr = STORAGE_get_nth_next_big_blocknr(&This->str,This->stde.pps_sb,This->offset.u.LowPart/BIGSIZE);
		assert(blocknr>=0);
		while (cb>0) {
			/* we ensured that it is allocated above, so it better is */
			assert(blocknr>=0);
			/* read old block everytime, since we can have
			 * overlapping data at START and END of the write
			 */
			if (!STORAGE_get_big_block(&This->str,blocknr,block))
				return E_FAIL;

			cc = BIGSIZE-(This->offset.u.LowPart&(BIGSIZE-1));
			if (cc>cb)
				cc=cb;
			memcpy(	((LPBYTE)block)+(This->offset.u.LowPart&(BIGSIZE-1)),
				pbv+curoffset,
				cc
			);
			if (!STORAGE_put_big_block(&This->str,blocknr,block))
				return E_FAIL;
			cb			-= cc;
			curoffset		+= cc;
			pbv			+= cc;
			This->offset.u.LowPart	+= cc;
			*byteswritten		+= cc;
			blocknr = STORAGE_get_next_big_blocknr(&This->str,blocknr);
		}
	}
	return S_OK;
}

/******************************************************************************
 *		_create_istream16	[Internal]
 */
static void _create_istream16(LPSTREAM16 *str) {
	IStream16Impl*	lpst;

	if (!strvt16.QueryInterface) {
		HMODULE16	wp = GetModuleHandle16("STORAGE");
		if (wp>=32) {
		  /* FIXME: what is This GetProcAddress16. Should the name be IStream16_QueryInterface of IStream16_fnQueryInterface */
#define VTENT(xfn)  strvt16.xfn = (void*)GetProcAddress16(wp,"IStream16_"#xfn);assert(strvt16.xfn)
			VTENT(QueryInterface);
			VTENT(AddRef);
			VTENT(Release);
			VTENT(Read);
			VTENT(Write);
			VTENT(Seek);
			VTENT(SetSize);
			VTENT(CopyTo);
			VTENT(Commit);
			VTENT(Revert);
			VTENT(LockRegion);
			VTENT(UnlockRegion);
			VTENT(Stat);
			VTENT(Clone);
#undef VTENT
			segstrvt16 = (const IStream16Vtbl*)MapLS( &strvt16 );
		} else {
#define VTENT(xfn) strvt16.xfn = IStream16_fn##xfn;
			VTENT(QueryInterface);
			VTENT(AddRef);
			VTENT(Release);
			VTENT(Read);
			VTENT(Write);
			VTENT(Seek);
	/*
			VTENT(CopyTo);
			VTENT(Commit);
			VTENT(SetSize);
			VTENT(Revert);
			VTENT(LockRegion);
			VTENT(UnlockRegion);
			VTENT(Stat);
			VTENT(Clone);
	*/
#undef VTENT
			segstrvt16 = &strvt16;
		}
	}
	lpst = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpst) );
	lpst->lpVtbl	= segstrvt16;
	lpst->ref	= 1;
	lpst->thisptr	= MapLS( lpst );
	lpst->str.hf	= NULL;
	lpst->str.lockbytes	= 0;
	*str = (void*)lpst->thisptr;
}


/* --- IStream32 implementation */

typedef struct
{
        /* IUnknown fields */
        const IStreamVtbl              *lpVtbl;
        LONG                            ref;
        /* IStream32 fields */
        struct storage_pps_entry        stde;
        int                             ppsent;
        HANDLE                          hf;
        ULARGE_INTEGER                  offset;
} IStream32Impl;

/*****************************************************************************
 *		IStream32_QueryInterface	[VTABLE]
 */
HRESULT WINAPI IStream_fnQueryInterface(
	IStream* iface,REFIID refiid,LPVOID *obj
) {
	IStream32Impl *This = (IStream32Impl *)iface;

	TRACE_(relay)("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
	if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) {
		*obj = This;
		return 0;
	}
	return OLE_E_ENUM_NOMORE;

}

/******************************************************************************
 * IStream32_AddRef [VTABLE]
 */
ULONG WINAPI IStream_fnAddRef(IStream* iface) {
	IStream32Impl *This = (IStream32Impl *)iface;
	return InterlockedIncrement(&This->ref);
}

/******************************************************************************
 * IStream32_Release [VTABLE]

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -