diff --git a/smbinfo.c b/smbinfo.c
index b1c129b..de9ebf6 100644
--- a/smbinfo.c
+++ b/smbinfo.c
@@ -66,6 +66,447 @@ usage(char *name)
 }
 
 static void
+win_to_timeval(uint64_t smb2_time, struct timeval *tv)
+{
+  tv->tv_usec = (smb2_time / 10) % 1000000;
+  tv->tv_sec  = (smb2_time - 116444736000000000) / 10000000;
+}
+
+struct bit_string {
+        unsigned int bit;
+        char *string;
+};
+
+struct bit_string directory_access_mask[] = {
+        { 0x00000001, "LIST_DIRECTORY" },
+        { 0x00000002, "ADD_FILE" },
+        { 0x00000004, "ADD_SUBDIRECTORY" },
+        { 0x00000008, "READ_EA" },
+        { 0x00000010, "WRITE_EA" },
+        { 0x00000020, "TRAVERSE" },
+        { 0x00000040, "DELETE_CHILD" },
+        { 0x00000080, "READ_ATTRIBUTES" },
+        { 0x00000100, "WRITE_ATTRIBUTES" },
+        { 0x00010000, "DELETE" },
+        { 0x00020000, "READ_CONTROL" },
+        { 0x00040000, "WRITE_DAC" },
+        { 0x00080000, "WRITE_OWNER" },
+        { 0x00100000, "SYNCHRONIZER" },
+        { 0x01000000, "ACCESS_SYSTEM_SECURITY" },
+        { 0x02000000, "MAXIMUM_ALLOWED" },
+        { 0x10000000, "GENERIC_ALL" },
+        { 0x20000000, "GENERIC_EXECUTE" },
+        { 0x40000000, "GENERIC_WRITE" },
+        { 0x80000000, "GENERIC_READ" },
+        { 0, NULL }
+};
+
+struct bit_string file_access_mask[] = {
+        { 0x00000001, "READ_DATA" },
+        { 0x00000002, "WRITE_DATA" },
+        { 0x00000004, "APPEND_DATA" },
+        { 0x00000008, "READ_EA" },
+        { 0x00000010, "WRITE_EA" },
+        { 0x00000020, "EXECUTE" },
+        { 0x00000040, "DELETE_CHILD" },
+        { 0x00000080, "READ_ATTRIBUTES" },
+        { 0x00000100, "WRITE_ATTRIBUTES" },
+        { 0x00010000, "DELETE" },
+        { 0x00020000, "READ_CONTROL" },
+        { 0x00040000, "WRITE_DAC" },
+        { 0x00080000, "WRITE_OWNER" },
+        { 0x00100000, "SYNCHRONIZER" },
+        { 0x01000000, "ACCESS_SYSTEM_SECURITY" },
+        { 0x02000000, "MAXIMUM_ALLOWED" },
+        { 0x10000000, "GENERIC_ALL" },
+        { 0x20000000, "GENERIC_EXECUTE" },
+        { 0x40000000, "GENERIC_WRITE" },
+        { 0x80000000, "GENERIC_READ" },
+        { 0, NULL }
+};
+
+static void
+print_bits(uint32_t mask, struct bit_string *bs)
+{
+        while (bs->string) {
+		if (mask & bs->bit)
+                    printf("%s ", bs->string);
+                bs++;
+        }
+}
+
+static void
+print_fileaccessinfo(uint8_t *sd, int type)
+{
+        uint32_t access_flags;
+
+        memcpy(&access_flags, &sd[0], 4);
+        access_flags = le32toh(access_flags);
+
+        if (type == S_IFDIR) {
+                printf("Directory access flags 0x%08x: ", access_flags);
+                print_bits(access_flags, directory_access_mask);
+        } else {
+                printf("File/Printer access flags 0x%08x: ", access_flags);
+                print_bits(access_flags, file_access_mask);
+        }
+        printf("\n");
+}
+
+static void
+fileaccessinfo(int f)
+{
+        struct smb_query_info *qi;
+	struct stat st;
+
+	fstat(f, &st);
+
+        qi = malloc(sizeof(struct smb_query_info) + 4);
+	memset(qi, 0, sizeof(qi) + 4);
+        qi->info_type = 0x01;
+        qi->file_info_class = 8;
+        qi->additional_information = 0;
+        qi->input_buffer_length = 4;
+
+        if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) {
+                fprintf(stderr, "ioctl failed with %s\n", strerror(errno));
+                exit(1);
+        }
+
+        print_fileaccessinfo((uint8_t *)(&qi[1]), st.st_mode & S_IFMT);
+	free(qi);
+}
+
+static void
+print_filealigninfo(uint8_t *sd)
+{
+        uint32_t mask;
+
+        memcpy(&mask, &sd[0], 4);
+        mask = le32toh(mask);
+
+        printf("File alignment: ");
+        if (mask == 0)
+                printf("BYTE_ALIGNMENT");
+        else if (mask == 1)
+                printf("WORD_ALIGNMENT");
+        else if (mask == 3)
+                printf("LONG_ALIGNMENT");
+        else if (mask == 7)
+                printf("QUAD_ALIGNMENT");
+        else if (mask == 15)
+                printf("OCTA_ALIGNMENT");
+        else if (mask == 31)
+                printf("32_bit_ALIGNMENT");
+        else if (mask == 63)
+                printf("64_bit_ALIGNMENT");
+        else if (mask == 127)
+                printf("128_bit_ALIGNMENT");
+        else if (mask == 255)
+                printf("254_bit_ALIGNMENT");
+        else if (mask == 511)
+                printf("512_bit_ALIGNMENT");
+
+        printf("\n");
+}
+
+static void
+filealigninfo(int f)
+{
+        struct smb_query_info *qi;
+
+        qi = malloc(sizeof(struct smb_query_info) + 4);
+	memset(qi, 0, sizeof(qi) + 4);
+        qi->info_type = 0x01;
+        qi->file_info_class = 17;
+        qi->additional_information = 0;
+        qi->input_buffer_length = 4;
+
+        if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) {
+                fprintf(stderr, "ioctl failed with %s\n", strerror(errno));
+                exit(1);
+        }
+
+        print_filealigninfo((uint8_t *)(&qi[1]));
+	free(qi);
+}
+
+struct bit_string file_attributes_mask[] = {
+        { 0x00000001, "READ_ONLY" },
+        { 0x00000002, "HIDDEN" },
+        { 0x00000004, "SYSTEM" },
+        { 0x00000010, "DIRECTORY" },
+        { 0x00000020, "ARCHIVE" },
+        { 0x00000080, "NORMAL" },
+        { 0x00000100, "TEMPORARY" },
+        { 0x00000200, "SPARSE_FILE" },
+        { 0x00000400, "REPARSE_POINT" },
+        { 0x00000800, "COMPRESSED" },
+        { 0x00001000, "OFFLINE" },
+        { 0x00002000, "NOT_CONTENT_INDEXED" },
+        { 0x00004000, "ENCRYPTED" },
+        { 0x00008000, "INTEGRITY_STREAM" },
+        { 0x00020000, "NO_SCRUB_DATA" },
+        { 0, NULL }
+};
+
+static void
+print_filebasicinfo(uint8_t *sd)
+{
+        struct timeval tv;
+        uint64_t u64;
+        uint32_t u32;
+
+        memcpy(&u64, &sd[0], 8);
+        win_to_timeval(le64toh(u64), &tv);
+        printf("Creation Time %s", ctime(&tv.tv_sec));
+
+        memcpy(&u64, &sd[8], 8);
+        win_to_timeval(le64toh(u64), &tv);
+        printf("Last Access Time %s", ctime(&tv.tv_sec));
+
+        memcpy(&u64, &sd[16], 8);
+        win_to_timeval(le64toh(u64), &tv);
+        printf("Last Write Time %s", ctime(&tv.tv_sec));
+
+        memcpy(&u64, &sd[24], 8);
+        win_to_timeval(le64toh(u64), &tv);
+        printf("Last Change Time %s", ctime(&tv.tv_sec));
+
+        memcpy(&u32, &sd[32], 4);
+        u32 = le32toh(u32);
+	printf("File Attributes 0x%08x: ", u32);
+	print_bits(u32, file_attributes_mask);
+        printf("\n");
+}
+
+static void
+filebasicinfo(int f)
+{
+        struct smb_query_info *qi;
+
+        qi = malloc(sizeof(struct smb_query_info) + 40);
+	memset(qi, 0, sizeof(qi) + 40);
+        qi->info_type = 0x01;
+        qi->file_info_class = 4;
+        qi->additional_information = 0;
+        qi->input_buffer_length = 40;
+
+        if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) {
+                fprintf(stderr, "ioctl failed with %s\n", strerror(errno));
+                exit(1);
+        }
+
+        print_filebasicinfo((uint8_t *)(&qi[1]));
+	free(qi);
+}
+
+static void
+print_filestandardinfo(uint8_t *sd)
+{
+        uint64_t u64;
+        uint32_t u32;
+
+        memcpy(&u64, &sd[0], 8);
+        printf("Allocation Size %" PRIu64 "\n", le64toh(u64));
+	
+        memcpy(&u64, &sd[8], 8);
+        printf("End Of File %" PRIu64 "\n", le64toh(u64));
+	
+        memcpy(&u32, &sd[16], 4);
+        printf("Number Of Links %" PRIu32 "\n", le32toh(u32));
+
+	printf("Delete Pending %d\n", sd[20]);
+	printf("Delete Directory %d\n", sd[21]);
+}
+
+static void
+filestandardinfo(int f)
+{
+        struct smb_query_info *qi;
+
+        qi = malloc(sizeof(struct smb_query_info) + 24);
+	memset(qi, 0, sizeof(qi) + 24);
+        qi->info_type = 0x01;
+        qi->file_info_class = 5;
+        qi->additional_information = 0;
+        qi->input_buffer_length = 24;
+
+        if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) {
+                fprintf(stderr, "ioctl failed with %s\n", strerror(errno));
+                exit(1);
+        }
+
+        print_filestandardinfo((uint8_t *)(&qi[1]));
+	free(qi);
+}
+
+static void
+print_fileinternalinfo(uint8_t *sd)
+{
+        uint64_t u64;
+
+        memcpy(&u64, &sd[0], 8);
+        printf("Index Number %" PRIu64 "\n", le64toh(u64));
+}
+
+static void
+fileinternalinfo(int f)
+{
+        struct smb_query_info *qi;
+
+        qi = malloc(sizeof(struct smb_query_info) + 8);
+	memset(qi, 0, sizeof(qi) + 8);
+        qi->info_type = 0x01;
+        qi->file_info_class = 6;
+        qi->additional_information = 0;
+        qi->input_buffer_length = 8;
+
+        if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) {
+                fprintf(stderr, "ioctl failed with %s\n", strerror(errno));
+                exit(1);
+        }
+
+        print_fileinternalinfo((uint8_t *)(&qi[1]));
+	free(qi);
+}
+
+struct bit_string file_mode_mask[] = {
+        { 0x00000002, "WRITE_THROUGH" },
+        { 0x00000004, "SEQUENTIAL_ONLY" },
+        { 0x00000008, "NO_INTERMEDIATE_BUFFERING" },
+        { 0x00000010, "SYNCHRONOUS_IO_ALERT" },
+        { 0x00000020, "SYNCHRONOUS_IO_NONALERT" },
+        { 0x00001000, "DELETE_ON_CLOSE" },
+        { 0, NULL }
+};
+
+static void
+print_filemodeinfo(uint8_t *sd)
+{
+        uint32_t u32;
+
+        memcpy(&u32, &sd[32], 4);
+        u32 = le32toh(u32);
+	printf("Mode 0x%08x: ", u32);
+	print_bits(u32, file_mode_mask);
+        printf("\n");
+}
+
+static void
+filemodeinfo(int f)
+{
+        struct smb_query_info *qi;
+
+        qi = malloc(sizeof(struct smb_query_info) + 4);
+	memset(qi, 0, sizeof(qi) + 4);
+        qi->info_type = 0x01;
+        qi->file_info_class = 16;
+        qi->additional_information = 0;
+        qi->input_buffer_length = 4;
+
+        if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) {
+                fprintf(stderr, "ioctl failed with %s\n", strerror(errno));
+                exit(1);
+        }
+
+        print_filemodeinfo((uint8_t *)(&qi[1]));
+	free(qi);
+}
+
+static void
+print_filepositioninfo(uint8_t *sd)
+{
+        uint64_t u64;
+
+        memcpy(&u64, &sd[0], 8);
+        printf("Current Byte Offset %" PRIu64 "\n", le64toh(u64));
+}
+
+static void
+filepositioninfo(int f)
+{
+        struct smb_query_info *qi;
+
+        qi = malloc(sizeof(struct smb_query_info) + 8);
+	memset(qi, 0, sizeof(qi) + 8);
+        qi->info_type = 0x01;
+        qi->file_info_class = 14;
+        qi->additional_information = 0;
+        qi->input_buffer_length = 8;
+
+        if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) {
+                fprintf(stderr, "ioctl failed with %s\n", strerror(errno));
+                exit(1);
+        }
+
+        print_filepositioninfo((uint8_t *)(&qi[1]));
+	free(qi);
+}
+
+static void
+print_fileeainfo(uint8_t *sd)
+{
+        uint32_t u32;
+
+        memcpy(&u32, &sd[0], 4);
+        printf("Ea Size %" PRIu32 "\n", le32toh(u32));
+}
+
+static void
+fileeainfo(int f)
+{
+        struct smb_query_info *qi;
+
+        qi = malloc(sizeof(struct smb_query_info) + 4);
+	memset(qi, 0, sizeof(qi) + 4);
+        qi->info_type = 0x01;
+        qi->file_info_class = 7;
+        qi->additional_information = 0;
+        qi->input_buffer_length = 4;
+
+        if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) {
+                fprintf(stderr, "ioctl failed with %s\n", strerror(errno));
+                exit(1);
+        }
+
+        print_fileeainfo((uint8_t *)(&qi[1]));
+	free(qi);
+}
+
+static void
+fileallinfo(int f)
+{
+        struct smb_query_info *qi;
+	struct stat st;
+
+	fstat(f, &st);
+
+        qi = malloc(sizeof(struct smb_query_info) + INPUT_BUFFER_LENGTH);
+	memset(qi, 0, sizeof(qi) + INPUT_BUFFER_LENGTH);
+        qi->info_type = 0x01;
+        qi->file_info_class = 18;
+        qi->additional_information = 0;
+        qi->input_buffer_length = INPUT_BUFFER_LENGTH;
+
+        if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) {
+                fprintf(stderr, "ioctl failed with %s\n", strerror(errno));
+                exit(1);
+        }
+
+        print_filebasicinfo((uint8_t *)(&qi[1]));
+        print_filestandardinfo((uint8_t *)(&qi[1]) + 40);
+        print_fileinternalinfo((uint8_t *)(&qi[1]) + 64);
+        print_fileeainfo((uint8_t *)(&qi[1]) + 72);
+        print_fileaccessinfo((uint8_t *)(&qi[1]) + 76, st.st_mode & S_IFMT);
+        print_filepositioninfo((uint8_t *)(&qi[1]) + 80);
+        print_filemodeinfo((uint8_t *)(&qi[1]) + 88);
+        print_filealigninfo((uint8_t *)(&qi[1]) + 92);
+        // SMB2 servers like Win16 does not seem to return name info
+	free(qi);
+}
+
+static void
 print_sid(unsigned char *sd)
 {
         int i;
@@ -152,10 +593,13 @@ print_sd(uint8_t *sd)
         }
 }
 
