/* $Id$ * reactos Cache Manager (Cc*) map Bcb handling of libcaptive * Copyright (C) 2003 Jan Kratochvil * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; exactly version 2 of June 1991 is required * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include "privatebcbmap.h" #include "reactos/ntos/types.h" #include "reactos/ddk/iotypes.h" #include "reactos/ddk/cctypes.h" #include "reactos/ddk/ccfuncs.h" #include "sharedcachemap.h" #include "privatebcb.h" /** * CcMapData: * @FileObject: Initialized open #FileObject to map. * %NULL value is forbidden. * @FileOffset: The @FileObject file offset from where to map the region from. * Negative value is forbidden. * @Length: Requested length of the region to map from @FileObject. * FIXME: Value %0 is currently forbidden by libcaptive; it should be allowed. * @Flags: %MAP_WAIT means whether disk waiting is permitted for this function. * Value without %MAP_WAIT is currently forbidden by libcaptive as we have no on-demand loading implemented. * %MAP_NO_READ will leave the pages unread (libcaptive: unread pages zeroed, * already mapped pages shared with existing content) - needed by ntfs.sys of NT-5.1sp1 * as during file write it will %MAP_NO_READ and consequently push the data there; * any request for the same file range read in the meantime will destroy the prepared data! * @Bcb: Returns initialized #PUBLIC_BCB to refer to the mapped region. * The memory region can be larger than requested as it is %PAGE_SIZE aligned. * %NULL pointer is forbidden. * @Buffer: Returns the mapped memory region start address. * This address may not be %PAGE_SIZE aligned. * %NULL pointer is forbidden. * * Maps the specified region of @FileObject to automatically chosen address space. * FIXME: No on-demand loading implemented yet - the whole region is read at the time of this function call. * * WARNING: If you modify the data in the returned @Buffer you must call some CcPinMappedData() * or CcPinRead() afterwards. W32 docs say you should never modify the data in any way from this function * but W32 filesystems apparently do not conform to it. If you do not take care of the * modified data by some dirty-marking facility such data will be carelessly dropped without * their commit to the disk. * * This call does not set the buffer as dirty - such buffer will not be flushed automatically. * * Every call to this function must be matched by a one corresponding CcUnpinData() call. * * We can be called as full CcMapData() (e.g. CcPinRead() from fastfat.sys) * even if such mapping for such file already exists. * We should probably create a new #Bcb for the same space, * at least ntfs.sys of NT-5.1sp1 appears to expect it. Bleech. * * Returns: %TRUE if the region was successfuly mapped. * @Bcb with the initialized new memory region. * @Buffer with the address of the exact byte specified by @FileOffset. */ BOOLEAN CcMapData(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN ULONG Flags,OUT PVOID *Bcb,OUT PVOID *Buffer) { CaptiveSharedCacheMapObject *SharedCacheMap; CaptivePrivateBcbMapObject *captive_private_bcb_map_object; BOOLEAN r; g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"enter: CcMapData: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX,Flags=0x%lX", (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length,Flags); g_return_val_if_fail(FileObject!=NULL,FALSE); g_return_val_if_fail(FileOffset!=NULL,FALSE); g_return_val_if_fail(FileOffset->QuadPart>=0,FALSE); g_return_val_if_fail(Length>0,FALSE); /* FIXME: not handled below; 0 should be allowed */ g_return_val_if_fail(Flags==MAP_WAIT,FALSE); /* FIXME */ g_return_val_if_fail(Bcb!=NULL,FALSE); g_return_val_if_fail(Buffer!=NULL,FALSE); SharedCacheMap=captive_FileObject_to_SharedCacheMap(FileObject); captive_private_bcb_map_object=captive_private_bcb_map_object_get_ref(SharedCacheMap); captive_shared_cache_map_data_validate_read(SharedCacheMap,FileObject,FileOffset->QuadPart,FileOffset->QuadPart+Length); *Bcb=captive_private_bcb_object_get_PublicBcb(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_map_object)); *Buffer=captive_shared_cache_map_get_buffer(SharedCacheMap)+FileOffset->QuadPart; r=TRUE; g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"leave: CcMapData: r=%d,Bcb=0x%lX,Buffer=0x%lX", r,(!Bcb ? -1 : (long)*Bcb),(!Buffer ? -1 : (long)*Buffer)); return r; } /** * CcRemapBcb: * @Bcb: Initialized #PUBLIC_BCB structure. * %NULL value is forbidden. * * Create a copy of @Bcb for the exactly same file contents as is @Bcb. * The returned copy has the same attributes as the result of CcMapData() * notwithstanding the current state of input @Bcb, therefore it is only * for read/only access etc. * * libcaptive calls CcMapData() internally with @Bcb parameters. * * This function is called only by ntfs.sys of NT-5.1sp1 and it will perform * these operations with the resulting #PUBLIC_BCB: * CcRemapBcb(), CcSetDirtyPinnedData(), CcUnpinData() * * Untested: This call does not set the buffer as dirty - such buffer will not be flushed automatically. * * Returns: Copy of @Bcb. This _pointer_ never equals to @Bcb. * It should be some different * #PUBLIC_BCB structure according to W32 doc. */ PVOID CcRemapBcb(IN PVOID Bcb) { CaptivePrivateBcbObject *captive_private_bcb_object; CaptiveSharedCacheMapObject *SharedCacheMap; CaptivePrivateBcbMapObject *captive_private_bcb_map_object; PUBLIC_BCB *PublicBcb; g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"enter: CcRemapBcb: Bcb=0x%lX",(long)Bcb); g_return_val_if_fail(Bcb!=NULL,NULL); captive_private_bcb_object=captive_PublicBcb_to_PrivateBcbObject(Bcb); SharedCacheMap=captive_private_bcb_object_get_SharedCacheMap(captive_private_bcb_object); /* 'Bcb' may even belong to SharedCacheMap without any existing map Bcb (just pin Bcbs). */ captive_private_bcb_map_object=captive_private_bcb_map_object_get_ref(SharedCacheMap); PublicBcb=captive_private_bcb_object_get_PublicBcb(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_map_object)); g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"leave: CcRemapBcb: r=0x%lX",(long)PublicBcb); return PublicBcb; }