/**************************************************************************** * DeviceIoControl (KERNEL32.@) * This is one of those big ugly nasty procedure which can do * a million and one things when it comes to devices. It can also be * used for VxD communication. * * A return value of FALSE indicates that something has gone wrong which * GetLastError can decipher. */ BOOL WINAPI DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned, LPOVERLAPPED lpOverlapped) { NTSTATUS status; TRACE( "(%p,%x,%p,%d,%p,%d,%p,%p)\n", hDevice,dwIoControlCode,lpvInBuffer,cbInBuffer, lpvOutBuffer,cbOutBuffer,lpcbBytesReturned,lpOverlapped ); /* Check if this is a user defined control code for a VxD */ if( HIWORD( dwIoControlCode ) == 0 ) { DeviceIoProc proc = get_vxd_proc( hDevice ); if (proc) return proc( dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped ); return FALSE; } /* Not a VxD, let ntdll handle it */ if (lpOverlapped) { LPVOID cvalue = ((ULONG_PTR)lpOverlapped->hEvent & 1) ? NULL : lpOverlapped; lpOverlapped->Internal = STATUS_PENDING; lpOverlapped->InternalHigh = 0; if (HIWORD(dwIoControlCode) == FILE_DEVICE_FILE_SYSTEM) status = NtFsControlFile(hDevice, lpOverlapped->hEvent, NULL, cvalue, (PIO_STATUS_BLOCK)lpOverlapped, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer); else status = NtDeviceIoControlFile(hDevice, lpOverlapped->hEvent, NULL, cvalue, (PIO_STATUS_BLOCK)lpOverlapped, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer); if (lpcbBytesReturned) *lpcbBytesReturned = lpOverlapped->InternalHigh; } else { IO_STATUS_BLOCK iosb; if (HIWORD(dwIoControlCode) == FILE_DEVICE_FILE_SYSTEM) status = NtFsControlFile(hDevice, NULL, NULL, NULL, &iosb, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer); else status = NtDeviceIoControlFile(hDevice, NULL, NULL, NULL, &iosb, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer); if (lpcbBytesReturned) *lpcbBytesReturned = iosb.Information; } if (status) SetLastError( RtlNtStatusToDosError(status) ); return !status; }
BOOLEAN DiskDriveQueryNtfsVolumeInfo( _In_ HANDLE DosDeviceHandle, _Out_ PNTFS_VOLUME_INFO VolumeInfo ) { IO_STATUS_BLOCK isb; NTFS_VOLUME_INFO result; memset(&result, 0, sizeof(NTFS_VOLUME_INFO)); if (NT_SUCCESS(NtFsControlFile( DosDeviceHandle, NULL, NULL, NULL, &isb, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &result, sizeof(result) ))) { *VolumeInfo = result; return TRUE; } return FALSE; }
void CALLBACK RemoveDeviceW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { try { WCHAR *s, *vol, *dev; uint64_t devid; win_handle h, token; TOKEN_PRIVILEGES tp; LUID luid; NTSTATUS Status; IO_STATUS_BLOCK iosb; set_dpi_aware(); if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) throw last_error(GetLastError()); if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid)) throw last_error(GetLastError()); tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) throw last_error(GetLastError()); s = wcsstr(lpszCmdLine, L"|"); if (!s) return; s[0] = 0; vol = lpszCmdLine; dev = &s[1]; devid = _wtoi(dev); if (devid == 0) return; h = CreateFileW(vol, FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); if (h == INVALID_HANDLE_VALUE) throw last_error(GetLastError()); Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_REMOVE_DEVICE, &devid, sizeof(uint64_t), nullptr, 0); if (!NT_SUCCESS(Status)) { if (Status == STATUS_CANNOT_DELETE) throw string_error(IDS_CANNOT_REMOVE_RAID); else throw ntstatus_error(Status); return; } BtrfsBalance bb(vol, true); bb.ShowBalance(hwnd); } catch (const exception& e) { error_message(hwnd, e.what()); } }
BOOLEAN DiskDriveQueryRefsVolumeInfo( _In_ HANDLE DosDeviceHandle, _Out_ PREFS_VOLUME_DATA_BUFFER VolumeInfo ) { IO_STATUS_BLOCK isb; REFS_VOLUME_DATA_BUFFER result; memset(&result, 0, sizeof(REFS_VOLUME_DATA_BUFFER)); if (NT_SUCCESS(NtFsControlFile( DosDeviceHandle, NULL, NULL, NULL, &isb, FSCTL_GET_REFS_VOLUME_DATA, // FSCTL_QUERY_REFS_VOLUME_COUNTER_INFO NULL, 0, &result, sizeof(result) ))) { *VolumeInfo = result; return TRUE; } return FALSE; }
BOOLEAN UnlockVolume( HANDLE Handle ) { IO_STATUS_BLOCK ioStatusBlock; NTSTATUS nts; if (!NT_SUCCESS(nts = NtFsControlFile(Handle, NULL, NULL, NULL, &ioStatusBlock, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0))) { printf("Unable to unlock volume (%x).\n", nts); return FALSE; } else { return TRUE; } }
NTSTATUS DfsFsctl( IN HANDLE DfsHandle, IN ULONG FsControlCode, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength ) { NTSTATUS status; IO_STATUS_BLOCK ioStatus; status = NtFsControlFile( DfsHandle, NULL, // Event, NULL, // ApcRoutine, NULL, // ApcContext, &ioStatus, FsControlCode, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength ); if(NT_SUCCESS(status)) status = ioStatus.Status; return status; }
NTSTATUS PhDisconnectNamedPipe( _In_ HANDLE FileHandle ) { NTSTATUS status; IO_STATUS_BLOCK isb; status = NtFsControlFile( FileHandle, NULL, NULL, NULL, &isb, FSCTL_PIPE_DISCONNECT, NULL, 0, NULL, 0 ); if (status == STATUS_PENDING) { status = NtWaitForSingleObject(FileHandle, FALSE, NULL); if (NT_SUCCESS(status)) status = isb.Status; } return status; }
static __inline NTSTATUS _UnlockDrive( IN HANDLE Handle ) { IO_STATUS_BLOCK IoStatusBlock; return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0); }
static __inline NTSTATUS _DismountDrive( IN HANDLE Handle ) { IO_STATUS_BLOCK IoStatusBlock; return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0); }
static __inline BOOLEAN _IsMounted( IN HANDLE Handle ) { IO_STATUS_BLOCK IoStatusBlock; NTSTATUS Status; Status = NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_IS_VOLUME_MOUNTED, 0, 0, 0, 0); return (BOOLEAN)(STATUS_SUCCESS == Status); }
static int OnSendAsynchronousFsctl( HWND hDlg, ULONG IoctlCode, PVOID InputBuffer = NULL, ULONG InputBufferSize = 0, PVOID OutputBuffer = NULL, ULONG OutputBufferSize = 0) { TFileTestData * pData = GetDialogData(hDlg); TApcEntry * pApc; NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES; // Create new APC entry pApc = (TApcEntry *)CreateApcEntry(pData, APC_TYPE_FSCTL, sizeof(TApcEntry) + OutputBufferSize); if(pApc != NULL) { // If there's an output buffer, move it to the APC structure if(OutputBuffer && OutputBufferSize) { memcpy(pApc + 1, OutputBuffer, OutputBufferSize); OutputBuffer = (pApc + 1); } // Send the FSCTL Status = NtFsControlFile(pData->hFile, pApc->hEvent, NULL, NULL, &pApc->IoStatus, IoctlCode, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize); // If the IOCTL returned STATUS_PENDING, it means that the oplock is active. // If the oplock breaks, the event becomes signalled, and we get the APC message if(Status == STATUS_PENDING) { pApc->UserParam = IoctlCode; InsertApcEntry(pData, pApc); } else { FreeApcEntry(pApc); } } SetResultInfo(hDlg, RtlNtStatusToDosError(Status)); return TRUE; }
NTSTATUS FsRtlpRegisterProviderWithMUP(IN HANDLE MupHandle, IN PCUNICODE_STRING RedirectorDeviceName, IN BOOLEAN MailslotsSupported) { NTSTATUS Status; ULONG BufferSize; IO_STATUS_BLOCK IoStatusBlock; PMUP_PROVIDER_REGISTRATION_INFO RegistrationInfo; PAGED_CODE(); DPRINT1("FsRtlpRegisterProviderWithMUP(%p, %wZ, %u)\n", (PVOID)MupHandle, RedirectorDeviceName, MailslotsSupported); /* We have to be able to store the name and the registration information */ BufferSize = RedirectorDeviceName->Length + sizeof(MUP_PROVIDER_REGISTRATION_INFO); RegistrationInfo = ExAllocatePoolWithTag(NonPagedPool, BufferSize, TAG_UNC); if (RegistrationInfo == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } /* Set the information about the provider (including its name) */ RegistrationInfo->RedirectorDeviceNameOffset = sizeof(MUP_PROVIDER_REGISTRATION_INFO); RegistrationInfo->RedirectorDeviceNameLength = RedirectorDeviceName->Length; RegistrationInfo->MailslotsSupported = MailslotsSupported; RtlCopyMemory((PWSTR)((ULONG_PTR)RegistrationInfo + RegistrationInfo->RedirectorDeviceNameOffset), RedirectorDeviceName->Buffer, RedirectorDeviceName->Length); /* Call MUP with the registration FSCTL */ Status = NtFsControlFile(MupHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_MUP_REGISTER_PROVIDER, RegistrationInfo, BufferSize, NULL, 0); if (Status == STATUS_PENDING) { Status = NtWaitForSingleObject(MupHandle, TRUE, NULL); } if (NT_SUCCESS(Status)) { Status = IoStatusBlock.Status; } /* And we're done! */ ASSERT(NT_SUCCESS(Status)); ExFreePoolWithTag(RegistrationInfo, TAG_UNC); return Status; }
void fs_dismount() { NTSTATUS Status; IO_STATUS_BLOCK IoSb; /* Check if volume is dirty */ Status = NtFsControlFile(fd, NULL, NULL, NULL, &IoSb, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0); if (!NT_SUCCESS(Status)) { DPRINT1("NtFsControlFile() failed with Status 0x%08x\n", Status); } }
LW_NTSTATUS LwIoConnectNamedPipe( IO_FILE_HANDLE File, PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock, PIO_STATUS_BLOCK IoStatusBlock ) { return NtFsControlFile( File, AsyncControlBlock, IoStatusBlock, 0x2, NULL, 0, NULL, 0 ); }
NTSTATUS fs_lock(BOOLEAN LockVolume) { NTSTATUS Status; IO_STATUS_BLOCK IoSb; /* Check if volume is dirty */ Status = NtFsControlFile(fd, NULL, NULL, NULL, &IoSb, LockVolume ? FSCTL_LOCK_VOLUME : FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0); if (!NT_SUCCESS(Status)) { DPRINT1("NtFsControlFile() failed with Status 0x%08x\n", Status); } return Status; }
NTSTATUS PhListenNamedPipe( _In_ HANDLE FileHandle, _In_opt_ HANDLE Event, _In_opt_ PIO_APC_ROUTINE ApcRoutine, _In_opt_ PVOID ApcContext, _Out_ PIO_STATUS_BLOCK IoStatusBlock ) { return NtFsControlFile( FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0 ); }
BOOLEAN fs_isdirty() { ULONG DirtyMask = 0; NTSTATUS Status; IO_STATUS_BLOCK IoSb; /* Check if volume is dirty */ Status = NtFsControlFile(fd, NULL, NULL, NULL, &IoSb, FSCTL_IS_VOLUME_DIRTY, NULL, 0, &DirtyMask, sizeof(DirtyMask)); if (!NT_SUCCESS(Status)) { DPRINT1("NtFsControlFile() failed with Status 0x%08x\n", Status); return FALSE; } /* Convert Dirty mask to a boolean value */ return (DirtyMask & 1); }
int plug_and_play_t::run() { OBJECT_ATTRIBUTES oa; IO_STATUS_BLOCK iosb; HANDLE pipe = 0; NTSTATUS r; LARGE_INTEGER timeout; current = static_cast<thread_t*>( this ); unicode_string_t pipename; pipename.copy( "\\Device\\NamedPipe\\ntsvcs" ); oa.Length = sizeof oa; oa.RootDirectory = 0; oa.ObjectName = &pipename; oa.Attributes = OBJ_CASE_INSENSITIVE; oa.SecurityDescriptor = 0; oa.SecurityQualityOfService = 0; timeout.QuadPart = -10000LL; r = NtCreateNamedPipeFile( &pipe, GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE, &oa, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN_IF, 0, TRUE, TRUE, FALSE, -1, 0, 0, &timeout ); if (r == STATUS_THREAD_IS_TERMINATING) return 0; if (r < STATUS_SUCCESS) dprintf("failed to create ntsvcs %08lx\n", r); if (terminated) stop(); r = NtFsControlFile( pipe, 0, 0, 0, &iosb, FSCTL_PIPE_LISTEN, 0, 0, 0, 0 ); if (r == STATUS_THREAD_IS_TERMINATING) return 0; if (r < STATUS_SUCCESS) dprintf("failed to connect ntsvcs %08lx\n", r); stop(); return 0; }
void BtrfsDeviceResize::do_resize(HWND hwndDlg) { NTSTATUS Status; IO_STATUS_BLOCK iosb; btrfs_resize br; { win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); if (h == INVALID_HANDLE_VALUE) throw last_error(GetLastError()); br.device = dev_id; br.size = new_size; Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_RESIZE, &br, sizeof(btrfs_resize), nullptr, 0); if (Status != STATUS_MORE_PROCESSING_REQUIRED && !NT_SUCCESS(Status)) throw ntstatus_error(Status); } if (Status != STATUS_MORE_PROCESSING_REQUIRED) { wstring s, t, u; load_string(module, IDS_RESIZE_SUCCESSFUL, s); format_size(new_size, u, true); wstring_sprintf(t, s, dev_id, u.c_str()); MessageBoxW(hwndDlg, t.c_str(), L"", MB_OK); EndDialog(hwndDlg, 0); } else { HWND par; par = GetParent(hwndDlg); EndDialog(hwndDlg, 0); BtrfsBalance bb(fn, false, true); bb.ShowBalance(par); } }
HRESULT __stdcall BtrfsIconOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib) { HANDLE h; NTSTATUS Status; IO_STATUS_BLOCK iosb; btrfs_get_file_ids bgfi; h = CreateFileW(pwszPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); if (h == INVALID_HANDLE_VALUE) return S_FALSE; Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_FILE_IDS, NULL, 0, &bgfi, sizeof(btrfs_get_file_ids)); if (Status != STATUS_SUCCESS) { CloseHandle(h); return S_FALSE; } CloseHandle(h); return (bgfi.inode == 0x100 && !bgfi.top) ? S_OK : S_FALSE; }
BOOLEAN DiskDriveQueryVolumeDirty( _In_ HANDLE DosDeviceHandle, _Out_ PBOOLEAN IsDirty ) { ULONG result; IO_STATUS_BLOCK isb; memset(&result, 0, sizeof(ULONG)); if (NT_SUCCESS(NtFsControlFile( DosDeviceHandle, NULL, NULL, NULL, &isb, FSCTL_IS_VOLUME_DIRTY, NULL, 0, &result, sizeof(result) ))) { if (result & VOLUME_IS_DIRTY) { *IsDirty = TRUE; } else { *IsDirty = FALSE; } return TRUE; } return FALSE; }
/* * @implemented */ BOOL WINAPI DisconnectNamedPipe(HANDLE hNamedPipe) { IO_STATUS_BLOCK Iosb; NTSTATUS Status; /* Send the FSCTL to the driver */ Status = NtFsControlFile(hNamedPipe, NULL, NULL, NULL, &Iosb, FSCTL_PIPE_DISCONNECT, NULL, 0, NULL, 0); if (Status == STATUS_PENDING) { /* Wait on NPFS to finish and get updated status */ Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL); if (NT_SUCCESS(Status)) Status = Iosb.Status; } /* Check for error */ if (!NT_SUCCESS(Status)) { /* Fail */ BaseSetLastNTError(Status); return FALSE; } return TRUE; }
BOOLEAN UnlockVolume( HANDLE Handle ) { IO_STATUS_BLOCK IoStatusBlock; if( !NT_SUCCESS(NtFsControlFile( Handle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0 )) ) { printf( "Unable to unlock volume.\n" ); return FALSE; } return TRUE; }
/* * @implemented */ BOOL WINAPI ConnectNamedPipe(IN HANDLE hNamedPipe, IN LPOVERLAPPED lpOverlapped) { NTSTATUS Status; if (lpOverlapped != NULL) { PVOID ApcContext; lpOverlapped->Internal = STATUS_PENDING; ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped); Status = NtFsControlFile(hNamedPipe, lpOverlapped->hEvent, NULL, ApcContext, (PIO_STATUS_BLOCK)lpOverlapped, FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0); /* return FALSE in case of failure and pending operations! */ if (!NT_SUCCESS(Status) || Status == STATUS_PENDING) { BaseSetLastNTError(Status); return FALSE; } } else { IO_STATUS_BLOCK Iosb; Status = NtFsControlFile(hNamedPipe, NULL, NULL, NULL, &Iosb, FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0); /* wait in case operation is pending */ if (Status == STATUS_PENDING) { Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL); if (NT_SUCCESS(Status)) { Status = Iosb.Status; } } if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); return FALSE; } } return TRUE; }
/* * @implemented */ BOOLEAN WINAPI CreateSymbolicLinkW(IN LPCWSTR lpSymlinkFileName, IN LPCWSTR lpTargetFileName, IN DWORD dwFlags) { IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE hSymlink = NULL; UNICODE_STRING SymlinkFileName = { 0, 0, NULL }; UNICODE_STRING TargetFileName = { 0, 0, NULL }; BOOLEAN bAllocatedTarget = FALSE, bRelativePath = FALSE; LPWSTR lpTargetFullFileName = NULL; SIZE_T cbPrintName; SIZE_T cbReparseData; PREPARSE_DATA_BUFFER pReparseData = NULL; PBYTE pBufTail; NTSTATUS Status; ULONG dwCreateOptions; DWORD dwErr; if(!lpSymlinkFileName || !lpTargetFileName || (dwFlags | SYMBOLIC_LINK_FLAG_DIRECTORY) != SYMBOLIC_LINK_FLAG_DIRECTORY) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } if(dwFlags & SYMBOLIC_LINK_FLAG_DIRECTORY) dwCreateOptions = FILE_DIRECTORY_FILE; else dwCreateOptions = FILE_NON_DIRECTORY_FILE; switch(RtlDetermineDosPathNameType_U(lpTargetFileName)) { case RtlPathTypeUnknown: case RtlPathTypeRooted: case RtlPathTypeRelative: bRelativePath = TRUE; RtlInitUnicodeString(&TargetFileName, lpTargetFileName); break; case RtlPathTypeDriveRelative: { LPWSTR FilePart; SIZE_T cchTargetFullFileName; cchTargetFullFileName = GetFullPathNameW(lpTargetFileName, 0, NULL, &FilePart); if(cchTargetFullFileName == 0) { dwErr = GetLastError(); goto Cleanup; } lpTargetFullFileName = RtlAllocateHeap(RtlGetProcessHeap(), 0, cchTargetFullFileName * sizeof(WCHAR)); if(lpTargetFullFileName == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } if(GetFullPathNameW(lpTargetFileName, cchTargetFullFileName, lpTargetFullFileName, &FilePart) == 0) { dwErr = GetLastError(); goto Cleanup; } } lpTargetFileName = lpTargetFullFileName; // fallthrough case RtlPathTypeUncAbsolute: case RtlPathTypeDriveAbsolute: case RtlPathTypeLocalDevice: case RtlPathTypeRootLocalDevice: default: if(!RtlDosPathNameToNtPathName_U(lpTargetFileName, &TargetFileName, NULL, NULL)) { bAllocatedTarget = TRUE; dwErr = ERROR_INVALID_PARAMETER; goto Cleanup; } } cbPrintName = wcslen(lpTargetFileName) * sizeof(WCHAR); cbReparseData = FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + TargetFileName.Length + cbPrintName; pReparseData = RtlAllocateHeap(RtlGetProcessHeap(), 0, cbReparseData); if(pReparseData == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } pBufTail = (PBYTE)(pReparseData->SymbolicLinkReparseBuffer.PathBuffer); pReparseData->ReparseTag = (ULONG)IO_REPARSE_TAG_SYMLINK; pReparseData->ReparseDataLength = (USHORT)cbReparseData - REPARSE_DATA_BUFFER_HEADER_SIZE; pReparseData->Reserved = 0; pReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0; pReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength = TargetFileName.Length; pBufTail += pReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset; RtlCopyMemory(pBufTail, TargetFileName.Buffer, TargetFileName.Length); pReparseData->SymbolicLinkReparseBuffer.PrintNameOffset = pReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength; pReparseData->SymbolicLinkReparseBuffer.PrintNameLength = (USHORT)cbPrintName; pBufTail += pReparseData->SymbolicLinkReparseBuffer.PrintNameOffset; RtlCopyMemory(pBufTail, lpTargetFileName, cbPrintName); pReparseData->SymbolicLinkReparseBuffer.Flags = 0; if(bRelativePath) pReparseData->SymbolicLinkReparseBuffer.Flags |= 1; // TODO! give this lone flag a name if(!RtlDosPathNameToNtPathName_U(lpSymlinkFileName, &SymlinkFileName, NULL, NULL)) { dwErr = ERROR_PATH_NOT_FOUND; goto Cleanup; } InitializeObjectAttributes(&ObjectAttributes, &SymlinkFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtCreateFile ( &hSymlink, FILE_WRITE_ATTRIBUTES | DELETE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_CREATE, FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT | dwCreateOptions, NULL, 0 ); if(!NT_SUCCESS(Status)) { dwErr = RtlNtStatusToDosError(Status); goto Cleanup; } Status = NtFsControlFile ( hSymlink, NULL, NULL, NULL, &IoStatusBlock, FSCTL_SET_REPARSE_POINT, pReparseData, cbReparseData, NULL, 0 ); if(!NT_SUCCESS(Status)) { FILE_DISPOSITION_INFORMATION DispInfo; DispInfo.DeleteFile = TRUE; NtSetInformationFile(hSymlink, &IoStatusBlock, &DispInfo, sizeof(DispInfo), FileDispositionInformation); dwErr = RtlNtStatusToDosError(Status); goto Cleanup; } dwErr = NO_ERROR; Cleanup: if(hSymlink) NtClose(hSymlink); RtlFreeUnicodeString(&SymlinkFileName); if (bAllocatedTarget) { RtlFreeHeap(RtlGetProcessHeap(), 0, TargetFileName.Buffer); } if(lpTargetFullFileName) RtlFreeHeap(RtlGetProcessHeap(), 0, lpTargetFullFileName); if(pReparseData) RtlFreeHeap(RtlGetProcessHeap(), 0, pReparseData); if(dwErr) { SetLastError(dwErr); return FALSE; } return TRUE; }
NTSTATUS FsRtlpRegisterProviderWithMUP ( IN HANDLE mupHandle, IN PUNICODE_STRING RedirDevName, IN BOOLEAN MailslotsSupported ) /*++ Routine Description: This private routine does the FSCTL to the MUP to tell it about a new redir Arguments: mupHandle - Handle to the MUP RedirDevName - The device name of the redir. MailslotsSupported - If TRUE, this redir supports mailslots. Return Value: NTSTATUS - The status of the operation. --*/ { NTSTATUS status; IO_STATUS_BLOCK ioStatusBlock; ULONG paramLength; PREDIRECTOR_REGISTRATION params; PAGED_CODE(); paramLength = sizeof( REDIRECTOR_REGISTRATION ) + RedirDevName->Length; params = ExAllocatePoolWithTag( NonPagedPool, paramLength, MODULE_POOL_TAG ); if( params == NULL ) return STATUS_INSUFFICIENT_RESOURCES; params->DeviceNameOffset = sizeof( REDIRECTOR_REGISTRATION ); params->DeviceNameLength = RedirDevName->Length; params->MailslotsSupported = MailslotsSupported; RtlCopyMemory( (PCHAR)params + params->DeviceNameOffset, RedirDevName->Buffer, RedirDevName->Length ); status = NtFsControlFile( mupHandle, 0, NULL, NULL, &ioStatusBlock, FSCTL_MUP_REGISTER_UNC_PROVIDER, params, paramLength, NULL, 0 ); if ( status == STATUS_PENDING ) { status = NtWaitForSingleObject( mupHandle, TRUE, NULL ); } if ( NT_SUCCESS( status ) ) { status = ioStatusBlock.Status; } ASSERT( NT_SUCCESS( status ) ); ExFreePool( params ); return status; }
INT_PTR CALLBACK BtrfsDeviceResize::DeviceResizeDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { try { switch (uMsg) { case WM_INITDIALOG: { win_handle h; WCHAR s[255]; wstring t, u; EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); GetDlgItemTextW(hwndDlg, IDC_RESIZE_DEVICE_ID, s, sizeof(s) / sizeof(WCHAR)); wstring_sprintf(t, s, dev_id); SetDlgItemTextW(hwndDlg, IDC_RESIZE_DEVICE_ID, t.c_str()); h = CreateFileW(fn.c_str(), FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); if (h != INVALID_HANDLE_VALUE) { NTSTATUS Status; IO_STATUS_BLOCK iosb; btrfs_device *devices, *bd; ULONG devsize; bool found = false; HWND slider; devsize = 1024; devices = (btrfs_device*)malloc(devsize); while (true) { Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_DEVICES, nullptr, 0, devices, devsize); if (Status == STATUS_BUFFER_OVERFLOW) { devsize += 1024; free(devices); devices = (btrfs_device*)malloc(devsize); } else break; } if (!NT_SUCCESS(Status)) { free(devices); return false; } bd = devices; while (true) { if (bd->dev_id == dev_id) { memcpy(&dev_info, bd, sizeof(btrfs_device)); found = true; break; } if (bd->next_entry > 0) bd = (btrfs_device*)((uint8_t*)bd + bd->next_entry); else break; } if (!found) { free(devices); return false; } free(devices); GetDlgItemTextW(hwndDlg, IDC_RESIZE_CURSIZE, s, sizeof(s) / sizeof(WCHAR)); format_size(dev_info.size, u, true); wstring_sprintf(t, s, u.c_str()); SetDlgItemTextW(hwndDlg, IDC_RESIZE_CURSIZE, t.c_str()); new_size = dev_info.size; GetDlgItemTextW(hwndDlg, IDC_RESIZE_NEWSIZE, new_size_text, sizeof(new_size_text) / sizeof(WCHAR)); wstring_sprintf(t, new_size_text, u.c_str()); SetDlgItemTextW(hwndDlg, IDC_RESIZE_NEWSIZE, t.c_str()); slider = GetDlgItem(hwndDlg, IDC_RESIZE_SLIDER); SendMessageW(slider, TBM_SETRANGEMIN, false, 0); SendMessageW(slider, TBM_SETRANGEMAX, false, (LPARAM)(dev_info.max_size / 1048576)); SendMessageW(slider, TBM_SETPOS, true, (LPARAM)(new_size / 1048576)); } else return false; break; } case WM_COMMAND: switch (HIWORD(wParam)) { case BN_CLICKED: switch (LOWORD(wParam)) { case IDOK: do_resize(hwndDlg); return true; case IDCANCEL: EndDialog(hwndDlg, 0); return true; } break; } break; case WM_HSCROLL: { wstring t, u; new_size = UInt32x32To64(SendMessageW(GetDlgItem(hwndDlg, IDC_RESIZE_SLIDER), TBM_GETPOS, 0, 0), 1048576); format_size(new_size, u, true); wstring_sprintf(t, new_size_text, u.c_str()); SetDlgItemTextW(hwndDlg, IDC_RESIZE_NEWSIZE, t.c_str()); EnableWindow(GetDlgItem(hwndDlg, IDOK), new_size > 0 ? true : false); break; } } } catch (const exception& e) { error_message(hwndDlg, e.what()); } return false; }
//-------------------------------------------------------------------- // // ScanFile // // This is only invoked for compressed, encrypted or sparse files, // which exists only on NTFS drives (WinNT/2K). Thus, we can use // the defrag API to zap the clusters belonging to the file // Determines if the the file is non-resident (outside the MFT), and // if so and we were able to open the volume for write access, we zap // the clusters. // //-------------------------------------------------------------------- BOOLEAN ScanFile( HANDLE VolumeHandle, DWORD ClusterSize, HANDLE FileHandle, PBOOLEAN ReallyCompressed, PBOOLEAN ZappedFile ) { DWORD status; int i; IO_STATUS_BLOCK ioStatus; ULONGLONG startVcn, prevVcn; LARGE_INTEGER clusterOffset; ULONGLONG endOfPrevRun; PGET_RETRIEVAL_DESCRIPTOR fileMappings; ULONGLONG fileMap[ FILEMAPSIZE ]; int lines = 0; // // Assume file is in an MFT record. // *ReallyCompressed = FALSE; *ZappedFile = FALSE; startVcn = 0; endOfPrevRun = LLINVALID; fileMappings = (PGET_RETRIEVAL_DESCRIPTOR) fileMap; while( !(status = NtFsControlFile( FileHandle, NULL, NULL, 0, &ioStatus, FSCTL_GET_RETRIEVAL_POINTERS, &startVcn, sizeof( startVcn ), fileMappings, FILEMAPSIZE * sizeof(ULONGLONG) ) ) || status == STATUS_BUFFER_OVERFLOW || status == STATUS_PENDING ) { // // If the operation is pending, wait for it to finish // if( status == STATUS_PENDING ) { WaitForSingleObject( FileHandle, INFINITE ); // // Get the status from the status block // if( ioStatus.Status != STATUS_SUCCESS && ioStatus.Status != STATUS_BUFFER_OVERFLOW ) { return ioStatus.Status == STATUS_SUCCESS; } } // // Loop through the buffer of number/cluster pairs, printing them // out. // startVcn = fileMappings->StartVcn; prevVcn = fileMappings->StartVcn; for( i = 0; i < (ULONGLONG) fileMappings->NumberOfPairs; i++ ) { // // On NT 4.0, a compressed virtual run (0-filled) is // identified with a cluster offset of -1 // if( fileMappings->Pair[i].Lcn != LLINVALID ) { // // Its compressed and outside the zone // *ReallyCompressed = TRUE; // // Overwrite the clusters if we were able to open the volume // for write access. // if( VolumeHandle != INVALID_HANDLE_VALUE ) { clusterOffset.QuadPart = fileMappings->Pair[i].Lcn * ClusterSize; SetFilePointer( VolumeHandle, clusterOffset.LowPart, &clusterOffset.HighPart, FILE_BEGIN ); if( !SecureOverwrite( VolumeHandle, ClusterSize * (DWORD) (fileMappings->Pair[i].Vcn - startVcn) )) { // // Couldn't zap the clusters, so we'll have to clean the free space // return TRUE; } } else { return TRUE; } } startVcn = fileMappings->Pair[i].Vcn; } // // If the buffer wasn't overflowed, then we're done // if( !status ) break; } // // Return now if there were any errors // if( status && status != STATUS_INVALID_PARAMETER && !Silent ) { printf("Scanning file: "); PrintNtError( status ); } // // If we made through with no errors we've overwritten all the file's // clusters. // if( status == STATUS_SUCCESS ) *ZappedFile = TRUE; return status == STATUS_SUCCESS; }
void BtrfsDeviceAdd::AddDevice(HWND hwndDlg) { wstring mess, title; NTSTATUS Status; UNICODE_STRING vn; OBJECT_ATTRIBUTES attr; IO_STATUS_BLOCK iosb; if (!sel) { EndDialog(hwndDlg, 0); return; } if (sel->fstype != L"") { wstring s; if (!load_string(module, IDS_ADD_DEVICE_CONFIRMATION_FS, s)) throw last_error(GetLastError()); wstring_sprintf(mess, s, sel->fstype.c_str()); } else { if (!load_string(module, IDS_ADD_DEVICE_CONFIRMATION, mess)) throw last_error(GetLastError()); } if (!load_string(module, IDS_CONFIRMATION_TITLE, title)) throw last_error(GetLastError()); if (MessageBoxW(hwndDlg, mess.c_str(), title.c_str(), MB_YESNO) != IDYES) return; win_handle h = CreateFileW(cmdline, FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); if (h == INVALID_HANDLE_VALUE) throw last_error(GetLastError()); { nt_handle h2; vn.Length = vn.MaximumLength = (uint16_t)(sel->pnp_name.length() * sizeof(WCHAR)); vn.Buffer = (WCHAR*)sel->pnp_name.c_str(); InitializeObjectAttributes(&attr, &vn, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, nullptr, nullptr); Status = NtOpenFile(&h2, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT); if (!NT_SUCCESS(Status)) throw ntstatus_error(Status); if (!sel->is_disk) { Status = NtFsControlFile(h2, nullptr, nullptr, nullptr, &iosb, FSCTL_LOCK_VOLUME, nullptr, 0, nullptr, 0); if (!NT_SUCCESS(Status)) throw string_error(IDS_LOCK_FAILED, Status); } Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_ADD_DEVICE, &h2, sizeof(HANDLE), nullptr, 0); if (!NT_SUCCESS(Status)) throw ntstatus_error(Status); if (!sel->is_disk) { Status = NtFsControlFile(h2, nullptr, nullptr, nullptr, &iosb, FSCTL_DISMOUNT_VOLUME, nullptr, 0, nullptr, 0); if (!NT_SUCCESS(Status)) throw ntstatus_error(Status); Status = NtFsControlFile(h2, nullptr, nullptr, nullptr, &iosb, FSCTL_UNLOCK_VOLUME, nullptr, 0, nullptr, 0); if (!NT_SUCCESS(Status)) throw ntstatus_error(Status); } } EndDialog(hwndDlg, 0); }
NTSTATUS NTAPI VfatFormat(IN PUNICODE_STRING DriveRoot, IN FMIFS_MEDIA_FLAG MediaFlag, IN PUNICODE_STRING Label, IN BOOLEAN QuickFormat, IN ULONG ClusterSize, IN PFMIFSCALLBACK Callback) { OBJECT_ATTRIBUTES ObjectAttributes; DISK_GEOMETRY DiskGeometry; IO_STATUS_BLOCK Iosb; HANDLE FileHandle; PARTITION_INFORMATION PartitionInfo; FORMAT_CONTEXT Context; NTSTATUS Status, LockStatus; DPRINT("VfatFormat(DriveRoot '%wZ')\n", DriveRoot); Context.TotalSectorCount = 0; Context.CurrentSectorCount = 0; Context.Callback = Callback; Context.Success = FALSE; Context.Percent = 0; InitializeObjectAttributes(&ObjectAttributes, DriveRoot, 0, NULL, NULL); Status = NtOpenFile(&FileHandle, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &ObjectAttributes, &Iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT); if (!NT_SUCCESS(Status)) { DPRINT1("NtOpenFile() failed with status 0x%.08x\n", Status); return Status; } Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &DiskGeometry, sizeof(DISK_GEOMETRY)); if (!NT_SUCCESS(Status)) { DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY failed with status 0x%.08x\n", Status); NtClose(FileHandle); return Status; } if (DiskGeometry.MediaType == FixedMedia) { DPRINT("Cylinders %I64d\n", DiskGeometry.Cylinders.QuadPart); DPRINT("TracksPerCylinder %ld\n", DiskGeometry.TracksPerCylinder); DPRINT("SectorsPerTrack %ld\n", DiskGeometry.SectorsPerTrack); DPRINT("BytesPerSector %ld\n", DiskGeometry.BytesPerSector); DPRINT("DiskSize %I64d\n", DiskGeometry.Cylinders.QuadPart * (ULONGLONG)DiskGeometry.TracksPerCylinder * (ULONGLONG)DiskGeometry.SectorsPerTrack * (ULONGLONG)DiskGeometry.BytesPerSector); Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &PartitionInfo, sizeof(PARTITION_INFORMATION)); if (!NT_SUCCESS(Status)) { DPRINT("IOCTL_DISK_GET_PARTITION_INFO failed with status 0x%.08x\n", Status); NtClose(FileHandle); return Status; } /* * FIXME: This is a hack! * Partitioning software MUST set the correct number of hidden sectors! */ PartitionInfo.HiddenSectors = DiskGeometry.SectorsPerTrack; } else { PartitionInfo.PartitionType = 0; PartitionInfo.StartingOffset.QuadPart = 0ULL; PartitionInfo.PartitionLength.QuadPart = DiskGeometry.Cylinders.QuadPart * (ULONGLONG)DiskGeometry.TracksPerCylinder * (ULONGLONG)DiskGeometry.SectorsPerTrack * (ULONGLONG)DiskGeometry.BytesPerSector; PartitionInfo.HiddenSectors = 0; PartitionInfo.PartitionNumber = 0; PartitionInfo.BootIndicator = FALSE; PartitionInfo.RewritePartition = FALSE; PartitionInfo.RecognizedPartition = FALSE; } /* If it already has a FAT FS, we'll use that type. * If it doesn't, we will determine the FAT type based on size and offset */ if (PartitionInfo.PartitionType != PARTITION_FAT_12 && PartitionInfo.PartitionType != PARTITION_FAT_16 && PartitionInfo.PartitionType != PARTITION_HUGE && PartitionInfo.PartitionType != PARTITION_XINT13 && PartitionInfo.PartitionType != PARTITION_FAT32 && PartitionInfo.PartitionType != PARTITION_FAT32_XINT13) { /* Determine the correct type based upon size and offset (copied from usetup) */ if (PartitionInfo.PartitionLength.QuadPart < (4200LL * 1024LL)) { /* FAT12 CHS partition (disk is smaller than 4.1MB) */ PartitionInfo.PartitionType = PARTITION_FAT_12; } else if (PartitionInfo.StartingOffset.QuadPart < (1024LL * 255LL * 63LL * 512LL)) { /* Partition starts below the 8.4GB boundary ==> CHS partition */ if (PartitionInfo.PartitionLength.QuadPart < (32LL * 1024LL * 1024LL)) { /* FAT16 CHS partition (partiton size < 32MB) */ PartitionInfo.PartitionType = PARTITION_FAT_16; } else if (PartitionInfo.PartitionLength.QuadPart < (512LL * 1024LL * 1024LL)) { /* FAT16 CHS partition (partition size < 512MB) */ PartitionInfo.PartitionType = PARTITION_HUGE; } else { /* FAT32 CHS partition (partition size >= 512MB) */ PartitionInfo.PartitionType = PARTITION_FAT32; } } else { /* Partition starts above the 8.4GB boundary ==> LBA partition */ if (PartitionInfo.PartitionLength.QuadPart < (512LL * 1024LL * 1024LL)) { /* FAT16 LBA partition (partition size < 512MB) */ PartitionInfo.PartitionType = PARTITION_XINT13; } else { /* FAT32 LBA partition (partition size >= 512MB) */ PartitionInfo.PartitionType = PARTITION_FAT32_XINT13; } } } DPRINT("PartitionType 0x%x\n", PartitionInfo.PartitionType); DPRINT("StartingOffset %I64d\n", PartitionInfo.StartingOffset.QuadPart); DPRINT("PartitionLength %I64d\n", PartitionInfo.PartitionLength.QuadPart); DPRINT("HiddenSectors %lu\n", PartitionInfo.HiddenSectors); DPRINT("PartitionNumber %d\n", PartitionInfo.PartitionNumber); DPRINT("BootIndicator 0x%x\n", PartitionInfo.BootIndicator); DPRINT("RewritePartition %d\n", PartitionInfo.RewritePartition); DPRINT("RecognizedPartition %d\n", PartitionInfo.RecognizedPartition); if (Callback != NULL) { Context.Percent = 0; Callback (PROGRESS, 0, (PVOID)&Context.Percent); } LockStatus = NtFsControlFile(FileHandle, NULL, NULL, NULL, &Iosb, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0); if (!NT_SUCCESS(LockStatus)) { DPRINT1("WARNING: Failed to lock volume for formatting! Format may fail! (Status: 0x%x)\n", LockStatus); } if (PartitionInfo.PartitionType == PARTITION_FAT_12) { /* FAT12 */ Status = Fat12Format(FileHandle, &PartitionInfo, &DiskGeometry, Label, QuickFormat, ClusterSize, &Context); } else if (PartitionInfo.PartitionType == PARTITION_FAT_16 || PartitionInfo.PartitionType == PARTITION_HUGE || PartitionInfo.PartitionType == PARTITION_XINT13) { /* FAT16 */ Status = Fat16Format(FileHandle, &PartitionInfo, &DiskGeometry, Label, QuickFormat, ClusterSize, &Context); } else if (PartitionInfo.PartitionType == PARTITION_FAT32 || PartitionInfo.PartitionType == PARTITION_FAT32_XINT13) { /* FAT32 */ Status = Fat32Format(FileHandle, &PartitionInfo, &DiskGeometry, Label, QuickFormat, ClusterSize, &Context); } else { Status = STATUS_INVALID_PARAMETER; } /* Attempt to dismount formatted volume */ LockStatus = NtFsControlFile(FileHandle, NULL, NULL, NULL, &Iosb, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0); if (!NT_SUCCESS(LockStatus)) { DPRINT1("Failed to umount volume (Status: 0x%x)\n", LockStatus); } LockStatus = NtFsControlFile(FileHandle, NULL, NULL, NULL, &Iosb, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0); if (!NT_SUCCESS(LockStatus)) { DPRINT1("Failed to unlock volume (Status: 0x%x)\n", LockStatus); } NtClose(FileHandle); if (Callback != NULL) { Context.Success = (BOOLEAN)(NT_SUCCESS(Status)); Callback (DONE, 0, (PVOID)&Context.Success); } DPRINT("VfatFormat() done. Status 0x%.08x\n", Status); return Status; }