1/* -------------------------------------------------------------------------- *
2 *
3 *   Copyright 2011 Shao Miller - All Rights Reserved
4 *
5 *   This program is free software; you can redistribute it and/or modify
6 *   it under the terms of the GNU General Public License as published by
7 *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 *   Boston MA 02111-1307, USA; either version 2 of the License, or
9 *   (at your option) any later version; incorporated herein by reference.
10 *
11 * ------------------------------------------------------------------------- */
12
13/****
14 * ntfstest.c
15 *
16 * (C) Shao Miller, 2011
17 *
18 * Tests ntfssect.c functions
19 *
20 * With special thanks to Mark Roddy for his article:
21 *   http://www.wd-3.com/archive/luserland.htm
22 */
23#include <windows.h>
24#include <stddef.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include "ntfssect.h"
30
31/*** Object types */
32
33/*** Function declarations */
34static void show_usage(void);
35static void show_last_err(void);
36static void show_err(DWORD);
37
38/*** Struct/union definitions */
39
40/*** Function definitions */
41
42/** Program entry-point */
43int main(int argc, char ** argv) {
44    int rc;
45    DWORD err;
46    S_NTFSSECT_VOLINFO vol_info;
47    HANDLE file;
48    LARGE_INTEGER vcn, lba;
49    S_NTFSSECT_EXTENT extent;
50    LONGLONG len;
51    BOOL ok;
52
53    if (argc != 2) {
54        rc = EXIT_FAILURE;
55        show_usage();
56        goto err_args;
57      }
58
59    /* Get volume info */
60    err = NtfsSectGetVolumeInfoFromFileName(argv[1], &vol_info);
61    if (err != ERROR_SUCCESS) {
62        show_err(err);
63        goto err_vol_info;
64      }
65    printf(
66        "Volume has %d bytes per sector, %d sectors per cluster\n",
67        vol_info.BytesPerSector,
68        vol_info.SectorsPerCluster
69      );
70
71    /* Open the file for reading */
72    file = CreateFile(
73        argv[1],
74        GENERIC_READ,
75        FILE_SHARE_READ,
76        NULL,
77        OPEN_EXISTING,
78        0,
79        NULL
80      );
81    if (file == INVALID_HANDLE_VALUE) {
82        rc = EXIT_FAILURE;
83        show_last_err();
84        goto err_file;
85      }
86
87    /* For each extent */
88    for (
89        vcn.QuadPart = 0;
90        NtfsSectGetFileVcnExtent(file, &vcn, &extent) == ERROR_SUCCESS;
91        vcn = extent.NextVcn
92      ) {
93        len = extent.NextVcn.QuadPart - extent.FirstVcn.QuadPart;
94        printf("Extent @ VCN #%lld,", extent.FirstVcn.QuadPart);
95        printf(" %lld clusters long:\n", len);
96        printf("  VCN #%lld -", extent.FirstVcn.QuadPart);
97        printf(" #%lld\n", extent.FirstVcn.QuadPart + len - 1);
98        printf("  LCN #%lld -", extent.FirstLcn.QuadPart);
99        printf(" #%lld\n", extent.FirstLcn.QuadPart + len - 1);
100        err = NtfsSectLcnToLba(
101            &vol_info,
102            &extent.FirstLcn,
103            &lba
104          );
105        if (err == ERROR_SUCCESS) {
106            printf("  LBA #%lld -", lba.QuadPart);
107            printf(
108                " #%lld\n",
109                lba.QuadPart + len * vol_info.SectorsPerCluster
110              );
111          }
112        continue;
113      }
114
115    rc = EXIT_SUCCESS;
116
117    CloseHandle(file);
118    err_file:
119
120    CloseHandle(vol_info.Handle);
121    err_vol_info:
122
123    err_args:
124
125    return rc;
126  }
127
128/** Display usage */
129static void show_usage(void) {
130    static const char usage_text[] = "\
131  File sector info . . . . . . . . . . . . . . . . . . . . Shao Miller, 2011\n\
132\n\
133  Usage: NTFSTEST.EXE <filename>\n\
134\n\
135  Attempts to dump cluster and sector info for <filename>.\n";
136
137    printf(usage_text);
138    return;
139  }
140
141static void show_last_err(void) {
142    show_err(GetLastError());
143    return;
144  }
145
146/** Display an error */
147static void show_err(DWORD err_code) {
148    void * buf;
149
150    FormatMessage(
151        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
152        NULL,
153        err_code,
154        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
155        (LPTSTR) &buf,
156        0,
157        NULL
158      );
159    fprintf(stderr, "Error: %s\n", buf);
160    LocalFree(buf);
161    return;
162  }
163
164