-void secdesc(int f) {
+static void
+secdesc(int f)
+{
         struct smb_query_info *qi;
 
         qi = malloc(sizeof(struct smb_query_info) + INPUT_BUFFER_LENGTH);
+	memset(qi, 0, sizeof(qi) + INPUT_BUFFER_LENGTH);
         qi->info_type = 0x03;
         qi->file_info_class = 0;
         qi->additional_information = 0x00000007; /* Owner, Group, Dacl */
@@ -167,13 +611,7 @@ void secdesc(int f) {
         }
 
         print_sd((uint8_t *)(&qi[1]));
-}
-
-void
-win_to_timeval(uint64_t smb2_time, struct timeval *tv)
-{
-  tv->tv_usec = (smb2_time / 10) % 1000000;
-  tv->tv_sec  = (smb2_time - 116444736000000000) / 10000000;
+	free(qi);
 }
 
 static void
@@ -236,7 +674,9 @@ print_quota(unsigned char *sd)
         }
 }
 
-void quota(int f) {
+static void
+quota(int f)
+{
         struct smb_query_info *qi;
         char *buf;
         int i;
@@ -264,6 +704,7 @@ void quota(int f) {
         }
 
         print_quota((unsigned char *)(&qi[1]));
+	free(qi);
 }
 
 int main(int argc, char *argv[])
@@ -290,11 +731,29 @@ int main(int argc, char *argv[])
         }
 
 
