| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| int32_t __stdcall __ntapi_tt_statfs( |
| __in void * hfile, |
| __out nt_statfs * statfs, |
| __in uint32_t infolen, |
| __out uintptr_t * buffer, |
| __in uint32_t buffer_size, |
| __in uint32_t flags) |
| { |
| int32_t status; |
| nt_iosb iosb; |
| nt_unicode_string * sdev; |
| wchar16_t * wch; |
| wchar16_t * wch_mark; |
| uint32_t offset; |
| uint32_t hash; |
| void * mnt_points_buffer; |
| nt_mount_points * mnt_points; |
| nt_fsai * fsai; |
| nt_fsfsi * fsfsi; |
| uint32_t * fsid; |
| uint64_t * pguid; |
| uint32_t written; |
| |
| |
| if (infolen < sizeof(*statfs)) |
| return NT_STATUS_INFO_LENGTH_MISMATCH; |
| |
| |
| __ntapi->tt_aligned_block_memset( |
| statfs,0,sizeof(*statfs)); |
| |
| statfs->hfile = hfile; |
| statfs->dev_name_maxlen = (uint16_t)infolen - sizeof(*statfs); |
| |
| |
| if (buffer_size >= 65536) |
| buffer_size = 65535; |
| |
| |
| if ((status = __ntapi->zw_query_volume_information_file( |
| hfile, |
| &iosb, |
| buffer, |
| buffer_size, |
| NT_FILE_FS_ATTRIBUTE_INFORMATION))) |
| return status; |
| |
| fsai = (nt_fsai *)buffer; |
| statfs->f_type = 0; |
| statfs->f_namelen = fsai->maximum_component_name_length; |
| |
| statfs->nt_fstype_hash = __ntapi->tt_buffer_crc32( |
| 0,&fsai->file_system_name, |
| fsai->file_system_name_length); |
| |
| |
| switch (statfs->nt_fstype_hash) { |
| case NT_FS_TYPE_HPFS_NAME_HASH: |
| case NT_FS_TYPE_NTFS_NAME_HASH: |
| case NT_FS_TYPE_SMB_NAME_HASH: |
| case NT_FS_TYPE_UDF_NAME_HASH: |
| statfs->f_files = 0xFFFFFFFF; |
| break; |
| |
| case NT_FS_TYPE_FAT16_NAME_HASH: |
| statfs->f_files = 0x10000; |
| break; |
| |
| case NT_FS_TYPE_FAT32_NAME_HASH: |
| statfs->f_files = 0x400000; |
| break; |
| |
| default: |
| |
| statfs->f_files = (uint64_t)(-1); |
| break; |
| } |
| |
| |
| |
| statfs->f_ffree = (size_t)statfs->f_files >> 4 << 3; |
| |
| |
| if ((status = __ntapi->zw_query_volume_information_file( |
| hfile, |
| &iosb, |
| buffer, |
| buffer_size, |
| NT_FILE_FS_FULL_SIZE_INFORMATION))) |
| return status; |
| |
| fsfsi = (nt_fsfsi *)buffer; |
| statfs->f_blocks = fsfsi->total_allocation_units.quad; |
| statfs->f_bfree = fsfsi->actual_available_allocation_units.quad; |
| statfs->f_bavail = fsfsi->caller_available_allocation_units.quad; |
| statfs->f_bsize = fsfsi->sectors_per_allocation_unit * fsfsi->bytes_per_sector; |
| statfs->f_frsize = fsfsi->bytes_per_sector; |
| |
| |
| if ((status = __ntapi->zw_query_object( |
| hfile, |
| NT_OBJECT_NAME_INFORMATION, |
| buffer, |
| buffer_size, |
| &written))) |
| return status; |
| |
| sdev = (nt_unicode_string *)buffer; |
| wch = sdev->buffer; |
| |
| if (sdev->strlen < __DEVICE_PATH_PREFIX_LEN) |
| return NT_STATUS_NOT_SUPPORTED; |
| |
| if ((wch[0] != '\\') |
| || (wch[1] != 'D') |
| || (wch[2] != 'e') |
| || (wch[3] != 'v') |
| || (wch[4] != 'i') |
| || (wch[5] != 'c') |
| || (wch[6] != 'e') |
| || (wch[7] != '\\')) |
| return NT_STATUS_NOT_SUPPORTED; |
| |
| if (sdev->strlen < __DEVICE_MUP_PREFIX_LEN) |
| return NT_STATUS_INVALID_HANDLE; |
| |
| if ((wch[8]=='M') |
| && (wch[9]=='u') |
| && (wch[10]=='p') |
| && (wch[11]=='\\')) { |
| statfs->nt_drive_letter = 0; |
| hash = __DEVICE_MUP_PREFIX_HASH; |
| flags &= ~NT_STATFS_VOLUME_GUID; |
| statfs->flags |= NT_STATFS_MUP_DEVICE; |
| |
| wch_mark = &wch[12]; |
| wch = wch_mark; |
| |
| for (; *wch!='\\'; ) |
| wch++; |
| wch++; |
| } else { |
| wch_mark = &wch[8]; |
| wch = wch_mark; |
| hash = __DEVICE_PATH_PREFIX_HASH; |
| } |
| |
| for (; *wch!='\\'; ) |
| wch++; |
| |
| statfs->obj_name_strlen = sdev->strlen; |
| statfs->obj_name_maxlen = statfs->dev_name_maxlen; |
| statfs->dev_name_strlen = sizeof(uint16_t) * (uint16_t)(wch - sdev->buffer); |
| statfs->dev_name_hash = __ntapi->tt_buffer_crc32( |
| hash,wch_mark, |
| sizeof(wchar16_t) * (wch - wch_mark)); |
| |
| |
| if (!(flags & NT_STATFS_DEV_NAME_COPY)) |
| (void)0; |
| else if (statfs->dev_name_maxlen < sdev->strlen) |
| return NT_STATUS_BUFFER_TOO_SMALL; |
| else |
| __ntapi->tt_memcpy_utf16( |
| statfs->dev_name, |
| sdev->buffer, |
| sdev->strlen); |
| |
| |
| |
| fsid = (uint32_t *)&(statfs->f_fsid); |
| fsid[0] = statfs->dev_name_hash; |
| fsid[1] = 0; |
| |
| |
| statfs->f_flags = 0; |
| statfs->nt_attr = 0; |
| statfs->nt_padding = 0; |
| |
| if (!(flags & NT_STATFS_VOLUME_GUID)) { |
| statfs->nt_drive_letter = 0; |
| pguid = (uint64_t *)&(statfs->nt_volume_guid); |
| pguid[0] = 0; |
| pguid[1] = 0; |
| return NT_STATUS_SUCCESS; |
| } |
| |
| |
| wch = (wchar16_t *)sdev->buffer; |
| mnt_points_buffer = (void *)((uintptr_t)wch + statfs->dev_name_strlen); |
| |
| *(--wch) = statfs->dev_name_strlen; |
| offset = sizeof(nt_unicode_string) + statfs->dev_name_strlen; |
| |
| if ((status = __ntapi->tt_get_dos_drive_mount_points( |
| 0,0, |
| (nt_mount_dev_name *)wch, |
| mnt_points_buffer, |
| buffer_size - offset))) |
| return status; |
| |
| offset = ((nt_mount_point_param *)mnt_points_buffer)->mount_points_offset; |
| mnt_points = (nt_mount_points *)((uintptr_t)mnt_points_buffer + offset); |
| |
| status = __ntapi->tt_dev_mount_points_to_statfs( |
| mnt_points,statfs); |
| |
| return status; |
| } |