NT4/private/ntos/dd/ftapi/lib/ftapi.c
2020-09-30 17:12:29 +02:00

410 lines
9.1 KiB
C

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
ftapi.c
Abstract:
This implements the FT API services.
Author:
Norbert Kusters 16-May-1995
Notes:
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include "ftapi.h"
NTSTATUS
DiskQueryVolumeDescriptionLength(
IN HANDLE VolumeHandle,
OUT PULONG VolumeDescriptionLength
)
/*++
Routine Description:
This routine returns the number of bytes required to return the
volume description.
Arguments:
VolumeHandle - Supplies a DASD handle to the volume.
VolumeDescriptionLength - Returns the length of the volume description.
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
FT_VOLUME_DESCRIPTION_LENGTH volLength;
status = NtDeviceIoControlFile(VolumeHandle, 0, NULL, NULL, &ioStatus,
FT_QUERY_VOLUME_DESCRIPTION_LENGTH,
NULL, 0, &volLength,
sizeof(FT_VOLUME_DESCRIPTION_LENGTH));
if (NT_SUCCESS(status)) {
*VolumeDescriptionLength = volLength.Length;
}
return status;
}
NTSTATUS
DiskQueryVolumeDescription(
IN HANDLE VolumeHandle,
OUT PFT_VOLUME_DESCRIPTION VolumeDescription,
IN ULONG VolumeDescriptionLength
)
/*++
Routine Description:
This routine returns the volume description for the given volume.
This returns a list that completely describes how all of the
separate partitions in the volume are structures and stacked.
Arguments:
VolumeHandle - Supplies a DASD handle to the volume.
VolumeDescription - Returns the volume description.
VolumeDescriptionLength - Supplies the size of the volume description
buffer.
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
status = NtDeviceIoControlFile(VolumeHandle, 0, NULL, NULL, &ioStatus,
FT_QUERY_VOLUME_DESCRIPTION,
NULL, 0, VolumeDescription,
VolumeDescriptionLength);
return status;
}
NTSTATUS
DiskRegenerate(
IN HANDLE Volume,
IN HANDLE NewMemberVolume
)
/*++
Routine Description:
This routine regenerates an orphaned member on 'Volume' using
'NewMemberVolume' as a new member for 'Volume'.
Arguments:
Volume - Supplies a DASD handle to the volume that has an orphan.
NewMemberVolume - Supplies a DASD handle to a new volume that will serve
to replace the orphan.
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
FT_VOLUME_DESCRIPTOR desc;
status = NtDeviceIoControlFile(NewMemberVolume, 0, NULL, NULL, &ioStatus,
FT_QUERY_VOLUME_DESCRIPTOR,
NULL, 0, &desc,
sizeof(FT_VOLUME_DESCRIPTOR));
if (!NT_SUCCESS(status)) {
return status;
}
status = NtDeviceIoControlFile(Volume, 0, NULL, NULL, &ioStatus,
FT_REGENERATE, &desc,
sizeof(FT_VOLUME_DESCRIPTOR), NULL, 0);
return status;
}
NTSTATUS
DiskDisolveVolume(
IN HANDLE Volume
)
/*++
Routine Description:
This routine breaks a composite volume (e.g. a mirror, stripe, volume set,
or a stack of these) into its individual partitions. Instead of having
one volume, you then have many partitions.
Arguments:
Volume - Supplies a DASD handle to the volume to disolve.
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
status = NtDeviceIoControlFile(Volume, 0, NULL, NULL, &ioStatus,
FT_DISOLVE_VOLUME, NULL, 0, NULL, 0);
return status;
}
NTSTATUS
DiskInitFtSet(
IN HANDLE Volume
)
/*++
Routine Description:
This routine starts up pending FT operations after set creation.
Such as regenerates and initializes.
Arguments:
Volume - Supplies a DASD handle to the volume to init.
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
status = NtDeviceIoControlFile(Volume, 0, NULL, NULL, &ioStatus,
FT_INITIALIZE_SET, NULL, 0, NULL, 0);
return status;
}
NTSTATUS
CreateVolumeList(
IN HANDLE* MemberVolumes,
IN ULONG NumberOfMembers,
OUT PFT_VOLUME_DESCRIPTOR_LIST* VolList,
OUT PULONG VolListSize
)
{
ULONG i;
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
FT_VOLUME_DESCRIPTOR volDesc;
*VolListSize = FIELD_OFFSET(FT_VOLUME_DESCRIPTOR_LIST, VolumeDescriptor) +
NumberOfMembers*sizeof(ULONG);
*VolList = RtlAllocateHeap(RtlProcessHeap(), 0, *VolListSize);
if (!*VolList) {
return FALSE;
}
(*VolList)->NumberOfVolumeDescriptors = NumberOfMembers;
for (i = 0; i < NumberOfMembers; i++) {
status = NtDeviceIoControlFile(MemberVolumes[i], 0, NULL, NULL,
&ioStatus, FT_QUERY_VOLUME_DESCRIPTOR,
NULL, 0, &volDesc,
sizeof(FT_VOLUME_DESCRIPTOR));
if (!NT_SUCCESS(status)) {
RtlFreeHeap(RtlProcessHeap(), 0, *VolList);
break;
}
(*VolList)->VolumeDescriptor[i] = volDesc.VolumeDescriptor;
}
return status;
}
NTSTATUS
DiskCreateStripe(
IN BOOLEAN StripeWithParity,
IN HANDLE* MemberVolumes,
IN ULONG NumberOfMembers
)
/*++
Routine Description:
This routine takes the given array of volumes and creates one volume
which is a stripe of the given volumes.
Arguments:
StripeWithParity - Supplies whether or not to create a stripe with
parity.
MemberVolumes - Supplies the individual members of the stripe.
NumberOfMembers - Supplies the number of members in the stripe.
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
ULONG volListSize;
PFT_VOLUME_DESCRIPTOR_LIST volList;
status = CreateVolumeList(MemberVolumes, NumberOfMembers, &volList,
&volListSize);
if (!NT_SUCCESS(status)) {
return status;
}
status = NtDeviceIoControlFile(MemberVolumes[0], 0, NULL, NULL, &ioStatus,
StripeWithParity ? FT_CREATE_STRIPE_WITH_PARITY :
FT_CREATE_STRIPE,
volList, volListSize, NULL, 0);
RtlFreeHeap(RtlProcessHeap(), 0, volList);
return status;
}
NTSTATUS
DiskCreateMirror(
IN HANDLE SourceVolume,
IN HANDLE ShadowVolume
)
/*++
Routine Description:
This routine takes two volumes and creates one mirror volume.
Arguments:
SourceVolume - Supplies the source volume.
ShadowVolume - Supplies the shadow volume.
Return Value:
NTSTATUS
--*/
{
HANDLE volumes[2];
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
ULONG volListSize;
PFT_VOLUME_DESCRIPTOR_LIST volList;
volumes[0] = SourceVolume;
volumes[1] = ShadowVolume;
status = CreateVolumeList(volumes, 2, &volList, &volListSize);
if (!NT_SUCCESS(status)) {
return status;
}
status = NtDeviceIoControlFile(SourceVolume, 0, NULL, NULL, &ioStatus,
FT_CREATE_MIRROR,
volList, volListSize, NULL, 0);
RtlFreeHeap(RtlProcessHeap(), 0, volList);
return status;
}
NTSTATUS
DiskCreateVolumeSet(
IN HANDLE* MemberVolumes,
IN ULONG NumberOfMembers
)
/*++
Routine Description:
This routine takes the given array of volumes and creates one volume
which is a volume set of the given volumes.
Arguments:
MemberVolumes - Supplies the individual members of the volume set.
NumberOfMembers - Supplies the number of members in the volume set.
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
ULONG volListSize;
PFT_VOLUME_DESCRIPTOR_LIST volList;
status = CreateVolumeList(MemberVolumes, NumberOfMembers, &volList,
&volListSize);
if (!NT_SUCCESS(status)) {
return status;
}
status = NtDeviceIoControlFile(MemberVolumes[0], 0, NULL, NULL, &ioStatus,
FT_CREATE_VOLUME_SET,
volList, volListSize, NULL, 0);
RtlFreeHeap(RtlProcessHeap(), 0, volList);
return status;
}