pagepos_local.privbcb_list=NULL;
pagepos_local.shmid=-1;
pagepos=g_hash_table_lookup(page_position_hash,&pagepos_local);
+ if (!pagepos && (Flags & PIN_IF_BCB)) /* BCB does not exist */
+ return FALSE;
g_assert(validate_page_position(pagepos));
g_assert(pagepos->privbcb_list!=NULL);
privbcb=privbcb_listitem;
}
}
+ if (!privbcb && (Flags & PIN_IF_BCB)) /* BCB does not exist */
+ return FALSE;
g_return_val_if_fail(privbcb!=NULL,FALSE); /* appropriate privbcb not found */
/* Sanity check 'privbcb': */
}
+static void captive_privbcb_flush(struct private_bcb *privbcb)
+{
+MDL *Mdl;
+KEVENT Event;
+IO_STATUS_BLOCK IoStatus;
+NTSTATUS err;
+gpointer base_sectoraligned;
+gsize length_sectoraligned;
+LARGE_INTEGER FileOffset_sectoraligned;
+
+ if (!privbcb->dirty)
+ return;
+
+ g_assert(privbcb->FileObject->DeviceObject!=NULL);
+ /* Is PAGE_SIZE aligned with 'privbcb->FileObject->DeviceObject->SectorSize'? */
+ g_assert(privbcb->FileObject->DeviceObject->SectorSize>0);
+ g_assert(0==CAPTIVE_ROUND_DOWN_EXCEEDING(PAGE_SIZE,privbcb->FileObject->DeviceObject->SectorSize));
+ /* We align here directly the 'privbcb->base' which is not correct.
+ * We should rather aligned according to 'privbcb->MappedOffset' but
+ * as 'privbcb->base' with PAGE_SIZE alignment is just a possibly
+ * better alignment than 'privbcb->FileObject->DeviceObject->SectorSize' it must the same operation.
+ */
+ g_assert(CAPTIVE_ROUND_DOWN_EXCEEDING(privbcb->base,privbcb->FileObject->DeviceObject->SectorSize)
+ ==CAPTIVE_ROUND_DOWN_EXCEEDING64(privbcb->MappedFileOffset.QuadPart,privbcb->FileObject->DeviceObject->SectorSize));
+ base_sectoraligned =CAPTIVE_ROUND_DOWN(privbcb->base,privbcb->FileObject->DeviceObject->SectorSize);
+ length_sectoraligned=CAPTIVE_ROUND_UP(((char *)privbcb->base)+privbcb->MappedLength,privbcb->FileObject->DeviceObject->SectorSize)
+ -((char *)base_sectoraligned);
+ g_assert(0==CAPTIVE_ROUND_DOWN_EXCEEDING(length_sectoraligned,privbcb->FileObject->DeviceObject->SectorSize));
+ FileOffset_sectoraligned.QuadPart=CAPTIVE_ROUND_DOWN64(privbcb->MappedFileOffset.QuadPart,privbcb->FileObject->DeviceObject->SectorSize);
+
+ Mdl=MmCreateMdl(NULL,base_sectoraligned,length_sectoraligned);
+ g_assert(Mdl!=NULL);
+
+ KeInitializeEvent(&Event,NotificationEvent,FALSE);
+
+ /* FIXME: read/write should be possible after CcSetDirtyPinnedData() etc. */
+ /* Use rather IoSynchronousPageWrite() than IoPageWrite() to prevent STATUS_PENDING. */
+ err=IoSynchronousPageWrite(privbcb->FileObject,Mdl,&FileOffset_sectoraligned,&Event,&IoStatus);
+ g_assert(NT_SUCCESS(err));
+ g_assert(NT_SUCCESS(IoStatus.Status));
+ /* We should write at least the unaligned mapped data although we
+ * do not need to successfuly write the whole aligned amount.
+ */
+ g_assert(IoStatus.Information>=CAPTIVE_ROUND_DOWN_EXCEEDING(privbcb->base,privbcb->FileObject->DeviceObject->SectorSize)
+ +privbcb->MappedLength);
+ g_assert(IoStatus.Information<=length_sectoraligned);
+
+ g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: 'dirty' flush: FileObject=%p,MappedFileOffset=0x%llX,MappedLength=0x%lX,base=%p"
+ "; base_sectoraligned=%p,FileOffset_sectoraligned=0x%llX,length_sectoraligned=0x%lX; ->Information=0x%lX",G_STRLOC,
+ privbcb->FileObject,(guint64)privbcb->MappedFileOffset.QuadPart,(gulong)privbcb->MappedLength,privbcb->base,
+ base_sectoraligned,(guint64)FileOffset_sectoraligned.QuadPart,(gulong)length_sectoraligned,
+ (gulong)IoStatus.Information);
+
+ privbcb->dirty=FALSE;
+}
+
+
/**
* CcUnpinData:
* @Bcb: Initialized #PUBLIC_BCB structure.
if (--privbcb->ref_count)
return;
- if (privbcb->dirty) {
-MDL *Mdl;
-KEVENT Event;
-IO_STATUS_BLOCK IoStatus;
-NTSTATUS err;
-gpointer base_sectoraligned;
-gsize length_sectoraligned;
-LARGE_INTEGER FileOffset_sectoraligned;
-
- g_assert(privbcb->FileObject->DeviceObject!=NULL);
- /* Is PAGE_SIZE aligned with 'privbcb->FileObject->DeviceObject->SectorSize'? */
- g_assert(privbcb->FileObject->DeviceObject->SectorSize>0);
- g_assert(0==CAPTIVE_ROUND_DOWN_EXCEEDING(PAGE_SIZE,privbcb->FileObject->DeviceObject->SectorSize));
- /* We align here directly the 'privbcb->base' which is not correct.
- * We should rather aligned according to 'privbcb->MappedOffset' but
- * as 'privbcb->base' with PAGE_SIZE alignment is just a possibly
- * better alignment than 'privbcb->FileObject->DeviceObject->SectorSize' it must the same operation.
- */
- g_assert(CAPTIVE_ROUND_DOWN_EXCEEDING(privbcb->base,privbcb->FileObject->DeviceObject->SectorSize)
- ==CAPTIVE_ROUND_DOWN_EXCEEDING64(privbcb->MappedFileOffset.QuadPart,privbcb->FileObject->DeviceObject->SectorSize));
- base_sectoraligned =CAPTIVE_ROUND_DOWN(privbcb->base,privbcb->FileObject->DeviceObject->SectorSize);
- length_sectoraligned=CAPTIVE_ROUND_UP(((char *)privbcb->base)+privbcb->MappedLength,privbcb->FileObject->DeviceObject->SectorSize)
- -((char *)base_sectoraligned);
- g_assert(0==CAPTIVE_ROUND_DOWN_EXCEEDING(length_sectoraligned,privbcb->FileObject->DeviceObject->SectorSize));
- FileOffset_sectoraligned.QuadPart=CAPTIVE_ROUND_DOWN64(privbcb->MappedFileOffset.QuadPart,privbcb->FileObject->DeviceObject->SectorSize);
-
- Mdl=MmCreateMdl(NULL,base_sectoraligned,length_sectoraligned);
- g_assert(Mdl!=NULL);
-
- KeInitializeEvent(&Event,NotificationEvent,FALSE);
-
- /* FIXME: read/write should be possible after CcSetDirtyPinnedData() etc. */
- /* Use rather IoSynchronousPageWrite() than IoPageWrite() to prevent STATUS_PENDING. */
- err=IoSynchronousPageWrite(privbcb->FileObject,Mdl,&FileOffset_sectoraligned,&Event,&IoStatus);
- g_assert(NT_SUCCESS(err));
- g_assert(NT_SUCCESS(IoStatus.Status));
- /* We should write at least the unaligned mapped data although we
- * do not need to successfuly write the whole aligned amount.
- */
- g_assert(IoStatus.Information>=CAPTIVE_ROUND_DOWN_EXCEEDING(privbcb->base,privbcb->FileObject->DeviceObject->SectorSize)
- +privbcb->MappedLength);
- g_assert(IoStatus.Information<=length_sectoraligned);
-
- g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: 'dirty' flush: FileObject=%p,MappedFileOffset=0x%llX,MappedLength=0x%lX,base=%p"
- "; base_sectoraligned=%p,FileOffset_sectoraligned=0x%llX,length_sectoraligned=0x%lX; ->Information=0x%lX",G_STRLOC,
- privbcb->FileObject,(guint64)privbcb->MappedFileOffset.QuadPart,(gulong)privbcb->MappedLength,privbcb->base,
- base_sectoraligned,(guint64)FileOffset_sectoraligned.QuadPart,(gulong)length_sectoraligned,
- (gulong)IoStatus.Information);
-
- privbcb->dirty=FALSE;
- }
+ captive_privbcb_flush(privbcb);
g_assert(privbcb->FileObject->SectionObjectPointers!=NULL);
g_assert(privbcb->FileObject->SectionObjectPointers->SharedCacheMap==PublicBcb);
/**
* CcPurgeCacheSection:
- * @SectionObjectPointer: FIXME: ???.
+ * @SectionObjectPointer: Pointer specifying file to purge;
+ * %NULL value is forbidden.
+ * libcaptive interprets only #SharedCacheMap field as #PUBLIC_BCB pointer.
+ * Field #SharedCacheMap value %NULL is permitted; libcaptive does a NOP with %FALSE return code in such case.
* @FileOffset: Starting offset of the ranger to purge.
* %NULL pointer is permitted and it means to purge the whole whole.
+ * FIXME: Non %NULL pointer is NOT IMPLEMENTED YET by libcaptive.
* @Length: Length of the range to purge. Ignored if @FileOffset==NULL.
* @UninitializeCacheMaps: Purge also private cache maps (FIXME: ???).
*
* Drop any caching for shrunken file which is not being deleted.
- * libcaptive implements this function as NOP as it does not cache anything.
+ * libcaptive will no longer consider such #BCB as dirty.
*
* Returns: %TRUE if the range was purged successfuly.
*/
struct private_bcb *privbcb;
g_return_val_if_fail(SectionObjectPointer!=NULL,FALSE);
- g_return_val_if_fail(SectionObjectPointer->SharedCacheMap!=NULL,FALSE);
+ if (SectionObjectPointer->SharedCacheMap==NULL)
+ return FALSE; /* failed - nothing to purge */
+ g_return_val_if_fail(FileOffset==NULL,FALSE); /* NOT IMPLEMENTED YET */
PublicBcb=SectionObjectPointer->SharedCacheMap;
g_return_val_if_fail(validate_Bcb(PublicBcb),FALSE);
SectionObjectPointer,PublicBcb,privbcb,privbcb->FileObject,
(guint64)(!FileOffset ? -1 : FileOffset->QuadPart),(gulong)Length,(gint)UninitializeCacheMaps);
+ privbcb->dirty=FALSE; /* purge it */
+
return TRUE;
}
/* NOP; no caching by libcaptive */
}
+
+
+/**
+ * CcFlushCache:
+ * @SectionObjectPointer: Pointer specifying file to flush;
+ * %NULL value is forbidden.
+ * libcaptive interprets only #SharedCacheMap field as #PUBLIC_BCB pointer.
+ * Field #SharedCacheMap value %NULL is permitted; libcaptive does a NOP in such case.
+ * @FileOffset: Optional starting point of the range to flush.
+ * %NULL value is permitted.
+ * @Length: Length of the range to flush. Ignored if @FileOffset is %NULL.
+ * @IoStatus: Optionally returns the resulting operation status.
+ * #Information field will contain the number of bytes flushed.
+ * %NULL value is permitted.
+ *
+ * Flushes out any pending dirty data in cache manager BCB mapping.
+ * FIXME: libcaptive currently always flushes the full file ignoring any @FileOffset or @Length.
+ */
+VOID CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
+ IN PLARGE_INTEGER FileOffset OPTIONAL,IN ULONG Length,OUT PIO_STATUS_BLOCK IoStatus OPTIONAL)
+{
+PUBLIC_BCB *PublicBcb;
+struct private_bcb *privbcb;
+
+ g_return_if_fail(SectionObjectPointer!=NULL);
+
+ if (SectionObjectPointer->SharedCacheMap==NULL) {
+ if (IoStatus) {
+ IoStatus->Status=STATUS_SUCCESS;
+ IoStatus->Information=0;
+ }
+ return;
+ }
+
+ PublicBcb=SectionObjectPointer->SharedCacheMap;
+ g_return_if_fail(validate_Bcb(PublicBcb));
+
+ private_bcb_hash_init();
+
+ privbcb=g_hash_table_lookup(private_bcb_hash,PublicBcb);
+ g_return_if_fail(privbcb!=NULL);
+
+ g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: SectionObjectPointer=%p(Bcb=%p,privbcb=%p,privbcb->FileObject=%p),"
+ "FileOffset=0x%llX,Length=0x%lX,IoStatus=%p",G_STRLOC,
+ SectionObjectPointer,PublicBcb,privbcb,privbcb->FileObject,
+ (guint64)(!FileOffset ? -1 : FileOffset->QuadPart),(gulong)Length,IoStatus);
+
+ if (FileOffset) {
+ g_assert(FileOffset->QuadPart >=privbcb->MappedFileOffset.QuadPart);
+ g_assert(FileOffset->QuadPart+Length<=privbcb->MappedFileOffset.QuadPart+privbcb->MappedLength);
+ }
+
+ /* FIXME: Flush just FileOffset..FileOfset+Length part */
+ captive_privbcb_flush(privbcb);
+
+ if (IoStatus) {
+ IoStatus->Status=STATUS_SUCCESS;
+ IoStatus->Information=(FileOffset && Length ? MIN(privbcb->MappedLength,Length) : privbcb->MappedLength);
+ }
+}