1 /*
2  * PROJECT:         ReactOS Tests
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * FILE:            tunneltest.c
5  * PURPOSE:         Usermode tunnel cache testing
6  * PROGRAMMERS:     Pierre Schweitzer (pierre@reactos.org)
7  * NOTES:           Based on indications from: http://support.microsoft.com/?kbid=172190
8  */
9 
10 #include <stdio.h>
11 #include <windef.h>
12 #include <winternl.h>
13 #include <winbase.h>
14 #define RTL_CONSTANT_STRING(s) { sizeof(s)-sizeof((s)[0]), sizeof(s), s }
15 
16 const UNICODE_STRING FatName = RTL_CONSTANT_STRING(L"FAT");
17 const UNICODE_STRING Fat32Name = RTL_CONSTANT_STRING(L"FAT32");
18 const UNICODE_STRING NtfsName = RTL_CONSTANT_STRING(L"NTFS");
19 
20 int wmain(int argc, WCHAR * argv[])
21 {
22     WCHAR TempPath[MAX_PATH + 1];
23     WCHAR CopyPath[MAX_PATH + 1];
24     WCHAR RootPath[] = {'A', ':', '\\', '\0'};
25     WCHAR FileSystemName[sizeof("FAT32")]; /* Max we should hold - fail otherwise, we don't care */
26     UNICODE_STRING FSName;
27     WCHAR File1[] = {'\\', 'f', 'i', 'l', 'e', '1', '\0'};
28     WCHAR File2[] = {'\\', 'f', 'i', 'l', 'e', '2', '\0'};
29     ULONG FilePos;
30     HANDLE hFile;
31     FILETIME FileTime, File1Time;
32 
33     /* Get temp path in which will work */
34     if (GetTempPathW(sizeof(TempPath) / sizeof(TempPath[0]), TempPath) == 0)
35     {
36         fprintf(stderr, "Failed to get temp path\n");
37         return GetLastError();
38     }
39 
40     /* Assume it's X:\ something */
41     RootPath[0] = TempPath[0];
42 
43     /* Get information about the volume */
44     if (GetVolumeInformationW(RootPath, NULL, 0, NULL, NULL, NULL, FileSystemName, sizeof(FileSystemName) / sizeof(FileSystemName[0])) == 0)
45     {
46         fprintf(stderr, "Failed to get volume info\n");
47         return GetLastError();
48     }
49 
50     /* Convert to string */
51     RtlInitUnicodeString(&FSName, FileSystemName);
52 
53     /* Bail out if that's not FAT or NTFS */
54     if (RtlCompareUnicodeString(&FSName, &FatName, FALSE) != 0 &&
55         RtlCompareUnicodeString(&FSName, &Fat32Name, FALSE) != 0 &&
56         RtlCompareUnicodeString(&FSName, &NtfsName, FALSE) != 0)
57     {
58         fprintf(stderr, "!(FAT, FAT32, NTFS): \'%S\'\n", FSName.Buffer);
59         return 0;
60     }
61 
62     /* Ensure we can store complete path - no overrun */
63     FilePos = wcslen(TempPath);
64     if (FilePos > MAX_PATH - sizeof(File2) / sizeof(WCHAR))
65     {
66         fprintf(stderr, "Files won't fit\n");
67         return 0;
68     }
69 
70     /* Create first file */
71     wcscat(TempPath, File1);
72     hFile = CreateFileW(TempPath, 0, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
73     if (hFile == INVALID_HANDLE_VALUE)
74     {
75         fprintf(stderr, "Failed to create file1\n");
76         return GetLastError();
77     }
78 
79     /* Get its creation timestamp. It will be our reference */
80     /* Get it in FileTime because file1 will renamed to file */
81     if (GetFileTime(hFile, &FileTime, NULL, NULL) == FALSE)
82     {
83         fprintf(stderr, "Failed to read creation time\n");
84         CloseHandle(hFile);
85         return GetLastError();
86     }
87 
88     CloseHandle(hFile);
89 
90     /* Wait a least 10ms (resolution of FAT) */
91     /* XXX: Increased to 1s for ReactOS... */
92     Sleep(1000);
93 
94     /* Create second file */
95     /* Remove old file from buffer */
96     TempPath[FilePos - 1] = 0;
97     wcscat(TempPath, File2);
98     hFile = CreateFileW(TempPath, 0, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
99     if (hFile == INVALID_HANDLE_VALUE)
100     {
101         fprintf(stderr, "Failed to create file2\n");
102         return GetLastError();
103     }
104     CloseHandle(hFile);
105 
106     /* Rename file1 to file */
107     TempPath[FilePos] = 0;
108     wcscat(TempPath, File1);
109     wcscpy(CopyPath, TempPath);
110     /* Remove number for dest */
111     CopyPath[wcslen(TempPath) - 1] = 0;
112     if (MoveFileW(TempPath, CopyPath) == 0)
113     {
114         fprintf(stderr, "Failed to rename file1\n");
115         return GetLastError();
116     }
117 
118     /* Rename file2 to file1 */
119     wcscpy(CopyPath, TempPath);
120     /* Change 1 to 2 */
121     CopyPath[wcslen(TempPath) - 1] = L'2';
122     if (MoveFileW(CopyPath, TempPath) == 0)
123     {
124         fprintf(stderr, "Failed to rename file2\n");
125         return GetLastError();
126     }
127 
128     /* Open file1 and get its creation time */
129     hFile = CreateFileW(TempPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
130     if (hFile == INVALID_HANDLE_VALUE)
131     {
132         fprintf(stderr, "Failed to open file1\n");
133         return GetLastError();
134     }
135     if (GetFileTime(hFile, &File1Time, NULL, NULL) == FALSE)
136     {
137         fprintf(stderr, "Failed to read creation time\n");
138         CloseHandle(hFile);
139         return GetLastError();
140     }
141     CloseHandle(hFile);
142 
143     /* Delete files */
144     CopyPath[wcslen(TempPath) - 1] = 0;
145     DeleteFileW(TempPath);
146     DeleteFileW(CopyPath);
147 
148     /* Compare both, they have to be strictly identical */
149     if (RtlCompareMemory(&FileTime, &File1Time, sizeof(FILETIME)) == sizeof(FILETIME))
150     {
151         fprintf(stdout, "Tunnel cache in action\n");
152         return 0;
153     }
154 
155     fprintf(stdout, "Tunnel cache NOT in action\n");
156     return 0;
157 }
158