+ PIRP Irp;
+ PFCB Fcb;
+ PFOBX Fobx;
+ NTSTATUS Status;
+ PNET_ROOT NetRoot;
+ PIO_STACK_LOCATION Stack;
+ FILE_INFORMATION_CLASS Class;
+ BOOLEAN CanWait, FcbTableAcquired, FcbAcquired;
+
+ PAGED_CODE();
+
+ Fcb = (PFCB)Context->pFcb;
+ Fobx = (PFOBX)Context->pFobx;
+ DPRINT("RxCommonSetInformation(%p), FCB: %p, FOBX: %p\n", Context, Fcb, Fobx);
+
+ Irp = Context->CurrentIrp;
+ Stack = Context->CurrentIrpSp;
+ Class = Stack->Parameters.SetFile.FileInformationClass;
+ DPRINT("Buffer: %p, Length: %lx, Class: %ld, ReplaceIfExists: %d\n",
+ Irp->AssociatedIrp.SystemBuffer, Stack->Parameters.SetFile.Length,
+ Class, Stack->Parameters.SetFile.ReplaceIfExists);
+
+ Status = STATUS_SUCCESS;
+ CanWait = BooleanFlagOn(Context->Flags, RX_CONTEXT_FLAG_WAIT);
+ FcbTableAcquired = FALSE;
+ FcbAcquired = FALSE;
+ NetRoot = (PNET_ROOT)Fcb->pNetRoot;
+
+#define _SEH2_TRY_RETURN(S) S; goto try_exit
+
+ _SEH2_TRY
+ {
+ /* Valide the node type first */
+ if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN &&
+ NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)
+ {
+ if (NodeType(Fcb) == RDBSS_NTC_STORAGE_TYPE_FILE)
+ {
+ if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE))
+ {
+ Status = STATUS_SUCCESS;
+ }
+ }
+ else if (NodeType(Fcb) != RDBSS_NTC_SPOOLFILE)
+ {
+ if (NodeType(Fcb) == RDBSS_NTC_MAILSLOT)
+ {
+ _SEH2_TRY_RETURN(Status = STATUS_NOT_IMPLEMENTED);
+ }
+ else
+ {
+ DPRINT1("Illegal type of file provided: %x\n", NodeType(Fcb));
+ _SEH2_TRY_RETURN(Status = STATUS_INVALID_PARAMETER);
+ }
+ }
+ }
+
+ /* We don't autorize advance operation */
+ if (Class == FileEndOfFileInformation && Stack->Parameters.SetFile.AdvanceOnly)
+ {
+ DPRINT1("Not allowed\n");
+
+ _SEH2_TRY_RETURN(Status = STATUS_SUCCESS);
+ }
+
+ /* For these to classes, we'll have to deal with the FCB table (removal)
+ * We thus need the exclusive FCB table lock
+ */
+ if (Class == FileDispositionInformation || Class == FileRenameInformation)
+ {
+ RxPurgeRelatedFobxs(NetRoot, Context, TRUE, Fcb);
+ RxScavengeFobxsForNetRoot(NetRoot, Fcb, TRUE);
+
+ if (!RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, CanWait))
+ {
+ Context->PostRequest = TRUE;
+ _SEH2_TRY_RETURN(Status = STATUS_PENDING);
+ }
+
+ FcbTableAcquired = TRUE;
+ }
+
+ /* Finally, if not paging file, we need exclusive FCB lock */
+ if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE))
+ {
+ Status = RxAcquireExclusiveFcb(Context, Fcb);
+ if (Status == STATUS_LOCK_NOT_GRANTED)
+ {
+ Context->PostRequest = TRUE;
+ _SEH2_TRY_RETURN(Status = STATUS_SUCCESS);
+ }
+ else if (Status != STATUS_SUCCESS)
+ {
+ _SEH2_LEAVE;
+ }
+
+ FcbAcquired = TRUE;
+ }
+
+ Status = STATUS_SUCCESS;
+
+ /* And now, perform the job! */
+ switch (Class)
+ {
+ case FileBasicInformation:
+ Status = RxSetBasicInfo(Context);
+ break;
+
+ case FileDispositionInformation:
+ {
+ PFILE_DISPOSITION_INFORMATION FDI;
+
+ /* Check whether user wants deletion */
+ FDI = Irp->AssociatedIrp.SystemBuffer;
+ if (FDI->DeleteFile)
+ {
+ /* If so, check whether it's doable */
+ if (!MmFlushImageSection(&Fcb->NonPaged->SectionObjectPointers, MmFlushForDelete))
+ {
+ Status = STATUS_CANNOT_DELETE;
+ }
+
+ /* And if doable, already remove from FCB table */
+ if (Status == STATUS_SUCCESS)
+ {
+ ASSERT(FcbAcquired && FcbTableAcquired);
+ RxRemoveNameNetFcb(Fcb);
+
+ RxReleaseFcbTableLock(&NetRoot->FcbTable);
+ FcbTableAcquired = FALSE;
+ }
+ }
+
+ /* If it succeed, perform the operation */
+ if (Status == STATUS_SUCCESS)
+ {
+ Status = RxSetDispositionInfo(Context);
+ }
+
+ break;
+ }
+
+ case FilePositionInformation:
+ Status = RxSetPositionInfo(Context);
+ break;
+
+ case FileAllocationInformation:
+ Status = RxSetAllocationInfo(Context);
+ break;
+
+ case FileEndOfFileInformation:
+ Status = RxSetEndOfFileInfo(Context);
+ break;
+
+ case FilePipeInformation:
+ case FilePipeLocalInformation:
+ case FilePipeRemoteInformation:
+ Status = RxSetPipeInfo(Context);
+ break;
+
+ case FileRenameInformation:
+ case FileLinkInformation:
+ case FileMoveClusterInformation:
+ /* If we can wait, try to perform the operation right now */
+ if (CanWait)
+ {
+ /* Of course, collapsing is not doable anymore, file is
+ * in an inbetween state
+ */
+ ClearFlag(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED);
+
+ /* Set the information */
+ Status = RxSetRenameInfo(Context);
+ /* If it succeed, drop the current entry from FCB table */
+ if (Status == STATUS_SUCCESS && Class == FileRenameInformation)
+ {
+ ASSERT(FcbAcquired && FcbTableAcquired);
+ RxRemoveNameNetFcb(Fcb);
+ }
+ _SEH2_TRY_RETURN(Status);
+ }
+ /* Can't wait? Post for async retry */
+ else
+ {
+ Status = RxFsdPostRequest(Context);
+ _SEH2_TRY_RETURN(Status);
+ }
+ break;
+
+ case FileValidDataLengthInformation:
+ if (!MmCanFileBeTruncated(&Fcb->NonPaged->SectionObjectPointers, NULL))
+ {
+ Status = STATUS_USER_MAPPED_FILE;
+ }
+ break;
+
+ case FileShortNameInformation:
+ Status = RxSetSimpleInfo(Context);
+ break;
+
+ default:
+ DPRINT1("Insupported class: %x\n", Class);
+ Status = STATUS_INVALID_PARAMETER;
+
+ break;
+ }
+
+try_exit: NOTHING;
+ /* If mini-rdr was OK and wants a re-post on this, do it */
+ if (Status == STATUS_SUCCESS)
+ {
+ if (Context->PostRequest)
+ {
+ Status = RxFsdPostRequest(Context);
+ }
+ }
+ }
+ _SEH2_FINALLY
+ {
+ /* Release any acquired lock */
+ if (FcbAcquired)
+ {
+ RxReleaseFcb(Context, Fcb);
+ }
+
+ if (FcbTableAcquired)
+ {
+ RxReleaseFcbTableLock(&NetRoot->FcbTable);
+ }
+ }
+ _SEH2_END;
+
+#undef _SEH2_TRY_RETURN
+
+ return Status;