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

📄 storage.c

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

/******************************************************************************
 * STORAGE_set_small_chain [Internal]
 */
static BOOL
STORAGE_set_small_chain(stream_access16*str,int blocknr,INT type) {
	BYTE	block[BIGSIZE];
	LPINT	sbd = (LPINT)block;
	int	lastblocknr,nextsmallblocknr,bigblocknr;
	struct storage_header sth;
	BOOL ret;

	READ_HEADER(str);

	assert(blocknr!=type);
	lastblocknr=-129;bigblocknr=-2;
	while (blocknr>=0) {
		/* cache block ... */
		if (lastblocknr/128!=blocknr/128) {
			bigblocknr = STORAGE_get_nth_next_big_blocknr(str,sth.sbd_startblock,blocknr/128);
			assert(bigblocknr>=0);
			ret = STORAGE_get_big_block(str,bigblocknr,block);
			assert(ret);
		}
		lastblocknr = blocknr;
		nextsmallblocknr = sbd[blocknr&(128-1)];
		sbd[blocknr&(128-1)] = type;
		ret = STORAGE_put_big_block(str,bigblocknr,block);
		assert(ret);
		if (type>=0)
			return TRUE;
		type = STORAGE_CHAINENTRY_FREE;
		blocknr = nextsmallblocknr;
	}
	return TRUE;
}

/******************************************************************************
 *		STORAGE_get_free_big_blocknr	[Internal]
 */
static int
STORAGE_get_free_big_blocknr(stream_access16 *str) {
	BYTE	block[BIGSIZE];
	LPINT	sbd = (LPINT)block;
	int	lastbigblocknr,i,bigblocknr;
	unsigned int curblock;
	struct storage_header sth;
	BOOL ret;

	READ_HEADER(str);
	curblock	= 0;
	lastbigblocknr	= -1;
	bigblocknr	= sth.bbd_list[curblock];
	while (curblock<sth.num_of_bbd_blocks) {
		assert(bigblocknr>=0);
		ret = STORAGE_get_big_block(str,bigblocknr,block);
		assert(ret);
		for (i=0;i<128;i++)
			if (sbd[i]==STORAGE_CHAINENTRY_FREE) {
				sbd[i] = STORAGE_CHAINENTRY_ENDOFCHAIN;
				ret = STORAGE_put_big_block(str,bigblocknr,block);
				assert(ret);
				memset(block,0x42,sizeof(block));
				ret = STORAGE_put_big_block(str,i+curblock*128,block);
				assert(ret);
				return i+curblock*128;
			}
		lastbigblocknr = bigblocknr;
		bigblocknr = sth.bbd_list[++curblock];
	}
	bigblocknr = curblock*128;
	/* since we have marked all blocks from 0 up to curblock*128-1
	 * the next free one is curblock*128, where we happily put our
	 * next large block depot.
	 */
	memset(block,0xff,sizeof(block));
	/* mark the block allocated and returned by this function */
	sbd[1] = STORAGE_CHAINENTRY_ENDOFCHAIN;
	ret = STORAGE_put_big_block(str,bigblocknr,block);
	assert(ret);

	/* if we had a bbd block already (mostlikely) we need
	 * to link the new one into the chain
	 */
	if (lastbigblocknr!=-1) {
		ret = STORAGE_set_big_chain(str,lastbigblocknr,bigblocknr);
		assert(ret);
	}
	sth.bbd_list[curblock]=bigblocknr;
	sth.num_of_bbd_blocks++;
	assert(sth.num_of_bbd_blocks==curblock+1);
	ret = STORAGE_put_big_block(str,-1,(LPBYTE)&sth);
	assert(ret);

	/* Set the end of the chain for the bigblockdepots */
	ret = STORAGE_set_big_chain(str,bigblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN);
	assert(ret);
	/* add 1, for the first entry is used for the additional big block
	 * depot. (means we already used bigblocknr) */
	memset(block,0x42,sizeof(block));
	/* allocate this block (filled with 0x42) */
	ret = STORAGE_put_big_block(str,bigblocknr+1,block);
	assert(ret);
	return bigblocknr+1;
}


/******************************************************************************
 *		STORAGE_get_free_small_blocknr	[Internal]
 */