-        if (!strcmp(argv[1], "secdesc")) {
+        if (!strcmp(argv[1], "fileaccessinfo"))
+                fileaccessinfo(f);
+        else if (!strcmp(argv[1], "filealigninfo"))
+                filealigninfo(f);
+        else if (!strcmp(argv[1], "fileallinfo"))
+                fileallinfo(f);
+        else if (!strcmp(argv[1], "filebasicinfo"))
+                filebasicinfo(f);
+        else if (!strcmp(argv[1], "fileeainfo"))
+                fileeainfo(f);
+        else if (!strcmp(argv[1], "fileinternalinfo"))
+                fileinternalinfo(f);
+        else if (!strcmp(argv[1], "filemodeinfo"))
+                filemodeinfo(f);
+        else if (!strcmp(argv[1], "filepositioninfo"))
+                filepositioninfo(f);
+        else if (!strcmp(argv[1], "filestandardinfo"))
+                filestandardinfo(f);
+        else if (!strcmp(argv[1], "secdesc"))
                 secdesc(f);
-        } else if (!strcmp(argv[1], "quota")) {
+        else if (!strcmp(argv[1], "quota"))
                 quota(f);
-        } else {
+        else {
                 fprintf(stderr, "Unknown command %s\n", argv[optind]);
                 exit(1);
         }
diff --git a/smbinfo.rst b/smbinfo.rst
index e37c709..2119f93 100644
--- a/smbinfo.rst
+++ b/smbinfo.rst
@@ -39,14 +39,23 @@ OPTIONS
 COMMAND
 *******
 
-`secdesc`: Print the security descriptor in the form
-- Revision
-- Control
-- Owner SID
-- Group SID
-- ACL
-- File types
-- File flags
+`fileaccessinfo`: Prints the FileAccessInformation class
+
+`filealigninfo`: Prints the FileAlignmentInformation class
+
+`fileallinfo`: Prints the FileAllInformation class
+
+`filebasicinfo`: Prints the FileBasicInformation class
+
+`fileeainfo`: Prints the FileEaInformation class
+
+`fileinternalinfo`: Prints the FileInternalInformation class
+
+`filemodeinfo`: Prints the FileModeInformation class
+
+`filepositioninfo`: Prints the FilePositionInformation class
+
+`filestandardinfo`: Prints the FileStandardInformation class
 
 `quota`: Print the quota for the volume in the form
 - SID Length
@@ -56,6 +65,15 @@ COMMAND
 - Quota Limit
 - SID
 
+`secdesc`: Print the security descriptor in the form
+- Revision
+- Control
+- Owner SID
+- Group SID
+- ACL
+- File types
+- File flags
+
 *****
 NOTES
 *****
