Windows: AFSParseMountPointTarget buffer overrun
[openafs.git] / src / WINNT / afsrdr / tools / objstatus / ObjectStatus.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
16  *   and/or other materials provided with the distribution.
17  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18  *   nor the names of their contributors may be used to endorse or promote
19  *   products derived from this software without specific prior written
20  *   permission from Kernel Drivers, LLC and Your File System, Inc.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 #include <windows.h>
36 #include <winioctl.h>
37 #include <stdio.h>
38 #include <shlwapi.h>
39
40 #include "AFSUserDefines.h"
41 #include "AFSUserIoctl.h"
42 #include "AFSUserStructs.h"
43
44 bool
45 ParseFID( char *FidName,
46           AFSFileID *FID);
47
48 char *
49 GetAFSFileType( IN DWORD FileType);
50
51 void
52 Usage()
53 {
54
55     printf("Usage: AFSObjectStatus </f FID (Cell.Volume.VNode.Unique)> | </n Full file name> /i <Invalidate entry by FID>\n");
56
57     return;
58 }
59
60 int
61 main(int argc, char* argv[])
62 {
63
64     ULONG rc = 0;
65     DWORD bytesReturned = 0;
66     HANDLE hControlDevice = NULL;
67     char *pBuffer = NULL;
68     DWORD dwError = 0, dwIndex = 0, dwBufferSize = 0;
69     AFSGetStatusInfoCB *pGetStatusInfo = NULL;
70     AFSStatusInfoCB *pStatusInfo = NULL;
71     AFSFileID stFID;
72     BOOLEAN bUseFID = false;
73     WCHAR wchFileName[ 256];
74     AFSInvalidateCacheCB *pInvalidate = NULL;
75     bool bInvalidate = false;
76     DWORD dwIOControl = 0;
77
78     if( argc < 2)
79     {
80
81         Usage();
82
83         return 0;
84     }
85
86     dwIndex = 1;
87
88     dwError = 1;
89
90     while( dwIndex < (DWORD)argc)
91     {
92
93         if( _stricmp(argv[ dwIndex], "/f") == 0)
94         {
95
96             if( !ParseFID( argv[ ++dwIndex],
97                            &stFID))
98             {
99
100                 printf("AFSObjectStatus Failed to parse fid %s\n", argv[ dwIndex]);
101
102                 dwError = -1;
103
104                 break;
105             }
106
107             bUseFID = true;
108         }
109         else if( _stricmp(argv[ dwIndex], "/n") == 0)
110         {
111
112             dwIndex++;
113
114             if( MultiByteToWideChar( CP_ACP,
115                                     MB_PRECOMPOSED,
116                                     argv[ dwIndex],
117                                     -1,
118                                     wchFileName,
119                                     (int)strlen( argv[ dwIndex]) + 1) == 0)
120             {
121
122                 printf("AFSObjectStatus Failed to map string %d\n", GetLastError());
123
124                 dwError = -1;
125
126                 break;
127             }
128         }
129         else if( _stricmp(argv[ dwIndex], "/i") == 0)
130         {
131
132             bInvalidate = true;
133         }
134         else
135         {
136
137             Usage();
138
139             dwError = -1;
140
141             break;
142         }
143
144         dwIndex++;
145     }
146
147     if( dwError == -1)
148     {
149
150         return 0;
151     }
152
153     if( bInvalidate &&
154         !bUseFID)
155     {
156
157         printf("AFSObjectStatus Must specify FID when performing invalidation\n");
158
159         return 0;
160     }
161
162     hControlDevice = CreateFile( AFS_SYMLINK,
163                                  GENERIC_READ | GENERIC_WRITE,
164                                  FILE_SHARE_READ | FILE_SHARE_WRITE,
165                                  NULL,
166                                  OPEN_EXISTING,
167                                  0,
168                                  NULL );
169
170     if( hControlDevice == INVALID_HANDLE_VALUE)
171     {
172
173         printf( "AFSObjectStatus: Failed to open control device error: %d\n", GetLastError());
174
175         return 0;
176     }
177
178     dwBufferSize = 1024;
179
180     pBuffer = (char *)malloc( dwBufferSize);
181
182     if( pBuffer != NULL)
183     {
184
185         if( bInvalidate)
186         {
187
188             pInvalidate = (AFSInvalidateCacheCB *)pBuffer;
189
190             pInvalidate->FileID = stFID;
191
192             pInvalidate->FileType = 0;
193
194             pInvalidate->Reason = AFS_INVALIDATE_FLUSHED;
195
196             pInvalidate->WholeVolume = false;
197
198             dwError = DeviceIoControl( hControlDevice,
199                                        IOCTL_AFS_INVALIDATE_CACHE,
200                                        pBuffer,
201                                        sizeof( AFSInvalidateCacheCB),
202                                        NULL,
203                                        0,
204                                        &bytesReturned,
205                                        NULL);
206
207             if( !dwError)
208             {
209                 printf( "AFSObjectStatus Failed to invalidate object error %d\n", GetLastError());
210             }
211             else
212             {
213                 printf("AFSObjectStatus Successfully invalidated object\n");
214             }
215         }
216         else
217         {
218
219             pGetStatusInfo = (AFSGetStatusInfoCB *)pBuffer;
220
221             memset( pGetStatusInfo, '\0', sizeof( AFSGetStatusInfoCB));
222
223             if( bUseFID)
224             {
225                 pGetStatusInfo->FileID = stFID;
226             }
227             else
228             {
229                 pGetStatusInfo->FileNameLength = (USHORT)(wcslen( wchFileName) * sizeof( WCHAR));
230
231                 dwIndex = 0;
232
233                 if( wchFileName[ 0] == L'\\' &&
234                     wchFileName[ 1] == L'\\')
235                 {
236                     dwIndex = 1;
237
238                     pGetStatusInfo->FileNameLength -= sizeof( WCHAR);
239                 }
240
241                 memcpy( pGetStatusInfo->FileName,
242                         &wchFileName[ dwIndex],
243                         pGetStatusInfo->FileNameLength);
244             }
245
246             dwError = DeviceIoControl( hControlDevice,
247                                        IOCTL_AFS_GET_OBJECT_INFORMATION,
248                                        pBuffer,
249                                        sizeof( AFSGetStatusInfoCB) + pGetStatusInfo->FileNameLength,
250                                        pBuffer,
251                                        dwBufferSize,
252                                        &bytesReturned,
253                                        NULL);
254
255             if( !dwError)
256             {
257                 printf( "AFSObjectStatus Failed to retrieve buffer %d\n", GetLastError());
258             }
259             else
260             {
261
262                 pStatusInfo = (AFSStatusInfoCB *)pBuffer;
263
264                 if( bUseFID)
265                 {
266                     printf("AFS ObjectStatus Results: FID (%08lX.%08lX.%08lX.%08lX)\n", stFID.Cell, stFID.Volume, stFID.Vnode, stFID.Unique);
267                 }
268                 else
269                 {
270                     printf("AFS ObjectStatus Results: Name (%S)\n", wchFileName);
271                 }
272
273                 printf("\n");
274                 printf("\t\t FID: %08lX.%08lX.%08lX.%08lX\n",
275                                         pStatusInfo->FileId.Cell,
276                                         pStatusInfo->FileId.Volume,
277                                         pStatusInfo->FileId.Vnode,
278                                         pStatusInfo->FileId.Unique);
279
280                 printf("\t\t TargetFID: %08lX.%08lX.%08lX.%08lX\n",
281                                         pStatusInfo->TargetFileId.Cell,
282                                         pStatusInfo->TargetFileId.Volume,
283                                         pStatusInfo->TargetFileId.Vnode,
284                                         pStatusInfo->TargetFileId.Unique);
285
286                 printf("\t\t Expiration: %08lX-%08lX\n", pStatusInfo->Expiration.HighPart, pStatusInfo->Expiration.LowPart);
287
288                 printf("\t\t Data Version: %08lX-%08lX\n", pStatusInfo->DataVersion.HighPart, pStatusInfo->DataVersion.LowPart);
289
290                 printf("\t\t FileType: %s - %08lX\n", GetAFSFileType( pStatusInfo->FileType), pStatusInfo->FileType);
291
292                 printf("\t\t Object Flags: %08lX\n", pStatusInfo->ObjectFlags);
293
294                 printf("\t\t Create Time: %08lX-%08lX\n", pStatusInfo->CreationTime.HighPart, pStatusInfo->CreationTime.LowPart);
295
296                 printf("\t\t Last Access Time: %08lX-%08lX\n", pStatusInfo->LastAccessTime.HighPart, pStatusInfo->LastAccessTime.LowPart);
297
298                 printf("\t\t Last Write Time: %08lX-%08lX\n", pStatusInfo->LastWriteTime.HighPart, pStatusInfo->LastWriteTime.LowPart);
299
300                 printf("\t\t Change Time: %08lX-%08lX\n", pStatusInfo->ChangeTime.HighPart, pStatusInfo->ChangeTime.LowPart);
301
302                 printf("\t\t File Attributes: %08lX\n", pStatusInfo->FileAttributes);
303
304                 printf("\t\t EOF: %08lX-%08lX\n", pStatusInfo->EndOfFile.HighPart, pStatusInfo->EndOfFile.LowPart);
305
306                 printf("\t\t Alloc Size: %08lX-%08lX\n", pStatusInfo->AllocationSize.HighPart, pStatusInfo->AllocationSize.LowPart);
307
308                 printf("\t\t EA Size: %08lX\n", pStatusInfo->EaSize);
309
310                 printf("\t\t Links: %08lX\n", pStatusInfo->Links);
311             }
312         }
313
314         free( pBuffer);
315     }
316
317     CloseHandle( hControlDevice);
318
319         return 0;
320 }
321
322 bool
323 ParseFID( char *FidName,
324           AFSFileID *FID)
325 {
326
327     char *pchCell = NULL, *pchVolume = NULL, *pchVnode = NULL, *pchUnique = NULL;
328     char *pchCurrentPos = FidName;
329     char *pLocation = NULL;
330     char chBuffer[ 50];
331
332     pchCell = pchCurrentPos;
333
334     pLocation = strchr( pchCell, '.');
335
336     if( pLocation == NULL)
337     {
338         return false;
339     }
340
341     pLocation++;
342
343     if( *pLocation == NULL)
344     {
345         return false;
346     }
347
348     pLocation--;
349
350     *pLocation = NULL;
351
352     pLocation++;
353
354     pchVolume = pLocation;
355
356     pLocation = strchr( pchVolume, '.');
357
358     if( pLocation == NULL)
359     {
360         return false;
361     }
362
363     pLocation++;
364
365     if( *pLocation == NULL)
366     {
367         return false;
368     }
369
370     pLocation--;
371
372     *pLocation = NULL;
373
374     pLocation++;
375
376     pchVnode = pLocation;
377
378     pLocation = strchr( pchVnode, '.');
379
380     if( pLocation == NULL)
381     {
382         return false;
383     }
384
385     pLocation++;
386
387     if( *pLocation == NULL)
388     {
389         return false;
390     }
391
392     pLocation--;
393
394     *pLocation = NULL;
395
396     pLocation++;
397
398     pchUnique = pLocation;
399
400     strcpy_s( chBuffer,
401               50,
402               "0x");
403
404     strcat_s( &chBuffer[ 2],
405               48,
406               pchCell);
407
408     if( !StrToIntEx( chBuffer,
409                      STIF_SUPPORT_HEX,
410                      (int *)&FID->Cell))
411     {
412
413         printf("AFSObjectStatus Failed to parse cell %s\n", chBuffer);
414
415         return false;
416     }
417
418     strcpy_s( chBuffer,
419               50,
420               "0x");
421
422     strcat_s( &chBuffer[ 2],
423               48,
424               pchVolume);
425
426     if( !StrToIntEx( chBuffer,
427                      STIF_SUPPORT_HEX,
428                      (int *)&FID->Volume))
429     {
430
431         printf("AFSObjectStatus Failed to parse volume %s\n", chBuffer);
432
433         return false;
434     }
435
436     strcpy_s( chBuffer,
437               50,
438               "0x");
439
440     strcat_s( &chBuffer[ 2],
441               48,
442               pchVnode);
443
444     if( !StrToIntEx( chBuffer,
445                      STIF_SUPPORT_HEX,
446                      (int *)&FID->Vnode))
447     {
448
449         printf("AFSObjectStatus Failed to parse vnode %s\n", chBuffer);
450
451         return false;
452     }
453
454     strcpy_s( chBuffer,
455               50,
456               "0x");
457
458     strcat_s( &chBuffer[ 2],
459               48,
460               pchUnique);
461
462     if( !StrToIntEx( chBuffer,
463                      STIF_SUPPORT_HEX,
464                      (int *)&FID->Unique))
465     {
466
467         printf("AFSObjectStatus Failed to parse Unique %s\n", chBuffer);
468
469         return false;
470     }
471
472     return true;
473 }
474
475 char *
476 GetAFSFileType( IN DWORD FileType)
477 {
478
479     char *pchType = NULL;
480
481     switch( FileType)
482     {
483
484         case AFS_FILE_TYPE_FILE:
485         {
486             pchType = "File";
487             break;
488         }
489
490         case AFS_FILE_TYPE_DIRECTORY:
491         {
492             pchType = "Directory";
493             break;
494         }
495
496         case AFS_FILE_TYPE_SYMLINK:
497         {
498             pchType = "Symbolic link";
499             break;
500         }
501
502         case AFS_FILE_TYPE_MOUNTPOINT:
503         {
504             pchType = "Mount point";
505             break;
506         }
507
508         case AFS_FILE_TYPE_DFSLINK:
509         {
510             pchType = "DFS link";
511             break;
512         }
513
514         default:
515         {
516             pchType = "Unknown";
517
518             break;
519         }
520     }
521
522     return pchType;
523 }