Ejemplo n.º 1
0
/****************************************************************************
 *		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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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());
    }
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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;
    }
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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);
}
Ejemplo n.º 9
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);
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 12
0
Archivo: unc.c Proyecto: GYGit/reactos
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;
}
Ejemplo n.º 13
0
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);
    }
}
Ejemplo n.º 14
0
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
        );
}
Ejemplo n.º 15
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;
}
Ejemplo n.º 16
0
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
        );
}
Ejemplo n.º 17
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);
}
Ejemplo n.º 18
0
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;
}
Ejemplo n.º 19
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);
    }
}
Ejemplo n.º 20
0
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;
}
Ejemplo n.º 21
0
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;
}
Ejemplo n.º 22
0
/*
 * @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;
}
Ejemplo n.º 23
0
Archivo: dd4.c Proyecto: mingpen/OpenNT
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;
}
Ejemplo n.º 24
0
/*
 * @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;
}
Ejemplo n.º 25
0
/*
 * @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;
}
Ejemplo n.º 26
0
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;
}
Ejemplo n.º 27
0
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;
}
Ejemplo n.º 28
0
//--------------------------------------------------------------------
//
// 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;
}
Ejemplo n.º 29
0
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);
}
Ejemplo n.º 30
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;
}