/* $Id$ * reactos Cache Manager (Cc*) pin 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 "privatebcbpin.h" #include "reactos/ddk/ccfuncs.h" #include "privatebcb.h" #include "captive/macros.h" /** * CcPinMappedData: * @FileObject: Initialized open #FileObject to map. * %NULL value is forbidden. * @MappedFileOffset: The @FileObject file offset from where to map the region from. * Negative value is forbidden. * @MappedLength: Requested length of the region to map from @FileObject. * FIXME: Value %0 is currently forbidden by libcaptive; it should be allowed. * @Wait: Whether disk waiting is permitted for this function. * Value currently ignored by libcaptive as the data must have been mapped by CcMapData() already anyway. * @Flags: %PIN_WAIT means whether disk waiting is permitted for this function. * Value without %PIN_WAIT is currently permtted by libcaptive as the data must have been mapped by CcMapData() already anyway. * %PIN_NO_READ is the same as %MAP_NO_READ - see CcMapData(). * FIXME: %PIN_EXCLUSIVE for exclusive @Bcb access is now ignored by libcaptive. * %PIN_IF_BCB if @Bcb should never be created; function is successful only if @Bcb already exists. * @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. * * This function will allow you to modify the data mapped by CcMapData(). * libcaptive does not differentiate this function with CcMapData(). * * This call does not set the buffer as dirty - such buffer will not be flushed automatically. * * NEVER re-read any memory from FileObject here! * at least fastfat.sys directory create relies on the fact of CcPinRead() * with already modified buffers to be left intact. * * This call will proceed as CcPinRead() if such #Bcb does not yet exist. * This is IMO just a bug workaround for a peruse by fastfat.sys FatLocateVolumeLabel(). * * Every call to this function must be matched by a one corresponding CcUnpinData() call. * * 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 CcPinMappedData (IN PFILE_OBJECT FileObject,IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN ULONG Flags,OUT PVOID *Bcb) { CaptiveSharedCacheMapObject *SharedCacheMap; CaptivePrivateBcbPinObject *captive_private_bcb_pin_object; BOOLEAN r; g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"enter: CcPinMappedData: 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==PIN_WAIT,FALSE); /* FIXME */ g_return_val_if_fail(Bcb!=NULL,FALSE); g_assert(Length<=PAGE_SIZE); /* Check PAGE_SIZE crossing */ g_assert((FileOffset->QuadPart&~(PAGE_SIZE-1))==((FileOffset->QuadPart+Length-1)&~(PAGE_SIZE-1))); SharedCacheMap=captive_FileObject_to_SharedCacheMap(FileObject); /* Do not invalide 'map'ped data otherwise ntfs.sys of NT-5.1sp1 mount crashes. */ captive_private_bcb_pin_object=captive_private_bcb_pin_object_get_ref(SharedCacheMap, CAPTIVE_ROUND_DOWN64(FileOffset->QuadPart,PAGE_SIZE), FALSE); /* invalidate_new */ captive_shared_cache_map_data_validate_noread(SharedCacheMap,FileOffset->QuadPart,FileOffset->QuadPart+Length); *Bcb=captive_private_bcb_object_get_PublicBcb(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object)); r=TRUE; g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"leave: CcPinMappedData: r=%d,Bcb=0x%lX", r,(!Bcb ? -1 : (long)*Bcb)); return r; } /** * CcPinRead: * @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: %PIN_WAIT means whether disk waiting is permitted for this function. * Value without %PIN_WAIT is currently permtted by libcaptive as the data must have been mapped by CcMapData() already anyway. * %PIN_NO_READ is the same as %MAP_NO_READ - see CcMapData(). * FIXME: %PIN_EXCLUSIVE for exclusive @Bcb access is now ignored by libcaptive. * %PIN_IF_BCB if @Bcb should never be created; function is successful only if @Bcb already exists. * @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. * * Merely a shortcut call for CcMapData() and CcPinMappedData() afterwards. * See these two functions for the details. It has a difference to subsequent * calling of CcMapData() and CcPinMappedData() instead as this call counts * only as one function for a corresponding CcUnpinData() call. * * 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. * * 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 CcPinRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN ULONG Flags,OUT PVOID *Bcb,OUT PVOID *Buffer) { CaptiveSharedCacheMapObject *SharedCacheMap; CaptivePrivateBcbPinObject *captive_private_bcb_pin_object; BOOLEAN r; g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"enter: CcPinRead: 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&~PIN_IF_BCB)==PIN_WAIT,FALSE); /* FIXME */ g_return_val_if_fail(Bcb!=NULL,FALSE); g_return_val_if_fail(Buffer!=NULL,FALSE); g_assert(Length<=PAGE_SIZE); /* Check PAGE_SIZE crossing */ g_assert((FileOffset->QuadPart&~(PAGE_SIZE-1))==((FileOffset->QuadPart+Length-1)&~(PAGE_SIZE-1))); SharedCacheMap=captive_FileObject_to_SharedCacheMap(FileObject); if (Flags&PIN_IF_BCB) { if ((captive_private_bcb_pin_object=captive_private_bcb_pin_object_get(SharedCacheMap, CAPTIVE_ROUND_DOWN64(FileOffset->QuadPart,PAGE_SIZE)))) g_object_ref(captive_private_bcb_pin_object); } else { /* Invalide possibly only 'map'ped data as we need to re-read them on CcPinRead(). * Otherwise any file written by fastfat.sys of NT-5.1sp1 will corrupt * the code+55AA of DOS boot sector (disk offset 0x0). */ captive_private_bcb_pin_object=captive_private_bcb_pin_object_get_ref(SharedCacheMap, CAPTIVE_ROUND_DOWN64(FileOffset->QuadPart,PAGE_SIZE), TRUE); /* invalidate_new */ } if (captive_private_bcb_pin_object) { 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_pin_object)); } *Buffer=captive_shared_cache_map_get_buffer(SharedCacheMap)+FileOffset->QuadPart; r=!!captive_private_bcb_pin_object; g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"leave: CcPinRead: r=%d,Bcb=0x%lX,Buffer=0x%lX", r,(!Bcb ? -1 : (long)*Bcb),(!Buffer ? -1 : (long)*Buffer)); return r; } /** * CcSetDirtyPinnedData: * @Bcb: #PUBLIB_BCB to be unpinned from CcRepinBcb(). * %NULL value is forbidden. * @Lsn: Optional LSN (Linear Sequence Number) to assign to @Bcb. * %NULL pointer is permitted. * * This call will set the buffer as dirty - such buffer will be flushed automatically. * * You should call it only on CcPin*() buffers - not just CcMapData() buffers * although libcaptive does not differentiate it. */ VOID CcSetDirtyPinnedData(IN PVOID Bcb,IN PLARGE_INTEGER Lsn OPTIONAL) { CaptivePrivateBcbPinObject *captive_private_bcb_pin_object; g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"enter: CcSetDirtyPinnedData: BcbVoid=0x%lX,Lsn=0x%lX", (long)Bcb,(!Lsn ? -1 : (long)Lsn->QuadPart)); g_return_if_fail(Bcb!=NULL); captive_private_bcb_pin_object=CAPTIVE_PRIVATE_BCB_PIN_OBJECT(captive_PublicBcb_to_PrivateBcbObject(Bcb)); captive_private_bcb_pin_object_set_dirty(captive_private_bcb_pin_object); if (Lsn) captive_private_bcb_pin_object_set_lsn(captive_private_bcb_pin_object,Lsn->QuadPart); g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"leave: CcSetDirtyPinnedData"); } /** * CcPreparePinWrite: * @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. * @Zero: %TRUE if the area of @FileOffset...@FileOffset+@Length should be cleared. * @Flags: %PIN_WAIT means whether disk waiting is permitted for this function. * Value without %PIN_WAIT is currently permtted by libcaptive as the data must have been mapped by CcMapData() already anyway. * %PIN_NO_READ is the same as %MAP_NO_READ - see CcMapData(). * FIXME: %PIN_EXCLUSIVE for exclusive @Bcb access is now ignored by libcaptive. * %PIN_IF_BCB if @Bcb should never be created; function is successful only if @Bcb already exists. * @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. * * Wrapper for a pair of CcPinRead() and CcSetDirtyPinnedData(). * The mapped range can be also optionally cleared if @Zero is specified. * See CcPinRead() for a more detailed documentation. * * This call will set the buffer as dirty - such buffer will be flushed automatically. * * Returns: %TRUE if the mapping was successful. */ BOOLEAN CcPreparePinWrite(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN BOOLEAN Zero,IN ULONG Flags,OUT PVOID *Bcb,OUT PVOID *Buffer) { CaptiveSharedCacheMapObject *SharedCacheMap; CaptivePrivateBcbPinObject *captive_private_bcb_pin_object; BOOLEAN r; g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"enter: CcPreparePinWrite: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX,Zero=%d,Flags=0x%lX", (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length,Zero,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==PIN_WAIT,FALSE); /* FIXME */ g_return_val_if_fail(Bcb!=NULL,FALSE); g_return_val_if_fail(Buffer!=NULL,FALSE); g_assert(0==CAPTIVE_ROUND_DOWN_EXCEEDING64(FileOffset->QuadPart,PAGE_SIZE)); /* NOT YET IMPLEMENTED */ g_assert(Length==PAGE_SIZE); /* NOT YET IMPLEMENTED */ SharedCacheMap=captive_FileObject_to_SharedCacheMap(FileObject); captive_private_bcb_pin_object=captive_private_bcb_pin_object_get_ref(SharedCacheMap, CAPTIVE_ROUND_DOWN64(FileOffset->QuadPart,PAGE_SIZE), FALSE); /* invalidate_new: FIXME: Is it compatible? */ captive_shared_cache_map_set_data_valid(SharedCacheMap,FileOffset->QuadPart,FileOffset->QuadPart+Length); if (Zero) memset(captive_shared_cache_map_get_buffer(SharedCacheMap)+FileOffset->QuadPart,0,Length); captive_shared_cache_map_set_dirty(SharedCacheMap,FileOffset->QuadPart,FileOffset->QuadPart+Length); *Bcb=captive_private_bcb_object_get_PublicBcb(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object)); *Buffer=captive_shared_cache_map_get_buffer(SharedCacheMap)+FileOffset->QuadPart; r=TRUE; g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"leave: CcPreparePinWrite: r=%d,Bcb=0x%lX,Buffer=0x%lX", r,(!Bcb ? -1 : (long)*Bcb),(!Buffer ? -1 : (long)*Buffer)); return r; }