static VOID IopDeviceFree( IN OUT PIO_DEVICE_OBJECT* ppDeviceObject ) { PIO_DEVICE_OBJECT pDeviceObject = *ppDeviceObject; if (pDeviceObject) { // The object should have already been rundown LWIO_ASSERT(LwListIsEmpty(&pDeviceObject->FileObjectsList)); // The device should not be in any lists. LWIO_ASSERT(LwListIsEmpty(&pDeviceObject->RootLinks)); LWIO_ASSERT(LwListIsEmpty(&pDeviceObject->DriverLinks)); RtlUnicodeStringFree(&pDeviceObject->DeviceName); LwRtlCleanupMutex(&pDeviceObject->Mutex); LwRtlCleanupMutex(&pDeviceObject->CancelMutex); IopDriverDereference(&pDeviceObject->Driver); IoMemoryFree(pDeviceObject); *ppDeviceObject = NULL; } }
VOID IopFileObjectFree( IN OUT PIO_FILE_OBJECT* ppFileObject ) { PIO_FILE_OBJECT pFileObject = *ppFileObject; if (pFileObject) { LWIO_ASSERT(LwListIsEmpty(&pFileObject->IrpList)); IopIrpFreeZctIrpList(pFileObject); IopDeviceLock(pFileObject->pDevice); LwListRemove(&pFileObject->DeviceLinks); IopDeviceUnlock(pFileObject->pDevice); IopDeviceDereference(&pFileObject->pDevice); LwRtlCleanupConditionVariable(&pFileObject->Rundown.Condition); LwRtlCleanupMutex(&pFileObject->Mutex); LwRtlUnicodeStringFree(&pFileObject->FileName); IopIrpDereference(&pFileObject->pCloseIrp); IoMemoryFree(pFileObject); *ppFileObject = NULL; } }
static VOID PvfsWildcardStackDestroy( PLW_LIST_LINKS pStack ) { PSTR a = NULL; PSTR b = NULL; while (!LwListIsEmpty(pStack)) { PvfsWildcardStackPop(pStack, &a, &b); } }
NTSTATUS NpfsClientCloseHandle( PNPFS_CCB pCCB ) { NTSTATUS ntStatus = 0; PNPFS_PIPE pPipe = NULL; PNPFS_CCB pSCB = NULL; PLW_LIST_LINKS pLink = NULL; PNPFS_IRP_CONTEXT pReadContext = NULL; pPipe = pCCB->pPipe; ENTER_MUTEX(&pPipe->PipeMutex); pSCB = pPipe->pSCB; pPipe->PipeClientState = PIPE_CLIENT_CLOSED; while (pSCB && !LwListIsEmpty(&pSCB->ReadIrpList)) { pLink = pSCB->ReadIrpList.Next; LwListRemove(pLink); pReadContext = LW_STRUCT_FROM_FIELD(pLink, NPFS_IRP_CONTEXT, Link); NpfsServerCompleteReadFile(pSCB, pReadContext); } pthread_cond_signal(&pPipe->PipeCondition); if (pPipe->PipeServerState == PIPE_SERVER_CLOSED) { ntStatus = NpfsFreePipeContext(pPipe); BAIL_ON_NT_STATUS(ntStatus); } error: pPipe->pCCB = NULL; LEAVE_MUTEX(&pPipe->PipeMutex); NpfsReleaseCCB(pCCB); return(ntStatus); }
PLW_LIST_LINKS LwListTraverse( IN PLW_LIST_LINKS Head, IN PLW_LIST_LINKS Cursor ) { if (LwListIsEmpty(Head)) { return NULL; } if (Cursor == NULL) { return Head->Next; } if (Cursor->Next == Head) { return NULL; } return Cursor->Next; }
BOOL PvfsListIsEmpty( PPVFS_LIST pList ) { BOOLEAN bIsEmpty = FALSE; NTSTATUS ntError = STATUS_SUCCESS; if (pList->CurrentSize == 0) { bIsEmpty = TRUE; if (!LwListIsEmpty(&pList->DataList)) { /* This would be a logic error */ ntError = STATUS_INTERNAL_ERROR; ntError = ntError; } } return bIsEmpty; }
VOID IopIrpFreeZctIrpList( IN OUT PIO_FILE_OBJECT pFileObject ) { PLW_LIST_LINKS pLinks = NULL;; PIRP_INTERNAL irpInternal = NULL; PIRP pIrp = NULL; while (!LwListIsEmpty(&pFileObject->ZctCompletionIrpList)) { pLinks = LwListRemoveHead(&pFileObject->ZctCompletionIrpList); irpInternal = LW_STRUCT_FROM_FIELD(pLinks, IRP_INTERNAL, CancelLinks); pIrp = &irpInternal->Irp; LWIO_ASSERT(1 == irpInternal->ReferenceCount); LWIO_ASSERT(!pIrp->FileHandle); IopIrpDereference(&pIrp); } }
BOOLEAN PvfsWildcardMatch( IN PSTR pszPathname, IN PSTR pszPattern, IN BOOLEAN bCaseSensitive ) { NTSTATUS ntError = STATUS_SUCCESS; PSTR pszString = NULL; PSTR pszMatch = NULL; PSTR pszPathUpper = NULL; PSTR pszPatternUpper = NULL; BOOLEAN bMatched = FALSE; LW_LIST_LINKS Stack; // Quick check for an exact match if (!strchr(pszPattern, '?') && !strchr(pszPattern, '*')) { return RtlCStringIsEqual(pszPathname, pszPattern, bCaseSensitive); } // If we have a case insensitive search, upper case the Pathname // and Pattern for easier comparison pszString = pszPathname; pszMatch = pszPattern; if (!bCaseSensitive) { ntError = RtlCStringDuplicate(&pszPathUpper, pszPathname); BAIL_ON_NT_STATUS(ntError); ntError = RtlCStringDuplicate(&pszPatternUpper, pszPattern); BAIL_ON_NT_STATUS(ntError); PvfsCStringUpper(pszPathUpper); PvfsCStringUpper(pszPatternUpper); pszString = pszPathUpper; pszMatch = pszPatternUpper; } // Enter state machine LwListInit(&Stack); reset_state: while (PVFS_CSTRING_NON_NULL(pszString) && PVFS_CSTRING_NON_NULL(pszMatch)) { PVFS_WILDCARD_TYPE eState = 0; CHAR cSrc = '\0'; CHAR cMatch = '\0'; DWORD dwCount = 0; // Save the current CHAR cSrc = *pszString; cMatch = *pszMatch; // Certain characters should never match and hence allow us to filter // certain file patterns if (cSrc == PVFS_STREAM_DELIMINATOR_C) { bMatched = FALSE; goto cleanup; } // Consumes the pattern from pszMatch eState = NextMatchState(&pszMatch, &dwCount); switch (eState) { case PVFS_WILDCARD_TYPE_NONE: if (cSrc != cMatch) { ntError = STATUS_NO_MATCH; pszString = NULL; } else { pszString++; } break; case PVFS_WILDCARD_TYPE_SPLAT: { // We are done if this is the last character in the pattern if (!PVFS_CSTRING_NON_NULL(pszMatch)) { pszString = NULL; } else { // Be greedy - Consume as much of the string using the '*' // as possible. This will require a stack in order to backtrack // on a failure. pszString = PvfsWildcardEatString(pszString, pszMatch); if (!pszString) { ntError = STATUS_NO_MATCH; } else { // Add next character past "String" match and the previously // match "Pattern" state (so we pick up the '*' when we pop // the stack ntError = PvfsWildcardStackPush( &Stack, pszString+1, pszMatch-1); BAIL_ON_NT_STATUS(ntError); } } break; } case PVFS_WILDCARD_TYPE_SINGLE: { DWORD i = 0; // Consume dwCount characters for (i=0; (i<dwCount) && PVFS_CSTRING_NON_NULL(pszString); i++, pszString++) { // no loop body ; } break; } case PVFS_WILDCARD_TYPE_DOT: // For now deal with the '.' as just another character if (cSrc != cMatch) { ntError = STATUS_NO_MATCH; pszString = NULL; } else { pszString++; } break; case PVFS_WILDCARD_TYPE_SPLAT_DOT: { PSTR pszCursor = NULL; // Similar to "A*B" except we search for the '.' from the end if ((pszCursor = strrchr(pszString, '.')) == NULL) { ntError = STATUS_NO_MATCH; pszString = NULL; } else { pszString = pszCursor + 1; } break; } case PVFS_WILDCARD_TYPE_SINGLE_DOT: { DWORD i = 0; // We can match 0 - dwCount characters up to the last '.' // This is really a hold over from DOS 8.3 filenames for (i=0; i<dwCount && PVFS_CSTRING_NON_NULL(pszString) && (*pszString != '.'); i++, pszString++) { // no loop body ; } // If we any path left, it better be on '.' for a match if (*pszString == '.') { pszString++; } else { ntError = STATUS_NO_MATCH; pszString = NULL; } break; } } // end of switch {...} } // end of for {...} // We matched if pszString is empty AND either pszMatch is empty // OR only contains wildcard characters if ((ntError == STATUS_SUCCESS) && !PVFS_CSTRING_NON_NULL(pszString) && (!PVFS_CSTRING_NON_NULL(pszMatch) || PvfsCStringOnlyContainsChars(pszMatch, "?*"))) { bMatched = TRUE; } else if (!LwListIsEmpty(&Stack)) { // Pop back to the earlier state, consume one character (*from '*') // and try another path ntError = PvfsWildcardStackPop(&Stack, &pszString, &pszMatch); BAIL_ON_NT_STATUS(ntError); pszString++; goto reset_state; } cleanup: PvfsWildcardStackDestroy(&Stack); if (!bCaseSensitive) { PVFS_FREE(&pszPathUpper); PVFS_FREE(&pszPatternUpper); } // If we have any string left to parse, we don't have a match return bMatched; error: goto cleanup; }
NTSTATUS IopDeviceRundown( IN PIO_DEVICE_OBJECT pDeviceObject ) { NTSTATUS status = 0; int EE = 0; BOOLEAN isLocked = FALSE; PLW_LIST_LINKS pLinks = NULL; LW_LIST_LINKS rundownList = { 0 }; LwListInit(&rundownList); IopDeviceLock(pDeviceObject); isLocked = TRUE; if (IsSetFlag(pDeviceObject->Flags, IO_DEVICE_OBJECT_FLAG_RUNDOWN)) { // TODO: Perhaps wait if currently running down. status = STATUS_SUCCESS; GOTO_CLEANUP_EE(EE); } SetFlag(pDeviceObject->Flags, IO_DEVICE_OBJECT_FLAG_RUNDOWN); // Gather rundown list for (pLinks = pDeviceObject->FileObjectsList.Next; pLinks != &pDeviceObject->FileObjectsList; pLinks = pLinks->Next) { PIO_FILE_OBJECT pFileObject = LW_STRUCT_FROM_FIELD(pLinks, IO_FILE_OBJECT, DeviceLinks); IopFileObjectReference(pFileObject); LwListInsertTail(&rundownList, &pFileObject->RundownLinks); } IopDeviceUnlock(pDeviceObject); isLocked = FALSE; // Now, actually run down every file w/o holding the device lock. while (!LwListIsEmpty(&rundownList)) { PIO_FILE_OBJECT pFileObject = NULL; pLinks = LwListRemoveHead(&rundownList); pFileObject = LW_STRUCT_FROM_FIELD(pLinks, IO_FILE_OBJECT, RundownLinks); IopFileObjectRundown(pFileObject); } IopRootRemoveDevice(pDeviceObject->Driver->Root, &pDeviceObject->RootLinks); cleanup: if (isLocked) { IopDeviceUnlock(pDeviceObject); } IO_LOG_LEAVE_ON_STATUS_EE(status, EE); return status; }
NTSTATUS NpfsClientWriteFile_Connected( PNPFS_CCB pCCB, PNPFS_IRP_CONTEXT pIrpContext ) { NTSTATUS ntStatus = 0; PNPFS_PIPE pPipe = NULL; PNPFS_CCB pSCB = NULL; PVOID pBuffer = NULL; ULONG Length = 0; ULONG ulBytesTransferred = 0; PLW_LIST_LINKS pLink = NULL; PNPFS_IRP_CONTEXT pReadContext = NULL; switch (pIrpContext->pIrp->Type) { case IRP_TYPE_FS_CONTROL: pBuffer = pIrpContext->pIrp->Args.IoFsControl.InputBuffer; Length = pIrpContext->pIrp->Args.IoFsControl.InputBufferLength; break; default: pBuffer = pIrpContext->pIrp->Args.ReadWrite.Buffer; Length = pIrpContext->pIrp->Args.ReadWrite.Length; break; } pPipe = pCCB->pPipe; pSCB = pPipe->pSCB; ntStatus = NpfsEnqueueBuffer( &pSCB->mdlList, pBuffer, Length, &ulBytesTransferred); BAIL_ON_NT_STATUS(ntStatus); while (!LwListIsEmpty(&pSCB->ReadIrpList) && !NpfsMdlListIsEmpty(&pSCB->mdlList)) { pLink = pSCB->ReadIrpList.Next; LwListRemove(pLink); pReadContext = LW_STRUCT_FROM_FIELD(pLink, NPFS_IRP_CONTEXT, Link); NpfsServerCompleteReadFile(pSCB, pReadContext); } pthread_cond_signal(&pPipe->PipeCondition); pIrpContext->pIrp->IoStatusBlock.BytesTransferred = ulBytesTransferred; error: pIrpContext->pIrp->IoStatusBlock.Status = ntStatus; return(ntStatus); }
VOID IopIrpCancelFileObject( IN PIO_FILE_OBJECT pFileObject, IN BOOLEAN IsForRundown ) { BOOLEAN isLocked = FALSE; PLW_LIST_LINKS pLinks = NULL; PIRP_INTERNAL irpInternal = NULL; LW_LIST_LINKS cancelList = { 0 }; PIRP pIrp = NULL; LwListInit(&cancelList); // Gather IRPs we want to cancel while holding FO lock. IopFileObjectLock(pFileObject); isLocked = TRUE; if (IsSetFlag(pFileObject->Flags, FILE_OBJECT_FLAG_CANCELLED)) { GOTO_CLEANUP(); } if (IsForRundown) { SetFlag(pFileObject->Flags, FILE_OBJECT_FLAG_CANCELLED); } // gather list of IRPs for (pLinks = pFileObject->IrpList.Next; pLinks != &pFileObject->IrpList; pLinks = pLinks->Next) { irpInternal = LW_STRUCT_FROM_FIELD(pLinks, IRP_INTERNAL, FileObjectLinks); LWIO_ASSERT(irpInternal->Irp.FileHandle == pFileObject); // Verify that this IRP is not already being cancelled. if (!irpInternal->CancelLinks.Next) { IopIrpReference(&irpInternal->Irp); LwListInsertTail(&cancelList, &irpInternal->CancelLinks); } } IopFileObjectUnlock(pFileObject); isLocked = FALSE; // Iterate over list, calling IopIrpCancel as appropriate. while (!LwListIsEmpty(&cancelList)) { pLinks = LwListRemoveHead(&cancelList); irpInternal = LW_STRUCT_FROM_FIELD(pLinks, IRP_INTERNAL, CancelLinks); pIrp = &irpInternal->Irp; IopIrpCancel(pIrp); IopIrpDereference(&pIrp); } cleanup: if (isLocked) { IopFileObjectUnlock(pFileObject); } }