Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

370 lines
8.7 KiB

#include <pch.cxx>
#if i386
//
// Temporarily disable optimizations until cl386 Drop 077 is fixed.
//
#pragma optimize("",off)
#endif
#define _NTAPI_ULIB_
#define _IFSUTIL_MEMBER_
#include "ulib.hxx"
#include "ifsutil.hxx"
#include "supera.hxx"
#include "message.hxx"
#include "rtmsg.h"
#include "ifssys.hxx"
#define MaxLabelLength 1024
DEFINE_EXPORTED_CONSTRUCTOR( SUPERAREA, SECRUN, IFSUTIL_EXPORT );
IFSUTIL_EXPORT
SUPERAREA::~SUPERAREA(
)
/*++
Routine Description:
Destructor for SUPERAREA.
Arguments:
None.
Return Value:
None.
--*/
{
Destroy();
}
VOID
SUPERAREA::Construct(
)
/*++
Routine Description:
Constructor for SUPERAREA.
Arguments:
None.
Return Value:
None.
--*/
{
_drive = NULL;
}
VOID
SUPERAREA::Destroy(
)
/*++
Routine Description:
This routine returns the object to its initial state freeing up
any memory in the process.
Arguments:
None.
Return Value:
None.
--*/
{
_drive = NULL;
}
IFSUTIL_EXPORT
BOOLEAN
SUPERAREA::Initialize(
IN OUT PMEM Mem,
IN OUT PLOG_IO_DP_DRIVE Drive,
IN SECTORCOUNT NumberOfSectors,
IN OUT PMESSAGE Message
)
/*++
Routine Description:
This routine initializes the SUPERAREA for the given drive.
Arguments:
Mem - Supplies necessary memory for the underlying sector run.
Drive - Supplies the drive where the superarea resides.
NumberOfSectors - Supplies the number of sectors in the superarea.
Message - Supplies an outlet for messages.
Return Value:
FALSE - Failure.
TRUE - Success.
--*/
{
Destroy();
DebugAssert(Mem);
DebugAssert(Drive);
DebugAssert(NumberOfSectors);
if (!SECRUN::Initialize(Mem, Drive, 0, NumberOfSectors)) {
Message->Set(MSG_FMT_NO_MEMORY);
Message->Display("");
return FALSE;
}
_drive = Drive;
return TRUE;
}
IFSUTIL_EXPORT
VOLID
SUPERAREA::ComputeVolId(
IN VOLID Seed
)
/*++
Routine Description:
This routine computes a new and unique volume identifier.
Arguments:
None.
Return Value:
A unique volume id.
--*/
{
VOLID volid;
PUCHAR p;
INT i;
LARGE_INTEGER NtfsTime;
if (Seed) {
volid = Seed;
} else {
volid = 0;
}
do {
if (!volid) {
IFS_SYSTEM::QueryNtfsTime( &NtfsTime );
if (NtfsTime.LowPart) {
volid = (VOLID) NtfsTime.LowPart;
} else {
volid = (VOLID) NtfsTime.HighPart;
}
if (volid == 0) { // This should never happen.
volid = 0x11111111;
}
}
p = (PUCHAR) &volid;
for (i = 0; i < sizeof(VOLID); i++) {
volid += *p++;
volid = (volid >> 2) + (volid << 30);
}
} while (!volid);
return volid;
}
NTSTATUS
SUPERAREA::FormatNotification(
IN PWSTRING Label,
OUT PFILE_FS_SIZE_INFORMATION FsSizeInfo,
OUT PFILE_FS_VOLUME_INFORMATION FsVolInfo
)
/*++
Routine Description:
This routine sets the volume label which serves as a notification
to the rest of the system that format has completed and the volume
is avaiable for use again.
Arguments:
Label - Supplies the volume label. If NULL, the current volume
label will be used.
FsSizeInfo - Retrieves the File System Size Information
FsVolInfo - Retrieves the File System Volume Information
Return Value:
NT status
--*/
{
//
// Close the current drive handle first
//
_drive->CloseDriveHandle();
return SUPERAREA::GenerateLabelNotification(_drive->GetNtDriveName(),
Label,
FsSizeInfo,
FsVolInfo);
}
NTSTATUS
SUPERAREA::GenerateLabelNotification(
IN PCWSTRING NtDriveName,
IN PWSTRING Label,
OUT PFILE_FS_SIZE_INFORMATION FsSizeInfo,
OUT PFILE_FS_VOLUME_INFORMATION FsVolInfo
)
/*++
Routine Description:
This routine sets the volume label which serves as a notification
to the rest of the system that the volume has changed.
Arguments:
NtDriveName - Supplies the name of the volume.
Label - Supplies the volume label. If NULL, the current volume
label will be used.
FsSizeInfo - Retrieves the File System Size Information
FsVolInfo - Retrieves the File System Volume Information
Return Value:
NT status
--*/
{
CONST vollen = sizeof(FILE_FS_VOLUME_INFORMATION) +
MaxLabelLength;
CONST lablen = sizeof(FILE_FS_LABEL_INFORMATION) +
MaxLabelLength;
PFILE_FS_VOLUME_INFORMATION volinfo;
PFILE_FS_LABEL_INFORMATION labinfo;
STR vol_info_buf[vollen];
STR lab_info_buf[lablen];
IO_STATUS_BLOCK status_block;
NTSTATUS status;
PCWSTRING ntDriveName;
UNICODE_STRING string;
OBJECT_ATTRIBUTES oa;
HANDLE handle;
ntDriveName = NtDriveName;
string.Length = (USHORT) ntDriveName->QueryChCount() * sizeof(WCHAR);
string.MaximumLength = string.Length;
string.Buffer = (PWSTR)ntDriveName->GetWSTR();
InitializeObjectAttributes( &oa,
&string,
OBJ_CASE_INSENSITIVE,
0,
0 );
status = NtOpenFile(&handle,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&oa, &status_block,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_ALERT | FILE_WRITE_THROUGH);
if (!NT_SUCCESS(status)) {
DebugPrintTrace(("IFSUTIL: Unable to open handle with status %x\n", status));
return status;
}
// status is good at this point
if (FsVolInfo) {
status = NtQueryVolumeInformationFile(handle,
&status_block,
FsVolInfo,
sizeof(*FsVolInfo),
FileFsVolumeInformation);
if (!NT_SUCCESS(status)) {
DebugPrintTrace(("IFSUTIL: Unable to query file system volume information with status %x\n", status));
}
}
if (NT_SUCCESS(status) &&
FsSizeInfo) {
status = NtQueryVolumeInformationFile(handle,
&status_block,
FsSizeInfo,
sizeof(*FsSizeInfo),
FileFsSizeInformation);
if (!NT_SUCCESS(status)) {
DebugPrintTrace(("IFSUTIL: Unable to query file system size information with status %x\n", status));
}
}
if (NT_SUCCESS(status) &&
Label == NULL) {
volinfo = (PFILE_FS_VOLUME_INFORMATION) vol_info_buf;
status = NtQueryVolumeInformationFile(handle,
&status_block,
volinfo,
vollen,
FileFsVolumeInformation);
if (!NT_SUCCESS(status)) {
DebugPrintTrace(("IFSUTIL: Unable to query volume label with status %x\n", status));
}
}
if (NT_SUCCESS(status)) {
labinfo = (PFILE_FS_LABEL_INFORMATION)lab_info_buf;
if (Label == NULL) {
labinfo->VolumeLabelLength = volinfo->VolumeLabelLength;
memcpy(labinfo->VolumeLabel, volinfo->VolumeLabel, labinfo->VolumeLabelLength);
} else {
labinfo->VolumeLabelLength = Label->QueryChCount()*sizeof(WCHAR);
memcpy(labinfo->VolumeLabel, Label->GetWSTR(), labinfo->VolumeLabelLength);
}
status = NtSetVolumeInformationFile(handle,
&status_block,
labinfo,
lablen,
FileFsLabelInformation);
if (!NT_SUCCESS(status)) {
DebugPrintTrace(("IFSUTIL: Unable to set volume label with status %x\n", status));
}
}
NtClose(handle);
return status;
}