static int
STORAGE_get_free_small_blocknr(stream_access16 *str) {
	BYTE	block[BIGSIZE];
	LPINT	sbd = (LPINT)block;
	int	lastbigblocknr,newblocknr,i,curblock,bigblocknr;
	struct storage_pps_entry	root;
	struct storage_header sth;

	READ_HEADER(str);
	bigblocknr	= sth.sbd_startblock;
	curblock	= 0;
	lastbigblocknr	= -1;
	newblocknr	= -1;
	while (bigblocknr>=0) {
		if (!STORAGE_get_big_block(str,bigblocknr,block))
			return -1;
		for (i=0;i<128;i++)
			if (sbd[i]==STORAGE_CHAINENTRY_FREE) {
				sbd[i]=STORAGE_CHAINENTRY_ENDOFCHAIN;
				newblocknr = i+curblock*128;
				break;
			}
		if (i!=128)
			break;
		lastbigblocknr = bigblocknr;
		bigblocknr = STORAGE_get_next_big_blocknr(str,bigblocknr);
		curblock++;
	}
	if (newblocknr==-1) {
		bigblocknr = STORAGE_get_free_big_blocknr(str);
		if (bigblocknr<0)
			return -1;
		READ_HEADER(str);
		memset(block,0xff,sizeof(block));
		sbd[0]=STORAGE_CHAINENTRY_ENDOFCHAIN;
		if (!STORAGE_put_big_block(str,bigblocknr,block))
			return -1;
		if (lastbigblocknr==-1) {
			sth.sbd_startblock = bigblocknr;
			if (!STORAGE_put_big_block(str,-1,(LPBYTE)&sth)) /* need to write it */
				return -1;
		} else {
			if (!STORAGE_set_big_chain(str,lastbigblocknr,bigblocknr))
				return -1;
		}
		if (!STORAGE_set_big_chain(str,bigblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
			return -1;
		newblocknr = curblock*128;
	}
	/* allocate enough big blocks for storing the allocated small block */
	if (!STORAGE_get_root_pps_entry(str,&root))
		return -1;
	if (root.pps_sb==-1)
		lastbigblocknr	= -1;
	else
		lastbigblocknr	= STORAGE_get_nth_next_big_blocknr(str,root.pps_sb,(root.pps_size-1)/BIGSIZE);
	while (root.pps_size < (newblocknr*SMALLSIZE+SMALLSIZE-1)) {
		/* we need to allocate more stuff */
		bigblocknr = STORAGE_get_free_big_blocknr(str);
		if (bigblocknr<0)
			return -1;
		READ_HEADER(str);
		if (root.pps_sb==-1) {
			root.pps_sb	 = bigblocknr;
			root.pps_size	+= BIGSIZE;
		} else {
			if (!STORAGE_set_big_chain(str,lastbigblocknr,bigblocknr))
				return -1;
			root.pps_size	+= BIGSIZE;
		}
		lastbigblocknr = bigblocknr;
	}
	if (!STORAGE_set_big_chain(str,lastbigblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
		return -1;
	if (!STORAGE_put_pps_entry(str,0,&root))
		return -1;
	return newblocknr;
}

/******************************************************************************
 *		STORAGE_get_free_pps_entry	[Internal]
 */
static int
STORAGE_get_free_pps_entry(stream_access16*str) {
	int	blocknr, i, curblock, lastblocknr=-1;
	BYTE	block[BIGSIZE];
	struct storage_pps_entry *stde = (struct storage_pps_entry*)block;
	struct storage_header sth;

	READ_HEADER(str);
	blocknr = sth.root_startblock;
	assert(blocknr>=0);
	curblock=0;
	while (blocknr>=0) {
		if (!STORAGE_get_big_block(str,blocknr,block))
			return -1;
		for (i=0;i<4;i++)
			if (stde[i].pps_sizeofname==0) /* free */
				return curblock*4+i;
		lastblocknr = blocknr;
		blocknr = STORAGE_get_next_big_blocknr(str,blocknr);
		curblock++;
	}
	assert(blocknr==STORAGE_CHAINENTRY_ENDOFCHAIN);
	blocknr = STORAGE_get_free_big_blocknr(str);
	/* sth invalidated */
	if (blocknr<0)
		return -1;

	if (!STORAGE_set_big_chain(str,lastblocknr,blocknr))
		return -1;
	if (!STORAGE_set_big_chain(str,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
		return -1;
	memset(block,0,sizeof(block));
	STORAGE_put_big_block(str,blocknr,block);
	return curblock*4;
}

/* --- IStream16 implementation */

typedef struct
{
        /* IUnknown fields */
        const IStream16Vtbl            *lpVtbl;
        LONG                            ref;
        /* IStream16 fields */
        SEGPTR                          thisptr; /* pointer to this struct as segmented */
        struct storage_pps_entry        stde;
        int                             ppsent;
        ULARGE_INTEGER                  offset;
	stream_access16			str;
} IStream16Impl;

/******************************************************************************
 *		IStream16_QueryInterface	[STORAGE.518]
 */
HRESULT CDECL IStream16_fnQueryInterface(
	IStream16* iface,REFIID refiid,LPVOID *obj
) {
	IStream16Impl *This = (IStream16Impl *)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;

}

/******************************************************************************
 * IStream16_AddRef [STORAGE.519]
 */
ULONG CDECL IStream16_fnAddRef(IStream16* iface) {
	IStream16Impl *This = (IStream16Impl *)iface;
	return InterlockedIncrement(&This->ref);
}

static void
_ilockbytes16_addref(SEGPTR lockbytes) {
    DWORD args[1];
    HRESULT hres;
    
    args[0] = (DWORD)lockbytes;	/* iface */
    if (!WOWCallback16Ex(
	(DWORD)((const ILockBytes16Vtbl*)MapSL(
		    (SEGPTR)((LPLOCKBYTES16)MapSL(lockbytes))->lpVtbl)
	)->AddRef,
	WCB16_PASCAL,
	1*sizeof(DWORD),
	(LPVOID)args,
	(LPDWORD)&hres
    ))
	ERR("CallTo16 ILockBytes16::AddRef() failed, hres %x\n",hres);
}

static void
_ilockbytes16_release(SEGPTR lockbytes) {
    DWORD args[1];
    HRESULT hres;
    
    args[0] = (DWORD)lockbytes;	/* iface */
    if (!WOWCallback16Ex(
	(DWORD)((const ILockBytes16Vtbl*)MapSL(
		    (SEGPTR)((LPLOCKBYTES16)MapSL(lockbytes))->lpVtbl)
	)->Release,
	WCB16_PASCAL,
	1*sizeof(DWORD),
	(LPVOID)args,
	(LPDWORD)&hres
    ))
	ERR("CallTo16 ILockBytes16::Release() failed, hres %x\n",hres);
}

static void
_ilockbytes16_flush(SEGPTR lockbytes) {
    DWORD args[1];
    HRESULT hres;
    
    args[0] = (DWORD)lockbytes;	/* iface */
    if (!WOWCallback16Ex(
	(DWORD)((const ILockBytes16Vtbl*)MapSL(
		    (SEGPTR)((LPLOCKBYTES16)MapSL(lockbytes))->lpVtbl)
	)->Flush,
	WCB16_PASCAL,
	1*sizeof(DWORD),
	(LPVOID)args,
	(LPDWORD)&hres
    ))
	ERR("CallTo16 ILockBytes16::Flush() failed, hres %x\n",hres);
}

/******************************************************************************
 * IStream16_Release [STORAGE.520]
 */
ULONG CDECL IStream16_fnRelease(IStream16* iface) {
	IStream16Impl *This = (IStream16Impl *)iface;
        ULONG ref;

	if (This->str.hf)
	    FlushFileBuffers(This->str.hf);
	else
	    _ilockbytes16_flush(This->str.lockbytes);
        ref = InterlockedDecrement(&This->ref);
	if (ref)
	    return ref;

	if (This->str.hf)
	    CloseHandle(This->str.hf);
	else
	    _ilockbytes16_release(This->str.lockbytes);
        UnMapLS( This->thisptr );
	HeapFree( GetProcessHeap(), 0, This );
	return 0;
}

/******************************************************************************
 *		IStream16_Seek	[STORAGE.523]
 *
 * FIXME
 *    Does not handle 64 bits
 */
HRESULT CDECL IStream16_fnSeek(
	IStream16* iface,LARGE_INTEGER offset,DWORD whence,ULARGE_INTEGER *newpos
) {
	IStream16Impl *This = (IStream16Impl *)iface;
	TRACE_(relay)("(%p)->([%d.%d],%d,%p)\n",This,offset.u.HighPart,offset.u.LowPart,whence,newpos);

	switch (whence) {
	/* unix SEEK_xx should be the same as win95 ones */
	case SEEK_SET:
		/* offset must be ==0 (<0 is invalid, and >0 cannot be handled
		 * right now.
		 */
		assert(offset.u.HighPart==0);
		This->offset.u.HighPart = offset.u.HighPart;
		This->offset.u.LowPart = offset.u.LowPart;
		break;
	case SEEK_CUR:
		if (offset.u.HighPart < 0) {
			/* FIXME: is this negation correct ? */
			offset.u.HighPart = -offset.u.HighPart;
			offset.u.LowPart = (0xffffffff ^ offset.u.LowPart)+1;

			assert(offset.u.HighPart==0);
			assert(This->offset.u.LowPart >= offset.u.LowPart);
			This->offset.u.LowPart -= offset.u.LowPart;
		} else {
			assert(offset.u.HighPart==0);
			This->offset.u.LowPart+= offset.u.LowPart;
		}
		break;
	case SEEK_END:
		assert(offset.u.HighPart==0);
		This->offset.u.LowPart = This->stde.pps_size-offset.u.LowPart;
		break;
	}
	if (This->offset.u.LowPart>This->stde.pps_size)
		This->offset.u.LowPart=This->stde.pps_size;
	if (newpos) *newpos = This->offset;
	return S_OK;
}

/******************************************************************************
 *		IStream16_Read	[STORAGE.521]
 */
HRESULT CDECL IStream16_fnRead(
        IStream16* iface,void  *pv,ULONG cb,ULONG  *pcbRead
) {
	IStream16Impl *This = (IStream16Impl *)iface;
	BYTE	block[BIGSIZE];
	ULONG	*bytesread=pcbRead,xxread;
	int	blocknr;
	LPBYTE	pbv = pv;

	TRACE_(relay)("(%p)->(%p,%d,%p)\n",This,pv,cb,pcbRead);
	if (!pcbRead) bytesread=&xxread;
	*bytesread = 0;

	if (cb>This->stde.pps_size-This->offset.u.LowPart)
		cb=This->stde.pps_size-This->offset.u.LowPart;
	if (This->stde.pps_size < 0x1000) {
		/* use small block reader */
		blocknr = STORAGE_get_nth_next_small_blocknr(&This->str,This->stde.pps_sb,This->offset.u.LowPart/SMALLSIZE);

⌨️ 快捷键说明

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