| |
| |
| |
| |
| |
| |
| #include <ntapi/ntapi.h> |
| #include <ntapi/nt_file.h> |
| #include <ntapi/nt_fsctl.h> |
| #include <ntapi/nt_mount.h> |
| #include <ntapi/nt_istat.h> |
| #include "ntapi_impl.h" |
| |
| int32_t __stdcall __ntapi_tt_istat( |
| __in void * hfile, |
| __out nt_istat * istat, |
| __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; |
| wchar16_t * wch_cap; |
| uint32_t hash; |
| uint32_t written; |
| |
| |
| if (infolen < sizeof(*istat)) |
| return NT_STATUS_INFO_LENGTH_MISMATCH; |
| |
| |
| __ntapi->tt_aligned_block_memset( |
| istat,0,sizeof(*istat)); |
| |
| istat->hfile = hfile; |
| istat->dev_name_maxlen = (uint16_t)infolen - sizeof(*istat); |
| |
| |
| if (buffer_size >= 65536) |
| buffer_size = 65535; |
| |
| |
| if (!(flags & NT_ISTAT_DEV_NAME_ONLY)) |
| if ((status = __ntapi->zw_query_information_file( |
| hfile, |
| &iosb, |
| &istat->fii, |
| sizeof(istat->fii), |
| NT_FILE_INTERNAL_INFORMATION))) |
| return status; |
| |
| |
| if (!(flags & NT_ISTAT_DEV_NAME_ONLY)) |
| if ((status = __ntapi->zw_query_information_file( |
| hfile, |
| &iosb, |
| &istat->ftagi, |
| sizeof(istat->ftagi), |
| NT_FILE_ATTRIBUTE_TAG_INFORMATION))) |
| return status; |
| |
| |
| 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) |
| && (wch[8]=='M') |
| && (wch[9]=='u') |
| && (wch[10]=='p') |
| && (wch[11]=='\\')) { |
| hash = __DEVICE_MUP_PREFIX_HASH; |
| istat->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; |
| } |
| |
| wch_cap = sdev->buffer + (sdev->strlen / sizeof(wchar16_t)); |
| |
| for (; wch<wch_cap && *wch!='\\'; ) |
| wch++; |
| |
| istat->obj_name_strlen = sdev->strlen; |
| istat->obj_name_maxlen = istat->dev_name_maxlen; |
| istat->dev_name_strlen = sizeof(uint16_t) * (uint16_t)(wch - sdev->buffer); |
| istat->dev_name_hash = __ntapi->tt_buffer_crc32( |
| hash,wch_mark, |
| sizeof(wchar16_t) * (wch - wch_mark)); |
| |
| if (!(flags & NT_ISTAT_DEV_NAME_COPY)) |
| return NT_STATUS_SUCCESS; |
| else if (istat->dev_name_maxlen < istat->dev_name_strlen) |
| return NT_STATUS_BUFFER_TOO_SMALL; |
| |
| __ntapi->tt_memcpy_utf16( |
| istat->dev_name, |
| sdev->buffer, |
| istat->dev_name_strlen); |
| |
| return status; |
| } |