NTSTATUS MemfsCreate( ULONG Flags, ULONG FileInfoTimeout, ULONG MaxFileNodes, ULONG MaxFileSize, PWSTR VolumePrefix, PWSTR RootSddl, MEMFS **PMemfs) { NTSTATUS Result; FSP_FSCTL_VOLUME_PARAMS VolumeParams; PWSTR DevicePath = (Flags & MemfsNet) ? L"" FSP_FSCTL_NET_DEVICE_NAME : L"" FSP_FSCTL_DISK_DEVICE_NAME; UINT64 AllocationUnit; MEMFS *Memfs; MEMFS_FILE_NODE *RootNode; PSECURITY_DESCRIPTOR RootSecurity; ULONG RootSecuritySize; BOOLEAN Inserted; *PMemfs = 0; if (0 == RootSddl) RootSddl = L"O:BAG:BAD:P(A;;FA;;;SY)(A;;FA;;;BA)(A;;FA;;;WD)"; if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(RootSddl, SDDL_REVISION_1, &RootSecurity, &RootSecuritySize)) return FspNtStatusFromWin32(GetLastError()); Memfs = (MEMFS *)malloc(sizeof *Memfs); if (0 == Memfs) { LocalFree(RootSecurity); return STATUS_INSUFFICIENT_RESOURCES; } memset(Memfs, 0, sizeof *Memfs); Memfs->MaxFileNodes = MaxFileNodes; AllocationUnit = MEMFS_SECTOR_SIZE * MEMFS_SECTORS_PER_ALLOCATION_UNIT; Memfs->MaxFileSize = (ULONG)((MaxFileSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit); Result = MemfsFileNodeMapCreate(&Memfs->FileNodeMap); if (!NT_SUCCESS(Result)) { free(Memfs); LocalFree(RootSecurity); return Result; } memset(&VolumeParams, 0, sizeof VolumeParams); VolumeParams.SectorSize = MEMFS_SECTOR_SIZE; VolumeParams.SectorsPerAllocationUnit = MEMFS_SECTORS_PER_ALLOCATION_UNIT; VolumeParams.VolumeCreationTime = MemfsGetSystemTime(); VolumeParams.VolumeSerialNumber = (UINT32)(MemfsGetSystemTime() / (10000 * 1000)); VolumeParams.FileInfoTimeout = FileInfoTimeout; VolumeParams.CaseSensitiveSearch = 1; VolumeParams.CasePreservedNames = 1; VolumeParams.UnicodeOnDisk = 1; VolumeParams.PersistentAcls = 1; if (0 != VolumePrefix) wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix); Result = FspFileSystemCreate(DevicePath, &VolumeParams, &MemfsInterface, &Memfs->FileSystem); if (!NT_SUCCESS(Result)) { MemfsFileNodeMapDelete(Memfs->FileNodeMap); free(Memfs); LocalFree(RootSecurity); return Result; } Memfs->FileSystem->UserContext = Memfs; Memfs->VolumeLabelLength = sizeof L"MEMFS" - sizeof(WCHAR); memcpy(Memfs->VolumeLabel, L"MEMFS", Memfs->VolumeLabelLength); #if 0 FspFileSystemSetOperationGuardStrategy(Memfs->FileSystem, FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE); #endif /* * Create root directory. */ Result = MemfsFileNodeCreate(L"\\", &RootNode); if (!NT_SUCCESS(Result)) { MemfsDelete(Memfs); LocalFree(RootSecurity); return Result; } RootNode->FileInfo.FileAttributes = FILE_ATTRIBUTE_DIRECTORY; RootNode->FileSecurity = malloc(RootSecuritySize); if (0 == RootNode->FileSecurity) { MemfsFileNodeDelete(RootNode); MemfsDelete(Memfs); LocalFree(RootSecurity); return STATUS_INSUFFICIENT_RESOURCES; } RootNode->FileSecuritySize = RootSecuritySize; memcpy(RootNode->FileSecurity, RootSecurity, RootSecuritySize); Result = MemfsFileNodeMapInsert(Memfs->FileNodeMap, RootNode, &Inserted); if (!NT_SUCCESS(Result)) { MemfsFileNodeDelete(RootNode); MemfsDelete(Memfs); LocalFree(RootSecurity); return Result; } LocalFree(RootSecurity); *PMemfs = Memfs; return STATUS_SUCCESS; }
int wmain(int argc, wchar_t **argv) { #if 0 WCHAR CurrentDirectory[MAX_PATH]; GetCurrentDirectoryW(MAX_PATH, CurrentDirectory); Test(CurrentDirectory); exit(0); #endif for (int argi = 1; argc > argi; argi++) { wchar_t *a = argv[argi]; if ('-' == a[0]) { if (0 == wcsncmp(L"--mask=", a, sizeof "--mask=" - 1)) OptCrashMask = wcstoul(a + sizeof "--mask=" - 1, 0, 0); else if (0 == wcscmp(L"--crash", a)) { OptCrashFlags &= ~FspCrashInterceptMask; OptCrashFlags |= FspCrashInterceptAccessViolation; } else if (0 == wcscmp(L"--terminate", a)) { OptCrashFlags &= ~FspCrashInterceptMask; OptCrashFlags |= FspCrashInterceptTerminate; } else if (0 == wcscmp(L"--huge-alloc-size", a)) { OptCrashFlags &= ~FspCrashInterceptMask; OptCrashFlags |= FspCrashInterceptHugeAllocationSize; } else if (0 == wcscmp(L"--enter", a)) OptCrashFlags |= FspCrashInterceptEnter; else if (0 == wcscmp(L"--leave", a)) OptCrashFlags |= FspCrashInterceptLeave; else if (0 == wcsncmp(L"--percent=", a, sizeof "--percent=" - 1)) OptCrashPercent = wcstoul(a + sizeof "--percent=" - 1, 0, 10); else if (0 == wcscmp(L"--disk", a)) OptMemfsFlags = MemfsDisk; else if (0 == wcscmp(L"--net", a)) OptMemfsFlags = MemfsNet; else if (0 == wcscmp(L"--non-cached", a)) OptFileInfoTimeout = 0; else if (0 == wcscmp(L"--cached", a)) OptFileInfoTimeout = -1; else if (0 == wcsncmp(L"--iterations=", a, sizeof "--iterations=" - 1)) OptIterations = wcstoul(a + sizeof "--iterations=" - 1, 0, 10); else if (0 == wcsncmp(L"--run-test=", a, sizeof "--run-test=" - 1)) OptPrefix = a + sizeof "--run-test=" - 1; else { fail("unknown option %S", a); exit(2); } } } if (0 == OptPrefix) { MEMFS *Memfs; HANDLE Process; DWORD ExitCode = -1; NTSTATUS Result; Result = MemfsCreate( OptMemfsFlags, OptFileInfoTimeout, 1024, 1024 * 1024, (MemfsNet & OptMemfsFlags) ? L"\\memfs\\share" : 0, 0, &Memfs); if (!NT_SUCCESS(Result)) { fail("cannot create MEMFS file system: (Status=%lx)", Result); exit(1); } //FspFileSystemSetDebugLog(MemfsFileSystem(Memfs), -1); FspCrashIntercept(MemfsFileSystem(Memfs), OptCrashMask, OptCrashFlags, OptCrashPercent); Result = MemfsStart(Memfs); if (!NT_SUCCESS(Result)) { fail("cannot start MEMFS file system: (Status=%lx)", Result); exit(1); } Result = CreateTestProcess( (MemfsNet & OptMemfsFlags) ? L"" : L"\\\\?\\GLOBALROOT", (MemfsNet & OptMemfsFlags) ? L"\\memfs\\share" : MemfsFileSystem(Memfs)->VolumeName, &Process); if (!NT_SUCCESS(Result)) { fail("cannot create test process: (Status=%lx)", Result); exit(1); } FspCrash(MemfsFileSystem(Memfs)); WaitForSingleObject(Process, INFINITE); GetExitCodeProcess(Process, &ExitCode); CloseHandle(Process); MemfsStop(Memfs); MemfsDelete(Memfs); if (0 != ExitCode) { fail("test process exitcode: %lx", ExitCode); exit(1); } } else { HANDLE Event; Event = OpenEvent(EVENT_MODIFY_STATE, FALSE, L"" FSCRASH_EVENT_NAME); if (0 == Event) { fail("cannot create test event: (Status=%lx)", FspNtStatusFromWin32(GetLastError())); exit(1); } for (ULONG Iterations = 0; -1 == OptIterations || OptIterations != Iterations; Iterations++) { Test(OptPrefix); SetEvent(Event); } } return 0; }